• Advertisement
Sign in to follow this  

Possible state problem in my particle system - SOLVED

This topic is 4786 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello. In my program I am mainly using textured quads so I use a set of global states which do not change, these are shown below.
// Set the vertex format
GlobalDirect3D9Device->SetFVF(D3DFVF_TLVERTEX);

// Set the render states for alpha blending
GlobalDirect3D9Device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); // Enable alpha blending
GlobalDirect3D9Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); // Set the source blend state
GlobalDirect3D9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); // Set the destination blend state
GlobalDirect3D9Device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
GlobalDirect3D9Device->SetRenderState(D3DRS_LIGHTING, FALSE);

// Set the texture stage states
GlobalDirect3D9Device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
GlobalDirect3D9Device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
GlobalDirect3D9Device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
	
GlobalDirect3D9Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
GlobalDirect3D9Device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
GlobalDirect3D9Device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
GlobalDirect3D9Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE2X);

// Where the TLVERTEX is defined as:
const DWORD D3DFVF_TLVERTEX = D3DFVF_XYZRHW | D3DFVF_TEX1;






However, I have just added a Particle System to the program which is defined in a derived class called ScreenEntityParticleSystem, this obviously requires different states on the device to be rendered. Please see the source for the Particle System below. The render states are changed in the RenderScreenEntity() method. When the program starts up I can see the textures quads in the background very briefly but then the whole screen starts flashing. I think that some of the states that are set in the RenderScreenEntity() method are not reverted back properly so the rest of the screen ends up being subjected to incorrect states are hence, an incorrect display. ScreenEntityParticleSystem.h
#ifndef SCREENENTITYPARTICLESYSTEM
#define SCREENENTITYPARTICLESYSTEM

#include "ScreenEntityBase.h"

struct Particle
{
	D3DXVECTOR2 CurrentPosition;	// The current position of the particle
	D3DXVECTOR2 CurrentVelocity;	// The current velocity of the particle
	D3DCOLOR Colour;				// The colour of the particle (RGBA)
	float StartTime;				// The time the particle started
	float LifeTime;					// The amount of time the particle has to live
	float AlphaDecay;				// The amount of alpha which decays each second
	bool Dead;
};

class ScreenEntityParticleSystem : public ScreenEntityBase
{
public:
	// (De)Constructors
	ScreenEntityParticleSystem();									// Default constructor
	ScreenEntityParticleSystem(ScreenEntityParticleSystem & rhs);	// Copy constructor
	ScreenEntityParticleSystem(RECT cScreenRectangle,
								DWORD cFlags,
								int cDepthLevel,
								string cBehaviourModifier,
								string cParticleTexture);			// Constrcutor

	~ScreenEntityParticleSystem();									// Deconstructor

	// Assignment operator
	ScreenEntityParticleSystem& ScreenEntityParticleSystem::operator =(ScreenEntityParticleSystem & rhs);

	// Public methods
	HRESULT Initialise();
	HRESULT HandleMessage(UINT MessageType, WPARAM wParam, LPARAM lParam);
	HRESULT RenderScreenEntity();
	void OutputInformation();
	virtual void Release();
	virtual void ControlEntity(bool start);

	// Get and set methods
	string GetParticleTextureLocation();
	void SetParticleTextureLocation(string newParticleTextureLocation);

	bool GetGravity();
	void SetGravity(bool newGravity);

	RECT GetReleaseArea();
	void SetReleaseArea(RECT newReleaseArea);

	float GetReleaseInterval();
	void SetReleaseInterval(float newReleaseInterval);

	int GetMaxParticles();
	void SetMaxParticles(int newMaxParticles);

	DWORD GetFlush();
	void SetFlush(DWORD newFlush);

	DWORD GetDiscard();
	void SetDicard(DWORD newDiscard);

	float GetMaxPointSize();
	void SetMaxPointSize(float newMaxPointSize);

	float GetSize();
	void SetSize(float newSize);

	float GetVelocityVar();
	void SetVelocityVar(float newVelocityVar);

	DWORD GetVBOffset();
	void SetVBOffset(DWORD newVBOffset);

	bool GetPaused();
	void SetPaused(bool newPaused);

	bool GetSupportsPSIZE();
	void SetSupportsPSIZE(bool newSupportsPSIZE);

	float GetLastTime();
	void SetLastTime(float newLastTime);

	stack<int> GetDeadList();
	void SetDeadList(stack<int> newDeadList);

	vector<Particle> GetParticleList();
	void SetParticleList(vector<Particle> newParticleList);

private:

	// Private methods
	HRESULT Update();
	void InitialiseParticle(Particle* DeadParticle);

	// Private Data Members
	string ParticleTextureLocation;	// The location of the particle file
	bool Gravity;					// true if gravity is to be taken into account
	RECT ReleaseArea;				// A rect from within which the particles are emitted
	float ReleaseInterval;			// The interval at which new particles should be released
	int MaxParticles;				// The maximum number of particles which may exist in the system
	DWORD VBOffset;					// The offset of the VB to write to
	DWORD Flush;					// The number of sprites to send to the hardware at once
	DWORD Discard;					// The maximum number of point sprites that the vertex buffer can load before we have to discard and start again
	float MaxPointSize;				// The maximum point size
	float Size;						// The size of the sprite to be drawn
	float VelocityVar;				// A scaling factor for the velocity
	bool Paused;					// Updates on particles are not carried out if this is true
	bool SupportsPSIZE;				// Hardware allows us to change the size of the point sprites
	float LastTime;					// Holds the time when the last updated occured	

	LPDIRECT3DVERTEXBUFFER9 VertexBuffer;	// Holds the vertices to be rendered
	LPDIRECT3DTEXTURE9		ParticleTexture;// Stores the particle texture
	stack<int> DeadList;					// Holds the dead particles
	vector<Particle> ParticleList;			// Holds all the particles
};

#endif


ScreenEntityParticleSystem.cpp



ScreenEntityParticleSystem.cpp
#include "ScreenEntityParticleSystem.h"
// Default constructor
ScreenEntityParticleSystem::ScreenEntityParticleSystem()
							:ScreenEntityBase()
{
	RECT TempRect;
	TempRect.bottom = 0;
	TempRect.top = 0;
	TempRect.left = 0;
	TempRect.right = 0;

	ReleaseArea				= TempRect;
	ParticleTextureLocation	= "";
	Gravity					= false;
	ReleaseInterval			= 1.0f;
	MaxParticles			= 1;
	VBOffset				= 0;
	Flush					= 128;
	Discard					= 512;
	Size					= 1.0f;
	VelocityVar				= 1.0f;
	Paused					= true;
	SupportsPSIZE			= false;
	LastTime				= timeGetTime();

	//TODO -- Is this necessary
	//DeadList.clear();
	ParticleList.clear();
}

