//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFTest | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ bool PFTestSplitSelected::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); int conditionType = pblock()->GetInt(kSplitSelected_conditionType, timeStart); // 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(); IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if (chTime == NULL) return false; // can't read timing info for a particle IParticleChannelBoolR* chSelect = GetParticleChannelSelectionRInterface(pCont); // test all particles testResult.SetSize(count); testResult.ClearAll(); testTime.SetCount(count); for(int i=0; i<count; i++) { bool selected = (chSelect != NULL) ? chSelect->GetValue(i) : false; bool sendOut = ((selected && (conditionType == kSplitSelected_conditionType_selected)) || (!selected && (conditionType == kSplitSelected_conditionType_notSelected))); if (sendOut && 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; }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| 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; }