Game Development Community

Can't do the math, need vector minipulation here.

by John Perricone · in Torque Game Engine · 01/04/2004 (1:59 pm) · 11 replies

How would I set the rotaion of 1 Object to point at another moving Object no matter where where the second moving object goes. Using only the scripts? Vector stuff here right? Does anyone have a snipit of code that they can post?

#1
01/04/2004 (3:21 pm)
//this lil function generates the rotation required for an object at PosOne to point at PosTwo (z rot only)
//reversing the order of vectorSub will provide the rotation of posTwo to point to posOne
function pointToPos(%posOne, %posTwo)
{
%vec = VectorSub(%posOne, %posTwo);
//get the angle
%rotAngleZ = mATan( firstWord(%vec), getWord(%vec, 1) );
//add pi to the angle
%rotAngleZ += 3.1415926;

//make this rotation a proper torque game value, anything more than 240 degrees is negative
if(%rotAngleZ > 4.18879)
{
//the rotation scale is seldom negative, instead make the axis value negative
%modifier = -1;
//subtract 2pi from the value, then make sure its positive
%rotAngleZ = mAbs(%rotAngleZ - 6.2831853);
//sigh, if only this were all true
}
else
%modifier = 1;

//assemble the rotation and send it back
return "0 0" SPC %modifier SPC %rotAngleZ;
}
#2
01/04/2004 (8:08 pm)
Thanks alot.

Could this be modified to include up/down rotation as well by repeating the process for the "Y" rotation?
#3
01/11/2004 (5:41 pm)
That one was actually written to return a value other functions would then work with. After a bit of head scratching (and a bout with giving the wronge numbers to a function) I came up with something that should do the trick just the way you want.

function pointToPos(%posOne, %posTwo)
{
   //PosOne needs to be the location of the object, PosTwo is the position you want it to face.

   //sub the two positions so we get a vector pointing from the origin in the direction we want our object to face
   %vec = VectorSub(%posTwo, %posOne);

   // pull the values out of the vector
   %x = firstWord(%vec);
   %y = getWord(%vec, 1);
   %z = getWord(%vec, 2);

   //this finds the distance from origin to our point
   %len = vectorLen(%vec);

   //---------XY-----------------
   //given the rise and length of our vector this will give us the angle in radians
   %rotAngleXY = mATan( %z, %len );

   //---------Z-----------------
   //get the angle for the z axis
   %rotAngleZ = mATan( %x, %y );

   //create 2 matrices, one for the z rotation, the other for the x rotation
   %matrix = MatrixCreateFromEuler("0 0" SPC %rotAngleZ * -1);
   %matrix2 = MatrixCreateFromEuler(%rotAngleXY SPC "0 0");

   //now multiply them together so we end up with the rotation we want
   %finalMat = MatrixMultiply(%matrix, %matrix2);

   //we're done, send the proper numbers back
   return getWords(%finalMat, 3, 6);
}
#4
01/11/2004 (7:41 pm)
Thanks again! Is there a way to set the rotation on an object without changing it's x, y, z position. What I mean is the first object is a moving vehicle, the second object a target. The first object is moving and I want to change it's rotations but not it's movement. I am working on AI Pilot Scripts, as you know there is very little support for it. So I am messing with controlling the vehicle object directly to simulate the AI Piloting. So far it is working ok, but I am stuck on setTransform(); commands. What is the command to set the Rotation in the Transform without messing with the first 3 words of the Transform?
#5
01/11/2004 (8:08 pm)
Okay heres a little redundancy..
the transform values are: pos.x pos.y pos.z rot.x rot.y rot.z rot.angle
Thats the order of values when you use getTranform.

Now unless you create a new consoleMethod to change the AI vehicles rotation you'll have to go through using setTransform. Luckily the objects position is available via %obj.position, which makes things a bit easier. You can do it so....

%obj.setTransform(%obj.position SPC %newRotation);

Where %newRotation is what the pointToPos returns.

SPC is simply a macro that means @ " " @ (just in case you didn't know).

That should have very little affect on the vehicles motion, since it's grabbing the position at the near instant its setting it, so things should be pretty smooth.
#6
01/11/2004 (11:34 pm)
I will give it try and see how it goes. Thanks for the help.
#7
01/22/2004 (7:14 pm)
Now that I know how to set one object to aim at a second object, my next question is how do I get the first object to rotate a bit slower and more realistic? And it has to be done in scripts.
#8
01/23/2004 (2:03 pm)
This can be done, but there's a nasty downside to the method, assuming you will be doing this for bot controlled vehicles. Since the server must send out the information to all the clients each time the vehicle is rotated, if you were to do the rotations in small increments to give it smooth movement, then you will find the network will quickly get overloaded, and not only will the vehicle rotation still be jerky, most everything else will be as well. While in single player it works well until enough other things are going on so that there is a high CPU load, then it gets jerky again.
#9
01/23/2004 (5:07 pm)
First I want to thank you Martin for the help you have giving me so far and your interest in my questions. I know that updating rotations is CPU intensive and I did not say I wanted real smooth, just not flipping 180 deg. in a split second. I was thinking of using "if the enemy object is more or less in a certain area close to our current lotation and facing direction then do the 'set Auto Aim' that you gave me above" else "Let the ai fly to %enemy.postion his default way (in which case he would eventually be more or less facing the enemy target) and than Auto Aim (above) would kick in. That would stop the 180 deg. flips and it would seem a little more realistic. Not to mention giving the player a chance to win.

My problem (question) is "how do I find out if the enemy more or less in front of me?".

I do have all of this working in a mod for tribes 2 and the bot pilots a shrike and dogfights you (Bot wins very easy with your auto aim). I could show you a picture or demo recording if you wanted to see it in action.
#10
01/23/2004 (8:53 pm)
Figuring out if the enemy is in front of the bot shouldn't be too difficult, just need to compare the bots current rotation to the rotation required to point at the target...

%botRot = rotFromTransform(%bot.getTransform);
(since you have T2, you have a function rotFromTransForm() )

%targetRot = results of pointToPos;

// rotation = x y z angle

Since an object can have a rotaion described with negative radians you need to multiply the z and angle components to ensure you get the proper compass tick the rotation is specifying.

%botZangle = getWord(%botRot, 2) * getWord(%botRot, 3);

get the angle the bot would have to rotate to to face the target...

%TargetZAngle = getWord(%targetRot, 2) * getWord(%targetRot, 3);

Now you can simply compare %botZangle and %TargetZAngle to see how similar the angles are. (the angles are in radians, if you want to see them in degrees then do a %degAngle = mRadToDeg(%botZangle) )

As for the intermidiate rotations, I'll have to think about that when I'm not so tired.(It's never as simple as you hope for)

Since you are playing with T2 mods, here's a lil tidbit that might not have ever made the rounds. it's a correction to get rid of the small drift that tracer projectiles and the like have that keeps them from being usefull sniper weapons...

initialDirection = MatrixMulVector("0 0 0 0 0 1 0", %obj.getMuzzleVector(%slot));
#11
01/26/2004 (6:54 pm)
Quote: //Now you can simply compare %botZangle and %TargetZAngle to see how similar the angles are. (the angles are in radians, if you want to see them in degrees then do a %degAngle = mRadToDeg(%botZangle) )

Thanks for the help.