Game Development Community

Immersive AI Engine by Gavin Bunney discussion

by Fyodor -bank- Osokin · in Torque Game Engine · 02/27/2007 (4:46 am) · 191 replies

Let's discuss the iAI engine here, not spamming the .blog is good :)

The first question - is it based on standard AIPlayer.cc from SDK?
May be it's written in documents, but I haven't read all of them yet..
#161
01/26/2008 (5:48 am)
@DALO - yup that is the same problem I was having, hence the reason for adding getAIMove to iAIAgent
#162
01/30/2008 (6:51 pm)
Alrighty, well here's a question for any C++ expert to answer. when this->setMoveDestination get's called it goes to the parent class of iAIAgent and traces through the parents member functions. Now it get's to roughly 235 ish in aiPlayer.cc to a throwCallback("onReachDestination"); This is the problem that prevents the bots from moving. It's looking for a script function onReachDestination, oops. The starter.fps calls AIPlayer::onReachDestination, what is the script version for iAIAgent? iAIAgent::onReachDestination doesn't seem to work for me?
Sooooo, how do you get this to work in engine and not script? The iAIAgent class is inherited from aiPlayer when the iAIAgent calls AIPlayer::getAIMove does it know which child class is accessing that function? if it does, how do you call a child member function from a parent member function? I've googled this lot's and can find lot's of examples of child class calling parent functions but not the reverse. How do we get the throwCallback("onReachDestination"); to just simply call iAIAgent::onReachDestination?

Any thoughts or ideas?
#163
01/30/2008 (11:47 pm)
Well, I kinda found a hack way to do it in case anyone is following the engine conversion stuff. Following what Jason said, get rid of the getAIMove in iAIAgent and on all setMoveDestination's get rid of the line below it, the Move line. When you call setMoveDestination it will still step through the getAIMove in the parent class. The part where it calls throwCallback("onReachDestination"); in the aiPlayer's getAIMove function, it just simply calls an Con::executef function which then calls a function in script. I made a new function in script which get's called and then I redirect it back to a Console Method which calles my iAIAgent::onReachDestination function. Bot's need to know when they have reached a point and when they do tell them to move somewhere else. Hopefully that makes sense and helps someone else out along the way.........anyone have an idea how to skip those extra steps?
DALO

*EDIT* oh and btw, this solves the walking backwards issue :-)
#164
02/01/2008 (12:25 pm)
Sorry about taking so long to get back to you.

I was thinking about how best to fix the problem, and (I haven't tried this yet) what about editing AIPlayer::getAIMove() to call the function [virtual] AIPlayer::onReachDestination() (supplied accordingly) which just throws the script callback (that keeps AIPlayer continuity), then the function iAIAgent::onReachDestination() *will* be called and you can do whatever you want in there.

What do you think? I know changing AIPlayer is not best solution, but this is a very minimal solution.
#165
02/06/2008 (12:22 pm)
Looking for the place where to customize the mMoveModifier set, I noticed that iAIPathNode::updateMoveModifier() is never called... I think actually the nodes are never updated, anybody also noticed this? Am I right?

Note: by "updated" I mean, the weight is never set on the nodes. (?)
#166
02/24/2008 (9:39 am)
Is there anyway to call updateMoveModifier() once i got a bot stand on that node? since im plan to do something like when bot is stand on that node it will make that node weight become impassable and it will be passable again once bot is leave that node using a trigger may be?
#167
02/27/2008 (5:02 am)
After playing arround with iAIPathNode::isClear() there was allways nodes connected to close to a object. IAIPATHGLOBAL_NODE_CLEARANCE defines a box but make a castRay which only test the point not a box.

I replaced it with the following:

bool iAIPathNode::isClear() 
{

   Point3F  center = this->mPosition + Point3F(0, 0, IAIPATHGLOBAL_NODE_CLEARANCE.z / 2);
   Point3F  extent = IAIPATHGLOBAL_NODE_CLEARANCE;
   U32  mask = IAIPATHGLOBAL_COLLISION_MASK;

   Box3F    B(center - extent, center + extent, true);

   EarlyOutPolyList polyList;
   polyList.mPlaneList.clear();
   polyList.mNormal.set(0,0,0);
   polyList.mPlaneList.setSize(6);
   polyList.mPlaneList[0].set(B.min, VectorF(-1,0,0));
   polyList.mPlaneList[1].set(B.max, VectorF(0,1,0));
   polyList.mPlaneList[2].set(B.max, VectorF(1,0,0));
   polyList.mPlaneList[3].set(B.min, VectorF(0,-1,0));
   polyList.mPlaneList[4].set(B.min, VectorF(0,0,-1));
   polyList.mPlaneList[5].set(B.max, VectorF(0,0,1));

   return ! gServerContainer.buildPolyList(B, mask, &polyList);
}

It will check a box now and works much better than the old function :)

