Game Development Community

Rotating a vector based on object orentation

by Zach Broderick · in Technical Issues · 11/23/2007 (12:59 am) · 9 replies

Ok in my game I have a spinning sawblade type object that if the player touches they get injured and impulsed at a 90 degree angle tangent from the point of contact.

I got this working so far for a horizontal blade. However I would like to be able to place the sawblade at any angle and have it work.

I'm assuming the easiest solution would be to mathematically rotate the blade to a horizontal position, then do the math I have already, then rotate it back to its previous position.

Or perhaps do the math as if it were horizontal. Then acquire the blades current rotation values and use those numbers to appropriately rotate my vector.

I'm currently a bit lost on what method to use, and how to actually do the math.
If someone could give me a shove in the right direction It would be very appreciated!

Here is my code as it currently stands...
// Create a vector pointing from this object, to the object collided with
   %impulseVec = vectornormalize(vectorsub( %col.getPosition(), %obj.getPosition() ));
   
   // Increase the magnatude of the vector and respectivly the impulse
   %impulseVec = vectorScale(%impulseVec, 2000);
   
   // Turn the vector 90 degrees about the Z axis (do this by swapping the X and Y)
   %x = getWord(%impulseVec, 1);
   %y = getWord(%impulseVec, 0);
   %z = getWord(%impulseVec, 2);
   
   %x = %x*-1; // set the X to negative(counterclockwise) 
   //setting Y to negative would make it push clockwise
   
   // apply the new 90 degree turn
   %impulseVec = %x SPC %y SPC %z;
   
   // apply the impulse
   %col.applyImpulse(%col.getWorldBoxCenter(), %impulseVec);

#1
11/23/2007 (2:11 am)
As I start to type I have no idea what the answer is but maybe we can work it through..

Also, I'm not quite sure what you are trying to achieve but I'm assuming that you want the object thrown in the direction the blade is spinning.

Assume the blade was made flat (hoizontal).

Given the above description of the model, the Z vector (up) points out of the middle of the flat side of the blade.

To get the Z vector you will need to multply "0 0 1" by the blade's transformation matrix.

We can now take the difference between the center of the blade and the collision point and get the collision point vector (a vector that points straight out from the blade to the collision point). Invert this if it starts throwing you in the opposite direction of the blade's spin.

We will use the crossproduct of the up vector and the collision point vector to obtain a vector that is tangential to the blade's spin.


I think this might be what you are looking for.

I'll leave it at that for now.
#2
11/23/2007 (1:10 pm)
function RotateVector(%vec,%x,%y,%z)
{
   %rot = MatrixCreateFromEuler(mDegToRad(%x) SPC mDegToRad(%y) SPC mDegToRad(%z));
   return MatrixMulVector(%rot, %vec);
}

%vec: The vector you want to rotate.
%x, %y, and %z: How many degrees to rotate the vector on the X-Axis (%x), the Y-Axis (%y), and the Z-Axis (%z).

Usage: %rotatedVector = rotateVector("0 0.1 0.05", 0, 5, 10); // This is just an example
#3
11/26/2007 (3:24 pm)
Ok let me explain a little more in depth.

We have a saw blade spinning counterclockwise. It is sitting horizontal in mid air.

When the player collides with this saw blade, the player is injured, and then an impulse pushes the player. The player is not pushed straight backward from the saw blade, rather they are pushed sideways, because the blade is spinning.

Heres a visual example...
img.photobucket.com/albums/1003/Kaanin/SawbladeExample.jpg
Now with my current code this works fine.

But it only works so long as the blade is laying flat(horizontal) If I were to rotate the blade so that it is sitting at an angle or vertical, the player is still tossed as though the blade was sitting flat(horizontal).

I would like to add a section to my code that would take into account the blades angle, and thusly change the impulse vectors angle.

BrTcY has fortunetly given me the code to rotate my vector.

