Seite 1 von 1

Hilfe bei Matheproblem (fuer Job!) gesucht: Vektorrechnung

Verfasst: Donnerstag 12. März 2009, 11:53
von shakebox
Gleich vorweg: nein, es geht nicht um ne Schulaufgabe oder so. Die Zeiten sind gottseidank schon lange rum. Aber weil es so lang her ist sind meine diesbezueglichen Faehigkeiten halt schon eingerostet. Evtl. sind ja in nem Umfeld wo doch "Denker" und "Algorithmen-Hantierer" am Werk sind Leute dabei die mir auf die Spruenge helfen koennen. Mir faellt grad kein passenderes Forum ein.

Geht um Folgendes bei meinem Job als Compositior fuer Kinofilm-VFX-Shots:
Moechte fuer einen Shot eine Beleuchtung faken von einzelnen Layern. Die eigentliche Funktion der Beleuchtung hab ich schon, nur muss ich jetzt die Richtung aus der die Lichtquelle scheint in Abhaengigkeit von drei Punkten im Raum definieren: das zu beleuchtende Objekt (ist fix), die Lichtquelle (Position ebenfalls fix) und die "Kamera" (die bewegt sich, dadurch veraendert sich eben die Beleuchtungsrichtung der Lichtquelle in Relation zur Kamera).

Soweit zur Erklaerung um was es geht, konkret brauch ich aber folgendes:

Ich hab die XYZ-Positionen der drei Punkte Lichtquelle L, Kamera K und Objekt O in nem festen, orthogonalen (?) 3D-Koordinatensystem. Nun will ich entweder die beiden Vektoren OK und OL oder das Koordinatensystem (kommt ja letztendlich aufs selbe raus) so drehen und verschieben dass erstens der Punkt O auf dem Nullpunkt des Koordinatensystems liegt und zweitens der Vektor OK auf der Z-Achse (also die die in die Tiefe geht) liegt.

Oder anders formuliert: ich will durch die Kamera auf das Objekt O schauen und dann soll mein Koordinatensytem so sein dass die X-Achse eben die horizontale Achse meines Bildes ist, die Y-Achse die vertikale und die Z-Achse eben "ins Bild hinein" geht. Der Ursprung des Koordinatensystems liegt dann also genau in der Mitte meines Bildes das ich mit der Kamera von dem Layer mache.

Wenn das Koordinatensystem so verdreht ist braeuchte ich dann als Ergebnis die neuen Koordinaten der Lichtquelle L, die sich ja aufgrund der ganzen Transformation eben auch "verschoben" hat.

Eigentlich duerfte das nicht sooo schwierig sein und in 2D wuerde ich es vielleicht in vielen Stunden hinbekommen, aber die Translation und vor allem dann ja Drehungen um zwei Achsen bei nem 3D-Raum lassen mich grad irgendwie keinen Ansatzpunkt finden.

Hoffe ich hab das nicht zu verwirrend geschrieben (sonst bitte nachfragen bzw. meckern) und freue mich auf jegliche Komplett- oder Teilloesung oder einfach nur hilfreiche Gedanken, Links, Tipps, usw.

Merci!

Verfasst: Donnerstag 12. März 2009, 12:14
von CM
Hoi,

das ist in der Tat nicht schwierig ;-). Aber doch recht komplex, so daß es einige Zeit erfordert so etwas gut zu implementieren.

Aber Du hast ja nach Gedanken gefragt. Also:
- Warum das Rad neu erfinden? Greife doch auf existierende Software zurück (blender, Max3d, etc. - wobei ich aber nicht weiterhelfen könnte, das können andere besser)
- Du schreibst so, als sei O nur ein Punkt. Das würde ich ggf. vom Konzept her anders sehen.
-
Wenn das Koordinatensystem so verdreht ist braeuchte ich dann als Ergebnis die neuen Koordinaten der Lichtquelle L, die sich ja aufgrund der ganzen Transformation eben auch "verschoben" hat.
Wieso das? Wenn Du diese Operation in einer für absolute Koordinaten ausdrückst, ist das gleichwertig einer Bewebung des Beobachters. Wenn Deine Lichtquelle eine Punktquelle ist, mußt Du sie nicht weiter berücksichtigen.
- Drehung von Vektoren: Stichwort "Rotationsmatrices"
- Ich finde ja die Vektorklasse von biopython einen guten Einstieg fürs Coding. Nicht sehr performant, aber übersichtlich.

