|
Houdini Development Toolkit - Version 6.5
Side Effects Software Inc. 2004
|
General Operators
Local Variables
Each OP can have local variables which are defined over the scope of
its cook (i.e. active when the cook method has been called). These
variables are defined in the OP_Operator constructor (which defines
the operator). Currently all variables must be floating point valued
(i.e. no vectors or strings).
The OP_Operator constructor takes an array of CH_LocalVariable's.
This class simply contains a string (representing the variable name)
and a unique integer (used for evaluation). So, for example, to
define 4 local variables for an operator, we might have the following
code:
// First, lets get a bunch of uniqe integers
enum {
VAR_PT, // Current point
VAR_NPT, // Total number of points
VAR_ID, // Particle ID
VAR_LIFE, // Life time
};
// Next, we define our local variable table
CH_LocalVariable
OP_MyNode::myVariables[] = {
{ "PT", VAR_PT },
{ "NPT", VAR_NPT },
{ "ID", VAR_ID },
{ "LIFE", VAR_LIFE },
{ 0 } // End the table with a null entry
};
During evaluation of the parameters of the OP, these variables become
"active". If the variable is found in an expression, the
getVariableValue callback will be invoked. It is your
responsibility to return a value for the variable in question. For
example, in the above example:
float
OP_MyNode::getVariableValue(int index)
{
GEO_Point *ppt;
int *id;
float *life;
if (myCurrPoint < 0) // Sorry, we're in an invalid state
return 0;
switch (index)
{
case VAR_PT: return myCurrPoint;
case VAR_NPT: return myTotalPoints;
case VAR_ID:
ppt = myInputGeo->points()(myCurrPoint);
id = (int *)ppt->getAttribData(myInputIdOffset);
return (float)*id;
case VAR_LIFE:
ppt = myInputGeo->points()(myCurrPoint);
life = (float *)ppt->getAttribData(myInputLifeOffset);
return life[0]/life[1];
}
return 0; // Whoops, forgot a variable
}
The code for cooking might look something like:
OP_ERROR
OP_MyNode::cookMe(OP_Context &context)
{
...
// First, let's set up the member data we'll need for
// evaluation of variables.
myInputGeo = input(0, context.myTime);
myInputIdOffset = myInputGeo->findPointAttrib("id",
sizeof(int), GEO_ATTRIB_INT);
myInputLifeOffset = myInputGeo->findPointAttrib("life",
sizeof(float)*2, GEO_ATTRIB_FLOAT);
myTotalPoints = myInputGeo->points().entries();
// Now, we loop through each point, doing expression
// evaluation INSIDE the loop.
for (myCurrPoint = 0; myCurrPoint < myTotalPoints; myCurrPoint++)
{
// In the POS() method, it's possible that the expression
// would use one of our local variables, so
pos.x() = POSX(context.myTime);
...
}
myCurrPoint = -1; // Make sure to flag that we're in a
// bad state
...
}
The reason for setting the flag myCurrPoint to -1 outside of
the loop is that occasionally, it is possible for your
getVariableValue method to be called out of context. The reason for
this is complicated, but it has to do with displaying the values of
the parameters in the dialog boxes (i.e. the parameters need to be
evaluated, but the OP isn't being cooked). In this case, it's
try to return a reasonable value.
Table of Contents
Operators |
Surface Operations |
Particle Operations |
Composite Operators |
Channel Operators
Material & Texture |
Objects |
Command and Expression |
Render Output |
Mantra Shaders |
Utility Classes |
Geometry Library |
Image Library |
Clip Library
Customizing UI |
Questions & Answers
Copyright © 2004 Side Effects Software Inc.
477 Richmond Street West, Toronto, Ontario, Canada M5V 3E7