# 3D Grafik Formeln



## Developer_X (17. Dez 2009)

Hi, ich habe schon sehr lange danach gegoogled, aber bin um ehrlich zu sein nie zu einem wirklichen Ergebniss gekommen.
Ich denke ihr könnt mir hier weiterhelfen.
Ihr habt sicher alle schon den MathematikStoff durch, ich bin erst in der achten.

Also:
Ich will die Formel für folgendes :

Ich habe selbst eine Klasse Vector3D geschrieben, 
es gibt die variablen x,y und z.

Nun möchte ich gerne wissen, wie ich ausrechnen kann, wo x und y sind, auf einer 2Dimensionalen Oberfläche, d.h. im Grunde genommen folgendes muss in der Fomel drin sein:

Point_x, Point_y, Point_z, und User_x, User_y, User_z.

Technisch gesehen kann man auf einer 2Dimensionalen Oberfläche wie unser aller Bildschirm es ist, keine 3Dimensionalen Objekte anzeigen, aber man kann mithilfe von Formeln herausfinden, wo die 3DKoordinaten auf der 2Dimensionalen Oberfläche sind.

Kann mir einer helfen?

Danke schon mal im Voraus Developer_X.


----------



## javimka (17. Dez 2009)

Weisst du, was eine Matrixmultiplikation ist? Damit steht und fällt eine solche Projektion!

Du hast also eine Anzahl Vektoren im 3D Raum und eine Kamera und willst wissen, wo deine Punkte im Bild der Kamera zu liegen kommen oder?


----------



## Marco13 (17. Dez 2009)

3D projection - Wikipedia, the free encyclopedia 

( 
	

	
	
		
		

		
			



)


----------



## Developer_X (17. Dez 2009)

danke, aber kannst du mir das vielleicht auch genauer erklären, das von Wikipedia reicht mir nicht, außerdem warum brauche ich ne Formel um Z auszurechnen?!

Ich wollte lediglich eine Formel, welche die 2DKoordinate auf einer Oberfläche eines 3DVektors umwandelt.

Kannst du mir so eine geben?


----------



## javimka (17. Dez 2009)

Weisst du, was eine Matrixmultiplikation ist?


----------



## Developer_X (17. Dez 2009)

nein leider nicht, ich habe mich auch schon mal an meinen Mathe Lehrer gewendet, der will mir das noch nicht erklären, aber ich denke ich weiß das nicht, ich kenn das nur von Vektoren.

Wäre nett von euch wenn ihr mir das auch noch erklären könntet.

Sry, aber ich hab leider nicht den Stoff des Studiums drauf.


----------



## Developer_X (17. Dez 2009)

ok ich habs mir mal angeguckt was eine Matrix ist, nach Wikipedia ist das aus meiner Sicht wie ein
2Dimensionales Array.

Eine Matrix ist also eine Tabellenförmige anordnungen von Objekte, zum Beispiel Mathematische Zahlen, mit denen man jeder zeit arbeiten kann, genau wie ein 2dimensionales Array.

Addieren, Subtrahieren, Multiplizieren, Dividieren, Radizieren und Potenzieren sind aber ganz komplizierte angelegenheiten, so wie ich das sehen konnte.

Aber was eine Matrix ist, habe ich gelernt, danke dass ihr mich das schon gelehrt habt.

Desweiteren habe ich folgende Vorstellung bekommen, was matrixen multiplikation sein könnte:

a b            e f
c d     *     g h

==
a * e + b * g +c * f +d *h ???

Ist eigentlich gar nicht so schwer.


----------



## javimka (17. Dez 2009)

Ganz so einfach sind Matrizen schon nicht. Wichtig für dich ist vor allem die Matrix-Vektor Multiplikation:


```
[a,b] * [x] = [ax+by]
[c,d]   [y]   [cx+dy]
```

Der Trick ist es, eine Matrix zu erstellen, die du mit jedem deiner Vektoren multiplizieren kannst und jeweils gerade den gesuchten 2D-Punkt erhälst. Um diese Matrix zu konstruieren, brauchst du Kugelkoordinaten. Kennst du die bereits?


----------



## Developer_X (17. Dez 2009)

tut mir leid die kenn ich aber auch nicht.


----------



## Developer_X (17. Dez 2009)

Nach Wikipedia:
_In räumlichen Polarkoordinaten wird ein Punkt durch seinen Abstand vom Ursprung und durch zwei Winkel angegeben. Wenn der Abstand vom Ursprung konstant ist (auf einer Sphäre = Kugeloberfläche), benötigt man nur die zwei Winkel, um einen Punkt eindeutig zu bezeichnen, und spricht dann von sphärischen Koordinaten. Der Begriff Kugelkoordinaten kann als Oberbegriff für diese beiden Fälle angesehen werden.

Für Polarkoordinaten in der Ebene (ein Abstand, ein Winkel) und Zylinderkoordinaten (zwei Abstände, ein Winkel) siehe den Artikel Polarkoordinaten._

Ich hab leider net kapiert was die damit meinen, von Wikipedia.
Das mit den Matrixen ging ja noch, aber das hier.





Dieses Bild gibt mir nicht gerade mehr aufschluss.
Da brauch ich wirklich hilfe


----------



## Developer_X (17. Dez 2009)

könntest du mir vielleicht eine Aufgabe zur Matrixen berechnung geben?
Mit variablen und so.


----------



## javimka (17. Dez 2009)

Weisst du, solche Dinge sollte dir wirklich ein Lehrer beibringen, über das Forum ist das schon sehr aufwendig.

Wenn du unbedingt eine Matrix-Aufgabe willst 
A = [1,0 ; 0,1], v = [4 ; 7]
Berechne A*v

A = [4,-3 ; 1,2], v = [2 ; 3]
Berechne A*v

A = [1,-1,1 ; 0,1,-1 ; 0,0,1], v = [1 ; 2 ; 3]
Berechne A*v

Übrigens Sind zweischen ; jeweils die Zeilen der Matrix, [a,b ; c,d] bedeutet also

```
[a , b]
[c , d]
```


----------



## Developer_X (17. Dez 2009)

*A = [1,0 ; 0,1], v = [4 ; 7]*

```
1*4 + 0*7 + 0*4 + 1*7
```

*A = [4,-3 ; 1,2], v = [2 ; 3]*

```
4 * 2 + -3*3 + 1*2 + 2*3
```

*A = [1,-1,1 ; 0,1,-1 ; 0,0,1], v = [1 ; 2 ; 3]*

```
1 * 1 + -1* 2 + 1*3 
+ 0 * 1 +  1*2 + -1*3 +0*1 + 0*2 + 0*3
```

Richtig?

Und danke dass du mir so viel beibringst.


----------



## javimka (17. Dez 2009)

Ist noch nicht ganz richtig. Du hast bei den ersten beiden Aufgabe zwar jeweils die richtigen Zahlen miteinander multipliziert, was für das erste Mal schon mal ganz vortrefflich ist, aber als Resultat kriegst du nicht eine Zahl, sondern wieder ein Vektor.
Matrix * Vektor = Vektor.

Der resultierende Vektor hat ja 2 oder 3 Elemente. Das erste Element kommt zustande, indem zu die erste Zeile der Matrix mit dem Vektor multiplizierst, also jeweils zwei Zaheln zusammenmultiplizierst und aufsummierst.
Das zweite Element kriegst du, wenn du die zweite Zeile der Matrix, wiederum mit dem Vektor multiplizierst und wieder aufsummierst.

```
[[COLOR="Red"]a[/COLOR],[COLOR="SeaGreen"]b[/COLOR] ; c,d] * [[COLOR="Red"]x[/COLOR] ; [COLOR="SeaGreen"]y[/COLOR]] = [[COLOR="Red"]a*x[/COLOR]+[COLOR="SeaGreen"]b*y[/COLOR] ; c*x+d*y]
```

Zahlenbeispiel:
[1,2 ; 3,4] * [5;6] = [1*5+2*6 ; 3*5+4*6] = [17;39]


----------



## Developer_X (17. Dez 2009)

ach so!
also das hier?

*A = [1,0 ; 0,1], v = [4 ; 7]*

```
1*4 + 0*7 
0*4 + 1*7
[U]Vector2f(4|7)[/U]
```

*A = [4,-3 ; 1,2], v = [2 ; 3]*

```
4 * 2 + -3*3 
1*2 + 2*3
[U]Vector2f(-1|8)[/U]
```

*A = [1,-1,1 ; 0,1,-1 ; 0,0,1], v = [1 ; 2 ; 3]*

```
1 * 1 + -1* 2 + 1*3 
0 * 1 +  1*2 + -1*3
0*1 + 0*2 + 0*3

[U]Vector 3f(2|-1|0)[/U]
```

Richtig?

Ich habe mit f die elemente gemeint


----------



## javimka (17. Dez 2009)

Bei der letzten Aufgabe wäre es 1*3, statt 0*3, aber sonst hast du alles komplett richtig. Bravo


----------



## Developer_X (17. Dez 2009)

hups, hab ich doch glatt übersehen!
^^

Aber nun zu den Kugelkoordinaten,
kannst du mir dazu etwas erzählen, zumindest alles nötige.


----------



## javimka (17. Dez 2009)

Ich hoffe, du kennst Polarkoordinaten.
In 2D hast du zum einen kartesische Koordinaten, als x- und y- Koordinaten. Ein Punkt in der Ebene kann aber auch anders dargestellt werden, nämlich mittels eines Winkels und dem Abstand zum Nullpunkt. Der Punkt ( pi/4, 5 ) ist also der Punkt, der im Winkel pi/4 zur x-Achse steht (gegen den Uhrzeigersinn) und den Abstand 5 zum Nullpunkt hat. Winkel werden natürlich in Radian gemessen.
Die Kugelkoordinaten sind die 3D Erweiterung der Polarkoordinaten. Es gibt einen Zusätzlichen Wert für die Koordinaten eines Punktes, nämlich den Winkel zwischen der z-Achse und der Verbingun des Punktes und dem Nullpunkt.


----------



## Developer_X (17. Dez 2009)

Also, ich habs mir mal durchgelesen, mir ist jetzt klar geworden, was Kugelkoordinaten sind,
schauen wir uns dazu doch mal das Bild an:





Es ist im grunde genommen wie das normale 3D-Koordinaten System, nur dass der ganze Raum gezerrt ist.
Meine Erklärung:
Also im Bild sind folgende Daten zu sehen:
Φ
r
θ

R erstmal zu bestimmen um eine "Platte zu bekommen".
Dann kann man sich noch auf dieser Platte nach hinten bewegen mit Φ
und von oben nach unten, natürlich auf dem kreisbogen, mit θ.

Das heißt im Grunde genommen:
x  r
y  θ
z  Φ

hab ich das so richtig verstanden?


----------



## Marco13 (17. Dez 2009)

Nur mal so als Einschub: Was die Kugekoordinaten jetzt mit der 3D-Projektion zu tun haben sollen, leuchtet mir nicht ganz ein ... ???:L


----------



## Developer_X (17. Dez 2009)

javimka hat gesagt.:


> Ich hoffe, du kennst Polarkoordinaten.
> In 2D hast du zum einen kartesische Koordinaten, als x- und y- Koordinaten. Ein Punkt in der Ebene kann aber auch anders dargestellt werden, nämlich mittels eines Winkels und dem Abstand zum Nullpunkt. Der Punkt ( pi/4, 5 ) ist also der Punkt, der im Winkel pi/4 zur x-Achse steht (gegen den Uhrzeigersinn) und den Abstand 5 zum Nullpunkt hat. Winkel werden natürlich in Radian gemessen.
> Die Kugelkoordinaten sind die 3D Erweiterung der Polarkoordinaten. Es gibt einen Zusätzlichen Wert für die Koordinaten eines Punktes, nämlich den Winkel zwischen der z-Achse und der Verbingun des Punktes und dem Nullpunkt.



