예제 #1
0
	void Emitter::setTank(int minTank,int maxTank)
	{
		SPK_ASSERT(minTank >= 0 == maxTank >= 0,"Emitter::setTank(int,int) : min and max tank values must be of the same sign");
		if (minTank < 0 || maxTank < 0) minTank = maxTank = -1;
		if (minTank > maxTank)
		{
			SPK_LOG_WARNING("Emitter::setTank(int,int) : min tank is greater than max tank. Values are swapped");
			std::swap(minTank,maxTank);
		}
		this->minTank = minTank;
		this->maxTank = maxTank;
		resetTank();
		SPK_ASSERT(flow >= 0.0f || currentTank >= 0,"Emitter::setTank(int,int) : the flow and tank of an emitter cannot be both negative");
	}
예제 #2
0
	void Group::reallocate(size_t capacity)
	{
		SPK_ASSERT(capacity != 0,"Group::reallocate(size_t) - Group capacity must not be 0");

		if (isInitialized() && (!particleData.initialized || capacity != particleData.maxParticles))
		{
			destroyAllAdditionnalData();

			size_t copySize = particleData.nbParticles;
			if (capacity < copySize)
				copySize = capacity;

			reallocateArray(particleData.positions,capacity,copySize);
			reallocateArray(particleData.velocities,capacity,copySize);
			reallocateArray(particleData.oldPositions,capacity,copySize);
			reallocateArray(particleData.ages,capacity,copySize);
			reallocateArray(particleData.lifeTimes,capacity,copySize);
			reallocateArray(particleData.energies,capacity,copySize);
			reallocateArray(particleData.sqrDists,capacity,copySize);
			reallocateArray(particleData.colors,capacity,copySize);

			for (size_t i = 0; i < nbEnabledParameters; ++i)
				reallocateArray(particleData.parameters[enabledParamIndices[i]],capacity,copySize);

			particleData.initialized = true;
		}

		particleData.maxParticles = capacity;
	}
예제 #3
0
	DX9Buffer::DX9Buffer(BufferInfo &info) :
		nbVertices(info.nbVertices),
		nbIndices(info.nbIndices),
		nbTexCoords(info.nbTexCoords),
		currentVertexIndex(0),
		currentColorIndex(0),
		currentTexCoordIndex(0),

		currentLock(NO_LOCK),
		vertexBuffer(NULL), colorBuffer(NULL), texCoordBuffer(NULL), indexBuffer(NULL),
		ptrVertexBuffer(NULL), ptrColorBuffer(NULL), ptrTexCoordBuffer(NULL), ptrIndexBuffer(NULL)
	{
		SPK_ASSERT(nbVertices > 0,"DX9Buffer::DX9Buffer(BufferInfo) - The number of vertices cannot be 0");

		DX9Info::getDevice()->CreateVertexBuffer(nbVertices*sizeof(D3DXVECTOR3), D3DUSAGE_DYNAMIC, D3DFVF_XYZ, D3DPOOL_DEFAULT, &vertexBuffer, NULL);
		DX9Info::getDevice()->CreateVertexBuffer(nbVertices*sizeof(D3DCOLOR), D3DUSAGE_DYNAMIC, D3DFVF_DIFFUSE, D3DPOOL_DEFAULT, &colorBuffer, NULL);

		// TODO : gérer les indices 32bit
		if( nbIndices > 0 )
		{
			DX9Info::getDevice()->CreateIndexBuffer(nbIndices*sizeof(short), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &indexBuffer, 0);

			unsigned int offsetIndex = 0;

			lock(INDEX_LOCK);
			// initialisation de l'index buffer
			for(size_t i = 0; i < nbIndices/6; i++)
			{
//#ifdef _DX9QUADRENDERER_CLOCKWISE_
				*(ptrIndexBuffer++) = 0 + offsetIndex;
				*(ptrIndexBuffer++) = 1 + offsetIndex;
				*(ptrIndexBuffer++) = 2 + offsetIndex;
				*(ptrIndexBuffer++) = 0 + offsetIndex;
				*(ptrIndexBuffer++) = 2 + offsetIndex;
				*(ptrIndexBuffer++) = 3 + offsetIndex;
// TODO handle counter clockwise
//#else
//				*(ptrIndexBuffer++) = 0 + offsetIndex;
//				*(ptrIndexBuffer++) = 2 + offsetIndex;
//				*(ptrIndexBuffer++) = 1 + offsetIndex;
//				*(ptrIndexBuffer++) = 0 + offsetIndex;
//				*(ptrIndexBuffer++) = 3 + offsetIndex;
//				*(ptrIndexBuffer++) = 2 + offsetIndex;
//#endif
				offsetIndex += 4;
			}
			unlock();
		}

		// TODO : gérer autre chose que les textures 2D
		if(nbTexCoords > 0)
			DX9Info::getDevice()->CreateVertexBuffer(nbVertices*sizeof(D3DXVECTOR2), D3DUSAGE_DYNAMIC, D3DFVF_TEX1|D3DFVF_TEXCOORDSIZE1(nbTexCoords), D3DPOOL_DEFAULT, &texCoordBuffer, NULL);
	}
예제 #4
0
	void Group::setLifeTime(float minLifeTime,float maxLifeTime)
	{
		SPK_ASSERT(minLifeTime > 0.0f && maxLifeTime > 0.0f,"Group::setLifeTime(float,float) - Life times must not be set to negative values");
		if (minLifeTime <= maxLifeTime)
		{
			this->minLifeTime = minLifeTime;
			this->maxLifeTime = maxLifeTime;
		}
		else
		{
			SPK_LOG_WARNING("Group::setEnergy(float,float) - minEnergy is higher than maxEnergy - Values are swapped");
			this->minLifeTime = maxLifeTime;
			this->maxLifeTime = minLifeTime;
		}
	}
예제 #5
0
	void DX9LineRenderer::render(const Group& group,const DataSet* dataSet,RenderBuffer* renderBuffer) const
	{
		SPK_ASSERT(renderBuffer != NULL,"DX9LinesRenderer::render(const Group&,const DataSet*,RenderBuffer*) - renderBuffer must not be NULL");
		DX9Buffer& buffer = static_cast<DX9Buffer&>(*renderBuffer);
		buffer.positionAtStart();

		initBlending();
		initRenderingOptions();

		DX9Info::getDevice()->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);

		for (ConstGroupIterator particleIt(group); !particleIt.end(); ++particleIt)
		{
			const Particle& particle = *particleIt;

			buffer.setNextVertex(particle.position());
			buffer.setNextVertex(particle.position() + particle.velocity() * length);

			buffer.setNextColor(particle.getColor());
			buffer.setNextColor(particle.getColor());
		}

		buffer.render(D3DPT_LINELIST, group.getNbParticles());
	}
예제 #6
0
	void Collider::modify(Group& group,DataSet* dataSet,float deltaTime) const
	{
		float groupSqrRadius = group.getPhysicalRadius() * group.getPhysicalRadius();
		SPK_ASSERT(group.getOctree() != NULL,"GLQuadRenderer::render(const Group&,const DataSet*,RenderBuffer*) - renderBuffer must not be NULL");
		const Octree& octree = *group.getOctree();

		for (GroupIterator particleIt0(group); !particleIt0.end(); ++particleIt0)
		{
			Particle& particle0 = *particleIt0;
			float radius0 = particle0.getParam(PARAM_SCALE);
			float m0 = particle0.getParam(PARAM_MASS);

			size_t index0 = particle0.getIndex();

			const Octree::Array<size_t>& neighborCells = octree.getNeighborCells(index0);
			size_t nbCells = neighborCells.size();

			for (size_t i = 0; i < nbCells; ++i) // For each neighboring cell in the octree
			{
				const Octree::Cell& cell = octree.getCell(neighborCells[i]);
				size_t nbParticleInCells = cell.particles.size();

				for (size_t j = 0; j < nbParticleInCells; ++j) // for each particles in the cell
				{
					size_t index1 = cell.particles[j];
					if (index1 >= index0)
						break; // as particle are ordered

					Particle particle1 = group.getParticle(index1);
					float radius1 = particle1.getParam(PARAM_SCALE);

					float sqrRadius = radius0 + radius1;
					sqrRadius *= sqrRadius * groupSqrRadius;

					// Gets the normal of the collision plane
					Vector3D normal = particle0.position() - particle1.position();
					float sqrDist = normal.getSqrNorm();

					if (sqrDist < sqrRadius) // particles are intersecting each other
					{
						Vector3D delta = particle0.velocity() - particle1.velocity();

						if (dotProduct(normal,delta) < 0.0f) // particles are moving towards each other
						{
							float oldSqrDist = getSqrDist(particle0.oldPosition(),particle1.oldPosition());
							if (oldSqrDist > sqrDist)
							{
								// Disables the move from this frame
								particle0.position() = particle0.oldPosition();
								particle1.position() = particle1.oldPosition();

								normal = particle0.position() - particle1.position();

								if (dotProduct(normal,delta) >= 0.0f)
									continue;
							}

							normal.normalize();

							// Gets the normal components of the velocities
							Vector3D normal0 = normal * dotProduct(normal,particle0.velocity());
							Vector3D normal1 = normal * dotProduct(normal,particle1.velocity());

							// Resolves collision
							float m1 = particle1.getParam(PARAM_MASS);

							if (oldSqrDist < sqrRadius && sqrDist < sqrRadius)
							{
								// Tweak to separate particles that intersects at both t - deltaTime and t
								// In that case the collision is no more considered as punctual
								if (dotProduct(normal,normal0) < 0.0f)
								{
									particle0.velocity() -= normal0;
									particle1.velocity() += normal0;
								}

								if (dotProduct(normal,normal1) > 0.0f)
								{
									particle1.velocity() -= normal1;
									particle0.velocity() += normal1;
								}
							}
							else
							{
								// Else classic collision equations are applied
								// Tangent components of the velocities are left untouched
								float elasticityM0 = elasticity * m0;
								float elasticityM1 = elasticity * m1;
								float invM01 = 1 / (m0 + m1);

								particle0.velocity() -= (1.0f + (elasticityM1 - m0) * invM01) * normal0;
								particle1.velocity() -= (1.0f + (elasticityM0 - m1) * invM01) * normal1;

								normal0 *= (elasticityM0 + m0) * invM01;
								normal1 *= (elasticityM1 + m0) * invM01;

								particle0.velocity() += normal1;
								particle1.velocity() += normal0;
							}
						}
					}
				}
			}
		}
	}
예제 #7
0
	void Emitter::setFlow(float flow)
	{
		SPK_ASSERT(flow >= 0.0f || currentTank >= 0,"Emitter::setFlow(float) : the flow and tank of an emitter cannot be both negative");
		this->flow = flow;
	}
예제 #8
0
	void GLQuadRenderer::render(const Group& group,const DataSet* dataSet,RenderBuffer* renderBuffer) const
	{
		SPK_ASSERT(renderBuffer != NULL,"GLQuadRenderer::render(const Group&,const DataSet*,RenderBuffer*) - renderBuffer must not be NULL");
		GLBuffer& buffer = static_cast<GLBuffer&>(*renderBuffer);
		buffer.positionAtStart(); // Repositions all the buffers at the start

		float oldModelView[16];
		for (int i = 0; i < 16; ++i)
			oldModelView[i] = modelView[i];
		glGetFloatv(GL_MODELVIEW_MATRIX,modelView);
		for (int i = 0; i < 16; ++i)
			if (oldModelView[i] != modelView[i])
			{
				invertModelView();
				break;
			}

		initBlending();
		initRenderingOptions();

		glShadeModel(GL_FLAT);

		switch(texturingMode)
		{
		case TEXTURE_MODE_2D :
			// Creates and inits the 2D TexCoord buffer if necessary
			if (buffer.getNbTexCoords() != 2)
			{
				buffer.setNbTexCoords(2);
				if (!group.isEnabled(PARAM_TEXTURE_INDEX))
				{
					float t[8] = {1.0f,0.0f,0.0f,0.0f,0.0f,1.0f,1.0f,1.0f};
					for (size_t i = 0; i < group.getCapacity() << 3; ++i)
						buffer.setNextTexCoord(t[i & 7]);
				}
			}

			// Binds the texture
#ifndef SPK_GL_NO_EXT
			if (SPK_GL_CHECK_EXTENSION(SPK_GL_TEXTURE_3D_EXT))
				glDisable(GL_TEXTURE_3D_EXT);
#endif
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D,textureIndex);

			// Selects the correct function
			if (!group.isEnabled(PARAM_TEXTURE_INDEX))
			{
				if (!group.isEnabled(PARAM_ANGLE))
					renderParticle = &GLQuadRenderer::render2D;
				else
					renderParticle = &GLQuadRenderer::render2DRot;
			}
			else
			{
				if (!group.isEnabled(PARAM_ANGLE))
					renderParticle = &GLQuadRenderer::render2DAtlas;
				else
					renderParticle = &GLQuadRenderer::render2DAtlasRot;
			}
			break;

		case TEXTURE_MODE_3D :
			// Creates and inits the 3D TexCoord buffer if necessery
			if (buffer.getNbTexCoords() != 3)
			{
				buffer.setNbTexCoords(3);
				float t[12] =  {1.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,1.0f,0.0f,1.0f,1.0f,0.0f};
				for (size_t i = 0; i < group.getCapacity() * 12; ++i)
					buffer.setNextTexCoord(t[i % 12]);
			}

			// Binds the texture
			glDisable(GL_TEXTURE_2D);
#ifndef SPK_GL_NO_EXT
			glEnable(GL_TEXTURE_3D_EXT);
			glBindTexture(GL_TEXTURE_3D_EXT,textureIndex);
#endif

			// Selects the correct function
			if (!group.isEnabled(PARAM_ANGLE))
				renderParticle = &GLQuadRenderer::render3D;
			else
				renderParticle = &GLQuadRenderer::render3DRot;
			break;

		case TEXTURE_MODE_NONE :
			if (buffer.getNbTexCoords() != 0)
				buffer.setNbTexCoords(0);

			glDisable(GL_TEXTURE_2D);

			// Selects the correct function
#ifndef SPK_GL_NO_EXT
			if (SPK_GL_CHECK_EXTENSION(SPK_GL_TEXTURE_3D_EXT))
				glDisable(GL_TEXTURE_3D_EXT);
#endif
			if (!group.isEnabled(PARAM_ANGLE))
				renderParticle = &GLQuadRenderer::render2D;
			else
				renderParticle = &GLQuadRenderer::render2DRot;
			break;
		}

		bool globalOrientation = precomputeOrientation3D(
			group,
			Vector3D(-invModelView[8],-invModelView[9],-invModelView[10]),
			Vector3D(invModelView[4],invModelView[5],invModelView[6]),
			Vector3D(invModelView[12],invModelView[13],invModelView[14]));

		// Fills the buffers
		if (globalOrientation)
		{
			computeGlobalOrientation3D(group);

			for (ConstGroupIterator particleIt(group); !particleIt.end(); ++particleIt)
				(this->*renderParticle)(*particleIt,buffer);
		}
		else
		{
			for (ConstGroupIterator particleIt(group); !particleIt.end(); ++particleIt)
			{
				computeSingleOrientation3D(*particleIt);
				(this->*renderParticle)(*particleIt,buffer);
			}
		}

		buffer.render(GL_QUADS,group.getNbParticles() << 2);
	}
예제 #9
0
	const Particle Group::getParticle(size_t index) const
	{
		SPK_ASSERT(index < particleData.nbParticles,"Group::getParticle(size_t) - Particle index is out of bounds : " << index);
		return Particle(const_cast<Group&>(*this),index);
	}
예제 #10
0
	const Ref<Action>& ActionSet::getAction(size_t index) const
	{
		SPK_ASSERT(index <= getNbActions(),"ActionSet::getAction(size_t) - Action index is out of bounds : " << index);
		return actions[index];
	}