[SOLVED] Realistic-looking airplane rotation

Hi,

I am attempting to implement plane rotation a bit like the game AirRivals, where moving the cursor upwards causes the plane to pitch upwards, with a fixed camera angle behind the plane.

To rotate the plane on the yaw axis, I used this code:

    float x = (Display.getWidth() / 2) - Mouse.getX();
    x/=500;
    Vector3f cAng = new Vector3f(0, x, 0);
    clamp(cAng); //Clamp between value of 0 and 1
    player.setAngularVelocity(cAng);

This works successfully, but when I try and add pitch to this, it completely breaks down.

float y = (Display.getHeight() / 2) - Mouse.getY();
    float x = (Display.getWidth() / 2) - Mouse.getX();
    y/=500;
    x/=500;
    Vector3f cAng = new Vector3f(y, x, 0);
    clamp(cAng);
    player.setAngularVelocity(cAng);

The issue here, as you can see in the GIF, is that when I pitch the plane up or down, the plane also starts to roll.

The plane pitch acts correctly (nose up or down as expected on a real plane) if I do NOT ever change the yaw. If I bash into the ground and get the yaw changed, the plane starts rolling around again.
The plane yaw always seems to work correctly, and always appears to turn it in the direction of the wingtips no matter the pitch/roll of the plane.

Basically, long story short - Changing the pitch works, changing the yaw works, but they do not seem to work together.

What can I do to solve this issue?

