00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <UT/UT_DSOVersion.h>
00029 #include <GEO/GEO_PrimPart.h>
00030 #include <GEO/GEO_Point.h>
00031 #include <GU/GU_Detail.h>
00032 #include <PRM/PRM_Include.h>
00033 #include <OP/OP_Operator.h>
00034 #include <OP/OP_OperatorTable.h>
00035 #include "POP_RadialBirth.h"
00036
00037 using namespace HDK_Sample;
00038
00039
00040
00041 static PRM_Name names[] =
00042 {
00043 PRM_Name("center", "Center"),
00044 PRM_Name("distance", "Distance"),
00045 PRM_Name("speed", "Speed"),
00046 PRM_Name("birthrate", "Birth Rate"),
00047 PRM_Name("group", "Birth Group"),
00048 PRM_Name(0)
00049 };
00050
00051 static PRM_Range birthRange(PRM_RANGE_RESTRICTED, 0, PRM_RANGE_UI, 10);
00052
00053 static PRM_Default speedDefaults[] =
00054 {
00055 PRM_Default(0),
00056 PRM_Default(1),
00057 };
00058
00059 static PRM_Default distanceDefaults[] =
00060 {
00061 PRM_Default(0),
00062 PRM_Default(1),
00063 };
00064
00065 PRM_Template
00066 POP_RadialBirth::myTemplateList[] =
00067 {
00068 PRM_Template(PRM_FLT_J, 1, &POPactivateName, PRMoneDefaults, 0,
00069 &PRMunitRange),
00070 PRM_Template(PRM_XYZ_J, 3, &names[0]),
00071 PRM_Template(PRM_FLT_J, 2, &names[1], distanceDefaults),
00072 PRM_Template(PRM_FLT_J, 2, &names[2], speedDefaults),
00073 PRM_Template(PRM_INT_J, 1, &names[3], PRMfourDefaults, 0, &birthRange),
00074 PRM_Template(PRM_STRING, 1, &names[4]),
00075 PRM_Template(PRM_FLT_J, 1, &POPlifeName, &POPlifeDefault),
00076 PRM_Template(PRM_FLT_J, 1, &POPlifevarName),
00077 PRM_Template(PRM_INT_J, 1, &POPoriginindexName),
00078 PRM_Template()
00079 };
00080
00081
00082
00083 void
00084 newPopOperator (OP_OperatorTable* table)
00085 {
00086 table->addOperator(
00087 new OP_Operator("hdk_radialbirth",
00088 "Radial Birth",
00089 POP_RadialBirth::myConstructor,
00090 POP_RadialBirth::myTemplateList,
00091 0,
00092 0,
00093 0,
00094 OP_FLAG_GENERATOR));
00095 }
00096
00097
00098
00099 unsigned
00100 POP_RadialBirth::disableParms (void)
00101 {
00102 return 0;
00103 }
00104
00105 OP_Node*
00106 POP_RadialBirth::myConstructor (OP_Network* net, const char* name,
00107 OP_Operator* entry)
00108 {
00109 return new POP_RadialBirth(net, name, entry);
00110 }
00111
00112 int *POP_RadialBirth::myIndirect = 0;
00113
00114 POP_RadialBirth::POP_RadialBirth (OP_Network* net, const char* name,
00115 OP_Operator* entry)
00116 :POP_Node (net, name, entry)
00117 {
00118 if (!myIndirect)
00119 myIndirect = allocIndirect(sizeof(myTemplateList)/sizeof(PRM_Template));
00120
00121 myLife = 100;
00122 myLifeVar = 0;
00123 myOriginIndex = 0;
00124 myCenter.assign(0, 0, 0);
00125 mySpeedMin = 0;
00126 mySpeedMax = 1;
00127 }
00128
00129 POP_RadialBirth::~POP_RadialBirth (void)
00130 {
00131 }
00132
00133 OP_ERROR
00134 POP_RadialBirth::cookPop (OP_Context& context)
00135 {
00136 POP_ContextData* data = (POP_ContextData*) context.getData();
00137 float t = context.myTime;
00138 GEO_PrimParticle* part;
00139 GEO_ParticleVertex* pvtx;
00140 UT_String birthName;
00141 GB_PointGroup* birthGroup = NULL;
00142 int born;
00143 UT_Vector4 birthpos;
00144 UT_Vector3 pos;
00145 float distmin;
00146 float distmax;
00147 float tmp;
00148
00149
00150 if (lockInputs(context) >= UT_ERROR_ABORT)
00151 return(error());
00152
00153
00154
00155
00156
00157
00158 part = data->getPrimPart(this);
00159 initParticleList(context, part);
00160
00161
00162
00163 if (data->isGuideOnly())
00164 goto done;
00165
00166
00167 GROUP(birthName);
00168 if (birthName.isstring())
00169 birthGroup = data->getDetail()->newPointGroup((const char*) birthName);
00170
00171
00172 if (!checkActivation(data, (POP_FParam) &POP_RadialBirth::ACTIVATE))
00173 goto done;
00174
00175
00176 myLife = LIFE(t);
00177 myLifeVar = LIFEVAR(t);
00178 mySpeedMin = SPEEDMIN(t);
00179 mySpeedMax = SPEEDMAX(t);
00180 if (mySpeedMax < mySpeedMin)
00181 {
00182 tmp = mySpeedMin;
00183 mySpeedMin = mySpeedMax;
00184 mySpeedMax = tmp;
00185 }
00186
00187 born = BIRTHRATE(t);
00188 distmin = DISTANCEMIN(t);
00189 distmax = DISTANCEMAX(t);
00190 if (distmax < distmin)
00191 {
00192 tmp = distmin;
00193 distmin = distmax;
00194 distmax = tmp;
00195 }
00196 myOriginIndex = ORIGININDEX();
00197 myCenter.assign(CENTERX(t), CENTERY(t), CENTERZ(t));
00198
00199
00200 while (born > 0)
00201 {
00202
00203
00204 pos.assign(data->random() - 0.5f,
00205 data->random() - 0.5f,
00206 data->random() - 0.5f);
00207 pos.normalize();
00208 pos *= (distmin + data->random() * (distmax - distmin));
00209 pos += myCenter;
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 birthpos = pos;
00220 pvtx =
00221 birthParticle(data, part, birthpos, NULL, NULL, NULL,
00222 (POP_IntFunc) &POP_RadialBirth::getOriginIndex,
00223 0, POP_ORIGIN_INDEX,
00224 (POP_FloatFunc) &POP_RadialBirth::getLifetime,
00225 (POP_BirthAttribFunc) &POP_RadialBirth::setAttrib);
00226 if (!pvtx)
00227 break;
00228
00229 if (birthGroup)
00230 birthGroup->add(pvtx->getPt());
00231
00232 born--;
00233 }
00234
00235 done:
00236
00237 unlockInputs();
00238
00239 return error();
00240 }
00241
00242 float
00243 POP_RadialBirth::getLifetime (POP_ContextData* data)
00244 {
00245 return myLife + 2.0f * (data->random() - 0.5f) * myLifeVar;
00246 }
00247
00248 int
00249 POP_RadialBirth::getOriginIndex (POP_ContextData* )
00250 {
00251 return myOriginIndex;
00252 }
00253
00254 void
00255 POP_RadialBirth::setAttrib (POP_ContextData* data, GEO_Point* ppt,
00256 UT_Vector3* vel, void*)
00257 {
00258
00259 *vel = ppt->getPos();
00260 *vel -= myCenter;
00261 vel->normalize();
00262 *vel *= (mySpeedMin + data->random() * (mySpeedMax - mySpeedMin));
00263 }
00264
00265 void
00266 POP_RadialBirth::addAttrib (void* userdata)
00267 {
00268 POP_ContextData* data = (POP_ContextData*) userdata;
00269
00270
00271 addOriginAttrib(data);
00272 }