// Copy constructor
ScreenEntityParticleSystem::ScreenEntityParticleSystem(ScreenEntityParticleSystem & rhs)
													:ScreenEntityBase(rhs)
{
	// Copy all the simple types
	ParticleTextureLocation = rhs.GetParticleTextureLocation();
	Gravity					= rhs.GetGravity();
	ReleaseArea				= rhs.GetReleaseArea();
	ReleaseInterval			= rhs.GetReleaseInterval();
	MaxParticles			= rhs.GetMaxParticles();
	VBOffset				= rhs.GetVBOffset();
	Flush					= rhs.GetFlush();
	Discard					= rhs.GetDiscard();
	MaxPointSize			= rhs.GetMaxPointSize();	
	Size					= rhs.GetSize();
	VelocityVar				= rhs.GetVelocityVar();
	Paused					= rhs.GetPaused();
	SupportsPSIZE			= rhs.GetSupportsPSIZE();
	LastTime				= rhs.GetLastTime();

	for(int i = 0;i < DeadList.size();i++)
		DeadList.pop();

	for(i = 0;i < rhs.GetDeadList().size();i++)
	{
		DeadList.push(rhs.GetDeadList().top());
		rhs.GetDeadList().pop();
	}

	ParticleList.clear();

	for(vector<Particle>::iterator walker = rhs.GetParticleList().begin();walker != rhs.GetParticleList().end();walker++)
	{
		ParticleList.push_back(*walker);
	}
}

// Constructor
ScreenEntityParticleSystem::ScreenEntityParticleSystem(RECT cScreenRectangle,
														DWORD cFlags,
														int cDepthLevel,
														string cBehaviourModifier,
														string cParticleTexture)
														:ScreenEntityBase(cScreenRectangle,
																			cFlags,
																			cDepthLevel,
																			cBehaviourModifier),
																			ParticleTextureLocation(cParticleTexture)
{
	LastTime = timeGetTime();
}

// Deconstructor
ScreenEntityParticleSystem::~ScreenEntityParticleSystem()
{
	// This may also need to be filled in at a later date
}

// Assignment operator
ScreenEntityParticleSystem& ScreenEntityParticleSystem::operator =(ScreenEntityParticleSystem & rhs)
{
	if(this == &rhs)
		return *this;

	// Call the base class operator so that the full assignment in carried out
	ScreenEntityBase::operator=(rhs);

	// Copy all the simple types
	ParticleTextureLocation = rhs.GetParticleTextureLocation();
	Gravity					= rhs.GetGravity();
	ReleaseArea				= rhs.GetReleaseArea();
	ReleaseInterval			= rhs.GetReleaseInterval();
	MaxParticles			= rhs.GetMaxParticles();
	VBOffset				= rhs.GetVBOffset();
	Flush					= rhs.GetFlush();
	Discard					= rhs.GetDiscard();
	MaxPointSize			= rhs.GetMaxPointSize();	
	Size					= rhs.GetSize();
	VelocityVar				= rhs.GetVelocityVar();
	Paused					= rhs.GetPaused();
	SupportsPSIZE			= rhs.GetSupportsPSIZE();

	for(int i = 0;i < DeadList.size();i++)
		DeadList.pop();

	for(i = 0;i < rhs.GetDeadList().size();i++)
	{
		DeadList.push(rhs.GetDeadList().top());
		rhs.GetDeadList().pop();
	}

	ParticleList.clear();

	for(vector<Particle>::iterator walker = rhs.GetParticleList().begin();walker != rhs.GetParticleList().end();walker++)
	{
		ParticleList.push_back(*walker);
	}

	return *this;
}


// Initialise the screen entity
HRESULT ScreenEntityParticleSystem::Initialise()
{
	// Create a vertex buffer for the particle system
	if(FAILED(GlobalDirect3D9Device->CreateVertexBuffer(Discard*sizeof(PointVertex),
														D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY | D3DUSAGE_POINTS,
														D3DFVF_TLVERTEXPOINT,
														D3DPOOL_DEFAULT,
														&VertexBuffer,
														NULL)))
	{
		return E_FAIL;
		DXTRACE_MSG("Could not create vertex buffer in particle system");
	}

	// Get the max point size
	D3DCAPS9 d3dcaps;
	GlobalDirect3D9Device->GetDeviceCaps(&d3dcaps);
	MaxPointSize = d3dcaps.MaxPointSize;

	// Check to see if we can change the size of the point sprites
	if(d3dcaps.FVFCaps & D3DFVFCAPS_PSIZE)
		SupportsPSIZE = true;
	else
		SupportsPSIZE = false;

	// Create the texture object
	if(FAILED(D3DXCreateTextureFromFile(GlobalDirect3D9Device,
										ParticleTextureLocation.c_str(),
										&ParticleTexture)))
	{
		return E_FAIL;
		DXTRACE_MSG("Could not create texture file in particle system");
	}

	// Initialise the GlobalGravityVector
	GlobalGravityVector.x = 0;
	GlobalGravityVector.y = 0.5;

	// The initialisation has been successful so we set the valid flag to true
	Flags = Flags | SCREENENTITY_VALID;

	return S_OK;
}

HRESULT ScreenEntityParticleSystem::HandleMessage(UINT MessageType, WPARAM wParam, LPARAM lParam)
{
	// The particle system is not effected by user input or render calls so just return S_OK
	return S_OK;
}

