Vehicle AI
by Daniel Neilsen · in Torque Game Engine · 05/08/2002 (1:15 pm) · 82 replies
Hey guys,
Just wondering if anyone out there has done anything in relation to vehicle ai?
Has anyone tried to get this working?
When I try and give my bots commands to move (my bots are hover vehicles) the dont seem to wanna go anywhere :/
Anyone had any luck with this?
Just wondering if anyone out there has done anything in relation to vehicle ai?
Has anyone tried to get this working?
When I try and give my bots commands to move (my bots are hover vehicles) the dont seem to wanna go anywhere :/
Anyone had any luck with this?
About the author
#62
Here goes the getAiMove ( part 1) :
( Snip .... )
05/18/2004 (6:03 am)
Also I don't know how to Use it.Here goes the getAiMove ( part 1) :
/**
* This method calculates the moves for the AI player
*
* @param movePtr Pointer to move the move list into
*/
bool AIPlayer::getAIMove(Move *movePtr)
{
*movePtr = NullMove;
// Use the eye as the current position.
MatrixF eye;
getEyeTransform(&eye);
Point3F location = eye.getPosition();
Point3F rotation = getRotation();
F32 myTol = mMoveTolerance;
if(isMounted())
myTol = mMoveTolerance *4;
else
myTol = mMoveTolerance;
// Orient towards the aim point, aim object, or towards
// our destination.
if (mAimObject || mAimLocationSet || mMoveState == ModeMove)
{
// Update the aim position if we're aiming for an object
if (mAimObject)
mAimLocation = mAimObject->getPosition();
else
if (!mAimLocationSet)
mAimLocation = mMoveDestination;
F32 xDiff = mAimLocation.x - location.x;
F32 yDiff = mAimLocation.y - location.y;
if ((!isZero(xDiff) || !isZero(yDiff)) && !isMounted())
{
// First do Yaw
// use the cur yaw between -Pi and Pi
F32 curYaw = rotation.z;
while (curYaw > M_2PI)
curYaw -= M_2PI;
while (curYaw < -M_2PI)
curYaw += M_2PI;
// find the yaw offset
F32 newYaw = mAtan( xDiff, yDiff );
F32 yawDiff = newYaw - curYaw;
// make it between 0 and 2PI
if( yawDiff < 0.0f )
yawDiff += M_2PI;
else if( yawDiff >= M_2PI )
yawDiff -= M_2PI;
// now make sure we take the short way around the circle
if( yawDiff > M_PI )
yawDiff -= M_2PI;
else if( yawDiff < -M_PI )
yawDiff += M_2PI;
movePtr->yaw = yawDiff;
// Next do pitch.
if (!mAimObject && !mAimLocationSet)
{
// Level out if were just looking at our next way point.
Point3F headRotation = getHeadRotation();
movePtr->pitch = -headRotation.x;
}
else
{
// This should be adjusted to run from the
// eye point to the object's center position. Though this
// works well enough for now.
F32 vertDist = mAimLocation.z - location.z;
F32 horzDist = mSqrt(xDiff * xDiff + yDiff * yDiff);
F32 newPitch = mAtan( horzDist, vertDist ) - ( M_PI / 2.0f );
if (mFabs(newPitch) > 0.01)
{
Point3F headRotation = getHeadRotation();
movePtr->pitch = newPitch - headRotation.x;
}
}
}
}
else
{
// Level out if we're not doing anything else
Con::printf("AI Steering : fica olhando para um lado e para o outro ");
Point3F headRotation = getHeadRotation();
movePtr->pitch = -headRotation.x;
}
// Move towards the destination
if (mMoveState == ModeMove)
{
F32 xDiff = mMoveDestination.x - location.x;
F32 yDiff = mMoveDestination.y - location.y;
F32 zDiff = mMoveDestination.z - location.z;
if(isMounted())
{
Con::printf("AI Steering : --------------------------------------------------estou montado");
movePtr->yaw = getSteeringAngle();
//movePtr->pitch = getSteeringPitch();
}( Snip .... )
#63
( snip 2 .... )
05/18/2004 (6:06 am)
( glue...)// Check if we should mMove, or if we are 'close enough'
//if (mFabs(xDiff) < mMoveTolerance && mFabs(yDiff) < mMoveTolerance)
if ((mFabs(xDiff) < myTol) && (mFabs(yDiff) < myTol)) // && (mFabs(zDiff) < myTol ))
{
mMoveState = ModeStop;
Con::printf("AI Steering : ------------------------------------- Cheguei no destino pela função default");
throwCallback("onReachDestination");
}
else {
// Build move direction in world space
if(isMounted())
if( isZero(zDiff))
movePtr->z = (location.z > mMoveDestination.z)? -1 : 1;
else
if( mFabs(yDiff) < mFabs(zDiff))
{
F32 value = mFabs(zDiff / yDiff);
movePtr->z = (location.z > mMoveDestination.z)? -value : value;
}
else
{
F32 value = mFabs(zDiff / yDiff);
movePtr->z = (location.z > mMoveDestination.z)? -value : value;
}
if (isZero(xDiff))
{
Con::printf("AI Steering : xDiff = 0");
if(isMounted())
movePtr->y = 1; // = mMoveState == ModeReverse ? -1 : 1;
else
movePtr->y = (location.y > mMoveDestination.y)? -1 : 1;
}
else
{
if (isZero(yDiff))
{
Con::printf("AI Steering : yDiff = 0");
movePtr->x = (location.x > mMoveDestination.x)? -1 : 1;
}
else
{
// Con::printf("AI Steering :uma das coordendas é 0, portanto muda só a outra");
if (mFabs(xDiff) > mFabs(yDiff)) {
F32 value = mFabs(yDiff / xDiff);
movePtr->y = (location.y > mMoveDestination.y)? -value : value;
movePtr->x = (location.x > mMoveDestination.x)? -1 : 1;
}
else {
F32 value = mFabs(xDiff / yDiff);
movePtr->x = (location.x > mMoveDestination.x)? -value : value;
movePtr->y = (location.y > mMoveDestination.y)? -1 : 1;
}
}
}
}
// Rotate the move into object space (this really only needs
// a 2D matrix)
Point3F newMove;
MatrixF moveMatrix;
moveMatrix.set(EulerF(0, 0, -(rotation.z + movePtr->yaw)));
if ( isMounted())
moveMatrix.mulV( Point3F( movePtr->x, movePtr->y, movePtr->z), &newMove );
else
moveMatrix.mulV( Point3F( movePtr->x, movePtr->y, 0 ), &newMove );
movePtr->x = newMove.x;
movePtr->y = newMove.y;
if( isMounted())
movePtr->z = newMove.z;
// Con::printf("AI Steering : Move PTR [%4.2f,%4.2f,%4.2f]", movePtr->x, movePtr->y,movePtr->z);
// Set movement speed. We'll slow down once we get close
// to try and stop on the spot...
if (mMoveSlowdown) {
F32 speed = mMoveSpeed;
F32 dist = mSqrt(xDiff*xDiff + yDiff*yDiff);
F32 maxDist = 5;
if (dist < maxDist)
speed *= dist / maxDist;
movePtr->x *= speed;
movePtr->y *= speed;
if (isMounted())
movePtr->z *= speed;
}
else {
movePtr->x *= mMoveSpeed;
movePtr->y *= mMoveSpeed;
if (isMounted())
movePtr->z *= mMoveSpeed;
}
// We should check to see if we are stuck...
if (location == mLastLocation) {
Con::printf("AI Steering : Estou Atolado ");
throwCallback("onMoveStuck");
mMoveState = ModeStop;
}
}( snip 2 .... )
#64
end getAiMove 3 parts
05/18/2004 (6:07 am)
( glue 2... )// Test for target location in sight if it's an object. The LOS is
// run from the eye position to the center of the object's bounding,
// which is not very accurate.
if (mAimObject) {
MatrixF eyeMat;
getEyeTransform(&eyeMat);
eyeMat.getColumn(3,&location);
Point3F targetLoc = mAimObject->getBoxCenter();
// This ray ignores non-static shapes. Cast Ray returns true
// if it hit something.
RayInfo dummy;
if (getContainer()->castRay( location, targetLoc,
InteriorObjectType | StaticShapeObjectType | StaticObjectType |
TerrainObjectType, &dummy)) {
if (mTargetInLOS) {
throwCallback( "onTargetExitLOS" );
mTargetInLOS = false;
}
}
else
if (!mTargetInLOS) {
throwCallback( "onTargetEnterLOS" );
mTargetInLOS = true;
}
}
// Replicate the trigger state into the move so that
// triggers can be controlled from scripts.
for( int i = 0; i < MaxTriggerKeys; i++ )
movePtr->trigger[i] = getImageTriggerState(i);
return true;
}end getAiMove 3 parts
#65
Ok now I say since we are just getting started.
lets only tackle one thing at a time ok?
so in saying that..
Lets get these guys First driving properly a Wheeled vehicle
there are only two planes to consider
opposed to flight which adds another plane.
So..
ignoring the want/need for pilots lets work on drivers first.
Ok since we will be using getSteeringAngle and all that code is compiling
there is very little to do.
to get the AI to Drive the vehicle only 2 fields of the Move structure are used.
the movePtr->y and the movePtr->yaw
being how he is using a wheeled vehicle he has no use for the other variables.
Ok so that said.
we Must make sure in the code that if(isMounted()) is true, that we are the last to apply a value to the two afore mentioned variables.
for example,
in section 2 of your getAIMove post, you will note that when the guy is mounted the code that was in place before you added this is overriding the values we want in our movePtr->y field.
in section 2 find the code:
Right below that in the isMounted test, be the Last one to apply 1 or 0 or -1 to the movePtr->y field, and your golden.
Lets clarify that the Majority of this function is used to move the AIPlayer towards his goal ON FOOT Not in a car.
so most of this code you Dont want to use when mounted.
So.. you can use an if / else test to remove alot of this code from happening when he is mounted... which you Have done..
But you missed the key area mentioned below..
the rest of the code is used to rotate his head.. and slow him down n stuff..
for Reference:
This is happening After you have applied your y movement when isMounted... this Has to change so This does not happen when mounted.
05/18/2004 (10:39 am)
Ok Bruno,Ok now I say since we are just getting started.
lets only tackle one thing at a time ok?
so in saying that..
Lets get these guys First driving properly a Wheeled vehicle
there are only two planes to consider
opposed to flight which adds another plane.
So..
ignoring the want/need for pilots lets work on drivers first.
Ok since we will be using getSteeringAngle and all that code is compiling
there is very little to do.
to get the AI to Drive the vehicle only 2 fields of the Move structure are used.
the movePtr->y and the movePtr->yaw
being how he is using a wheeled vehicle he has no use for the other variables.
Ok so that said.
we Must make sure in the code that if(isMounted()) is true, that we are the last to apply a value to the two afore mentioned variables.
for example,
in section 2 of your getAIMove post, you will note that when the guy is mounted the code that was in place before you added this is overriding the values we want in our movePtr->y field.
in section 2 find the code:
if( isMounted()) movePtr->z = newMove.z;
Right below that in the isMounted test, be the Last one to apply 1 or 0 or -1 to the movePtr->y field, and your golden.
Lets clarify that the Majority of this function is used to move the AIPlayer towards his goal ON FOOT Not in a car.
so most of this code you Dont want to use when mounted.
So.. you can use an if / else test to remove alot of this code from happening when he is mounted... which you Have done..
But you missed the key area mentioned below..
the rest of the code is used to rotate his head.. and slow him down n stuff..
for Reference:
// Rotate the move into object space (this really only needs // a 2D matrix) Point3F newMove; MatrixF moveMatrix; moveMatrix.set(EulerF(0, 0, -(rotation.z + movePtr->yaw))); if ( isMounted()) moveMatrix.mulV( Point3F( movePtr->x, movePtr->y, movePtr->z), &newMove ); else moveMatrix.mulV( Point3F( movePtr->x, movePtr->y, 0 ), &newMove ); movePtr->x = newMove.x; movePtr->y = newMove.y; if( isMounted()) movePtr->z = newMove.z;This is the offending code..
This is happening After you have applied your y movement when isMounted... this Has to change so This does not happen when mounted.
#66
Now I'm starting to understand.
I changed the MoveTolerance to *7 just in case.
changed the offending code to :
And changed the game back to a whelled vehicle.
What happens now (I'm assuming that you have my test game environment ) :
The bot hits the bomb in his way from node 0 to node 1. A car pops and he mounts it.
the car drives backwards until node 1 is reached. it then procedes forward to node 2 and node 0.
when it reaches node 0 it procedes forward, backs up, turn and go all the way to node 1 in reverse.
On every loop the car backs some more after reaching node 0.
05/18/2004 (12:11 pm)
Ok,Now I'm starting to understand.
I changed the MoveTolerance to *7 just in case.
changed the offending code to :
if(!isMounted())
{
Point3F newMove;
MatrixF moveMatrix;
moveMatrix.set(EulerF(0, 0, -(rotation.z + movePtr->yaw)));
moveMatrix.mulV( Point3F( movePtr->x, movePtr->y, 0 ), &newMove );
movePtr->x = newMove.x;
movePtr->y = newMove.y;
}And changed the game back to a whelled vehicle.
What happens now (I'm assuming that you have my test game environment ) :
The bot hits the bomb in his way from node 0 to node 1. A car pops and he mounts it.
the car drives backwards until node 1 is reached. it then procedes forward to node 2 and node 0.
when it reaches node 0 it procedes forward, backs up, turn and go all the way to node 1 in reverse.
On every loop the car backs some more after reaching node 0.
#67
I can guarantee that if you have set the movePtr->y to 1
that he will Not drive backward's.
the Only way he will drive backwards is if the movePtr->y < 0
So.. this Must mean that somehow, the move is still being applied.
I was able to produce No backward movement by making sure Noone has touched the movePtr->y after me.
also I had no trouble with the "slowdown" code so i just left it after mine.
Edit:
1.75 is still not alot of tolerance.
If i was you and your just playing for now getting the feel for it
go ahead and bump that sucker up to at least 3
Edit 2:
also might I suggest you have the movePtr->y printed to the console for this debug purpose
..
Be sure that this printout happens at the End of the function so you can prove that indeed your not maintaining your value.
05/18/2004 (3:30 pm)
Hmm ..I can guarantee that if you have set the movePtr->y to 1
that he will Not drive backward's.
the Only way he will drive backwards is if the movePtr->y < 0
So.. this Must mean that somehow, the move is still being applied.
I was able to produce No backward movement by making sure Noone has touched the movePtr->y after me.
also I had no trouble with the "slowdown" code so i just left it after mine.
Edit:
1.75 is still not alot of tolerance.
If i was you and your just playing for now getting the feel for it
go ahead and bump that sucker up to at least 3
Edit 2:
also might I suggest you have the movePtr->y printed to the console for this debug purpose
..
Be sure that this printout happens at the End of the function so you can prove that indeed your not maintaining your value.
#68
changed the bad part to :
The 2D driving seems to be OK now. Let's start thinking 3D ?
05/18/2004 (4:22 pm)
YEAH !!! got it !changed the bad part to :
//Con::printf("AI Steering : ------%4.2f %4.2f");
if (mFabs(xDiff) > mFabs(yDiff))
{
F32 value = mFabs(yDiff / xDiff);
movePtr->x = (location.x > mMoveDestination.x)? -1 : 1;
if(isMounted())
movePtr->y = value;
else
movePtr->y = (location.y > mMoveDestination.y)? -value : value;
}
else
{
F32 value = mFabs(xDiff / yDiff);
movePtr->x = (location.x > mMoveDestination.x)? -value : value;
if(isMounted())
movePtr->y = 1;
else
movePtr->y = (location.y > mMoveDestination.y)? -1 : 1;
}The 2D driving seems to be OK now. Let's start thinking 3D ?
#69
well the First thing to do would be to have a Solid understanding of the component's of this code you wish to use.
then make the changes such as you have to the getSteeringAngle|Yaw
(rename?)
to create the getSteeringPitch function.
Or.. go right away to consolidating this code to one function.
I would prolly keep em seperated till I at least had em both working.
I would most likely turn off forward movement and just go with the rotations to test the working of it.
you should be able to force him to next node with a function call?
im not sure.
there are ALOT of factors in making this guy a pilot he will have to learn and consider for Proper flight travel.
But.. one step at a time... :)
so get your function back to calling..
But First!
clean up that function and make it more understandable and legible.
(to you) getAIMove(..)
figure out the smooth places to "break" the code into your path so you are not having Both sets of code running when he is trying to drive/pilot
(both sets, us modifying the movePtr->yaw and movePtr->y vs. the original walking code)
see the problem has been that you didnt break that code up to have it fire only what is necessary.
I would do that first.
make it so that when driving he does only what is necessary.
then once that is in and still working nice i would begin pilot training :)
Edit:
isn't it cool watching them drive thier path's?
I went immediately and setup AI Cam so i can watch them..
it's a cool camera mode with a sweet zoom.
05/18/2004 (4:32 pm)
Ok,well the First thing to do would be to have a Solid understanding of the component's of this code you wish to use.
then make the changes such as you have to the getSteeringAngle|Yaw
(rename?)
to create the getSteeringPitch function.
Or.. go right away to consolidating this code to one function.
I would prolly keep em seperated till I at least had em both working.
I would most likely turn off forward movement and just go with the rotations to test the working of it.
you should be able to force him to next node with a function call?
im not sure.
there are ALOT of factors in making this guy a pilot he will have to learn and consider for Proper flight travel.
But.. one step at a time... :)
so get your function back to calling..
But First!
clean up that function and make it more understandable and legible.
(to you) getAIMove(..)
figure out the smooth places to "break" the code into your path so you are not having Both sets of code running when he is trying to drive/pilot
(both sets, us modifying the movePtr->yaw and movePtr->y vs. the original walking code)
see the problem has been that you didnt break that code up to have it fire only what is necessary.
I would do that first.
make it so that when driving he does only what is necessary.
then once that is in and still working nice i would begin pilot training :)
Edit:
isn't it cool watching them drive thier path's?
I went immediately and setup AI Cam so i can watch them..
it's a cool camera mode with a sweet zoom.
#70
I'll clean up the getAIMove and set it for a more encapsulated look.
Meanwhile, could you check that getSteeringPitch function. I really don't know if it works or not. Also, do you think we should add a mClimbing enum attribute and use it instead of mSteering in getSteeringPitch ?
05/18/2004 (5:10 pm)
Wise words,I'll clean up the getAIMove and set it for a more encapsulated look.
Meanwhile, could you check that getSteeringPitch function. I really don't know if it works or not. Also, do you think we should add a mClimbing enum attribute and use it instead of mSteering in getSteeringPitch ?
#71
Added the prototypes to AIplayer.h
and that huge stuff became
[code]
bool AIPlayer::getAIMountedMove(Move *movePtr)
{
*movePtr = NullMove;
// Use the eye as the current position.
MatrixF eye;
getEyeTransform(&eye);
Point3F location = eye.getPosition();
// Point3F rotation = getRotation();
F32 myTol = mMoveTolerance * 7;
// Move towards the destination
if (mMoveState == ModeMove)
{
F32 xDiff = mMoveDestination.x - location.x;
F32 yDiff = mMoveDestination.y - location.y;
F32 zDiff = mMoveDestination.z - location.z;
//Con::printf("AI Steering : --------------------------------------------------estou montado");
movePtr->yaw = getSteeringAngle();
//movePtr->pitch = getSteeringPitch();
// Check if we should mMove, or if we are 'close enough'
if ((mFabs(xDiff) < myTol) && (mFabs(yDiff) < myTol)) // && (mFabs(zDiff) < myTol ))
{
mMoveState = ModeStop;
Con::printf("AI Steering : ------------------------------------- Cheguei no destino pela fun
05/18/2004 (6:07 pm)
Ok.Added the prototypes to AIplayer.h
bool AIPlayer::getAIMove(Move *movePtr)
{
if(isMounted())
return(getAIMountedMove(movePtr));
else
return(getAIOnFootMove(movePtr));
}and that huge stuff became
[code]
bool AIPlayer::getAIMountedMove(Move *movePtr)
{
*movePtr = NullMove;
// Use the eye as the current position.
MatrixF eye;
getEyeTransform(&eye);
Point3F location = eye.getPosition();
// Point3F rotation = getRotation();
F32 myTol = mMoveTolerance * 7;
// Move towards the destination
if (mMoveState == ModeMove)
{
F32 xDiff = mMoveDestination.x - location.x;
F32 yDiff = mMoveDestination.y - location.y;
F32 zDiff = mMoveDestination.z - location.z;
//Con::printf("AI Steering : --------------------------------------------------estou montado");
movePtr->yaw = getSteeringAngle();
//movePtr->pitch = getSteeringPitch();
// Check if we should mMove, or if we are 'close enough'
if ((mFabs(xDiff) < myTol) && (mFabs(yDiff) < myTol)) // && (mFabs(zDiff) < myTol ))
{
mMoveState = ModeStop;
Con::printf("AI Steering : ------------------------------------- Cheguei no destino pela fun
#72
I continued working on the getSteeringPitch. But I got to a dead end. I checked the getSteering function and wondered if the mSteering variable would be an accumulated value.
So I created an mPitching attribute in the vehicle class and tried to set it as the mSteering was in updateMove ( vehicle.c) :
But still no use. I guess that getSteeringPitch must be wrong but my math isn't good enough to understand what it does.
05/22/2004 (7:43 pm)
Hi Badguy,I continued working on the getSteeringPitch. But I got to a dead end. I checked the getSteering function and wondered if the mSteering variable would be an accumulated value.
So I created an mPitching attribute in the vehicle class and tried to set it as the mSteering was in updateMove ( vehicle.c) :
// Steering
if (move != &NullMove) {
F32 y = move->yaw;
mSteering.x = mClampF(mSteering.x + y,-mDataBlock->maxSteeringAngle, mDataBlock->maxSteeringAngle);
F32 p = move->pitch;
mSteering.y = mClampF(mSteering.y + p,-mDataBlock->maxSteeringAngle, mDataBlock->maxSteeringAngle);
//Bruno
mPitching.x = mClampF(mPitching.x + y,-mDataBlock->maxSteeringAngle, mDataBlock->maxSteeringAngle);
mPitching.y = mClampF(mPitching.y + p,-mDataBlock->maxSteeringAngle, mDataBlock->maxSteeringAngle);
mPitching.z = mClampF(mPitching.z + p,-mDataBlock->maxSteeringAngle, mDataBlock->maxSteeringAngle);
}
else {
mSteering.x = 0;
mSteering.y = 0;
//Bruno
mPitching.x = 0;
mPitching.y = 0;
mPitching.z = 0;
}But still no use. I guess that getSteeringPitch must be wrong but my math isn't good enough to understand what it does.
#73
Did you two ever finish this and create a resource? I'm trying to follow the thread to implement the 2d bot steering, but I did not know my Orc was such a bad driver.
07/27/2004 (4:48 am)
Bruno, Badyguy;Did you two ever finish this and create a resource? I'm trying to follow the thread to implement the 2d bot steering, but I did not know my Orc was such a bad driver.
#74
There is no resource yet, but the code of my may 18th message is up to date.
HTH
07/27/2004 (6:27 am)
@Simon,There is no resource yet, but the code of my may 18th message is up to date.
HTH
#75
05/21/2006 (4:05 pm)
Is there any working code lying around for this?
#77
05/22/2006 (7:42 am)
I made the 3D vehicle AI work at some point.. tho it's buried in old code somewhere
#78
05/22/2006 (10:25 am)
Thanks Bruno.
#79
Having some trouble making it work with TSE, although I think it's a problem on my side, and not TSE (MS4).
01/24/2007 (12:56 am)
Im was quite sure I got it here... Apparently not... I have a AiFlyingVehicle.h and AiflyingVehicle.cpp... Can someone point me to that resource? Having some trouble making it work with TSE, although I think it's a problem on my side, and not TSE (MS4).
Torque Owner Bruno Grieco
I don't know what you are talking about.
What code is overuling the movePtr->y ? Why should I need it when I want to fly ?
I've already tried coding it. It ended up in this :
F32 AIPlayer::getSteeringPitch() { // Build a Triangle .. calculate angle of rotation required to meet target.. // man there has to be a better way! >:) Point3F desired; int mAvoidObject = 0; Point3F mAvoidLocation; if(mAvoidObject) desired=mAvoidLocation; else desired=mMoveDestination; MatrixF mat = getObjectMount()->getTransform(); Point3F center,front; Point3F wFront; Box3F box=getObjectMount()->getObjBox(); box.getCenter(¢er); front=center; front.y=box.max.y; // should be true for all these objects getObjectMount()->getWorldBox().getCenter(¢er); front=center+front; Point3F objFront=front; Point3F offset = front - center; EulerF rot; rot=extractEuler(mat); MatrixF transform(rot); transform.mulV(offset, &wFront); front = wFront + center; Point3F ftoc; ftoc.x=mFabs(front.x-center.x); ftoc.y=mFabs(front.y-center.y); ftoc.z=mFabs(front.z-center.z); F32 fToc=mSqrt((ftoc.z*ftoc.z)+(ftoc.y*ftoc.y)); Point3F ltoc; ltoc.x=mFabs(desired.x-center.x); ltoc.y=mFabs(desired.y-center.y); ltoc.z=mFabs(desired.z-center.z); F32 lToc=mSqrt((ltoc.z*ltoc.z)+(ltoc.y*ltoc.y)); Point3F ftol; ftol.x=mFabs(front.x-desired.x); ftol.y=mFabs(front.y-desired.y); ftol.z=mFabs(front.z-desired.z); F32 fTol=mSqrt((ftol.z*ftol.z)+(ftol.y*ftol.y)); F32 myAngle = mAcos(((lToc*lToc) + (fToc * fToc) - (fTol*fTol))/(2*lToc*fToc)); Point3F location = getPosition(); F32 xDiff = desired.x - location.x; F32 yDiff = desired.y - location.y; F32 zDiff = desired.z - location.z; F32 finalYaw=mRadToDeg(myAngle); F32 maxSteeringAngle=0; if(isMounted()) { VehicleData *vd=(VehicleData*)getObjectMount()->getDataBlock(); maxSteeringAngle=vd->maxSteeringAngle; } if(finalYaw > 150) mSteering = TurnAround; if(finalYaw < 5 && mLastSteered != 0) mSteering = Straight; else if(finalYaw < 5) mSteering = SteerNull; else {// Quickly Hack out left or right turn info Point3F rotData=objFront-desired; MatrixF leftM(-rot); Point3F leftP; leftM.mulV(rotData, &leftP); leftP = leftP + desired; if(leftP.y<desired.y) mSteering=Right; else mSteering=Left; } Vehicle *v=(Vehicle*)getObjectMount(); Point2F steering=v->getSteering(); F32 steer=0; switch(mSteering) { case SteerNull: break; case Left: steer=myAngle < maxSteeringAngle ? -myAngle-steering.y: -maxSteeringAngle-steering.y; mLastSteered=steer; break; case Right: steer=myAngle < maxSteeringAngle ? myAngle-steering.y: maxSteeringAngle-steering.y; mLastSteered=steer; break; case Straight: steer=-steering.y; mLastSteered=0; break; case TurnAround: steer=maxSteeringAngle-steering.y; mLastSteered=steer; break; }; //Con::printf("AI Steering Pitch: %f", steer); return steer; }What is wrong with this ??? I can't really go further. I don't know the math for it. For instance, I don't have a clue of what that ExtractEuler function does...
TIA
Bruno