Me again, rotations in local space instead of global


This is my first attempt at using quaternions instead of matrix (and my first at this in JME using either). In GL or Java3D, for my space ship movement for players, I used to create a 4x4 matrix with the change in pitch, yaw and change in z axis (forward movement). I would then multiply it by the current transform of the object and then set the object transform to the result. This meant that in game, moving the mouse would always result in changes in the local coordinate space, so moveing the mouse side to side, would always give a change in the local yaw axis, even if you were upside down and back to front, or anywhere in between.

Trying to do this in JME results in transforms happening in global space, so if you pitch up 90 degrees, and then move the mouse side to side, you get roll instead of yaw. I'm including my code to see if anyone can spot the newbie mistake I am making.



            Quaternion deltaAngle = delta.getRotation();
            deltaAngle.fromAngles(yAngle*FastMath.DEG_TO_RAD, xAngle * FastMath.DEG_TO_RAD, 0);
            System.out.println("delta before combine: " + delta.getRotation() + ", " + delta.getTranslation());
            TransformQuaternion current = playerObject.getInterpolatedLocation(controller.getServerTime());
            System.out.println("current: " + current.getRotation() + ", " + current.getTranslation());
            System.out.println("delta after combine: " + delta.getRotation() + ", " + delta.getTranslation());   
            playerObject.setTargetLocation(delta, controller.getServerTime()+1000);

rot = targets.getLocalRotation();

rot.fromAngleAxis(angle, Vector3f.UNIT_Z);

Try this...I dont know if is this you want...


Nope, thats not it.

If I have a node that has a local rotation that is pitched up at 45 degress, and attached as a child I have another node. If I set the child node to contain the delta angles, then they are offset by the parent. I'm trying to achive this effect without lots of nodes as I am updating a data model, not the spatials in my scenegraph (they get updated in the render loop and are interpolated).

Using TransformQuaternion objects, I have one that contains the current local transform for the object, and I construct another that is the delta, which might be a pitch up of another 2 degrees, and a yaw of 5 degrees and maybe a translation in the z of 1 unit.

I'm currently using a combineWithParent as the javadoc says thats similar to node/spatial transforms, which is exactly what I'm after. Assuming the current pitch is 45 degree, no other rotations, and we are at 0,0,0, then the new pitch is correct, the yaw is around the world yaw axis, not the local one, and the z movement seems to work ok.

I'm guessing I'm just not understanding how TransformQuaternions work, and how to combine them to get the delta applied in local coord space instead of world coord space.



what does your setTargetLocation method do and your getInterpolatedLocation method do?


Thats all to do with smothly interpolating. I store a current known location, and a target location for each object with times against each. The idea is that when transmitted across the network, as long as I compensate for server time compared to client time (as in the clocks are set different) every client should see the same thing.

The target location (set with setTargetLocation) is just a TransformQuaternion and then using the current time, the last known posistions time, and the time on target, I can use the TransformQuaternion's interpolateTransforms method

public TransformQuaternion getInterpolatedLocation(long time) {
            if(timeOnTarget!=0) {
                    float ratio = (timeOnTarget - lastUpdateTime) / ((float)(time - lastUpdateTime));
                    interpolatedLocation.interpolateTransforms(lastKnownLocation, targetLocation, ratio);
                    return interpolatedLocation;
            } else {
                    return lastKnownLocation;

*just spotted that the ratio calc is the wrong way round, but that should just mean that the target location is returned each time*



Well, I don't want you to think I'm ignoring you, so I'm just going to admit that I'm dumb and not sure what the problem is and what needs to be done. In all honesty, Quaternions hurt my brain.


Does that mean you use TransformMatrix rather than TransformQuaternion's for calculating movements?


Actually, neither. I have never worked on a Space Flight/Sim type game that requires that sort of movement. My movement has been very simple direct manipulation of the local translation/rotation of a node (i.e. moving forward is getting the direction the node is facing and adding to translation, strafing similar and rotation is and angle/axis calculation). However, Shingoki has worked on aircarrier that has very impressive ship movement (irrisor has worked on similar stuff as well), so they can probably help you better, which I'll pay attention so I can educate myself as well.

I would checkout aircarrier from CVS and check out the code and run the examples.

I hope that will help.


Thanks for pointing me at that CVS repo. I checked out the code to see how they handle the updates and i've followed the patter they use. It's all sorted :slight_smile:

For anyone who is interested, my code is now as follows

         if(speed!=0 || xAngle!=0 || yAngle!=0) {
            TransformQuaternion current = playerObject.getInterpolatedLocation(controller.getServerTime());

            current.getRotation().getRotationColumn(0, tempVect);
            tempRotMatrix.fromAxisAngle(tempVect, yAngle*FastMath.DEG_TO_RAD);
            current.getRotation().getRotationColumn(1, tempVect);
            tempRotMatrix.fromAxisAngle(tempVect, xAngle*FastMath.DEG_TO_RAD);
            target.getRotation().getRotationColumn(2, tempVect);
            playerObject.setTargetLocation(target, controller.getServerTime()+1000);

Thanks for your help. I was getting most upset having spent 4 evenings trying to figure out how Quaternions work. I'll stick to comms code, that makes sence, i'm sure quaternions don't :)