Polar Koordinaten kenne ich nicht, aber habs jetzt bei wikipedia nachgelesen, und hat mir die augen noch weiter geöffnet.

Im "PolarKoordinatenSystem" kann man den Punkt mit dem Radius angeben, und dem Abstand zum Mittelpunkt des Kreises angeben, is klar, und dieses andere, das Kugelkoordinatensystem, ist ja eigentlich nur noch mal, mit nem zweiten winkel, und dem abstand.


----------



## javimka (17. Dez 2009)

Nein, die Umrechnung ist komplizierter.

Für einen Punkt p ist
r der Abstand von p zum Nullpunkt, wobei r>=0 gilt
Φ Der Winkel zwischen dem "Schatten" von p auf der x-y-Ebene und der x-Achse, wobei 0<=Φ<2*pi gilt
θ Der Winkel zwischen det z-Achse und p, wobei 0<=θ<pi gilt


----------



## Developer_X (17. Dez 2009)

Ok, hab ich kapiert,


----------



## Developer_X (17. Dez 2009)

kannste mir jetzt sagen, was ich noch wissen muss?


----------



## javimka (17. Dez 2009)

Du musst wissen, wie du die Projektionsmatrix zusammenstellen kannst. Dazu brauchst du die Kugelkoordinaten deiner Kamera. Wie du die berechnen kannst, steht auf Wikipedia.
Das schwierigste ist, mit den Werten, diese Matrix zu basteln. Wie das geht steht auch auf Wikipedia, aber ist meiner Meinung nach schlecht erklärt.


----------



## Developer_X (17. Dez 2009)

meiner meinung nach auch, deswegen, kannst dus mir bitte erklären?


> Heute ist mein Geburts tag , Developer_X 17.12.2009


----------



## javimka (17. Dez 2009)

Nein, das geht leider nicht, da müsste ich ja ein ganzes Buch schreiben. Vielleicht gehst du mal in die Bibliothek oder möglicherweise, ist das einfach noch ein bisschen zu mathematisch für dich.


----------



## Developer_X (17. Dez 2009)

ja eben deswegen brauch ich einen lehrer, den mein eigener will es mir nicht beibringen.


----------



## Marco13 (17. Dez 2009)

*räusper* ... was soll das mit den Polarkoordinaten? Ich dengele jetzt seit >10 Jahren mit Computergrafik rum, und kenne auch die Namen "Foley, van Dam, Feiner & Hughes", aber Polarkoordinaten kann ich da jetzt nicht einordnen... ???:L (Man könnte die verwenden um die Kameraposition zu beschreiben, aber das wäre ja ein Krampf im Vergleich zu dem, was z.B. ein gluLookAt macht...)


----------



## javimka (17. Dez 2009)

was macht gluLookAt denn?

Ich kenne es so, dass man die Polarkoordinaten der Kamera verwendet, um mit ein paar sin/cos die Projektionsmatrix zu erstellen. Er will ja die 2D Koordinaten auf dem Bidlschirm berechnen. 

Ich arbeite allerdings nicht seit 10 Jahren mit Computergrafik


----------



## Marco13 (17. Dez 2009)

Was genau es macht steht hier http://oss.sgi.com/cgi-bin/cvsweb.cgi/projects/ogl-sample/main/gfx/lib/glu/libutil/project.c?rev=1.4;content-type=text%2Fplain  Also, es berechnet eben den Teil der Projektionsmatrix, der sich aus der Blickrichtung (mit Aug- und Blickpunkt) ergibt. Dann noch die Perspektive dazu, dann hat man das wichtigste ja schon...


----------



## javimka (17. Dez 2009)

Sieht mir ja mehr nach C aus, als Java und der Rückgabewert ist void


----------



## Marco13 (17. Dez 2009)

Ja, ist C ... aber in Brainfuck würde man die Matrix genau so berechnen - wäre nur etwas unübersichtlicher


----------



## Guest2 (18. Dez 2009)

Moin,

DevX, das was Du machen willst ist eigentlich "nur" eine Projektion von 3D Koordinaten auf 2D Koordinaten.

Grundsätzlich brauchst Du:

v = Deinen Punkt im 3D Raum (x, y, z)
Das sind Deine Eingangsdaten. In OpenGL nennt man die Objektkoordinaten. Um einfacher Rechnen zu können, erweitert man v zu v = (x, y, z, w) wobei w bei einem Punkt immer 1 ist (also (x, y, z, 1)). (Das nennt man homogene Koordinaten)

MV = Deine ModelViewMatrix 
Beschreibt wie einzelne Objekte zum Koordinatenursprung (0,0,0) stehen. Wenn MV die Einheitsmatrix ist (in der Matrix auf der Diagonalen 1 sonnst 0), ist das so als ob Du in dem Punkt (0,0,0) stehst und in Richtung -z blickst. MV bildet die Objektkoordinaten auf die Augkoordinaten ab. Das heißt, wenn Du z.B. mit Deiner Kamera 5 Einheiten weiter links stehst, wird genau das in MV festgehalten. Technisch gesehen ist MV eine 4x4 Matrix.  

P = Deine Projektionsmatrix
Beschreibt wie Deine Kamera die 3D Koordinaten auf 2D Koordinaten abbilden soll. Wenn Du Dir einen normalen Fotoapparat ansiehst, kennst Du ja den Zoom. Daran siehst Du, das es keinen festen Weg von 3D auf 2D gibt, sondern das P von weitern Faktoren abhängt (z.B. dem Zoom). Genau brauchst Du die Fenstergröße (= das Papierformat), den Blickwinkel (= den Zoom), und den minimalen / maximalen Abstand den ein Objekt zur Kamera haben darf =  zNear / zFar) . Technisch gesehen ist auch P eine 4x4 Matrix.

v' = Deine 2D Koordinaten (x', y', z', w')
x' und y' sind das Ergebnis und das was Du wissen willst (fast), w' brauchst Du aber noch zum rechnen.


Insgesamt gilt nun: v' = (x', y', z', w') = P * MV * v

