Eigene 3D Visualisierung

thunderwave

Grünschnabel
Hallo alle zusammen!

Ich wollte gerne eine Anwendung in Java schreiben die mir simple dreidimensionale Objekte wie zum Beispiel einen Quader darstellen kann.
Mein Ziel ist es außerdem sowohl das Objekt zu bewegen als auch zu rotieren. Außerdem sollen die Kamera Koordinaten ebenfalls änderbar sein.

Ich habe einige Seiten durchgestöbert, und bin auf folgendes gestoßen:

jjam.de Hier gibts unter der Kategorie 3D drei Applets mit dem Namen Würfel. Das sieht auf den ersten Blick perfekt aus. Die Rotation des Objektes ist sogar schon mit integriert. Ich habe die Anwendung erweitert und versucht ein wenig rum zu spielen. Habe bei Wikipedia diese Seite hier gefunden 3D Perspective projection und erkannt, dass das Applet von jjam.de ebenfalls diese Transformationsmatrix verwendet mit den ganzen cos / sin Berechnungen. Im Applet wird also der Vektor d berechnet. Ich konnte das Programm leider nicht erweitern, dass ich auch die Kameraposition ändern konnte. Bei Wikipedia steht zwar dass es eine Kamera Transformation ist und:
a- the 3D position of a point A that is to be projected.
c - the 3D position of a point C representing the camera.
Aber nachdem ich die beiden Parameter implementiert habe, entsprach es nicht der Kamerabewegung sondern einer Bewegung des Objektes. In der Formel sieht man ja auch, dass einfach nur der Vektor c von a subtrahiert wird. Das ist nicht das, was ich eigentlich wollte.


Habe dann schließlich weiter gegoogelt und die ganze Zeit ziemlich mathematisch belastete Transformationen mit 4x4 Matrizen gefunden. Bin mir nicht sicher, aber ich vermute in der 4.Dimension steckt da die Information über die Kameraposition drin. Allerdings habe ich nicht rausfinden können, wie so eine 4x4 Matrix dann letztendlich auf eine 2D Fläche umgewandelt wird.

Ich hoffe ihr könnt mir helfen.
Schöne Grüße zur Nacht

thunderwave
 
Hallo,

in den Applet Demos welche mit dem SUN JDK mitkommen findest du ein Beispiel zur Darstellung von 3D-Objekten:
C:\Program Files\Java\jdk1.6.0_23\demo\applets\WireFrame

Gruß Tom
 
Hi thunderwave,

möchtest Du, dass das Objekt vom User bewegt wird oder soll die Rotation automatisch durchgeführt werden ?
Muß es Java 2D oder darf es auch Java 3D sein ?

Gruß

knoppi
 
@Thomas
Danke für den Link, hab mir das Beispiel runtergeladen und ausgeführt. Die Beispiele sind relativ komplex und der Quellcode ist kaum dokumentiert leider, hilft mir also nicht wirklich weiter.

@knoppi60
Ich würde es gerne in 2D belassen, mir fehlt ja nur eine kleine Funktioinalität und bisher benutze ich nur Java 2D Befehle. Die Java 3D API funktioniert ja im Vergleich zu 2D ganz anders, mit einem Szene Graph, etc.

Ich möchte das Objekt um einen festen Wert entweder an der Position 1 oder an der Position 2 wechseln. Der Benutzer soll also nicht beliebig bewegen können. Zu beachten ist, dass ich aber nicht das Objekt selber bewegen will, sondern den Betrachter. Stelle dir vor, du schaust nur mit dem linken Auge drauf (Position 1), dann wechselst du, linkes Auge zu, rechtes auf (Position 2).

Die Rotation ist schon fertig, das funktioniert, ich brauch nur, dass ich die Position des Betrachters ändern kann. Ich glaube das was ich meine ist bei der Formel hier auf Wikipedia zu erkennen.
e_x,y,z = the viewer's position relative to the display surface

Ich poste mal den Quelltext, den ich schon habe:

Rotationsberechnung:

Code:
/**
	 * @param geo list of points / coordinates to transform / project
	 * @param thetaX orientation x axis
	 * @param thetaY orientation y axis
	 * @param thetaZ orientation z axis
	 * @param camX x position of camera
	 * @param camY y position of camera
	 * @param camZ z position of camera
	 */
	public void transform3DTo2D(Geom3D geo, double thetaX, double thetaY,
			double thetaZ, double camX, double camY, double camZ) {
		double aX, aY, aZ; // temp point

		for (Point3D p : geo.points) {
			aX = p.x;
			aY = p.y;
			aZ = p.z;

			// 3D -> 2D transformation matrix calculation with rotation 
			// and camera coordinate parameters
			aY = p.y;
			aZ = p.z;
            // Rotation um x-Achse
            //p[i][x] = px;
            p.y = (aY-camY)*Math.cos(thetaX)-(aZ-camZ)*Math.sin(thetaX);
            p.z = (aY-camY)*Math.sin(thetaX)+(aZ-camZ)*Math.cos(thetaX);

            aX = p.x;
            aZ = p.z;
            // Rotation um y-Achse
            p.x = (aX-camX)*Math.cos(thetaY)+(aZ-camZ)*Math.sin(thetaY);
            //p[i][y]= py;
            p.z =-(aX-camX)*Math.sin(thetaY)+(aZ-camZ)*Math.cos(thetaY);

            aY = p.y;
            aX = p.x;
            // Rotation um z-Achse
            p.x = (aX-camX)*Math.cos(thetaZ)-(aY-camY)*Math.sin(thetaZ);
            p.y = (aY-camY)*Math.cos(thetaZ)+(aX-camX)*Math.sin(thetaZ);
		}
	}
Und hier das Zeichnen
Code:
final static double PERSPECTIVE_FACTOR = 1000;
	
	/**
	 * @param g2d graphics 
	 * @param cube - geometric object with coordinates
	 * @param offset2D - relative move on the display
	 * @param eye - the viewer's position relative to the display surface
	 */
	public static void paint(Graphics2D g2d, Cube cube, int[] offset2D, Point3D eye) {
		int wx = offset2D[0];
		int wy = offset2D[1];
            
		for (Point3D[] pa : cube.lineList) {
			double fromZ = pa[0].z;
			double toZ = pa[1].z;
			int fromX = (int) (wx + (pa[0].x) * (1+fromZ/PERSPECTIVE_FACTOR));
			int fromY = (int) (wy + (pa[0].y) * (1+fromZ/PERSPECTIVE_FACTOR));
			int toX = (int) (wx + (pa[1].x) * (1+toZ/PERSPECTIVE_FACTOR));
			int toY = (int) (wy + (pa[1].y) * (1+toZ/PERSPECTIVE_FACTOR));
			
			// b_x = (d_x - e_x) (e_z / d_z)
			// b_y = (d_y - e_y) (e_z / d_z)
			if (eye != null && eye.z != 0) {
				fromX = (int) ((fromX - eye.x) * (eye.z / fromZ));
				fromY = (int) ((fromY - eye.y) * (eye.z / fromZ));
				toX = (int) ((toX - eye.x) * (eye.z / toZ));
				toY = (int) ((toY - eye.y) * (eye.z / toZ));
			}
			g2d.drawLine(fromX, fromY, toX, toY);
		}       
	}

Das interessante ist nun: Solange ich eye auf null lasse klappt alles wunderbar. Das Rotieren, Bewegen und auch die Perspektive sieht in Ordnung aus. Setze ich aber eye auf x=1, y=1, z=1 dann ist das Bild weg, oben in der linken Ecke sieht man ab und zu kurze Linien.

Ich habe auch alle möglichen Werte ausprobiert, sogar interaktiv. Im interaktiven Modus hatte ich ein besseres Bild bekommen, aber sobald ich die Animation mit Rotation starte, kommt nur Müll raus.

Was mache ich falsch?

PS: Mein konkreter Anwendungsfall ist das Erzeugen von zwei Bildern (an Position 1 und 2) für ein 3D Bild. Momentan ist das Bild aber nicht korrekt, die Objekte auf den beiden Bildern sind parallel.
 
Zuletzt bearbeitet:
Hi thunderwave,

vielleicht ist der Wert für eye zu groß? Vielleicht solltest du auch den Blickwinkel anpassen.
Wie sieht es denn aus, wenn das 3D Objekt nicht rotiert ?

Grüße

knoppi
 
Zuletzt bearbeitet:
Hi Knoppi,
Die Größe des Wertes spielt keine Rolle, auch bei kleinen Weren passt es nicht. Blickwinkel ist genau das richtige Stichwort. Wenn nämlich die Betrachterposition wechselt bzw. mit jeweils einem Auge draufschaut, ändert sich ja der Winkel.

Ich dachte, dass ich dafür nur den Eye Wert einstellen muss und der Winkel automatisch aus der Rotationsmatrix berechnet wird. Tuts aber nicht... Das heißt dafür muss es eine Extra Berechnung geben.
 
Jou, ich geh mal grad von den 3D-Libs aus ;)
In den 3D-Bibliotheken wie z.B. OpenGL oder auch Java3D, was u.a. darauf basiert, usw. gibts einmal den Standpunkt oder Beobachterposten oder auch Kamera und dann noch eine Funktion oder Methode lookAt, in der die Blickrichtung beschrieben wird.

Ich bin was am nachschauen - das kann jetzt was dauern *gg*.
Da ich für 3D-Welt erstellen mit der 2D-Bibliothek jetzt auch nicht so der Experte bin. Im Prinzip ist das Problem hier ja auch das gleiche: wo steh ich und wo guck ich hin ?

Viele Grüße

knoppi

PS: Da hast du dir aber einiges vorgenommen :D
 
Zurück