If you want to add this, dont forget to add
#include "collision/earlyOutPolyList.h"
to the includes.
#168
05/24/2008 (1:16 pm)
Not sure if Jason, Dalo and/or Greg are still checking this, but removing
if (!isAimLocationSet())

in iAIAgent.cc

bool iAIAgent::getAIMove(Move *movePtr)
{
   *movePtr = NullMove;

   // Use the eye as the current position.
   MatrixF eye;
   getEyeTransform(&eye);
   Point3F location = eye.getPosition();
   Point3F rotation = getRotation();

   // Orient towards the aim point, aim object, or towards
   // our destination.
   if (getAimObject() || getAimLocation() || getMoveState() == ModeMove) {

      // Update the aim position if we're aiming for an object
      if (getAimObject())
         setAimLocation( getAimObject()->getPosition() + getAimOffset() );
      else
            //if (!isAimLocationSet())            <----------------------
            setAimLocation( getMoveDestination() );
...

Will make your bots face the way they are running. Not sure about what other effects this may have.
#169
05/29/2008 (1:46 pm)
IS THERE AN UPDATE FOR TGEA 1.7 I JUST FOUND THIS RESOURCE AND TRIED IT BUT I GOT ERRORS SO I WAS WONDERING IF ANYONE WAS ABLE TO GET IT TO WORK FOR TGEA 1.7? IF SO CAN THEY POST THE CODE OR SEND IT DIRECTLY TO MY EMAIL: JSTANLEYNWO@YAHOO.COM OR imaginationseven7@yahoo.com

THANKS
#170
06/26/2008 (8:44 am)
For some reason I was getting 'strcmp': identifier not found and 'strlen': identifier not found in iAIAgent.cc. I changed both calls to dStrcmp and dStrlen respectively to get past that. but then I got:
Quote:7>iAIAgent.obj : error LNK2019: unresolved external symbol "public: void __thiscall AIPlayer::setTargetInLOS(bool)" (?setTargetInLOS@AIPlayer@@QAEX_N@Z) referenced in function "public: virtual bool __thiscall iAIAgent::getAIMove(struct Move *)" (?getAIMove@iAIAgent@@UAE_NPAUMove@@@Z)
7>iAIAgent.obj : error LNK2019: unresolved external symbol "public: bool __thiscall AIPlayer::isTargetInLOS(void)" (?isTargetInLOS@AIPlayer@@QAE_NXZ) referenced in function "public: virtual bool __thiscall iAIAgent::getAIMove(struct Move *)" (?getAIMove@iAIAgent@@UAE_NPAUMove@@@Z)
7>iAIAgent.obj : error LNK2019: unresolved external symbol "public: class Point3F __thiscall AIPlayer::getLastLocation(void)" (?getLastLocation@AIPlayer@@QAE?AVPoint3F@@XZ) referenced in function "public: virtual bool __thiscall iAIAgent::getAIMove(struct Move *)" (?getAIMove@iAIAgent@@UAE_NPAUMove@@@Z)
7>iAIAgent.obj : error LNK2019: unresolved external symbol "public: bool __thiscall AIPlayer::isMoveSlowdown(void)" (?isMoveSlowdown@AIPlayer@@QAE_NXZ) referenced in function "public: virtual bool __thiscall iAIAgent::getAIMove(struct Move *)" (?getAIMove@iAIAgent@@UAE_NPAUMove@@@Z)
7>iAIAgent.obj : error LNK2019: unresolved external symbol "public: bool __thiscall AIPlayer::isAimLocationSet(void)" (?isAimLocationSet@AIPlayer@@QAE_NXZ) referenced in function "public: virtual bool __thiscall iAIAgent::getAIMove(struct Move *)" (?getAIMove@iAIAgent@@UAE_NPAUMove@@@Z)
7>iAIAgent.obj : error LNK2019: unresolved external symbol "public: class Point3F __thiscall AIPlayer::getAimOffset(void)" (?getAimOffset@AIPlayer@@QAE?AVPoint3F@@XZ) referenced in function "public: virtual bool __thiscall iAIAgent::getAIMove(struct Move *)" (?getAIMove@iAIAgent@@UAE_NPAUMove@@@Z)
7>iAIAgent.obj : error LNK2019: unresolved external symbol "public: enum AIPlayer::MoveState __thiscall AIPlayer::getMoveState(void)" (?getMoveState@AIPlayer@@QAE?AW4MoveState@1@XZ) referenced in function "public: virtual bool __thiscall iAIAgent::getAIMove(struct Move *)" (?getAIMove@iAIAgent@@UAE_NPAUMove@@@Z)
I mean yuck what the hell's with that.
#171
06/26/2008 (8:55 am)
It's pretty hard to say what is causing that, without being able to see the code and debug but my guess is that you are probably missing something really simple such as a ; or ) or a ". In my experience when you see a bunch of funky symbols that make no sense it's because of 1 little thing.........good luck with that ;-)
#172
06/26/2008 (9:02 am)
Haha thanks DALO ;p as far as I can see it's because there are a bunch of methods:
AIPlayer::setTargetInLOS(bool)
AIPlayer::isTargetInLOS(void)
AIPlayer::getLastLocation(void)
AIPlayer::isMoveSlowdown(void)
AIPlayer::isAimLocationSet(void)
AIPlayer::getAimOffset(void)
AIPlayer::getMoveState(void)
that are defined in aiPlayer.h but have no body anywhere in the project. So it compiles fine but can't link as iAIAgent calls all those methods. I was using Greg's AIPlayer code.. if no one else has had this problem maybe I'm just missing a file? Or does everyone else's aiPlayer.cc HAVE method bodies for those?
#173
06/26/2008 (9:41 am)
Yeah it's posted somewhere up above, it's such a looooong post now that it may be hard to find.
Point3F AIPlayer::getAimOffset(){
return mAimOffset;
}

AIPlayer::MoveState AIPlayer::getMoveState(){
return mMoveState;
}
bool AIPlayer::isAimLocationSet(){
return mAimLocationSet;
}
bool AIPlayer::isMoveSlowdown(){
return mMoveSlowdown;
}
Point3F AIPlayer::getLastLocation(){
return mLastLocation;
}

bool AIPlayer::isTargetInLOS(){
return mTargetInLOS;
}

void AIPlayer::setTargetInLOS( bool targetInLOS ){
mTargetInLOS = targetInLOS;
}

This is from my code, add these to AIPlayer and hopefully that'll do the trick.
#174
06/26/2008 (9:49 am)
Oooookkk thanks DALO I went to put that code in aiplayer.cpp and lo and behold it was there. why was my find in project not finding it? because I had the old aiPlayer.cc in my project instead of Greg's aiPlayer.cpp which was dutifully sitting there in the dir, not getting compiled. -_-. it's too late for me to be trusted in front of a keyboard.
#175
06/27/2008 (5:10 pm)
I recently did a port of the line rendering code to TGEA 1_7_1.

It's not perfect and it is very slow but I thought I would post it and see if anyone can offer suggestions.

Change the following four methods:

bool iAIPath::prepRenderImage(SceneState *state, const U32 stateKey, const U32 startZone, const bool modifyBaseZoneState)
{
	
	
// render if there is a path to render and want to show it
   if ((this->mShow) && (this->mPathNodes.size() > 0))
   {
      // return if last state
      if (this->isLastState(state, stateKey)) return false;
      // set last state
      this->setLastState(state, stateKey);
      // see if object rendered
      if (state->isObjectRendered(this))
      {
         // get a SceneRenderImage to show on
         //IB: Changed for TGEA
         RenderInst *image = gRenderInstManager.allocInst();
         //SceneRenderImage* image = new SceneRenderImage;
         image->obj = this;

         image->state = state;
         image->type = RenderInstManager::RIT_ObjectTranslucent;
         image->translucent = true;
         image->calcSortPoint(this, state->getCameraPosition());

         // insert into scene image
         //state->insertRenderImage(image);
			gRenderInstManager.addInst(image);

      }
   }
	
   return false;
}


void iAIPath::renderObject(SceneState *state, RenderInst *image)//SceneRenderImage
{
   // save matrix to restore canonical state
   GFX->pushWorldMatrix(); 
	
   // enable blend
   GFX->setAlphaBlendEnable(true); 

   ColorF Xcolor(1.f, 1.f, 1.f, 0.f);

   PrimBuild::color(Xcolor);//IB: add color

   // see if we want a linear or spline path
   if (this->mRenderSpline)
   {
      CameraSpline pathSpline;
      // add the lastNode to the spline
      if (this->mLastNode)
      {
         pathSpline.push_back(new CameraSpline::Knot(this->mLastNode->mPosition, QuatF(0, 0, 0, 0), 1.0f, CameraSpline::Knot::NORMAL, CameraSpline::Knot::SPLINE));
      }
      // iterate over all the nodes: add to spline and draw the stick
      for (U32 j = 0; j < this->mPathNodes.size(); j++)
      {
         if (this->mPathNodes[j])
         {
            // add a new knot for each path node
            pathSpline.push_back(new CameraSpline::Knot(this->mPathNodes[j]->mPosition, QuatF(0, 0, 0, 0), 1.0f, CameraSpline::Knot::NORMAL, CameraSpline::Knot::SPLINE));
         }


         PrimBuild::begin(GFXLineList, 2);
         // draw the path node
         PrimBuild::color4i(this->mPathNodeColour.red, this->mPathNodeColour.green, this->mPathNodeColour.blue, this->mPathNodeColour.alpha);
         PrimBuild::vertex3fv(this->mPathNodes[j]->mPosition + IAIPATHGLOBAL_PATH_RENDER_CLEARANCE);
			PrimBuild::vertex3fv(this->mPathNodes[j]->mPosition + IAIPATHGLOBAL_PATH_RENDER_CLEARANCE + IAIPATHGLOBAL_PATH_RENDER_NODE_HEIGHT);

         PrimBuild::end();

      }
      F32 iter = 0.0f;
      Point3F lastPoint = Point3F(0,0,0);
      // draw the entire spline
      while (iter < (pathSpline.size()-1))
      {
         // get set k to the current knot value
         CameraSpline::Knot k;
         pathSpline.value(iter, &k);
         // advance the spline iter
         iter = pathSpline.advanceDist(iter, 2.0f);
         // get the knot point information
         Point3F newPoint;
         k.mRotation.mulP(Point3F(0,0,0), &newPoint);
         newPoint += k.mPosition;
         // check if there is a last point info stored
         if (lastPoint == Point3F(0,0,0))
         {
            lastPoint = newPoint;
         } else
         {
				
             PrimBuild::begin(GFXLineList, 2);

             PrimBuild::color4i(this->mPathColour.red, this->mPathColour.green, this->mPathColour.blue, this->mPathColour.alpha);

            // draw a line between the new point and the last point
            PrimBuild::vertex3fv(newPoint + IAIPATHGLOBAL_PATH_RENDER_CLEARANCE);
            PrimBuild::vertex3fv(lastPoint + IAIPATHGLOBAL_PATH_RENDER_CLEARANCE);

            PrimBuild::end();
         }
      }
   } else
   {
      // draw a path between the last node and the current start node
      if (this->mLastNode)
      {
            PrimBuild::begin(GFXLineList, 2);		

            PrimBuild::color4i(this->mPathColour.red, this->mPathColour.green, this->mPathColour.blue, this->mPathColour.alpha);
            PrimBuild::vertex3fv(this->mLastNode->mPosition + IAIPATHGLOBAL_PATH_RENDER_CLEARANCE);
            PrimBuild::vertex3fv(this->mPathNodes[0]->mPosition + IAIPATHGLOBAL_PATH_RENDER_CLEARANCE);

            PrimBuild::end();
      }
      for (int j = 1; j < this->mPathNodes.size(); j++)
      {
         if (this->mPathNodes[j])
         {
            PrimBuild::begin(GFXLineList, 4);	
            // draw the path line
            PrimBuild::color4i(this->mPathColour.red, this->mPathColour.green, this->mPathColour.blue, this->mPathColour.alpha);
            PrimBuild::vertex3fv(this->mPathNodes[j-1]->mPosition + IAIPATHGLOBAL_PATH_RENDER_CLEARANCE);
            PrimBuild::vertex3fv(this->mPathNodes[j]->mPosition + IAIPATHGLOBAL_PATH_RENDER_CLEARANCE);

            // draw the node stick
            PrimBuild::color4i(this->mPathNodeColour.red, this->mPathNodeColour.green, this->mPathNodeColour.blue, this->mPathNodeColour.alpha);
            PrimBuild::vertex3fv(this->mPathNodes[j]->mPosition + IAIPATHGLOBAL_PATH_RENDER_CLEARANCE);
            PrimBuild::vertex3fv(this->mPathNodes[j]->mPosition + IAIPATHGLOBAL_PATH_RENDER_CLEARANCE + IAIPATHGLOBAL_PATH_RENDER_NODE_HEIGHT);

            PrimBuild::end();
         }
      }
   }

   // disable the blend
   GFX->setAlphaBlendEnable(false); //IB TSE Change

   // restore canonical maxtrix state
   GFX->popWorldMatrix();

}

bool iAIPathGrid::prepRenderImage(SceneState *state, const U32 stateKey, const U32 startZone, const bool modifyBaseZoneState)
{

	
   //IB: My TGEA translation
   if (this->mShow)
   {
       // Return if last state.
       if (isLastState(state, stateKey)) return false;
       // Set Last State.
       setLastState(state, stateKey);

       RenderInst *ri = gRenderInstManager.allocInst();
       ri->obj = this;
       ri->state = state;
       ri->type = RenderInstManager::RIT_ObjectTranslucent;//
       ri->translucent = true;
       ri->calcSortPoint(this, state->getCameraPosition());
       gRenderInstManager.addInst(ri);

    }

   return true;//IB: doesn't seem to matter what we return.
}

void iAIPathGrid::renderObject(SceneState *state, RenderInst *image)//SceneRenderImage *image
{
	
   // save matrix to restore canonical state
   GFX->pushWorldMatrix();
 
   // render the nodes
   for (U32 i = 0; i < this->mNodes.size(); ++i)
   {

        // going to render some lines!
       PrimBuild::begin(GFXLineList, 2);

       PrimBuild::color4i(IAIPATHGLOBAL_GRID_RENDER_NODE_COLOUR);
       PrimBuild::vertex3fv(this->mNodes[i]->mPosition + IAIPATHGLOBAL_GRID_RENDER_CLEARANCE);
       PrimBuild::vertex3fv(this->mNodes[i]->mPosition + IAIPATHGLOBAL_GRID_RENDER_CLEARANCE + IAIPATHGLOBAL_GRID_RENDER_NODE_HEIGHT);

       PrimBuild::end();

      // render neighbour links
      for (U32 j = 0; j < this->mNodes[i]->mNeighbours.size(); ++j)
      {

         if (this->mNodes[i]->mNeighbours[j])
         {
             PrimBuild::begin(GFXLineList, 2);
            PrimBuild::color4i(IAIPATHGLOBAL_GRID_RENDER_COLOUR);

            PrimBuild::vertex3fv(this->mNodes[i]->mPosition + IAIPATHGLOBAL_GRID_RENDER_CLEARANCE);
            PrimBuild::vertex3fv(this->mNodes[i]->mNeighbours[j]->mPosition + IAIPATHGLOBAL_GRID_RENDER_CLEARANCE);

            PrimBuild::end();
         }
      }
   }

   // restore canonical rendering state
	GFX->setAlphaBlendEnable(false); //IB TSE Change

   // restore canonical maxtrix state
	GFX->popWorldMatrix();
}
#176
07/01/2008 (6:50 am)
Hello All,

Is anyone running this on a Linux version of TGE? As I'm trying to get the port running on RTS-SK 1.5.2 in Linux. But I keep getting this message:
--> Compiling immersiveAI/seek/path/iAIPathMap.cc
In file included from immersiveAI/seek/path/iAIPathGrid.h:23,
                 from immersiveAI/seek/path/iAIPathMap.h:23,
                 from immersiveAI/seek/path/iAIPathMap.cc:11:
immersiveAI/seek/path/iAIPathNode.h:51: error: 'iAIPathGrid' has not been declared
immersiveAI/seek/path/iAIPathNode.h:124: error: ISO C++ forbids declaration of 'iAIPathGrid' with no type
immersiveAI/seek/path/iAIPathNode.h:124: error: expected ';' before '*' token
make[1]: *** [out.GCC4.DEBUG/immersiveAI/seek/path/iAIPathMap.obj] Error 1

If anyone has an idea how to fix/debug this please help!

Thanks for any help,

Arjan Gelderblom
#177
07/01/2008 (7:20 am)
Is there any examples of this AI engine in use to look at ?
#178
07/01/2008 (3:36 pm)
Seems I got it compiling in Linux as well simple patch did the trick:
seek/path/iAIpathNode.h
#define _IAIPATHNODE_H_

class iAIPathNode {

	friend class iAIPathMap;
	friend class iAIPathGrid;
	friend class iAIPath;
	friend class iAIPathFind;

public:
Should be:
#define _IAIPATHNODE_H_

class iAIPathMap;
class iAIPathGrid;
class iAIPath;
class iAIPathFind;

class iAIPathNode {

public:

Now let's see if it's also working! But at least I hope this will help someone else too!

Greetings,

Arjan Gelderblom

Edit: Tested and can confirm that it seems to work. Pathfinding works correctly (as that is the only thing implemented by the mod and only thing I need from this resource!
#179
07/04/2008 (12:26 pm)
I'm having some trouble also...

I've got everything set up and compiled with no errors. However, when I go into the World Editor the iAIAgent category appears, along with the iAIAgent_soldier, iAIAgentDAta, and iAIAGent_Bandit. But when I click on the soldier, bandit or data, nothing happens. nothing appears, and nothing spawns.

I'm a programmer noob, so I'm sure it's something simple that I'm missing.

Any help??
#180
07/04/2008 (4:32 pm)
Quote:I've got everything set up and compiled with no errors. However, when I go into the World Editor the iAIAgent category appears, along with the iAIAgent_soldier, iAIAgentDAta, and iAIAGent_Bandit. But when I click on the soldier, bandit or data, nothing happens. nothing appears, and nothing spawns.

As I don't have the whole immersiveAI implemented I can't help you with everything but for starters you could check the output of your console for any errors. You can see the console by pressing ~ when the mission is loaded. Just scroll it for any errors and post them back.

If there are no errors in your console try running your .exe (debug version) from console to see if it outputs any errors.

Greetings