HRESULT ScreenEntityParticleSystem::Update()
{
	DXTRACE_MSG("************************************** Before update");
	OutputInformation();
	float CurrentTime = timeGetTime();
	float ElapsedTime = (float)((CurrentTime - LastTime) * 0.001);

	for(int i = 0;i < ParticleList.size();i++)
	{
		// If the particle is not dead then we process it
		if(!(ParticleList.Dead))
		{
			// If the particle is dead, put it on the dead list
			if(((CurrentTime - ParticleList.StartTime) * 0.001) >= ParticleList.LifeTime)
			{
				char test[500];
				sprintf(test, "Particle is dead -> CurrentTime: %f, StartTime: %f, LifeTime: %f",
								CurrentTime,
								ParticleList.StartTime,
								ParticleList.LifeTime);

				DXTRACE_MSG("Particle has died");
				DXTRACE_MSG(test);
				DXTRACE_MSG("Particle is dead");
				
				
				// Tell the Particle that it is dead and put a reference to it on the deadlist
				ParticleList.Dead = true;
				DeadList.push(i);
			}
			else
			{
				// The particle is still in it's active lifetime so we updated the position and velocity
				// If gravity is switched on then we apply this here
				if(Gravity)
				{
					ParticleList.CurrentVelocity += GlobalGravityVector * ElapsedTime;
				}

				// Update the position with respect to the velocity
				ParticleList.CurrentPosition += ParticleList.CurrentVelocity * ElapsedTime;

				// Update the alpha value
				 // TODO -- Finsh this
			}
		}
		else
		{
			// This particle is dead so it does not need to be updated
		}
	}

	// Now we need to emit new particles
	if(CurrentTime - LastTime > ReleaseInterval)
	{
		// It is time to release a new particle, first check if there are any on the dead list
		if(!(DeadList.empty()))
		{
			// Restart the dead particle
			InitialiseParticle(&ParticleList[DeadList.top()]);

			// Remove the reference from the deadlist
			DeadList.pop();
		}
		else
		{
			// There are no dead particles to reactivate so we will make
			// another one if there is enough space on the ParticleList
			if(ParticleList.size() <= MaxParticles)
			{
				Particle newParticle;
				InitialiseParticle(&newParticle);
				ParticleList.push_back(newParticle);
			}
			else
			{
				// There is no space for any more particles so we don't do anything
			}
		}
	}

	// Last update the LastTime float
	LastTime = CurrentTime;

	DXTRACE_MSG("************************************** After update");
	OutputInformation();

	return S_OK;
}	

HRESULT ScreenEntityParticleSystem::RenderScreenEntity()
{
	// If the system is not paused, then update the particles before they are rendered
	if(!(Paused))
		Update();

	// Set the render states for using point sprites
	GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
	GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
	GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSIZE, FtoDW(Size));
	GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(1.0f));
	GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSCALE_A, FtoDW(0.0f));
	GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f));
	GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSCALE_C, FtoDW(1.0f));
	GlobalDirect3D9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

	// Used as a reference to the vertex buffer
	PointVertex* Vertices;
	DWORD NumParticlesToRender= 0;

	// Lock the vertex buffer. Fill the vertex buffer in small chunks, using D3DLOCK_NOOVERWRITE.
	// When done filling each chunk, call DrawPrimitive and lock the next chunk. When space runs
	// out in the vertex buffer, start over at the beginning using D3DLOCK_DISCARD.

	// Move the offset to fill the next chunk of the vertex buffer
	VBOffset += Flush;

	// If about to overflow the buffer, set it back to 0
	if(VBOffset >= Discard)
		VBOffset = 0;

	// Lock the vertex buffer
	HRESULT hr;
	if(FAILED(hr = VertexBuffer->Lock(VBOffset*sizeof(PointVertex),	// Offset to lock
									Flush*sizeof(PointVertex),	// Size to lock
									(VOID **) &Vertices,
									VBOffset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD)))
	{
		DXTRACE_ERR("Failed to lock the vertex buffer in the render method of the particle system", hr);
		return hr;
	}

	// Render each particle
	for(vector<Particle>::iterator walker = ParticleList.begin(); walker != ParticleList.end();walker++)
	{
		if(!walker->Dead){
                D3DXVECTOR2	vVel(walker->CurrentVelocity);

		Vertices->posit = walker->CurrentPosition;
		Vertices->color = walker->Colour;
		Vertices++;

		if(++NumParticlesToRender == Flush)
		{
			// Done filling this chunk of the vertex buffer so unlock and draw so that the
			// next chunk can start being filled
			VertexBuffer->Unlock();

			GlobalDirect3D9Device->SetStreamSource(0, VertexBuffer, 0, sizeof(PointVertex));
			GlobalDirect3D9Device->SetFVF(D3DFVF_TLVERTEXPOINT);

			if(FAILED(hr = GlobalDirect3D9Device->DrawPrimitive(D3DPT_POINTLIST,
																VBOffset,
																NumParticlesToRender)))
			{
				DXTRACE_ERR("Draw primitive failed inside the Flush-if in the render method", hr);
				return hr;
			}

			// Lock the next chunk of the vertex buffer. If we are at the end of the vertex buffer
			// DISCARD the vertex buffer and start at the beginning. Otherwise, specify NOOVERWRITE
			// so we can continue filling the VB while the previous chunk is drawing.
			VBOffset += Flush;

			// If about to overflow reset the offset to 0
			if(VBOffset >= Discard)
				VBOffset = 0;

			if(FAILED(hr = VertexBuffer->Lock(VBOffset*sizeof(PointVertex),
												Flush*sizeof(PointVertex),
												(VOID **) &Vertices,
												VBOffset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD)))
			{
				DXTRACE_ERR("Failed to lock the vertex buffer in the latter part of the render method", hr);
				return hr;
			}

			NumParticlesToRender = 0;
		}
                }
	}

	// Unlock the vertex buffer
	VertexBuffer->Unlock();

	// Render any remaining particles
	if(NumParticlesToRender)
	{
		GlobalDirect3D9Device->SetStreamSource(0, VertexBuffer, 0, sizeof(PointVertex));
		GlobalDirect3D9Device->SetFVF(D3DFVF_TLVERTEXPOINT);

		if(FAILED(hr = GlobalDirect3D9Device->DrawPrimitive(D3DPT_POINTLIST,
															VBOffset,
															NumParticlesToRender)))
		{
			DXTRACE_ERR("Draw primitive failed inside the final part of the render method", hr);
			return hr;
		}
	}

	// Reset render states
	GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
	GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
	GlobalDirect3D9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
	GlobalDirect3D9Device->SetFVF(D3DFVF_TLVERTEX);

	return S_OK;
}

