//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();
	}
}
//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);
		}
	}
}
//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();
	}
}
Example #4
0
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);
    }
}
void RenderParticleSystemActor::update(float deltaTime) 
{
	setTransform(PxTransform(PxIdentity));

#if defined(RENDERER_ENABLE_CUDA_INTEROP)

	SampleRenderer::RendererParticleSystemShape* shape = 
		static_cast<SampleRenderer::RendererParticleSystemShape*>(getRenderShape());

	if (shape->isInteropEnabled() && (mPS->getPxParticleSystem().getParticleBaseFlags()&PxParticleBaseFlag::eGPU))
	{
		PxParticleReadData* data = mPS->getPxParticleSystem().lockParticleReadData(PxDataAccessFlag::eREADABLE | PxDataAccessFlag::eDEVICE);

		if(data)
		{
			if(mUseMeshInstancing) 
			{
				shape->updateInstanced(mPS->getValidParticleRange(),
					reinterpret_cast<CUdeviceptr>(&data->positionBuffer[0]),			
					mPS->getValiditiesDevice(),
					mPS->getOrientationsDevice(),
					data->nbValidParticles);
			} 
			else 
			{
				CUdeviceptr lifetimes = 0;
				if(mFading && mPS->useLifetime()) 
					lifetimes = mPS->getLifetimesDevice();

				shape->updateBillboard(mPS->getValidParticleRange(),
					reinterpret_cast<CUdeviceptr>(&data->positionBuffer[0]),			
					mPS->getValiditiesDevice(),
					lifetimes,
					data->nbValidParticles);
			}

			data->unlock();
		}
	}
	else

#endif

	{
		PxParticleReadData* data = mPS->getPxParticleSystem().lockParticleReadData(PxDataAccessFlag::eREADABLE);

		if(data)
		{
			if(mUseMeshInstancing) 
			{
				SampleRenderer::RendererParticleSystemShape* shape = 
					static_cast<SampleRenderer::RendererParticleSystemShape*>(getRenderShape());
				shape->updateInstanced(mPS->getValidParticleRange(),
								&(mPS->getPositions()[0]), 
								mPS->getValidity(),
								&(mPS->getOrientations()[0]));

			} 
			else 
			{
				SampleRenderer::RendererParticleSystemShape* shape = 
					static_cast<SampleRenderer::RendererParticleSystemShape*>(getRenderShape());
				const PxReal* lifetimes = NULL;
				if(mFading && mPS->useLifetime()) 
				{
					lifetimes = &(mPS->getLifetimes()[0]);
				}
				shape->updateBillboard(mPS->getValidParticleRange(),
								&(mPS->getPositions()[0]), 
								mPS->getValidity(),
								lifetimes);
			}

			data->unlock();
		}
	}
}