Generierung einer Matrix anhand einer Ebene

Design Patterns, Erklärungen zu Algorithmen, Optimierung, Softwarearchitektur
Forumsregeln
Wenn das Problem mit einer Programmiersprache direkt zusammenhängt, bitte HIER posten.
Antworten
joggel

Generierung einer Matrix anhand einer Ebene

Beitrag von joggel »

Guten Morgen,

ich stehe vor einem kleinen Problem. Ich habe das schon mal im IRC angesprochen, aber die Lösung hat da nicht funktioniert, oder ich habe sie nicht verstanden.

Es geht um einen "Tunnelflug". Ich nmöchte durch einen Tunnel fliegen, der seine Richtung (samt Biegungen und so) entlang einer Spline ständig ändert.
Einen Tunnel generiere ich ja aus zB 2 Kreisen deren Vertices ich dann verbinde.

Wie ich vorgehen möchte:
Ich berechne die KreisVertices auf einer Ebene (zB eine Ebene die zwischen der Y- und X-Achse aufgespannt wird) und jage dann diese Vertices durch eine Matrix, die eine Translation und Rotation im 3D-Raum beschreibt

Es geht mir also vlt eher darum, wie ich eine Matrix generiere, die ich durch eine Fläche im Raum beschreibe.

Wie gesagt, ich möchte Punkte entlang einer Spline (3D) berechnen (wie das geht weiß ich).
Und an jedem dieser Punkte wird eine Fläche aufgespannt. Anhand dieser Fläche generiere ich eine Matrix (transformation + rotation).
Dann berechne ich Kreisvertices, die ich eben mit dieser Matrix multipliziere, damit die neuen Kreisvertices auf der Ebene landen.

Ich hoffe ich konnte mein Problem verständlich darlegen.
Wie würdet ihr dabei vorgehen?


Achso... ich benutze ja OpenSceneGraph. Dort kann ich Matrizen sehr leicht durch Rotation bzw Translation bzw Scalierung generieren.
bspw:

Code: Alles auswählen

osg::Matrix matrix = osg::Matrix::identity();
matrix = matrix *  osg::Matrix::rotate(osg::Quat(osg::DegreesToRadians(90.0), osg::Vec3(0, 0, 1))) * osg::Matrix::translate(x,y,z);
Also, es würde mir helfen wenn ich solche Parameter bekommen würde.
Also den Rotationswinkel, die Achse um die rotiert werden soll, und den translationsVektor (wobei der ja eher einfach zu ermitteln ist).


Gruß
smurfer
Establishment
Beiträge: 195
Registriert: 25.02.2002, 14:55

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von smurfer »

Hi,

ich bin tatsächlich nicht sicher, ob ich dein Problem verstanden habe. Falls ja: kannst Du aus Deiner Splinerepräsentation nicht an den Stellen, an denen Du Kreis-Vertices erzeugen möchtest, die tangentialen Vektoren nehmen und zwischen je zwei aufeinander folgenden Vektoren die Rotationsmatrix berechnen?

Grüße, smurfer

p.s.: Mal auf die Schnelle als Ansatz gesucht, ohne zu wissen, ob es genau für dich zutrifft:
Rotationsmatrix, Vektoren: https://stackoverflow.com/questions/231 ... ined-by-tw
Tangentialvektor, Splines https://math.stackexchange.com/question ... ne#1272117
joggel

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joggel »

Danke smurfer. Ich werd mir die Links mal anschauen.

Ich werde auch mal eine Skizze zu hause machen, um mein Vorhaben zu verdeutlichen
joggel

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joggel »

Also mal so zwischendurch:

Ich möchte mir Flächen definieren entlang einer spline.
Diese Flächen haben einen Normalvektor und einen Stützvekor.
Dann möchte ich auf diesen Flächen Kreise zeichnen....

@smurfer
Was ist ein Tangent in diesem zusammengang?
joeydee
Establishment
Beiträge: 1039
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joeydee »

Dein Hauptproblem ist vermutlich, eine Ebene hat eine Definition zu wenig für eine eindeutige Matrix. Du hast Position und Normale, aber es fehlt eine definierte Richtung auf der Ebene selbst. Es gibt beliebig viele Matrizen, bei denen z.B. "z" mit der Normalen übereinstimmt, und x/y irgendwo auf der Ebene liegen (rotationssymmetrisch um z).
Du musst also beim Startpunkt des Splines auch einen lokalen "right"- und "up"-Vektor festlegen, welche zu der Startrichtung (die Normale zum nächsten Punkt) senkrecht stehen. Zumindest eine Richtung definieren, die andere ergibt sich dann aus dem Kreuzprodukt.
Oder ist das schon dein "Stützvektor"?

