gluLookAt mit glMultMatrix und Array

Seikuassi

Aktives Mitglied
Hallo Forum-Nutzer,

mit dieser Frage möchte ich im Prinzip eine Java (oder von mir aus auch eine C/C++)-Methode/-Funktion erhalten, mit der man die gluLookAt-Methode mit glMultMatrix und einem (in meinem Fall) float-Array ausführen kann.

Die Deklaration der Methode sieht theoretisch wie die gluLookAt-Methode folgendermaßen aus:
Java:
private void lookAt(float eyeX,float eyeY,float eyeZ,float centerX,float centerY,float centerZ,float upX,float upY,float upZ);
Also eye war der Betrachterpunkt (Wo stehe ich?), center der Referenzpunkt in der Szene (Wo schaue ich hin?) und up der Up-Vektor.

Die Funktion würde theoretisch dann so ausgeführt werden:
Java:
public void draw(){
   glMatrixMode(GL_PROJECTION); // Perspektive-Matrix verwenden
   {
      glLoadIdentity(); // Standard-Matrix laden (überhaupt nötig???)
   }
   glMatrixMode(GL_MODELVIEW); // Modell-Matrix verwenden
   {
      glLoadIdentity(); // Standard-Matrix laden
      lookAt(0f,0f,-5f,0f,0f,0f,0f,1f,0f); // "Kameraposition" festlegen
      drawCube(0.1f); // eigene Methode, die einen Würfel in die Welt zeichnet
   }
   return;
}

Frage:Wie müsste die Methode aussehen, wenn ich auch nur möglichst Standard-Java (Math.cos etc.) bzw. "normale" OpenGL-Funktionen (gl...) verwenden würde? Und wo müsste diese Funktion aufgerufen werden - in der Projektions-Matrix oder der Modell-Matrix?

Vielen Dank im Voraus!

Mit freundlichen Grüßen
Seikuassi

P.S.: Für eine einfache Methode (1:1 wie ich es beschrieben habe), wäre ich sehr dankbar.
 
Kurz ich nochmal.

Ich benutze LWJGL für die Grafiken.

glTranslatef(x,y,z) multipliziert ja die aktuelle Matrix mit
| 1 0 0 x |
| 0 1 0 y |
| 0 0 1 z |
| 0 0 0 1 |

Was mache ich falsch bzw. anders wenn ich folgenden Code schreibe:
Java:
glLoadIdentity(); // Default-Matrix laden
float[]m={ // Matrix erstellen
   1f,0f,0f,0f,
   0f,1f,0f,0f,
   0f,0f,1f,0f,
   x,y,z,1f};
glMultMatrix(FloatBuffer.wrap(m)); // Matrix multiplizieren (habe ich wrap falsch verstanden?) => Programm stürzt ab
Allerdings bewegt sich dann nichts in der Szene bzw. das Programm stürzt ab, anders wie beim glTranslatef.
Denn wenn das mit der Matrizenmultiplikation klappen würde, wäre das Hauptthema schon um einiges leichter...

Danke nochmal!

Mit freundlichen Grüßen,

Seikuassi
 
Hallo nochmal,

also das FloatBuffer-Problem ist gelöst. Habe völlig übersehen, dass LWJGL in der Klasse BufferUtils FloatBuffer erzeugen kann 😳.

Kurz nochmal zur der Frage bzw. einer Alternative...: Findet Ihr es für ein Spiel oder allgemein für eine 3D-Welt sinnvoll, wenn man gluLookAt verwendet oder die Kamera dreht ohne einen Referenzpunkt (centerXYZ) zu haben?
Wie müsste die Berechnung der Matrix aussehen, die die Kamera positioniert und die X- und Y-Achse von der verschobenen gleichen Kamera dreht, die man dann z.B. mit glMultMatrix laden kann? Das also folgender Code gleichzeitig ausgeführt wird:
Java:
glTranslatef(x,y,z); // Position festlegen
glRotatef(rot[0],1f,0f,0f); // X-Achse drehen
glRotatef(rot[1],0f,1f,0f); // Y-Achse drehen

Danke im Voraus!

Seikuassi
 
Lösungen gefunden.

Für die Methode, dass man gluLookAt nachbilden möchte, muss man die Vector3f-Klasse verwenden (oder selbst nachbilden) und entsprechen die Matrix setzen (siehe gluLookAt-Matrix).

