diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/module/emitter/src/EmitterGeomExplicitImpl.cpp | |
| download | physx-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/emitter/src/EmitterGeomExplicitImpl.cpp')
| -rw-r--r-- | APEX_1.4/module/emitter/src/EmitterGeomExplicitImpl.cpp | 830 |
1 files changed, 830 insertions, 0 deletions
diff --git a/APEX_1.4/module/emitter/src/EmitterGeomExplicitImpl.cpp b/APEX_1.4/module/emitter/src/EmitterGeomExplicitImpl.cpp new file mode 100644 index 00000000..ed63cc79 --- /dev/null +++ b/APEX_1.4/module/emitter/src/EmitterGeomExplicitImpl.cpp @@ -0,0 +1,830 @@ +/* + * 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 "Apex.h" +#include "ApexUsingNamespace.h" +#include "PsSort.h" +#include "PsMathUtils.h" +#include "PsHashSet.h" +#include "EmitterAsset.h" +#include "EmitterGeomExplicitImpl.h" +//#include "ApexSharedSerialization.h" +#include "RenderDebugInterface.h" +#include "RenderDebugInterface.h" +#include "ApexPreview.h" +#include "EmitterGeomExplicitParams.h" +#include "ParamArray.h" + +namespace nvidia +{ +namespace emitter +{ + +PX_INLINE static void GetNormals(const PxVec3& n, PxVec3& t1, PxVec3& t2) +{ + PxVec3 nabs(PxAbs(n.x), PxAbs(n.y), PxAbs(n.z)); + + t1 = nabs.x <= nabs.y && nabs.x <= nabs.z + ? PxVec3(0, -n.z, n.y) + : nabs.y <= nabs.x && nabs.y <= nabs.z ? PxVec3(-n.z, 0, n.x) + : PxVec3(-n.y, n.x, 0); + t1.normalize(); + + t2 = n.cross(t1); + t2.normalize(); +} + +EmitterGeomExplicitImpl::EmitterGeomExplicitImpl(NvParameterized::Interface* params) +{ + mGeomParams = (EmitterGeomExplicitParams*)params; + + mDistance = mGeomParams->distance; + if (mDistance < PX_EPS_F32) + { + mInvDistance = PX_MAX_F32; + } + else + { + mInvDistance = 1 / mDistance; + } + + // get points + mPoints.resize((uint32_t)mGeomParams->points.positions.arraySizes[0]); + if (!mPoints.empty()) + { + PX_COMPILE_TIME_ASSERT(sizeof(PointParams) == sizeof(mGeomParams->points.positions.buf[0])); + memcpy(&mPoints[0], mGeomParams->points.positions.buf, mPoints.size() * sizeof(PointParams)); + } + + // get point velocities + for (uint32_t i = 0; i < (uint32_t)mGeomParams->points.velocities.arraySizes[0]; i++) + { + mVelocities.pushBack(mGeomParams->points.velocities.buf[i]); + } + + // get spheres + mSpheres.resize((uint32_t)mGeomParams->spheres.positions.arraySizes[0]); + if (!mSpheres.empty()) + { + PX_COMPILE_TIME_ASSERT(sizeof(SphereParams) == sizeof(mGeomParams->spheres.positions.buf[0])); + memcpy(&mSpheres[0], mGeomParams->spheres.positions.buf, mSpheres.size() * sizeof(SphereParams)); + } + + // get sphere velocities + for (int32_t i = 0; i < mGeomParams->spheres.velocities.arraySizes[0]; i++) + { + mSphereVelocities.pushBack(mGeomParams->spheres.velocities.buf[i]); + } + + // get ellipsoids + mEllipsoids.resize((uint32_t)mGeomParams->ellipsoids.positions.arraySizes[0]); + if (!mEllipsoids.empty()) + { + PX_COMPILE_TIME_ASSERT(sizeof(EllipsoidParams) == sizeof(mGeomParams->ellipsoids.positions.buf[0])); + memcpy(&mEllipsoids[0], mGeomParams->ellipsoids.positions.buf, mEllipsoids.size() * sizeof(EllipsoidParams)); + } + + // get ellipsoid velocities + for (int32_t i = 0; i < mGeomParams->ellipsoids.velocities.arraySizes[0]; i++) + { + mEllipsoidVelocities.pushBack(mGeomParams->ellipsoids.velocities.buf[i]); + } + + updateCollisions(); +} + +EmitterGeomExplicitImpl::EmitterGeomExplicitImpl() : + mDistance(0.0f), + mInvDistance(PX_MAX_F32), + mGeomParams(NULL) +{} + +EmitterGeom* EmitterGeomExplicitImpl::getEmitterGeom() +{ + return this; +} + +#ifdef WITHOUT_DEBUG_VISUALIZE +void EmitterGeomExplicitImpl::visualize(const PxTransform& , RenderDebugInterface&) +{ +} +#else +void EmitterGeomExplicitImpl::visualize(const PxTransform& pose, RenderDebugInterface& renderDebug) +{ + using RENDER_DEBUG::DebugColors; + RENDER_DEBUG_IFACE(&renderDebug)->pushRenderState(); + + RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::DarkGreen)); + + RENDER_DEBUG_IFACE(&renderDebug)->setPose(pose); + + PxVec3 pos; + for (uint32_t i = 0; i < mPoints.size(); ++i) + { + RENDER_DEBUG_IFACE(&renderDebug)->debugPoint(pos, 0.01f); + } + + for (uint32_t i = 0; i < mSpheres.size(); ++i) + { + RENDER_DEBUG_IFACE(&renderDebug)->debugSphere(mSpheres[i].center, mSpheres[i].radius); + } + + for (uint32_t i = 0; i < mEllipsoids.size(); ++i) + { + PxVec3 n = mEllipsoids[i].normal, t1, t2; + GetNormals(n, t1, t2); + + PxMat44 unitSphereToEllipsoid( + mEllipsoids[i].radius * t1, + mEllipsoids[i].radius * t2, + mEllipsoids[i].polarRadius * n, + mEllipsoids[i].center + ); + + RENDER_DEBUG_IFACE(&renderDebug)->setPose(pose * PxTransform(unitSphereToEllipsoid)); + + RENDER_DEBUG_IFACE(&renderDebug)->debugSphere(PxVec3(0.0f), 1.0f); + } + + RENDER_DEBUG_IFACE(&renderDebug)->popRenderState(); +} +#endif + +#ifdef WITHOUT_DEBUG_VISUALIZE +void EmitterGeomExplicitImpl::drawPreview(float , RenderDebugInterface*) const +{ +} +#else +void EmitterGeomExplicitImpl::drawPreview(float scale, RenderDebugInterface* renderDebug) const +{ + using RENDER_DEBUG::DebugColors; + RENDER_DEBUG_IFACE(renderDebug)->pushRenderState(); + RENDER_DEBUG_IFACE(renderDebug)->setCurrentColor(RENDER_DEBUG_IFACE(renderDebug)->getDebugColor(DebugColors::DarkGreen), + RENDER_DEBUG_IFACE(renderDebug)->getDebugColor(DebugColors::DarkGreen)); + + PxVec3 pos; + for (uint32_t i = 0 ; i < mPoints.size() ; i++) + { + pos = mPoints[i].position; + RENDER_DEBUG_IFACE(renderDebug)->debugPoint(pos, scale); + } + + for (uint32_t i = 0; i < mSpheres.size(); ++i) + { + RENDER_DEBUG_IFACE(renderDebug)->debugSphere(mSpheres[i].center, mSpheres[i].radius * scale); + } + + for (uint32_t i = 0; i < mEllipsoids.size(); ++i) + { + PxVec3 n = mEllipsoids[i].normal, t1, t2; + GetNormals(n, t1, t2); + + PxMat44 unitSphereToEllipsoid( + mEllipsoids[i].radius * t1, + mEllipsoids[i].radius * t2, + mEllipsoids[i].polarRadius * n, + mEllipsoids[i].center + ); + + RENDER_DEBUG_IFACE(renderDebug)->setPose(unitSphereToEllipsoid); + + RENDER_DEBUG_IFACE(renderDebug)->debugSphere(PxVec3(0.0f), scale); + } + + RENDER_DEBUG_IFACE(renderDebug)->popRenderState(); +} +#endif + +/* ApexEmitterActor callable methods */ + +void EmitterGeomExplicitImpl::updateAssetPoints() +{ + if (!mGeomParams) + { + return; + } + + // just copy the position and velocity lists to mGeomParams + + NvParameterized::Handle h(*mGeomParams); + NvParameterized::ErrorType pError; + + // Update positions + + pError = mGeomParams->getParameterHandle("points.positions", h); + PX_ASSERT(pError == NvParameterized::ERROR_NONE); + + pError = h.resizeArray((int32_t)mPoints.size()); + PX_ASSERT(pError == NvParameterized::ERROR_NONE); + + PX_COMPILE_TIME_ASSERT(sizeof(PointParams) == sizeof(mGeomParams->points.positions.buf[0])); + memcpy(&mGeomParams->points.positions.buf[0], &mPoints[0], mPoints.size()); + + // velocities may or may not exist, handle this + pError = mGeomParams->getParameterHandle("velocities", h); + if (pError == NvParameterized::ERROR_NONE) + { + pError = mGeomParams->resizeArray(h, (int32_t)mVelocities.size()); + PX_ASSERT(pError == NvParameterized::ERROR_NONE); + + pError = h.setParamVec3Array(&mVelocities[0], (int32_t)mVelocities.size()); + PX_ASSERT(pError == NvParameterized::ERROR_NONE); + } +} + +void EmitterGeomExplicitImpl::addParticleList( + uint32_t count, + const PointParams* params, + const PxVec3* velocities) +{ + if (velocities) + { + mVelocities.resize(mPoints.size(), PxVec3(0.0f)); + } + + for (uint32_t i = 0 ; i < count ; i++) + { + mPoints.pushBack(*params++); + + if (velocities) + { + mVelocities.pushBack(*velocities++); + } + } + + updateCollisions(); + updateAssetPoints(); +} + +void EmitterGeomExplicitImpl::addParticleList(uint32_t count, + const PxVec3* positions, + const PxVec3* velocities) +{ + if (velocities) + { + mVelocities.resize(mPoints.size(), PxVec3(0.0f)); + } + + for (uint32_t i = 0 ; i < count ; i++) + { + PointParams params = { positions[i], false }; + mPoints.pushBack(params); + + if (velocities) + { + mVelocities.pushBack(velocities[i]); + } + } + + updateCollisions(); + updateAssetPoints(); +} + +void EmitterGeomExplicitImpl::addParticleList(uint32_t count, + const PointListData& data) +{ + if (data.velocityStart != NULL) + { + mVelocities.resize(mPoints.size(), PxVec3(0.0f)); + } + if (data.userDataStart != NULL) + { + mPointsUserData.resize(mPoints.size(), 0); + } + + const uint8_t* positionCurr = static_cast<const uint8_t*>(data.positionStart); + const uint8_t* velocityCurr = static_cast<const uint8_t*>(data.velocityStart); + const uint8_t* userDataCurr = static_cast<const uint8_t*>(data.userDataStart); + + for (uint32_t i = 0 ; i < count ; i++) + { + const PxVec3& position = *reinterpret_cast<const PxVec3*>(positionCurr); + positionCurr += data.positionStrideBytes; + + PointParams params = { position, false }; + mPoints.pushBack(params); + + if (velocityCurr != NULL) + { + const PxVec3& velocity = *reinterpret_cast<const PxVec3*>(velocityCurr); + velocityCurr += data.velocityStrideBytes; + + mVelocities.pushBack(velocity); + } + if (userDataCurr != NULL) + { + const uint32_t userData = *reinterpret_cast<const uint32_t*>(userDataCurr); + userDataCurr += data.userDataStrideBytes; + + mPointsUserData.pushBack(userData); + } + } + + updateCollisions(); + updateAssetPoints(); +} + +void EmitterGeomExplicitImpl::addSphereList( + uint32_t count, + const SphereParams* params, + const PxVec3* velocities) +{ + if (velocities) + { + mSphereVelocities.resize(mSpheres.size(), PxVec3(0.0f)); + } + + for (uint32_t i = 0 ; i < count ; i++) + { + mSpheres.pushBack(*params++); + + if (velocities) + { + mSphereVelocities.pushBack(*velocities++); + } + } + + updateCollisions(); + + // just copy the position and velocity lists to mGeomParams + if (!mGeomParams) + { + return; + } + + NvParameterized::Handle h(*mGeomParams); + NvParameterized::ErrorType pError; + + // Update positions + + pError = mGeomParams->getParameterHandle("spheres.positions", h); + PX_ASSERT(pError == NvParameterized::ERROR_NONE); + + pError = h.resizeArray((int32_t)mSpheres.size()); + PX_ASSERT(pError == NvParameterized::ERROR_NONE); + + PX_COMPILE_TIME_ASSERT(sizeof(SphereParams) == sizeof(mGeomParams->spheres.positions.buf[0])); + memcpy(mGeomParams->spheres.positions.buf, &mSpheres[0], mSpheres.size() * sizeof(SphereParams)); + + // velocities may or may not exist, handle this + pError = mGeomParams->getParameterHandle("spheres.velocities", h); + if (pError == NvParameterized::ERROR_NONE) + { + pError = mGeomParams->resizeArray(h, (int32_t)mSphereVelocities.size()); + PX_ASSERT(pError == NvParameterized::ERROR_NONE); + + h.setParamVec3Array(&mSphereVelocities[0], (int32_t)mSphereVelocities.size()); + } +} + +void EmitterGeomExplicitImpl::addEllipsoidList( + uint32_t count, + const EllipsoidParams* params, + const PxVec3* velocities) +{ + if (velocities) + { + mEllipsoidVelocities.resize(mEllipsoids.size(), PxVec3(0.0f)); + } + + for (uint32_t i = 0 ; i < count ; i++) + { + mEllipsoids.pushBack(*params++); + + if (velocities) + { + mEllipsoidVelocities.pushBack(*velocities++); + } + } + + updateCollisions(); + + // just copy the position and velocity lists to mGeomParams + if (!mGeomParams) + { + return; + } + + NvParameterized::Handle h(*mGeomParams); + NvParameterized::ErrorType pError; + + // Update positions + + pError = mGeomParams->getParameterHandle("ellipsoids.positions", h); + PX_ASSERT(pError == NvParameterized::ERROR_NONE); + + pError = h.resizeArray((int32_t)mEllipsoids.size()); + PX_ASSERT(pError == NvParameterized::ERROR_NONE); + + PX_COMPILE_TIME_ASSERT(sizeof(EllipsoidParams) == sizeof(mGeomParams->ellipsoids.positions.buf[0])); + memcpy(mGeomParams->ellipsoids.positions.buf, &mEllipsoids[0], mEllipsoids.size() * sizeof(EllipsoidParams)); + + // velocities may or may not exist, handle this + pError = mGeomParams->getParameterHandle("ellipsoids.velocities", h); + if (pError == NvParameterized::ERROR_NONE) + { + pError = mGeomParams->resizeArray(h, (int32_t)mEllipsoidVelocities.size()); + PX_ASSERT(pError == NvParameterized::ERROR_NONE); + + h.setParamVec3Array(&mEllipsoidVelocities[0], (int32_t)mEllipsoidVelocities.size()); + } +} + +void EmitterGeomExplicitImpl::getParticleList( + const PointParams* ¶ms, + uint32_t& numPoints, + const PxVec3* &velocities, + uint32_t& numVelocities) const +{ + numPoints = mPoints.size(); + params = numPoints ? &mPoints[0] : 0; + + numVelocities = mVelocities.size(); + velocities = numVelocities ? &mVelocities[0] : 0; +} + +void EmitterGeomExplicitImpl::getSphereList( + const SphereParams* ¶ms, + uint32_t& numSpheres, + const PxVec3* &velocities, + uint32_t& numVelocities) const +{ + numSpheres = mSpheres.size(); + params = numSpheres ? &mSpheres[0] : 0; + + numVelocities = mSphereVelocities.size(); + velocities = numVelocities ? &mSphereVelocities[0] : 0; +} + +void EmitterGeomExplicitImpl::getEllipsoidList( + const EllipsoidParams* ¶ms, + uint32_t& numEllipsoids, + const PxVec3* &velocities, + uint32_t& numVelocities) const +{ + numEllipsoids = mEllipsoids.size(); + params = numEllipsoids ? &mEllipsoids[0] : 0; + + numVelocities = mSphereVelocities.size(); + velocities = numVelocities ? &mSphereVelocities[0] : 0; +} + +#define EPS 0.001f + +bool EmitterGeomExplicitImpl::isInside(const PxVec3& x, uint32_t shapeIdx) const +{ + if (!mBboxes[shapeIdx].contains(x)) + { + return false; + } + + uint32_t nspheres = mSpheres.size(), + nellipsoids = mEllipsoids.size(); + + if (shapeIdx < nspheres) // Sphere + { + const SphereParams& sphere = mSpheres[shapeIdx]; + return PxAbs((x - sphere.center).magnitudeSquared() - sphere.radius * sphere.radius) < EPS; + } + else if (shapeIdx < nspheres + nellipsoids) // Ellipsoid + { + const EllipsoidParams& ellipsoid = mEllipsoids[shapeIdx - nspheres]; + + PxVec3 y(x - ellipsoid.center); + + PxVec3 n(ellipsoid.normal); + n.normalize(); + + float normalProj = y.dot(n); + + PxVec3 planeProj = y - normalProj * n; + float planeProjMag2 = planeProj.magnitudeSquared(); + + float R2 = ellipsoid.radius * ellipsoid.radius, + Rp2 = ellipsoid.polarRadius * ellipsoid.polarRadius; + + if (planeProjMag2 > R2 + EPS) + { + return false; + } + + return normalProj * normalProj < EPS + Rp2 * (1.0f - 1.0f / R2 * planeProjMag2); + } + else // Point + { + return (x - mPoints[shapeIdx - nspheres - nellipsoids].position).magnitudeSquared() < EPS; + } +} + +void EmitterGeomExplicitImpl::AddParticle( + physx::Array<PxVec3>& positions, physx::Array<PxVec3>& velocities, + physx::Array<uint32_t>* userDataArrayPtr, + const PxTransform& pose, float cutoff, PxBounds3& outBounds, + const PxVec3& pos, const PxVec3& vel, uint32_t userData, + uint32_t srcShapeIdx, + QDSRand& rand) const +{ + float r = rand.getScaled(0, 1); + if (r > cutoff) + { + return; + } + + PxVec3 randPos = pos + PxVec3( + rand.getScaled(-mDistance, mDistance), + rand.getScaled(-mDistance, mDistance), + rand.getScaled(-mDistance, mDistance)); + + // Check collisions + for (uint32_t i = 0; i < mCollisions[srcShapeIdx].next; ++i) + { + uint32_t collisionShapeIdx = mCollisions[srcShapeIdx].shapeIndices[i]; + + // If colliding body was already processed and point lies in this body + if (collisionShapeIdx < srcShapeIdx && isInside(pos, collisionShapeIdx)) + { + return; + } + } + + /* if absolute positions are submitted, pose will be at origin */ + if (pose == PxTransform(PxIdentity)) + { + positions.pushBack(randPos); + velocities.pushBack(vel); + } + else + { + positions.pushBack(pose.transform(randPos)); + velocities.pushBack(pose.rotate(vel)); + } + + if (userDataArrayPtr) + { + userDataArrayPtr->pushBack(userData); + } + + outBounds.include(positions.back()); +} + +void EmitterGeomExplicitImpl::computeFillPositions( + physx::Array<PxVec3>& positions, + physx::Array<PxVec3>& velocities, + physx::Array<uint32_t>* userDataArrayPtr, + const PxTransform& pose, + const PxVec3& scale, + float density, + PxBounds3& outBounds, + QDSRand& rand) const +{ + PX_UNUSED(scale); + uint32_t shapeIdx = 0; // Global shape index + + for (uint32_t i = 0; i < mPoints.size(); ++i, ++shapeIdx) + { + const uint32_t pointUserData = i < mPointsUserData.size() ? mPointsUserData[i] : 0; + + AddParticle( + positions, velocities, userDataArrayPtr, + pose, density, outBounds, + mPoints[i].position, i >= mVelocities.size() ? PxVec3(0.0f) : mVelocities[i], pointUserData, + shapeIdx, + rand + ); + } + + for (uint32_t i = 0; i < mSpheres.size(); ++i, ++shapeIdx) + { + PxVec3 c = mSpheres[i].center; + float R = mSpheres[i].radius; + + const uint32_t sphereUserData = 0; + + float RR = R * R; + + int32_t nx = (int32_t)(R * mInvDistance); + + for (int32_t j = -nx; j < nx; ++j) + { + float x = j * mDistance, + xx = x * x; + + float yext = PxSqrt(PxMax(0.0f, RR - xx)); + int32_t ny = (int32_t)(yext * mInvDistance); + + for (int32_t k = -ny; k < ny; ++k) + { + float y = k * mDistance; + + float zext = PxSqrt(PxMax(0.0f, RR - xx - y * y)); + int32_t nz = (int32_t)(zext * mInvDistance); + + for (int32_t l = -nz; l < nz; ++l) + { + float z = l * mDistance; + + AddParticle( + positions, velocities, userDataArrayPtr, + pose, density, outBounds, + c + PxVec3(x, y, z), + i >= mSphereVelocities.size() ? PxVec3(0.0f) : mSphereVelocities[i], sphereUserData, + shapeIdx, + rand + ); + } //l + } //k + } //j + } //i + + for (uint32_t i = 0; i < mEllipsoids.size(); ++i, ++shapeIdx) + { + PxVec3 c = mEllipsoids[i].center, + n = mEllipsoids[i].normal; + + const uint32_t ellipsoidUserData = 0; + + // TODO: precompute this stuff? + + float R = mEllipsoids[i].radius, + Rp = mEllipsoids[i].polarRadius; + + PxVec3 t1, t2; + GetNormals(n, t1, t2); + + float RR = R * R, + Rp_R = PxAbs(Rp / R); + + int32_t nx = (int32_t)(R * mInvDistance); + for (int32_t j = -nx; j <= nx ; ++j) + { + float x = j * mDistance, + xx = x * x; + + float yext = PxSqrt(PxMax(0.0f, RR - xx)); + int32_t ny = (int32_t)(yext * mInvDistance); + + for (int32_t k = -ny; k <= ny; ++k) + { + float y = k * mDistance; + + float zext = Rp_R * PxSqrt(PxMax(0.0f, RR - xx - y * y)); + int32_t nz = (int32_t)(zext * mInvDistance); + + int32_t lmax = Rp < 0 ? 0 : nz; // Check for half-ellipsoid + for (int32_t l = -nz; l <= lmax; ++l) + { + float z = l * mDistance; + + AddParticle( + positions, velocities, userDataArrayPtr, + pose, density, outBounds, + c + x * t1 + y * t2 + z * n, + i >= mEllipsoidVelocities.size() ? PxVec3(0.0f) : mEllipsoidVelocities[i], ellipsoidUserData, + shapeIdx, + rand + ); + } //l + } //k + } //j + } //i +} + +struct EndPoint +{ + float val; + + uint32_t boxIdx; + bool isLeftPoint; + + EndPoint(float v, uint32_t idx, bool left) + : val(v), boxIdx(idx), isLeftPoint(left) {} + + PX_INLINE static bool isLessThan(const EndPoint& p1, const EndPoint& p2) + { + if (p1.val < p2.val) + { + return true; + } + + // Adjacent shapes do intersect + if (p1.val == p2.val) + { + return p1.isLeftPoint && !p2.isLeftPoint; + } + + return false; + } +}; + +void EmitterGeomExplicitImpl::updateCollisions() +{ + uint32_t npoints = mPoints.size(), + nspheres = mSpheres.size(), + nellipsoids = mEllipsoids.size(); + + mCollisions.reset(); + + uint32_t ntotal = npoints + nspheres + nellipsoids; + if (!ntotal) + { + return; + } + + mBboxes.resize(ntotal); + mCollisions.resize(ntotal); + + physx::Array<bool> doDetectOverlaps(ntotal); + + // TODO: use custom axis instead of Ox + // E.g. (sx, sy, sz) or simply choose the best of Ox, Oy, Oz + + for (uint32_t i = 0; i < nspheres; ++i) + { + PxVec3 r3(mSpheres[i].radius); + + mBboxes[i] = PxBounds3(mSpheres[i].center - r3, mSpheres[i].center + r3); + doDetectOverlaps[i] = mSpheres[i].doDetectOverlaps; + } + + for (uint32_t i = 0; i < nellipsoids; ++i) + { + PxVec3 r3(mEllipsoids[i].radius, mEllipsoids[i].radius, mEllipsoids[i].polarRadius); + PxBounds3 localBox(-r3, r3); + + PxVec3 n = mEllipsoids[i].normal; + n.normalize(); + + PxMat33 T = physx::shdfnd::rotFrom2Vectors(PxVec3(0, 0, 1), n); + + if(!localBox.isValid()) + { + localBox.setEmpty(); + } + + localBox = PxBounds3::transformFast(T, localBox); + localBox.minimum += mEllipsoids[i].center; + localBox.maximum += mEllipsoids[i].center; + + mBboxes[nspheres + i] = localBox; + doDetectOverlaps[nspheres + i] = mEllipsoids[i].doDetectOverlaps; + } + + for (uint32_t i = 0; i < npoints; ++i) + { + mBboxes[nspheres + nellipsoids + i] = PxBounds3(mPoints[i].position, mPoints[i].position); + doDetectOverlaps[nspheres + nellipsoids + i] = mPoints[i].doDetectOverlaps; + } + + physx::Array<EndPoint> endPoints; + endPoints.reserve(2 * ntotal); + for (uint32_t i = 0; i < ntotal; ++i) + { + endPoints.pushBack(EndPoint(mBboxes[i].minimum.x, i, true)); + endPoints.pushBack(EndPoint(mBboxes[i].maximum.x, i, false)); + } + + nvidia::sort(&endPoints[0], endPoints.size(), EndPoint::isLessThan); + + nvidia::HashSet<uint32_t> openedBoxes; + for (uint32_t i = 0; i < endPoints.size(); ++i) + { + uint32_t boxIdx = endPoints[i].boxIdx; + + if (endPoints[i].isLeftPoint) + { + for (nvidia::HashSet<uint32_t>::Iterator j = openedBoxes.getIterator(); !j.done(); ++j) + { + if (!doDetectOverlaps[boxIdx] || !doDetectOverlaps[*j]) + { + break; + } + + if (!mBboxes[*j].intersects(mBboxes[boxIdx])) + { + continue; + } + + mCollisions[boxIdx].pushBack(*j); + mCollisions[*j].pushBack(boxIdx); + } //j + + openedBoxes.insert(boxIdx); + } + else + { + PX_ASSERT(openedBoxes.contains(boxIdx)); + openedBoxes.erase(boxIdx); + } + } //i +} + +} +} // namespace nvidia::apex |