//simple routine to render our particles void ParticleFluidEmitter::renderParticles() { // lock SDK buffers of *PxParticleSystem* ps for reading PxParticleFluidReadData * fd = m_pf->lockParticleFluidReadData(); // access particle data from PxParticleReadData float minX =1000,maxX = -1000,minZ = 1000,maxZ = -1000,minY = 1000,maxY = -1000; if (fd) { PxStrideIterator<const PxParticleFlags> flagsIt(fd->flagsBuffer); PxStrideIterator<const PxVec3> positionIt(fd->positionBuffer); PxStrideIterator<const PxF32> densityIt(fd->densityBuffer); for (unsigned i = 0; i < fd->validParticleRange; ++i, ++flagsIt, ++positionIt,++densityIt) { if (*flagsIt & PxParticleFlag::eVALID) { //density tells us how many neighbours a particle has. //If it has a density of 0 it has no neighbours, 1 is maximum neighbouts //we can use this to decide if the particle is seperate or part of a larger body of fluid glm::vec3 pos(positionIt->x,positionIt->y,positionIt->z); Gizmos::addAABBFilled(pos, m_size, m_colour, nullptr, false); } } // return ownership of the buffers back to the SDK fd->unlock(); } }
//simple routine to render our particles void ParticleEmitter::RenderParticles() { // lock SDK buffers of *PxParticleSystem* ps for reading PxParticleReadData* rd = m_ps->lockParticleReadData(); // access particle data from PxParticleReadData if (rd) { PxStrideIterator<const PxParticleFlags> flagsIt(rd->flagsBuffer); PxStrideIterator<const PxVec3> positionIt(rd->positionBuffer); for (unsigned int i = 0; i < rd->validParticleRange; ++i, ++flagsIt, ++positionIt) { if (*flagsIt & PxParticleFlag::eVALID) { //convert physx vector to a glm vec3 glm::vec3 pos(positionIt->x,positionIt->y,positionIt->z); //use a gizmo box to visualize particle. This would be much better done using a facing quad preferably done using the geometry shader m_model->SetLocalTransform(glm::translate(pos) * glm::scale(glm::vec3(0.1f))); m_model->Render(); } } // return ownership of the buffers back to the SDK rd->unlock(); } }
//simple routine to render our particles void ParticleFluidEmitter::renderParticles() { // lock SDK buffers of *PxParticleSystem* ps for reading PxParticleFluidReadData * fd = m_pf->lockParticleFluidReadData(); // access particle data from PxParticleReadData float minX =1000,maxX = -1000,minZ = 1000,maxZ = -1000,minY = 1000,maxY = -1000; if (fd) { PxStrideIterator<const PxParticleFlags> flagsIt(fd->flagsBuffer); PxStrideIterator<const PxVec3> positionIt(fd->positionBuffer); PxStrideIterator<const PxF32> densityIt(fd->densityBuffer); for (unsigned i = 0; i < fd->validParticleRange; ++i, ++flagsIt, ++positionIt,++densityIt) { if (*flagsIt & PxParticleFlag::eVALID) { //density tells us how many neighbours a particle has. //If it has a density of 0 it has no neighbours, 1 is maximum neighbouts //we can use this to decide if the particle is seperate or part of a larger body of fluid glm::vec3 pos(positionIt->x,positionIt->y,positionIt->z); //glm::vec4 colournoise = glm::vec4(((float)(rand() % 100)) / 100, ((float)(rand() % 100)) / 100, ((float)(rand() % 100)) / 100, 1); glm::vec4 colour = glm::vec4(0.196f, 0.518f, 0.749f, 1.0f); //colour.a = 1; Gizmos::addAABBFilled(pos, glm::vec3(.12, .12, .12), colour); //Gizmos::addDisk(pos, 0.1f, 6, glm::vec4(1, 0, 1, 1)); } } // return ownership of the buffers back to the SDK fd->unlock(); } }
//updateParticle void ParticleFluidEmitter::update(float delta) { //tick the emitter m_time += delta; m_respawnTime+= delta; int numberSpawn = 0; //if respawn time is greater than our release delay then we spawn at least one particle so work out how many to spawn if(m_respawnTime>m_releaseDelay) { numberSpawn = (int)(m_respawnTime/m_releaseDelay); m_respawnTime -= (numberSpawn * m_releaseDelay); } // spawn the required number of particles for(int count = 0;count < numberSpawn;count++) { //get the next free particle int particleIndex = getNextFreeParticle(); if(particleIndex >=0) { //if we got a particle ID then spawn it addPhysXParticle(particleIndex); } } //check to see if we need to release particles because they are either too old or have hit the particle sink //lock the particle buffer so we can work on it and get a pointer to read data PxParticleReadData* rd = m_pf->lockParticleReadData(); // access particle data from PxParticleReadData was OK if (rd) { vector<PxU32> particlesToRemove; //we need to build a list of particles to remove so we can do it all in one go PxStrideIterator<const PxParticleFlags> flagsIt(rd->flagsBuffer); PxStrideIterator<const PxVec3> positionIt(rd->positionBuffer); for (unsigned i = 0; i < rd->validParticleRange; ++i, ++flagsIt, ++positionIt) { if (*flagsIt & PxParticleFlag::eVALID) { //if particle is either too old or has hit the sink then mark it for removal. We can't remove it here because we buffer is locked if (*flagsIt & PxParticleFlag::eCOLLISION_WITH_DRAIN) { //mark our local copy of the particle free releaseParticle(i); //add to our list of particles to remove particlesToRemove.push_back(i); } } } // return ownership of the buffers back to the SDK rd->unlock(); //if we have particles to release then pass the particles to remove to PhysX so it can release them if(particlesToRemove.size()>0) { //create a buffer of particle indicies which we are going to remove PxStrideIterator<const PxU32> indexBuffer(&particlesToRemove[0]); //free particles from the physics system m_pf->releaseParticles(particlesToRemove.size(), indexBuffer); } } }
void ParticleEmitter::Draw(RenderingEngine& _renderer) { // Lock SDK buffers of *PxParticleSystem* ps for reading PxParticleFluidReadData * fd = particleFluid->lockParticleFluidReadData(); // Access particle data from PxParticleReadData float minX = 1000, maxX = -1000, minZ = 1000, maxZ = -1000, minY = 1000, maxY = -1000; if (fd) { PxStrideIterator<const PxParticleFlags> flagsIt(fd->flagsBuffer); PxStrideIterator<const PxVec3> positionIt(fd->positionBuffer); PxStrideIterator<const PxF32> densityIt(fd->densityBuffer); for (unsigned i = 0; i < fd->validParticleRange; ++i, ++flagsIt, ++positionIt, ++densityIt) { if (*flagsIt & PxParticleFlag::eVALID) { // Density tells us how many neighbours a particle has. // If it has a density of 0 it has no neighbours, 1 is maximum neighbours // We can use this to decide if the particle is seperate or part of a larger body of fluid vec3 position(positionIt->x, positionIt->y, positionIt->z); Gizmos::AddSphere(position, restParticleDistance * 0.5f, 4, 4, vec4(1, 0, 1, 1)); } } // return ownership of the buffers back to the SDK fd->unlock(); } Gizmos::AddTransform(this->transform->worldMatrix); }
//simple routine to render our particles void ParticleEmitter::renderParticles() { // lock SDK buffers of *PxParticleSystem* ps for reading PxParticleReadData* rd = m_ps->lockParticleReadData(); // access particle data from PxParticleReadData if (rd) { PxStrideIterator<const PxParticleFlags> flagsIt(rd->flagsBuffer); PxStrideIterator<const PxVec3> positionIt(rd->positionBuffer); for (unsigned i = 0; i < rd->validParticleRange; ++i, ++flagsIt, ++positionIt) { if (*flagsIt & PxParticleFlag::eVALID) { //convert physx vector to a glm vec3 glm::vec3 pos(positionIt->x,positionIt->y,positionIt->z); //use a gizmo box to visualize particle. This would be much better done using a facing quad preferably done using the geometry shader Gizmos::addAABBFilled(pos,glm::vec3(.1,.1,.1),glm::vec4(1,0,1,1)); } } // return ownership of the buffers back to the SDK rd->unlock(); } }
void DownGroup::updateVisuals() { ParticleGroup::updateVisuals(); PxParticleReadData * readData = m_particleSystem->lockParticleReadData(); assert(readData); m_particleDrawable->updateParticles(readData); // Get drained Particles std::vector<uint32_t> particlesToDelete; PxStrideIterator<const PxParticleFlags> flagsIt(readData->flagsBuffer); PxStrideIterator<const PxVec3> positionIt = readData->positionBuffer; TerrainInteraction terrain("water"); std::vector<unsigned int> lavaToSteam; glowutils::AxisAlignedBoundingBox steamBbox; std::vector<glm::vec3> steamPositions; const TerrainSettings & terrainSettings = terrain.terrain().settings; for (unsigned i = 0; i < readData->validParticleRange; ++i, ++flagsIt, ++positionIt) { // check range if (!(*flagsIt & PxParticleFlag::eVALID)) { continue; } if (positionIt->y > terrainSettings.maxHeight * 0.75f) { particlesToDelete.push_back(i); continue; } if (*flagsIt & PxParticleFlag::eCOLLISION_WITH_STATIC) { if (positionIt->y < m_particleSize + 0.1) // collision with water plane { if (m_elementName == "lava") { lavaToSteam.push_back(i); steamBbox.extend(reinterpret_cast<const glm::vec3&>(*positionIt)); steamPositions.push_back(reinterpret_cast<const glm::vec3&>(*positionIt)); continue; } else { particlesToDelete.push_back(i); continue; } } if (terrain.topmostElementAt(positionIt->x, positionIt->z) == m_elementName) { particlesToDelete.push_back(i); } } } assert(m_numParticles == readData->nbValidParticles); readData->unlock(); if (!particlesToDelete.empty()) releaseParticles(particlesToDelete); if (!lavaToSteam.empty()) { DownGroup * steamGroup = ParticleGroupTycoon::instance().getNearestGroup("steam", steamBbox.center()); steamGroup->createParticles(steamPositions); releaseParticles(lavaToSteam); } }