Für den Fall, dass man die "Kamera" zu der Position bewegt, in der man gerade schaut, muss man mit trigonometrischen Funktionen (sin, cos, tan) arbeiten.
Hier mal für LWJGL 3.0.0a so ein Code (WindowCallbackAdapter):
Java:
public void key(long window,int key,int scancode,int action,int mods){
		if(key==GLFW_KEY_ESCAPE&&action==GLFW_PRESS){ // wenn die Escape-Taste gedrueckt wurde
			glfwSetWindowShouldClose(window,GL_TRUE); // Fenster schliessen
		}else if(key==GLFW_KEY_W&&(action==GLFW_PRESS||action==GLFW_REPEAT)){ // wenn die W-Taste gedrueckt wurde
			Game.loc.x+=this.speed*Math.sin(Math.toRadians(Game.loc.yaw));
			Game.loc.y-=this.speed*Math.tan(Math.toRadians(Game.loc.roll));
			Game.loc.z+=this.speed*Math.cos(Math.toRadians(Game.loc.yaw));
			Game.loc.x=(float)Math.round(Game.loc.x*100000)/100000; // Wert auf 5 Nachkommastellen runden
			Game.loc.y=(float)Math.round(Game.loc.y*100000)/100000; // Wert auf 5 Nachkommastellen runden
			Game.loc.z=(float)Math.round(Game.loc.z*100000)/100000; // Wert auf 5 Nachkommastellen runden
			System.out.println(Game.loc.x+" "+Game.loc.y+" "+Game.loc.z);
		}else if(key==GLFW_KEY_S&&(action==GLFW_PRESS||action==GLFW_REPEAT)){ // wenn die S-Taste gedrueckt wurde
			Game.loc.x-=this.speed*Math.sin(Math.toRadians(Game.loc.yaw));
			Game.loc.y+=this.speed*Math.tan(Math.toRadians(Game.loc.roll));
			Game.loc.z-=this.speed*Math.cos(Math.toRadians(Game.loc.yaw));
			Game.loc.x=(float)Math.round(Game.loc.x*100000)/100000; // Wert auf 5 Nachkommastellen runden
			Game.loc.y=(float)Math.round(Game.loc.y*100000)/100000; // Wert auf 5 Nachkommastellen runden
			Game.loc.z=(float)Math.round(Game.loc.z*100000)/100000; // Wert auf 5 Nachkommastellen runden
			System.out.println(Game.loc.x+" "+Game.loc.y+" "+Game.loc.z);
		}else if(key==GLFW_KEY_A&&(action==GLFW_PRESS||action==GLFW_REPEAT)){ // wenn die A-Taste gedrueckt wurde
			Game.loc.x-=this.speed*Math.sin(Math.toRadians(Game.loc.yaw+90f));
			Game.loc.z-=this.speed*Math.cos(Math.toRadians(Game.loc.yaw+90f));
			Game.loc.x=(float)Math.round(Game.loc.x*100000)/100000; // Wert auf 5 Nachkommastellen runden
			Game.loc.z=(float)Math.round(Game.loc.z*100000)/100000; // Wert auf 5 Nachkommastellen runden
			System.out.println(Game.loc.x+" "+Game.loc.y+" "+Game.loc.z);
		}else if(key==GLFW_KEY_D&&(action==GLFW_PRESS||action==GLFW_REPEAT)){ // wenn die D-Taste gedrueckt wurde
			Game.loc.x+=this.speed*Math.sin(Math.toRadians(Game.loc.yaw+90f));
			Game.loc.z+=this.speed*Math.cos(Math.toRadians(Game.loc.yaw+90f));
			Game.loc.x=(float)Math.round(Game.loc.x*100000)/100000; // Wert auf 5 Nachkommastellen runden
			Game.loc.z=(float)Math.round(Game.loc.z*100000)/100000; // Wert auf 5 Nachkommastellen runden
			System.out.println(Game.loc.x+" "+Game.loc.y+" "+Game.loc.z);
		}else if(key==GLFW_KEY_E&&(action==GLFW_PRESS||action==GLFW_REPEAT)){ // wenn die E-Taste gedrueckt wurde
			Game.loc.y-=this.speed;
			Game.loc.y=(float)Math.round(Game.loc.y*100000)/100000; // Wert auf 5 Nachkommastellen runden
			System.out.println(Game.loc.x+" "+Game.loc.y+" "+Game.loc.z);
		}else if(key==GLFW_KEY_R&&(action==GLFW_PRESS||action==GLFW_REPEAT)){ // wenn die R-Taste gedrueckt wurde
			Game.loc.y+=this.speed;
			Game.loc.y=(float)Math.round(Game.loc.y*100000)/100000; // Wert auf 5 Nachkommastellen runden
			System.out.println(Game.loc.x+" "+Game.loc.y+" "+Game.loc.z);
		}else if(key==GLFW_KEY_UP&&(action==GLFW_PRESS||action==GLFW_REPEAT)){ // wenn die obere Pfeil-Taste gedrueckt wurde
			if(Game.loc.roll<=0f){
				Game.loc.roll=360f;
			}
			Game.loc.roll-=this.rot_speed;
			Game.loc.roll=(float)Math.round(Game.loc.roll*100000)/100000; // Wert auf 5 Nachkommastellen runden
		}else if(key==GLFW_KEY_DOWN&&(action==GLFW_PRESS||action==GLFW_REPEAT)){ // wenn die untere Pfeil-Taste gedrueckt wurde
			if(Game.loc.roll>=360f){
				Game.loc.roll=0f;
			}
			Game.loc.roll+=this.rot_speed;
			Game.loc.roll=(float)Math.round(Game.loc.roll*100000)/100000; // Wert auf 5 Nachkommastellen runden
		}else if(key==GLFW_KEY_LEFT&&(action==GLFW_PRESS||action==GLFW_REPEAT)){ // wenn die linke Pfeil-Taste gedrueckt wurde
			if(Game.loc.yaw<=0f){
				Game.loc.yaw=360f;
			}
			Game.loc.yaw-=this.rot_speed;
			Game.loc.yaw=(float)Math.round(Game.loc.yaw*100000)/100000; // Wert auf 5 Nachkommastellen runden
		}else if(key==GLFW_KEY_RIGHT&&(action==GLFW_PRESS||action==GLFW_REPEAT)){ // wenn die rechte Pfeil-Taste gedrueckt wurde
			if(Game.loc.yaw>=360f){
				Game.loc.yaw=0f;
			}
			Game.loc.yaw+=this.rot_speed;
			Game.loc.yaw=(float)Math.round(Game.loc.yaw*100000)/100000; // Wert auf 5 Nachkommastellen runden
		}
		return;
	}

Wieder mal eine Frage selbst beantwortet 😉.
 

Zurück
Oben