HTH
Christian

Verfasst: Donnerstag 12. März 2009, 12:26
von shakebox
ok, dann vielleicht noch zur naeheren Erklaerung:

1. ich brauch das "neu" weil ich es in der Software Shake die ich verwende als Expressions in bestehende Nodes einbauen muss. Und da Shake da keine ganze Scriptsprache wie Python oder sowas drin hat sondern nur ne recht einfache Syntax (letztendlich C-aehnlich) mit einfachen Funktionen wie sin() usw. muss ich das eben neu schreiben. Brauche also letztendlich schon die eigentlichen Formeln.
Ich kann es auch nicht vorher extern machen weil das waehrend der Laufzeit, sprich beim Rendern des Shots, errechnet werden soll und ich dauernd an der Position der Objekte (letztendlich sind es eben mehrere, ich mach aber fuer jedes einzelne ne eigene Rechnung) was aendern will und muss.

2. Dein zweiter Teil ist mir nicht so klar. Was ich habe ist folgendes: ich "filme" das Objekt mit einer bewegten Kamera, wobei sich der Abstand der Kamera vom Objekt nicht aendert, sie rotiert also nur um das Objekt. Das Objekt ist also immer gleich gross im Bild. Nun habe ich schon eine bestehende Node (so nennt man einen Operator-Baustein in Shake), der die Beleuchtung macht (mittels einer Normalmap). Diese Node hat drei Parameter: X, Y und Z-Koordinaten, wobei X eben die horizontale Bildachse ist, Y die vertikale und Z die in die Tiefe und der Nullpunkt liegt genau in Bildmitte.

Wenn sich jetzt die Kamera um das Objekt bewegt bewirkt das im Ergebnisbild eigentlich nix anderes als dass die Lichtquelle vermeintlich dauernd aus ner anderen Richtung kommt. Und genau die muss ich eben errechnen und dann in die Node als XYZ angeben.

Wird es dadurch klarer?

Sonst hier nochmal anders formuliert meine Aufgabenstellung:

gegeben sind drei Punkt O, L und K mit ihren XYZ-Werten. Nun sollen alle Punkte im Koordinatensystem so verschoben werden dass folgendes gilt:

1. O bekommt die neuen Koordinaten 0/0/0
2. K bekommt die neuen Koordinaten 0/0/Z'
3. Der Betrag des Vektors OK bleibt gleich, dadurch ergibt sich ja die Koordinate Z' von K, richtig?
4. die dafuer noetige Transformation soll eben genauso auf L bzw. den Vektor OL angewendet werden, dessen Betrag sich auch nicht aendern soll.
5. wie sind nun die neuen Koordinaten X'/Y'/Z' von der neuen Position L'

Hoffe das ist so richtig formuliert und passt zu dem was oben steht :)

Verfasst: Donnerstag 12. März 2009, 13:38
von CM
Oh, Ok. Was Du brauchst ist also eine Umsetzung in einer anderen Sprache. Sofern diese arrays oder Listen aufweist, letztlich nicht kein absolutes Hindernis.

Gesetzt, Dein Objekt hat die Koordinaten self.coord in Form eines numpy-array (zum Umscheiben in eine andere Sprach siehe unten):

Code: Alles auswählen

def transform(self, rot, tran):
    self.coord=numpy.dot(self.coord, rot) + tran
Hierbei ist rot die Rotationsmatrix und tran ein Translationsvektor. Anzuwenden wie folgt:
shift:

Code: Alles auswählen

shift = numpy.array([dx, dy, dz])
object.transform(rotaxis(0, Vector(0, 1, 0)), shift)
Mit dx, dy, dz Deine Veränderungen in x, y und z. Das mußt Du nur einmal machen, da dann Dein Objekt zentriert ist. Dieselben shift-Werte auch auf die Kamera und die Lichtquelle anwenden.
Rotieren:

