I'm building a particle engine and an having trouble with inheritance. I have a particle struct that contains information like position and color about ine particle, and a particle engine class that updates all the particles and draws them. It contains a virtual function that controls the details of the update, and so I inheret from it classes like smoke and fire which implement it in a certain way. Heres the header for the engine:
#ifndef PARTICLEENGINE_H
#define PARTICLEENGINE_H
#include "3DMath.h"
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <vector>
using namespace std;
struct SParticle{
SParticle();
bool Active;
float Life;
float Fade;
//float Rotation;
float Red;
float Green;
float Blue;
float MultAlpha;
float Radius;
float RadiusSpeed;
float Rotation;
CVector3 Position;
CVector3 Direction;
CVector3 Gravity;
bool ChangeColor;
};
class CParticleEngine{
public:
//holds all the particles
vector<SParticle> m_vParticles;
int m_iNumberOfParticles;
float m_fSlowDown;
void InitAllParticles();
CParticleEngine(int n, CVector3 p);
CVector3 m_vPosition;
void Update(double elapsed_time);
//all entities must implement an init function
virtual void InitOneParticle(SParticle &particle) = 0;
CVector3 Vector(){return m_vPosition;}
float Number(){return m_vParticles[0].Life;}
};
class Smoke : public CParticleEngine{
public:
Smoke(int n, CVector3 p);
void InitOneParticle(SParticle &particle);
};
#endif
and here's the source file:
#include "ParticleEngine.h"
#include "CCamera.h"
#include <gl\gl.h>
extern GLuint t_Particles[3];
extern int yay;
extern CCamera Camera;
//-------------SParticle--------------
//
// Constructor for SParticle
//
//------------------------------------
SParticle :: SParticle()
{
Active = true;
Life = 1.0;
Fade = 0;
Red = 1;
Green = 1;
Blue = 1;
MultAlpha = 1;
Radius = 10;
RadiusSpeed = 0.1;
Rotation = 0;
Position = CVector3(0,0,0);
Direction = CVector3(5,5,5);
Gravity = CVector3(0,0,0);
ChangeColor = false;
}
//------------------CParticleEngine-------------------
//
// Constructor for CParticleEngine
//
//----------------------------------------------------
CParticleEngine :: CParticleEngine(int n, CVector3 p)
{
m_vPosition = p;
m_fSlowDown = 2.0;
for(int i=0; i<n; ++i)
{
// SParticle *particle = new SParticle();
// m_vParticles.push_back(particle);
m_vParticles.push_back(SParticle());
}
InitAllParticles();
}
//------------------InitAllParticles------------------
//
// initiates all particles
//
//----------------------------------------------------
void CParticleEngine :: InitAllParticles()
{
for(int i=0; i<m_vParticles.size(); i++)
{
// m_vParticles->InitParticle(m_vPosition);
InitOneParticle(m_vParticles);
}
}
//----------------------Update---------------------
//
// Updates the particles
//
//-------------------------------------------------
void CParticleEngine :: Update(double elapsed_time)
{
elapsed_time*=50;
glBindTexture(GL_TEXTURE_2D,t_Particles[2]);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
for (int loop=0;loop<m_vParticles.size();loop++) // Loop Through All The Particles
{
glLoadIdentity();
Camera.Look();
glTranslatef(0, 10, 0);
float x = m_vParticles[loop].Position.x;
float y = m_vParticles[loop].Position.y;
float z = m_vParticles[loop].Position.z;
// Draw The Particle Using Our RGB Values, Fade The
//Particle Based On It's Life
glColor4f(m_vParticles[loop].Red,
m_vParticles[loop].Green,
m_vParticles[loop].Blue,
m_vParticles[loop].Life/m_vParticles[loop].MultAlpha);
float radius = m_vParticles[loop].Radius;
glTranslatef(x, y, z);
glRotatef(m_vParticles[loop].Rotation,0,0,1);
glBegin(GL_TRIANGLE_STRIP);
// Build Quad From A Triangle Strip
glTexCoord2d(1,1); glVertex3f(radius,radius,0);
glTexCoord2d(0,1); glVertex3f(-
radius,radius,0);
glTexCoord2d(1,0); glVertex3f(radius,-
radius,0);
glTexCoord2d(0,0); glVertex3f(-radius,-
radius,0);
glEnd();
m_vParticles[loop].Position.x +=
elapsed_time*m_vParticles[loop].Direction.x/(m_fSlowDown*1000);
m_vParticles[loop].Position.y +=
elapsed_time*m_vParticles[loop].Direction.y/(m_fSlowDown*1000);
m_vParticles[loop].Position.z +=
elapsed_time*m_vParticles[loop].Direction.z/(m_fSlowDown*1000);
m_vParticles[loop].Direction.x +=
elapsed_time*m_vParticles[loop].Gravity.x;
m_vParticles[loop].Direction.y +=
elapsed_time*m_vParticles[loop].Gravity.y;
m_vParticles[loop].Direction.z +=
elapsed_time*m_vParticles[loop].Gravity.z;
m_vParticles[loop].Radius += elapsed_time*m_vParticles
[loop].RadiusSpeed;
m_vParticles[loop].Life -= elapsed_time*m_vParticles[loop].Fade;
if (m_vParticles[loop].Life<=0.0f) // If Particle Is Burned Out
{
InitOneParticle(m_vParticles[loop]);
}
}//loop
}
Smoke :: Smoke(int n, CVector3 p):CParticleEngine(n, p){}
void Smoke :: InitOneParticle(SParticle &particle)
{
particle.Active = true;
particle.Life = 1.0;
particle.Fade = (rand()%150)/1000.0f + 0.002;
particle.MultAlpha = 2.5;
particle.Radius = 10;
particle.RadiusSpeed = (rand()%150)/1000.0f + 0.002;
float col = (rand()%600)/1000.0f;
particle.Red = col; // Select Red Rainbow Color
particle.Green = col; // Select Red Rainbow Color
particle.Blue = col;
particle.Rotation = (rand()%100)*3.6;
//Position = p;//CVector3(20,20,20);
particle.Direction = CVector3(float((rand()%50)-26.0f)*0.0f,
float((rand()%20)+10.0f)*70.0f,
float((rand()%50)-26.0f)*0.0f);
particle.Position = m_vPosition + CVector3(float((rand()%50)-26.0f)*0.15f,
float((rand()%20)+10.0f)*0.0f,
float((rand()%50)-26.0f)*0.15f);
//CVector3 Direction = CVector3(10,10,0);
particle.Gravity = CVector3(-5,0,0);
}
now when I call the constructor like this:
Smoke Smoke(1000, CVector3(80,120,80));
I get some kind of runtime error/crash. if I erase the InitAllParticles();
from the ctor then it doesn't crash. Also, if I make the
InitOneParticle(SParticle &particle) not virtual, but rather part of CParticleEngine and call the ctor:
CParticleEngine ParticleEngine(1000, CVector3(120,120,180));
then it works fine?
What is the problem?
Thanks.
"We've all heard that a million monkeys banging on a million typewriters will eventually reproduce the entire works of Shakespeare. Now, thanks to the internet, we know this is not true." -- Professor Robert Silensky