Jump to content
  • Advertisement
Sign in to follow this  
RenZimE

[.net] i am at the end of my rope with this (simple particle system)

This topic is 5395 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

ok i am really at the end of my rope with this, can any one see why this would not update the particle when actualy rendering. it works off screen in the testing but not when actualy rendering, all i get is a bunch of particles just hanging there in space. its really got me swearing at my pc.
#region Using directives

using System;
using Tao.OpenGl;
using Tao.Platform.Windows;
#if CSHARP2
using System.Collections.Generic;
#else
using System.Collections;
#endif

#endregion

namespace StarFeck
{
	public struct Particle
	{
		public bool active;
		public float _scale;

		public float life;
		public float fade;
		public float mass;
		public float acceleration;

		public Vector3D location;
		public Vector3D velocity;
		public Vector3D color;

		public void Update(float fTime)
		{
			if (!active)
				return;
			
			location.X += velocity.X * acceleration; // fTime ignored on movement for time being
			location.Y += velocity.Y * acceleration;
			location.Z += velocity.Z * acceleration;

			life -= (fade * fTime);

			if (life <= 0)
				active = false;
		}

		public void Render()
		{
			if (!active) // dont draw it not active
				return;

			Gl.glPushMatrix();
			
			Gl.glTranslatef(location.X, location.Y, location.Z);

			Gl.glBegin(Gl.GL_TRIANGLE_STRIP);
				Gl.glColor4f(color.X, color.Y, color.Z, life);
				Gl.glTexCoord2d(0, 0); Gl.glVertex3f(-0.5f * _scale, -0.5f * _scale, 0);
				Gl.glTexCoord2d(0, 1); Gl.glVertex3f(-0.5f * _scale, 0.5f * _scale, 0);
				Gl.glTexCoord2d(1, 0); Gl.glVertex3f(0.5f * _scale, -0.5f * _scale, 0);				
				Gl.glTexCoord2d(1, 1); Gl.glVertex3f(0.5f * _scale, 0.5f * _scale, 0);
			Gl.glEnd();
			
			Gl.glPopMatrix();
		}


	}

	public class ParticleEmiter
	{
#if CSHARP2
		protected Collection<Particle> m_liveParticles = new Collection<Particle>();
		protected Collection<Particle> m_particlePool = new Collection<Particle>();
#else
		protected ArrayList m_liveParticles	= new ArrayList();
		protected ArrayList m_particlePool	= new ArrayList();
#endif	
		protected Vector3D m_Center = new Vector3D();

		protected string m_TexturePath;
		protected int m_ParticleCountMax=0;
		protected int m_LiveParticleCount=0;
		protected int m_ParticlePoolCount=0;
		protected GLTexture2D m_ParticleTexture = new GLTexture2D();


		public ParticleEmiter(string texpath,int particles,float scale)
		{
			m_Center = new Vector3D(0, 0, 0);

			m_ParticleTexture.LoadTexture(texpath);
			m_ParticleCountMax = particles;
			m_ParticlePoolCount = particles;
			Particle p= new Particle();

			for (int i = 0; i < particles; i++)
			{
				p._scale = scale;
				p.acceleration = 1.0f;
				p.active = false;
				p.color = new Vector3D(1.0f, 0, 0);
				p.life = 1.0f;
				p.location = m_Center;
				p.mass = 1.0f;
				p.velocity = m_Center;
				m_particlePool.Add(p);
			}
		}

		public void Explode(int particles,float acceleration,Vector3D color)
		{
			Random r = new Random();
			Particle p;
			if (m_ParticlePoolCount < particles)
				return;

			for (int i = 0; (i < particles) && (i < m_ParticlePoolCount); i++)
			{
#if CSHARP2
				p = m_particlePool;
#else
				p =(Particle)m_ParticlePool;
#endif
				p.location = m_Center;
				p.color = color;
				p.acceleration = acceleration;
				p._scale = 2.0f;
				p.velocity = new Vector3D(r.Next(-100, 100) / 10.0f, r.Next(-100, 100) / 10.0f, r.Next(-100, 100) / 10.0f);
				p.life = 6.0f;
				p.fade = 0.1f;
				p.active = true;
				m_liveParticles.Add(p);
				m_LiveParticleCount++;
				m_particlePool.RemoveAt(i);
			}
		}

		public void UpdateParticles(float fTime)
		{
			Particle p;
			for (int i = 0; i < m_liveParticles.Count; i++)
			{
#if CSHARP2
				p = m_liveParticles;
#else
				p =(Particle)m_liveParticles;
#endif				

				if (p.active)
				{
					p.Update(fTime);
					m_ParticleTexture.Bind();
					p.Render();
				}
				else
				{
					m_particlePool.Add(p);
					m_liveParticles.Remove(p);
					m_LiveParticleCount--;
					m_ParticlePoolCount++;
				}
			}
		}
	}
}


