air-plane: Y-axis rotation, effected by translation

So my flight sim is doing well… -At least while flying in the North-East corner of the world-map…

But the further I get from map-coords (0,0) , the choppier the Y-rotation gets (I think its called YAW)… Progressively getting worse as distance to (0,0) increases…

Change_Roll is perfect… Change_Pitch is perfect… The problem is only with Change_yaw, though their codes are ALMOST the same

Here is the code:

 position = orientation.Translation;
 orientation *= Matrix.CreateFromAxisAngle(Vector3.Normalize(orientation.Up), changeAmount.Y);                                                     orientation.Translation = position;

If I execute this code with orientation.translation = Vector3.Zero it works smoothly…
But as soon as I set translation back to original map position(if the coordinate values are high enough), its choppy…

-Any Ideas on how translation effects rotation? -And why this should only be true for yaw?

You must keep separate fields for Vector3 Position, Matrix orientation and combine them into a new Matrix worldTranslation on each update.

The quick&dirty fix here would be to zero orientation.Translation before mul with rotation.

Thanks, I like the fact that I made myself understandable, but isnt that what i did with this code:

position = orientation.Translation;
(also tried this here:) orientation.Translation = Vector3.Zero;
orientation *= Matrix.CreateFromAxisAngle(Vector3.Normalize(orientation.Up), changeAmount.Y);
orientation.Translation = position?

No it’s not. You are constantly adding a small amount of rotation each frame to the same matrix. Over time, this will result in accumulation of floating point error. Rotation and scale occupy the same components of the matrix, so the accumulated floating point error usually shows up as the model getting smaller until it eventually disappears.

I would suggest storing position and rotation separately and creating the matrix from scratch each frame.

Vector3 position;
Vector3 rotation;

Each frame, update the position and rotation, then create the transform matrix.

rotation.Y += changeAmount.Y;
Matrix.CreateFromYawPitchRoll(rotation.Y, rotation.X, rotation.Z, out orientation);
orientation.Translation = position;

Ok! Thanks!

  • I’m still a bit unsure as to whats going on, since my problem manifests as a choppy y-rotation motion, not scaling issues, and the severity diminishes when I fly back towards map_pos(0,0)…
    You would think a floating point error would carry on despite translation changes, no? -Unless ofcoarse running reverse eventually decreases the float size to something tolerable…

I think I see where this is going: I will follow your directions, and post an update with the results…

There is also the case where the further you go from the origin (0, 0, 0) along any or all axes, floating point precision becomes less. That might be a factor as well.

About those floats: my position floats dont go higher than 30-or-50-some-thousand, and still I get choppy yaw-changes… Thats within float limits if I remember correctly ?

I tried to use CreateFromYawPitchRoll, but it seems to apply rotation to my model according to the ground or world, ie pitch moves the nose in an up-down direction regardless of roll… Just like Matrix.CreateRotation… Which is why I was using Matrix.CreateFromAxisAngle…

-The plane should ofcoarse pitch around the wing-axis, ie in a direction depending on roll-amount…

So, for now: Both you guys gave different answers…
2* matrices and a vector3,
2 * vector3 and a matrix…

Will either work?

Well, another solution would be to use a Vector3 for position and a Quaternion for rotation.
On each frame rotate the quaternion, Normalize it and get a rotation Matrix.
Update the Position by adding velocityellapsedTimerotationMtx.Forward.

Then create a worldTransform matrix by combining rotation & position.

Thanks nkast, now I have enough material to be confused for hours on end… Great excersize, this pacing around my house, tapping on my head, and the cats are amused, a win win :slight_smile:

Ok, so thats 3 suggestions on something of which I know very little…

Just for safety: Are these proposed solutions inter-changable for a completely basic 3d-flyer or would you nudge me toward a specific one?

Why would I use a rotated normalized quaternion to get a rotation matrix, instead of just using a rotation matrix from the start?

As KonajuGames pointed out, my original suggestion to have a Rotation Matrix was flowed because it will accumulate rounding errors. Don’t use that.

The other two are more or less inter-changable. It’s best to use KonajuGames because Quaternions are a bit hard to ge your mind around the first time.

Of course you can still use CreateFromAxisAngle() instead of CreateFromYawPitchRoll(). I’m just in the habit of using CreateFromYawPitchRoll for the stuff I have done.

We’re really taking guesses because we can’t see any more of your code. Are you sure that the changeAmount.Y value is sensible at the time the problem is visible? If it is larger than expected, then it will be seen as choppy rotation. Check all of your inputs so you are sure you’re not seeing a case of “garbage in, garbage out”.

awesome. I have been checking out those Quaternions… I had to practice just to pronounce it…!
With a mere C-level math background, I felt smart just looking at that stuff…
-Though I got the impression its possible to use them without being intimimately familier with them, it suits me just fine to tackle this one later :slight_smile:

Yeah I see your point… I think its easier for me to summerize my code in human terms:
Its completely simple… It contains nothing but a few of the most basic classes (airplane, world, map_tile) with very basic constructors.
-The only update/draw code I use are the absolute minimum variable updates to achieve a first-person flight over terrain effect, and I am constantly changing these around to try and make it work, so its not exactly written in stone.

So thanks for now guys, I feel privileged getting such constructive feed-back!
I will look at everything you mentioned, and then some (if needed)…
-I will mark this thread [SOLVED] if and when I succeed…

The symptoms you describe definitely sound like the effects of floating point error. I normally try to keep everything within the +/- 10,000 range. You could scale your world and models down by a factor of 10 or 100 if you really have to.

That said, how far do you get from zero before this choppiness manifests?

Going back to your original code, you could try zeroing out the translation before applying the rotation. Without doing that, you are rotating an already offset world transform, which is probably wrong:

position = orientation.Translation;
orientation.Translation = Vector3.Zero; // NEW LINE
orientation *= Matrix.CreateFromAxisAngle(Vector3.Normalize(orientation.Up), changeAmount.Y); 
orientation.Translation = position;

about mid-way 15-30,000, so what you confirmed about float values indeed seems solid. I thought for sure they could go higher… like millions at least…
I have thought of 2 work-arounds…
Either index my world into smaller sections, not exceeding say 10,000 in width.
Or translate my whole map so that 0,0 represents the center…
-For scalability I should probably go with the first…

I’ve already tried zeroing my translation before rotation and it works at 0,0 -but when I reapply the real position, its choppy again…

I’d say do option 2 at the very least. Otherwise you’re missing out on three quarters of the optimum floating point precision area (in X,Z space).

Regarding option 1, it sounds like potentially a can of worms and I’d avoid it unless you need a really really massive world. A better option is probably to scale everything down by a factor of 100. Your model drawing (position and scale) can just be multiplied by 0.01 as can your velocities and acceleration constants.

Awesome thoughts! Shrink the whole world, including the observer… Sounds so simple it just might work!

I actually returned to a 2d project for the time being, but when the time comes (next project), I feel like your answer will nudge me further along… Thank you :slight_smile:

1 Like