void ScreenEntityParticleSystem::OutputInformation()
{
	char output[500];

	DXTRACE_MSG("****************************************** Particle Output Information");
	
	// Walk through the particle list and for each particle output the colour, position,
	// velocity, starttime, lifetime and alpha decay
	for(vector<Particle>::iterator walker = ParticleList.begin();walker != ParticleList.end();walker++)
	{
		sprintf(output, "Position x: %f, Position y: %f, Velocity x: %f, Velocity y: %f, Starttime: %f, LifeTime: %f, AlphaDecay: %f",
						walker->CurrentPosition.x,
						walker->CurrentPosition.y,
						walker->CurrentVelocity.x,
						walker->CurrentVelocity.y,
						walker->StartTime,
						walker->LifeTime,
						walker->AlphaDecay);

		DXTRACE_MSG(output);
	}

	DXTRACE_MSG("****************************************** Particle Output Information end");
}

void ScreenEntityParticleSystem::Release()
{
	SAFE_RELEASE(VertexBuffer);
	SAFE_RELEASE(ParticleTexture);
	//TODO -- Is this necessary
	//DeadList.clear();
	ParticleList.clear();
}

void ScreenEntityParticleSystem::ControlEntity(bool start)
{
	if(start)
		Paused = false;
	else
		Paused = true;
}

void ScreenEntityParticleSystem::InitialiseParticle(Particle* DeadParticle)
{
	// Tell the particle that it is alive!
	DeadParticle->Dead = false;

	// Place the particle somewhere within the release area
	DeadParticle->CurrentPosition.x = GetRandomNumber(ReleaseArea.left, ReleaseArea.right);
	DeadParticle->CurrentPosition.y = GetRandomNumber(ReleaseArea.top, ReleaseArea.bottom);

	// Set the intial velocity, colour, lifetime and alpha decay in accordance with the type of effect being created
	if((Flags & PARTICLE_FIRE) > 0)
	{
		// ************** VELOCITY ****
		// If this is fire then all the particles need to be sent more or less upwards so we
		// set the y value to -2 (-y is up) and then add a Random between -10 and 10 divided
		// 10 leading to +/-1
		DeadParticle->CurrentVelocity.y = -2.0f;
		DeadParticle->CurrentVelocity.y += (float)(GetRandomNumber(-10, 10)/10);

		// The x is set straight up the middle (0) but we vary it with a random number between
		// 10 and -10 which is then divide by 20 giving a maximum of 0.5 either way. That equates
		// to a maximum angle of 22.5 degrees which may have to be reduced
		DeadParticle->CurrentVelocity.x = 0.0f;
		DeadParticle->CurrentVelocity.x += (float)(GetRandomNumber(-10,10)/20);

		// ************** COLOUR ****
		// Define each colour element (plus the alpha)
		float r, g, b, a, random;

		// Calculate the random to be 0.2 either way. So get a random number between -10 and
		// 10 and then divide it by fifty.

		random = (float)(GetRandomNumber(-10,10)/50); // Random

		r = 0.9f + random; // Red

		g = 0.4f + random; // Green

		b = 0.2f + random; // Blue

		a = 1.0f; // Start the alpha at full
		
		// Set the colour
		DeadParticle->Colour = D3DXCOLOR(r, g, b, a);

		// ************** LIFETIME ****
		// Alter the life time by 0.5 either way
		DeadParticle->LifeTime = 1.5f + (float)((GetRandomNumber(-10,10)/20));

		// ************** ALPHA DECAY ****
		// Alter the alpha decay by 0.1 either way
		DeadParticle->AlphaDecay = 0.1 + (float)((GetRandomNumber(-10, 10)/100));		
	}
	else if((Flags & PARTICLE_FIRE) > 0)
	{
		DXTRACE_MSG("Particle dust not defined yet!!");
	}
	else
	{
		DXTRACE_MSG("Particle system is of an invalid type or flag not set");
		PostQuitMessage(0);
	}

	// Set the start time of the particle
	DeadParticle->StartTime = timeGetTime();
}

// Get and set methods
string ScreenEntityParticleSystem::GetParticleTextureLocation()
{
	return ParticleTextureLocation;
}

void ScreenEntityParticleSystem::SetParticleTextureLocation(string newParticleTextureLocation)
{
	ParticleTextureLocation = newParticleTextureLocation;
}

bool ScreenEntityParticleSystem::GetGravity()
{
	return Gravity;
}

void ScreenEntityParticleSystem::SetGravity(bool newGravity)
{
	Gravity = newGravity;
}


DWORD ScreenEntityParticleSystem::GetVBOffset()
{
	return VBOffset;
}

void ScreenEntityParticleSystem::SetVBOffset(DWORD newVBOffset)
{
	VBOffset = newVBOffset;
}

RECT ScreenEntityParticleSystem::GetReleaseArea()
{
	return ReleaseArea;
}

bool ScreenEntityParticleSystem::GetSupportsPSIZE()
{
	return SupportsPSIZE;
}

void ScreenEntityParticleSystem::SetReleaseArea(RECT newReleaseArea)
{
	ReleaseArea = newReleaseArea;
}

float ScreenEntityParticleSystem::GetReleaseInterval()
{
	return ReleaseInterval;
}

void ScreenEntityParticleSystem::SetReleaseInterval(float newReleaseInterval)
{
	ReleaseInterval = newReleaseInterval;
}

int ScreenEntityParticleSystem::GetMaxParticles()
{
	return MaxParticles;
}

void ScreenEntityParticleSystem::SetMaxParticles(int newMaxParticles)
{
	MaxParticles = newMaxParticles;
}

DWORD ScreenEntityParticleSystem::GetFlush()
{
	return Flush;
}

void ScreenEntityParticleSystem::SetFlush(DWORD newFlush)
{
	Flush = newFlush;
}

DWORD ScreenEntityParticleSystem::GetDiscard()
{
	return Discard;
}

void ScreenEntityParticleSystem::SetDicard(DWORD newDiscard)
{
	Discard = newDiscard;
}

float ScreenEntityParticleSystem::GetMaxPointSize()
{
	return MaxPointSize;
}

void ScreenEntityParticleSystem::SetMaxPointSize(float newMaxPointSize)
{
	MaxPointSize = newMaxPointSize;
}

float ScreenEntityParticleSystem::GetSize()
{
	return Size;
}

void ScreenEntityParticleSystem::SetSize(float newSize)
{
	Size = newSize;
}

float ScreenEntityParticleSystem::GetVelocityVar()
{
	return VelocityVar;
}

void ScreenEntityParticleSystem::SetVelocityVar(float newVelocityVar)
{
	VelocityVar = newVelocityVar;
}

bool ScreenEntityParticleSystem::GetPaused()
{
	return Paused;
}

