Page 1 of 1

Collisions, how to update...

Posted: Thu Feb 07, 2013 11:57 pm
by LJS
When iterating over the manifolds, how can a collision object know about a collision. I mean, I wrap both, the visual objects and the physical objects, into one class so they 'stay together'. If an btCollisionObject has collided with a wall, how can I let the wrapping class now to stop moving?

example:

Code: Select all

class cWrappingClass : public btMotionState
                     , public btActionInterface
{
public:
  get/set world transform{...}
  updateAction(...){...}
protected:
  btCollisionObject* m_colObj;
  btCollisionShape*  m_shape;
  VisualMesh*        m_mesh;
}

Re: Collisions, how to update...

Posted: Fri Feb 08, 2013 2:15 pm
by MaxDZ8
You'll need some extra mangling besides behaviors enabled by those two interfaces.
After iterating the manifolds you must signal them to your gameplay object so it can react. Those are sometimes called "touch" events and they are often gameplay-dependent so be prepared to use a virtual function and implement some logic. The exact syntax will depend on the object as well as you might want to trigger a function in certain conditions instead of others... mind elaborating on your needs?

Re: Collisions, how to update...

Posted: Sat Feb 09, 2013 1:47 am
by LJS
Problem X: Create some objects that will stay static, walk, run, fall, swim, fly, drive or whatever thoughout a scenery. Kind off basic.

Problem Y:
in this case: btCollisionObject == btRigidBody due to their relationship and readabillity of the text.

As I tend to generalize everything I do too in this case. My intention is to get some callback firing the cWrappingClass so I could create a callBackCollisionStart/End structure.

When going over the manifold I only have access to only btCollisionObject and giving me the hassle of iterating over a vector<cWrappingClass> after that to find a particulare collisionobject. This can't be right.

Maybe it would be a better idea to inherit from btCollisionObject so I can get access to cWrappingClass.

Think I completly miss the point of the structure in bullet. I am ...wachamacallit... stuck.

Propably I am missing a callback which I could implement at cWrappingClass level.



Regards,

Re: Collisions, how to update...

Posted: Sat Feb 09, 2013 8:26 am
by MaxDZ8
LJS wrote:Problem X: Create some objects that will stay static, walk, run, fall, swim, fly, drive or whatever thoughout a scenery. Kind off basic.
Actually, kinematic objects are hard. I have spent weeks, if not months on my kinematic controller and it still does not get its things right. Consider the action "fly".
- not applicable to humans
- actually applicable to humans with a jetpack
- but only if the jetpack has fuel
"jetpack" and "fuel" are gameplay-dependant concept and "fuel" in particular is also dependant on state of a specific object. Ouch.
Consider the action "swim"
- actually needs to perform collision testing against a static object
- eventually needs to collide with a procedurally generated ocean mesh.
Consider "drive"
- use the provided kinematic controller. I have been told it works right.

So, elaborate on your specific needs.
LJS wrote: Problem Y:
When going over the manifold I only have access to only btCollisionObject and giving me the hassle of iterating over a vector<cWrappingClass> after that to find a particulare collisionobject. This can't be right.
I'm afraid there's no "right" thing to do either. How could you do that?
btCollisionObject* is used because it can point to all objects instantiated from derived classes. btCollisionObject is the "core" class used by Bullet collision (without rigid dynamics). It is therefore very handy to pool btCollisionObject* for processing.
If you take a look at the source code, you will see that adding a btRigidBody to the world actually pools it by calling addCollisionObject. The specific type information is therefore lost and there's no way to recover it (from bullet collision components).

I have no idea of what your cWrappingClass is supposed to do, actually I cannot quite understand what you mean with the words "iterating over a vector<cWrappingClass> after that to find a particulare collisionobject". What particular object? Have you considered std::find_if? What about std::map<btCollisionObject*, ...>?
LJS wrote:Maybe it would be a better idea to inherit from btCollisionObject so I can get access to cWrappingClass.
Implement what, from which base class... to do what? Getting access from where? From overriden function implementation I guess?

As a side note, while C++ does not allow non-overridable functions, you don't want to put an override in performance-critical paths. I actually don't think you're going to have callback this easily. I guess it would be possible to do something similar by overriding btCollisionObject::needsCollision, but I don't really suggest to do that.

Re: Collisions, how to update...