some one please help me before i go bald :(

Share this post


Link to post
Share on other sites
Advertisement
Disclaimer: I could be way wrong here.

You have to remember that in .NET you have two different types at the core. You have reference types, and you have value types. If you pass around value types, then a new type is created and then that type is passed. Now, a struct is a value type and not a reference type. So, when you pull the particle out of your list, a new particle is created and then you update that particle. The original particle remains untouched because it wasn't passed by reference. There's two directions you could go. Check out the "ref" keyword that allows you to pass a value type by reference, or to change the struct to a class so that it is passed around by reference by default.

I hope this assesment is at least partly correct and helps at least a little bit :).

Share this post


Link to post
Share on other sites
Hey man maybe I am just not seeing it, but where is your main loop? I see the particle object and the particle emitter object. Looks like they should work. If we could see the rest of the code we might be able to help you out a bit more.

Share this post


Link to post
Share on other sites
Quote:
Original post by bL0wF1sH
Disclaimer: I could be way wrong here.

You have to remember that in .NET you have two different types at the core. You have reference types, and you have value types. If you pass around value types, then a new type is created and then that type is passed. Now, a struct is a value type and not a reference type. So, when you pull the particle out of your list, a new particle is created and then you update that particle. The original particle remains untouched because it wasn't passed by reference. There's two directions you could go. Check out the "ref" keyword that allows you to pass a value type by reference, or to change the struct to a class so that it is passed around by reference by default.

I hope this assesment is at least partly correct and helps at least a little bit :).


omg your absolutly spot on there blowfish. i made such a silly mistake :( i forgot to re insert the updated particle back into list. ( i feel stupidly idiotic now after having gotten some sleep and taking another look at it )

p.s.
just ask if you wish to see my particle solution and i shall post it( how ever basic it may seem its a nice easy example and could be ported to direx3D)

[Edited by - RenZimE on October 14, 2004 7:51:44 AM]

Share this post


Link to post
Share on other sites
well this is what i came up with after a few hours of bashing my head against my desk last night then sleeping on the thoughts (and the lumps).


the following source is useable for any one who wants to use it and learn from it. its only one way to do some it and probably not the best or fastest.


#region Using directives

using System;
using Tao.OpenGl;
using Tao.Platform.Windows;
#if CSHARP2
using System.Collections.Generic;
#else
using System.Collections;
#endif

#endregion

/// <Refs>
/// Particle system version 0.1
/// needs work in some area's
///
/// Author. RenZimE
/// all source and algorithems remain the property of the author and respective owners.
/// </Refs>

namespace StarFeck
{
#region Delegates
public delegate void ParticleUpdateMethod(ref Particle p,float fTime);
public delegate void ParticleSetupMethod(ref Particle p);
#endregion

#region Particle structure
public struct Particle
{
#region Particle Variables
public bool active;
public float _scale;

public float life;
public float fade;
public float mass;
public float acceleration;

public Vector3D location;
public Vector3D velocity;
public Vector3D color;

private Vector3D vD;
private Vector3D vR;
private Vector3D vU;
private Matrix bbMatrix;
#endregion
#region Methods
/// <summary>
/// this function is designed to render the particle with billboarding
/// while it was only designed for this it would not take much to impliment
/// a frustum culling system into it.
/// </summary>
/// <param name="Cam">Current Camera</param>
public void Render(CCamera Cam)
{
Gl.glPushMatrix();

vD = Cam.Location - location;
vD.Normalize();
vR = MathEx.cross(Cam.UpDirection, vD);
vU = MathEx.cross(vD, vR);

bbMatrix = new Matrix(vR.X, vR.Y, vR.Z, 0,
vU.X, vU.Y, vU.Z, 0,
vD.X, vD.Y, vD.Z, 0,
location.X, location.Y, location.Z, 1);

Gl.glMultMatrixf(bbMatrix.m);

Gl.glDepthMask(Gl.GL_FALSE);
Gl.glBegin(Gl.GL_TRIANGLE_STRIP);
Gl.glColor4f(color.X, color.Y, color.Z, life);
Gl.glTexCoord2d(0, 0); Gl.glVertex3f(-0.5f * _scale, -0.5f * _scale, 0);
Gl.glTexCoord2d(0, 1); Gl.glVertex3f(-0.5f * _scale, 0.5f * _scale, 0);
Gl.glTexCoord2d(1, 0); Gl.glVertex3f(0.5f * _scale, -0.5f * _scale, 0);
Gl.glTexCoord2d(1, 1); Gl.glVertex3f(0.5f * _scale, 0.5f * _scale, 0);
Gl.glEnd();
Gl.glDepthMask(Gl.GL_TRUE);

Gl.glPopMatrix();
}

/// <summary>
/// basic render function for the particle
/// </summary>

public void Render()
{
if (!active) // dont draw it not active
return;

Gl.glPushMatrix();

Gl.glTranslatef(location.X, location.Y, location.Z);

Gl.glPopMatrix();
}
#endregion
}
#endregion

#region Particle Emiter class
/// <summary>
/// Basic Particle emiter designed to be easily extendable
/// using Delegates to handle particle updates and creation
/// values.
/// </summary>
public class ParticleEmiter
{
/// <note>
/// Need to Comment class and perform optimizations
/// to the emiter to improve performace under large
/// particle counts of 1k and up
/// </note>

#if CSHARP2
private Collection<Particle> m_liveParticles = new Collection<Particle>();
private Collection<Particle> m_particlePool = new Collection<Particle>();
#else
private ArrayList m_liveParticles = new ArrayList();
private ArrayList m_particlePool = new ArrayList();
#endif
private Vector3D m_Center = new Vector3D();

private string m_TexturePath;
private int m_ParticleCountMax = 0;
private int m_LiveParticleCount = 0;
private int m_ParticlePoolCount = 0;
private float m_scale = 0;
private Vector3D m_HeadingApature = new Vector3D(2.0f, 2.0f, 2.0f);

private Random m_Rand = new Random();

private GLTexture2D m_ParticleTexture = new GLTexture2D();

public ParticleUpdateMethod UpdateMethod = null;
public ParticleSetupMethod SetupMethod = null;

public Vector3D HeadingApature
{
get { return m_HeadingApature; }
set { m_HeadingApature = value; }
}

public Vector3D Location
{
get { return m_Center; }
set { m_Center = value; }
}

public int FreeParticleCount
{
get { return m_ParticlePoolCount; }
}

public int UsedParticles
{
get { return m_LiveParticleCount; }
}

public int NumParticles
{
get { return m_ParticleCountMax; }
set { m_ParticleCountMax = value; }
}

public ParticleEmiter(string texpath,int particles,float scale)
{
m_Center = new Vector3D(0, 0, 0);

m_ParticleTexture.LoadTexture(texpath);
m_ParticleCountMax = particles;
m_scale = scale;
}

public void EmitParticles(float fTime)
{
Particle p;
while( m_LiveParticleCount < m_ParticleCountMax)
{
if (m_particlePool.Count > 0)
{
#if CSHARP2
p = m_particlePool[0];
#else
p =(Particle)m_particlePool[0];
#endif
m_particlePool.RemoveAt(0);
}
else
p = new Particle();

if (SetupMethod != null)
SetupMethod(ref p);
else
DefParticleSetup(ref p);

m_LiveParticleCount++;

m_liveParticles.Add(p);
}
for(int i = 0; i < m_LiveParticleCount; i++)
{

#if CSHARP2
p = m_liveParticles;
#else
p = (Particle)m_LiveParticles;
#endif

if (UpdateMethod != null)
UpdateMethod(ref p, fTime);
else
DefParticleUpdate(ref p, fTime);

if (p.active)
{
m_liveParticles = p;
}
else
{
if (m_LiveParticleCount <= m_ParticleCountMax)
{
m_particlePool.Add(p);
m_liveParticles.RemoveAt(i);
m_LiveParticleCount--;
m_ParticlePoolCount++;
}
else
{
m_liveParticles.RemoveAt(i);
m_LiveParticleCount--;
}
}
}
}

public void Render()
{
Gl.glEnable(Gl.GL_BLEND); // Enable Blending
Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE); // Type Of Blending To Perform
m_ParticleTexture.Bind();
for (int i = 0; i < m_LiveParticleCount; i++)
{

#if CSHARP2
m_liveParticles.Render();
#else
((Particle)m_LiveParticles).Render();
#endif
}
Gl.glDisable(Gl.GL_BLEND);
}

public void Render(CCamera Cam)
{
Gl.glEnable(Gl.GL_BLEND); // Enable Blending
Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE); // Type Of Blending To Perform
m_ParticleTexture.Bind();
for (int i = 0; i < m_LiveParticleCount; i++)
{

#if CSHARP2
m_liveParticles.Render(Cam);
#else
((Particle)m_LiveParticles).Render(Cam);
#endif
}
Gl.glDisable(Gl.GL_BLEND);
}

public void ClearEmiter()
{
m_particlePool.Clear();
m_liveParticles.Clear();
m_LiveParticleCount = 0;
m_ParticlePoolCount = 0;
}

// a nice and simple burst Setup for our particle
public void DefParticleSetup(ref Particle p)
{
p._scale = m_scale;
p.acceleration = (float)m_Rand.NextDouble();
p.color = new Vector3D(0, (float)m_Rand.NextDouble() - 0.5f, (float)m_Rand.NextDouble() + 0.5f);
p.fade = 0.1f;
p.life = 1.0f;
p.location = m_Center;
p.velocity = new Vector3D(((float)m_Rand.NextDouble() - 0.5f) * m_HeadingApature.X,
((float)m_Rand.NextDouble() - 0.5f) * m_HeadingApature.Y,
((float)m_Rand.NextDouble() - 0.5f) * m_HeadingApature.Z);
p.active = true;
}

// a nice and basic update for our particle (a simple burst)
public void DefParticleUpdate(ref Particle p,float fTime)
{
if (!p.active)
return;

p.location += p.velocity * p.acceleration;

p.life -= (p.fade * fTime);
if(p._scale > 0)
p._scale -= (p.fade * fTime);

if (p.life <= 0)
p.active = false;
}
}
#endregion
}


Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!