void ScreenEntityParticleSystem::SetPaused(bool newPaused)
{
	Paused = newPaused;
}

float ScreenEntityParticleSystem::GetLastTime()
{
	return LastTime;
}

void ScreenEntityParticleSystem::SetLastTime(float newLastTime)
{
	LastTime = newLastTime;
}

stack<int> ScreenEntityParticleSystem::GetDeadList()
{
	return DeadList;
}

void ScreenEntityParticleSystem::SetDeadList(stack<int> newDeadList)
{
	for(int i = 0;i < DeadList.size();i++)
		DeadList.pop();

	for(i = 0;i < newDeadList.size();i++)
	{
		DeadList.push(newDeadList.top());
		newDeadList.pop();
	}
}

vector<Particle> ScreenEntityParticleSystem::GetParticleList()
{
	return ParticleList;
}

void ScreenEntityParticleSystem::SetParticleList(vector<Particle> newParticleList)
{
	ParticleList.clear();

	for(vector<Particle>::iterator walker = newParticleList.begin();walker != newParticleList.end();walker++)
	{
		ParticleList.push_back(*walker);
	}
}






edit: Almost forgot, D3DFVF_TLVERTEXPOINT = D3DFVF_XYZRHW | D3DFVF_DIFFUSE; If anybody can spot the problem I will be eternally grateful! Also, any comments on the code are welcome. Thanks in advance. Kind regards. Mark Coleman [Edited by - mrmrcoleman on January 11, 2005 12:31:02 PM]

Share this post


Link to post
Share on other sites
Advertisement
This kind of problem you solve easiest with a trial&error approach, just comment out states till you can pinpoint whats going wrong.

Share this post


Link to post
Share on other sites
I have had a bit of a tinker about and I have more problems...

I took all the rest of the interface out so that no textured quads were being drawn and now I can see my particles but they are flashing on and off with a frequency of about 0.5 seconds.

Also the supposedly dead particles seem to be being drawn (also flashing) in their final location until they are reused.

Can anybody see a problem in the render section of my code? I pretty much plagiarised the algorithm from an example that I found on the internet (which I believe is very similar to the SDK sample) without fully understanding it. And I still don't really understand how it works because my knowledge of vertex buffers and how they work is limited at best.

Could somebody look through my rendering code and see if they can see any problems? As far as I am aware it is pretty much identical to the sample but the vertices are XYZRHW | DIFFUSE because my interface is all in 2d.

Thanks in advance.

Regards.

Mark Coleman

Share this post


Link to post
Share on other sites
To draw the particles are you just iterating through the live particle list? casue when you kill a particle you add it to the dead list but as far as i can tell you dont remove it from the live list. That could be why the dead particles are being redraw?

Then again maybe not, im not 1337 enought to know what most of that code does:)

Share this post


Link to post
Share on other sites
Grekster, the particles are not removed from the ParticleList, they just have a flag set to tell the render code that they are dead. In the render loop this is checked (if(!walker->Dead)), and the particle is only drawn if the particle is 'alive'.

Thanks for the response though.

Mark Coleman

Share this post


Link to post
Share on other sites
Oh I missed that check lol. Im not very up on Direct X so it must have just blended in with all the meaningless DX code lol

Anyway good luck fixing it:)

Share this post


Link to post
Share on other sites
Ok, I have had a play around and have found that some of the render states in the RenderScreenEntity method were incorrect for point sprites in Orthogonal mode, also I had forgotten to reset the stream source which explains why the other screen entities were not drawing correctly. However I still have the problem that the entities are only visible only some of the time and when they are visible they seem to be flashing on and off?

Here is the new cpp file.

#include "ScreenEntityParticleSystem.h"

// TODO -- Add the gravity vector as a member of this class
// Also make render call update if the system is not paused
// GetRandomNumber needs to be able to return negative values
// Correct the clearing of stack objects

// Need to take into account the VELOCITY VAR

// Try using an object, the render states will definately be wrong.
// Make sure the states are changed before and after the render method

// Default constructor
ScreenEntityParticleSystem::ScreenEntityParticleSystem()
:ScreenEntityBase()
{
RECT TempRect;
TempRect.bottom = 0;
TempRect.top = 0;
TempRect.left = 0;
TempRect.right = 0;

ReleaseArea = TempRect;
ParticleTextureLocation = "";
Gravity = false;
ReleaseInterval = 1.0f;
MaxParticles = 1;
VBOffset = 0;
Flush = 128;
Discard = 512;
Size = 1.0f;
VelocityVar = 1.0f;
Paused = true;
SupportsPSIZE = false;
LastTime = timeGetTime();
LastEmit = 0.0f;

//TODO -- Is this necessary
//DeadList.clear();
ParticleList.clear();
}

// Copy constructor
ScreenEntityParticleSystem::ScreenEntityParticleSystem(ScreenEntityParticleSystem & rhs)
:ScreenEntityBase(rhs)
{
// Copy all the simple types
ParticleTextureLocation = rhs.GetParticleTextureLocation();
Gravity = rhs.GetGravity();
ReleaseArea = rhs.GetReleaseArea();
ReleaseInterval = rhs.GetReleaseInterval();
MaxParticles = rhs.GetMaxParticles();
VBOffset = rhs.GetVBOffset();
Flush = rhs.GetFlush();
Discard = rhs.GetDiscard();
MaxPointSize = rhs.GetMaxPointSize();
Size = rhs.GetSize();
VelocityVar = rhs.GetVelocityVar();
Paused = rhs.GetPaused();
SupportsPSIZE = rhs.GetSupportsPSIZE();
LastTime = rhs.GetLastTime();
LastEmit = rhs.GetLastEmit();

for(int i = 0;i < DeadList.size();i++)
DeadList.pop();

for(i = 0;i < rhs.GetDeadList().size();i++)
{
DeadList.push(rhs.GetDeadList().top());
rhs.GetDeadList().pop();
}

ParticleList.clear();

for(vector<Particle>::iterator walker = rhs.GetParticleList().begin();walker != rhs.GetParticleList().end();walker++)
{
ParticleList.push_back(*walker);
}
}

// Constructor
ScreenEntityParticleSystem::ScreenEntityParticleSystem(RECT cScreenRectangle,
DWORD cFlags,
int cDepthLevel,
string cBehaviourModifier,
string cParticleTexture)
:ScreenEntityBase(cScreenRectangle,
cFlags,
cDepthLevel,
cBehaviourModifier),
ParticleTextureLocation(cParticleTexture)
{
LastTime = timeGetTime();
LastEmit = 0.0f;
}