Posted: Sat Feb 09, 2013 12:06 pm
by LJS
A jetpack is very simple. As I tend to generalize everything - which is the core of OOP or c++ wouldn't have existed - I've taken the liberty to use a jetpack.

Code: Select all

class cWrappingClass; /* ...same functionality but skipping some 'inbetween'-classes c.q. abstract classes... */
class cJetpack : public cWrappingClass
{
  cChar* m_owner
  void setOwner(cChar* owner){...}
  void startFlying()
  {
    if( m_fuell <= 0 || !m_worn )
      return;
    ...fire up...and so take controls of m_owner;
  }
}
class  cChar : public cWrappingClass
{
  cJetpack* m_jetpack;
  ...
  void updateAction() // inherits from btActionInterface
  {
    if( KeyDown( FLY ) )
        if( m_jetpack )
           jetpack->startFlying();
    }
  }
}
A humanoid is just the same as a car, plane or whatever. A jetpack could be a bicycle. They move and boom they hit something, i.e. collision detected. Then they can't move or will destruct whatever they bumped into.

My specific need is: for instance (generalize stuff) the humanoid starts flying up 2 metres then it bumps into a ceiling (can be the inside of a plane, doesn't matter). How to prevend moving.

My specific need is: for instance (generalize stuff) the car (worn by cChar, see topmost snippet) starts riding and then it bumps into a plane which has landed. How to prevend moving, start crashing, catch fire.

Am not talking about overriding anything but how to access the class which is responsible for the memory obA uses.

Code: Select all

>>> PSEUDO-LIKE-CODE <<<
class cWrappingClass : public btActionInterface, public btMotionState
{
  OnCollisionStart(){}
  OnCollisionEnd(){}
  cWrappingClass()
  {
    cPhysicsManager* phworld = cPhysicsManager::getSingleton();
    phworld->addCollisionObject( m_collisionObject );
  }
}

class MainThreadClass
{
  void initialize()
  {
     // create descendants of cWrappingClass
     addSceneObject( new cHumanoid(...) );
     addSceneObject( new cHumanoid(...) );
     addSceneObject( new cCar(...) );
     addSceneObject( new cPlane(...) );
     addSceneObject( new cFish(...) );
     addSceneObject( new cHouse(...) );
     addSceneObject( new cHouse(...) );
     addSceneObject( new cHouse(...) );
     addSceneObject( new cStreet(...) );
     addSceneObject( new cAnotherBuilding(...) );
     addSceneObject( new cPlayer(...) );
  }
}

class cPhysicsManager
{
  void update( Ogre::Real deltaTime )
  {
  
    // atm: m_dynamicsWorld is an btDiscreteDynamicsWorld*
    m_dynamicsWorld->stepSimulation( deltaTime );

    int numManifolds = m_dynamicsWorld->getDispatcher()->getNumManifolds();
    for( int i = 0; i < numManifolds; ++i )
    {

      btPersistentManifold* contactManifold =  m_dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
      btCollisionObject* obA = (btCollisionObject*)contactManifold->getBody0();
      btCollisionObject* obB = (btCollisionObject*)contactManifold->getBody1();
  
      // as obA's allocated memory is a member of cWrappingClass, i.e. cWrappingClass::m_collisionObject, how can I access that cWrappingClass's instance in a gracefull manner
      iterate over all cWrappingClasses
        if iter->CollObj() == obA
         call iter->OnCollisionStart(); // this I want, iter is of type cWrappingClass
         // also I want [b]somewhere[/b] iter->OnCollisionEnd();
    
    }

  }

}

#ifdef _DEBUG
  if( m_debugDrawer )
    m_debugDrawer->Update();
#endif

}
As said, I am new at bullet and I am stuck. (Ever tried to stand up while wrapped in a net, I feel foolish where I learned c++ without any forum or book, i.e. profesional noob. Have learned English by coding alone but still I feel foolish. I know, my english isn't all that, my apologies).



Regards,

Re: Collisions, how to update...

Posted: Sat Feb 09, 2013 2:30 pm
by MaxDZ8
LJS wrote:A jetpack is very simple. As I tend to generalize everything - which is the core of OOP or c++ wouldn't have existed - I've taken the liberty to use a jetpack.
Since you claim to be a beginner, I'm being bold and self-declare myself the veteran here.
You're falling victim to over-approximation.
The core of OOP is not to generalize everything. It is to generalize when it makes sense providing you the tools to do so. And there are a few reasons for which this should not happen, such as the fact you're thinking at a generic kinematic controller (low level abstraction), but tied to a very specific gameplay concept (high level abstraction). If you think this is OOP I'm afraid we give two different meanings to the word. Personally I was introduced to OOP when it meant "functions are written near the data they mangle".
A humanoid is just the same as a car, plane or whatever. A jetpack could be a bicycle. They move and boom they hit something, i.e. collision detected. Then they can't move or will destruct whatever they bumped into.
No. A car needs its own internal simulation for kinematics, many articles have been written about that. I've never seen a bicycle explode in reality. A humanoid is absolutely NOT the same as a car.
Again, you can go with overgeneralization as much as you want. Ring me when you get the job done.

There's no "for instance" in game design. There are the requirements, the functionalities you need to make your game work and the functionalities you need to get the job done without losing your mental sanity.
Anything else is not supposed to be there.
Anyway...

Code: Select all

class cPhysicsManager
{
  void update( Ogre::Real deltaTime )
  {
  
    // atm: m_dynamicsWorld is an btDiscreteDynamicsWorld*
    m_dynamicsWorld->stepSimulation( deltaTime );

    int numManifolds = m_dynamicsWorld->getDispatcher()->getNumManifolds();
    // note you were doing it the other way around: you were looking for a matching wrapper class for each pointer
    // returned by manifolds. It is probably easier to it the other way around as you have to keep those objects somewhere.
    cWrappingClass *interesting = ...; // or loop on a collection.
    interesting->wasTouching = interesting.currentlyTouching; // fully copy for readability
    interesting->currentlyTouching.clear();
    for( int i = 0; i < numManifolds; ++i )
    {

      btPersistentManifold* contactManifold =  m_dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
      btCollisionObject* obA = (btCollisionObject*)contactManifold->getBody0();
      btCollisionObject* obB = (btCollisionObject*)contactManifold->getBody1();
      if(interesting != obA && interesting != obB) continue;
      btCollisionObject *other = obA == interesting? obB : obA;
      // also remember to reject based on bidirectional distance. It takes some care...
      interesting->currentlyTouching.push_back(other); // or maybe push more data. or maybe use std::set.    
    }
  }
  interesting->NotifyCollisionEnd(); // for each pointer in wasTouching which is not in currentlyTouching send a message
  interesting->NotifyCollisionBegin(); // for each pointer in currentlyTouching which is not in wasTouching, send a message.
}
My specific need is: for instance (generalize stuff) the humanoid starts flying up 2 metres then it bumps into a ceiling (can be the inside of a plane, doesn't matter). How to prevend moving.
When collision occurs, the manifold shows up in the manifold pool (eventually local to a btGhostObject). If a manifold involves touching or encroaching, send a "Touch" event to the kinematic controller. This is the only thing that in general makes sense.

Code: Select all

class FlyingMan : public cWrappingClass {
  bool canMove;
  void OnCollisionBegin() { canMove = false; }
  void updateAction(...) {
    if(canMove) { ... }
  }
};
Actually, nobody would likely do that, until you want the collided object to be sticky: you probably just need to check your sweeps (because you are sweeping them don't you?).
My specific need is: for instance (generalize stuff) the car (worn by cChar, see topmost snippet) starts riding and then it bumps into a plane which has landed. How to prevend moving, start crashing, catch fire.
Kinematic controller reaction to "touch" event is to hide current mesh and spawn a particle system "fire".

Code: Select all

class BoomBoomCar : public cWrappingClass {
  ...
  void OnCollisionBegin() {
    graphicsMesh.FadeOut(1.0f); // say this blends to alpha=0 in 1 second, in the meanwhile...
    ParticleSystem *ps = particleManager.NewSystemFromResource("Fire.ps.settings"); // "particle system setting resource", texture to use, how to animate...
    ps->SetOrigin(graphicsMesh.getNamedPoint("joint_explosion");
    ps->Active(true);
    this->MarkForRigidBodyRemoval(); // nobody really wants to call this->dtor on the go
    this->ps = ps; // say we keep ownership of it...
  }
};
Of course for a lot of objects it would be far better to use btGhostObject instead of using the global pool but for a start we go that way.

Is it starting to be make sense?