void ParticleEmitterRate::stepInternal(ParticleData& particles, PxReal dt, const PxVec3& externalAcceleration, PxReal maxParticleVelocity) { PX_ASSERT(mNumX > 0 && mNumY > 0); PxU32 numEmittedParticles = 0; //figure out how many particle have to be emitted with the given rate. mParticlesToEmit += mRate*dt; PxU32 numEmit = (PxU32)(mParticlesToEmit); if(numEmit == 0) return; PxU32 numLayers = (PxU32)(numEmit / (mNumX * mNumY)) + 1; PxReal layerDistance = dt * mVelocity / numLayers; PxU32 sparseMax = 0; //either shuffle or draw without repeat (approximation) bool denseEmission = (PxU32(PARTICLE_EMITTER_SPARSE_FACTOR*numEmit) > mNumSites); if(denseEmission) { initDenseSites(); } else { sparseMax = PARTICLE_EMITTER_SPARSE_FACTOR*numEmit; mSites.resize(sparseMax); } // generate particles PxU32 l = 0; while(numEmit > 0) { PxVec3 layerVec = mAxisZ * (layerDistance * (PxReal)l); l++; if(denseEmission) shuffleDenseSites(); else initSparseSiteHash(numEmit, sparseMax); for (PxU32 i = 0; i < mNumSites && numEmit > 0; i++) { PxU32 emissionSite; if (denseEmission) emissionSite = mSites[i]; else emissionSite = pickSparseEmissionSite(sparseMax); PxU32 x = emissionSite / mNumY; PxU32 y = emissionSite % mNumY; PxReal offset = 0.0f; if (y%2) offset = mSpacingX * 0.5f; if (isOutsideShape(x,y,offset)) continue; //position noise PxVec3 posNoise; posNoise.x = randInRange(-mRandomPos.x, mRandomPos.x); posNoise.y = randInRange(-mRandomPos.y, mRandomPos.y); posNoise.z = randInRange(-mRandomPos.z, mRandomPos.z); PxVec3 emissionPoint = mBasePos + layerVec + mAxisX*(posNoise.x+offset+mSpacingX*x) + mAxisY*(posNoise.y+mSpacingY*y) + mAxisZ*posNoise.z; PxVec3 particleVelocity; computeSiteVelocity(particleVelocity, emissionPoint); bool isSpawned = spawnParticle(particles, numEmittedParticles, particles.maxParticles - particles.numParticles, emissionPoint, particleVelocity); if(isSpawned) { numEmit--; mParticlesToEmit -= 1.0f; } else return; } } }
void ParticleEmitterPressure::stepInternal(ParticleData& particles, PxReal dt, const PxVec3& externalAcceleration, PxReal maxParticleVelocity) { PX_ASSERT(mNumX > 0 && mNumY > 0); mSimulationAcceleration = externalAcceleration; mSimulationMaxVelocity = maxParticleVelocity; PxU32 numEmittedParticles = 0; PxU32 maxParticlesPerStep = (PxU32)physx::shdfnd::floor(mMaxRate*dt); PxU32 maxParticles = PxMin(particles.maxParticles - particles.numParticles, maxParticlesPerStep); PxU32 siteNr = 0; for(PxU32 y = 0; y != mNumY; y++) { PxReal offset = 0.0f; if (y%2) offset = mSpacingX * 0.5f; for(PxU32 x = 0; x != mNumX; x++) { if (isOutsideShape(x,y,offset)) continue; SiteData& siteData = mSites[siteNr]; //position noise PxVec3 posNoise; posNoise.x = randInRange(-mRandomPos.x, mRandomPos.x); posNoise.y = randInRange(-mRandomPos.y, mRandomPos.y); //special code for Z noise if (!siteData.predecessor) siteData.noiseZ = randInRange(-mRandomPos.z, mRandomPos.z); else { PxReal noiseZOffset = PxMin(mMaxZNoiseOffset, mRandomPos.z); siteData.noiseZ += randInRange(-noiseZOffset, noiseZOffset); siteData.noiseZ = PxClamp(siteData.noiseZ, mRandomPos.z, -mRandomPos.z); } posNoise.z = siteData.noiseZ; //set position PxVec3 sitePos = mBasePos + mAxisX*(offset+mSpacingX*x) + mAxisY*(mSpacingY*y) + mAxisZ*siteData.noiseZ; PxVec3 particlePos = sitePos + mAxisX*posNoise.x + mAxisY*posNoise.y; PxVec3 siteVel; computeSiteVelocity(siteVel, particlePos); if (siteData.predecessor) { predictPredecessorPos(siteData, dt); } else { bool isSpawned = spawnParticle(particles, numEmittedParticles, maxParticles, particlePos, siteVel); if(isSpawned) { updatePredecessor(siteData, particlePos, siteVel); } else { siteData.predecessor = false; return; } } bool allSpawned = stepEmissionSite(siteData, particles, numEmittedParticles, maxParticles, sitePos, siteVel, dt); if(!allSpawned) return; siteNr++; } } }