Page 1 of 1

problems bouncing ball

Posted: Tue Mar 02, 2004 4:51 am
by thesmileman
I know this is probibly a sad way to do this(if there is a better way,which I am sure there is let me know) thanks.

I am trying to get a fireball to change direction when it collides with anything. I was hoping Irrlicht had a onCollision() call but no dice. I already have generic collision detection working (aka ball hits wall and stops).

What I decided to do was to get the position of where my fireball should be (currentPosition+direction) and then update the position of the fireball with this new position. Then check the position after it has been updated and if this position is not the same as (position+direction) then collision has occured.

This did not work and I have tried several different ways of doing the above and I get the same result, (the fireball just goes back and forth in a small space in midair). It seems that when I change the direction it just changes right back. Here is my code:

*NOTE: ps4 is my fireball

Code: Select all

while(irrDevice->run()) { 
   //save position where ball should be
   newLocation = newLocation = ps4->getPosition()+direction;
   
   // move fireball
   ps4->setPosition(newLocation);
   
   //Do scenecrap
   irrDriver->beginScene(true,true,0);      
   irrSceneMgr->drawAll();
   irrDriver->endScene();

   //Check for collision
   if(newLocation != ps4->getPosition())
      direction.invert(); //collision detected so change direction
      // I know the above does not make the ball bounce but just to test this 
      // code I am seeing if I can send the ball back in the direction it came
}
I tried using the getResultPosition() but it did not change the direction of the ball just mad it slide across the object.

Thanks for any help!

Posted: Tue Mar 02, 2004 8:01 pm
by Mercior
My advice would be to manage the collision manually (excuse the variables, this is pasted from one of my projects):

Code: Select all


	newloc = world->smgr->getSceneCollisionManager()->getCollisionResultPosition(world->g_selector, 
	loc, vector3df(30,50,30), velocity,					// position, radius, move vector
	triout, outFalling, 0.0005f, vector3df(0, -10, 0));	// gravity

if (newloc != loc + velocity)
{
  // it collided.. invert the velocity vector or whatever :)
}

reflect

Posted: Tue Mar 02, 2004 10:02 pm
by schick
Maybe the vector template should have a reflect( vector<T> n) function. something like:

Code: Select all


reflect( n)
{
  normalize();		  
  n.normalize();
  return (v - n * 2.0 * (v.dotProduct( n))) * v.getLength();
}


Posted: Tue Mar 02, 2004 11:11 pm
by Phunk
I think that the col. det. that you want is too advanced for the irrlicht engine, what you described, that the ball just slides at the wall is the result of the col. det. in irrlicht, as it just looks at the pos that the ball has, and then modifies the vector to make it not go into the wall, and leaving the remaining values unchanged, thus causes sliding. can't you use the getResultPosition() to check if a collision is happening, and then the vector returned minus "your position" should be the normal of the wall that you will want to bounce against. then you can use the code that is submitted above to create the right reflection.

Posted: Wed Mar 03, 2004 2:48 am
by Guest
Schick, What is v in your reflect code above?

Posted: Wed Mar 03, 2004 2:55 am
by Guest
actually if you wouldn't mind could you explain your entine reflect code. Thanks

Aaarrrrrgggghhghh

Posted: Wed Mar 03, 2004 3:19 am
by thesmileman
Thanks guys for your help but I am still getting the same result: the ball justs bounces back and forth is a very small spot in midair. Here is my code if anyone can tell me whats wrong.

*note I do not want gravity.

Also what is the triout in the getCollisionResultPosition() and do I need it? The API says its optional but compiler will not accept function without something there.

Code: Select all

core::vector3df newLoc, oldLoc, velocity;
oldLoc = ps4->getPosition();
velocity = core::vector3df(-5,0,5);
bool outFalling = false;
core::triangle3df triout; 
	
while(irrDevice->run()) { 
   newLoc = irrSceneMgr->getSceneCollisionManager()->getCollisionResultPosition(metaSelector, 
            oldLoc, core::vector3df(6,6,6), velocity, triout, 
            outFalling, 0.5f,core::vector3df(0, 0, 0));		
   if (newLoc != oldLoc + velocity) 
      velocity.invert();

   ps4->setPosition(newLoc);
   oldLoc = newLoc;

   irrDriver->beginScene(true,true,0);      
   irrSceneMgr->drawAll();
   irrDriver->endScene();
}

Posted: Wed Mar 03, 2004 11:22 am
by Mercior
If its bouncing then the

Code: Select all

if (newLoc != oldLoc + velocity)
must always be true.. could be a prescision thing - try something like:

Code: Select all

if (newLoc.getDistanceFrom(oldLoc + velocity) > 1)

Posted: Wed Mar 03, 2004 12:51 pm
by schick
@Guest

"v is the vector of your velocity, n is supposed to be the normal of the plane you want to collide with"

@thesmileman

Code: Select all

      // temp variables
      triangle3d<f32> triout, triorg;
      bool isfalling = false;
 
      ISceneCollisionManager* collmgr = SceneManager->getSceneCollisionManager(); 

      setPosition( collmgr->getCollisionResultPosition( World,
                                                        getPosition(),
                                                        Radius,
                                                        Velocity,
                                                        triout,
                                                        isfalling,
                                                        0.0005f, // working
                                                        Gravity));

      if( triorg != triout)
        {		
          // well, we collided 
          vector3df v = Velocity.normalize();		  
          vector3df n = triout.getNormal().normalize();
          Velocity = (v - n * 2.0 * (v.dotProduct( n))) * v.getLength();
		  
        }
 
Well, that code is supposed to be in the OnPostRender() function of your scenenode.

WHHAAAAAAAAAAAAHOOOOOOOOOOOOO!!!!!!!!!!

Posted: Wed Mar 03, 2004 3:26 pm
by thesmileman
Sweet Mercior thanks for the help that worked great! Also thanks schick for the comparision of the triangle with the old triangle that also worked and I am using the later method.

Schick, is there any reason why after the first bounce the ball slows down? It only happens after the first bounce and the speed of the ball stays the same.

Also If anyone is trying to use Schicks code don't forget at the end of the code you must set the old triangle to the new triangle as such:

Code: Select all

triorg = triout;

ehmm

Posted: Wed Mar 03, 2004 3:43 pm
by schick
ok, need to check my math knowledge :-).

found the bug

Posted: Wed Mar 03, 2004 4:26 pm
by schick
Here we go, got the solution. Replace the one first mentioned with that one. That's it, what math is for :-).

Code: Select all

      if( triorg != triout)
        {		
          // well, we collided 
          vector3df n = triout.getNormal().normalize();
          Velocity = (Velocity - n * 2.0 * (Velocity.dotProduct( n))).normalize() * Velocity.getLength();
        }

Posted: Wed Mar 03, 2004 5:25 pm
by thesmileman
Sweet that worked. I had gotten around it by just multiplying the velocity by a speed vector which worked fine except for some reason, everyonce in a while the ball would bounce straight back as though I had used velocity.invert() but this code fixed it.

I really wished I had paid more attention in my Liner Algebra class as it would come in really handy with all the 3D programming.

Thanks again!