CameraNode and setLocalRotation. [Solved]

Hi!



I'm trying to rotate my camera such an Euler angles and I'm really having serious problems :frowning:

I'll try a lot of things, like converting this angles to an quaternion, to a Matrix , with some codes I found on Internet, and then applying it directly to the cam but it has not the results I want. So I decided to use the CameraNode to make it easy, but also having problems.

First of all I want to say that I'm using Polhemus, a system of Tracking, which return me the angles in Euler mode. So this is because I can't change "the type of the angles". In openGL, I simply do something like:



glRotatef( ds.pnoInfo[1].az  , 0.0f , 1.0f , 0.0f );

glRotatef( ds.pnoInfo[1].el  , 1.0f , 0.0f , 0.0f );

glRotatef( ds.pnoInfo[1].roll , 0.0f , 0.0f , 1.0f );



and it works fine.



In jME I'll try several things but I think this ones are the most cute.



      mNodeCam.setLocalRotation((new Quaternion(new float[] {ds.pnoInfo[1].az,0,0})));

      mNodeCam.updateWorldData(0);

      mNodeCam.setLocalRotation(new Quaternion(new float[] {0,ds.pnoInfo[1].el(),0}));

      mNodeCam.updateWorldData(0);

      mNodeCam.setLocalRotation(new Quaternion(new float[] {0,0,ds.pnoInfo[1].roll}));

      mNodeCam.updateWorldData(0);



or

      mNodeCam.setLocalRotation((new Quaternion(new float[] {ds.pnoInfo[1].az,0,0})));

      mNodeCam.setLocalRotation(new Quaternion(new float[] {0,ds.pnoInfo[1].el(),0}));

      mNodeCam.setLocalRotation(new Quaternion(new float[] {0,0,ds.pnoInfo[1].roll}));

      mNodeCam.updateWorldData(0);



The Polhemus return the angles in radians.



Anyone knows what can be happening? Because I don't know what else try. If there is any suggest completely different of this, I'll also accept it :slight_smile: :slight_smile: :slight_smile:



Thanks!

i think thats what you want:


/** fromAngles builds a quaternion from the Euler rotation angles (x,y,z). */
getLocalRotation().fromAngles(ds.pnoInfo[1].el, ds.pnoInfo[1].az, ds.pnoInfo[1].roll );

It could be a good solution :slight_smile: I'll try it tomorrow.



Thankss!!!

Hi there,



I tried something similar than yours, but it doesn't work :frowning:

I mean, I can't do getLocalRoatation because what I want is set, but I've got the idea, and I make a Quaternion using this function (fromAngles). The code was:



Quaternion mRotation = new Quaternion();

mRotation.fromAngles(ds.pnoInfo[1].el, ds.pnoInfo[1].az, ds.pnoInfo[1].roll );

rootNode.setLocalRotation(mRotation);



As you can see, I'll do it in a rootNode that contains a box (just to make it easier to verify if it's going well), but the only thing I've got it's a simple rotation in the Z Axis.



I think the problem it's next:

In openGL you can accumulate the operations, so when you do an rotation in X Axis and then another rotation in Y Axis is not the same than if you first do the rotation in Y Axis and then in X axis. So notice that in my code openGL:


glRotatef( ds.pnoInfo[1].az  , 0.0f , 1.0f , 0.0f );
glRotatef( ds.pnoInfo[1].el  , 1.0f , 0.0f , 0.0f );
glRotatef( ds.pnoInfo[1].roll , 0.0f , 0.0f , 1.0f );


I first do an rotation in Y Axis then in X Axis and finally in Z Axis... Anyway to do it?

Lots of thanks.

You can multiply quaternions to perform a delta rotation.


// Create a quaternion which represents the desired delta rotation.
// In this case I'm only rotating in the X axis.
Quaternion delta = new Quaternion(new float[]{.01f, 0, 0});

