# [JOGL 2.0] Kleines Problem mit freier Flugsteuerung



## Daniel.S (20. Aug 2011)

Hallo!

Ich arbeite derzeit an einem 3D-Sonnensystem. Man soll als Beobachter (das Raumschiff) unser Sonnensystem erkunden können. Gesteuert wird per Maus und W (Schub nach vorne) und S (Umkehrschub). Mein "yaw" (Rotation um y-Achse) funktioniert ohne Probleme. Wenn ich aber einen Kreis um die x-Achse fliege gibt es irgendwann ein Problem: Irgendwann fliege ich einfach nachhinten. 
Ich habe eine Vermutung dass es am tan(x) liegt. Kann das Problem aber leider nicht näher spezifizieren...
Hier mal der Source-Code der Maussteuerung:

```
public class MouseMovingControl extends AMovingControl {
	
	public MouseMovingControl(OrbitSimulator orbitSim) {
		super(orbitSim);
	}
	
	 public void mouseMoved(MouseEvent e) {
    	 this.orbitSim.mouseMotionStartX = e.getX();
         this.orbitSim.mouseMotionStartY = e.getY();
    	
    }
    
    public void mouseDragged(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        this.calcYAngle( (float)((x -this.orbitSim.mouseMotionStartX)));
        this.calcXAngle((float)(-(y - this.orbitSim.mouseMotionStartY)));
        this.orbitSim.mouseMotionStartX = x;
        this.orbitSim.mouseMotionStartY = y;
        this.orbitSim.repaint();
    	System.out.println(this.orbitSim.yaw + "y-Achse");
    	System.out.println(this.orbitSim.pitch +"x-Achse");
    }
    
    //Berechne Winkel um y-Achse
    private void calcYAngle(float amount) {
    	float yaw = this.orbitSim.yaw;
    	yaw += amount;
   	   while(yaw > 360 ||yaw < 0) {
			  if(yaw > 360) {
				 yaw -= 360;
			  }
			  if(yaw < 0) {
				  yaw += 360;
			  }
		  }
    	this.orbitSim.yaw = yaw;
    }
    
    //Berechne Winkel um x-Achse
    private void calcXAngle(float amount) {
   	float pitch = this.orbitSim.pitch;
   	pitch += amount;
  	   while(pitch > 360 ||pitch < 0) {
			  if(pitch > 360) {
				  pitch -= 360;
			  }
			  if(pitch < 0) {
				  pitch += 360;
			  }
		  }
  	   this.orbitSim.pitch = pitch;
     }
}
```

Hier der Code der die eigentliche Position nachher berechnet:

```
//Bewegung nach vorne
	  private void walkForward() {

		  this.orbitSim.position[0] -= this.speed *  (float)Math.sin(Math.toRadians(this.orbitSim.yaw));                                            
		  this.orbitSim.position[1] += this.speed * (float)Math.tan(Math.toRadians(this.orbitSim.pitch));
		  this.orbitSim.position[2] += this.speed * (float)Math.cos(Math.toRadians(this.orbitSim.yaw));
	   }
```

position[0] = x-Achse
position[1] = y-Achse
position[2] = z-Achse
Sieht jemand einen Fehler? Eventuell fehlt mir ja einfach eine Einschränkung einer Funktion auf einen bestimmten Wertebereich.
Danke!


----------



## Marco13 (20. Aug 2011)

Sieht ein bißchen ... wackelig aus... Diese Berechnung der neuen Position mit sin, cos und vor allem tan... Wo kommt der 'tan' her? Steht der nur ... so der Vollständigkeit halber da, damit alle drei mal vorkommen? 


Verwendest du irgendeine Lib oder ein paar Klassen für Matrizen und Vektoren (Vecmath, oder irgendwas eigenes?) - dem aktuellen Code nach wohl nicht...?! 

Es wäre vermutlich vorteilhaft, die aktuelle _Orientierung_ (also Blickrichtung und Rotation um die Blickrichtung) in einer Form zu speichern, die ohne Eulerwinkel auskommt. Wenn man nicht aufpasst, bekommt man da nämlich auch einen Gimbal Lock ? Wikipedia . Kürzlich war ein Thread zur Steuerung eines Objektes in 3D, der sich auf Java3D bezog, aber bei dem die für die Steuerung am ehesten relevanten Teile (d.h. bewegen und drehen) ziemlich unabhängig von Java3D waren: http://www.java-forum.org/spiele-multimedia-programmierung/122050-java-3d-steuerung-kskb.html - Passt vielleicht nicht ganz zu deiner gewünschten Steuerung, aber könnte ein paar Ansätze enthalten.


----------



## Daniel.S (20. Aug 2011)

Ja das mit dem tan ist schwachsinn. Im Prinzip möcht ich (der Beobachter) mich halt dahin bewegen, wo ich gerade hingucke. Ich benutze kein gluLookAt sondern transformiere "von Hand":

```
gl.glRotatef(pitch, 1.0f, 0.0f, 0.0f);
	        gl.glRotatef(yaw, 0.0f, 1.0f, 0.0f);
	        gl.glTranslatef(position[0], position[1], position[2]);
```

Math Libs etc. hab ich bisher nicht genutzt, da ich bis vor kurzem auf die rotation um die x-achse verzichtet habe.


----------



## Marco13 (20. Aug 2011)

In dem Verlinkten Thread wurde so eine Steuerung im Prinzip ja umgesetzt. Allerdings unter Verwendung der Vecmath-Klassen (Matrix4f, Point3f, Vector3f...). Grundsätzlich könntest du das ohne diese Klassen nachbauen, aber ... ohne irgendeine Repräsentation von Punkten, Vektoren und Matrizen wird man in 3D nicht glücklich...


----------

