Quaternion Fun!
The question is not which one is cheaper, but whether the difference will be significant enough for you to notice and spend time wondering about. If not, then that's not the reason to pick one or the other. Consider how much work a modern computer can do, and how little work a quaternion slerp or matrix multiplication needs.
Slerp can be incremental as well and the best solution I know requires 4 multiplication and 4 addition (it is therefore a lot cheaper than a single matrix multiplication).
I will not derive this algorithm, but you can find it in
Barrera, Tony, et. al. "Incremental Spherical Linear interpolation", Proceedings of SIGRAD, vol. 13 2004.
Li, Xin. "To slerp or not to slerp?", Game Developer Magazine, August 2006, Volume 13, Number 7.
I discovered it in the second article, where other incremental versions are presented (pseudo-code listings from the article).
Let
α = angle between q_0 and q_1 as 4D vectors = cos^{-1}(dot(q_0, q_N))
β = incremental angle = α/N
A = 2cos(β)
p_0 = (q_n - cos(α)q_0)/sin(α)
q_1 = cos(β)q_0 + sin(β)p_0
then the k-th (k > 1) quaternion is
q_k = A q_{k-1} - q_{k-2}
Since A is a real number, you have only 4 multiplications and 4 subtraction (the other quantities are computed once).
I will not derive this algorithm, but you can find it in
Barrera, Tony, et. al. "Incremental Spherical Linear interpolation", Proceedings of SIGRAD, vol. 13 2004.
Li, Xin. "To slerp or not to slerp?", Game Developer Magazine, August 2006, Volume 13, Number 7.
I discovered it in the second article, where other incremental versions are presented (pseudo-code listings from the article).
Let
α = angle between q_0 and q_1 as 4D vectors = cos^{-1}(dot(q_0, q_N))
β = incremental angle = α/N
A = 2cos(β)
p_0 = (q_n - cos(α)q_0)/sin(α)
q_1 = cos(β)q_0 + sin(β)p_0
then the k-th (k > 1) quaternion is
q_k = A q_{k-1} - q_{k-2}
Since A is a real number, you have only 4 multiplications and 4 subtraction (the other quantities are computed once).
Interpolating between two matrix states is neither easy or efficient. But interpolating between two quaternions is both, so you should do that.
Given quaternions representing the initial and final orientations of the object, you interpolate (typically every timestep) with a factor between 0 and 1. For example, interpolating with 0.333... will produce a quaternion that rotates the object 1/3 of the way to it's desired orientation.
Your API probably provides the interpolation function for you. In directX, it's D3DXQuaternionSlerp.
For simplicity, start with an object whose world space transform is the identity matrix.
Now you create a quaternion that will rotate it into it's initial orientation. And a second quaternion representing it's final orientation.
Every timestep you determine what the factor is (between 0 and 1) and use D3DXQuaternionSlerp to get the quaternion representing the object's current orientation. Then you call D3DXMatrixRotationQuaternion to convert the current orientation to a matrix, which you can use as the object's world transformation.
Given quaternions representing the initial and final orientations of the object, you interpolate (typically every timestep) with a factor between 0 and 1. For example, interpolating with 0.333... will produce a quaternion that rotates the object 1/3 of the way to it's desired orientation.
Your API probably provides the interpolation function for you. In directX, it's D3DXQuaternionSlerp.
For simplicity, start with an object whose world space transform is the identity matrix.
Now you create a quaternion that will rotate it into it's initial orientation. And a second quaternion representing it's final orientation.
Every timestep you determine what the factor is (between 0 and 1) and use D3DXQuaternionSlerp to get the quaternion representing the object's current orientation. Then you call D3DXMatrixRotationQuaternion to convert the current orientation to a matrix, which you can use as the object's world transformation.
Once again thank you for all your interest and input. I tried implementing the quaternion iteration idea. I didnt get very far before i realised that there is a crucial bit of information that is important and so far makes it impractical to use quaternions, at least to my knowledge.
I am not just making one interpolation but two at the same time which results in the effect of one. I am interpolating the last set of frames worth of error as well as the next set of frames predicted rotation. This still results in an interpolation between where I am and where i want to be in the future, unfortunately it only works with matrices because I can combine the two rotations into one. I believe the quaternions give me two orientations instead of amount of rotation (maybe im wrong) and so cannot be then interpolated between or combined.
You may ask why I am doing this as the behaviour should be exactly the same as if i just interpolated between where am and where will be in future. The reason is that I need to be able to drop one orientation interpolation and just set the orientation to where it currently should be.
Sorry if that's confusing.
I am not just making one interpolation but two at the same time which results in the effect of one. I am interpolating the last set of frames worth of error as well as the next set of frames predicted rotation. This still results in an interpolation between where I am and where i want to be in the future, unfortunately it only works with matrices because I can combine the two rotations into one. I believe the quaternions give me two orientations instead of amount of rotation (maybe im wrong) and so cannot be then interpolated between or combined.
You may ask why I am doing this as the behaviour should be exactly the same as if i just interpolated between where am and where will be in future. The reason is that I need to be able to drop one orientation interpolation and just set the orientation to where it currently should be.
Sorry if that's confusing.
your explanation is definitely confusing but anyways,
if you have multiple rotations acting on an object, that should result in ONE quaternion. you should really only ever interpolate one quaternion pair (begin and end). just to be clear, a matrix has a rotation about X,Y, and Z axes, where a quaternion is the combined rotation about those axes. one matrix, 3 rotations => 1 quaternion, 1 rotation.
if you have multiple rotations acting on an object, that should result in ONE quaternion. you should really only ever interpolate one quaternion pair (begin and end). just to be clear, a matrix has a rotation about X,Y, and Z axes, where a quaternion is the combined rotation about those axes. one matrix, 3 rotations => 1 quaternion, 1 rotation.
Quote:Yes thx for that. I didn't deliberately 'ditch' it. I posted the question, left the forum, and I'd forgotten to put up 'email when someone responds' and then couldnt find it again. Since i had run a search and nothing came up, i had assumed my browser hadn't posted before i had closed the tab window. Many apologies. Dont know why i posted in the DirectX section.Ok, sorry about that - I was just puzzled :) For future reference though, you can find your older threads by going to your profile and looking at the 'previous threads started' section.
Quote:Original post by stu2000
Once again thank you for all your interest and input. I tried implementing the quaternion iteration idea. I didnt get very far before i realised that there is a crucial bit of information that is important and so far makes it impractical to use quaternions, at least to my knowledge.
I am not just making one interpolation but two at the same time which results in the effect of one. I am interpolating the last set of frames worth of error as well as the next set of frames predicted rotation. This still results in an interpolation between where I am and where i want to be in the future, unfortunately it only works with matrices because I can combine the two rotations into one. I believe the quaternions give me two orientations instead of amount of rotation (maybe im wrong) and so cannot be then interpolated between or combined.
You may ask why I am doing this as the behaviour should be exactly the same as if i just interpolated between where am and where will be in future. The reason is that I need to be able to drop one orientation interpolation and just set the orientation to where it currently should be.
Sorry if that's confusing.
I decided to try and expand this with some simple diagrams:
The current states in an EXTREME case of bad error.
What I do with matrices
What happens with quaternions, unless someone can improve.
I realise that for quaternions, i could just have a bool that switches to false IF i snap the orientation to where currently should be, which when true, interpolate between where should-currently-be and where should-be-in-future and whenever false, just interpolate between where-currently-am and where should-be-in-future. However this would also result in needing to keep track of T for the slerp, performing the full slerp instead of faster iteration version someone provided earlier. (because can happen at any time point and wont have previous quaternion to carry on from).
With matrices I just set the rotation offset representing the error interpolation to an identity matrix at the point of snapping the orientation and it just carries on correctly. The other rotation offset matrix that interpolates between where should be and where should be in future remains the same.
Hope that's clearer.
--------------
In terms of speed implementing that IF switch and performing one full slerp is probably faster than performing the two rotation matrix accumulations (18 mults) every frame. Now just gotta find out which of the two methods supervisor wants based on how easy they will be for others to understand, and neatness of code.
Sorry, but I do not understand your problem. To combine two rotations with quaternions you simply have to multiply the two quaternions representing the rotations together in the correct order. What are you exactly trying to do?
ok so if i do perform two slerp iterations for the two offsets with quaternions as shown in the diagram below, they should combine like this? The dashed line represents the previous orientation and the solid one represents the new orientation by adding the offset. Both are in world space.
If so then that's all i need. I just thought you couldn't multiply them together to combine rotations like with matrices, the main reason being the matrices in this case are rotations to be combined with the current orientation, and are not a rotation representing the actual orientation. Im pretty sure doing a slerp will get me a quaternion representing the orientation from 0 when what i need is a rotation from the current position which i can constantly combine each frame. Does that make sense?
--------------
Imagine youve got a clock. You know its second hand turns 1/360 degrees every second clockwise. Thats the offset1. Every frame you apply that offset to the orientation to get the new orientation. You dont need to know the orientation at any time to have a fully working clock. Now say that that clock was ahead by 10 seconds and you want to correct that over 10 seconds. You calculate a second offset that makes it turn counter-clockwise by 1/360th of a degree every second. The result is that the clock does not change for those 10 seconds. If you forget to take away that second offset it will be wrong again and you will have to re-calculate and apply the second offset again. Im pretty sure with slerp, what i will get is an orientation i desire at any point in time given t, when really what i want is to find out the quaternion to apply an offset each frame. But I really want to apply two quaternion offsets, one for the error, and one for the normal change of rotation in time.
The trick is calculating a quaternion offset from two quaternion orientations and you want that offset to be applied N times to get from one to the other quaternion. Now do that twice to get the error and the normal movement so that you can apply both to the current orientation every time frame.
--
this thread looks similar http://www.blitzmax.com/Community/posts.php?topic=51812
Quaternions P, Q.
inverse of P (P') when combined with Q gets you from P to Q. ie P'Q is the total offset looking for.
Now can i somehow divide that offset into little chunks so that i dont go from P to Q in one go but in N timesteps like i have done with matrices by getting to the angle and dividing that by N before deriving the matrix.
[Edited by - stu2000 on September 28, 2010 4:25:39 AM]
If so then that's all i need. I just thought you couldn't multiply them together to combine rotations like with matrices, the main reason being the matrices in this case are rotations to be combined with the current orientation, and are not a rotation representing the actual orientation. Im pretty sure doing a slerp will get me a quaternion representing the orientation from 0 when what i need is a rotation from the current position which i can constantly combine each frame. Does that make sense?
--------------
Imagine youve got a clock. You know its second hand turns 1/360 degrees every second clockwise. Thats the offset1. Every frame you apply that offset to the orientation to get the new orientation. You dont need to know the orientation at any time to have a fully working clock. Now say that that clock was ahead by 10 seconds and you want to correct that over 10 seconds. You calculate a second offset that makes it turn counter-clockwise by 1/360th of a degree every second. The result is that the clock does not change for those 10 seconds. If you forget to take away that second offset it will be wrong again and you will have to re-calculate and apply the second offset again. Im pretty sure with slerp, what i will get is an orientation i desire at any point in time given t, when really what i want is to find out the quaternion to apply an offset each frame. But I really want to apply two quaternion offsets, one for the error, and one for the normal change of rotation in time.
The trick is calculating a quaternion offset from two quaternion orientations and you want that offset to be applied N times to get from one to the other quaternion. Now do that twice to get the error and the normal movement so that you can apply both to the current orientation every time frame.
--
this thread looks similar http://www.blitzmax.com/Community/posts.php?topic=51812
Quaternions P, Q.
inverse of P (P') when combined with Q gets you from P to Q. ie P'Q is the total offset looking for.
Now can i somehow divide that offset into little chunks so that i dont go from P to Q in one go but in N timesteps like i have done with matrices by getting to the angle and dividing that by N before deriving the matrix.
[Edited by - stu2000 on September 28, 2010 4:25:39 AM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement