//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+
//|							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;
}
Пример #2
0
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;
}