// multLocal() performs the multiplication AND updates the quaternion.
// mult() would perform the multiplication and return the result withoutout
// performing an update.
Quaternion current = ...
current.multLocal(delta);

Sorry if I don't inderstand it at all, but I think that what your code do is "auto Increment" the rotation, and in my case I have new angles in each update gived by my sensor. So I think it doesn't works. Thanks anyway :slight_smile: :slight_smile:

the two code pieces do the same.


rootNode.getLocalRotation()mRotation)fromAngles(ds.pnoInfo[1].el, ds.pnoInfo[1].az, ds.pnoInfo[1].roll );;


and


Quaternion mRotation = new Quaternion();
mRotation.fromAngles(ds.pnoInfo[1].el, ds.pnoInfo[1].az, ds.pnoInfo[1].roll );
rootNode.setLocalRotation(mRotation);



the 2nd version creates a new Quaternion while the first version used the already existing one.

Here is a modified TestRotateAboutPoint to show absolute and relative rotation


package jmetest.scene;

import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingSphere;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.scene.Node;
import com.jme.scene.shape.Sphere;

public class TestRotateAboutPoint extends SimpleGame {
  private Sphere s;
  private Sphere moon1;
  private Node pivotNode1;

  private float [] eulerAngles;
  private Quaternion rot = new Quaternion();
  private boolean absolute = true;
 
  public static void main(String[] args) {
    TestRotateAboutPoint app = new TestRotateAboutPoint();
    app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
    app.start();
  }

  protected void simpleUpdate() {
    if (absolute) {
        eulerAngles[1] += tpf*1;
        if (eulerAngles[1] > FastMath.PI) {
            eulerAngles[1] = -FastMath.PI;
        }
        // set new rotation values based on the three euler angles
        pivotNode1.getLocalRotation().fromAngles(eulerAngles);
    } else {
        // the following two lines add a small rotation to the existing
        rot.fromAngles(0, tpf*1, 0);
        pivotNode1.getLocalRotation().multLocal(rot);   
    }

    // print out euler angles
    float [] x = pivotNode1.getLocalRotation().toAngles(null);
    System.out.println("euler[0] " +x[0]);
    System.out.println("euler[1] " +x[1]);
    System.out.println("euler[0] " +x[2]);
  }

  protected void simpleInitGame() {
    display.setTitle("jME - Rotation About a Point");

    eulerAngles = new float [3];
    eulerAngles[0] = 0;
    eulerAngles[1] = 0;
    eulerAngles[2] = 0;
   
    //Planet
    s = new Sphere("Planet", 25, 25, 25);
    s.setModelBound(new BoundingSphere());
    s.updateModelBound();
    rootNode.attachChild(s);
   
    //Moon
    moon1 = new Sphere("Moon 1",25, 25, 10);
    moon1.setModelBound(new BoundingSphere());
    moon1.updateModelBound();
    moon1.setLocalTranslation(40, 0, 0);
    pivotNode1 = new Node("PivotNode 1");
    pivotNode1.attachChild(moon1);
   
    rootNode.attachChild(pivotNode1);
   
    cam.getLocation().z = 100;
  }
}

Sorry for the confusion.  I interpreted your question as asking how to accumulate the rotation one axis at a time.


I first do an rotation in Y Axis then in X Axis and finally in Z Axis... Anyway to do it?

I will make a brief explanation just in case someone will be in the same situation. What I finally do is a simple multiplication of the matrix, in the order I want, so this is de code:



y.fromAngleNormalAxis(getAngleY(), new Vector3f(0.0f , 1.0f , 0.0f));

x.fromAngleNormalAxis(getAngleX(), new Vector3f(1.0f , 0.0f , 0.0f));

z.fromAngleNormalAxis(getAngleZ(), new Vector3f(0.0f , 0.0f , 1.0f));

aux = y.mult(x);

aux = aux.mult(z);



where x , y , z and aux are the matrix and getAngleA returns the A angle of the sensor.



Thanks a lot for your attempts.