// Deconstructor
ScreenEntityParticleSystem::~ScreenEntityParticleSystem()
{
// This may also need to be filled in at a later date
}

// Assignment operator
ScreenEntityParticleSystem& ScreenEntityParticleSystem::operator =(ScreenEntityParticleSystem & rhs)
{
if(this == &rhs)
return *this;

// Call the base class operator so that the full assignment in carried out
ScreenEntityBase::operator=(rhs);

// Copy all the simple types
ParticleTextureLocation = rhs.GetParticleTextureLocation();
Gravity = rhs.GetGravity();
ReleaseArea = rhs.GetReleaseArea();
ReleaseInterval = rhs.GetReleaseInterval();
MaxParticles = rhs.GetMaxParticles();
VBOffset = rhs.GetVBOffset();
Flush = rhs.GetFlush();
Discard = rhs.GetDiscard();
MaxPointSize = rhs.GetMaxPointSize();
Size = rhs.GetSize();
VelocityVar = rhs.GetVelocityVar();
Paused = rhs.GetPaused();
SupportsPSIZE = rhs.GetSupportsPSIZE();
LastTime = rhs.GetLastTime();
LastEmit = rhs.GetLastEmit();

for(int i = 0;i < DeadList.size();i++)
DeadList.pop();

for(i = 0;i < rhs.GetDeadList().size();i++)
{
DeadList.push(rhs.GetDeadList().top());
rhs.GetDeadList().pop();
}

ParticleList.clear();

for(vector<Particle>::iterator walker = rhs.GetParticleList().begin();walker != rhs.GetParticleList().end();walker++)
{
ParticleList.push_back(*walker);
}

return *this;
}


// Initialise the screen entity
HRESULT ScreenEntityParticleSystem::Initialise()
{
// Create a vertex buffer for the particle system
if(FAILED(GlobalDirect3D9Device->CreateVertexBuffer(Discard*sizeof(PointVertex),
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY | D3DUSAGE_POINTS,
D3DFVF_TLVERTEXPOINT,
D3DPOOL_DEFAULT,
&VertexBuffer,
NULL)))
{
return E_FAIL;
DXTRACE_MSG("Could not create vertex buffer in particle system");
}

// Get the max point size
D3DCAPS9 d3dcaps;
GlobalDirect3D9Device->GetDeviceCaps(&d3dcaps);
MaxPointSize = d3dcaps.MaxPointSize;

// Check to see if we can change the size of the point sprites
if(d3dcaps.FVFCaps & D3DFVFCAPS_PSIZE)
SupportsPSIZE = true;
else
SupportsPSIZE = false;

// Create the texture object
if(FAILED(D3DXCreateTextureFromFile(GlobalDirect3D9Device,
ParticleTextureLocation.c_str(),
&ParticleTexture)))
{
return E_FAIL;
DXTRACE_MSG("Could not create texture file in particle system");
}

// Initialise the GlobalGravityVector
GlobalGravityVector.x = 0;
GlobalGravityVector.y = 0.5;

// The initialisation has been successful so we set the valid flag to true
Flags = Flags | SCREENENTITY_VALID;

return S_OK;
}

HRESULT ScreenEntityParticleSystem::HandleMessage(UINT MessageType, WPARAM wParam, LPARAM lParam)
{
// The particle system is not effected by user input or render calls so just return S_OK
return S_OK;
}

HRESULT ScreenEntityParticleSystem::Update()
{
DXTRACE_MSG("********************************************************");
DXTRACE_MSG("Beginning of update");
OutputInformation();

float CurrentTime = timeGetTime();
float ElapsedTime = (float)((CurrentTime - LastTime) * 0.001);

for(int i = 0;i < ParticleList.size();i++)
{
// If the particle is not dead then we process it
if(!(ParticleList.Dead))
{
// If the particle is dead, put it on the dead list
if(((CurrentTime - ParticleList.StartTime) * 0.001) >= ParticleList.LifeTime)
{
// Tell the Particle that it is dead and put a reference to it on the deadlist
ParticleList.Dead = true;
DeadList.push(i);
}
else
{
// The particle is still in it's active lifetime so we updated the position and velocity
// If gravity is switched on then we apply this here
if(Gravity)
{
ParticleList.CurrentVelocity += GlobalGravityVector * ElapsedTime;
}

// Update the position with respect to the velocity
ParticleList.CurrentPosition += ParticleList.CurrentVelocity * ElapsedTime;

// Update the alpha value
// TODO -- Finsh this
}
}
else
{
// This particle is dead so it does not need to be updated
}
}

// Now we need to emit new particles
if(((CurrentTime - LastEmit) * 0.001f) > ReleaseInterval)
{
// It is time to release a new particle, first check if there are any on the dead list
if(!(DeadList.empty()))
{
// Restart the dead particle
InitialiseParticle(&ParticleList[DeadList.top()]);

// Remove the reference from the deadlist
DeadList.pop();
}
else
{
// There are no dead particles to reactivate so we will make
// another one if there is enough space on the ParticleList
if(ParticleList.size() <= MaxParticles)
{
Particle newParticle;
InitialiseParticle(&newParticle);
ParticleList.push_back(newParticle);
}
else
{
// There is no space for any more particles so we don't do anything
}
}
LastEmit = CurrentTime;
}

// Last update the LastTime float
LastTime = CurrentTime;

DXTRACE_MSG("End of update");
OutputInformation();
DXTRACE_MSG("********************************************************");

return S_OK;
}

HRESULT ScreenEntityParticleSystem::RenderScreenEntity()
{
// If the system is not paused, then update the particles before they are rendered
if(!(Paused))
Update();

// Set the render states for using point sprites
GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
//GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSIZE, FtoDW(Size));
GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(1.0f));
//GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSCALE_A, FtoDW(0.0f));
//GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f));
//GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSCALE_C, FtoDW(1.0f));
GlobalDirect3D9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

// Used as a reference to the vertex buffer
PointVertex* Vertices;
DWORD NumParticlesToRender= 0;

// Lock the vertex buffer. Fill the vertex buffer in small chunks, using D3DLOCK_NOOVERWRITE.
// When done filling each chunk, call DrawPrimitive and lock the next chunk. When space runs
// out in the vertex buffer, start over at the beginning using D3DLOCK_DISCARD.

