From 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 Mon Sep 17 00:00:00 2001 From: git perforce import user Date: Tue, 25 Oct 2016 12:29:14 -0600 Subject: Initial commit: PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167] --- .../LowLevelParticles/src/PtSpatialLocalHash.cpp | 173 +++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 PhysX_3.4/Source/LowLevelParticles/src/PtSpatialLocalHash.cpp (limited to 'PhysX_3.4/Source/LowLevelParticles/src/PtSpatialLocalHash.cpp') diff --git a/PhysX_3.4/Source/LowLevelParticles/src/PtSpatialLocalHash.cpp b/PhysX_3.4/Source/LowLevelParticles/src/PtSpatialLocalHash.cpp new file mode 100644 index 00000000..82a3ac28 --- /dev/null +++ b/PhysX_3.4/Source/LowLevelParticles/src/PtSpatialLocalHash.cpp @@ -0,0 +1,173 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PtSpatialHashHelper.h" +#if PX_USE_PARTICLE_SYSTEM_API + +#include "PtSpatialHash.h" +#include "PtParticle.h" +#include "PsUtilities.h" + +/*! +Builds local hash and reorders particle index table. +*/ +void physx::Pt::SpatialHash::buildLocalHash(const Particle* particles, PxU32 numParticles, ParticleCell* cells, + PxU32* particleIndices, PxU16* hashKeyArray, PxU32 numHashBuckets, + PxF32 cellSizeInv, const PxVec3& packetCorner) +{ + PX_ASSERT(particles); + PX_ASSERT(cells); + PX_ASSERT(particleIndices); + PX_ASSERT(numHashBuckets > numParticles); // Needs to be larger to have at least one empty hash bucket (required to + // detect invalid cells). + + // Mark packet cell entries as empty. + for(PxU32 c = 0; c < numHashBuckets; c++) + cells[c].numParticles = PX_INVALID_U32; + + PX_ALIGN(16, Particle fakeParticle); + fakeParticle.position = PxVec3(FLT_MAX, FLT_MAX, FLT_MAX); + + PxU32 numParticles4 = ((numParticles + 3) & ~0x3) + 4; // ceil up to multiple of four + 4 for save unrolling + + // Add particles to cell hash + + const Particle* prt0 = particles; + const Particle* prt1 = (1 < numParticles) ? particles + 1 : &fakeParticle; + const Particle* prt2 = (2 < numParticles) ? particles + 2 : &fakeParticle; + const Particle* prt3 = (3 < numParticles) ? particles + 3 : &fakeParticle; + + struct Int32Vec3 + { + PX_FORCE_INLINE void set(const PxVec3& realVec, const PxF32 scale) + { + x = static_cast(Ps::floor(realVec.x * scale)); + y = static_cast(Ps::floor(realVec.y * scale)); + z = static_cast(Ps::floor(realVec.z * scale)); + } + PxI32 x; + PxI32 y; + PxI32 z; + }; + + PX_ALIGN(16, Int32Vec3 cellCoords[8]); + cellCoords[0].set(prt0->position - packetCorner, cellSizeInv); + cellCoords[1].set(prt1->position - packetCorner, cellSizeInv); + cellCoords[2].set(prt2->position - packetCorner, cellSizeInv); + cellCoords[3].set(prt3->position - packetCorner, cellSizeInv); + + for(PxU32 p = 0; p < numParticles4; p += 4) + { + const Particle* prt0_N = (p + 4 < numParticles) ? particles + p + 4 : &fakeParticle; + const Particle* prt1_N = (p + 5 < numParticles) ? particles + p + 5 : &fakeParticle; + const Particle* prt2_N = (p + 6 < numParticles) ? particles + p + 6 : &fakeParticle; + const Particle* prt3_N = (p + 7 < numParticles) ? particles + p + 7 : &fakeParticle; + + PxU32 wIndex = (p + 4) & 7; + cellCoords[wIndex].set(prt0_N->position - packetCorner, cellSizeInv); + cellCoords[wIndex + 1].set(prt1_N->position - packetCorner, cellSizeInv); + cellCoords[wIndex + 2].set(prt2_N->position - packetCorner, cellSizeInv); + cellCoords[wIndex + 3].set(prt3_N->position - packetCorner, cellSizeInv); + + PxU32 rIndex = p & 7; + for(PxU32 i = 0; i < 4; ++i) + { + if(p + i < numParticles) + { + const Int32Vec3& int32Vec3 = cellCoords[rIndex + i]; + const GridCellVector cellCoord(PxI16(int32Vec3.x), PxI16(int32Vec3.y), PxI16(int32Vec3.z)); + PxU32 hashKey = getCellIndex(cellCoord, cells, numHashBuckets); + PX_ASSERT(hashKey < PT_PARTICLE_SYSTEM_HASH_KEY_LIMIT); + ParticleCell* cell = &cells[hashKey]; + hashKeyArray[p + i] = Ps::to16(hashKey); + PX_ASSERT(cell); + + if(cell->numParticles == PX_INVALID_U32) + { + // Entry is empty -> Initialize new entry + cell->coords = cellCoord; + cell->numParticles = 1; // this avoids some LHS + } + else + { + cell->numParticles++; // this avoids some LHS + } + PX_ASSERT(cell->numParticles != PX_INVALID_U32); + } + } + } + + // Set for each cell the starting index of the associated particle index interval. + PxU32 cellFirstParticle = 0; + for(PxU32 c = 0; c < numHashBuckets; c++) + { + ParticleCell& cell = cells[c]; + + if(cell.numParticles == PX_INVALID_U32) + continue; + + cell.firstParticle = cellFirstParticle; + cellFirstParticle += cell.numParticles; + } + + reorderParticleIndicesToCells(particles, numParticles, cells, particleIndices, numHashBuckets, hashKeyArray); +} + +/*! +Reorders particle indices to cells. +*/ +void physx::Pt::SpatialHash::reorderParticleIndicesToCells(const Particle* /*particles*/, PxU32 numParticles, + ParticleCell* cells, PxU32* particleIndices, + PxU32 numHashBuckets, PxU16* hashKeyArray) +{ + for(PxU32 c = 0; c < numHashBuckets; c++) + { + ParticleCell& cell = cells[c]; + if(cell.numParticles == PX_INVALID_U32) + continue; + + cell.numParticles = 0; + } + + // Reorder particle indices according to cells + for(PxU32 p = 0; p < numParticles; p++) + { + // Get cell for fluid + ParticleCell* cell; + cell = &cells[hashKeyArray[p]]; + + PX_ASSERT(cell); + PX_ASSERT(cell->numParticles != PX_INVALID_U32); + + particleIndices[cell->firstParticle + cell->numParticles] = p; + cell->numParticles++; + } +} + +#endif // PX_USE_PARTICLE_SYSTEM_API -- cgit v1.2.3