How to create a new IPSA collision shape

How to create a new SoCollisionShape subclass named SoCollisionShapeExample:

SoCollisionShapeExample.h
 #include "SoCollisionShape.h"
 #include <Inventor/fields/SoSFVec3f.h>
 #include <Inventor/SbString.h>

 class SoCollisionShapeExample : public SoCollisionShape
 {
 SO_KIT_HEADER(SoCollisionShapeExample);  // set up the necessary information for the headerfile

 public:
   SoCollisionShapeExample(const SbString& nodeName = "");
   virtual ~SoCollisionShapeExample();

   static void initClass();

   SoSFVec3f dimension;
 protected:
   virtual dGeomID cGeom(const SbMatrix& mm);
   virtual void updateVisualisationAndOdeProperties();
 };

SoCollisionShapeExample.cpp

 #include "../include/SoCollisionShapeExample.h"

 #include <Inventor/SbLinear.h>

 #include <ode/ode.h>

 #include <cassert>

 SO_KIT_SOURCE(SoCollisionShapeExample);  // set up the necessary information for the implementation file

 // Initialises the class and it's type id variables.
 void SoCollisionShapeExample::initClass()
 {
   SO_KIT_INIT_CLASS(SoCollisionShapeExample, SoCollisionShape, "CollisionShape");
 }

 // set up the class structure
 SoCollisionShapeExample::SoCollisionShapeExample(const SbString& nodeName = "")
 : SoCollisionShape(nodeName)
 {
   // define the Coin constructor
   SO_KIT_CONSTRUCTOR(SoCollisionShapeExample);

   // only write necessary member fields to files and not more
   isBuiltIn = TRUE;

   // define the field variables
   SO_KIT_ADD_FIELD(dimension, (2.0, 0.0, 1.0));

   // change the default type of the visualisation object to SoCube
   SO_KIT_CHANGE_ENTRY_TYPE(visualisation, SoCube, SoCube);

   // the visualisation is created by default
   SO_KIT_CHANGE_NULL_BY_DEFAULT(visualisation, FALSE);

   // set up the instance
   SO_KIT_INIT_INSTANCE();

   // monitor property fields for changes to automatically update the visualisation shape and ODE parameters
   updateOdePropertiesTrigger.appendConnection(&dimension);
 }

 SoCollisionShapeExample::~SoCollisionShapeExample()
 {
   // release objects created with new
 }

 // method which creates the ODE geom (also known as collision shape)
 dGeomID SoCollisionShapeExample::cGeom(const SbMatrix& mm)
 {
   // check if the shape is associated with a collision space
   assert(NULL != this->space);

   // create a box geom as example
   const SbVec3f dim = this->dimension.getValue();
   return dCreateBox(this->space, dim[0], dim[1], dim[2]);
 }

 // method which updates the ODE properties and the visualisation of the collisionshape
 void SoCollisionShapeExample::updateVisualisationAndOdeProperties()
 {
   // retrieve the dimension vector
   const SbVec3f dim = this->dimension.getValue();

   // retrieve the geom ID
   const dGeomID boxID = this->geometry;

   // set the new property values on the ODE object
   if (NULL != boxID)
     dGeomBoxSetLengths(boxID, dim[0], dim[1], dim[2]);

   // change the property values of the visualisation if one is present
   SoCube* visualisationShape = dynamic_cast<SoCube*> (getPart("visualisation", TRUE));
   if (NULL != visualisationShape)
   {
     visualisationShape->width.setValue(dim[0]);
     visualisationShape->height.setValue(dim[1]);
     visualisationShape->depth.setValue(dim[2]);
   }
 }

Steps to take:

  1. Create a subclass of SoCollisionShape.
  2. Add additional members to the declaration in the header file if necessary (like dimension).
  3. The first entry in the cpp file must be the call:
     SO_KIT_SOURCE(SoCollisionShapeExample); 
    
  4. Afterwards implement the method
     SoCollisionShapeExample::initClass() { SO_KIT_INIT_CLASS(SoCollisionShapeExample, SoCollisionShape, "CollisionShape"); } 
    
  5. Then implement the Constructor:
    1. Call
       SO_KIT_CONSTRUCTOR(SoCollisionShapeExample);
      
    2. Set
       isBuiltin = TRUE; 
      
    3. Add any field with:
       SO_KIT_ADD_FIELD(fieldname,(defaultvalue)); 
      
    4. If necessary change the default visualisation shape with:
       SO_KIT_CHANGE_ENTRY_TYPE(visualisation,SoCube,SoCube); 
      
    5. If the visualisation shape should be created immediately change this with:
       SO_KIT_CHANGE_NULL_BY_DEFAULT(visualisation, FALSE); 
      
    6. To initialise the class call
       SO_KIT_INIT_INSTANCE(); 
      
    7. For each ODE related property call
       updateOdePropertiesTrigger.appendConnection(&odeParameterName); 
      
      This enables the SoCollisionShape class to automatically update the ODE parameters in the engine and the visualisation shape if they change in the class.
  6. Override the destructor if objects where allocated in the constructor and need to be destroyed. Otherwise leave it out of the header file and don't implement it.
  7. Implement the method cGeom() which creates the ODE collision shape object and returns its ID.
  8. Implement the method updateVisualisationAndOdeProperties() which updates the ODE parameters and reshapes the visualisation shape.
  9. Add the line
     #include "SoCollisionShapeExample.h" 
    
    into the file
    $(IPSA_HOME)/include/ipsaclasses.h 
    .
  10. The last thing to do is to register the initialisation method in the global initialisation routine. This is done by adding one line to SoWorldPhysics::initClasses(). In the example the line would looke like this:
     SoCollisionShapeExample::initClass(); 
    

See the CollisionShape classes page for all collision shape classes existing in IPSA. Details on how to implement the different methods can be taken from the individual collision shape classes.


Get IPSA - Inventor Physics Simulation API at SourceForge.net. Fast, secure and Free Open Source software downloads
Generated on Sat Mar 10 20:00:17 2012 for IPSA by  doxygen 1.5.8