Code: Alles auswählen

object.transform(rotaxis(angle, Vector(1, 0, 0)), array((0, 0, 0), 'f'))
für eine Rotation um angle um "x", wenn x die nullte Koordinate sein soll. angle ist hierbei der Winkel in Radian.
So, und wie sieht nun rotaxis aus? Siehe obenstehender Link - unter Verwendung des Bio.PDB.Vector-Moduls. Wie gesagt: Nicht sehr performant, aber für wenige Objekte schnell genug.

Dann würde das Vorgehen so aussehen:
1. Du hast beliebige Koordinaten für O, K und L. Zentriere O (Koordinaten = [0, 0, 0], wende dieselbe Operation auf K und L an.
2. Mache Deinen Snapshot.
3. Rotiere K um O. Wenn die Achse eine andere sein soll als im Beispiel, setze Vector auf Vector(0, 1, 0) oder Vector(0, 0, 1). In meiner Software siehst Du einen Shortcut dafür ab Zeile 418 ff..
4. Wiederhole Schritt 3 bis Du fertig bist in beliebigen Inkrementen.

Wie der Winkel LOK berechnet wird, steht ebenfalls im Vector-Modul von biopython und auf Wikipedie (s.u).

Wie gesagt, ich habe hierzu bei biopython abgekupfert, aber mit dem Vector-Modul bist Du rel. fix fertig mit Coden. Wie das in einer anderen Sprache aussieht weiß ich so auch nicht. Aber alles was Du brauchst ist ein Muster für Vectorprodukte (numpy.dot) siehe Wikipedia (die Englische Version des Artikels ist einfach besser von da kommst Du formelmäßig auch weiter).
Falls Du mit C++-Code als Extension für Deine Software was anfangen kannst, so kann ich Dir das geben (ist allerdings noch frisch und wahrscheinlich buggy - konkret bin ich mir nicht sicher, ob es einen memory leak gibt - ich arbeite dran). Wrappen mußt Du selber.

Alternativ kannst Du Quaternionen anwenden, was ich aber noch nicht gemacht habe - ehrlich gesagt, überfordert mich das auch etwas, aber openbabel hat eine Implementierung dafür.

Kurz: Der Link aus meinem ersten Post hier, ist womöglich das ein Muster für Dich.

Gruß,
Christian

Verfasst: Donnerstag 12. März 2009, 14:03
von shakebox
ui, jetzt erschlaegste mich etwas :) Ich glaube ich merke gerade dass ich mir das ein wenig zu einfach vorstelle und das glaub ne Hausnummer zu hoch fuer mich ist.

Was ich letztendlich halt brauche ist irgendwie was nach dem Motto:
Lxneu = sin(OxKx-OxLx)... usw.

Denn ich kann da nicht wirklich programmieren sondern nur einzeilige Expressions schreiben.

Danke Dir aber sehr fuer Deine Muehe. Muss mal schauen ob es hier im Haus irgendjemanden gibt der mit Deinen tollen Ausfuehrungen mehr anfangen kann als ich und das mit mir in die entsprechenden Formeln ueberfuehren kann. Sonst muss ich mir einfach ne ganz andere Loesung fuer diese Beleuchtung ausdenken und das ganz anders faken. Leider gibt es bei uns halt keine R&D-Abteilung, die sowas sicher schnell koennte.

Verfasst: Donnerstag 12. März 2009, 14:04
von HWK
Das könnte helfen.
MfG
HWK

Verfasst: Donnerstag 12. März 2009, 17:02
von CM
Super Link - Danke! Da sind sogar auf einmal Quaternionen ganz einfach ;-).

Verfasst: Donnerstag 12. März 2009, 17:05
von CM
shakebox hat geschrieben:Denn ich kann da nicht wirklich programmieren sondern nur einzeilige Expressions schreiben.
Autsch. Dann geht es natürlich immer noch, aber Du müßtest viel mehr schreiben, als selbst in C. Kannst Du wenigstens Funktionen definieren? Und irgendwas wie typedef in C? Sonst solltest Du Dich wirklich fragen, ob das die richtige Sprache für das Problem ist.

Gruß,
Christian