Skip to main content
gamedev.net
🔒 Locked 🎮 Unity

Particle system problem...

Started by mrmrcoleman Jan 10, 2005 at 12:29 PM 1 replies 400+ views
Original Post
mrmrcoleman
mrmrcoleman
This may be a DirectX problem, but I have a thread over there also. I thought you guys might be able to check out my algorithms for me. I have a 2d user interface which is mainly composed of textured quads. I have just implemented a particle system which uses point sprites but I don't seem to be having much luck. Sometimes I can see the particles and sometimes I can't, and when I can see them they are flashing on and off with a frequency of about 0.5 seconds. The code for the particle system class is shown below. ScreenEntityParticleSystem.cpp

#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);
	}
}

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

	float GetLastEmit();
	void SetLastEmit(float newLastEmit);

	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	
	float LastEmit;					// The last time new particles were emitted

	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

Thanks for any help guys, I can't figure out what the problem could be?! Kind regards. Mark Coleman
HarryW
HarryW
Sounds like z-fighting perhaps? Are the quads you're using for particles coplanar with a background quad, or something similar? You could turn depth testing off to check, assuming your particles are rendered after your background.
Harry.
mrmrcoleman
mrmrcoleman
Hello HarryW, I have these RenderStates set globally.

GlobalDirect3D9Device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
GlobalDirect3D9Device->SetRenderState(D3DRS_ZENABLE, FALSE);

I have tested the render code with only the particle system involved and I still get the same problems so I don't think it is a z problem?

Mark Coleman

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.