running processes outside rendering loop

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Asteroth
Posts: 11
Joined: Tue Feb 13, 2007 2:33 am

running processes outside rendering loop

Post by Asteroth »

I'm using Irrlicht to create a virtual world for testing AI algorithms, such as teaching a robot to walk around a maze picking up objects and avoiding walls/obstacles.

The rendering process is quite CPU intensive, but not necessary for the robots behaviour, just so I can see what it's doing! Because of this I'd like to be able to have to robot explore even when the window is inactive. I need to to be able to do collision detection, getAbsolutePosition(), getRotation(), getCollisionPoint() etc, but outside the rendering loop.

Anyway, my question is, would something like the following be ok:

Code: Select all

 while(device->run()) 
 {
    robot movement code, collision detection etc...

    //only render window if active
    if (device->isWindowActive()) 
    {
       driver->beginScene(true, true, video::SColor(0,200,200,200));
       smgr->drawAll();
       driver->endScene();
    }
 }
I've done a few tests but get some odd results. I'm new to graphics and rendering engines and not very familiar with their structure, but I'm assuming all the things I'd be doing outside the rendering loop would only involve the scenegraph?

Thanks in advance.
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

this should be fine... ;)

if you have many robots and/or they do much calculation you should split he work...
I mean something linke this:

Code: Select all

int idRobotNow = -1; // for 1st = 0
while(device->run())
 {
    idRobotNow = (idRobotNow + 1) % countRobots;
    robot movement code for idRobotNow, collision detection etc...

    //only render window if active
    if (device->isWindowActive())
    {
       driver->beginScene(true, true, video::SColor(0,200,200,200));
       smgr->drawAll();
       driver->endScene();
    }
 }
or you can make a seperate function for the rendering and call it from the robots themselves...
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
Asteroth
Posts: 11
Joined: Tue Feb 13, 2007 2:33 am

Post by Asteroth »

thats great, thanks! I haven't looked into multiple robots yet, but your idea would be useful once/if I get to that stage :)
Asteroth
Posts: 11
Joined: Tue Feb 13, 2007 2:33 am

Post by Asteroth »

ok, been working on this a bit for a while... It all seems to work fine apart from when I try and switch back to the screen after leaving it running for a few seconds. My robot jumps at this point, and usually thows an error because of this.

I suspect this is something to do with the translation/transformation matrices being re-calculated when the OnPostRender function is called. If these aren't being updated outside of the rendering process then this might be the cause. This is only a guess however and I'm not familiar enough with the process to be certain.

any ideas?
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Asteroth wrote:when I try and switch back to the screen after leaving it running for a few seconds.
What do you mean ???
Do you have something like a menu screen you're switching to, or do you leave the complete window (for example with Alt-Tab) ???
What does your main (rendering) loop look like (maybe post your main loop) ???
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
Asteroth
Posts: 11
Joined: Tue Feb 13, 2007 2:33 am

Post by Asteroth »

apologies, I'll try and be a bit more explicit.

The jump occurs when I Alt-Tab back and forth between the window, and likewise when I minimise and then maximise. Both have the same effect as far as I'm aware.

My main rendering loop looks like...

Code: Select all

 while(device->run()) 
 {
    
   //render only when window active
   if (device->isWindowActive()) 
   {
     driver->beginScene(true, true, video::SColor(0,200,200,200));
    
     if(robotActive)
       robot->process(); //move robot around in the world
    
     smgr->drawAll();
     driver->endScene();
   }
    
   //if window inactive, but robot active, process as usual
   else if(robotActive)
     robot->process(); //move robot around in the world

   // otherwise sleep to free up CPU cycles
   else
     Sleep(30);
 }
the robotActive is a trigger so I can turn the robots movement routine on and off.

the function robot->process() makes calls to the scene manager, collision manager and driver to get information about the world i.e. distance from nearest wall. It then moves the robot in one of 3 ways, described by the function doAction(int a)

(by the way RobotClass is derived from the SceneNode class in the same way as descibed in the tutorial for Custom SceneNodes)

Code: Select all

void RobotClass::doAction(int a) 
{
  
  // STEP 1: rotate robot about axis
  core::vector3df rot = this->getRotation();
  
  switch(a) {
  
  case 0: //do nothing
    break;
  case 1: //rotate left 15 degrees
    rot.Y-=15;
    this->setRotation(rot);
    break;
  case 2: //rotate right 15 degrees 
    rot.Y+=15;
    this->setRotation(rot);
    break;
  }

  //STEP 2: move robot forward by 2 points
  core::vector3df pos(sqrt(2.0),0,sqrt(2.0)); //XZ vector length of 2   
  core::matrix4 mat; 
  mat.setRotationDegrees(this->getRotation());
  mat.transformVect(pos); //pos now faces the direction of the robot
  pos+=this->getPosition();
  this->setPosition(pos); //move avatar to pos
  this->updateAbsolutePosition(); //is this necessary?
}
I don't know if its relevant, but I overloaded the render() function to draw 2 lines showing the robots field of view

Code: Select all

void RobotClass::render()
{
  robotModel->render(); //robotModel is a child animated scenenode, that  represents the robot in the world.

  //draw field of view lines
  driver->setTransform(video::ETS_WORLD, core::matrix4());
  driver->draw3DLine(getAbsolutePosition(),leftLine,video::SColor(0,255,0,0));
  driver->draw3DLine(getAbsolutePosition(),rightLine,video::SColor(0,255,0,0));
}
Hope that makes things a bit clearer.

Basically so long as the window is active the robot moves fine. Obviously I can't tell if it's working okay when the window is minimised, but as soon as I alt-tab back to look, the robot jumps!

I think this is to do with the absoluteTransformation matrix not being updated/set correctly outside my rendering loop, but I can't pin-point the problem!

Thanks in advance - this has really got me stumped! :?
Asteroth
Posts: 11
Joined: Tue Feb 13, 2007 2:33 am

Post by Asteroth »

ps. the reason I included the robot->process() function twice (once inside and once outside the rendering loop) is because some of the routines draw lines i.e. when the robot spots an object it draws a line to it to indicate it has found it.
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Hmmm, one problem I see is with calling the robot process when the window is not active: the draw functions have to be between beginScene and endScene, but this is not the case at this point in your code...
But this should not explain the jumping...
Otherwise the code seems to be OK...

I hadn't had a look at the source of Irrlicht's event receiver, but it could be that it's also disabled if the window is not active (can someone else confirm this ???)...
If so this will probably lead to collision faults if you update something when the window isn't active...
Maybe you should pause everything if the window isn't active ???
AFAIR every game I played pauses then...
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
Post Reply