Raycasting Tutorial / Vektor Mathe Frage

8

Ich schaue mir dieses nette Raycasting-Tutorial unter http://lodev.org/cgtutor/raycasting.html an und habe eine wahrscheinlich sehr einfache mathematische Frage.

Im DDA-Algorithmus habe ich Probleme, die Berechnung der Variablen deltaDistX und deltaDistY zu verstehen. Dies sind die Entfernungen, die der Strahl von 1 x-Seite zur nächsten x-Seite oder von 1 y-Seite zur nächsten zurücklegen muss y-Seite, im quadratischen Raster, aus dem die Weltkarte besteht (siehe Abbildung unten).

Geben Sie hier die Bildbeschreibung ein

Im Tutorial werden sie wie folgt berechnet, jedoch ohne viel Erklärung:

//length of ray from one x or y-side to next x or y-side
double deltaDistX = sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));
double deltaDistY = sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));

rayDirY und rayDirX sind die Richtung eines gestrahlten Strahls.

Wie bekommt man diese Formeln? Es sieht so aus, als ob der Satz von Pythagoras Teil davon ist, aber irgendwie geht es hier um Spaltung. Kann mich jemand darauf hinweisen, welches mathematische Wissen mir hier fehlt, oder die Formel "beweisen", indem er zeigt, wie sie abgeleitet ist?

Mattboy
quelle
Sie möchten wahrscheinlich auch Rubbelapixel.com/lessons/3d-basic-lessons/… überprüfen, das eine sehr schöne und detaillierte Erklärung von DDA enthält.
Grieverheart

Antworten:

8

Ahh ja. Ich warf meine Mathematik darauf und ich denke, ich habe es geschlagen. Sie haben Recht, es beinhaltet den Satz von Pythagoras und einige Skalierungen.

Sie beginnen mit Ihrem normalisierten Vektor, der Ihren Strahl darstellt.

Geben Sie hier die Bildbeschreibung ein

Es hat eine xKomponente und eine yKomponente. Zuerst wollen wir sehen, wie lange es dauert, wenn eine Einheit in die xRichtung fährt . Also, was machen wir? Wir wollen den gesamten Vektor so skalieren, dass die xKomponente gleich ist 1. Um herauszufinden, nach was skaliert werden soll, gehen wir wie folgt vor:

scaleFactor = 1/rayDirX;

Das in Mathe zu schreiben ist wirklich gerecht

scaledX = rayDirX * (1/rayDirX) = 1

Also können wir das einfach so nennen 1.

Dann für die yKomponente:

scaledY = rayDirY * (1/rayDirX) = rayDirY/rayDirX

Jetzt haben wir unsere skalierten Komponenten als (1, rayDirY/rayDirX)

Jetzt wollen wir die Länge wissen. Jetzt kommt Pythagorean ins Spiel. Welches ist

length = sqrt((x * x) + (y * y))

Wenn wir also unsere skalierten Komponenten anschließen, erhalten wir:

length = sqrt((1 * 1 ) + (rayDirY / rayDirX) * (rayDirY / rayDirX))

Wenden Sie etwas Algebra an und vereinfachen Sie und wir erhalten:

length = sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))

Gleiches gilt für die Länge, wenn die yKomponente eine Einheit zurücklegt, außer wir haben (rayDirX/rayDirY, 1)die Ergebnisse

length = sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))

Dort haben wir Ihre beiden Gleichungen aus Ihrer Frage. Ziemlich ordentlich. Danke für die Algebraübung.

MichaelHouse
quelle
ahh du hast mich geschlagen! Sehr schön!
Philip
Ha, ich habe immer wieder nach neuen Antworten gesucht! Ich hatte das Gefühl, als würde ich gegen jemanden fahren :)
MichaelHouse
Sehr schön danke! War viel weniger offensichtlich als ich erwartet hatte.
Mattboy
Ich fand die Antwort erst, als ich aufgab, sie rückzuentwickeln, und versuchte herauszufinden, wie ich diesen Wert erhalten würde, wenn ich es tun würde. Ich dachte, vielleicht wäre das Skalieren des Vektors eine Art Abkürzung, aber es stellt sich heraus, dass es genauso ist, wie sie es tun :)
MichaelHouse
1

Angenommen, die Einheitslänge jedes Gitterabstands beträgt 1.

Das Dreieck (Dreieck 1) im veröffentlichten Diagramm (OP-Frage), das aus deltaDistXder Hypotenuse besteht, hat den gleichen Kosinuswert seines Winkels wie der Kosinuswert des Winkels, der in dem Dreieck gebildet wird, das durch die Bestandteile des rayDir# Vector(Dreieck 2) gebildet wird.

Das Folgende kann also gleichgesetzt ( Vektorgrößen unten ) und vereinfacht (1-3) werden.

Denken Sie daran: cos = Base / Hypotenuse

0. cosine_triangle_2                   = cosine_triangle_1
1. rayDirX/sqrt(rayDirX^2 + rayDirY^2) = 1/deltaDistX
2. (rayDirX*deltaDistX)^2              = rayDirX^2 + rayDirY^2
3. deltaDistX                          = sqrt(1+ rayDirY^2/rayDirX^2)

In ähnlicher Weise kann die Gleichung für deltaDistYabgeleitet werden.

metrischer Raum
quelle