HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Creating a custom generator POP

Introduction

Generator POPs are similar to modifier POPs. Most of the concepts introduced in writing a modifier POP apply here with a few differences.

Differences from modifier POPs

An example of a generator POP (.h / .C) can be found in the toolkit samples. Only the important differences will be examined.

POP_RadialBirth::myTemplateList[] =
{
PRM_Template(PRM_XYZ_J, 3, &names[0]),
PRM_Template(PRM_FLT_J, 2, &names[1], distanceDefaults),
PRM_Template(PRM_FLT_J, 2, &names[2], speedDefaults),
PRM_Template(PRM_INT_J, 1, &names[3], PRMfourDefaults, 0, &birthRange),
PRM_Template(PRM_STRING, 1, &names[4]),
};

The source group used in modifier POPs represents a subset of particles to apply the operation on. This concept doesn't really apply when birthing particles, so generator POPs don't require a source group. The activation field still applies.

void
{
table->addOperator(
new OP_Operator("hdk_radialbirth", // Name
"Radial Birth", // English
POP_RadialBirth::myConstructor, // "Constructor"
POP_RadialBirth::myTemplateList, // simple parms
0, // MinSources
0, // MaxSources
0, // variable pair
OP_FLAG_GENERATOR)); // op flags
}

Note that the OP_FLAG_GENERATOR flag must be set to tell the operator table that this POP is a generator.

POP_RadialBirth::POP_RadialBirth (OP_Network* net, const char* name,
OP_Operator* entry)
:POP_Node (net, name, entry)

When birthing new particles, it doesn't make sense to have local variables that represent the particle's attributes. It's the classic chicken and the egg problem. It's not possible to define particle attributes based on local variables because the attributes have no value yet. So, it makes no sense to derive from the POP_LocalVar class. Generator POPs should derive from POP_Node directly, or from POP_GenVar.

part = data->getPrimPart(this);
initParticleList(context, part);

Each generator creates a new particle system, or in Houdini geometry terms, its own particle primitive. POP_Node::myParticleList should contain a list of particle primitives that the POP processes. For modifier POPs, this list is generated from the input wires using POP_Node::buildParticleList(). Generator POPs will want to initialize the list with the primitive is creates. POP_ContextData::getPrimPart(POP_Node *) returns the primitive associated with this generator. The call will create a new primitive if one doesn't exist yet. The POP_Node::initParticleList() call initializes the list with the newly created primitive.

birthParticle(data, part, birthpos, NULL, NULL, NULL,
(POP_IntFunc) &POP_RadialBirth::getOriginIndex,
(POP_FloatFunc) &POP_RadialBirth::getLifetime,
(POP_BirthAttribFunc) &POP_RadialBirth::setAttrib);

POP_Node::birthParticle() is used to birth particles into the particle primitive. This method will birth a particle at a specific location, allow the new particle to inherit attributes, and set some of the particle's initial attributes like the origin and lifetime.

Summary

This example demonstrated the general structure of a generator POP. It covered the following topics: