6.6. Creating a Simple Engine

The following examples illustrate the basic steps outlined in Section 6.1, “Overview”. Example 6-1 shows the header file for a simple engine, MultFloatVec3f, which multiplies a float value (SoSFFloat SoSFFloat SoSFFloat ) by a vector value (SoSFVec3f SoSFVec3f SoSFVec3f ) and produces an output of type SoSFVec3f SoSFVec3f SoSFVec3f . Example 6-2 shows the source file for this class.

[Tip]

The SoCalculator SoCalculator SoCalculator engine provides a built-in way of doing this type of simple arithmetic.

Example 6.1.  MultFloatVec3f.h

#include <Inventor/engines/SoSubEngine.h>
#include <Inventor/fields/SoSFFloat.h>
#include <Inventor/fields/SoSFVec3f.h>

class MultFloatVec3f : public SoEngine {

   SO_ENGINE_HEADER(MultFloatVec3f);

 public:

   // Input fields: a scalar (float) and a vector
   SoSFFloat       scalar;
   SoSFVec3f       vector;

   // The output is a vector
   SoEngineOutput  product;  // (SoSFVec3f) product

   // Initializes this class for use in scene graphs. This
   // should be called after database initialization and before
   // any instance of this engine is constructed.
   static void initClass();
   static void exitClass();

   // Constructor
   MultFloatVec3f();

 private:
   // Destructor. Since engines are never deleted explicitly,
   // this can be private.
   virtual ~MultFloatVec3f();

   // Evaluation method
   virtual void evaluate();
};

Example 6.2.  MultFloatVec3f.c++

#include "MultFloatVec3f.h"

SO_ENGINE_SOURCE(MultFloatVec3f);

// Initializes the MultFloatVec3f class. This is a one-time
// thing that is done after database initialization and before
// any instance of this class is constructed.

void
MultFloatVec3f::initClass()
{
   // Initialize type id variables. The arguments to the macro
   // are: the name of the engine class, the class this is
   // derived from, and the name registered with the type
   // of the parent class.
   SO_ENGINE_INIT_CLASS(MultFloatVec3f, SoEngine, "Engine");
}

void
MultFloatVec3f::exitClass()
{
   SO_ENGINE_EXIT_CLASS(MultFloatVec3f);
}
// Constructor

MultFloatVec3f::MultFloatVec3f()
{
   // Do standard constructor stuff
   SO_ENGINE_CONSTRUCTOR(MultFloatVec3f);

   // Define input fields and their default values
   SO_ENGINE_ADD_INPUT(scalar,  (0.0));
   SO_ENGINE_ADD_INPUT(vector,  (0.0, 0.0, 0.0));

   // Define the output, specifying its type
   SO_ENGINE_ADD_OUTPUT(product, SoSFVec3f);
}

// Destructor. Does nothing.

MultFloatVec3f::~MultFloatVec3f()
{
}

// This is the evaluation routine.

void
MultFloatVec3f::evaluate()
{
   // Compute the product of the input fields
   SbVec3f  prod = scalar.getValue() * vector.getValue();

   // "Send" the value to the output. In effect, we are setting
   // the value in all fields to which this output is connected.
   SO_ENGINE_OUTPUT(product, SoSFVec3f, setValue(prod));
}