#include <UT/UT_DSOVersion.h>
#include <GEO/GEO_PrimPart.h>
#include <GEO/GEO_Point.h>
#include <GU/GU_Detail.h>
#include <PRM/PRM_Include.h>
#include <OP/OP_Operator.h>
#include <OP/OP_OperatorTable.h>
#include "POP_RadialBirth.h"
using namespace HDK_Sample;
static PRM_Name names[] =
{
PRM_Name("center", "Center"),
PRM_Name("distance", "Distance"),
PRM_Name("speed", "Speed"),
PRM_Name("birthrate", "Birth Rate"),
PRM_Name("group", "Birth Group"),
PRM_Name(0)
};
static PRM_Range birthRange(PRM_RANGE_RESTRICTED, 0, PRM_RANGE_UI, 10);
static PRM_Default speedDefaults[] =
{
PRM_Default(0),
PRM_Default(1),
};
static PRM_Default distanceDefaults[] =
{
PRM_Default(0),
PRM_Default(1),
};
PRM_Template
POP_RadialBirth::myTemplateList[] =
{
PRM_Template(PRM_FLT_J, 1, &POPactivateName, PRMoneDefaults, 0,
&PRMunitRange),
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]),
PRM_Template(PRM_FLT_J, 1, &POPlifeName, &POPlifeDefault),
PRM_Template(PRM_FLT_J, 1, &POPlifevarName),
PRM_Template(PRM_INT_J, 1, &POPoriginindexName),
PRM_Template()
};
void
newPopOperator (OP_OperatorTable* table)
{
table->addOperator(
new OP_Operator("hdk_radialbirth",
"Radial Birth",
POP_RadialBirth::myConstructor,
POP_RadialBirth::myTemplateList,
0,
0,
0,
OP_FLAG_GENERATOR));
}
unsigned
POP_RadialBirth::disableParms (void)
{
return 0;
}
OP_Node*
POP_RadialBirth::myConstructor (OP_Network* net, const char* name,
OP_Operator* entry)
{
return new POP_RadialBirth(net, name, entry);
}
int *POP_RadialBirth::myIndirect = 0;
POP_RadialBirth::POP_RadialBirth (OP_Network* net, const char* name,
OP_Operator* entry)
:POP_Node (net, name, entry)
{
if (!myIndirect)
myIndirect = allocIndirect(sizeof(myTemplateList)/sizeof(PRM_Template));
myLife = 100;
myLifeVar = 0;
myOriginIndex = 0;
myCenter.assign(0, 0, 0);
mySpeedMin = 0;
mySpeedMax = 1;
}
POP_RadialBirth::~POP_RadialBirth (void)
{
}
OP_ERROR
POP_RadialBirth::cookPop (OP_Context& context)
{
POP_ContextData* data = (POP_ContextData*) context.getData();
float t = context.getTime();
GEO_PrimParticle* part;
GEO_ParticleVertex* pvtx;
UT_String birthName;
GB_PointGroup* birthGroup = NULL;
int born;
UT_Vector4 birthpos;
UT_Vector3 pos;
float distmin;
float distmax;
float tmp;
if (lockInputs(context) >= UT_ERROR_ABORT)
return(error());
part = data->getPrimPart(this);
initParticleList(context, part);
if (data->isGuideOnly())
goto done;
GROUP(birthName);
if (birthName.isstring())
{
forceValidGroupName(birthName, UT_ERROR_WARNING);
birthGroup = data->getDetail()->newPointGroup((const char*) birthName);
}
if (!checkActivation(data, (POP_FParam) &POP_RadialBirth::ACTIVATE))
goto done;
myLife = LIFE(t);
myLifeVar = LIFEVAR(t);
mySpeedMin = SPEEDMIN(t);
mySpeedMax = SPEEDMAX(t);
if (mySpeedMax < mySpeedMin)
{
tmp = mySpeedMin;
mySpeedMin = mySpeedMax;
mySpeedMax = tmp;
}
born = BIRTHRATE(t);
distmin = DISTANCEMIN(t);
distmax = DISTANCEMAX(t);
if (distmax < distmin)
{
tmp = distmin;
distmin = distmax;
distmax = tmp;
}
myOriginIndex = ORIGININDEX();
myCenter.assign(CENTERX(t), CENTERY(t), CENTERZ(t));
while (born > 0)
{
pos.assign(data->random() - 0.5f,
data->random() - 0.5f,
data->random() - 0.5f);
pos.normalize();
pos *= (distmin + data->random() * (distmax - distmin));
pos += myCenter;
birthpos = pos;
pvtx =
birthParticle(data, part, birthpos, NULL, NULL, NULL,
(POP_IntFunc) &POP_RadialBirth::getOriginIndex,
0, POP_ORIGIN_INDEX,
(POP_FloatFunc) &POP_RadialBirth::getLifetime,
(POP_BirthAttribFunc) &POP_RadialBirth::setAttrib);
if (!pvtx)
break;
if (birthGroup)
birthGroup->add(pvtx->getPt());
born--;
}
done:
unlockInputs();
return error();
}
float
POP_RadialBirth::getLifetime (POP_ContextData* data)
{
return myLife + 2.0f * (data->random() - 0.5f) * myLifeVar;
}
int
POP_RadialBirth::getOriginIndex (POP_ContextData* )
{
return myOriginIndex;
}
void
POP_RadialBirth::setAttrib (POP_ContextData* data, GEO_Point* ppt,
UT_Vector3* vel, void*)
{
*vel = ppt->getPos();
*vel -= myCenter;
vel->normalize();
*vel *= (mySpeedMin + data->random() * (mySpeedMax - mySpeedMin));
}
void
POP_RadialBirth::addAttrib (void* userdata)
{
POP_ContextData* data = (POP_ContextData*) userdata;
addOriginAttrib(data);
}