• Advertisement
Sign in to follow this  

Applying Player Movement to Velocity Vectors

This topic is 1647 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

In my initial code I had player movement applied directly as offsets to the position and orientation data.

 

My idea was to try and change that, so that player movement and rotation was instead applied once to the player's velocity or angular velocity vectors.

 

With simple translation this is easy. However, when the player rotates, the translation vector needs to change direction. This means subtracting the old vector and adding the new one. To complicate things further, the same is true of the 'up' vector if the player is pitching downwards.

 

So before each physics update the old vectors are subtracted, a new orientation matrix is calculated for the next frame, and the velocity vectors are re-applied in the proper directions.

 

This worked for either translation or rotation alone, but when moving and rotating simultaneously I ended up with residual velocity (around 0.02-0.07 units/sec, compared to a movement speed of around 1.6-8.0 units/sec). It's small enough that it seems like it could possibly be a rounding error but also not so small that there could be some small error in my algorithm, or else the method described above is just not possible.

 

I wanted just one set of velocity and angular velocity vectors, so that during the physics update step all collision could be handled in one step. Otherwise I will have to make a second collision step if I simulate player movement separately. This seems undesirable since my player is just an instance of a mobile game entity which I will be adding later, so all these objects would add more overhead to the movement step.

 

Suggestions?

 

Share this post


Link to post
Share on other sites
Advertisement

This sounds like a 3D scenario yes?  The answer is not simple in that case.  You are going about this correctly for position...rotation is another story.

 

Angular velocity is generally represented with a vector called omega.  The direction of omega represents the axis of rotation and the magnitude represents the velocity of the rotation.  You can think of omega as the time derivative of your rotation matrix R; however unlike position you can't simply multiply omega by your time step and add it to R.  It's a bit trickier than that but it's not terrible.  The formula for what you want to do is here:

 

http://www.google.com/url?sa=t&rct=j&q=&esrc=s&frm=1&source=web&cd=1&ved=0CC0QFjAA&url=http%3A%2F%2Fwww.cs.cmu.edu%2F~baraff%2Fsigcourse%2Fnotesd1.pdf&ei=YgsHUvzCBOWh2gW13oHIAw&usg=AFQjCNHGXY6ZN2RYXF7f28loeidm1rOxZQ&sig2=8P7y8zCkm6aBEgpeuIS0vw&bvm=bv.50500085,d.aWc

 

at the bottom of page 8.  This approach is going to lead you to another problem...how do you change omega to get rotations that correspond to the player's input?  This requires applying forces, computing the torque, and then integrating the torque with the help of an inertia tensor to compute omega.  Again, not hard but all the texts that explain how to do this require some familiarity with calculus and some patience.

Edited by nonoptimalrobot

Share this post


Link to post
Share on other sites
[quote name='nonoptimalrobotND' timestamp='1376194105' post='5084849']
however unlike position you can't simply multiply omega by your time step and add it to R[size=NaN][background=#d6e3fe ! important]F[/background]

I do use the rotation function from the glm library:
 
//apply angular velocity to orientation
const float langle = glm::length( lrmotion.mAngularVel );

if( langle != 0.f )
{
    lrorient.mOrient = glm::mat3( glm::rotate(
        glm::mat4(
            glm::vec4( lrorient.mOrient[0], 0.f ),
            glm::vec4( lrorient.mOrient[1], 0.f ),
            glm::vec4( lrorient.mOrient[2], 0.f ),
            glm::vec4( 0.f, 0.f, 0.f, 1.f ) ),
        langle,
        lrmotion.mAngularVel ) );
}
Edited by PrestoChung

Share this post


Link to post
Share on other sites

I see, I misunderstood your question.  While the method you are using to apply an angular velocity to your rotation isn't exactly "normal" it does get the job done.  It doesn't extend well to doing things the "real" way with a physically derived angular velocity but you don't seem to be considered about that.

 

The 1st, 2nd and 3rd row of your orientation matrix are actually the local x, y and z axis of the player's local coordinate system specified in world space.

mtxRotation = | ux vx nz |
              | uy vy ny |
              | uz vz nz |

x-axis = [ux, ux, uz]
y-axis = [vx, vy, vz]
z-axis = [nx, ny, nz]

To adjust the players translation in a consistent way regardless of the current orientation:

vPosition += [ux, uy, uz] * vVelocity.x * fDeltaTime
vPosition += [vx, vy, vz] * vVelocity.y * fDeltaTime
vPosition += [nx, ny, nz] * vVelocity.z * fDeltaTime

Note that this is the same as:

vPosition += mtxRotation * vVelocity * fDeltaTime

In this scenario your velocity is always defined local to the players orientation.  The x-component always corresponds to left-to-right motion, the y-component always corresponds to vertical motion and the z-component always corresponds to forward-to-back motion.

Edited by nonoptimalrobot

Share this post


Link to post
Share on other sites

My problem seems to be with rotation (adding vectors).

I found the proper formula here for axis-angle representation:

