예제 #1
0
파일: PsMathUtils.cpp 프로젝트: panmar/pg2
	PxQuat slerp(const PxReal t, const PxQuat& left, const PxQuat& right) 
	{
		const PxReal quatEpsilon = (PxReal(1.0e-8f));

		PxReal cosine = left.dot(right);
		PxReal sign = PxReal(1);
		if (cosine < 0)
		{
			cosine = -cosine;
			sign = PxReal(-1);
		}

		PxReal sine = PxReal(1) - cosine*cosine;

		if(sine>=quatEpsilon*quatEpsilon)	
		{
			sine = PxSqrt(sine);
			const PxReal angle = PxAtan2(sine, cosine);
			const PxReal i_sin_angle = PxReal(1) / sine;

			const PxReal leftw = PxSin(angle*(PxReal(1)-t)) * i_sin_angle;
			const PxReal rightw = PxSin(angle * t) * i_sin_angle * sign;

			return left * leftw + right * rightw;
		}

		return left;
	}
예제 #2
0
void FixedStepper::substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize)
{
	if(mAccumulator > mFixedSubStepSize)
		mAccumulator = 0.0f;

	// don't step less than the step size, just accumulate
	mAccumulator  += stepSize;
	if(mAccumulator < mFixedSubStepSize)
	{
		substepCount = 0;
		return;
	}

	substepSize = mFixedSubStepSize;
	substepCount = PxMin(PxU32(mAccumulator/mFixedSubStepSize), mMaxSubSteps);

	mAccumulator -= PxReal(substepCount)*substepSize;
}
예제 #3
0
void VariableStepper::substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize)
{
	if(mAccumulator > mMaxSubStepSize)
		mAccumulator = 0.0f;

	// don't step less than the min step size, just accumulate
	mAccumulator  += stepSize;
	if(mAccumulator < mMinSubStepSize)
	{
		substepCount = 0;
		return;
	}

	substepCount = PxMin(PxU32(PxCeil(mAccumulator/mMaxSubStepSize)), mMaxSubSteps);
	substepSize = PxMin(mAccumulator/substepCount, mMaxSubStepSize);

	mAccumulator -= PxReal(substepCount)*substepSize;
}
예제 #4
0
void PxsFluidDynamics::updatePacketLocalHash(PxsSphUpdateType updateType, PxVec3* forceBuf, PxsFluidParticle* particles, const PxsParticleCell& packet,
											 const PxsFluidPacketSections& packetSections, const PxsFluidPacketHaloRegions& haloRegions, 
											 PxsFluidDynamicsTempBuffers& tempBuffers)
{
	// Particle index lists for local hash of particle cells (for two subpackets A and B).
	PxU32* particleIndicesSpA = tempBuffers.indicesSubpacketA;
	PxU32* particleIndicesSpB = tempBuffers.indicesSubpacketB;

	// Local hash tables for particle cells (for two subpackets A and B).
	PxsParticleCell* particleCellsSpA = tempBuffers.cellHashTableSubpacketA;
	PxsParticleCell* particleCellsSpB = tempBuffers.cellHashTableSubpacketB;

	PxVec3 packetCorner = PxVec3(PxReal(packet.coords.x), PxReal(packet.coords.y), PxReal(packet.coords.z)) * mParams.packetSize;

	PxU32 particlesLeftA0 = packet.numParticles;
	PxsFluidParticle* particlesSpA0 = particles + packet.firstParticle;
	PxVec3* forceBufA0 = forceBuf + packet.firstParticle;

	while (particlesLeftA0)
	{
		PxU32 numParticlesSpA = PxMin(particlesLeftA0, static_cast<PxU32>(PXS_FLUID_SUBPACKET_PARTICLE_LIMIT_FORCE_DENSITY));

		// Make sure the number of hash buckets is a power of 2 (requirement for the used hash function)
		const PxU32 numCellHashBucketsSpA = Ps::nextPowerOfTwo(numParticlesSpA + 1);
		PX_ASSERT(numCellHashBucketsSpA <= tempBuffers.cellHashMaxSize);

		// Get local cell hash for the current subpacket
		PxsFluidSpatialHash::buildLocalHash(particlesSpA0, numParticlesSpA, particleCellsSpA,
			particleIndicesSpA, tempBuffers.hashKeys, numCellHashBucketsSpA, mParams.cellSizeInv, packetCorner);

		//---------------------------------------------------------------------------------------------------

		//
		// Compute particle interactions between particles within the current subpacket.
		//

		updateCellsSubpacket(updateType, forceBufA0, particlesSpA0, particleCellsSpA, particleIndicesSpA, numCellHashBucketsSpA, mParams, tempBuffers);

		//---------------------------------------------------------------------------------------------------

		//
		// Compute particle interactions between particles of current subpacket and particles
		// of other subpackets within the same packet (i.e., we process all subpacket pairs).
		//
		
		PxU32 particlesLeftB = particlesLeftA0 - numParticlesSpA;
		PxsFluidParticle* particlesSpB = particlesSpA0 + numParticlesSpA;
		PxVec3* forceBufB = forceBufA0 + numParticlesSpA;

		while (particlesLeftB)
		{
			PxU32 numParticlesSpB = PxMin(particlesLeftB, static_cast<PxU32>(PXS_FLUID_SUBPACKET_PARTICLE_LIMIT_FORCE_DENSITY));
			
			// Make sure the number of hash buckets is a power of 2 (requirement for the used hash function)
			const PxU32 numCellHashBucketsSpB = Ps::nextPowerOfTwo(numParticlesSpB + 1);
			PX_ASSERT(numCellHashBucketsSpB <= tempBuffers.cellHashMaxSize);

			// Get local cell hash for other subpacket
			PxsFluidSpatialHash::buildLocalHash(particlesSpB, numParticlesSpB, particleCellsSpB, particleIndicesSpB, tempBuffers.hashKeys,
				numCellHashBucketsSpB, mParams.cellSizeInv, packetCorner);

			// For the cells of subpacket A, find neighboring cells in the subpacket B and compute particle interactions.
			updateCellsSubpacketPair(updateType, forceBufA0, forceBufB, particlesSpA0, particlesSpB, particleCellsSpA, particleCellsSpB,
				particleIndicesSpA, particleIndicesSpB, numCellHashBucketsSpA, numCellHashBucketsSpB, true, mParams, tempBuffers, numParticlesSpA < numParticlesSpB);

			particlesLeftB -= numParticlesSpB;
			particlesSpB += numParticlesSpB;
			forceBufB += numParticlesSpB;
		}

		particlesLeftA0 -= numParticlesSpA;
		particlesSpA0 += numParticlesSpA;
		forceBufA0 += numParticlesSpA;
	}

	//---------------------------------------------------------------------------------------------------

	//
	// Compute particle interactions between particles of sections of the current packet and particles of neighboring
	// halo regions
	//

	PX_ASSERT(PXS_FLUID_BRUTE_FORCE_PARTICLE_THRESHOLD_HALO_VS_SECTION <= PXS_FLUID_SUBPACKET_PARTICLE_LIMIT_FORCE_DENSITY);
	if (haloRegions.maxNumParticles != 0)
	{
		for(PxU32 s=0; s < 26; s++)
		{
			PxU32 numSectionParticles = packetSections.numParticles[s];
			if (numSectionParticles == 0)
				continue;

			bool sectionEnablesBruteForce = (numSectionParticles <= PXS_FLUID_BRUTE_FORCE_PARTICLE_THRESHOLD_HALO_VS_SECTION);

			SectionToHaloTable& neighborHaloRegions = sSectionToHaloTable[s];
			PxU32 numHaloNeighbors = neighborHaloRegions.numHaloRegions;

			PxU32 particlesLeftA = numSectionParticles;
			PxsFluidParticle* particlesSpA = particles + packetSections.firstParticle[s];
			PxVec3* forceBufA = forceBuf + packetSections.firstParticle[s];

			while (particlesLeftA)
			{
				PxU32 numParticlesSpA = PxMin(particlesLeftA, static_cast<PxU32>(PXS_FLUID_SUBPACKET_PARTICLE_LIMIT_FORCE_DENSITY));

				// Compute particle interactions between particles of the current subpacket (of the section) 
				// and particles of neighboring halo regions relevant. 

				//Process halo regions which need local hash building first.
				bool isLocalHashValid = false;

				// Make sure the number of hash buckets is a power of 2 (requirement for the used hash function)
				const PxU32 numCellHashBucketsSpA = Ps::nextPowerOfTwo(numParticlesSpA + 1);
				PX_ASSERT(numCellHashBucketsSpA <= tempBuffers.cellHashMaxSize);
#if MERGE_HALO_REGIONS
				//Read halo region particles into temporary buffer 
				PxU32 numMergedHaloParticles = 0;
				for(PxU32 h = 0; h < numHaloNeighbors; h++)
				{
					PxU32 haloRegionIdx = neighborHaloRegions.haloRegionIndices[h];
					PxU32 numHaloParticles = haloRegions.numParticles[haloRegionIdx];

					// chunk regions into subpackets!
					PxU32 particlesLeftB = numHaloParticles;
					PxsFluidParticle* particlesSpB = particles + haloRegions.firstParticle[haloRegionIdx];
					PxVec3* forceBufB = forceBuf + haloRegions.firstParticle[haloRegionIdx];
					while (particlesLeftB)
					{
						PxU32 numParticlesSpB = PxMin(particlesLeftB, static_cast<PxU32>(PXS_FLUID_SUBPACKET_PARTICLE_LIMIT_FORCE_DENSITY));
		
						// if there are plenty of particles already, don't bother to do the copy for merging.
						if (numParticlesSpB > PXS_FLUID_BRUTE_FORCE_PARTICLE_THRESHOLD_HALO_VS_SECTION)
						{
							updateSubpacketPairHalo(forceBufA, particlesSpA, numParticlesSpA, particleCellsSpA, particleIndicesSpA, isLocalHashValid, numCellHashBucketsSpA, 
								forceBufB, particlesSpB, numParticlesSpB, particleCellsSpB, particleIndicesSpB, packetCorner, updateType, hashKeyArray, tempBuffers);							
						}
						else
						{
							if (numMergedHaloParticles + numParticlesSpB > PXS_FLUID_SUBPACKET_PARTICLE_LIMIT_FORCE_DENSITY)
							{
								//flush
								updateSubpacketPairHalo(forceBufA, particlesSpA, numParticlesSpA, particleCellsSpA, particleIndicesSpA, isLocalHashValid, numCellHashBucketsSpA, 
									tempBuffers.mergedHaloRegions, numMergedHaloParticles, particleCellsSpB, particleIndicesSpB, packetCorner, updateType, hashKeyArray, tempBuffers);
								numMergedHaloParticles = 0;
							}

							for (PxU32 k = 0; k < numParticlesSpB; ++k)
								tempBuffers.mergedHaloRegions[numMergedHaloParticles++] = particlesSpB[k];
						}

						particlesLeftB -= numParticlesSpB;
						particlesSpB += numParticlesSpB;						
					}
				}

				//flush
				updateSubpacketPairHalo(forceBufA, particlesSpA, numParticlesSpA, particleCellsSpA, particleIndicesSpA, isLocalHashValid, numCellHashBucketsSpA, 
					tempBuffers.mergedHaloRegions, numMergedHaloParticles, particleCellsSpB, particleIndicesSpB, packetCorner, updateType, hashKeyArray, tempBuffers);
#else // MERGE_HALO_REGIONS
				for(PxU32 h = 0; h < numHaloNeighbors; h++)
				{
					PxU32 haloRegionIdx = neighborHaloRegions.haloRegionIndices[h];
					PxU32 numHaloParticles = haloRegions.numParticles[haloRegionIdx];

					bool haloRegionEnablesBruteForce = (numHaloParticles <= PXS_FLUID_BRUTE_FORCE_PARTICLE_THRESHOLD_HALO_VS_SECTION);

					if (sectionEnablesBruteForce && haloRegionEnablesBruteForce)
						continue;

					if (!isLocalHashValid)
					{
						// Get local cell hash for the current subpacket
						PxsFluidSpatialHash::buildLocalHash(particlesSpA, numParticlesSpA, particleCellsSpA,
							particleIndicesSpA, tempBuffers.hashKeys, numCellHashBucketsSpA, mParams.cellSizeInv, packetCorner);
						isLocalHashValid = true;
					}

					PxU32 particlesLeftB = numHaloParticles;
					PxsFluidParticle* particlesSpB = particles + haloRegions.firstParticle[haloRegionIdx];
				
					while (particlesLeftB)
					{
						PxU32 numParticlesSpB = PxMin(particlesLeftB, static_cast<PxU32>(PXS_FLUID_SUBPACKET_PARTICLE_LIMIT_FORCE_DENSITY));

						// It is important that no data is written to particles in halo regions since they belong to
						// a neighboring packet. The interaction effect of the current packet on the neighboring packet will be
						// considered when the neighboring packet is processed.
						
						// Make sure the number of hash buckets is a power of 2 (requirement for the used hash function)
						const PxU32 numCellHashBucketsSpB = Ps::nextPowerOfTwo(numParticlesSpB + 1);
						PX_ASSERT(numCellHashBucketsSpB <= tempBuffers.cellHashMaxSize);

						// Get local cell hash for other subpacket
						PxsFluidSpatialHash::buildLocalHash(particlesSpB, numParticlesSpB, particleCellsSpB, particleIndicesSpB, tempBuffers.hashKeys,
							numCellHashBucketsSpB, mParams.cellSizeInv, packetCorner);

						// For the cells of subpacket A, find neighboring cells in the subpacket B and compute particle interactions.
						updateCellsSubpacketPair(updateType, forceBufA, NULL, particlesSpA, particlesSpB, particleCellsSpA, particleCellsSpB,
							particleIndicesSpA, particleIndicesSpB, numCellHashBucketsSpA, numCellHashBucketsSpB, false, mParams, tempBuffers, numParticlesSpA > numParticlesSpB);
						
						particlesLeftB -= numParticlesSpB;
						particlesSpB += numParticlesSpB;						
					}
				}

				//Now process halo regions which don't need local hash building.
				PxU32 mergedIndexCount = 0;
				for(PxU32 h = 0; h < numHaloNeighbors; h++)
				{
					PxU32 haloRegionIdx = neighborHaloRegions.haloRegionIndices[h];
					PxU32 numHaloParticles = haloRegions.numParticles[haloRegionIdx];
					if (numHaloParticles == 0)
						continue;

					bool haloRegionEnablesBruteForce = (numHaloParticles <= PXS_FLUID_BRUTE_FORCE_PARTICLE_THRESHOLD_HALO_VS_SECTION);

					if (!sectionEnablesBruteForce || !haloRegionEnablesBruteForce)
						continue;

					// The section and the halo region do not have enough particles to make it worth
					// building a local cell hash --> use brute force approach

					// This is given by the brute force condition (haloRegionEnablesBruteForce). Its necessary to 
					// make sure a halo region alone fits into the merge buffer.
					PX_ASSERT(numHaloParticles <= PXS_FLUID_SUBPACKET_PARTICLE_LIMIT_FORCE_DENSITY);

					if (mergedIndexCount + numHaloParticles > PXS_FLUID_SUBPACKET_PARTICLE_LIMIT_FORCE_DENSITY)
					{
						updateParticleGroupPair(forceBufA, NULL, particlesSpA, particles,
							tempBuffers.orderedIndicesSubpacket, numSectionParticles,
							tempBuffers.mergedIndices, mergedIndexCount,
							false, updateType == PXS_SPH_DENSITY,
							mParams, tempBuffers.simdPositionsSubpacket, tempBuffers.indexStream);	
						mergedIndexCount = 0;
					}

					PxU32 hpIndex = haloRegions.firstParticle[haloRegionIdx];
					for (PxU32 k = 0; k < numHaloParticles; k++)
						tempBuffers.mergedIndices[mergedIndexCount++] = hpIndex++;
				}

				if (mergedIndexCount > 0)
				{
					updateParticleGroupPair(forceBufA, NULL, particlesSpA, particles,
						tempBuffers.orderedIndicesSubpacket, numSectionParticles,
						tempBuffers.mergedIndices, mergedIndexCount,
						false, updateType == PXS_SPH_DENSITY,
						mParams, tempBuffers.simdPositionsSubpacket, tempBuffers.indexStream);
				}
#endif // MERGE_HALO_REGIONS

				particlesLeftA -= numParticlesSpA;
				particlesSpA += numParticlesSpA;
				forceBufA += numParticlesSpA;
			}
		}
	}
}
예제 #5
0
	void CreateTerrainGeomtry(LevelGeometry &lg)
	{
		const int PATCH_SIZE = 64;

		if (!Terrain)
			return;

		PxHeightFieldGeometry g = Terrain->GetHFShape();
		const float colScale = g.columnScale;
		const float rowScale = g.rowScale;
		const float heightScale = g.heightScale;

		PxHeightField *physHF = g.heightField;

		PxU32 nbCols = physHF->getNbColumns();
		PxU32 nbRows = physHF->getNbRows();

		PxU32 patchCols = static_cast<PxU32>(ceilf(nbCols / static_cast<float>(PATCH_SIZE)));
		PxU32 patchRows = static_cast<PxU32>(ceilf(nbRows / static_cast<float>(PATCH_SIZE)));

		lg.meshes.Resize(patchCols * patchRows);
		lg.meshStartObjectsIdx = lg.meshes.Count();

		for (PxU32 pi = 0; pi < patchCols; ++pi)
		{
			for (PxU32 pj = 0; pj < patchRows; ++pj)
			{
				//	Fill patch vertices first.
				LevelGeometry::Mesh &p = lg.meshes[pi * patchRows + pj];

				PxU32 startCol = pi * PATCH_SIZE;
				PxU32 startRow = pj * PATCH_SIZE;

				PxU32 endCol = (pi + 1) * PATCH_SIZE;
				PxU32 endRow = (pj + 1) * PATCH_SIZE;

				PxU32 w = std::min(endCol - startCol + 1, nbCols - startCol);
				PxU32 h = std::min(endRow - startRow + 1, nbRows - startRow);

				p.vertices.Resize(w * h);

				for(PxU32 i = 0; i < w; ++i)
				{
					for(PxU32 j = 0; j < h; ++j)
					{
						PxReal x = PxReal(i + startCol);
						PxReal z = PxReal(j + startRow);
						PxReal y = physHF->getHeight(x, z) * heightScale;
						PxU32 idx = i * h + j;

						p.vertices[idx] = r3dVector(x * colScale, y, z * rowScale);
					}
				}

				//	Now triangulate patch
				const PxU32 nbFaces = (w - 1) * (h - 1) * 2;

				p.indices.Resize(nbFaces * 3);
				int * indices = &p.indices.GetFirst();
				for (PxU32 i = 0; i < (w - 1); ++i) 
				{
					for (PxU32 j = 0; j < (h - 1); ++j) 
					{
						// first triangle
						uint32_t baseIdx = 6 * (i * (h - 1) + j);

						indices[baseIdx + 0] = (i + 1) * h + j; 
						indices[baseIdx + 1] = i * h + j;
						indices[baseIdx + 2] = i * h + j + 1;
						// second triangle
						indices[baseIdx + 3] = (i + 1) * h + j + 1;
						indices[baseIdx + 4] = (i + 1) * h + j;
						indices[baseIdx + 5] = i * h + j + 1;
					}
				}

				//	Filter outside triangles
  				uint32_t indicesCount = gConvexRegionsManager.FilterOutsideTriangles(&p.vertices.GetFirst(), &p.indices.GetFirst(), p.indices.Count());
  				p.indices.Resize(indicesCount);
			}
		}
	}