Dann:
- Berechne von einem Punkt zum nächsten die neue Ebenennormale ("front"-Vektor, so weit warst du sicher schon),
- Kreuzprodukt der Normalen mit dem alten right-Vektor ergibt den neuen up-Vektor,
- Kreuzprodukt der Normalen mit dem neuen up-Vektor ergibt den neuen right-Vektor.
(Das funktioniert nur, wenn du sicherstellen kannst, dass von Punkt zu Punkt keine 90-Grad-Wendungen auftreten und so der alte up- oder right-Vektor mit der neuen Richtung exakt zusammenfallen könnte - das wäre ein Gimbal Lock und das Kreuzprodukt würde keine brauchbaren Vektoren ausspucken).

Deine 4x4-Matrix für deine x/y-Ebene ergibt sich dann aus den berechneten Vektoren und der Punktposition:
right.x | up.x | front.x | pos.x
right.y | up.y | front.y | pos.y
right.z | up.z | front.z | pos.z
0 | 0 | 0 | 1

Irgendwelche Rotationswinkel rausrechnen um damit eine neue Matrix zu generieren würde sich intern in den Berechnungen übrigens aufheben (cos(acos(x)), das sollte man also lassen.
joggel

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joggel »

Danke joey.

Soweit wurde mir das im IRC auch schon vermittelt, glaube ich.
Na ich werds mal versuchen umzusetzen.
Falls es klappt, oder auch nicht, melde ich mich hier noch mal...

Noch eine Frage:
"Upvector" == Normalvector der Ebene?
Ach nein. Du schriebst ja: Normalvektor, up- und right-Vektor...
smurfer
Establishment
Beiträge: 195
Registriert: 25.02.2002, 14:55

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von smurfer »

joggel hat geschrieben:@smurfer
Was ist ein Tangent in diesem zusammengang?
Die Tangente, bzw. der repräsentierende Vektor. Die Tangente ist die Gerade, die an einem Punkt die gleiche Steigung wie in Deinem Fall dein Spline hat und somit 90° zur Normalen steht. Der Vektor ist gewissermaßen in Tunnelflugrichtung orientiert und entspricht der Ebenennormale. Aus zwei solcher Vektoren ließe sich die entsprechende Rotation berechnen.

Alternativ oder wenn Du explizit über Ebenen gehen möchtest, siehe Antwort von joeydee. Sein erster Schritt entspricht im weitesten Sinne der Tangente (bzw. einer Tangente zwischen den Punkten).

Grüße, smurfer
joeydee
Establishment
Beiträge: 1039
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joeydee »

joggel hat geschrieben:Danke joey.
Noch eine Frage:
"Upvector" == Normalvector der Ebene?
Ach nein. Du schriebst ja: Normalvektor, up- und right-Vektor...
Ja, nach der Beschreibung die du gegeben hast (Kreis in x/y-Ebene soll zu einem Tunnelsegment werden): Kreisebene-z == front == Ebenennormale; Kreisebene-x zeigt zur rechten Wand im Tunnel (right), Kreisebene-y zur Decke (up).
smurfer
Establishment
Beiträge: 195
Registriert: 25.02.2002, 14:55

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von smurfer »

joeydee hat geschrieben:Irgendwelche Rotationswinkel rausrechnen um damit eine neue Matrix zu generieren würde sich intern in den Berechnungen übrigens aufheben (cos(acos(x)), das sollte man also lassen.
War das auf meinen Beitrag bezogen? Falls ja, kann gut sein (in dem Fall ignorier, was ich geschrieben habe, Joggel), war nur eine spontane Idee ohne groß drüber nachzudenken. Würde mich dennoch interessieren, was Du meinst, konnte ich nicht ganz zuordnen.
joeydee
Establishment
Beiträge: 1039
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joeydee »

Neinnein :) das war joggel's ursprüngliche Anfrage, da er Funktionen für Matritzen aus Rotationswinkeln in seiner Lib vorliegen hat (erster Post, letzter Absatz). Aber die braucht man ja gar nicht.
joggel

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joggel »

Ja, ich hatte das ja vor mit Rotationswinkel zu berechnen.

Aber nochmal zur Vollständigkeit und zu meinem Verständniss (@smurfer):
Wie würde denn die Herleitung einer solchen Matrix aussehen, wenn ich 2 dieser Tangentialvektoren hätte?
Und was wären die beiden Vektoren. Einer wäre ja der Normalvektor der Fläche, oder?
joggel

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joggel »

Ich stehe wieder vor einem Problem!

Das generieren der Röhre funktioniert schon sehr gut.
Nun möchte ich die Camera durch diese Röhre bewegen. Also auf genau der selben Spline.
Um die Camera auszurichten brauche ich ja eine Position (Eye-Vector), einen Referenzpunkt auf den ich schaue (Center-Vector) und einen Vektor der angibt wo Oben ist (up-Vektor).

Ich habe absolut keine Idee wie ich das umsetzen kann.

Im Prinzip müßte es ja genauso wie mein vorheriges Problem, mit den Flächen, zu behandeln sein, oder?
joeydee
Establishment
Beiträge: 1039
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joeydee »

Ja. Position und 3 Richtungsvektoren (oder 2, der dritte ergibt sich immer aus dem Kreuzprodukt) ergeben direkt deine Kamera-Matrix (View-Matrix). Ist dasselbe wie deine Transformationsmatrix oben, nur an getweenten Spline-Punkten.
Im Prinzip kannst du einfach mit der ersten Ebene (t=0 auf dem Spline) als View-Matrix starten, die Kamera auf dem Spline entlangbewegen und immer einen LookAt auf den Splinepunkt bei t+1 durchführen. Die Kamera wird sich nicht unbedingt "upright" verhalten, aber falls das egal ist, würde ich diesen Weg ausprobieren.
Hast du eine LookAt-Funktion in der Lib?
joggel

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joggel »

Ja, eine LookAt-Funktion bietet mir osg.

Bisher habe ich das ja auch gemacht.
Also den Eye-Vector = SplineFunc(t).
Den Center-Vector = SplineFunc(t+0.1) zB.
Mir fehlt halt lediglich der Up-Vector.
Wobei ich aber sagen muss, das die Kamerafahrt dadurch sehr "unruhig" wird.
Aber okay, es kann auch sein, weil ich die Spline-Kontrollpunkte sehr sehr ungünstig errechnet habe.
Ich habe eine Gerade definiert, und entlang dieser geraden habe ich dann immer per rand() eine Abweichung von der Geraden berechnet, wo dann der Splinekontrollpunkt liegt. Ist vlt nicht ganz soooo günstig.
Mal sehen ob mir da etwas "harmonischeres" einfällt...

Aber zurück:
Mir fehlt da eigentlich nur der Up-Vector...
joeydee
Establishment
Beiträge: 1039
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joeydee »

Probier mal den Up-Vektor der alten View-Matrix. Normalerweise wird im LookAt die Matrix wieder orthogonalisiert.
Wenn du nicht beliebig rollen willst: wie hattest du den Stützvektor für deine Ebenen berechnet? Kannst du das für die Kamera ebenso machen?
joggel

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joggel »

Ich habe bis jetzt noch nicht weiter programmiert.
Was ich mir aber überlegt habe: soll sich denn der Up-Vector bei einer Bewegung durch die Röhre ändern?
Es soll doch Oben stets Oben sein; also kann doch der Up-Vector die ganze Zeit konstant bleiben. Oder liege ich da falsch? Was sich die ganze zeit über ändert ist doch der eye- und der center-vector...

Zu der frage nach dem stützvektor:
Ich habe leider eher geringe kentnisse im bereich linearer Algebra;
Ich dachte, das der Stützvektor lediglich die Position der Fläche im Raum definiert. Also in meinem Fall: Splinefunc(t).
joeydee
Establishment
Beiträge: 1039
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joeydee »

Ok, das mit dem Stützvektor war dann ein Missverständnis. Das ist also die Position.
Nochmal die genauere Nachfrage: Wenn das mit den Kreisen nun geht, wie ermittelst du dort den fehlenden Vektor um die Matrix zu konstruieren?

Wenn der Up-Vektor global konstant bleibt (z.B. +y), kann es theoretisch den Fall geben, dass er irgendwann mit dem Eye-Vektor zusammenfällt (z.B. wenn der Spline senkrecht nach oben geht). Dann hast du einen Gimbal-Lock, ist nicht lösbar, die Ansicht kollabiert. Dasselbe wie bei den Kreisen.
joggel

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joggel »

joeydee hat geschrieben:Ok, das mit dem Stützvektor war dann ein Missverständnis. Das ist also die Position.
Nochmal die genauere Nachfrage: Wenn das mit den Kreisen nun geht, wie ermittelst du dort den fehlenden Vektor um die Matrix zu konstruieren?
Ich habe von anfang an folgende Vektoren definiert:
- Front-Vector (=Normale der Ebene)
- Right-Vector (zeigt zur rechten Seite des Kreises)
- Up-Vector (zeigt nach Oben des Kreises)
- Position

Und diese berechne ich mir für jeden Kreis, nach deinem Vorschlag, neu und konstruiere daraus die Matrix.

Mein spontaner Gedanke ist, dass ich sowas dann auch bei der berechnung des Up-Vektors für die LookAt-Funktion machen kann.
Front-Vektor == Center-Vektor
Position == Eye-Vektor
Up-Vektor == Up-Vektor

Nur fehlt mir da der Right-Vektor, oder?
Ich könnte von Anfang an einen definieren, und daraus ständig die Parameter neu berechnen, so wie bei den Kreisen.
Diese Parameter müßte ich mir dann immer merken, und für jede neue Position neu berechnen.
Nur frage ich mich: gibt es denn da keinen einfacheren Weg?
joeydee
Establishment
Beiträge: 1039
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joeydee »

Das geht in die richtige Richtung. Ich versuche nochmal die wesentlichen Punkte allgemein zusammenzufassen, das wirst du immr wieder brauchen, bei mir hat es irgendwann "Klick" gemacht.
- Eine Matrix für einen deiner Kreise zu berechnen und eine View-Matrix für die Kamera zu berechnen ist exakt dasselbe Problem.
- Um eine Matrix eindeutig definieren zu können, brauchst du eine Position und mindestens zwei Richtungen (als normalisierte Vektoren, möglichst schon senkrecht zueinander). Nur Position und eine Richtung (z.B. look-at == front) reicht nicht, es gibt unendlich viele Möglichkeiten daraus eine Matrix zu machen (rollend um den front-Vektor).
- Aus diesem Grund darf die zweite Richtung nie mit der ersten zusammenfallen, sonst gibt es einen Gimbal-Lock, es lässt sich keine Transformationsmatrix aufspannen.
- Die dritte notwendige Richtung ergibt sich aus dem Kreuzprodukt (X) der ersten beiden (z.B. right = front X up oder up = front X right)
- Waren die ersten beiden Richtungen nicht senkrecht zueinander, kann man sie mit dem Kreuzprodukt abschließend orthogonalisieren.
- Eine Matrix setzt sich aus den Spaltenvektoren right,up,front und position zusammen. Der jeweils 4. Eintrag in den Spalten ist 0,0,0,1 (letzte Zeile aus der 4x4 Einheitsmatrix) - s. vorherige Seite

Konkret auf deine Anwendung bezogen:
Kreisebene-Position = Splinepos = Ebenenpunkt = Eyepos
Kreisebene-Normale = (normalize(next Splinepos - akt. Splinepos)) = front = view = lokale Z-Richtung
Kreisebene-Y = up = lokale Y-Richtung
Kreisebene-X = right = lokale X-Richtung
(Alle Angaben in Weltkoordinaten, also untransformiert)

Die ersten beiden sind klar.
up und right sind von den gegebenen Bedingungen (Spline) grundsätzlich undefiniert.
Hat man einen, kann man den anderen per Kreuzprodukt definieren.

Du musst mindestens einen der fehlenden Vektoren beim Start definieren.

Eine Möglichkeit wäre also, den ersten up-Vektor zu definieren (z.B. Welt-Y 0,1,0) wenn man weiß dass der Spline immer in Welt-Z-Richtung startet. Knn er auch zufällig direkt in Y-Richtung starten, geht das nicht.
Für die nächste Position dann zuerst den up-Vektor der letzten Kamera nehmen, daraus den neuen right-Vektor bestimmen (newRight = oldUp X newFront), dann den up-Vektor korrigieren (newUp = newFront X newRight), dann hast du die neue Matrix beisammen.
Wenn du eine Look-At-Funktion aus einer Lib aufrufst mit jeweils dem alten Up-Vektor, wird diese sehr wahrscheinlich genau das machen.

Für mehr Kontrolle müsstest du einen zweiten Spline parallel zum ersten definieren, der jeweils die up-Richtung für eine bestimmte Position angibt. Und sicherstellen dass sich beide Splines nie schneiden (up wäre dann nämlich 0,0,0, und das ist gleichbedeutend mit einem Gimbal Lock)

Einen "einfachen" Weg, aus einem Spline eine immer eindeutige Up-Richtung zu bekommen, gibt es nicht.
joggel

Re: Generierung einer Matrix anhand einer Ebene

Beitrag von joggel »

Danke!!!
Ja, brauch da evtl etwas übung, aber im allgemeinen bekomme ich schon ein besseres Verständniss für das thema, auch dank deiner ausführlichen erklärung. Danke :)

Ich habe mir überlegt, ich werde das mit der zweiten Spline umsetzen. Das erscheint mir eine elegante Lösung, und bietet zusätzlich noch Möglichkeiten den up-vector variabel zu halten. Also das die Spline, die den up-vector definiert, auch etwas um die andere Spline rollt... gefällt mir!!
THX!!
Antworten