aboutsummaryrefslogtreecommitdiff
path: root/APEX_1.4/module/pxparticleios/src/ParticleIosActorCPU.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/module/pxparticleios/src/ParticleIosActorCPU.cpp
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'APEX_1.4/module/pxparticleios/src/ParticleIosActorCPU.cpp')
-rw-r--r--APEX_1.4/module/pxparticleios/src/ParticleIosActorCPU.cpp442
1 files changed, 442 insertions, 0 deletions
diff --git a/APEX_1.4/module/pxparticleios/src/ParticleIosActorCPU.cpp b/APEX_1.4/module/pxparticleios/src/ParticleIosActorCPU.cpp
new file mode 100644
index 00000000..b2ba89ed
--- /dev/null
+++ b/APEX_1.4/module/pxparticleios/src/ParticleIosActorCPU.cpp
@@ -0,0 +1,442 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, related documentation
+ * and any modifications thereto. Any use, reproduction, disclosure or
+ * distribution of this software and related documentation without an express
+ * license agreement from NVIDIA CORPORATION is strictly prohibited.
+ */
+
+
+#include "ApexDefs.h"
+#include "Apex.h"
+#include "SceneIntl.h"
+#include "ApexSDKIntl.h"
+
+#include "ParticleIosActor.h"
+#include "ParticleIosActorCPU.h"
+#include "ParticleIosAssetImpl.h"
+#include "IofxAsset.h"
+#include "IofxActor.h"
+#include "ModuleParticleIosImpl.h"
+#include "ParticleIosScene.h"
+#include "RenderDebugInterface.h"
+#include "AuthorableObjectIntl.h"
+#include "FieldSamplerQueryIntl.h"
+#include "PxMath.h"
+#include "ApexMirroredArray.h"
+
+#include "PxParticleSystem.h"
+#include "PxParticleCreationData.h"
+#include "PxParticleReadData.h"
+#include "PxParticleDeviceExclusive.h"
+
+namespace nvidia
+{
+namespace pxparticleios
+{
+using namespace physx;
+
+#pragma warning(disable: 4355) // 'this' : used in base member initializer list
+
+ParticleIosActorCPU::ParticleIosActorCPU(
+ ResourceList& list,
+ ParticleIosAssetImpl& asset,
+ ParticleIosScene& scene,
+ IofxAsset& iofxAsset)
+ : ParticleIosActorImpl(list, asset, scene, iofxAsset, false)
+ , mSimulateTask(*this)
+{
+ initStorageGroups(mSimulationStorage);
+
+ mField.reserve(mMaxParticleCount);
+ mLifeTime.setSize(mMaxParticleCount);
+ mLifeSpan.setSize(mMaxTotalParticleCount);
+ mInjector.setSize(mMaxTotalParticleCount);
+ mBenefit.setSize(mMaxTotalParticleCount);
+
+ mNewIndices.resize(mMaxParticleCount);
+ mAddedParticleList.reserve(mMaxParticleCount);
+ mRemovedParticleList.reserve(mMaxParticleCount);
+ mInputIdToParticleIndex.setSize(mMaxParticleCount, ApexMirroredPlace::CPU);
+
+ mIndexPool = PxParticleExt::createIndexPool(mMaxParticleCount);
+
+ mUpdateIndexBuffer.reserve(mMaxParticleCount);
+ mUpdateVelocityBuffer.reserve(mMaxParticleCount);
+}
+ParticleIosActorCPU::~ParticleIosActorCPU()
+{
+ if (mIndexPool)
+ {
+ mIndexPool->release();
+ mIndexPool = NULL;
+ }
+
+}
+
+PxTaskID ParticleIosActorCPU::submitTasks(PxTaskManager* tm)
+{
+ ParticleIosActorImpl::submitTasks(tm);
+ mInjectorsCounters.setSize(mInjectorList.getSize(), ApexMirroredPlace::CPU);
+
+ if (mAsset->getParticleDesc()->Enable == false)
+ {
+ return mInjectTask.getTaskID();
+ }
+
+ const PxTaskID taskID = tm->submitUnnamedTask(mSimulateTask);
+ return taskID;
+}
+
+void ParticleIosActorCPU::setTaskDependencies(PxTaskID taskStartAfterID, PxTaskID taskFinishBeforeID)
+{
+ PxTask* iosTask = NULL;
+ if (mAsset->getParticleDesc()->Enable)
+ {
+ iosTask = &mSimulateTask;
+ }
+ ParticleIosActorImpl::setTaskDependencies(taskStartAfterID, taskFinishBeforeID, iosTask, false);
+}
+
+namespace
+{
+class FieldAccessor
+{
+ const PxVec4* mField;
+public:
+ explicit FieldAccessor(const PxVec4* field)
+ {
+ mField = field;
+ }
+
+ PX_INLINE void operator()(unsigned int srcIdx, PxVec3& velocityDelta)
+ {
+ if (mField != NULL)
+ {
+ velocityDelta += mField[srcIdx].getXYZ();
+ }
+ }
+};
+}
+
+void ParticleIosActorCPU::simulateParticles()
+{
+ float deltaTime = mParticleIosScene->getApexScene().getPhysXSimulateTime();
+ const PxVec3& eyePos = mParticleIosScene->getApexScene().getEyePosition();
+
+ SCOPED_PHYSX_LOCK_WRITE(&mParticleIosScene->getApexScene());
+
+ mTotalElapsedTime += deltaTime;
+
+ uint32_t totalCount = mParticleCount + mInjectedCount;
+ uint32_t activeCount = mLastActiveCount + mInjectedCount;
+
+ mParticleBudget = mMaxParticleCount;
+ if (mParticleBudget > activeCount)
+ {
+ mParticleBudget = activeCount;
+ }
+ uint32_t targetCount = mParticleBudget;
+
+ uint32_t maxStateID = 0; //we could drop state in case targetCount = 0
+
+ for(uint32_t i = 0; i < mInjectorList.getSize(); ++i)
+ {
+ mInjectorsCounters[i] = 0;
+ }
+
+ if (targetCount > 0)
+ {
+ maxStateID = mParticleCount;
+ for (uint32_t i = 0; i < maxStateID; ++i)
+ {
+ mNewIndices[i] = IosBufferDescIntl::NOT_A_PARTICLE;
+ }
+
+ uint32_t boundCount = 0;
+ if (activeCount > targetCount)
+ {
+ boundCount = activeCount - targetCount;
+ }
+
+ float benefitMin = PxMin(mLastBenefitMin, mInjectedBenefitMin);
+ float benefitMax = PxMax(mLastBenefitMax, mInjectedBenefitMax);
+ PX_ASSERT(benefitMin <= benefitMax);
+ benefitMax *= 1.00001f;
+
+ /*
+ boundBin - the highest benefit bin that should be culled
+ boundCount - before computeHistogram it's the total culled particles.
+ - after computeHistogram it's the count of culled particles in boundBin
+ boundIndex - count of culled particles in boundBin (0..boundCount-1)
+ */
+ int32_t boundBin = (int32_t)computeHistogram(totalCount, benefitMin, benefitMax, boundCount);
+ float factor = HISTOGRAM_BIN_COUNT / (benefitMax - benefitMin);
+ for (uint32_t i = 0, boundIndex = 0; i < totalCount; ++i)
+ {
+ float benefit = mBenefit[i];
+ if (benefit > -FLT_MAX)
+ {
+ PX_ASSERT(benefit >= benefitMin && benefit < benefitMax);
+
+ int32_t bin = int32_t((benefit - benefitMin) * factor);
+ if (bin < boundBin)
+ {
+ mBenefit[i] = -FLT_MAX;
+ continue;
+ }
+ if (bin == boundBin && boundIndex < boundCount)
+ {
+ mBenefit[i] = -FLT_MAX;
+ ++boundIndex;
+ }
+ }
+ }
+ }
+
+ if (mParticleCount > 0)
+ {
+ mRemovedParticleList.clear();
+ for (uint32_t i = 0 ; i < mParticleCount; ++i)
+ {
+ if (!(mBenefit[i] > -FLT_MAX))
+ {
+ mRemovedParticleList.pushBack(mInputIdToParticleIndex[i]);
+ mInputIdToParticleIndex[i] = INVALID_PARTICLE_INDEX;
+ }
+ }
+ if (mRemovedParticleList.size())
+ {
+ PxStrideIterator<const uint32_t> indexData( &mRemovedParticleList[0] );
+ ((PxParticleBase*)mParticleActor)->releaseParticles(mRemovedParticleList.size(), indexData);
+ mIndexPool->freeIndices(mRemovedParticleList.size(), indexData);
+ mRemovedParticleList.clear();
+ }
+ }
+
+ mLastActiveCount = 0;
+ mLastBenefitSum = 0.0f;
+ mLastBenefitMin = +FLT_MAX;
+ mLastBenefitMax = -FLT_MAX;
+
+ if (targetCount > 0)
+ {
+ const Px3InjectorParams* injectorParamsList = DYNAMIC_CAST(ParticleIosSceneCPU*)(mParticleIosScene)->mInjectorParamsArray.begin();
+
+ FieldAccessor fieldAccessor(mFieldSamplerQuery ? mField.getPtr() : 0);
+
+ mAddedParticleList.clear();
+ mUpdateIndexBuffer.clear();
+ mUpdateVelocityBuffer.clear();
+ physx::PxParticleReadData* readData = ((PxParticleBase*)mParticleActor)->lockParticleReadData();
+
+ bool isDensityValid = false;
+ if (!mIsParticleSystem)
+ {
+ PxParticleFluidReadData* fluidReadData = static_cast<PxParticleFluidReadData*>(readData);
+ isDensityValid = (fluidReadData->densityBuffer.ptr() != 0);
+ }
+
+ for (uint32_t dstIdx = 0, srcHole = targetCount; dstIdx < targetCount; ++dstIdx)
+ {
+ uint32_t srcIdx = dstIdx;
+ //do we have a hole in dstIdx region?
+ if (!(mBenefit[dstIdx] > -FLT_MAX))
+ {
+ //skip holes in srcIdx region
+ while (!(mBenefit[srcHole] > -FLT_MAX))
+ {
+ ++srcHole;
+ }
+ PX_ASSERT(srcHole < totalCount);
+ srcIdx = srcHole++;
+ }
+ //do we have a new particle?
+ bool isNewParticle = (srcIdx >= mParticleCount);
+
+ uint32_t pxIdx;
+ PxVec3 position;
+ PxVec3 velocity;
+ PxVec3 collisionNormal;
+ uint32_t particleFlags;
+ float density;
+
+ if (isNewParticle)
+ {
+ PxStrideIterator<uint32_t> indexBuffer(&pxIdx);
+ if (mIndexPool->allocateIndices(1, indexBuffer) != 1)
+ {
+ PX_ALWAYS_ASSERT();
+ continue;
+ }
+ mInputIdToParticleIndex[dstIdx] = pxIdx;
+ }
+ else
+ {
+ pxIdx = mInputIdToParticleIndex[srcIdx];
+ PX_ASSERT((readData->flagsBuffer[pxIdx] & PxParticleFlag::eVALID));
+ if (dstIdx != srcIdx)
+ {
+ PX_ASSERT(dstIdx < mParticleCount || !(readData->flagsBuffer[mInputIdToParticleIndex[dstIdx]] & PxParticleFlag::eVALID));
+ mInputIdToParticleIndex[dstIdx] = pxIdx;
+ }
+
+ position = readData->positionBuffer[pxIdx],
+ velocity = readData->velocityBuffer[pxIdx],
+ collisionNormal = readData->collisionNormalBuffer[pxIdx],
+ particleFlags = readData->flagsBuffer[pxIdx],
+ density = isDensityValid ? static_cast<PxParticleFluidReadData*>(readData)->densityBuffer[pxIdx] : 0.0f;
+ }
+
+ unsigned int injIndex;
+ float benefit = simulateParticle(
+ NULL, injectorParamsList,
+ deltaTime, eyePos,
+ isNewParticle, srcIdx, dstIdx,
+ mBufDesc.pmaPositionMass->getPtr(), mBufDesc.pmaVelocityLife->getPtr(),
+ mBufDesc.pmaCollisionNormalFlags->getPtr(), mBufDesc.pmaUserData->getPtr(), mBufDesc.pmaActorIdentifiers->getPtr(),
+ mLifeSpan.getPtr(), mLifeTime.getPtr(), mBufDesc.pmaDensity ? mBufDesc.pmaDensity->getPtr() : NULL, mInjector.getPtr(),
+ fieldAccessor, injIndex,
+ mGridDensityParams,
+ position,
+ velocity,
+ collisionNormal,
+ particleFlags,
+ density
+ );
+
+ if (injIndex < mInjectorsCounters.getSize())
+ {
+ ++mInjectorsCounters[injIndex];
+ }
+
+ if (isNewParticle)
+ {
+ NewParticleData data;
+ data.destIndex = pxIdx;
+ data.position = position;
+ data.velocity = velocity;
+ mAddedParticleList.pushBack(data);
+
+ mBufDesc.pmaInStateToInput->get(maxStateID) = dstIdx | IosBufferDescIntl::NEW_PARTICLE_FLAG;
+ ++maxStateID;
+ }
+ else
+ {
+ mUpdateIndexBuffer.pushBack(pxIdx);
+ mUpdateVelocityBuffer.pushBack(velocity);
+
+ mNewIndices[srcIdx] = dstIdx;
+ }
+
+ mBenefit[dstIdx] = benefit;
+ if (benefit > -FLT_MAX)
+ {
+ mLastBenefitSum += benefit;
+ mLastBenefitMin = PxMin(mLastBenefitMin, benefit);
+ mLastBenefitMax = PxMax(mLastBenefitMax, benefit);
+ ++mLastActiveCount;
+ }
+ }
+
+ if (readData)
+ {
+ readData->unlock();
+ }
+
+ if (mUpdateIndexBuffer.size())
+ {
+ ((PxParticleBase*)mParticleActor)->setVelocities(mUpdateIndexBuffer.size(), PxStrideIterator<const uint32_t>(&mUpdateIndexBuffer[0]), PxStrideIterator<const PxVec3>(&mUpdateVelocityBuffer[0]));
+ }
+
+ if (mAddedParticleList.size())
+ {
+ PxParticleCreationData createData;
+ createData.numParticles = mAddedParticleList.size();
+ createData.positionBuffer = PxStrideIterator<const PxVec3>(&mAddedParticleList[0].position, sizeof(NewParticleData));
+ createData.velocityBuffer = PxStrideIterator<const PxVec3>(&mAddedParticleList[0].velocity, sizeof(NewParticleData));
+ createData.indexBuffer = PxStrideIterator<const uint32_t>(&mAddedParticleList[0].destIndex, sizeof(NewParticleData));
+ bool ok = ((PxParticleBase*)mParticleActor)->createParticles(createData);
+ PX_ASSERT(ok);
+ PX_UNUSED(ok);
+ }
+
+ //update stateToInput
+ for (uint32_t i = 0; i < mParticleCount; ++i)
+ {
+ uint32_t srcIdx = mBufDesc.pmaOutStateToInput->get(i);
+ PX_ASSERT(srcIdx < mParticleCount);
+ mBufDesc.pmaInStateToInput->get(i) = mNewIndices[srcIdx];
+ }
+ }
+ mParticleCount = targetCount;
+
+ /* Oh! Manager of the IOFX! do your thing */
+ mIofxMgr->updateEffectsData(deltaTime, mParticleCount, mParticleCount, maxStateID);
+}
+
+uint32_t ParticleIosActorCPU::computeHistogram(uint32_t dataCount, float dataMin, float dataMax, uint32_t& bound)
+{
+ const float* dataArray = mBenefit.getPtr();
+
+ uint32_t histogram[HISTOGRAM_BIN_COUNT];
+
+ //clear Histogram
+ for (uint32_t i = 0; i < HISTOGRAM_BIN_COUNT; ++i)
+ {
+ histogram[i] = 0;
+ }
+
+ float factor = HISTOGRAM_BIN_COUNT / (dataMax - dataMin);
+ //accum Histogram
+ for (uint32_t i = 0; i < dataCount; ++i)
+ {
+ float data = dataArray[i];
+ if (data >= dataMin && data < dataMax)
+ {
+ int32_t bin = int32_t((data - dataMin) * factor);
+ ++histogram[bin];
+ }
+ }
+ //compute CDF from Histogram
+ uint32_t countSum = 0;
+ for (uint32_t i = 0; i < HISTOGRAM_BIN_COUNT; ++i)
+ {
+ uint32_t count = histogram[i];
+ countSum += count;
+ histogram[i] = countSum;
+ }
+
+ PX_ASSERT(countSum == mLastActiveCount + mInjectedCount);
+
+ //binary search in CDF
+ uint32_t beg = 0;
+ uint32_t end = HISTOGRAM_BIN_COUNT;
+ while (beg < end)
+ {
+ uint32_t mid = beg + ((end - beg) >> 1);
+ if (bound > histogram[mid])
+ {
+ beg = mid + 1;
+ }
+ else
+ {
+ end = mid;
+ }
+ }
+
+ PX_ASSERT(histogram[beg] >= bound);
+ if (beg > 0)
+ {
+ bound -= histogram[beg - 1];
+ }
+
+ return beg;
+}
+
+}
+} // end namespace nvidia
+
+