Hallo,
ich will mit dem PC dreidimensionale Objekte zeichen, mein Programm will
aber 2D-Koordinaten. Also suche ich eine handliche Library die mir das
umrechnet.
Ich meine das etwa so:
Ich: Punkt (x,y,z)=(3,4,5); Kamera (x,y,z)=(0,0,0) schaut in diese und
diese Richtung
Programm: Punkt an Position (x,y)=(4.7, 2.9) zeichnen.
Eigentlich wollte ich das selber schreiben aber ich steig trotz
Leistungskurs vor zig Jahren nicht durch die Mathematik. :-(
Gefunden habe ich http://www.base32.de/3dengine.html aber da fehlt
irgendwie ein Beispiel wie der ganze Kram zu verwenden ist.
Mathedoofi schrieb:> Gefunden habe ich http://www.base32.de/3dengine.html aber da fehlt> irgendwie ein Beispiel wie der ganze Kram zu verwenden ist.
In der Datei "3d.c" ist doch ein Beispiel drin. Da muss man sich halt
ein bisschen durchhangeln. Aber da die Lib ja für nen mc ist, weiß ich
nicht, ob das das ist, was du suchst.
In welcher Programmiersprache hättest du es denn gerne?
Wie komplex soll es denn werden? Einfache Zentralperspektive is simpel:
X = (a*px)/pz
Y = (a*pz)/pz
"a" ist der Abstand des Betrachters zum (virtuellen) Bildschirm px,py,pz
die 3D Koordinate und X,Y die entsprechende 2D Bildschirm-Koordinate.
Allerdings musst Du Dich selbst um verdeckte Linien/Flächen etc kümmern.
Für eine Bewegung/Kippen der Kamera muss man dabei die Objekte
manipulieren. Aber für einfache Sachen taugt's.
Ansonsten bleibt die Frage, auf welchem System und wass die
Anforderungen sind. Bitmapping gewünscht? I.d.R sollte man OpenGL oder
directX nehmen...
Mathedoofi schrieb:> Achso, parallele Linien sollen parallel bleiben, also nicht auf einen> weit entfernten Punkt zulaufen.
? dann gibt es aber keine Perspektive/Tiefeneffekt. Lass die 3
Koordinate einfach weg...
Das ist lediglich eine Matrixmultiplikation, den Overkill einer
"Bibliothek" braucht's dazu nicht:
Gegeben ist ein Punkt P, der in die Ebene zu projizieren ist, die durch
zwei Vektoren X und Y aufgespannt wird. Zusammen mit einem dritten
Vektor Z, der Blickrichtung, wird der ganze Raum aufgespannt, in dem P
liegt.
Da es sich um eine Parallelprojektion handeln soll, liegt o.E. der
Koordinatenursprung in der Ebene.
Bezeichnet nun k = (x, y, z) den Koordinatenvektor von P bezüglich
dieser Basis B = { X, Y, Z }, dann ist P offenbar:
und der gesuchte Koordinatenvektor k
Die z-Koordinate ist der Abstand (in Einheiten von |Z|) zur Ebene und
interessiert nicht. Die beiden Koordinaten x und y sind die gesuchten
2D-Koordinaten.
Die Matrix B^-1 ist eine 3×3 Matrix; da z nicht benötigt wird, kann man
einfach die dritte Zeile entfernen und erhält damit eine Projektion
R³ -> R²
Das Ergebnis hängt davon ab, wie die Vektoren X und Y in die Ebene
gelegt werden; dies ist nicht eindeutig.
benji schrieb:> In der Datei "3d.c" ist doch ein Beispiel drin.
Oh, hab ich glatt übersehen. So wirklich verstanden habe ich die Library
trotzdem nicht.
(
> Aber da die Lib ja für nen mc ist, weiß ich> nicht, ob das das ist, was du suchst.
Das könnte man ja umschreiben.
> In welcher Programmiersprache hättest du es denn gerne?
Im Idealfall C, aber da bin ich flexibel solange die verwendete Sprache
einigermaßen verständlich ist...
)
Michael Potthoff schrieb:> Wie komplex soll es denn werden?
So einfach wie möglich...
Michael Potthoff schrieb:> Mathedoofi schrieb:>> Achso, parallele Linien sollen parallel bleiben, also nicht auf einen>> weit entfernten Punkt zulaufen.>> ? dann gibt es aber keine Perspektive/Tiefeneffekt. Lass die 3> Koordinate einfach weg...
Verstehe ich gerade nich... Wenn ich einen Würfel mit parallelen Kanten
zeichne und von oben schräg drauf gucke habe ich doch meine
Perspektive?!?
Johann L. schrieb:> Das ist lediglich eine Matrixmultiplikation, den Overkill einer> "Bibliothek" braucht's dazu nicht:> [...]
Ah, das ist Mathe in verträglichen Dosen, nicht dieses Fachchinesisch
wie bei Wikipedia... Die Transformation lässt sich also durch eine
Matrixmultiplikation darstellen, das wirkliche Problem ist dann ja wohl
das Finden der Transformationsmatrix(?) B bzw B^-1 richtig? Was ich
nicht verstehe: Wenn ich 2 bzw 3 Vektoren nehme um meine "Leinwand"
darzustellen bekomme ich doch unendlich viele davon, muss da nicht noch
irgendwo ein Punkt dazu der auf dieser Leinwand liegt
(Koordinatenursprung)?
Ich ärgere mich übrigens gerade ziemlich das ich meine Formelsammlung
verbummelt hab...
Da es für den PC ist:
Such dir ein OpenGL Tutorial. Gibts wie Sand am Meer. Dann hast du mit
der Mathe dahinter erst mal nichts zu tun, obwohl es hilft wenn man sie
versteht. Komplexe Sachverhalte lassen sich nun mal nicht mit
Küchenutensilien erklären, so dass man sie in allen Details versteht.
Tom K. schrieb:> In openCV gibt es projectPoints(), das auf den ersten Blick Dein Problem> lösen könnte. Handlich ist openCV aber definitiv nicht.
Puh, ne, das ist wirklich nicht handlich. Danke trotzdem!
Karl Heinz Buchegger schrieb:> Da es für den PC ist:>> Such dir ein OpenGL Tutorial. Gibts wie Sand am Meer. Dann hast du mit> der Mathe dahinter erst mal nichts zu tun, obwohl es hilft wenn man sie> versteht. Komplexe Sachverhalte lassen sich nun mal nicht mit> Küchenutensilien erklären, so dass man sie in allen Details versteht.
Unterschätze meine Küche nicht! :-) Ne, ernsthaft, ich brauche
eigentlich nur einen Satz Formeln (X,Y)=f(x,y,z und Kameraposition),
verstehen muss ich die garnicht wenn genau beschrieben ist was was ist.
Ich wühle mich gerade durch diverse Tutorials und Uniskripte, mal sehen
was da raus kommt...
Mathedoofi schrieb:> Unterschätze meine Küche nicht! :-) Ne, ernsthaft, ich brauche> eigentlich nur einen Satz Formeln (X,Y)=f(x,y,z und Kameraposition),> verstehen muss ich die garnicht wenn genau beschrieben ist was was ist.
Willkommen bei Vektoralgebra und Matrizenrechnen.
Im Prinzip ist es ganz einfach :-)
(Ne, im Ernst. Auf den ersten Blick sieht das alles reichlich
kompliziert aus. Hat man den Trick aber erst mal raus, ist es wirklich
ziemlich einfach)
http://cs.fit.edu/~wds/classes/cse5255/thesis/transformation/transformation.html
asdf schrieb:> http://wiki.delphigl.com/index.php/Hauptseite
Danke!
> Mathedoofi schrieb:>> verstehen muss ich die garnicht> würde aber ungemein helfen.
Wohl war. Mathe ist schon etwas sehr Merkwürdiges...
Karl Heinz Buchegger schrieb:> (Ne, im Ernst. Auf den ersten Blick sieht das alles reichlich> kompliziert aus. Hat man den Trick aber erst mal raus, ist es wirklich> ziemlich einfach)
Wenn man es kann ist es immer einfach. :-)
Ich schreib jetzt mal das "Kochrezept" ab was ich mir erarbeitet habe
und hoffe auf Kommentare "richtig/falsch, weil". Ich benutze meine
eigenen Wörter, bitte nicht zuuu pingelig sein... Grundlage ist dieses
Skript http://www.mttcs.org:8008/Skripte/Ext/Pra/Material/vorlesung3.pdf
So ganz klar ist mir die Sache noch nicht aber ich bin ihr ein Stückchen
näher (hoffe ich...).
Also:
a. Eine Ebene ist definiert durch 2 Vektoren mit einem gemeinsamen
Ursprung.
b. Es gibt das universelle dreidimensionale Weltkoordinatensystem in dem
die Objekte positioniert werden und das dreidimensionale Kamerasystem.
Die Projektion erfolgt auf eine Ebene = "Leinwand" die parallel zur
Ebene Vektor(OX) und Vektor(OY) ist. Der Abstand zwischen beiden Ebenen
beträgt d.
c. Im Beispiel sind die Ebenen wie im Anhang zu sehen ausgerichtet.
Kochbuch:
1. Operationen festlegen die aus dem Weltkoordinatensystem das
Kamerakoordinatensystem machen.
im Beispiel: 1 - Rotation entlang OX 180°
2 - Rotation entlang OZ 90°
2. Matrixen für diese Operationen rausfinden (s. Skript) und in
umgekehrter Reihenfolge multiplizieren, anschließend "Kehrwert"
ausrechnen.
Rx = [ 1 0 0 0 ]
[ 0 -1 0 0 ]
[ 0 0 -1 0 ]
[ 0 0 0 1 ]
Rz = [ 0 -1 0 0 ]
[ 1 0 0 0 ]
[ 0 0 1 0 ]
[ 0 0 0 1 ]
M = (RzRx)^-1 = [ 0 1 0 0 ]
[ 1 0 0 0 ]
[ 0 0 -1 0 ]
[ 0 0 0 1 ]
3. Jeden Punkt in homogene Koordinaten umwandeln und mit M
multiplizieren um vom Weltksystem ins Kameraksystem zu kommen.
Sei P(5,3,2) (im Weltkoordinatensystem), in homogen [ 5 ]
[ 3 ]
[ 2 ]
[ 1 ]
P' = MP = [ 3 ]
[ 5 ]
[ -2 ]
[ 1 ]
DIE GROSSE FRAGE: STIMMT DAS BIS HIER?
Mit dem letzten Punkt habe ich noch so meine Probleme:
4. Auf die Leinwand projezieren: Mit Projektionsmatrix für
perspektivische Projektion multiplizieren (s. Skript) um 2D-Koordinaten
zu erhalten.
Sei E die Projektionsmatrix.
Sei Abstand d = 1.
E = [ 1 0 0 0 ]
[ 0 1 0 0 ]
[ 0 0 1 0 ]
[ 0 0 1/d 0 ]
entspricht also
E = [ 1 0 0 0 ]
[ 0 1 0 0 ]
[ 0 0 1 0 ]
[ 0 0 1 0 ]
P'E = [ 3 ]
[ 5 ]
[ -2 ]
[ -2 ]
in "normalen Koordinaten" umrechnen = durch -2 teilen und man erhält die
2D-Koordinaten im Kameraksystem (x,y)=(-1.5, -2.5) und die Entfernung
zur Leinwand=1. Das kommt mir aber komisch vor, ich hätte auf positive
Koordinaten getippt?!? Wenn ich d negatif mache passt es besser.
-->Problem!
Soweit also meine Erkenntnisse...
> 1. Operationen festlegen die aus dem Weltkoordinatensystem das> Kamerakoordinatensystem machen.> im Beispiel: 1 - Rotation entlang OX 180°> 2 - Rotation entlang OZ 90°>> 2. Matrixen für diese Operationen rausfinden (s. Skript) und in> umgekehrter Reihenfolge multiplizieren, anschließend "Kehrwert"> ausrechnen.
Im Prinzip, denke ich, soweit richtig, wenn auch noch sehr
unvollständig.
Allerdings ist gibt es eine einfachere Sichtweise:
Ich projeziere immer entlang der Z-Achse (oder Y, je nachdem welche
SIchtweise man bevorzugt). D.h. meine Kamera sitzt immer im Ursprung und
schaut immer von dort aus in Richtung der Achse.
Und dann verschiebe und drehe ich einfach das Universum solange, bis ich
genau meinen Beobachter im Koordinatenursprung habe und die Richtung in
die er schaut genau in diese festgelegte Achse zeigt. (Und seine
Up-Richtung mit der globalen Up-Richtung identisch ist).
Im Endeffkt kommt nach all den Manipulationen hinten nach dieselbe
Matrix raus, aber die Sichtweise ist einfacher, weil ich mich nicht mit
beliebig orientierten Bildebenen im Raum rum schlagen muss :-)
Karl Heinz Buchegger schrieb:> Schau dir mal dieses Buch an>> A trip down the graphics pipeline> Jim Blinn>> By Google gibts davon die Online-Version.> Ab Seite 21 "Nested Transformations and Blobby Man"> ist ein Artikel, der für dich interessant ist.
Ach Shit. die für dich interessanten Seiten 24 und 25 fehlen in der
Vorschau.
Karl Heinz Buchegger schrieb:> Im Prinzip, denke ich, soweit richtig, wenn auch noch sehr> unvollständig.
Ich will ja kein Buch schreiben, wenn es für meine Zwecke reicht ist
gut. Das ganze ist eh nur eine rein private Spielerei.
> Allerdings ist gibt es eine einfachere Sichtweise:> [...]> Im Endeffkt kommt nach all den Manipulationen hinten nach dieselbe> Matrix raus, aber die Sichtweise ist einfacher, weil ich mich nicht mit> beliebig orientierten Bildebenen im Raum rum schlagen muss :-)
Ich bleib jetzt bei meiner Methode, bin froh das einigermaßen verstanden
zu haben.
Kannst du noch was zur eigentlichen Projektion und dem Vorzeichenfehler
(Punkt 4) sagen?
Karl Heinz Buchegger schrieb:> Ach Shit. die für dich interessanten Seiten 24 und 25 fehlen in der> Vorschau.
Pech gehabt, Danke trotzdem!
Mathedoofi schrieb:> Ich bleib jetzt bei meiner Methode, bin froh das einigermaßen verstanden> zu haben.
Ich find die Sichtweise "Kamera bewegen" irgendwie deutlich logischer...
Mathedoofi schrieb:> Mathedoofi schrieb:>> Ich bleib jetzt bei meiner Methode, bin froh das einigermaßen verstanden>> zu haben.> Ich find die Sichtweise "Kamera bewegen" irgendwie deutlich logischer...
Nicht, wenn du die allgemeine Mathe dahinter entwickeln musst.
Das macht man in der Grafik bzw. in Copmutational Geometry oft:
Man löst ein Problem nicht im allgemeinen Fall, weil das formelmässig zu
aufwändig wird. Die Schnittpunkte einer beliebig orientierten Geraden
durch einen beliebig orientierten Zylinder zu berechnen ist formelmässig
kompliziert.
Ist der Zylinder aber im Koodinatenursprung und in einer Normallage (zb
er steht senkrecht), dann vereinfachen sich die Formeln.
Was macht man daher: Man transformiert das Problem aus seiner
allgemeinen Lage im Raum in diese Normallage, berechnet dort die Lösung
und transformiert das Ergebnis wieder zurück.
Genauso auch hier:
Habe ich meine Kamera im Koordinatenursprung und schaut sie immer
entlang der Z-Achse, dann ist die Berechnung des perspektivischen Bildes
trivial :-)
Du meinst also es ist sinnvoller die Kamera im Ursprung zu lassen und
die Objekte so zu manipulieren dass sie davor auftauchen?
Was ist mit der eigentlichen Projektion, passt meine Rechnung von oben?
Auch für diesen Fall ist es einfach:
A bezeichne die Position des Auges und P ein in die Ebene E zu
projizierender Punkt; die Projektion sei mit P' bezeichnet.
Offenbar lieht P' auf der durch A und P gegebenen Geraden:
mit einem noch zu bestimmenden Parameter λ.
Die Ebene E ist gegeben durch einen Punkt Q sowie einer Normalen n, d.h.
es gilt
In der Praxis wird man n und Q aus der Blickrichtung ableiten und dem
Abstand, den die Projektionsebene E vom Auge haben soll.
Einsetzen von P' in die letzte Gleichung liefert
Damit ist P' bestimmt. Was zu tun bleibt, ist die Koordinaten von P'
bezüglich zweier die Ebene E aufspannenden Vektoren X und Y zu finden.
siehe oben.
Nix hochtrabendes also; Anschauung nud die Basics reichen vollkommen
aus.
Johann L. schrieb:> Auch für diesen Fall ist es einfach:
Danke! So gut wie du müsste man Mathe können.
Also ich versuche es mal: (Wie oben vorgeschlagen lasse ich die Kamera
an einer Stelle stehen und bewege stattdessen die Objekte)
> A bezeichne die Position des Auges
auf der y-Achse (rechtshändiges System) bei -5: A(0;-5;0)
> und P
P(x;y;z)
> ein in die Ebene E
das ist die Ebene x0z
> zu> projizierender Punkt; die Projektion sei mit P' bezeichnet.>> Offenbar lieht P' auf der durch A und P gegebenen Geraden:>
> mit einem noch zu bestimmenden Parameter λ.>> Die Ebene E ist gegeben durch einen Punkt Q
Q(0;0;0)
> sowie einer Normalen n,
Vektor n(0;1;0)
> d.h.> es gilt>
> In der Praxis wird man n und Q aus der Blickrichtung ableiten und dem> Abstand, den die Projektionsebene E vom Auge haben soll.>> Einsetzen von P' in die letzte Gleichung liefert>
> Damit ist P' bestimmt. Was zu tun bleibt, ist die Koordinaten von P'> bezüglich zweier die Ebene E aufspannenden Vektoren X und Y zu finden.
Die Einheitsvektoren 0x und 0z passen, von daher:
P'(X;Y;Z)
X=5x/(y+5)
Y=0
Z=5z/(y+5)
Passt das so? Ich würde sagen es sieht gut aus.
Danke für die Mathenachhilfe! ;-)