http://www.physicsforums.com/showthread.php?t=542904

It uses sin and cos functions which I think are computationally expensive? Are there version of these functions that use dot and cross products instead?

 

Are you talking about the formulas for composition of rotations? If you express rotations by quaternions or matrices, all you need to do is multiply them.

 

Also, how many times per frame do you expect to call these trigonometric functions? Even if it's in the hundreds you probably shouldn't worry about it from the point of view of performance.

Share this post


Link to post
Share on other sites
As many times as possible. I see I can convert to a quaternion representation but that will also involve sin and cos functions. It might be unavoidable, I just haven't used any trig functions directly in my code, probably because I mostly rely on the glm library and actually it looks like it has quaternion facilities available so I should probably just revert to that approach.

Share this post


Link to post
Share on other sites
Question about composing/decomposing rotations.

If you have two rotations Q1 and Q2, then the result of rotating first by Q1 then Q1 is Q':

Q' = Q2Q1
If you have Q' how do you get back to Q1? Is it rotating by Q' then rotating by the inverse of Q2?

Q1 = inverse(Q2)Q'
Similarly, could you start with Q' and remove the Q1 rotation, leaving the Q2 rotation? I'm trying to find a clear set of operations and identities that I can use algebraically for rotations.

Share this post


Link to post
Share on other sites

You can pre- and post-multiply by matrices on both sides without changing the validity of a matrix equation.

 

So to obtain Q2 from

 

Q' = Q2Q1

 

you would post-multiply by inverse(Q1) on both sides

 

Q' * Q1-1 = Q2 * Q1 * Q1-1

 

Q' * Q1-1 = Q2 * I = Q2

 

EDIT: So Q2 = Q' * inverse(Q1)

 

You can do the 2 multiplies on the right hand side in any order (without changing which matrices are on the left or right) since matrix multiplication is associative:

 

A * B * C = (A * B) * C = A * (B * C)

 

but not commutative (i.e. AB != BA in general).

 

EDIT2: Similarly for quaternions, you can pre- and post-multiply equations by a quaternion, and they are associative but not commutative.

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites

If you are trying to find identities and operations for rotations/matrices in general then the following may be of use as well

 

(AB)-1= B-1A-1

 

If a matrix is orthonormal (all rows are perpendicular [orthogonal] to each other and normalised, as are the columns)

 

AT = A-1

 

where AT = transpose of A. 3x3 Rotation matrices are always orthonormal (as are 4x4 rotation matrices with no translation component).

 

Regardless of whether matrices are orthonormal (i.e. this is always true)

 

(AB)T = BTAT

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites

Similarly to how the inverse of an orthonormal matrix is its transpose, the inverse of a unit quaternion is its conjugate. So you never actually need to compute inverses when handling rotations.

Edited by Álvaro

Share this post


Link to post
Share on other sites

You can pre- and post-multiply by matrices on both sides without changing the validity of a matrix equation.

 
Does pre-multiplication by the Identity matrix also leave the right hand side unchanged? Solving for Q1:

Q2-1 Q' = Q2-1 Q2 Q1
Q2-1 Q' = I Q1
Q2-1 Q' = Q1

Similarly to how the inverse of an orthonormal matrix is its transpose, the inverse of a unit quaternion is its conjugate. So you never actually need to compute inverses when handling rotations.


Does a unit quaternion imply a fixed angle of rotation (1 radian or something?). Would that mean an extra value needed to represent angle of rotation?

Share this post


Link to post
Share on other sites

Does pre-multiplication by the Identity matrix also leave the right hand side unchanged?

That's what "identity" means.

 

 

 


Does a unit quaternion imply a fixed angle of rotation (1 radian or something?). Would that mean an extra value needed to represent angle of rotation?

No, all rotations are represented by unit quaternions.

 

You should try to get some general education about matrices and quaternions if you are going to be using them.

Edited by Álvaro

Share this post


Link to post
Share on other sites
biggrin.png It's been a few years since I did my linear algebra. Never got to quaternions but I have a nice book on the subject. I think I have enough to get by now. Thanks for the replies.

Share this post


Link to post
Share on other sites

The identity matrix always commutes with any other matrix, and does nothing, so IA = AI = A.

 

If A is invertible, then A-1 always commutes with A as well, so

 

AA-1 = A-1A = I

 

EDIT: That is a consequence of matrices with elements from a field ring forming a ring under addition and multiplication (a ring is an algebraic structure, they are based on the properties shared by integers, polynomials with coefficients from a ring, and square matrices over a field ring). In a ring, an element always commutes with its (unique) inverse (if it has one, this is not required, e.g. in the ring of integers there is no integer a such that 2a = 1) and the identity element for multiplication always commutes and is unique. Quaternions form a ring too (just not a commutative one. However, quaternions are a bit more special than matrices/rings in general in that every non-zero quaternion has a unique inverse under multiplication, so form a division ring). A commutative ring (which the quaternions aren't) in which every non-zero element has an inverse is a field.

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement