/**
*  @brief
*    Inits all the trails of the particle of the group
*/
void SPK_PLLineTrailRenderer::Init(const SPK::Group &cGroup)
{
	if (prepareBuffers(cGroup)) {
		for (size_t i=0; i<cGroup.getNbParticles(); i++) {
			const SPK::Particle &cParticle = cGroup.getParticle(i);
			Init(cParticle, cParticle.getAge());
		}
	}
}
Esempio n. 2
0
	void Modifier::beginProcess(Group& group)
	{
		savedActive = active;
		
		if (!active)
			return;
		
		if (!prepareBuffers(group))
			active = false; // if buffers of the modifier in the group are not ready, the modifier is made incative for the frame
	}
Esempio n. 3
0
	void GraphDistributor::open()
	{
		if (isOpen) {
			log << "\nDouble openning distributor!\n";
			return;
		}
		isOpen = true;
		prepareBuffers();

	}
Esempio n. 4
0
	void GLLineTrailRenderer::init(const Group& group)
	{
		if (!prepareBuffers(group))
			return;

		for (size_t i = 0; i < group.getNbParticles(); ++i)
		{
			const Particle& particle = group.getParticle(i);
			init(particle,particle.getAge());
		}
	}
Esempio n. 5
0
void InternalSpriteRenderer::flush(IGraphicsContext* context)
{
	int spriteCount = m_spriteDataList.size();
	if (spriteCount == 0) {
		return;
	}

	// Allocate vertex buffer and index buffer, if needed.
	prepareBuffers(context->device(), m_spriteDataList.size());

	// Initialize sprite index list.
	for (int i = 0; i < spriteCount; ++i) {
		m_spriteIndexList[i] = i;
	}

	// Sort of sprite index.
	{
		if (m_state.sortMode == SpriteSortMode::DepthBackToFront)
		{
			SpriteCmpDepthBackToFront cmp;
			cmp.spriteList = &m_spriteDataList;
			std::stable_sort(m_spriteIndexList.begin(), m_spriteIndexList.begin() + spriteCount, cmp);
		}
		else if (m_state.sortMode == SpriteSortMode::DepthFrontToBack)
		{
			SpriteCmpDepthFrontToBack cmp;
			cmp.spriteList = &m_spriteDataList;
			std::stable_sort(m_spriteIndexList.begin(), m_spriteIndexList.begin() + spriteCount, cmp);
		}
	}

	// Copy vertex data.
	Vertex* vb = static_cast<Vertex*>(context->map(m_vertexBuffer));
	for (int iSprite = 0, iVertex = 0; iSprite < spriteCount; iSprite++)
	{
		int iData = m_spriteIndexList[iSprite];
		memcpy(&vb[iVertex], m_spriteDataList[iData].vertices, sizeof(SpriteData::vertices));
		iVertex += 4;
	}
    context->unmap(m_vertexBuffer);

	// Render
	context->setVertexDeclaration(m_vertexDeclaration);
	context->setVertexBuffer(0, m_vertexBuffer);
	context->setIndexBuffer(m_indexBuffer);
	context->setPrimitiveTopology(PrimitiveTopology::TriangleList);
	context->drawPrimitiveIndexed(0, spriteCount * 2);

	// Cleanup
	clear();
}
        void MediaObject::setSource(const Phonon::MediaSource &source)
        {
            if (m_state == Phonon::PlayingState)
            {
                setError(Phonon::NormalError, QLatin1String("source changed while playing"));
                stop();
            }

            m_source = source;
            m_hasSource = true;
            m_sourceIsValid = false;

            emit currentSourceChanged(source);

            if (source.type() == Phonon::MediaSource::LocalFile) {
                if (!openWaveFile(source.fileName())) {
                  setError(Phonon::FatalError, QLatin1String("cannot open media file"));
                  return ;
                }
            } else if (source.type() == Phonon::MediaSource::Stream) {
                if (m_stream)
                   delete m_stream;
                m_stream = new IOWrapper(this, source);
                m_mediaSize = m_stream->size();
            } else if (source.type() == Phonon::MediaSource::Url) {
                if (!openWaveFile(source.url().toLocalFile())) {
                    setError(Phonon::FatalError, QLatin1String("cannot open media file"));
                    return ;
                }
            } else {
                setError(Phonon::FatalError, QLatin1String("type of source not supported"));
                return ;
            }
            setState(Phonon::LoadingState);

            if (!readHeader())
                setError(Phonon::FatalError, QLatin1String("invalid header"));
            else if (!getWaveOutDevice())
                setError(Phonon::FatalError, QLatin1String("No waveOut device available"));
            else if (!fillBuffers())
                setError(Phonon::FatalError, QLatin1String("no data for buffering"));
            else if (!prepareBuffers())
                setError(Phonon::FatalError, QLatin1String("cannot prepare buffers"));
            else
                m_sourceIsValid = true;

            if (m_sourceIsValid)
                setState(Phonon::StoppedState);
        }
Esempio n. 7
0
	void DX9LineRenderer::render(const Group& group)
	{
		HRESULT hr;

		if( !DX9PrepareBuffers(group) )
			return;
		
		if (!prepareBuffers(group))
			return;

		initBlending();

		if( group.getNbParticles() != 0 )
		{
			for (size_t i = 0; i < group.getNbParticles(); ++i)
			{
				const Particle& particle = group.getParticle(i);

				D3DCOLOR c = D3DCOLOR_COLORVALUE(particle.getR(), particle.getG(), particle.getB(), particle.getParamCurrentValue(PARAM_ALPHA));

				Assign((gpuIterator)->position, particle.position());

				(gpuIterator++)->color = c;

				Assign((gpuIterator)->position, (particle.position() + particle.velocity() * length));

				(gpuIterator++)->color = c;
			}

			void *ptr;

			if( DX9VertexBuffer->Lock(0, 0, &ptr, 0) == D3D_OK )
			{
				std::memcpy(ptr, gpuBuffer, group.getNbParticles() * 2 * sizeof(LineVertex));
				if( DX9VertexBuffer->Unlock() == D3D_OK )
				{
					LPDIRECT3DDEVICE9 device = DX9Info::getDevice();
					device->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE);
					device->SetStreamSource(0, DX9VertexBuffer, 0, sizeof(LineVertex));
					device->DrawPrimitive(D3DPT_LINELIST, 0, group.getNbParticles());
				}
			}
		}
	}
	void GLLineRenderer::render(const Group& group)
	{
		if (!prepareBuffers(group))
			return;

		initBlending();
		initRenderingHints();

		glLineWidth(width);
		glDisable(GL_TEXTURE_2D);
		glShadeModel(GL_FLAT);

		for (size_t i = 0; i < group.getNbParticles(); ++i)
		{
			const Particle& particle = group.getParticle(i);

			*(gpuIterator++) = particle.position().x;
			*(gpuIterator++) = particle.position().y;
			*(gpuIterator++) = particle.position().z;

			gpuIterator += 4; // skips the first vertex color data as GL_FLAT was forced

			*(gpuIterator++) = particle.position().x + particle.velocity().x * length;
			*(gpuIterator++) = particle.position().y + particle.velocity().y * length;
			*(gpuIterator++) = particle.position().z + particle.velocity().z * length;

			*(gpuIterator++) = particle.getR();
			*(gpuIterator++) = particle.getG();
			*(gpuIterator++) = particle.getB();
			*(gpuIterator++) = particle.getParamCurrentValue(PARAM_ALPHA);	
		}

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);

		// interleaves vertex and color data
		glVertexPointer(3,GL_FLOAT,7 * sizeof(float),gpuBuffer);
		glColorPointer(4,GL_FLOAT,7 * sizeof(float),gpuBuffer + 3);
	
		glDrawArrays(GL_LINES,0,group.getNbParticles() << 1);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}
Esempio n. 9
0
void GL42Renderer::prepareScene() {
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);

	shaderProgram = new ShaderProgram();

	shaderProgram->loadShader("shaders/colors.vs", GL_VERTEX_SHADER);
	shaderProgram->loadShader("shaders/colors.fs", GL_FRAGMENT_SHADER);
	
	shaderProgram->link();
	shaderProgram->validate();
	
	prepareBuffers();

	projectionMatrix = glm::perspective(60.0f, (float) 1024 / (float) 768, 0.1f, 100.f);
	viewMatrix = glm::lookAt(glm::vec3(0,0,3), glm::vec3(0,0,0), glm::vec3(0,1,0));

	shaderProgram->bind();
}
Esempio n. 10
0
	void DepthBuilderBuffered::buildNextStep()
	{
		prepareBuffers();
		isNextStepRequired = false;

		//main action
		for (Vertex localVertex = 0; localVertex < graph->numLocalVertex; ++localVertex) {
			if (vertexState[localVertex] == stateJustFilled) {
				//printf("%d: dist vertex, depth [%ld]\n", rank, depth[localVertex]);
				distributeVertexDepth(localVertex);
				vertexState[localVertex] = stateSent;
			}

			probeSynchData();
		}

		flushBuffers();
		waitForOthersToEnd();
		comm->Allreduce(IN_PLACE, &isNextStepRequired, 1, SHORT, LOR);
	}
Esempio n. 11
0
	void DX9LineRenderer::render(const Group& group)
	{
		HRESULT hr;

		if (!prepareBuffers(group))
			return;

		initBlending();

		D3DXMATRIX view;
		DX9Info::getDevice()->GetTransform(D3DTS_VIEW, &view);
		D3DXVECTOR3 r(-view._11, view._12, view._13);
		D3DXVECTOR3 d(-view._31, view._32, view._33);

		// position de la caméra
		D3DXVECTOR3 p(view._41, view._42, view._43);

		D3DXVECTOR3 right;
		//D3DXVECTOR3 direction;
		D3DXVECTOR3 vel;
		D3DCOLOR c;

		float w2 = this->getWidth() / 2.0f;

		if( group.getNbParticles() != 0 )
		{
			hr = gpuBuffer->Lock(0, group.getNbParticles()*4*sizeof(LineVertex), (void**)&gpuIterator, 0);

			for (size_t i = 0; i < group.getNbParticles(); ++i)
			{
				const Particle& particle = group.getParticle(i);

				c = D3DCOLOR_COLORVALUE(particle.getR(), particle.getG(), particle.getB(), particle.getParamCurrentValue(PARAM_ALPHA));
				
				Assign(vel, particle.velocity());

				//D3DXVec3ProjectNormal(&right, &r, &vel);
				D3DXVec3Cross(&right, &vel, &d);
				D3DXVec3Normalize(&right, &right);

				Assign((gpuIterator)->position, particle.position());
				(gpuIterator)->position += right * w2;
				(gpuIterator++)->color = c;

				Assign((gpuIterator)->position, particle.position());
				(gpuIterator)->position -= right * w2;
				(gpuIterator++)->color = c;

				Assign((gpuIterator)->position, (particle.position() + particle.velocity() * length));
				(gpuIterator)->position -= right * w2;
				(gpuIterator++)->color = c;

				Assign((gpuIterator)->position, (particle.position() + particle.velocity() * length));
				(gpuIterator)->position += right * w2;
				(gpuIterator++)->color = c;
			}

			gpuBuffer->Unlock();

			DX9Info::getDevice()->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE);
			DX9Info::getDevice()->SetStreamSource(0, gpuBuffer, 0, sizeof(LineVertex));
			DX9Info::getDevice()->SetIndices(indexBuffer);
			DX9Info::getDevice()->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, group.getNbParticles()*4, 0, group.getNbParticles()*2);
		}
	}
