How to create a new IPSA physics body

How to create a new SoPhysics subclass named SoPhysicsExample:

SoPhysicsExample.h
 #include "SoPhysics.h"
 #include <Inventor/fields/SoSFVec3f.h>
 #include <Inventor/SbString.h>

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

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

   static void initClass();

   SoSFVec3f dimension;
 protected:
   virtual dMass getInitialMass();
   virtual void updateDependentObjects();
 };

SoPhysicsExample.cpp

 #include "../include/SoPhysicsExample.h"

 #include <Inventor/SbLinear.h>

 #include <ode/ode.h>

 #include <cassert>

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

 // Initialises the class and it's type id variables.
 void SoPhysicsExample::initClass()
 {
   SO_KIT_INIT_CLASS(SoPhysicsExample, SoPhysics, "Physics");
 }

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

   // 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 shape to SoCube
   SO_KIT_CHANGE_ENTRY_TYPE(visualisationShape, SoNode, SoCube);
   // change the default type of the collision shape to SoCollisionShapeExample
   SO_KIT_CHANGE_ENTRY_TYPE(collisionShape, SoCollisionShape, SoCollisionShapeExample);

   // the visualisation shape is created by default
   SO_KIT_CHANGE_NULL_BY_DEFAULT(visualisationShape, FALSE);
   // the collision shape is created by default
   SO_KIT_CHANGE_NULL_BY_DEFAULT(collisionShape, FALSE);

   // set up the instance
   SO_KIT_INIT_INSTANCE();

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

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

 // method which calculates an inertia matrix and creates the ODE mass
 dMass SoPhysicsExample::getInitialMass()
 {
   // get the scaling parameter
   SbVec3f scaling = this->scale.getValue();

   // get the specified mass
   float specifiedMass = this->mass.getValue();

   // do the math ...
   // calculate the inertia matrix [[v1, v2, v3], [v4, v5, v6], [v7, v8, v9]]

   // create an ODE mass object and set the inertia matrix
   dMass mass;
   dMassSetParameters(&mass, specifiedMass, v1,v2,v3, v4,v5,v6, v7,v8,v9);

   return mass;
 }

 // method which updates the properties of the Physics visualisation and collision shape
 void SoPhysicsExample::updateDependentObjects()
 {
   // the dynamic_cast returns a NULL pointer if the cast fails
   const SbVec3f DIMENSION_VALUES = dimension.getValue();
   SoCollisionShapeBox* cShape = dynamic_cast<SoCollisionShapeBox*> (this->getPart("collisionShape", FALSE));
   if (NULL != cShape)
   {
     // WARNING: change of Geom for ODE-Collisioncheck
     // is not supported, only visualisation !!
     cShape->dimension.setValue(DIMENSION_VALUES);
   }

   SoCube* visShape = dynamic_cast<SoCube*> (this->getPart("visualisationShape", FALSE));
   if (NULL != visShape)
   {
     // The values are SoCube{ width, height, depth/length } in this order
     visShape->width.setValue(DIMENSION_VALUES[0]);
     visShape->height.setValue(DIMENSION_VALUES[1]);
     visShape->depth.setValue(DIMENSION_VALUES[2]);
   }
 }

Steps to take:

  1. Create a subclass of SoPhysics.
  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(SoPhysicsExample); 
    
  4. Afterwards implement the method
     SoPhysicsExample::initClass() { SO_KIT_INIT_CLASS(SoPhysicsExample, SoPhysics, "Physics"); } 
    
  5. Then implement the Constructor:
    1. Call
       SO_KIT_CONSTRUCTOR(SoPhysicsExample);
      
    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 field which should change the visualisation and collision shape call
       updateDependentObjectsTrigger.appendConnection(&parameterName); 
      
      This enables the SoPhysics class to automatically update the parameters of the visualisation and collision shape if parameterName changes 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 getIntialMass() which calculates the mass of the physics object and returns it.
  8. Implement the method updateDependentObjects() which updates the dependent collision and visualisation shape of the object.
  9. Add the line
     #include "SoPhysicsExample.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:
     SoPhysicsExample::initClass(); 
    

See the Physic Classes page for all physics classes existing in IPSA. Details on how to implement the different methods can be taken from the individual physics classes.
Also see How to create a new IPSA collision shape for completing the implementation with an appropriate collision shape class.


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