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 <UT/UT_Matrix3.h>
00030 #include <UT/UT_Defines.h>
00031 #include <GEO/GEO_PrimPart.h>
00032 #include <GEO/GEO_Point.h>
00033 #include <GU/GU_Detail.h>
00034 #include <GU/GU_PrimTube.h>
00035 #include <PRM/PRM_Include.h>
00036 #include <OP/OP_Operator.h>
00037 #include <OP/OP_OperatorTable.h>
00038 #include "POP_LocalForce.h"
00039
00040 using namespace HDK_Sample;
00041
00042
00043
00044 static PRM_Name names[] =
00045 {
00046 PRM_Name("origin", "Origin"),
00047 PRM_Name("dir", "Direction"),
00048 PRM_Name("radius", "Radius"),
00049 PRM_Name("length", "Length"),
00050 PRM_Name("strength", "Strength"),
00051 PRM_Name(0),
00052 };
00053
00054 PRM_Range lengthRange(PRM_RANGE_RESTRICTED, 0.001, PRM_RANGE_UI, 5);
00055
00056 static PRM_Default dirDefaults[] =
00057 {
00058 PRM_Default(0), PRM_Default(0), PRM_Default(1)
00059 };
00060
00061 PRM_Template
00062 POP_LocalForce::myTemplateList[] =
00063 {
00064 PRM_Template(PRM_FLT_J, 1, &POPactivateName, PRMoneDefaults, 0,
00065 &PRMunitRange),
00066 PRM_Template(PRM_STRING, 1, &POPsourceName, 0,
00067 &POP_Node::pointGroupMenu),
00068 PRM_Template(PRM_XYZ_J, 3, &names[0]),
00069 PRM_Template(PRM_DIRECTION, 3, &names[1], dirDefaults),
00070 PRM_Template(PRM_FLT_J, 1, &names[2], PRMoneDefaults),
00071 PRM_Template(PRM_FLT_J, 1, &names[3], PRMoneDefaults, 0, &lengthRange),
00072 PRM_Template(PRM_FLT_J, 1, &names[4], PRMoneDefaults),
00073 PRM_Template(PRM_TOGGLE, 1, &POPignoremassName),
00074 PRM_Template(PRM_TOGGLE, 1, &POPoverridemassName),
00075 PRM_Template(PRM_FLT_J, 1, &POPmassName, PRMoneDefaults, 0,
00076 &POPmassRange),
00077
00078 PRM_Template()
00079 };
00080
00081 OP_TemplatePair
00082 POP_LocalForce::myTemplatePair (myTemplateList, &POP_LocalVar::myTemplatePair);
00083
00084 OP_VariablePair
00085 POP_LocalForce::myVariablePair (0, &POP_LocalVar::myVariablePair);
00086
00087
00088
00089 void
00090 newPopOperator (OP_OperatorTable* table)
00091 {
00092 table->addOperator(
00093 new OP_Operator("localforce",
00094 "LocalForce",
00095 POP_LocalForce::myConstructor,
00096 &POP_LocalForce::myTemplatePair,
00097 1,
00098 1,
00099 &POP_LocalForce::myVariablePair));
00100 }
00101
00102
00103
00104 unsigned
00105 POP_LocalForce::disableParms (void)
00106 {
00107 unsigned changed = 0;
00108 int ignoremass = IGNOREMASS();
00109 int overridemass = OVERRIDEMASS();
00110
00111
00112 changed += enableParm("mass", overridemass && !ignoremass);
00113 changed += enableParm("overridemass", !ignoremass);
00114
00115 return changed;
00116 }
00117
00118 OP_Node*
00119 POP_LocalForce::myConstructor (OP_Network* net, const char* name,
00120 OP_Operator* entry)
00121 {
00122 return new POP_LocalForce(net, name, entry);
00123 }
00124
00125 int *POP_LocalForce::myIndirect = 0;
00126
00127 POP_LocalForce::POP_LocalForce (OP_Network* net, const char* name,
00128 OP_Operator* entry)
00129 :POP_LocalVar (net, name, entry)
00130 {
00131 if (!myIndirect)
00132 myIndirect = allocIndirect(sizeof(myTemplateList)/sizeof(PRM_Template));
00133
00134
00135 setTemplate(1);
00136
00137
00138
00139
00140
00141
00142 myGuide = new POP_Guide;
00143 myGuideHandle.allocateAndSet(myGuide);
00144 }
00145
00146 POP_LocalForce::~POP_LocalForce (void)
00147 {
00148 }
00149
00150 OP_ERROR
00151 POP_LocalForce::cookPop (OP_Context &context)
00152 {
00153 float t = context.myTime;
00154 int thread = context.getThread();
00155 POP_ContextData* data = (POP_ContextData*) context.getData();
00156 GEO_PrimParticle* part;
00157 GEO_ParticleVertex* pvtx;
00158 UT_Matrix4 xform;
00159 UT_Vector3 origin;
00160 UT_Vector3 dir;
00161 float radius;
00162 float length;
00163 POP_FParam strength;
00164 POP_FParam mass;
00165 int massOffset;
00166 UT_String sourceName;
00167 const GB_PointGroup *sourceGroup = NULL;
00168 GU_PrimTubeParms parms;
00169 GU_CapOptions caps;
00170 UT_Interrupt* boss = UTgetInterrupt();
00171
00172
00173
00174 if (doUpdateViewport(data))
00175 {
00176 data->appendGuide(this, myGuideHandle);
00177 }
00178
00179 if (lockInputs(context) >= UT_ERROR_ABORT)
00180 return(error());
00181
00182 setupDynamicVars(data);
00183
00184
00185 if (buildParticleList(context) >= UT_ERROR_ABORT)
00186 goto done;
00187
00188
00189
00190
00191 allowVar(0);
00192 origin.assign(ORIGINX(t), ORIGINY(t), ORIGINZ(t));
00193 dir.assign(DIRX(t), DIRY(t), DIRZ(t));
00194 dir.normalize();
00195 radius = RADIUS(t);
00196 radius = UTabs(radius);
00197 length = LENGTH(t);
00198 allowVar(1);
00199
00200
00201
00202
00203 if (doUpdateViewport(data))
00204 {
00205 parms.taper = 1.0f;
00206 buildQuadricXform(parms.xform, 0, 0, length / 2,
00207 radius, radius, length, 'x');
00208 xform.instance(origin, dir, 1.0,
00209 0, 0, 0, 0, 0);
00210 parms.xform *= xform;
00211 parms.gdp = myGuide;
00212 GU_PrimTube::build(parms, caps, GEOPRIMTUBE);
00213 }
00214
00215
00216 if (!checkActivation(data, (POP_FParam) &POP_LocalForce::ACTIVATE))
00217 goto done;
00218
00219
00220 SOURCE(sourceName);
00221 if (sourceName.isstring())
00222 {
00223 sourceGroup = parsePointGroups((const char*) sourceName,
00224 data->getDetail());
00225 if (!sourceGroup)
00226 {
00227 addError(POP_BAD_GROUP, sourceName);
00228 goto done;
00229 }
00230 }
00231
00232
00233 setupVars(data, sourceGroup);
00234
00235
00236
00237
00238 POP_FCACHE(strength, STRENGTH, getStrength, myStrength, POP_LocalForce);
00239
00240 if (OVERRIDEMASS())
00241 {
00242
00243
00244 massOffset = -1;
00245 POP_FCACHE(mass, MASS, getMass, myMass, POP_LocalForce);
00246 }
00247 else
00248 {
00249
00250
00251
00252 massOffset = data->getMassOffset();
00253 if (massOffset < 0)
00254 {
00255 myMass = 1.0f;
00256 mass = (POP_FParam) &POP_LocalForce::getMass;
00257 }
00258 }
00259
00260 if (IGNOREMASS())
00261 {
00262
00263
00264 massOffset = -1;
00265 myMass = 1.0f;
00266 mass = (POP_FParam) &POP_LocalForce::getMass;
00267 }
00268
00269 if (boss->opInterrupt())
00270 goto done;
00271
00272 if (error() >= UT_ERROR_ABORT)
00273 goto done;
00274
00275
00276
00277
00278 myCurrIter = 0;
00279
00280
00281
00282 if (sourceGroup)
00283 {
00284 FOR_ALL_GROUP_POINTS(data->getDetail(), sourceGroup, myCurrPt)
00285 {
00286 changePoint(myCurrPt, data, t, origin, dir, radius, length,
00287 strength, massOffset, mass);
00288 myCurrIter++;
00289 }
00290 }
00291 else
00292 {
00293
00294
00295 for (part = myParticleList.iterateInit() ;
00296 part ; part = myParticleList.iterateNext())
00297 {
00298 if (boss->opInterrupt())
00299 goto done;
00300
00301 for (pvtx = part->iterateInit() ; pvtx ; pvtx = pvtx->next)
00302 {
00303 myCurrPt = pvtx->getPt();
00304 changePoint(myCurrPt, data, t, origin, dir, radius, length,
00305 strength, massOffset, mass);
00306 myCurrIter++;
00307 }
00308 }
00309 }
00310
00311 done:
00312
00313 cleanupDynamicVars();
00314
00315 unlockInputs();
00316
00317
00318 myCurrPt = NULL;
00319
00320 return error();
00321 }
00322
00323 void
00324 POP_LocalForce::changePoint (GEO_Point* ppt, POP_ContextData* data, float t,
00325 const UT_Vector3& origin, const UT_Vector3& dir,
00326 float radius, float length,
00327 POP_FParam strength,
00328 int massOffset, POP_FParam mass)
00329 {
00330 int* state;
00331 UT_Vector3* accel;
00332 UT_Vector3 D;
00333 float s;
00334 float m;
00335 float dist;
00336
00337
00338 state = ppt->castAttribData<int>(data->getStateOffset());
00339
00340
00341 if ((*state & PART_STATE_STOPPED) || (*state & PART_STATE_DYING))
00342 return;
00343
00344
00345
00346 if (massOffset >= 0)
00347 m = *( ppt->castAttribData<float>(massOffset));
00348 else
00349 m = POP_PEVAL(mass);
00350
00351
00352 D = ppt->getPos();
00353 D -= origin;
00354 dist = D.normalize();
00355
00356
00357
00358
00359 t = dot(D, dir);
00360 if (t < 0 || t * dist > length)
00361 return;
00362
00363
00364 D *= dist;
00365 D -= dir * t;
00366
00367
00368 if (D.length() < radius)
00369 {
00370 accel = ppt->castAttribData<UT_Vector3>(data->getAccelOffset());
00371
00372
00373
00374
00375 s = POP_PEVAL(strength);
00376
00377
00378 if (UTequalZero(m))
00379 m = 0.01;
00380
00381 s /= m;
00382
00383 if (!data->isGuideOnly())
00384 {
00385
00386
00387
00388 accel->x() += dir.x() * s;
00389 accel->y() += dir.y() * s;
00390 accel->z() += dir.z() * s;
00391 }
00392
00393 if (doUpdateViewport(data))
00394 addAccelGuide(ppt, dir.x() * s, dir.y() * s, dir.z() * s,
00395 data->myTimeInc);
00396 }
00397 }