// Move the offset to fill the next chunk of the vertex buffer
VBOffset += Flush;

// If about to overflow the buffer, set it back to 0
if(VBOffset >= Discard)
VBOffset = 0;

// Lock the vertex buffer
HRESULT hr;
if(FAILED(hr = VertexBuffer->Lock(VBOffset*sizeof(PointVertex), // Offset to lock
Flush*sizeof(PointVertex), // Size to lock
(VOID **) &Vertices,
VBOffset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD)))
{
DXTRACE_ERR("Failed to lock the vertex buffer in the render method of the particle system", hr);
return hr;
}

GlobalDirect3D9Device->SetStreamSource(0, VertexBuffer, 0, sizeof(PointVertex));

// Render each particle
for(vector<Particle>::iterator walker = ParticleList.begin(); walker != ParticleList.end();walker++)
{
if(!(walker->Dead))
{
D3DXVECTOR2 vVel(walker->CurrentVelocity);

Vertices->posit = walker->CurrentPosition;
Vertices->color = walker->Colour;
Vertices++;

if(++NumParticlesToRender == Flush)
{
// Done filling this chunk of the vertex buffer so unlock and draw so that the
// next chunk can start being filled
VertexBuffer->Unlock();

GlobalDirect3D9Device->SetFVF(D3DFVF_TLVERTEXPOINT);

if(FAILED(hr = GlobalDirect3D9Device->DrawPrimitive(D3DPT_POINTLIST,
VBOffset,
NumParticlesToRender)))
{
DXTRACE_ERR("Draw primitive failed inside the Flush-if in the render method", hr);
return hr;
}

// Lock the next chunk of the vertex buffer. If we are at the end of the vertex buffer
// DISCARD the vertex buffer and start at the beginning. Otherwise, specify NOOVERWRITE
// so we can continue filling the VB while the previous chunk is drawing.
VBOffset += Flush;

// If about to overflow reset the offset to 0
if(VBOffset >= Discard)
VBOffset = 0;

if(FAILED(hr = VertexBuffer->Lock(VBOffset*sizeof(PointVertex),
Flush*sizeof(PointVertex),
(VOID **) &Vertices,
VBOffset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD)))
{
DXTRACE_ERR("Failed to lock the vertex buffer in the latter part of the render method", hr);
return hr;
}

NumParticlesToRender = 0;
}
}
else
{
// Do nothing as this particle is dead
}
}

// Unlock the vertex buffer
VertexBuffer->Unlock();

// Render any remaining particles
if(NumParticlesToRender)
{
GlobalDirect3D9Device->SetFVF(D3DFVF_TLVERTEXPOINT);

if(FAILED(hr = GlobalDirect3D9Device->DrawPrimitive(D3DPT_POINTLIST,
VBOffset,
NumParticlesToRender)))
{
DXTRACE_ERR("Draw primitive failed inside the final part of the render method", hr);
return hr;
}
}

// Reset render states
GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
GlobalDirect3D9Device->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
GlobalDirect3D9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
GlobalDirect3D9Device->SetFVF(D3DFVF_TLVERTEX);

// Re-set the stream source
GlobalDirect3D9Device->SetStreamSource(0, GlobalDirect3D9VertexBuffer, 0, sizeof(TLVERTEX));

return S_OK;
}

void ScreenEntityParticleSystem::OutputInformation()
{
char output[500];

// Walk through the particle list and for each particle output the colour, position,
// velocity, starttime, lifetime and alpha decay
for(vector<Particle>::iterator walker = ParticleList.begin();walker != ParticleList.end();walker++)
{
sprintf(output, "Position x: %f, Position y: %f, Velocity x: %f, Velocity y: %f, Starttime: %f, LifeTime: %f, AlphaDecay: %f",
walker->CurrentPosition.x,
walker->CurrentPosition.y,
walker->CurrentVelocity.x,
walker->CurrentVelocity.y,
walker->StartTime,
walker->LifeTime,
walker->AlphaDecay);

DXTRACE_MSG(output);
}
}

void ScreenEntityParticleSystem::Release()
{
SAFE_RELEASE(VertexBuffer);
SAFE_RELEASE(ParticleTexture);
//TODO -- Is this necessary
//DeadList.clear();
ParticleList.clear();
}

void ScreenEntityParticleSystem::ControlEntity(bool start)
{
if(start)
Paused = false;
else
Paused = true;
}

void ScreenEntityParticleSystem::InitialiseParticle(Particle* DeadParticle)
{
// Tell the particle that it is alive!
DeadParticle->Dead = false;

// Place the particle somewhere within the release area
DeadParticle->CurrentPosition.x = GetRandomNumber(ReleaseArea.left, ReleaseArea.right);
DeadParticle->CurrentPosition.y = GetRandomNumber(ReleaseArea.top, ReleaseArea.bottom);

// Set the intial velocity, colour, lifetime and alpha decay in accordance with the type of effect being created
if((Flags & PARTICLE_FIRE) > 0)
{
// ************** VELOCITY ****
// If this is fire then all the particles need to be sent more or less upwards so we
// set the y value to -2 (-y is up) and then add a Random between -10 and 10 divided
// 10 leading to +/-1
DeadParticle->CurrentVelocity.y = -2.0f;
DeadParticle->CurrentVelocity.y += (float)(GetRandomNumber(-10, 10)/10);

// The x is set straight up the middle (0) but we vary it with a random number between
// 10 and -10 which is then divide by 20 giving a maximum of 0.5 either way. That equates
// to a maximum angle of 22.5 degrees which may have to be reduced
DeadParticle->CurrentVelocity.x = 0.0f;
DeadParticle->CurrentVelocity.x += (float)(GetRandomNumber(-10,10)/20);

// ************** COLOUR ****
// Define each colour element (plus the alpha)
float r, g, b, a, random;

// Calculate the random to be 0.2 either way. So get a random number between -10 and
// 10 and then divide it by fifty.

//random = (float)(GetRandomNumber(-10,10)/50); // Random

r = 0.5f;// + random; // Red

g = 0.5f;// + random; // Green

b = 0.5f;// + random; // Blue

a = 0.5f; // Start the alpha at full

// Set the colour
DeadParticle->Colour = D3DXCOLOR(r, g, b, a);

// ************** LIFETIME ****
// Alter the life time by 0.5 either way
DeadParticle->LifeTime = 10.5f;// + (float)((GetRandomNumber(-10,10)/20));

// ************** ALPHA DECAY ****
// Alter the alpha decay by 0.1 either way
DeadParticle->AlphaDecay = 0.1;// + (float)((GetRandomNumber(-10, 10)/100));
}
else if((Flags & PARTICLE_DUST) > 0)
{
DXTRACE_MSG("Particle dust not defined yet!!");
}
else
{
DXTRACE_MSG("Particle system is of an invalid type or flag not set");
PostQuitMessage(0);
}

// Set the start time of the particle
DeadParticle->StartTime = timeGetTime();
}