Now what I need is a way to attain the current rotation of my sawblade, so that i can rotate the vector that way.
#4
11/26/2007 (3:59 pm)
I think brian described what you need to do pretty well.
// assumes that when the blade is unrotated, the blade lies in the XY plane
   // ie, that the "Axis" of the blade is Z.


   // %bladeCenter    = the center of the blade
   // %bladeTransform = the transformation of the blade, including rotation. (ie %blade.getTransform())
   // %pointOfContact = the point where kork hits the blade

   // cancel the translation in the transform:
   // (i think this is actually unneccessary, but just to be safe.)  
   %bladeTransform = setWord(%bladeTransform, 0, "0");
   %bladeTransform = setWord(%bladeTransform, 1, "0");
   %bladeTransform = setWord(%bladeTransform, 2, "0");
   
   %axis  = "0 0 1";
   %axis  = MatrixMulVec(%bladeTransform, %axis);
   
   // get the vector from the center of the saw to the point of contact:
   %cenToContact = VectorSub(%pointOfContact, %bladeCenter);
   
   // cross that vector w/ the axis of rotation to get the tangent to the blade
   %cross = VectorCross(%axis, %cenToContact);
   
   // as Brian notes, this may yield the exact opposite vector,
   // which if that happens just replace the above line with
   // %cross = VectorCross(%cenToContact, %axis);
#5
11/27/2007 (9:27 pm)
Gah this is getting difficult.
After alot of reading on quaternion's and such I'm starting to get this all down.

Ok Orion, first how do I attain the point of contact. The onCollision() function does not get passed the point where the objects collide (as far as i know). If this point is unattainable, the next best bet is we can create a vector from %obj to %col, which is about the same thing.

Second MatrixMulVec() Is not a function currently supported by torque.


Ok so Ive gotten it to a point where I have a vector pointing the correct way...if the saw was horizontal.


Bottom line... I need to know how to rotate a vector based on the quaternion rotation values of an object. In other words I need to rotate the vector the same way the object is rotated. Anyone know how to do that?
#6
11/28/2007 (12:25 am)
My mistake; it's MatrixMulVector.
note i believe the two arguments to that function are reversed in TDN:
the transform should be first, not second.
#7
11/28/2007 (12:52 am)
HOLY CRAP IT WORKS!

Thank you so much Orion!

Well I gotta say I'm impressed with how you were able to get it all working with little to no experimentation...that is unless you actually tested this code yourself ingame :p
But even at that its works better then I expected.

I cant thank you enough. You are awesome!

As stated earlier I don't really know how to find the point of contact. So I'm simply using the WorldBoxCenter of the object that ran into the blade. Which gives nearly the exact same results.

Heres the final source code for anyone interested...
function WhirlingBlade::onCollision(%this,%obj,%col)
{
   //This function applys damage and an impulse to anything that touches the blade
   // %obj = This object (whirling blade)
   // %col = The object that ran into the blade
   // assumes that when the blade is unrotated, the blade lies in the XY plane
   // ie, that the "Axis" of the blade is Z.

   %objCenter = %obj.getWorldBoxCenter();
   %colCenter = %col.getWorldBoxCenter();
   %objTransform = %obj.getTransform();
   
   %axis  = "0 0 1";
   %axis  = MatrixMulVector(%objTransform, %axis);
   
   // Get the vector from the center of %obj to the center of %col
   %objToCol = VectorSub(%colCenter, %objCenter);
   
   // Cross that vector w/ the axis of rotation to get the tangent to %obj
   // %cross = VectorCross(%objToCol, %axis); Yeilds a clockwise based tangent
   %cross = VectorCross(%axis, %objToCol);   // Yeilds a counterclockwise based tangent
   
   // Scale the impulse based on the blades force
   %vec = VectorScale(%cross, %this.bladeForce);
   
   // Apply the final impulse and damage
   %col.applyImpulse(%col.getWorldBoxCenter(), %vec);
   %col.applyDamage(%this.bladeDamage);
}
#8
11/28/2007 (1:05 am)
Awesome! glad it's working.

it's exactly what Brian described,
just with each step turned into code.

vectors are your friends !
#9
11/28/2007 (5:09 am)
Well that worked out pretty well :) If I had had more time...

@Orion: I think I'd really like to work with you.