Fixed point maths, quaternions, rounding errors and normalisation.
I’ve just updated the 3D game thing I’m writing to use quaternions to hold the orientation / attitude of the camera and the objects I’m rendering.
It all seems to work and was not difficult to code. I’m reasonably happy with it. But, I know there are rounding errors accumulating each time I pre-multiply the current quaternion with one that represents the change in orientation. All the literature says to expect this in the form of the quaternion drifting away from unit length, and to rectify it, once it has reached a certain point, by dividing the quaternion by its length, thus returning it to a unit length. I’m using fixed point maths for everything. Currently 16 bits, 2 before the point, 14 after. My rounding errors so far are small, but they do exist. They don’t become a problem in the small demo / play about code that I have at the moment, but I do suspect that they’ll cause issues over the time it takes to play the game for real. I have questions about the use of quaternions in this way.
|
Quote:
|
Quote:
|
I just wonder if ultimately this (quaternions) would be slower than standard 3x3 matrix math on Amiga?
Btw, I work in Unity on a daily basis, and most of the maths is "under the hood" so to speak... |
Quote:
|
Quote:
|
Quote:
And in any case I never used quaternions. But for the various matrix calculations I used 2:14 and the results always seemed good to me. If you want to continue using a bare 68k, 2:30 it's not an option, the internal ALU is 16-bit, so even a simple sum would require many more cycles. I am very curious to see your results with quaternions. |
Quote:
Maybe 2:30 can be an option if it's restricted to a tiny section of code where the performance isn't critical though? Maybe it's necessary for the normalisation step, which may turn out to be very infrequent. These are things I just don't know. I will try and upload an executable and log files later. |
In a Doom-type game you could just reset the vectors each time the player view more or less aligns with one of the base vectors. Who would notice, when turning around, that one turn had a slightly smaller or larger angle to make the camera vector hit a right angle?
|
Quote:
Quote:
Quote:
Quote:
If this makes you feel any better, mathieeedoubbas uses the same algorithm, for the IEEE mantissa of double precision numbers. |
Quote:
Look, once again, without knowing the precision you want to reach in the application (as in, "how precise do the vectors you attempt to rotate have to be over how many iterations"), nobody would be able to answer. |
Quote:
|
Quote:
Quote:
|
Quote:
Perhaps someone with experience could say, "well, game engine x renormalises its quaternions when they drift more than y% away from unit length". That would be a worthwhile contribution to the conversation. Or they could explain how to calculate the limitations of the particular fixed point size used in order to work out when it's not even worth trying to normalise. That would be helpful too. We could even discuss the cost of normalisation to try and work out how often we can afford to normalise. But to refuse to engage until your question is answered is unhelpful, particularly as it's a question that, a) can only be answered through experience, b) you have provided no help or guidance is how to answer, and c) may not even be relevant once the limitations of the fixed point maths are taken into account. |
Quote:
My main loop currently does this: Code:
for (;;) { Code:
a = (4000, 0000, 0000, 0000) [10000000] Code:
LONG QuaternionLengthSquared(const Quaternion * q) { Edit: Very slowly, 0x0FFF7544 = 0.999868, and if I run it for longer, I get 0x0FE88AC1 = 0.994273. |
Quote:
Code:
moveq #0,d1 ;but can be an useful value from a previous calc |
Quote:
The square root of the 4.28 number is the length of the quaternion (think vector) described by the 2.14 numbers. If there were no rounding errors then the 4.28 number would always be 1<<28, but because we're always moving the quaternion (by multiplying it with another one representing where the control stick is pointed), the rounding errors build up, leading to a quaternion that is slightly off unit length. I need to divide the four 2:14 numbers by the square root of the 4.28 number (or multiply by the inverse square root, but I don't think that's possible in fixed point). I need to work out, first, when is the division actually possible with the fixed point maths, and second, when do I want to do it? I see these two questions as interlinked, as the answer to the second may be forced by the first. |
Quote:
If you have a f-fractional bit matrix, then clearly, the resulting relative error of a multiplication with a 4x4 matrix can not be higher than 4*2^-f. If you have a screen resolution of W pixel, then you get a maxmal absolute error of W*4*2^-f. Approximately, after N iterations, you get an error of N*W*4*2^-f pixels. This is not really "high mathematics", just some basic estimates. Concerning quaternions: After thinking about it, I believe you must be using homogeneous coordinates. In such a case, the sign collected from the SU(2) rotations (instead of SO(3) = rotation matrices) does not matter. But without seeing your formulae, it is hard to tell. I'm also not clear why this should be better than the typical 4x4 matrices you use for coordinate computation in projective space (aka "homogeneous coordinates). |
Quote:
Quote:
Quote:
|
Just for understanding, when I use fixed point I do with 8:8. Which is for movement of BOBs or Sprites on a 2d screen.
How can you just use 2:14? I mean, two bits for the coordinates of the whole number seems a bit small, isn't it? How does this work? |
All times are GMT +2. The time now is 13:14. |
Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.