bool PFOperatorForceSpaceWarp::updateFromMXSForces() { if (theHold.RestoreOrRedoing()) return false; return UpdateFromMXSRefObjects(pblock(), kForceSpaceWarp_ForceNodeList, kForceSpaceWarp_ForcesMaxscript, gUpdateForcesInProgress, this); }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFAction | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //+--------------------------------------------------------------------------+ //| From IPFAction | //+--------------------------------------------------------------------------+ int PFTestScale::GetRand() { return pblock()->GetInt(kScaleTest_randomSeed); }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFTest | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ bool PFTestScale::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator, BitArray& testResult, Tab<float>& testTime) { bool exactStep = IsExactIntegrationStep(timeEnd, pSystem); // get the constant properties of the test int testType = pblock()->GetInt(kScaleTest_testType, timeEnd); int axisType = pblock()->GetInt(kScaleTest_axisType, timeEnd); int condType = pblock()->GetInt(kScaleTest_conditionType, timeEnd); int syncType = pblock()->GetInt(kScaleTest_sync, timeEnd); ParamID varParamID = (testType == kScaleTest_testType_scale) ? kScaleTest_scaleVariation : kScaleTest_sizeVariation; bool hasTestVariation = (pblock()->GetFloat(varParamID, 0) != 0.0f); if (!hasTestVariation) { Control* ctrl = pblock()->GetControllerByID(varParamID); if (ctrl != NULL) hasTestVariation = (ctrl->IsAnimated() != 0); } // get channel container interface IChannelContainer* chCont; chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; // acquire absolutely necessary particle channels IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if (chAmount == NULL) return false; // can't find number of particles in the container int count = chAmount->Count(); if (count == 0) return true; // no particles to test IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if (chTime == NULL) return false; // can't read timing info for a particle IParticleChannelNewR* chNew = GetParticleChannelNewRInterface(pCont); if (chNew == NULL) return false; // can't find newly entered particles for duration calculation // acquire more particle channels IParticleChannelPTVR* chBirthTime = NULL; if (syncType == kScaleTest_sync_age) { chBirthTime = GetParticleChannelBirthTimeRInterface(pCont); if (chBirthTime == NULL) return false; // can't read particle age } IParticleChannelPTVR* chEventStartR = NULL; IParticleChannelPTVW* chEventStartW = NULL; bool initEventStart = false; if (syncType == kScaleTest_sync_event) { chEventStartR = (IParticleChannelPTVR*)chCont->EnsureInterface(PARTICLECHANNELEVENTSTARTR_INTERFACE, ParticleChannelPTV_Class_ID, true, PARTICLECHANNELEVENTSTARTR_INTERFACE, PARTICLECHANNELEVENTSTARTW_INTERFACE, false, actionNode, NULL, &initEventStart); if (chEventStartR == NULL) return false; // can't read event start time if (initEventStart) { chEventStartW = GetParticleChannelEventStartWInterface(pCont); if (chEventStartW == NULL) return false; // can't write event start time } } IParticleChannelMeshR* chShape = NULL; if (testType != kScaleTest_testType_scale) { chShape = GetParticleChannelShapeRInterface(pCont); if (chShape == NULL) return false; // can't read particle shape to find bounding box } IParticleChannelPoint3R* chScale = NULL; if (testType != kScaleTest_testType_preSize) { chScale = GetParticleChannelScaleRInterface(pCont); if (chScale == NULL) return false; // can't read particle scale } IParticleChannelFloatR* chRandFloatR = NULL; IParticleChannelFloatW* chRandFloatW = NULL; bool initRandFloat = false; if (hasTestVariation) { chRandFloatW = (IParticleChannelFloatW*)chCont->EnsureInterface(PARTICLECHANNELRANDFLOATW_INTERFACE, ParticleChannelFloat_Class_ID, true, PARTICLECHANNELRANDFLOATR_INTERFACE, PARTICLECHANNELRANDFLOATW_INTERFACE, true, actionNode, (Object*)this, &initRandFloat); chRandFloatR = (IParticleChannelFloatR*)chCont->GetPrivateInterface(PARTICLECHANNELRANDFLOATR_INTERFACE, (Object*)this); if ((chRandFloatR == NULL) || (chRandFloatW == NULL)) return false; // can't set rand float value for newly entered particles } // grab the rand generator for test variation RandGenerator* randGen = randLinker().GetRandGenerator(pCont); if (randGen == NULL) return false; // check all particles testResult.SetSize(count); testResult.ClearAll(); testTime.SetCount(count); for(int i=0; i<count; i++) { if (chNew->IsNew(i)) { // initialize some channels if (initEventStart) chEventStartW->SetValue(i, chTime->GetValue(i)); if (initRandFloat) chRandFloatW->SetValue(i, randGen->Rand11()); } PreciseTimeValue syncTime = chTime->GetValue(i); switch(syncType) { case kScaleTest_sync_age: syncTime -= chBirthTime->GetValue(i); break; case kScaleTest_sync_event: syncTime -= chEventStartR->GetValue(i); break; } TimeValue syncTimeTV = TimeValue(syncTime); float testValue = 0.0f; if (testType == kScaleTest_testType_scale) { testValue = GetPFFloat(pblock(), kScaleTest_scaleValue, syncTimeTV); if (hasTestVariation) testValue += chRandFloatR->GetValue(i)*GetPFFloat(pblock(), kScaleTest_scaleVariation, syncTimeTV); } else { testValue = GetPFFloat(pblock(), kScaleTest_sizeValue, syncTimeTV); if (hasTestVariation) testValue += chRandFloatR->GetValue(i)*GetPFFloat(pblock(), kScaleTest_sizeVariation, syncTimeTV); } Point3 cur3DValue; if (testType == kScaleTest_testType_scale) { cur3DValue = chScale->GetValue(i); } else { Mesh* curMesh = const_cast <Mesh*>(chShape->GetValue(i)); if (curMesh == NULL) continue; Box3 curBox = curMesh->getBoundingBox(); cur3DValue = curBox.pmax - curBox.pmin; if (testType == kScaleTest_testType_postSize) cur3DValue *= chScale->GetValue(i); } float currentValue = 0.0f; switch(axisType) { case kScaleTest_axisType_average: currentValue = (cur3DValue.x + cur3DValue.y + cur3DValue.z)/3.0f; break; case kScaleTest_axisType_minimum: currentValue = min(cur3DValue.x, min(cur3DValue.y, cur3DValue.z)); break; case kScaleTest_axisType_median: currentValue = max(min(cur3DValue.x, cur3DValue.y), max(min(cur3DValue.x, cur3DValue.z), min(cur3DValue.y, cur3DValue.z))); break; case kScaleTest_axisType_maximum: currentValue = max(cur3DValue.x, max(cur3DValue.y, cur3DValue.z)); break; case kScaleTest_axisType_x: currentValue = cur3DValue.x; break; case kScaleTest_axisType_y: currentValue = cur3DValue.y; break; case kScaleTest_axisType_z: currentValue = cur3DValue.z; break; } bool testSatisfied = (condType == kScaleTest_conditionType_less) ? (currentValue < testValue) : (currentValue > testValue); if (testSatisfied && exactStep) { testResult.Set(i); testTime[i] = 0.0f; } } return true; }
bool PFTestGoToRotation::doPostProceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator) { if (pblock() == NULL) return false; IChannelContainer* chCont; chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; // acquire absolutely necessary particle channels IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if (chAmount == NULL) return false; // can't find number of particles in the container int i, count = chAmount->Count(); if (count == 0) return true; // no particles to modify IParticleChannelQuatR* chOrientR = GetParticleChannelOrientationRInterface(pCont); if (chOrientR == NULL) return false; // can't read current orientation for a particle IParticleChannelQuatW* chOrientW = GetParticleChannelOrientationWInterface(pCont); if (chOrientW == NULL) return false; // can't modify current orientation for a particle IParticleChannelAngAxisR* chSpinR = GetParticleChannelSpinRInterface(pCont); if (chSpinR == NULL) return false; // can't read current spin for a particle IParticleChannelAngAxisW* chSpinW = GetParticleChannelSpinWInterface(pCont); if (chSpinW == NULL) return false; // can't modify current spin for a particle // acquire private channels IParticleChannelPTVR* chStartTime = (IParticleChannelPTVR*)(chCont->GetPrivateInterface(PARTICLECHANNELSTARTTIMER_INTERFACE, (Object*)this)); if (chStartTime == NULL) return false; IParticleChannelPTVR* chEndTime = (IParticleChannelPTVR*)(chCont->GetPrivateInterface(PARTICLECHANNELENDTIMER_INTERFACE, (Object*)this)); if (chEndTime == NULL) return false; IParticleChannelPTVR* chProceedTime = (IParticleChannelPTVR*)(chCont->GetPrivateInterface(PARTICLECHANNELPROCEEDTIMER_INTERFACE, (Object*)this)); if (chProceedTime == NULL) return false; int targetType = pblock()->GetInt(kGoToRotation_targetType, timeEnd); bool initOnce = (targetType == kGoToRotation_targetType_constant); IParticleChannelBoolR* chGotInitR = (IParticleChannelBoolR*)(chCont->GetPrivateInterface(PARTICLECHANNELGOTINITR_INTERFACE, (Object*)this)); IParticleChannelBoolW* chGotInitW = (IParticleChannelBoolW*)(chCont->GetPrivateInterface(PARTICLECHANNELGOTINITW_INTERFACE, (Object*)this)); if ((chGotInitR == NULL) || (chGotInitW == NULL)) return false; IParticleChannelQuatR* chStartRot = (IParticleChannelQuatR*)(chCont->GetPrivateInterface(PARTICLECHANNELSTARTROTR_INTERFACE, (Object*)this)); if (chStartRot == NULL) return false; IParticleChannelQuatR* chEndRotR = (IParticleChannelQuatR*)(chCont->GetPrivateInterface(PARTICLECHANNELENDROTR_INTERFACE, (Object*)this)); if (chEndRotR == NULL) return false; IParticleChannelQuatW* chEndRotW = (IParticleChannelQuatW*)(chCont->GetPrivateInterface(PARTICLECHANNELENDROTW_INTERFACE, (Object*)this)); if (chEndRotW == NULL) return false; IParticleChannelAngAxisR* chStartSpin = (IParticleChannelAngAxisR*)(chCont->GetPrivateInterface(PARTICLECHANNELSTARTSPINR_INTERFACE, (Object*)this)); if (chStartSpin == NULL) return false; IParticleChannelFloatR* chEndSpin = (IParticleChannelFloatR*)(chCont->GetPrivateInterface(PARTICLECHANNELENDSPINR_INTERFACE, (Object*)this)); if (chEndSpin == NULL) return false; float easyIn = GetPFFloat(pblock(), kGoToRotation_easeIn, timeEnd.TimeValue() ); // particle properties modification for(i=0; i<count; i++) { // if the particle out of the transition period then do nothing PreciseTimeValue startT = chStartTime->GetValue(i); PreciseTimeValue endT = chEndTime->GetValue(i); if (endT < timeEnd) continue; if (endT <= startT) continue; // rollback the current rotation: remove the effect of the integration to know the real orientation value // need that if not initialized, or the target rotation is changing Quat curOrient = chOrientR->GetValue(i); bool needRollback = true; if (initOnce) if (chGotInitR->GetValue(i)) needRollback = false; if (needRollback) { AngAxis curSpin = chSpinR->GetValue(i); float timeDif = float(timeEnd - chProceedTime->GetValue(i)); curSpin.angle *= -timeDif; curOrient += Quat(curSpin); } if (initOnce) { if (!chGotInitR->GetValue(i)) { chEndRotW->SetValue(i, curOrient); } } else { chEndRotW->SetValue(i, curOrient); } chGotInitW->SetValue(i, true); Quat resRot; AngAxis resSpin; InterpolateRotation(chStartRot->GetValue(i), chEndRotR->GetValue(i), chStartSpin->GetValue(i), chEndSpin->GetValue(i), startT, endT, timeEnd, easyIn, initOnce, resRot, resSpin); chOrientW->SetValue(i, resRot); chSpinW->SetValue(i, resSpin); } return true; }
bool PFOperatorSimpleSpeed::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator) { // acquire all necessary channels, create additional if needed IParticleChannelNewR* chNew = GetParticleChannelNewRInterface(pCont); if(chNew == NULL) return false; IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if(chTime == NULL) return false; IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if(chAmount == NULL) return false; // the position channel may not be present. For some option configurations it is okay IParticleChannelPoint3R* chPos = GetParticleChannelPositionRInterface(pCont); int iDir = _pblock()->GetInt(kSimpleSpeed_direction, timeStart); if ((chPos == NULL) && ((iDir == kSS_Icon_Center_Out) || (iDir == kSS_Icon_Arrow_Out))) return false; IChannelContainer* chCont; chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; // the channel of interest bool initSpeed = false; IParticleChannelPoint3W* chSpeed = (IParticleChannelPoint3W*)chCont->EnsureInterface(PARTICLECHANNELSPEEDW_INTERFACE, ParticleChannelPoint3_Class_ID, true, PARTICLECHANNELSPEEDR_INTERFACE, PARTICLECHANNELSPEEDW_INTERFACE, true, actionNode, (Object*)NULL, &initSpeed); IParticleChannelPoint3R* chSpeedR = GetParticleChannelSpeedRInterface(pCont); if ((chSpeed == NULL) || (chSpeedR == NULL)) return false; // there are no new particles if (chNew->IsAllOld()) return true; float fUPFScale = 1.0f/TIME_TICKSPERSEC; // conversion units per seconds to units per tick Point3 pt3SpeedVec; RandGenerator* prg = randLinker().GetRandGenerator(pCont); int iQuant = chAmount->Count(); bool wasIgnoringEmitterTMChange = IsIgnoringEmitterTMChange(); if (!wasIgnoringEmitterTMChange) SetIgnoreEmitterTMChange(); for(int i = 0; i < iQuant; i++) { if(chNew->IsNew(i)) { // apply only to new particles TimeValue tv = chTime->GetValue(i).TimeValue(); Matrix3 nodeTM = pNode->GetObjectTM(tv); float fSpeedParam = fUPFScale * GetPFFloat(pblock(), kSimpleSpeed_speed, tv); // change speed in user selected direction switch(iDir) { case kSS_Along_Icon_Arrow: { // icon arrow appears to be in the negative z direction pt3SpeedVec = -Normalize(nodeTM.GetRow(2)); } break; case kSS_Icon_Center_Out: { Point3 pt3IconCenter = nodeTM.GetTrans(); Point3 pt3PartPos = chPos->GetValue(i); pt3SpeedVec = Normalize(pt3PartPos - pt3IconCenter); } break; case kSS_Icon_Arrow_Out: { Point3 pt3PartPos = chPos->GetValue(i); Point3 pt3ArrowVec = nodeTM.GetRow(2); Point3 pt3Tmp = CrossProd(pt3PartPos - nodeTM.GetTrans(), pt3ArrowVec); pt3SpeedVec = Normalize(CrossProd(pt3ArrowVec, pt3Tmp)); } break; case kSS_Rand_3D: { pt3SpeedVec = RandSphereSurface(prg); } break; case kSS_Rand_Horiz: { float fAng = TWOPI * prg->Rand01(); // establish x, y coordinates of random angle, z component zero float x = cos(fAng); float y = sin(fAng); float z = 0.0f; pt3SpeedVec = Point3(x, y, z); } break; case kSS_Inherit_Prev: { if (initSpeed) pt3SpeedVec = Point3::Origin; else pt3SpeedVec = Normalize(chSpeedR->GetValue(i)); } break; } // account for reverse check box int iRev = _pblock()->GetInt(kSimpleSpeed_reverse, 0); float fDirMult = iRev > 0 ? -1.f : 1.f; // calculate variation float fVar = fUPFScale * GetPFFloat(pblock(), kSimpleSpeed_variation, tv); if(fVar > 0.f) fSpeedParam = fSpeedParam + fVar * prg->Rand11(); pt3SpeedVec = fDirMult * fSpeedParam * pt3SpeedVec; // calculate divergence float fDiv = GetPFFloat(pblock(), kSimpleSpeed_divergence, tv); pt3SpeedVec = DivergeVectorRandom(pt3SpeedVec, prg, fDiv); chSpeed->SetValue(i, pt3SpeedVec); } } if (!wasIgnoringEmitterTMChange) ClearIgnoreEmitterTMChange(); return true; }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From ReferenceMaker | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ RefTargetHandle PFTestGoToRotation::GetReference(int i) { if (i==0) return (RefTargetHandle)pblock(); return NULL; }
//+--------------------------------------------------------------------------+ //| From IPFAction | //+--------------------------------------------------------------------------+ void PFTestGoToRotation::SetRand(int seed) { pblock()->SetValue(kGoToRotation_randomSeed, 0, seed); }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFTest | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ bool PFTestDuration::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator, BitArray& testResult, Tab<float>& testTime) { TimeValue proceedTime = timeStart; int testType = pblock()->GetInt(kDuration_testType, proceedTime); int disparity = pblock()->GetInt(kDuration_disparity, proceedTime); // get channel container interface IChannelContainer* chCont; chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; // acquire absolutely necessary particle channels IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if (chAmount == NULL) return false; // can't find number of particles in the container IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if (chTime == NULL) return false; // can't read timing info for a particle IParticleChannelNewR* chNew = GetParticleChannelNewRInterface(pCont); if (chNew == NULL) return false; // can't find newly entered particles for duration calculation // acquire more particle channels IParticleChannelPTVR* chBirthTime = NULL; if (testType == kDuration_testType_age) { chBirthTime = GetParticleChannelBirthTimeRInterface(pCont); if (chBirthTime == NULL) return false; // can't read particle age } IParticleChannelIDR* chID = NULL; if (disparity != 0) { chID = GetParticleChannelIDRInterface(pCont); if (chID == NULL) return false; // can't read particle index for first-to-last disparity } IParticleChannelPTVR* chEventStartR = NULL; IParticleChannelPTVW* chEventStartW = NULL; bool initEventStart = false; if (testType == kDuration_testType_event) { chEventStartR = (IParticleChannelPTVR*)chCont->EnsureInterface(PARTICLECHANNELEVENTSTARTR_INTERFACE, ParticleChannelPTV_Class_ID, true, PARTICLECHANNELEVENTSTARTR_INTERFACE, PARTICLECHANNELEVENTSTARTW_INTERFACE, false, actionNode, NULL, &initEventStart); if (chEventStartR == NULL) return false; // can't read event start time if (initEventStart) { chEventStartW = GetParticleChannelEventStartWInterface(pCont); if (chEventStartW == NULL) return false; // can't write event start time } } // acquire TestDuration private particle channel; if not present then create it IParticleChannelPTVW* chTestW = (IParticleChannelPTVW*)chCont->EnsureInterface(PARTICLECHANNELTESTDURATIONW_INTERFACE, ParticleChannelPTV_Class_ID, true, PARTICLECHANNELTESTDURATIONR_INTERFACE, PARTICLECHANNELTESTDURATIONW_INTERFACE, false, actionNode, (Object*)this); IParticleChannelPTVR* chTestR = (IParticleChannelPTVR*)chCont->GetPrivateInterface(PARTICLECHANNELTESTDURATIONR_INTERFACE, (Object*)this); if ((chTestR == NULL) || (chTestW == NULL)) return false; // can't set test value for newly entered particles int i, count; PreciseTimeValue curTestValue; count = chAmount->Count(); // check if all particles are "old". If some particles are "new" then we // have to calculate test values for those. if (!chNew->IsAllOld()) { TimeValue testValue = pblock()->GetTimeValue(kDuration_testValue, proceedTime); TimeValue variation = pblock()->GetTimeValue(kDuration_variation, proceedTime); int subframe = pblock()->GetInt(kDuration_subframeSampling, proceedTime); TimeValue testFirst = pblock()->GetInt(kDuration_testFirst, proceedTime); TimeValue testLast = pblock()->GetInt(kDuration_testLast, proceedTime); TimeValue lastIndex = pblock()->GetInt(kDuration_lastIndex, proceedTime); if (lastIndex <= 0) lastIndex = 1; int tpf = GetTicksPerFrame(); RandGenerator* randGen = NULL; if (variation != 0) randGen = randLinker().GetRandGenerator(pCont); int index; for(i=0; i<count; i++) if (chNew->IsNew(i)) // calculate test value only for new particles { if (disparity) { index = chID->GetParticleIndex(i); if (index > lastIndex) curTestValue = PreciseTimeValue( testLast ); else curTestValue = PreciseTimeValue( testFirst + (testLast-testFirst)*(float(index)/lastIndex) ); } else curTestValue = PreciseTimeValue( testValue ); if (variation != 0) curTestValue += PreciseTimeValue( randGen->Rand11()*variation ); // adjust test value according to test type if (testType == kDuration_testType_age) curTestValue += chBirthTime->GetValue(i); else if (testType == kDuration_testType_event) { if (initEventStart) chEventStartW->SetValue(i, chTime->GetValue(i)); curTestValue += chEventStartR->GetValue(i); } if (!subframe) // round the test value to the nearest frame curTestValue = PreciseTimeValue(int(floor(TimeValue(curTestValue)/float(tpf) + 0.5f) * tpf)); chTestW->SetValue(i, curTestValue); } } // test all particles PreciseTimeValue curParticleValue; testResult.SetSize(count); testResult.ClearAll(); testTime.SetCount(count); int condType = pblock()->GetInt(kDuration_conditionType, proceedTime); BitArray particlesToAdvance; particlesToAdvance.SetSize(count); particlesToAdvance.ClearAll(); for(i=0; i<count; i++) { curTestValue = chTestR->GetValue(i); curParticleValue = chTime->GetValue(i); if (curParticleValue > timeEnd) continue; // particle has been proceeded beyond // the testing interval [timeStart,timeEnd] switch( condType ) { case kDuration_conditionType_less: if (curParticleValue <= curTestValue) { // particle doesn't need to be advanced in "time" since the current time value is the condition value testResult.Set(i); testTime[i] = float( curParticleValue - timeStart ); } break; case kDuration_conditionType_greater: if (timeEnd < curTestValue) break; // particle won't satisfy the condition // even at the end of the test interval if (curParticleValue >= curTestValue) { // particle doesn't need to be advanced in "time" since the current time value is more than satisfactory testResult.Set(i); testTime[i] = float( curParticleValue - timeStart ); break; } testResult.Set(i); testTime[i] = float( curTestValue - timeStart ); // the particle needs to be advanced in time if possible particlesToAdvance.Set(i); break; default: DbgAssert(0); break; } } // advance particles in time if they satisfy the condition and need to be pushed forward if (integrator != NULL) { Tab<PreciseTimeValue> timeToAdvance; timeToAdvance.SetCount(count); for(i=0; i<count; i++) if (particlesToAdvance[i] != 0) timeToAdvance[i] = timeStart + testTime[i]; integrator->Proceed(pCont, timeToAdvance, particlesToAdvance); } return true; }
bool PFOperatorSimpleOrientation::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator) { // acquire all necessary channels, create additional if needed IParticleChannelNewR* chNew = GetParticleChannelNewRInterface(pCont); if(chNew == NULL) return false; IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if(chTime == NULL) return false; IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if(chAmount == NULL) return false; // there are no new particles // if (chNew->IsAllOld()) return true; // we may need speed channel for "Speed Space" and "Speed Space Follow" types IParticleChannelPoint3R* chSpeed; int iDir = pblock()->GetInt(kSimpleOrientation_direction, 0); if ((iDir == kSO_Speed) || (iDir == kSO_SpeedFollow)) chSpeed = GetParticleChannelSpeedRInterface(pCont); bool bRestrictToAxis = (pblock()->GetInt(kSimpleOrientation_restrictToAxis, 0) != 0); IChannelContainer* chCont; chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; // the channel of interest IParticleChannelQuatW* chOrient = (IParticleChannelQuatW*)chCont->EnsureInterface(PARTICLECHANNELORIENTATIONW_INTERFACE, ParticleChannelQuat_Class_ID, true, PARTICLECHANNELORIENTATIONR_INTERFACE, PARTICLECHANNELORIENTATIONW_INTERFACE, true ); if (chOrient == NULL) return false; RandGenerator* prg = randLinker().GetRandGenerator(pCont); Matrix3 m3Orient; float fEulerAng[3]; int iQuant = chAmount->Count(); for(int i = 0; i < iQuant; i++) { if((chNew->IsNew(i)) || (iDir == kSO_SpeedFollow)) { // apply only to new particles or to all for "follow" type TimeValue tv = chTime->GetValue(i).TimeValue(); // set particle direction in user selected direction switch(iDir) { case kSO_Rand_3D: { Point3 p3x = RandSphereSurface(prg); Point3 p3y = RandSphereSurface(prg); while(p3x == p3y) p3y = RandSphereSurface(prg); p3y = Normalize(p3y - p3x * DotProd(p3x, p3y)); Point3 p3z = p3x ^ p3y; m3Orient = Matrix3(p3x, p3y, p3z, Point3::Origin); } break; case kSO_Rand_Horiz: { fEulerAng[0] = fEulerAng[1] = 0.0f; fEulerAng[2] = TWOPI * prg->Rand01(); EulerToMatrix(fEulerAng, m3Orient, EULERTYPE_XYZ); } break; case kSO_World: { fEulerAng[0] = GetPFFloat(pblock(), kSimpleOrientation_x, tv); fEulerAng[1] = GetPFFloat(pblock(), kSimpleOrientation_y, tv); fEulerAng[2] = GetPFFloat(pblock(), kSimpleOrientation_z, tv); EulerToMatrix(fEulerAng, m3Orient, EULERTYPE_XYZ); } break; case kSO_Speed: case kSO_SpeedFollow: { fEulerAng[0] = GetPFFloat(pblock(), kSimpleOrientation_x, tv); fEulerAng[1] = GetPFFloat(pblock(), kSimpleOrientation_y, tv); fEulerAng[2] = GetPFFloat(pblock(), kSimpleOrientation_z, tv); if (chSpeed != NULL) m3Orient = SpeedSpaceMatrix(chSpeed->GetValue(i)); else m3Orient = Matrix3(Point3::XAxis, Point3::YAxis, Point3::ZAxis, Point3::Origin); // m3Orient.SetRotate(Quat(m3Orient)); Matrix3 eulerRot; EulerToMatrix(fEulerAng, eulerRot, EULERTYPE_XYZ); // m3Orient = m3Orient * eulerRot; m3Orient = eulerRot * m3Orient; } break; } // account for divergence parameter if ((iDir != kSO_SpeedFollow) && (iDir != kSO_Rand_3D)) { float fDiv = GetPFFloat(pblock(), kSimpleOrientation_divergence, tv); Point3 p3RotAxis = RandSphereSurface(prg); if(fDiv > 0.f) { if (bRestrictToAxis) { p3RotAxis.x = GetPFFloat(pblock(), kSimpleOrientation_axisX, tv); p3RotAxis.y = GetPFFloat(pblock(), kSimpleOrientation_axisY, tv); p3RotAxis.z = GetPFFloat(pblock(), kSimpleOrientation_axisZ, tv); if (LengthSquared(p3RotAxis) > 0.0f) { p3RotAxis = Normalize(p3RotAxis); } else { p3RotAxis = Point3::XAxis; fDiv = 0.0f; } } float fRandDiv = fDiv * prg->Rand11(); m3Orient = m3Orient * RotAngleAxisMatrix(p3RotAxis, fRandDiv); } else { // perform operations that change randomness state prg->Rand11(); } } chOrient->SetValue(i, Quat(m3Orient)); } } return true; }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFAction | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //+--------------------------------------------------------------------------+ //| From IPFAction | //+--------------------------------------------------------------------------+ int PFTestDuration::GetRand() { return pblock()->GetInt(kDuration_randomSeed); }
//+--------------------------------------------------------------------------+ //| From IPFAction | //+--------------------------------------------------------------------------+ void PFTestDuration::SetRand(int seed) { pblock()->SetValue(kDuration_randomSeed, 0, seed); }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFTest | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ bool PFTestSplitByAmount::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator, BitArray& testResult, Tab<float>& testTime) { int contIndex; if (!hasParticleContainer(pCont, contIndex)) return false; _lastUpdate(contIndex) = timeEnd.TimeValue(); bool exactStep = IsExactIntegrationStep(timeEnd, pSystem); // update all other systems to the current time; everybody should be in sync // for proper accumulation amounts int i; for(i=0; i<allParticleContainers().Count(); i++) { if (allParticleContainer(i) == pCont) continue; if (allSystemNode(i) == pNode) continue; if (lastUpdate(i) == timeEnd.TimeValue()) continue; TimeValue timeToUpdateTo = timeEnd.TimeValue(); allSystemNode(i)->NotifyDependents(FOREVER, PartID(&timeToUpdateTo), kPFMSG_UpdateToTime, NOTIFY_ALL, TRUE ); } // get channel container interface IChannelContainer* chCont; chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; // acquire absolutely necessary particle channels IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if (chAmount == NULL) return false; // can't find number of particles in the container IParticleChannelNewR* chNew = GetParticleChannelNewRInterface(pCont); if (chNew == NULL) return false; // can't find "new" property of particles in the container // acquire TestSplitByAmount private particle channel; if not present then create it IParticleChannelBoolW* chTestW = (IParticleChannelBoolW*)chCont->EnsureInterface(PARTICLECHANNELTESTSPLITBYAMOUNTW_INTERFACE, ParticleChannelBool_Class_ID, true, PARTICLECHANNELTESTSPLITBYAMOUNTR_INTERFACE, PARTICLECHANNELTESTSPLITBYAMOUNTW_INTERFACE, false, actionNode, (Object*)this); IParticleChannelBoolR* chTestR = (IParticleChannelBoolR*)chCont->GetPrivateInterface(PARTICLECHANNELTESTSPLITBYAMOUNTR_INTERFACE, (Object*)this); if ((chTestR == NULL) || (chTestW == NULL)) return false; // can't set test value for newly entered particles int count = chAmount->Count(); // check if all particles are "old". If some particles are "new" then we // have to calculate test values for those. if (!chNew->IsAllOld()) { RandGenerator* randGen = randLinker().GetRandGenerator(pCont); if (randGen == NULL) return false; int testType = pblock()->GetInt(kSplitByAmount_testType, timeStart); float fraction = GetPFFloat(pblock(), kSplitByAmount_fraction, timeStart); int everyN = GetPFInt(pblock(), kSplitByAmount_everyN, timeStart); int firstN = pblock()->GetInt(kSplitByAmount_firstN, timeStart); bool perSource = (pblock()->GetInt(kSplitByAmount_perSource, timeStart) != 0); int curWentThru = perSource ? wentThruTotal(pNode) : wentThruTotal(); // number of "first N" particles is adjusted by multiplier coefficient // of the master particle system. This is done to make "first N" // parameter to be consistent to "total" number of particles acclaimed // by a birth operator IPFSystem* pfSys = PFSystemInterface(pSystem); if (pfSys == NULL) return false; // no handle for PFSystem interface firstN *= pfSys->GetMultiplier(timeStart); for(i=0; i<count; i++) { if (chNew->IsNew(i)) { // calculate test value only for new particles bool sendOut = false; switch(testType) { case kSplitByAmount_testType_fraction: sendOut = (randGen->Rand01() <= fraction); break; case kSplitByAmount_testType_everyN: _wentThruAccum(contIndex) += 1; if (wentThruAccum(contIndex) >= everyN) { sendOut = true; _wentThruAccum(contIndex) = 0; } break; case kSplitByAmount_testType_firstN: _wentThruTotal(contIndex) += 1; if (curWentThru++ < firstN) sendOut = true; break; case kSplitByAmount_testType_afterFirstN: _wentThruTotal(contIndex) += 1; if (curWentThru++ >= firstN) sendOut = true; break; } chTestW->SetValue(i, sendOut); } } } // check all particles by predefined test channel testResult.SetSize(count); testResult.ClearAll(); testTime.SetCount(count); if (exactStep) { for(i=0; i<count; i++) { if (chTestR->GetValue(i)) { testResult.Set(i); testTime[i] = 0.0f; } } } return true; }
//+--------------------------------------------------------------------------+ //| From IPFAction | //+--------------------------------------------------------------------------+ void PFTestSplitByAmount::SetRand(int seed) { pblock()->SetValue(kSplitByAmount_randomSeed, 0, seed); }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFAction | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ int PFTestSplitByAmount::GetRand() { return pblock()->GetInt(kSplitByAmount_randomSeed); }
RefResult PFOperatorMaterialStatic::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message) { IParamMap2* map; TSTR dynamicNameSuffix; if ( hTarget == pblock() ) { switch (message) { case REFMSG_CHANGE: { ParamID lastUpdateID = pblock()->LastNotifyParamID(); if (lastUpdateID == kMaterialStatic_material) { if (updateFromMXSMtl()) { NotifyDependents(FOREVER, PART_MTL, kPFMSG_UpdateMaterial, NOTIFY_ALL, TRUE); NotifyDependents(FOREVER, 0, kPFMSG_DynamicNameChange, NOTIFY_ALL, TRUE); } UpdatePViewUI(lastUpdateID); return REF_STOP; } if (!(theHold.Holding() || theHold.RestoreOrRedoing())) return REF_STOP; switch ( lastUpdateID ) { case kMaterialStatic_assignMaterial: RefreshUI(kMaterialStatic_message_assignMaterial); NotifyDependents(FOREVER, PART_MTL, kPFMSG_UpdateMaterial, NOTIFY_ALL, TRUE); NotifyDependents(FOREVER, 0, kPFMSG_DynamicNameChange, NOTIFY_ALL, TRUE); break; case kMaterialStatic_assignID: RefreshUI(kMaterialStatic_message_assignID); break; case kMaterialStatic_type: RefreshUI(kMaterialStatic_message_type); break; case kMaterialStatic_rateType: RefreshUI(kMaterialStatic_message_rateType); break; } UpdatePViewUI(lastUpdateID); break; } case REFMSG_NODE_WSCACHE_UPDATED: updateFromRealMtl(); break; // Initialization of Dialog case kMaterialStatic_RefMsg_InitDlg: // Set ICustButton properties for MaterialStatic DAD button map = (IParamMap2*)partID; if (map != NULL) { HWND hWnd = map->GetHWnd(); if (hWnd) { ICustButton *iBut = GetICustButton(GetDlgItem(hWnd, IDC_MATERIAL)); iBut->SetDADMgr(_dadMgr()); ReleaseICustButton(iBut); } } // Refresh UI RefreshUI(kMaterialStatic_message_assignMaterial); RefreshUI(kMaterialStatic_message_assignID); return REF_STOP; // New Random Seed case kMaterialStatic_RefMsg_NewRand: theHold.Begin(); NewRand(); theHold.Accept(GetString(IDS_NEWRANDOMSEED)); return REF_STOP; } } if ( hTarget == const_cast <Mtl*> (material()) ) { switch (message) { case REFMSG_CHANGE: return REF_STOP; // if (ignoreRefMsgNotify()) return REF_STOP; // if (!(theHold.Holding() || theHold.RestoreOrRedoing())) return REF_STOP; break; case REFMSG_NODE_NAMECHANGE: if (HasDynamicName(dynamicNameSuffix)) { if (lastDynamicName() != dynamicNameSuffix) { _lastDynamicName() = dynamicNameSuffix; NotifyDependents(FOREVER, 0, kPFMSG_DynamicNameChange, NOTIFY_ALL, TRUE); UpdatePViewUI(kMaterialStatic_material); } } return REF_STOP; case REFMSG_TARGET_DELETED: _material() = NULL; if (pblock() != NULL) pblock()->SetValue(kMaterialStatic_material, 0, NULL); if (theHold.Holding()) { if (HasDynamicName(dynamicNameSuffix)) { if (lastDynamicName() != dynamicNameSuffix) { _lastDynamicName() = dynamicNameSuffix; NotifyDependents(FOREVER, 0, kPFMSG_DynamicNameChange, NOTIFY_ALL, TRUE); UpdatePViewUI(kMaterialStatic_material); } } } break; } } return REF_SUCCEED; }
int PFOperatorSimpleOrientation::GetRand() { return pblock()->GetInt(kSimpleOrientation_seed); }
bool PFOperatorMaterialStatic::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator) { if (pblock() == NULL) return false; int assignID = pblock()->GetInt(kMaterialStatic_assignID, timeEnd); if (assignID == 0) return true; // nothing to assign int showInViewport = pblock()->GetInt(kMaterialStatic_showInViewport, timeEnd); if (!showInViewport) { // check if the system is in render; if not then return IPFSystem* iSystem = GetPFSystemInterface(pSystem); if (iSystem == NULL) return false; if (!iSystem->IsRenderState()) return true; // nothing to show in viewport } int type = pblock()->GetInt(kMaterialStatic_type, timeEnd); // acquire absolutely necessary particle channels IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if (chAmount == NULL) return false; // can't find number of particles in the container int i = 0; int count = chAmount->Count(); if (count == 0) return true; // no particles to modify IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if (chTime == NULL) return false; // can't read timing for a particle IParticleChannelNewR* chNew = GetParticleChannelNewRInterface(pCont); if (chNew == NULL) return false; // can't find newly entered particles for duration calculation IChannelContainer* chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; // ensure material index channel IParticleChannelIntR* chMtlIDR = GetParticleChannelMtlIndexRInterface(pCont); if (chMtlIDR == NULL) addCTWO( pCont ); IParticleChannelIntW* chMtlIDW = (IParticleChannelIntW*)chCont->EnsureInterface(PARTICLECHANNELMTLINDEXW_INTERFACE, ParticleChannelInt_Class_ID, true, PARTICLECHANNELMTLINDEXR_INTERFACE, PARTICLECHANNELMTLINDEXW_INTERFACE, true, actionNode, NULL); if (chMtlIDW == NULL) return false; // can't modify MaterialIndex channel in the container if (!isSelfCreator(pCont, chCont, actionNode)) return true; RandGenerator* randGen = randLinker().GetRandGenerator(pCont); int rateType = pblock()->GetInt(kMaterialStatic_rateType, timeEnd); int numSubMtls = pblock()->GetInt(kMaterialStatic_numSubMtls, timeEnd); if (numSubMtls < 1) numSubMtls = 1; int cycleLoop = pblock()->GetInt(kMaterialStatic_loop, timeEnd); float rateSec = pblock()->GetFloat(kMaterialStatic_ratePerSecond, timeEnd); float ratePart = pblock()->GetFloat(kMaterialStatic_ratePerParticle, timeEnd); int mtlID = 0; bool useRatePerSec = ((type != kMaterialStatic_type_id) && (rateType == kMaterialStatic_rateType_second)); bool useRatePerPart = ((type != kMaterialStatic_type_id) && (rateType == kMaterialStatic_rateType_particle)); bool initRands = false; // recalc offset if necessary if (_offsetTime(pCont) == TIME_NegInfinity) { _offsetTime(pCont) = timeStart.TimeValue(); // find the earliest time of the coming particles PreciseTimeValue minTime = chTime->GetValue(0); for(i=1; i<count; i++) if (minTime > chTime->GetValue(i)) minTime = chTime->GetValue(i); if (useRatePerSec) if (type == kMaterialStatic_type_cycle) _cycleOffset(pCont) = float(PreciseTimeValue(_offsetTime(pCont)) - minTime)*rateSec/TIME_TICKSPERSEC; initRands = true; } else if (_offsetTime(pCont) != timeStart.TimeValue()) { if (useRatePerSec) { if (type == kMaterialStatic_type_cycle) { float timeDelta = float(timeStart.TimeValue() - _offsetTime(pCont)); float addOffset = timeDelta*rateSec/TIME_TICKSPERSEC; _cycleOffset(pCont) += addOffset; if (_cycleOffset(pCont) >= numSubMtls) { if (cycleLoop) _cycleOffset(pCont) -= numSubMtls*int(_cycleOffset(pCont)/numSubMtls); else _cycleOffset(pCont) = numSubMtls - 1.0f; } } } _offsetTime(pCont) = timeStart.TimeValue(); initRands = true; } if (initRands && useRatePerSec && (type == kMaterialStatic_type_random)) { int intervalDelta = int(timeEnd.TimeValue() - timeStart.TimeValue()) + 1; _randMtlIndex(pCont).SetCount(intervalDelta); float curOffset = _cycleOffset(pCont); int curMtlID = int(curOffset); _randMtlIndex(pCont)[0] = curMtlID; for(int i=1; i<intervalDelta; i++) { float addOffset = rateSec/TIME_TICKSPERSEC; curOffset += addOffset; if (int(curOffset) != curMtlID) { curOffset = randGen->Rand0X(numSubMtls-1) + (curOffset - floor(curOffset)); curMtlID = int(curOffset); } _randMtlIndex(pCont)[i] = curMtlID; _cycleOffset(pCont) = curOffset; } } float curCycleOffset = _cycleOffset(pCont); float ratePerPart = pblock()->GetFloat(kMaterialStatic_ratePerParticle, timeEnd); for(i=0; i<count; i++) { if (!chNew->IsNew(i)) continue; // the ID is already set switch(type) { case kMaterialStatic_type_id: mtlID = GetPFInt(pblock(), kMaterialStatic_materialID, chTime->GetValue(i).TimeValue()); mtlID--; break; case kMaterialStatic_type_cycle: if (rateType == kMaterialStatic_rateType_second) { float timeDelta = float(chTime->GetValue(i) - timeStart); float addOffset = timeDelta*rateSec/TIME_TICKSPERSEC; mtlID = int(curCycleOffset + addOffset); if (mtlID >= numSubMtls) { if (cycleLoop) mtlID = mtlID%numSubMtls; else mtlID = numSubMtls - 1; } } else { // per particle rate type mtlID = int(curCycleOffset); if (mtlID >= numSubMtls) { if (cycleLoop) mtlID = mtlID%numSubMtls; else mtlID = numSubMtls - 1; } if (ratePart > 0.0f) { curCycleOffset += 1.0f/ratePart; if (curCycleOffset >= numSubMtls) { if (cycleLoop) curCycleOffset -= numSubMtls*int(curCycleOffset/numSubMtls); else curCycleOffset = numSubMtls - 1.0f; } } } break; case kMaterialStatic_type_random: if (rateType == kMaterialStatic_rateType_second) { int timeDelta = int( chTime->GetValue(i) - timeStart.TimeValue() ); mtlID = _randMtlIndex(pCont)[timeDelta]; } else { // per particle rate type mtlID = int(curCycleOffset); int oldMtlID = mtlID; if (mtlID >= numSubMtls) { if (cycleLoop) mtlID = mtlID%numSubMtls; else mtlID = numSubMtls - 1; } if (ratePart > 0.0f) { curCycleOffset += 1.0f/ratePart; if (int(curCycleOffset) != oldMtlID) curCycleOffset = randGen->Rand0X(numSubMtls-1) + (curCycleOffset - floor(curCycleOffset)); } } break; default: DbgAssert(0); } if (mtlID < 0) mtlID = 0; chMtlIDW->SetValue(i, mtlID); } if (useRatePerPart) _cycleOffset(pCont) = curCycleOffset; return true; }
int PFOperatorMaterialFrequency::GetRand() { return pblock()->GetInt(kMaterialFrequency_randomSeed); }
//+--------------------------------------------------------------------------+ //| From IPFAction | //+--------------------------------------------------------------------------+ int PFTestGoToRotation::GetRand() { return pblock()->GetInt(kGoToRotation_randomSeed); }
void PFOperatorMaterialFrequency::SetRand(int seed) { pblock()->SetValue(kMaterialFrequency_randomSeed, 0, seed); }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFOperator | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ bool PFTestGoToRotation::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator) { if (postProceed()) return doPostProceed(pCont, timeStart, timeEnd, pSystem, pNode, actionNode, integrator); if (pblock() == NULL) return false; IChannelContainer* chCont; chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; // acquire absolutely necessary particle channels IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if (chAmount == NULL) return false; // can't find number of particles in the container int i, count = chAmount->Count(); if (count == 0) return true; // no particles to modify IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if (chTime == NULL) return false; // can't read timing info for a particle IParticleChannelNewR* chNew = GetParticleChannelNewRInterface(pCont); if (chNew == NULL) return false; // can't find newly entered particles for speedGoToTarget calculation IParticleChannelPTVR* chBirth = GetParticleChannelBirthTimeRInterface(pCont); if (chBirth == NULL) return false; // can't read birth time data IParticleChannelQuatR* chOrient = GetParticleChannelOrientationRInterface(pCont); if (chOrient == NULL) return false; // can't read current orientation for a particle // may create and initialize spin channel if it is not present IParticleChannelAngAxisR* chSpinR = NULL; IParticleChannelAngAxisW* chSpinW = NULL; bool initSpin = false; chSpinR = (IParticleChannelAngAxisR*)chCont->EnsureInterface(PARTICLECHANNELSPINR_INTERFACE, ParticleChannelAngAxis_Class_ID, true, PARTICLECHANNELSPINR_INTERFACE, PARTICLECHANNELSPINW_INTERFACE, true, actionNode, NULL, &initSpin); if (chSpinR == NULL) return false; // can't read spin data if (initSpin) { chSpinW = GetParticleChannelSpinWInterface(pCont); if (chSpinW == NULL) return false; // can't modify spin data } if (initSpin) { AngAxis aa(Point3::XAxis, 0.0f); if (!chNew->IsAllOld()) for(i=0; i<count; i++) { if (chNew->IsNew(i)) chSpinW->SetValue(i, aa); } } // create channel to store the start moment of the transition process // the time is when a particle enters the event IParticleChannelPTVW* chStartTimeW = NULL; bool initStartTime = false; chStartTimeW = (IParticleChannelPTVW*)chCont->EnsureInterface(PARTICLECHANNELSTARTTIMEW_INTERFACE, ParticleChannelPTV_Class_ID, true, PARTICLECHANNELSTARTTIMER_INTERFACE, PARTICLECHANNELSTARTTIMEW_INTERFACE, true, actionNode, (Object*)this, &initStartTime); if (chStartTimeW == NULL) return false; // can't modify the start time // create channel to store the end moment of the transition process // the time is used to determine when a particle should go to the next event, and when to finish the transition process IParticleChannelPTVW* chEndTimeW = NULL; bool initEndTime = false; chEndTimeW = (IParticleChannelPTVW*)chCont->EnsureInterface(PARTICLECHANNELENDTIMEW_INTERFACE, ParticleChannelPTV_Class_ID, true, PARTICLECHANNELENDTIMER_INTERFACE, PARTICLECHANNELENDTIMEW_INTERFACE, true, actionNode, (Object*)this, &initEndTime); if (chEndTimeW == NULL) return false; // can't modify the end time // create channel to store info about the last time for each particle for the proceed function // the data is used to rollback the effect of integration to find the desirable orientation IParticleChannelPTVW* chProceedTimeW = NULL; chProceedTimeW = (IParticleChannelPTVW*)chCont->EnsureInterface(PARTICLECHANNELPROCEEDTIMEW_INTERFACE, ParticleChannelPTV_Class_ID, true, PARTICLECHANNELPROCEEDTIMER_INTERFACE, PARTICLECHANNELPROCEEDTIMEW_INTERFACE, false, actionNode, (Object*)this); if (chProceedTimeW == NULL) return false; // can't modify the proceed time for(i=0; i<count; i++) chProceedTimeW->SetValue(i, chTime->GetValue(i)); // create channel to store info if the final rotation has been initialized IParticleChannelBoolW* chGotInitW = NULL; bool initGotInit = false; chGotInitW = (IParticleChannelBoolW*)chCont->EnsureInterface(PARTICLECHANNELGOTINITW_INTERFACE, ParticleChannelBool_Class_ID, true, PARTICLECHANNELGOTINITR_INTERFACE, PARTICLECHANNELGOTINITW_INTERFACE, true, actionNode, (Object*)this, &initGotInit); if (chGotInitW == NULL) return false; // can't modify if init data // create channel to store initial rotation IParticleChannelQuatW* chStartRotW = NULL; bool initStartRot = false; chStartRotW = (IParticleChannelQuatW*)chCont->EnsureInterface(PARTICLECHANNELSTARTROTW_INTERFACE, ParticleChannelQuat_Class_ID, true, PARTICLECHANNELSTARTROTR_INTERFACE, PARTICLECHANNELSTARTROTW_INTERFACE, true, actionNode, (Object*)this, &initStartRot); if (chStartRotW == NULL) return false; // can't modify the start rotation // create channel to store end rotation IParticleChannelQuatW* chEndRotW = NULL; bool initEndRot = false; chEndRotW = (IParticleChannelQuatW*)chCont->EnsureInterface(PARTICLECHANNELENDROTW_INTERFACE, ParticleChannelQuat_Class_ID, true, PARTICLECHANNELENDROTR_INTERFACE, PARTICLECHANNELENDROTW_INTERFACE, true, actionNode, (Object*)this, &initEndRot); if (chEndRotW == NULL) return false; // can't modify the end rotation // create channel to store initial spin IParticleChannelAngAxisW* chStartSpinW = NULL; bool initStartSpin = false; chStartSpinW = (IParticleChannelAngAxisW*)chCont->EnsureInterface(PARTICLECHANNELSTARTSPINW_INTERFACE, ParticleChannelAngAxis_Class_ID, true, PARTICLECHANNELSTARTSPINR_INTERFACE, PARTICLECHANNELSTARTSPINW_INTERFACE, true, actionNode, (Object*)this, &initStartSpin); if (chStartSpinW == NULL) return false; // can't modify the start rotation // create channel to store final spin rate as a float IParticleChannelFloatW* chEndSpinW = NULL; bool initEndSpin = false; chEndSpinW = (IParticleChannelFloatW*)chCont->EnsureInterface(PARTICLECHANNELENDSPINW_INTERFACE, ParticleChannelFloat_Class_ID, true, PARTICLECHANNELENDSPINR_INTERFACE, PARTICLECHANNELENDSPINW_INTERFACE, true, actionNode, (Object*)this, &initEndSpin); if (chEndSpinW == NULL) return false; // can't modify the start rotation int sync = pblock()->GetInt(kGoToRotation_syncBy, timeEnd); TimeValue time = pblock()->GetTimeValue(kGoToRotation_time, timeEnd); TimeValue timeVar = pblock()->GetTimeValue(kGoToRotation_variation, timeEnd); int matchSpin = pblock()->GetInt(kGoToRotation_matchSpin, timeEnd); float spin = GetPFFloat(pblock(), kGoToRotation_spin, timeEnd.TimeValue())/TIME_TICKSPERSEC; float spinVar = GetPFFloat(pblock(), kGoToRotation_spinVariation, timeEnd.TimeValue())/TIME_TICKSPERSEC; RandGenerator* randGen = randLinker().GetRandGenerator(pCont); if (randGen == NULL) return false; if (!chNew->IsAllOld()) { for(i=0; i<count; i++) { if (!chNew->IsNew(i)) continue; if (initStartTime) chStartTimeW->SetValue(i, chTime->GetValue(i) ); if (initEndTime) { PreciseTimeValue endTime(time); switch(sync) { case kGoToRotation_syncBy_age: endTime += chBirth->GetValue(i); break; case kGoToRotation_syncBy_event: endTime += chTime->GetValue(i); break; } if (timeVar > 0) { int sign = randGen->RandSign(); endTime += PreciseTimeValue(sign*randGen->Rand0X(timeVar)); } else { randGen->RandSign(); randGen->Rand0X(10); } chEndTimeW->SetValue(i, endTime); } if (initGotInit) chGotInitW->SetValue(i, false); if (initStartRot) chStartRotW->SetValue(i, chOrient->GetValue(i)); if (initEndRot) chEndRotW->SetValue(i, chOrient->GetValue(i)); if (initStartSpin) chStartSpinW->SetValue(i, chSpinR->GetValue(i)); if (initEndSpin) { float endSpin = 0; if (matchSpin) { AngAxis aa = chSpinR->GetValue(i); endSpin = aa.angle; } else endSpin = spin; if (spinVar > 0.0f) endSpin += spinVar*randGen->Rand11(); else randGen->Rand11(); chEndSpinW->SetValue(i, endSpin); } } } return true; }
bool PFOperatorMaterialFrequency::IsMaterialHolder() const { return (pblock()->GetInt(kMaterialFrequency_assignMaterial, 0) != 0); }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFTest | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ bool PFTestGoToRotation::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator, BitArray& testResult, Tab<float>& testTime) { if (pblock() == NULL) return false; // get channel container interface IChannelContainer* chCont; chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; // acquire absolutely necessary particle channels IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if (chAmount == NULL) return false; // can't find number of particles in the container int i, count = chAmount->Count(); if (count == 0) return true; // no particles to test IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if (chTime == NULL) return false; // can't read timing info for a particle IParticleChannelQuatW* chOrientW = GetParticleChannelOrientationWInterface(pCont); if (chOrientW == NULL) return false; // can't modify current orientation for a particle IParticleChannelAngAxisR* chSpinR = GetParticleChannelSpinRInterface(pCont); if (chSpinR == NULL) return false; // can't read current spin for a particle IParticleChannelAngAxisW* chSpinW = GetParticleChannelSpinWInterface(pCont); if (chSpinW == NULL) return false; // can't modify current spin for a particle // acquire private channels IParticleChannelPTVR* chEndTime = (IParticleChannelPTVR*)(chCont->GetPrivateInterface(PARTICLECHANNELENDTIMER_INTERFACE, (Object*)this)); if (chEndTime == NULL) return false; IParticleChannelBoolR* chGotInitR = (IParticleChannelBoolR*)(chCont->GetPrivateInterface(PARTICLECHANNELGOTINITR_INTERFACE, (Object*)this)); if (chGotInitR == NULL) return false; IParticleChannelQuatR* chEndRotR = (IParticleChannelQuatR*)(chCont->GetPrivateInterface(PARTICLECHANNELENDROTR_INTERFACE, (Object*)this)); if (chEndRotR == NULL) return false; IParticleChannelFloatR* chEndSpin = (IParticleChannelFloatR*)(chCont->GetPrivateInterface(PARTICLECHANNELENDSPINR_INTERFACE, (Object*)this)); if (chEndSpin == NULL) return false; bool sendOut = (pblock()->GetInt(kGoToRotation_sendOut, timeEnd) != 0); bool stopSpin = (pblock()->GetInt(kGoToRotation_stopSpin, timeEnd) != 0); // test all particles PreciseTimeValue curTime; testResult.SetSize(count); testResult.ClearAll(); testTime.SetCount(count); BitArray particlesToAdvance; particlesToAdvance.SetSize(count); particlesToAdvance.ClearAll(); for(i=0; i<count; i++) { curTime = chEndTime->GetValue(i); if (curTime > timeEnd) continue; if (curTime < timeStart) { testTime[i] = float(chTime->GetValue(i) - timeStart); } else { testTime[i] = float(curTime - timeStart); particlesToAdvance.Set(i); } testResult.Set(i); } // advance particles in time if they satisfy the condition and need to be pushed forward if (integrator != NULL) { Tab<PreciseTimeValue> timeToAdvance; timeToAdvance.SetCount(count); for(i=0; i<count; i++) if (particlesToAdvance[i] != 0) timeToAdvance[i] = timeStart + testTime[i]; integrator->Proceed(pCont, timeToAdvance, particlesToAdvance); } for(i=0; i<count; i++) { if (particlesToAdvance[i] == 0) continue; Quat curRot = chEndRotR->GetValue(i); chOrientW->SetValue(i, chEndRotR->GetValue(i)); AngAxis spin = chSpinR->GetValue(i); spin.angle = stopSpin ? 0.0f : chEndSpin->GetValue(i); chSpinW->SetValue(i, spin); } if (!sendOut) testResult.ClearAll(); return true; }
bool PFOperatorMaterialFrequency::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator) { if (pblock() == NULL) return false; int assignID = pblock()->GetInt(kMaterialFrequency_assignID, timeEnd); if (assignID == 0) return true; // nothing to assign int showInViewport = pblock()->GetInt(kMaterialFrequency_showInViewport, timeEnd); if (!showInViewport) { // check if the system is in render; if not then return IPFSystem* iSystem = GetPFSystemInterface(pSystem); if (iSystem == NULL) return false; if (!iSystem->IsRenderState()) return true; // nothing to show in viewport } // acquire absolutely necessary particle channels IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if (chAmount == NULL) return false; // can't find number of particles in the container IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if (chTime == NULL) return false; // can't read timing for a particle IParticleChannelNewR* chNew = GetParticleChannelNewRInterface(pCont); if (chNew == NULL) return false; // can't find newly entered particles for duration calculation IChannelContainer* chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; // ensure material index channel IParticleChannelIntW* chMtlIDW = (IParticleChannelIntW*)chCont->EnsureInterface(PARTICLECHANNELMTLINDEXW_INTERFACE, ParticleChannelInt_Class_ID, true, PARTICLECHANNELMTLINDEXR_INTERFACE, PARTICLECHANNELMTLINDEXW_INTERFACE, true); if (chMtlIDW == NULL) return false; // can't modify Material Index channel in the container IParticleChannelIntR* chMtlIDR = GetParticleChannelMtlIndexRInterface(pCont); RandGenerator* randGen = randLinker().GetRandGenerator(pCont); int i, j, count = chAmount->Count(); int mtlID; float idShare[10], slideShare[10]; int pblockIDShare[] = { kMaterialFrequency_id1, kMaterialFrequency_id2, kMaterialFrequency_id3, kMaterialFrequency_id4, kMaterialFrequency_id5, kMaterialFrequency_id6, kMaterialFrequency_id7, kMaterialFrequency_id8, kMaterialFrequency_id9, kMaterialFrequency_id10 }; for(i=0; i<count; i++) { if (!chNew->IsNew(i)) continue; // the ID is already set TimeValue curTime = chTime->GetValue(i).TimeValue(); float totalShare = 0.0f; for(j=0; j<10; j++) { totalShare += (idShare[j] = GetPFFloat(pblock(), pblockIDShare[j], curTime)); slideShare[j] = totalShare; } float randomShare = totalShare*randGen->Rand01(); for(j=0; j<10; j++) { mtlID = j; if (randomShare < slideShare[j]) break; } chMtlIDW->SetValue(i, mtlID); } return true; }
int PFOperatorSimpleSpeed::GetRand() { return pblock()->GetInt(kSimpleSpeed_seed); }
bool PFOperatorMaterialFrequency::verifyMtlsMXSSync() { if (pblock() == NULL) return true; return (_material() == pblock()->GetMtl(kMaterialFrequency_material, 0)); }
//+--------------------------------------------------------------------------+ //| From IPFAction | //+--------------------------------------------------------------------------+ void PFTestScale::SetRand(int seed) { pblock()->SetValue(kScaleTest_randomSeed, 0, seed); }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From PFOperatorMaterialStatic | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ PFOperatorMaterialStatic::PFOperatorMaterialStatic() { GetClassDesc()->MakeAutoParamBlocks(this); // set the initial value for sub-mtls rate to the number of frames per second pblock()->SetValue(kMaterialStatic_ratePerSecond, 0, float(TIME_TICKSPERSEC)/GetTicksPerFrame() ); }
int shell() { int err = 0; extern PCBDLL **PRIORITY_QUEUES; // Makin ur queues PCBDLL_CREATION PRIORITY_QUEUES = PCBDLL_creation( TDF_QUEUES ); buffer_size = BUFFER_SIZE; EXIT_PROMPT_LOOP = 0; strcpy(EXIT_STRING, "exit\0"); welcome_message(); // Debugging check // givemeready(); while (!EXIT_PROMPT_LOOP) { display_prompt(); // `tdf:$ ' currently SYS_REQ_ERR = sys_req(READ, TERMINAL, BUFFER, &buffer_size); err = append_history(BUFFER); PARSER_ERROR = parse_buffer(BUFFER, PARSED_CMD, ARGUMENTS); // The most trivial case if (!strcmp(BUFFER,"\n\0")) { //Just a New Line continue; } switch (PARSER_ERROR) { case PARSER_FAIL_WHITESPACE: continue; break; case PARSER_FAIL_LONGNAME: printf("Invalid command name entered. Must be less than 9 characters.\n"); continue; break; case PARSER_WIN_SINGLETON: //This is linked to PARSER_WIN_HAS_ARGS which follows case PARSER_WIN_HAS_ARGS: if (!strcmp(PARSED_CMD,EXIT_STRING)) { //Equal to EXIT_STRING if(exit_confirmation() == SHELL_EXIT_CONFIRM) { EXIT_PROMPT_LOOP = !EXIT_PROMPT_LOOP; break; } else { continue; } } break; default: printf("I have no idea how you got here. File a bug report!\n"); printf("Parser exited wth status of: %d\n", PARSER_ERROR); continue; break; } if (!strcmp(PARSED_CMD, "date")) { date(ARGUMENTS); } else if (!strcmp(PARSED_CMD, "dispatch")) { dispatch ( ); } else if (!strcmp(PARSED_CMD, "display") || !strcmp(PARSED_CMD, "ls")) { display(ARGUMENTS); continue; } else if (!strcmp(PARSED_CMD, "hossgive")){ givemeready(); } else if (!strcmp(PARSED_CMD, "load")) { load( ARGUMENTS ); } else if (!strcmp(PARSED_CMD, "loadr3")) { loadr3 ( ); } else if (!strcmp(PARSED_CMD, "history")) { history(ARGUMENTS); } else if (!strcmp(PARSED_CMD, "pblock")) { pblock(ARGUMENTS); } else if (!strcmp(PARSED_CMD, "pcreate")) { pcreate(ARGUMENTS); } else if (!strcmp(PARSED_CMD, "pdelete")) { pdelete(ARGUMENTS); } else if (!strcmp(PARSED_CMD, "presume")) { presume(ARGUMENTS); } else if (!strcmp(PARSED_CMD, "psetprio")) { psetprio(ARGUMENTS); } else if (!strcmp(PARSED_CMD, "pshow")) { pshow(ARGUMENTS); } else if (!strcmp(PARSED_CMD, "pshowall")) { pshowall(); } else if (!strcmp(PARSED_CMD, "pshowblk")) { pshowblk(); } else if (!strcmp(PARSED_CMD, "pshowrd")) { pshowrd(); } else if (!strcmp(PARSED_CMD, "psuspend")) { psuspend(ARGUMENTS); } else if (!strcmp(PARSED_CMD, "punblock")) { punblock(ARGUMENTS); } else if (!strcmp(PARSED_CMD, "version")) { version(ARGUMENTS); } else if (!strcmp(PARSED_CMD, "help")) { help(ARGUMENTS); } else { //printf("Command not found.\n"); continue; } } departing_message(); // Clean up our queues PCBDLL_freeall( ); return err; }
bool PFOperatorForceSpaceWarp::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator) { // acquire all necessary channels, create additional if needed IChannelContainer* chCont; chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if(chAmount == NULL) return false; int iQuant = chAmount->Count(); if (iQuant < 1) return true; // no particles to proceed IParticleChannelNewR* chNew = GetParticleChannelNewRInterface(pCont); if (chNew == NULL) return false; IParticleChannelIDR* chID = GetParticleChannelIDRInterface(pCont); if (chID == NULL) return false; IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if(chTime == NULL) return false; IParticleChannelPTVR* chAge = GetParticleChannelBirthTimeRInterface(pCont); if(chAge == NULL) return false; // the channel of interest speed bool initSpeed = false; //channel does not exist so make it and note that we have to fill it out IParticleChannelPoint3W* chSpeedW = (IParticleChannelPoint3W*)chCont->EnsureInterface(PARTICLECHANNELSPEEDW_INTERFACE, ParticleChannelPoint3_Class_ID, true, PARTICLECHANNELSPEEDR_INTERFACE, PARTICLECHANNELSPEEDW_INTERFACE, true, actionNode, NULL, &initSpeed); IParticleChannelPoint3R* chSpeed = GetParticleChannelSpeedRInterface(pCont); if ((chSpeedW == NULL) || (chSpeed == NULL)) return false; bool initPosition = false; IParticleChannelPoint3W* chPosW = (IParticleChannelPoint3W*)chCont->EnsureInterface(PARTICLECHANNELPOSITIONW_INTERFACE, ParticleChannelPoint3_Class_ID, true, PARTICLECHANNELPOSITIONR_INTERFACE, PARTICLECHANNELPOSITIONW_INTERFACE, true, actionNode, NULL, &initPosition); IParticleChannelPoint3R* chPos = GetParticleChannelPositionRInterface(pCont); if ((chPosW == NULL) || (chPos == NULL)) return false; bool useScript = ((scriptPBlock()->GetInt(kForceSpaceWarp_useScriptWiring, 0) != 0) && (scriptPBlock()->GetInt(kForceSpaceWarp_useFloat, 0) == kForceSpaceWarp_useFloat_influence)); IParticleChannelFloatR* chFloat = NULL; if (useScript) { chFloat = GetParticleChannelMXSFloatRInterface(pCont); if (chFloat == NULL) return false; } int timeType = kAbsoluteTime; _pblock()->GetValue(kForceSpaceWarp_Sync,0, timeType, FOREVER); IParticleChannelPTVR* chEventStart = NULL; IParticleChannelPTVW* chEventStartW = NULL; bool initEventStart = false; if (timeType == kEventDuration) { chEventStartW = (IParticleChannelPTVW*) chCont->EnsureInterface(PARTICLECHANNELEVENTSTARTW_INTERFACE, ParticleChannelPTV_Class_ID, true, PARTICLECHANNELEVENTSTARTR_INTERFACE, PARTICLECHANNELEVENTSTARTW_INTERFACE, false, actionNode, NULL, &initEventStart); chEventStart = GetParticleChannelEventStartRInterface(pCont); if ((chEventStart == NULL) || (chEventStartW == NULL)) return false; } int overlapping = pblock()->GetInt(kForceSpaceWarp_Overlapping, 0); // collecting force fields Tab<ForceField*> ff; ForceField* curFF; int i, j; for(i=0; i<pblock()->Count(kForceSpaceWarp_ForceNodeList); i++) { INode* node = pblock()->GetINode(kForceSpaceWarp_ForceNodeList, 0, i); if (node == NULL) continue; Object* ob = GetPFObject(node->GetObjectRef()); if (ob == NULL) continue; if (ob->SuperClassID() == WSM_OBJECT_CLASS_ID) { WSMObject* obref = (WSMObject*)ob; curFF = obref->GetForceField(node); if (curFF != NULL) { if (ob->ClassID() == CS_VFIELDOBJECT_CLASS_ID) { // CS VectorField SW doesn't init properly partobj on GetForceField // this is a quick fix for that (bayboro 3/6/2003) CS_VectorField* vf = (CS_VectorField*)curFF; vf->partobj = GetParticleInterface(pSystem); } ff.Append(1, &curFF); } } } if (ff.Count() == 0) return true; // no force fields // some calls for a reference node TM may initiate REFMSG_CHANGE notification // we have to ignore that while processing the particles bool wasIgnoring = IsIgnoringRefNodeChange(); if (!wasIgnoring) SetIgnoreRefNodeChange(); float influence = 0.0f; for(i = 0; i < iQuant; i++) { TimeValue t = 0; if (timeType == kAbsoluteTime) t = chTime->GetValue(i).TimeValue(); else if (timeType == kParticleAge) t = chTime->GetValue(i).TimeValue() - chAge->GetValue(i).TimeValue(); else { if (initEventStart && chNew->IsNew(i)) chEventStartW->SetValue(i, chTime->GetValue(i)); t = chTime->GetValue(i).TimeValue() - chEventStart->GetValue(i).TimeValue(); } if (useScript) { influence = chFloat->GetValue(i); } else { influence = GetPFFloat(pblock(), kForceSpaceWarp_Influence, t); } Point3 v(0.0f,0.0f,0.0f); if (!initSpeed || !chNew->IsNew(i)) //if we created a speed channel the channel incoming is bogus so just use 0,0,0 ad default v = chSpeed->GetValue(i); Point3 p(0.0f,0.0f,0.0f); if (!initPosition || !chNew->IsNew(i)) //if we created a pos channel the channel incoming is bogus so just use 0,0,0 ad default p = chPos->GetValue(i); Point3 force = Point3::Origin; for(j=0; j<ff.Count(); j++) { // buffer vectors to guard true position and speed from malicious force Point3 pp = p; Point3 vv = v; Point3 nextForce = ff[j]->Force(t,pp,vv,chID->GetParticleBorn(i)) * influence; float lenSq = LengthSquared(nextForce); if (lenSq <= 0.0f) continue; // not a valid force if (overlapping == kForceSpaceWarp_Overlapping_additive) { force += nextForce; } else { if (lenSq > LengthSquared(force)) force = nextForce; } // p = pp; // v = vv; } v += force * float(timeEnd - chTime->GetValue(i)); chPosW->SetValue(i, p); chSpeedW->SetValue(i, v); } for(i=0; i<ff.Count(); i++) if (ff[i] != NULL) ff[i]->DeleteThis(); if (!wasIgnoring) ClearIgnoreRefNodeChange(); return true; }