// Get and set methods
string ScreenEntityParticleSystem::GetParticleTextureLocation()
{
return ParticleTextureLocation;
}

void ScreenEntityParticleSystem::SetParticleTextureLocation(string newParticleTextureLocation)
{
ParticleTextureLocation = newParticleTextureLocation;
}

bool ScreenEntityParticleSystem::GetGravity()
{
return Gravity;
}

void ScreenEntityParticleSystem::SetGravity(bool newGravity)
{
Gravity = newGravity;
}


DWORD ScreenEntityParticleSystem::GetVBOffset()
{
return VBOffset;
}

void ScreenEntityParticleSystem::SetVBOffset(DWORD newVBOffset)
{
VBOffset = newVBOffset;
}

RECT ScreenEntityParticleSystem::GetReleaseArea()
{
return ReleaseArea;
}

bool ScreenEntityParticleSystem::GetSupportsPSIZE()
{
return SupportsPSIZE;
}

void ScreenEntityParticleSystem::SetReleaseArea(RECT newReleaseArea)
{
ReleaseArea = newReleaseArea;
}

float ScreenEntityParticleSystem::GetReleaseInterval()
{
return ReleaseInterval;
}

void ScreenEntityParticleSystem::SetReleaseInterval(float newReleaseInterval)
{
ReleaseInterval = newReleaseInterval;
}

int ScreenEntityParticleSystem::GetMaxParticles()
{
return MaxParticles;
}

void ScreenEntityParticleSystem::SetMaxParticles(int newMaxParticles)
{
MaxParticles = newMaxParticles;
}

DWORD ScreenEntityParticleSystem::GetFlush()
{
return Flush;
}

void ScreenEntityParticleSystem::SetFlush(DWORD newFlush)
{
Flush = newFlush;
}

DWORD ScreenEntityParticleSystem::GetDiscard()
{
return Discard;
}

void ScreenEntityParticleSystem::SetDicard(DWORD newDiscard)
{
Discard = newDiscard;
}

float ScreenEntityParticleSystem::GetMaxPointSize()
{
return MaxPointSize;
}

void ScreenEntityParticleSystem::SetMaxPointSize(float newMaxPointSize)
{
MaxPointSize = newMaxPointSize;
}

float ScreenEntityParticleSystem::GetSize()
{
return Size;
}

void ScreenEntityParticleSystem::SetSize(float newSize)
{
Size = newSize;
}

float ScreenEntityParticleSystem::GetVelocityVar()
{
return VelocityVar;
}

void ScreenEntityParticleSystem::SetVelocityVar(float newVelocityVar)
{
VelocityVar = newVelocityVar;
}

bool ScreenEntityParticleSystem::GetPaused()
{
return Paused;
}

void ScreenEntityParticleSystem::SetPaused(bool newPaused)
{
Paused = newPaused;
}

float ScreenEntityParticleSystem::GetLastTime()
{
return LastTime;
}

void ScreenEntityParticleSystem::SetLastTime(float newLastTime)
{
LastTime = newLastTime;
}

float ScreenEntityParticleSystem::GetLastEmit()
{
return LastEmit;
}

void ScreenEntityParticleSystem::SetLastEmit(float newLastEmit)
{
LastEmit = newLastEmit;
}

stack<int> ScreenEntityParticleSystem::GetDeadList()
{
return DeadList;
}

void ScreenEntityParticleSystem::SetDeadList(stack<int> newDeadList)
{
for(int i = 0;i < DeadList.size();i++)
DeadList.pop();

for(i = 0;i < newDeadList.size();i++)
{
DeadList.push(newDeadList.top());
newDeadList.pop();
}
}

vector<Particle> ScreenEntityParticleSystem::GetParticleList()
{
return ParticleList;
}

void ScreenEntityParticleSystem::SetParticleList(vector<Particle> newParticleList)
{
ParticleList.clear();

for(vector<Particle>::iterator walker = newParticleList.begin();walker != newParticleList.end();walker++)
{
ParticleList.push_back(*walker);
}
}



If anybody could find time to have a quick look through I would be extremely apreciative. This is driving me crazy now.

Kind regards.

Mark Coleman

Share this post


Link to post
Share on other sites
Ok, I have found that I wasn't setting the correct texture to be rendered but I am still getting an annoying flashing of the particles. Now the particles are permanently visible but they seem to be flashing in groups independent of each other, some will be flashing whilst others are not?

I have had a look at some screen shots and it looks like the number of particles in each 'group' (whether flashing or not) is equal to the flush size of one 'batch' of particles which is sent to the vertex buffer in one go. This seems to indicate that there is a problem with my vertex buffer, what do you think?

Has anybody seen this before? Am I wasting my time asking or not? Nobody seems to have any idea..!

Anyway, a huge thanks for any help to solve this extremely annoying problem.

Kind regards.

Mark Coleman

Share this post


Link to post
Share on other sites
Ok I think I found your problem
I think its on this file right here

ScreenEntityParticleSystem.h

I saw a comment of yours saying amount of alpha that decays each time, the alpha channel is related to the transparencie(however you write this) of the RGB channels so thats why the particles are flashing I think that you made some kinda of loop on this so they are becoming transparent and solid in a great speed so it looks like flashes
Hope this helped a bit
If not I dont know
At least also please take a time to look at my thread and try to solve my small 2 mistakes :)

Share this post


Link to post
Share on other sites
Hello. I managed to fix the flashing. I had the wrong vertex buffer settings. The flush and the discard were set at 32 and 128 respectably with a max particle count of 512. I found that when I increased the flush, discard and max particles to 128, 512 and 1024 respectively and the flashing stopped altogether. I don't understand why it works, but I am just happy that it does. Perhaps someone could explain to me why this is the case?

Regards.

Mark Coleman

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement