# Absolute rotation

sigh
I really don’t get quaternions. No matter how many times I go over Math for dummies, I still don’t get them.
What I am trying to achieve is rotation around world’s y axis when mouse moves horizontally and world’s x axis when mouse moves vertically.
I tried multiple things, but still no luck, just relative rotation. The code for mouse handling is not the problem, because well… I know how to do that part
My code so far:

``````    @Override
public void onAnalog(String name, float value, float tpf) {
value *= k;
if (enabled){
if (name.equals("rotX")){
yRot += value;
}else if (name.equals("rotY")){
xRot -= value;
}else if (name.equals("rotY1")){
xRot += value;
}else if (name.equals("rotX1")){
yRot -= value;
}
Quaternion rot = q.fromAngles(xRot, yRot, 0);
shipPivotNode.setLocalRotation(rot);
actualShip.setLocalRotation(rot);
}
}
``````

EDIT: With this code rotation around absolute Y axis works ok, but X rotation is relative.
Any help is welcome. Actual code is welcome, but a good explanation would be even better.

The Scenegraph is there to hide Quaternions from you.

If I got you right your Rotational Pivot Point is wrong? Then try to add an intermediary node whose local translation is the inverse of the parent node’s world translation, so your own world translation becomes Vector3f.ZERO (No clue if there isn’t even a setWorldTranslation).

Then you simply rotate that intermediary node. Most of the Time you already have such a (0, 0, 0) node, e.g. for your zone

What you want to achieve sounds like a rather easy task though, so what’s wrong with `Quaternion.angleAxis(Vector3f.UNIT_X, FastMath.PI);` ?

Edit: Try the Quaternion where you can specify a vector and use the Unit Vectors.
Then multiply the two single quaternions, that is even better than fromAngles because you know the order (which makes a difference)

And then what to do with it? The shipPivotNode is a child of rootNode, so there shouldn’t be any diffrence…

Can I just check: you want to rotate something around Y when you move the mouse horizontally, and around X when you move it vertically. You have the mouse input fine and you’ve got it changing your xRot and yRot values as it’s supposed to.

The thing you are rotating is actualShip, but is that attached to shipPivotNode? Am I right in assuming this node is used so that the actualShip can be rotated around a point (the pivotNode) instead of rotating the actualShip around its own origin (so probs its center)?

My pivot node’s at 0,0,0.[quote=“Darkchaos, post:3, topic:36593”]
because you know the order (which makes a difference)
[/quote]

That’s the exact problem. I don’t want the second rotation to be relative to first, but absolute.

No. There are 2 ships. One is attached to `shipPivotNode` and the other is `actualShip`. One attached to pivot is batched and displayed and the second one is offscreen and used for raycasting and stuff. That’s because android’s performance is not very good without batching.

You can’t. Rotational Orders matter.
Imagine a cat. The cat is now rotated around her view axis. This means her feet are pointing into the sky. Now you make her rotate around 90 degrees so her head is looking at the sky.

Now exchange the order: 90 deg → cat is looking down. Now flip the cat around her axis → Cat is still looking down.

Yeah, okay. Is there a way to calculate the relative rotation required to get the effect of absolute rotation?

Still no solutions?
Basically what I am trying to do is like a trackball. You swipe left, the model rotates left. Whatever it’s current rotation is…

I can’t understand why rotX-> yRot+=value and rotY-> xRot-=value,and so on.

Check how rotations are being added/subtracted because an absolute Y and a relative X moving is pretty strange.

Oh, that’s because mouse x axis should rotate spatial around y axis and the other way.

fromAngles() will give you ‘absolute’ quake style rotation where you rotate around the y-axis first (always UNIT_Y) and then the x axis based on that.

But for some reason, you want to rotate around x separately. Like if you looked 90 degrees left and then rotate 45 degrees around X then you’d be tipping your head sideways? Or?

If that’s what you want then you will have to calculate the two rotations separately and then do a change of basis on whatever one you want to rotate second. (change of basis = multiply by the inverse… ie: you want what that world rotation will be in the new local rotated space).

But it would help us a lot if you could describe the effect you want using an actual example.

Today I tried doing multiplication by the inverse but it didn’t work out very good. It was doing some completely random rotation.
What I am trying to achieve is basically a ChaseCamera but instead of moving the camera, I want to rotate the target.

But a chase camera would have a rotation around x that is relative to the rotation around y.

So I mean describe what you want to happen like “If I rotate my head X degrees to the right (around y) then rotate it X degrees around X then I want my head to be oriented like…”

Because from your current description, I can’t make that be a chase camera as usually chase cameras have consistent orientation.

Let me try to explain it another way. Idk if my english is good enough though.
Imagine that the object I am trying to rotate is a sphere. A trackball in fact. Then when you swipe the screen up the trackball rotates up on axis relative to camera. Same for horizontal rotation. And since my camera is aligned to the world’s coordinate system, the rotation of the trackball should be around absolute x and y axes.
Does this make any sense?

So you are rotating the object and not the camera? That clarifies things a lot.

In that case, ALL of your rotations will need to be relative and not stacked like you are doing.

I’ll do it for one but you’ll need to do it for both x and y separately…
Quaternion xDeltaRot = new Quaternion().fromAngles(xDelta, 0, 0);

Quaternion currentRot = ship.getWorldRotation();

// Convert the world delta rotation into local delta rotation
Quaternion xLocalRot = currentRot.inverse().mult(xDeltaRot);
currentRot = currentRot.mult(xLocalRot);

…repeat for y.

2 Likes