But this is as intended - think about it: Do 3 steps using your hand - 1st do a pitch and a yaw, 2nd do a pitch and a yaw, 3rd do a pitch and a yaw => result: z axis rotates too (after the 3rd step, the air plane is now rolled to the side - like in your .gif animation.

So, there is no real solution since there is no real problem. :chimpanzee_closedlaugh:

And some background info:
Typically, in physics engines, the “angular velocity” is both an axis and a magnitude. The axis is the normalized version of the vector and the magnitude is length of the vector.

Yes, but when I move my cursor upwards, I just want the planes’ pitch to change - Not the roll. How can I achieve that?

If it’s using physics then you need to apply forces instead of setting the rotational velocity directly.

Else you will have to do a bunch of math to figure out how to accumulate relative angular velocity changes. The physics engine should already be doing this for applied rotational impulses somehow.

Ah, that’s the problem.
Well, it’s quite simple: You must do your calculations in “air plane space”.
For that, you get the local rotation and local translation (or “transform” - contains both).
Then you multiply your desired cAngPlane with it and use the resulting cAngWorld.

For what pspeed said: You don’t need ‘dynamic physics’ (forces, impulses) to “emulate” air plane movements. But if you want to “simulate” air plane movements, you will need to use dynamic physics and some complex ‘aerodynamics’ calculations.

…implies he is already using physics as angular velocity is a pretty specific thing.

If this were quaternions then it would be easy. The math to calculate a new angular velocity from a local-space angular acceleration is a bit non-trivial and is already being done by the physics engine anyway.

Edit: also, OP’s code is effectively trying to manually apply local acceleration to the angular velocity. Why not just apply acceleration to the physics object directly instead of doing it by hand?

I know what he does.
Uses ‘kinematic’ physics instead of writing custom code to handle forward moves and rotations.
The physics when (mis)used this way is what’s called “arcade” instead of “realistic” physics (in this case highly arcade, and not really a physics simulation anymore).

The code is weird and broken - agree to that.
To fix it, just rotate the cAng by the spatials orientation - that’s what I proposed.
If it is an elegant idea to write code like that is not what I’m to judge.

@joehot200 try something like this:

Vector3f cAng;
Spatial airplane;
airplane.getLocalRotation().mult(cAng);

You might need to experiment a little with these things.

cAng is three values. “rotation about x axis” “rotation about y axis” “rotation about z axis”. I’m pretty sure treating it like a position is going to cause issues. (Even clamping is going to cause issues, frankly.)

For arcade “physics”, it’s best to abandon bullet’s notion of velocity and just set the direction of the plane directly from quaternions. Then local rotation becomes multiplying quaternions together.

I’m pretty sure that rotating the vector (like if you rotate an axis) will lead to the desired result.
Usually the angular velocity in game engines is an axis of rotation multiplied by a scalar magnitude.
If @joehot200 would test it, we could see if I’m right.
If I’m not right, then a different solution is needed (e.g. convert to a quaternion and then mult quaternions).

For the second part you are right - there are other ways to achieve arcade airplanes.

The angular velocity that you describe cannot be represented by just one vec3. For a physics engine, angular velocity is almost always three values… rotation about each axis. It is the scalar about each axis and those cannot just be ‘rotated’ with a quaternion… it wouldn’t make sense.

In the book “Game Physics Engine Development” the author describes that any angular velocity can be represented by a quaternion (which is essentially three Euler angles encoded in a special way). The author further describes that the rotation is like I described it.

But all that is meaningless, if trying the piece of code works. Working things prove things to be correct (at least that’s how engineers see it - don’t ask mathmaticians). :chimpanzee_closedlaugh:

This is what I initially tried doing, but the same problem occurs. I was originally applying torque to the plane, but this didn’t work either.

I’m really sorry, but could you explain a bit more about how I would implement this in my code? Multiplying the rotation by the vector I want to change it by seems a bit odd, and I can’t work out how this would work or what I would do in my code to try and implement it.

I’m not completely sure what you mean by this. It is easy enough to represent an objects’ rotation or angular velocity with vectors, and this indeed is what I did when I programmed with java and LWJGL.

I would prefer not to be forced into directly setting the planes’ rotation, but rather apply velocities to it. This would give a more realistic feel when plane collisions occur. Is there no other option other than just directly setting the planes’ rotation?

By the way, I’m a bit of a Quaternion noob. I’ve read up jMonkey’s wiki page about Quaternions, but no concrete information about what exactly they represent and how to modify them to correctly represent rotations.

Hm, I see… this would be a lot of work. I would need to explain a lot.
I do only have little time (my project is now overdue one day and I would like to participate in the contest that ends Wednesday too…)
So, all I have for now, is this sad monkey: :chimpanzee_sad:

He is patently wrong. Unless he’s just using it to store the values but then it’s a vec4 and not really a quaternion anymore.

Also 100% incorrect… except in that they both represent rotations. Otherwise they are as different as is possible to be and still represent something similar.

Angular velocity has to be euler angles because you might have velocity greater than PI. A quaternion only represents rotation as it’s been normalized.

Any number of euler angle combinations can end up representing the same quaternion. But a given quaternion can only be converted to exactly one set of euler angles. This euler → quaternion information loss is why a quaternion can’t be used to represent angular velocity. Anything over 90 degrees per second would be lost or converted to some other rotation.

You have to transform the local space torque into world space torque. I didn’t this code so I can’t comment on it.

Ah, yes, got tricked again.
It’s not quaternion, but non-normalized quaternion-like thing.
Doesn’t matter anymore - I’m out (no time).

I’m still unable to solve the problem with my fairly limited mathematical understanding of quaternions and other physics stuff, so I’m currently just going to set the planes’ rotation to that of the camera and go onto other things. I guess I’ll just have to shove this problem down the line and leave it for another time.

Hey hold on for a second, I might have the thing you’re looking for (check at 0:51 or 1:41 for example):

I was sort of reuctant to suggest it before since the system sets rotations directly, but it should work with forces too, as long as you provide high damping. I think this is the code:

//wid,hei = current resolution height, width				
float verti = -(getInputManager().getCursorPosition().y-15 - hei/2)*1080/hei; 
float horiz = -(getInputManager().getCursorPosition().x+16 - wid/2)*1920/wid;
			
Vector3f axis = new Vector3f(verti/400,horiz/600,rollspeed);
axis = airplane.getLocalRotation().mult(axis); //what you were missing
control.setAngularVelocity(axis);

I think you, ironically, forgot to take the plane’s rotation into account.

That’s what I was trying to tell - even posted some similar code.
Maybe he tries it now… :chimpanzee_closedlaugh:

1 Like

Sorry, I didn’t read the entire thread through. You said it. :smile:

Hey, huge thanks for the code. It is much better than what I was using.

Rolling is still a possibility though. Take a look at this, for example:

There is a simple way to counter this - To apply the rolling velocity to be the opposite of the planes’ current rotation.

How can I get the planes’ current roll angle, preferably in degrees?