Esempio n. 12
0
	void GLQuadRenderer::render(const Group& group)
	{
		if (!prepareBuffers(group))
			return;

		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();
		initRenderingHints();

		glShadeModel(GL_FLAT);

		switch(texturingMode)
		{
		case TEXTURE_2D :
			if (getTexture3DGLExt() == SUPPORTED)
				glDisable(GL_TEXTURE_3D);
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D,textureIndex);
			glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,getTextureBlending());

			if (!group.getModel()->isEnabled(PARAM_TEXTURE_INDEX))
			{
				if (!group.getModel()->isEnabled(PARAM_ANGLE))
					renderParticle = &GLQuadRenderer::render2D;
				else
					renderParticle = &GLQuadRenderer::render2DRot;
			}
			else
			{
				if (!group.getModel()->isEnabled(PARAM_ANGLE))
					renderParticle = &GLQuadRenderer::render2DAtlas;
				else
					renderParticle = &GLQuadRenderer::render2DAtlasRot;
			}
			break;

		case TEXTURE_3D :
			glDisable(GL_TEXTURE_2D);
			glEnable(GL_TEXTURE_3D);
			glBindTexture(GL_TEXTURE_3D,textureIndex);
			glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,getTextureBlending());

			if (!group.getModel()->isEnabled(PARAM_ANGLE))
				renderParticle = &GLQuadRenderer::render3D;
			else
				renderParticle = &GLQuadRenderer::render3DRot;
			break;

		case TEXTURE_NONE :
			glDisable(GL_TEXTURE_2D);
			if (getTexture3DGLExt() == SUPPORTED)
				glDisable(GL_TEXTURE_3D);
			if (!group.getModel()->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]));

		if (globalOrientation)
		{
			computeGlobalOrientation3D();

			for (size_t i = 0; i < group.getNbParticles(); ++i)
				(this->*renderParticle)(group.getParticle(i));
		}
		else
		{
			for (size_t i = 0; i < group.getNbParticles(); ++i)
			{
				const Particle& particle = group.getParticle(i);
				computeSingleOrientation3D(particle);
				(this->*renderParticle)(particle);
			}
		}

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);

		if (texturingMode == TEXTURE_2D)
		{
			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
			glTexCoordPointer(2,GL_FLOAT,0,textureBuffer);
		}
		else if (texturingMode == TEXTURE_3D)
		{
			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
			glTexCoordPointer(3,GL_FLOAT,0,textureBuffer);
		}

		// interleaves vertex and color data
		glVertexPointer(3,GL_FLOAT,7 * sizeof(float),gpuBuffer);
		glColorPointer(4,GL_FLOAT,7 * sizeof(float),gpuBuffer + 3);

		glDrawArrays(GL_QUADS,0,group.getNbParticles() << 2);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);

		if (texturingMode != TEXTURE_NONE)
			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	}
Esempio n. 13
0
	void GLLineTrailRenderer::render(const Group& group)
	{	
		if (!prepareBuffers(group))
			return;

		initBlending();
		initRenderingHints();

		// Inits lines' parameters
		glLineWidth(width);
		glDisable(GL_TEXTURE_2D);
		glShadeModel(GL_SMOOTH);

		for (size_t i = 0; i < group.getNbParticles(); ++i)
		{
			const Particle& particle = group.getParticle(i);
			float age = particle.getAge();
			float oldAge = *valueIterator;

			if ((age == 0.0f)||(age < *valueIterator)) // If the particle is new, buffers for it are reinitialized
				init(particle,0.0f);
			else
			{
				if (age - *(valueIterator + 1) >= duration / (nbSamples - 1)) // shifts the data by one
				{
					std::memmove(vertexIterator + 6,vertexIterator + 3,(nbSamples - 1) * 3 * sizeof(float));
					std::memmove(colorIterator + 8,colorIterator + 4,((nbSamples - 1) << 2) * sizeof(float));
					std::memmove(valueIterator + 1,valueIterator,(nbSamples - 1) * sizeof(float));

					// post degenerated vertex copy
					std::memcpy(vertexIterator + (nbSamples + 1) * 3,vertexIterator + nbSamples * 3,3 * sizeof(float));
				}

				// Updates the current sample
				const Vector3D& pos = particle.position();
				*(vertexIterator++) = pos.x;
				*(vertexIterator++) = pos.y;
				*(vertexIterator++) = pos.z;

				std::memcpy(vertexIterator,vertexIterator - 3,3 * sizeof(float));
				vertexIterator += (nbSamples + 1) * 3;

				colorIterator += 4; // skips post degenerated vertex color
				*(colorIterator++) = particle.getR();
				*(colorIterator++) = particle.getG();
				*(colorIterator++) = particle.getB();
				*(colorIterator++) = particle.getParamCurrentValue(PARAM_ALPHA);
				colorIterator += 3;

				*(valueIterator++) = age;
				//valueIterator += nbSamples;

				// Updates alpha
				for (size_t i = 0; i < nbSamples - 1; ++i)
				{
					float ratio = (age - oldAge) / (duration - age + *valueIterator);
					if (ratio > 0.0f)
						*colorIterator *= ratio < 1.0f ? 1.0f - ratio : 0.0f;
					colorIterator += 4;
					++valueIterator;
				}
				++colorIterator;
			}
		}

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);

		glColorPointer(4,GL_FLOAT,0,colorBuffer);
		glVertexPointer(3,GL_FLOAT,0,vertexBuffer);

		glDrawArrays(GL_LINE_STRIP,0,group.getNbParticles() * (nbSamples + 2));

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}
	void IRRQuadRenderer::render(const Group& group)
	{
		if (!prepareBuffers(group))
			return;

		irr::video::IVideoDriver* driver = device->getVideoDriver();

		// Computes the inverse model view
		irr::core::matrix4 invModelView;
		{
			irr::core::matrix4 modelView(driver->getTransform(irr::video::ETS_VIEW));
			modelView *= driver->getTransform(irr::video::ETS_WORLD);
			modelView.getInversePrimitive(invModelView); // wont work for odd modelview matrices (but should happen in very special cases)
		}

		// Saves the renderer texture
		irr::video::ITexture* savedTexture = material.TextureLayer[0].Texture;
		if (texturingMode == TEXTURE_NONE)
			material.TextureLayer[0].Texture = NULL;

		if ((texturingMode == TEXTURE_2D)&&(group.getModel()->isEnabled(PARAM_TEXTURE_INDEX)))
		{
			if (group.getModel()->isEnabled(PARAM_ANGLE))
				renderParticle = &IRRQuadRenderer::renderAtlasRot;
			else
				renderParticle = &IRRQuadRenderer::renderAtlas;
		}
		else
		{
			if (group.getModel()->isEnabled(PARAM_ANGLE))
				renderParticle = &IRRQuadRenderer::renderRot;
			else
				renderParticle = &IRRQuadRenderer::renderBasic;
		}

		// At the first frame we pass the full buffer so that VBOs are correctly initialised
		// Then at next frames we pass only what is needed to be rendered
		if (currentBuffer->areVBOInitialized())
			currentBuffer->setUsed(group.getNbParticles());
		else
			currentBuffer->setUsed(group.getParticles().getNbReserved());

		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]));

		if (globalOrientation)
		{
			computeGlobalOrientation3D();

			for (size_t t = 0; t < group.getNbParticles(); ++t)
				(this->*renderParticle)(group.getParticle(t));
		}
		else
		{
			for (size_t t = 0; t < group.getNbParticles(); ++t)
			{
				const Particle& particle = group.getParticle(t);
				computeSingleOrientation3D(particle);
				(this->*renderParticle)(particle);
			}
		}
		currentBuffer->getMeshBuffer().setDirty(irr::scene::EBT_VERTEX);

		driver->setMaterial(material);
		driver->drawMeshBuffer(&currentBuffer->getMeshBuffer()); // this draw call is used in order to be able to use VBOs

		currentBuffer->setVBOInitialized(true);
		material.TextureLayer[0].Texture = savedTexture; // Restores the texture
	}
//[-------------------------------------------------------]
//[ Public virtual SPK::Renderer functions                ]
//[-------------------------------------------------------]
void SPK_PLQuadRendererShaders::render(const SPK::Group &group)
{
	// Is there a valid m_pSPK_PLBuffer instance?
	if (prepareBuffers(group) && m_pSPK_PLBuffer && m_pSPK_PLBuffer->GetVertexBuffer()) {
		// Update the vertex buffer
		UpdateVertexBuffer(group);

		// Setup render states
		InitBlending();
		GetPLRenderer().SetRenderState(RenderState::ZEnable,      isRenderingHintEnabled(SPK::DEPTH_TEST));
		GetPLRenderer().SetRenderState(RenderState::ZWriteEnable, isRenderingHintEnabled(SPK::DEPTH_WRITE));

		/*
			// [TODO] Alpha test
			if (isRenderingHintEnabled(SPK::ALPHA_TEST)) {
				pFixedFunctions->SetRenderState(FixedFunctions::RenderState::AlphaTestEnable,    true);
				pFixedFunctions->SetRenderState(FixedFunctions::RenderState::AlphaTestFunction,  Compare::GreaterEqual);
				pFixedFunctions->SetRenderState(FixedFunctions::RenderState::AlphaTestReference, Tools::FloatToUInt32(getAlphaTestThreshold()));
			} else {
				pFixedFunctions->SetRenderState(FixedFunctions::RenderState::AlphaTestEnable, false);
			}
			*/

		// Make our program to the current one
		if (GetPLRenderer().SetProgram(m_pProgram)) {
			// Set the "ObjectSpaceToClipSpaceMatrix" fragment shader parameter
			if (m_pObjectSpaceToClipSpaceMatrixProgramUniform)
				m_pObjectSpaceToClipSpaceMatrixProgramUniform->Set(m_mWorldViewProjection);

			// Set "TextureMap" program uniform
			if (m_pTextureMapProgramUniform) {
				Texture *pTexture = m_pTextureHandler->GetTexture();
				if (pTexture && pTexture->GetTextureBuffer()) {
					const int nTextureUnit = m_pTextureMapProgramUniform->Set(pTexture->GetTextureBuffer());
					if (nTextureUnit >= 0) {
						GetPLRenderer().SetSamplerState(nTextureUnit, Sampler::AddressU,  TextureAddressing::Wrap);
						GetPLRenderer().SetSamplerState(nTextureUnit, Sampler::AddressV,  TextureAddressing::Wrap);
						GetPLRenderer().SetSamplerState(nTextureUnit, Sampler::MagFilter, TextureFiltering::Linear);
						GetPLRenderer().SetSamplerState(nTextureUnit, Sampler::MinFilter, TextureFiltering::Linear);
						GetPLRenderer().SetSamplerState(nTextureUnit, Sampler::MipFilter, TextureFiltering::Linear);
					}
				}
			}

			// Set program vertex attributes, this creates a connection between "Vertex Buffer Attribute" and "Vertex Shader Attribute"
			VertexBuffer *pVertexBuffer = m_pSPK_PLBuffer->GetVertexBuffer();
			if (m_pPositionProgramAttribute)
				m_pPositionProgramAttribute->Set(pVertexBuffer, PLRenderer::VertexBuffer::Position);
			if (m_pTexCoordProgramAttribute)
				m_pTexCoordProgramAttribute->Set(pVertexBuffer, PLRenderer::VertexBuffer::TexCoord);
			if (m_pColorProgramAttribute)
				m_pColorProgramAttribute->Set(pVertexBuffer, PLRenderer::VertexBuffer::Color);

			// Make the index buffer to the current renderer index buffer
			IndexBuffer *pIndexBuffer = m_pSPK_PLBuffer->GetIndexBuffer();
			if (pIndexBuffer)
				GetPLRenderer().SetIndexBuffer(pIndexBuffer);

			// Draw
			GetPLRenderer().DrawIndexedPrimitives(Primitive::TriangleList, 0, static_cast<uint32>(group.getNbParticles()*NumOfVerticesPerParticle-1), 0, static_cast<uint32>(group.getNbParticles()*NumOfIndicesPerParticle));
		}
	}
}
//[-------------------------------------------------------]
//[ Public virtual SPK::Renderer functions                ]
//[-------------------------------------------------------]
void SPK_PLLineRendererShaders::render(const SPK::Group &group)
{
	// Is there a valid m_pSPK_PLBuffer instance?
	if (prepareBuffers(group) && m_pSPK_PLBuffer && m_pSPK_PLBuffer->GetVertexBuffer()) {
		// Get the vertex buffer instance from m_pSPK_PLBuffer and lock it
		VertexBuffer *pVertexBuffer = m_pSPK_PLBuffer->GetVertexBuffer();
		if (pVertexBuffer->Lock(Lock::WriteOnly)) {
			// Vertex buffer data
			const uint32 nVertexSize = pVertexBuffer->GetVertexSize();
			float *pfPosition = static_cast<float*>(pVertexBuffer->GetData(0, VertexBuffer::Position));

			// Fill the vertex buffer with the current data
			for (size_t i=0, nCurrentVertex=0; i<group.getNbParticles(); i++) {
				// Get the particle
				const SPK::Particle &cParticle = group.getParticle(i);

				// Copy over the particle position into the vertex data
				pfPosition[0] = cParticle.position().x;
				pfPosition[1] = cParticle.position().y;
				pfPosition[2] = cParticle.position().z;
				pfPosition = reinterpret_cast<float*>(reinterpret_cast<char*>(pfPosition) + nVertexSize);	// Next, please!
				// Copy over the particle color into the vertex data
				pVertexBuffer->SetColor(static_cast<uint32>(nCurrentVertex), Color4(cParticle.getR(), cParticle.getG(), cParticle.getB(), cParticle.getParamCurrentValue(SPK::PARAM_ALPHA)));
				nCurrentVertex++;	// Next, please!

				// Copy over the particle position into the vertex data
				pfPosition[0] = cParticle.position().x + cParticle.velocity().x*length;
				pfPosition[1] = cParticle.position().y + cParticle.velocity().y*length;
				pfPosition[2] = cParticle.position().z + cParticle.velocity().z*length;
				pfPosition = reinterpret_cast<float*>(reinterpret_cast<char*>(pfPosition) + nVertexSize);	// Next, please!
				// Copy over the particle color into the vertex data
				pVertexBuffer->SetColor(static_cast<uint32>(nCurrentVertex), Color4(cParticle.getR(), cParticle.getG(), cParticle.getB(), cParticle.getParamCurrentValue(SPK::PARAM_ALPHA)));
				nCurrentVertex++;	// Next, please!
			}

			// Unlock the vertex buffer
			pVertexBuffer->Unlock();
		}

		// Setup render states
		InitBlending();
		GetPLRenderer().SetRenderState(RenderState::ZEnable,      isRenderingHintEnabled(SPK::DEPTH_TEST));
		GetPLRenderer().SetRenderState(RenderState::ZWriteEnable, isRenderingHintEnabled(SPK::DEPTH_WRITE));
		GetPLRenderer().SetRenderState(RenderState::LineWidth,    Tools::FloatToUInt32(width));

		// Make our program to the current one
		if (GetPLRenderer().SetProgram(m_pProgram)) {
			// Set the "ObjectSpaceToClipSpaceMatrix" fragment shader parameter
			if (m_pObjectSpaceToClipSpaceMatrixProgramUniform)
				m_pObjectSpaceToClipSpaceMatrixProgramUniform->Set(m_mWorldViewProjection);

			// Set program vertex attributes, this creates a connection between "Vertex Buffer Attribute" and "Vertex Shader Attribute"
			if (m_pPositionProgramAttribute)
				m_pPositionProgramAttribute->Set(pVertexBuffer, PLRenderer::VertexBuffer::Position);
			if (m_pColorProgramAttribute)
				m_pColorProgramAttribute->Set(pVertexBuffer, PLRenderer::VertexBuffer::Color);

			// Draw
			GetPLRenderer().DrawPrimitives(Primitive::LineList, 0, static_cast<uint32>(group.getNbParticles() << 1));
		}
	}
}