Fast das was Du willst, denn v' muss noch durch die w' Komponente in v' geteilt (normalisiert werden). Dann hast Du Koordinaten im Einheitswürfel, das heiß sie sind zwar schon auf 2D Abgebildet, aber x', y', z' liegen alle noch zwischen -1 und +1 ("Normalized Device Coordinates"). Da Du ja Fensterkoordinaten willst, musst Du diese noch entsprechend verschieben und aufziehen. (z.B. x'' = (x' + 1) / 2 * Fensterbreite).

Also insgesamt:

x'' = (x' / w' + 1) / 2 * Fensterbreite 
y'' = (y' / w' + 1) / 2 * Fensterhöhe 


Der Einfachheit halber nehmen wir jetzt an Du stehst mit Deiner Kamera in (0,0,0) und Blickst nach -z, dann wird MV zur Einheitsmatrix (ist dann wie * 1 und kann wegfallen), dann gilt:

v' = (x', y', z', w')  = P * v

und (immer noch):

x'' = (x' / w' + 1) / 2 * Fensterbreite 
y'' = (y' / w' + 1) / 2 * Fensterhöhe

Außer dem P müsstest Du jetzt erstmal alles kennen bzw. berechnen können.

Und das P muss man jetzt erstmal einfach wissen (also unten kopieren)(man kann es auch herleiten, aber nicht mehr heute  )

In Java sieht das dann so aus (oder soll ich es mal in Brainfuck versuchen? ) :


```
public class Projection {

    public static float[] gluPerspective(final float fovy, final float aspect, final float zNear, final float zFar) {

        final float[] projectionMatrix = new float[15];

        final float f = (float) (1.0 / Math.tan(Math.toRadians(fovy / 2.0)));

        projectionMatrix[0] = f / aspect;
        projectionMatrix[5] = f;
        projectionMatrix[10] = (zFar + zNear) / (zNear - zFar);
        projectionMatrix[14] = (2 * zFar * zNear) / (zNear - zFar);
        projectionMatrix[11] = -1;

        return projectionMatrix;

    }


    public static float[] project(final float[] projectionMatrix, final float x, final float y, final float z) {

        // Clip Coordinates
        final float clipCoordinateX = x * projectionMatrix[0];
        final float clipCoordinateY = y * projectionMatrix[5];
        final float clipCoordinateZ = z * projectionMatrix[10] + projectionMatrix[14];
        final float clipCoordinateW = z * projectionMatrix[11];

        // Normalized Device Coordinates
        return new float[] { clipCoordinateX / clipCoordinateW, clipCoordinateY / clipCoordinateW, clipCoordinateZ / clipCoordinateW };

    }


    public static int[] clipAndTranslateDivide(final float[] normalizedDeviceCoordinates, final float width, final float height) {

        // clip z
        if (!(normalizedDeviceCoordinates[2] >= -1 && normalizedDeviceCoordinates[2] <= +1))
            return null;

        // clip x
        final int x = Math.round((normalizedDeviceCoordinates[0] + 1) / 2 * width);
        if (!(x >= 0 && x <= width))
            return null;

        // clip y
        final int y = Math.round((normalizedDeviceCoordinates[1] + 1) / 2 * width);
        if (!(y >= 0 && y <= width))
            return null;

        return new int[] { x, y };

    }


    public static void main(final String[] args) {

        // Viewport parameters
        final float width = 500;
        final float height = 500;
        final float fovy = 90f;
        final float zNear = 1f;
        final float zFar = 100f;

        // Eye Coordinates
        final float x = -1.0f;
        final float y = 0.5f;
        final float z = -1.0f;

        final float[] projectionMatrix = gluPerspective(fovy, width / height, zNear, zFar);
        final float[] normalizedDeviceCoordinates = project(projectionMatrix, x, y, z);
        final int[] windowCoordinates = clipAndTranslateDivide(normalizedDeviceCoordinates, width, height);

        System.out.println("Point(" + x + ", " + y + ", " + z + ") is at " + Arrays.toString(windowCoordinates));

    }
}
```


Ergibt:


```
Point(-1.0, 0.5, -1.0) is at [0, 375]
```

Also genau da wo man ihn erwaten würde.

(Kann trotzdem sein das da irgendwo noch ein Dreher drinne steckt, aber ist mir jetzt spät genug  )

P.S.: Mir ist durchaus bewusst das Du das nicht auf Anhieb verstehen wirst (kannst), aber einfach nicht aufgeben, dann wird es schon irgendwann klarer werden (zumindest ein wenig  ) 


@Marco (bzgl. den Polarkoordinaten): Danke, wollte eben schon den Foley, van Dam raus graben, weil ich dachte ich hätte was verdrängt 

Gruß,
Fancy


----------



## Developer_X (18. Dez 2009)

Danke für diese Erklräung, ich werd mir das mal mehrmals durchlesen, und ich muss dir sagen danke, da ich gerne nicht nur JOGl oder JAVA3D verwenden möchte,
 ich möchte mal selbst dieses ganze selbst machen, oder wenigstens wissen wie man das macht.

Danke euch allen.

DX


----------



## Marco13 (18. Dez 2009)

Um das nochmal explizit zu erwähnen: In Amazon.com: Computer Graphics: Principles and Practice in C (2nd Edition) (9780201848403): James D. Foley, Andries van Dam, Steven K. Feiner, John F. Hughes: Books steht das alles drin. Das ist die "Bibel" der Grafikprogrammierung, aber ebenso wie die Bibel würde ich auch bei diesem Buch kaum jemandem empfehlen, es zu lesen. Lange Ausführungen über PHIGS und CRTs (was? ???:L ) sind nicht mehr zeitgemäß. Einiges ändert sich aber nie: Speziell die mathematischen Grundlagen* von Projektionen und anderen Transformationen sind dort ausführlich erklärt. Nicht einfach. Nicht immer so verständlich, wie man sie mit einem gewissen didaktischen Wohlwollen vielleicht machen könnte. Aber ausführlich.

*Grundlagen heißt hier: Das, was auf dem Stoff der 12.-13. Klasse aufbaut...


----------

