bettsmatt/BetaFX

Working on particle effects

1 parent 9c68892 commit f5c5f43871321bf48e99818492d58bbf66f64652 committed Oct 16, 2012
Showing with 190 additions and 61 deletions.
1. +19 −10 Particle.cpp
2. +9 −5 Particle.h
3. +107 −42 ParticleEmitter.cpp
4. +8 −1 ParticleEmitter.h
5. +38 −0 Render.h
6. +9 −3 main.cpp
29 Particle.cpp
 @@ -20,18 +20,19 @@ #include #include -Particle::Particle(float* initialVelocity) { +void Particle::init(float* pos, float* initialVelocity, float m, Camera* cam) { - // Zero position = new float[3]; velocity = new float[3]; acceletation = new float[3]; - // Set initial velocity - for(int i = 0 ; i < 3 ; i ++) + + for (int i = 0 ; i < 3 ; i ++){ + position[i] = pos[i]; velocity[i] = initialVelocity[i]; + } - mass = 1; // Default + mass = m; // Default /* * Lifespan @@ -40,12 +41,8 @@ Particle::Particle(float* initialVelocity) { float LO = 18000; lifeSpanLeft = lifeSpan = LO + (float)rand()/((float)RAND_MAX/(HI-LO)); -} + camera = cam; -Particle::~Particle(void) { - free(position); - free(velocity); - free(acceletation); } @@ -80,6 +77,18 @@ void Particle::tick (){ } +float Particle::Dist(){ + return sqrt( + (position[0] * position[0]) - (camera->rotx * camera->rotx) + + (position[1] * position[1]) - (camera->rotx * camera->rotx) + + (position[2] * position[2]) - (camera->rotx * camera->rotx) + ); +} + +void Particle::RenderMe(){ + renderParticle(); +} + void Particle::renderParticle() { glPushMatrix();
14 Particle.h
 @@ -19,26 +19,27 @@ #include "define.h" #include -#include +#include "Render.h" +#include "Camera.h" class Particle { private: - float* acceletation; // x, y, z float mass; - int lifeSpan; + Camera* camera; public: + int lifeSpanLeft; float* position; // x, y, z float* velocity; // x, y, z - Particle(float*); // Initial velocity - ~Particle(void); + + void init(float*, float*, float, Camera*); // position, velocity, mass void tick(); // Simulate one frame bool isDead(); // Particle has expired @@ -50,6 +51,9 @@ class Particle void setPosition (float*); // Set the position + void RenderMe(); + void SetDist(float*); + float Dist(); };
149 ParticleEmitter.cpp
 @@ -19,24 +19,33 @@ #include #include #include +#include +#include +#include +#define PI 3.14159265359f #define MAX_PARTICLES 10000 -ParticleEmitter::ParticleEmitter(void) { +using namespace std; +ParticleEmitter::ParticleEmitter(Camera* c) { + + c = camera; orientation = new float[4]; position = new float[3]; vector = new float[3]; particles = (Particle**) malloc (sizeof(Particle*) * MAX_PARTICLES); + index = 0; created = 0; gravityOn = false; numGravity = 3; + float** v = (float**) malloc (sizeof (float) * numGravity); float** p = (float**) malloc (sizeof (float) * numGravity); @@ -45,9 +54,12 @@ ParticleEmitter::ParticleEmitter(void) { p[i] = new float[3]; } - p[0][0] = 10; - p[1][0] = -10; - p[2][2] = 10; + for(int i = 0 ; i < numGravity ; i ++){ + p[i][0] = 15.0f * sin((PI * 2 / numGravity) * i ); + p[i][2] = 15.0f * cos((PI * 2 / numGravity) * i ); + p[i][1] = 0; + } + for(int i = 0 ; i < numGravity ; i ++){ @@ -56,29 +68,22 @@ ParticleEmitter::ParticleEmitter(void) { up[1] = 1; // Take cross product of position and z, multiply by some number - v[i][0] = (up[1] * p[i][2] - up[2] * p[i][1]) * 0.001f; - v[i][1] = (up[2] * p[i][0] - up[0] * p[i][2]) * 0.001f; - v[i][2] = (up[0] * p[i][1] - up[1] * p[i][0]) * 0.001f; - + v[i][0] = (up[1] * p[i][2] - up[2] * p[i][1]) * 0.002f; + v[i][1] = (up[2] * p[i][0] - up[0] * p[i][2]) * 0.002f; + v[i][2] = (up[0] * p[i][1] - up[1] * p[i][0]) * 0.002f; } - - - - /* * Test Gravity Wells */ - numGravity = 3; gravity = (Particle**) malloc (sizeof(Particle*) * numGravity); for(int i = 0 ; i < numGravity ; i ++){ - gravity[i] = new Particle(v[i]); - gravity[i]->setPosition(p[i]); + gravity[i] = (Particle*) malloc (sizeof(Particle)); + gravity[i]->init(p[i],v[i], 100, camera); } - - gravityOn = true; + gravityOn = false; } @@ -99,28 +104,32 @@ bool ParticleEmitter::isGravityOn(){ return gravityOn; } -void ParticleEmitter::emit(){ +void ParticleEmitter::cloud(int num, float radius){ - float XHI = 0.1f; - float XLO = -0.1f; + for(int i = 0 ; i < num ; i ++){ + float* p = new float[3]; + float* v = new float[3]; - float YHI = 0.1f; - float YLO = -0.1f; + for(int j = 0 ; j < 3 ; j ++) + p[j] = 0 + sin((float)rand()/((float)RAND_MAX/(PI*2-0))) * (float)rand()/((float)RAND_MAX/(radius-0)); - float ZHI = 0.3f; - float ZLO = 0.2f; + create(p,v,1.0f); + + } + + +} + +void ParticleEmitter::create(float* p, float * v, float m){ - float* v = new float[3]; - v[0] = XLO + (float)rand()/((float)RAND_MAX/(XHI-XLO)); - v[1] = YLO + (float)rand()/((float)RAND_MAX/(YHI-YLO)); - v[2] = ZLO + (float)rand()/((float)RAND_MAX/(ZHI-ZLO)); int start = index; // Make a new particle and increment the index if(created < MAX_PARTICLES){ - particles[index++] = new Particle(v); + particles[index] = (Particle*) malloc (sizeof(Particle)); + particles[index++]->init(p,v, 1, camera); created++; } @@ -131,7 +140,8 @@ void ParticleEmitter::emit(){ // Replace the dead one if( particles[i]->isDead()){ - particles[i] = new Particle(v); + particles[index] = (Particle*) malloc (sizeof(Particle)); + particles[index++]->init(p, v, 1, camera); index = i; goto found; // I always wanted to use one of these :) } @@ -140,7 +150,8 @@ void ParticleEmitter::emit(){ // Loop from start to the expired index, if we haven't found anything yet for(int i = 0 ; i < start ; i ++) if(particles[i]->isDead()){ - particles[i] = new Particle(v); + particles[index] = (Particle*) malloc (sizeof(Particle)); + particles[index++]->init(p, v, 1, camera); index = i; goto found; // I always wanted to use one of these :) } @@ -150,6 +161,32 @@ void ParticleEmitter::emit(){ } +void ParticleEmitter::emit(){ + + + float XHI = 0.1f; + float XLO = -0.1f; + + float YHI = 0.1f; + float YLO = -0.1f; + + float ZHI = 0.3f; + float ZLO = 0.2f; + + float* v = new float[3]; + v[0] = XLO + (float)rand()/((float)RAND_MAX/(XHI-XLO)); + v[1] = YLO + (float)rand()/((float)RAND_MAX/(YHI-YLO)); + v[2] = ZLO + (float)rand()/((float)RAND_MAX/(ZHI-ZLO)); + + float* p = new float[3]; + p[0] = position[0]; + p[1] = position[1]; + p[2] = position[2]; + + create(p,v,1.0f); + +} + void ParticleEmitter::tick(){ // Loop through all active particles drawing them @@ -158,21 +195,24 @@ void ParticleEmitter::tick(){ // Alive! if(!particles[i]->isDead()){ - particles[i]->applyFriction(0.001f); + particles[i]->applyFriction(0.01f); if(gravityOn) for(int j = 0 ; j < numGravity ; j ++) - particles[i]->applyAttractiveForce(particles[i], gravity[j], 0.2f, 100); + particles[i]->applyAttractiveForce(particles[i], gravity[j], 0.01f, 1000); particles[i]->tick(); // Simulate } - for(int i = 0 ; i < numGravity ; i ++){ - for(int j = 0 ; j < numGravity ; j ++){ - if(i != j) - gravity[i]->applyAttractiveForce(gravity[i], gravity[j], 0.002f, 1000); + if(gravityOn){ + for(int i = 0 ; i < numGravity ; i ++){ + for(int j = 0 ; j < numGravity ; j ++){ + if(i != j ){ + gravity[i]->applyAttractiveForce(gravity[i], gravity[j], 0.001f, 1000); + } + } } } @@ -247,13 +287,29 @@ void ParticleEmitter::turnGravityOff(){ gravityOn = false; } - +class ParticleComp { +public: + bool operator()(Particle& t1, Particle& t2) + { + return t1.position[1] > t2.position[1]; // true;//t1.Dist() < t2.Dist(); + } +}; void ParticleEmitter::renderParticles() { glPushMatrix(); + // Order by distance from camera. + priority_queue, ParticleComp> pq; + + for(int i = 0; i < MAX_PARTICLES && i < created ; i ++){ + if(!particles[i]->isDead()){ + pq.push(*particles[i]); + } + } + // Rotate to face vector, might take this out + glRotatef( orientation[0], orientation[1], @@ -266,7 +322,6 @@ void ParticleEmitter::renderParticles() { glPopMatrix(); glPushMatrix(); - /* * All particles have the same texture, so we do this here. */ @@ -283,18 +338,26 @@ void ParticleEmitter::renderParticles() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + int size = pq.size(); + for(int i = 0 ; i < size ; i ++){ + Particle p = pq.top(); + p.renderParticle(); + pq.pop(); + } + + /* // Loop through all active particles drawing them for(int i = 0; i < MAX_PARTICLES && i < created ; i ++) // Alive! if(!particles[i]->isDead()) particles[i]->renderParticle(); // Render - + */ glDisable(GL_BLEND); glDisable(GL_POINT_SPRITE_ARB); glDisable(GL_TEXTURE_2D); - + glDepthMask(1); for(int i = 0; i < numGravity ; i ++) gravity[i]->renderParticle(); @@ -303,6 +366,7 @@ void ParticleEmitter::renderParticles() { } void ParticleEmitter::collideWithBalls(Ball* ball, Collision* c){ + /* int count = 0; for(int i = 0; i < MAX_PARTICLES && i < created ; i ++){ if(c->checkIfCollidedBallParticle(ball, particles[i])){ @@ -312,9 +376,10 @@ void ParticleEmitter::collideWithBalls(Ball* ball, Collision* c){ } else{ count++; - //c->collisionBall(1, 100, 0.001, 1, 0.1, ball->position, particles[i]->position, ball->velocity, particles[i]->velocity); + c->collisionBall(1, 100, 0.001, 1, 0.1, ball->position, particles[i]->position, ball->velocity, particles[i]->velocity); } } } if(count > 0) printf("Count: %d\n", count); +*/ }
9 ParticleEmitter.h
 @@ -22,6 +22,7 @@ #include "Particle.h" #include "Ball.h" #include "Collision.h" +#include class ParticleEmitter { @@ -42,6 +43,11 @@ class ParticleEmitter Particle** gravity; bool gravityOn; + void create(float*, float*, float); + + Camera* camera; + + public: float* getPosition(); // Get the world coordinates @@ -57,6 +63,7 @@ class ParticleEmitter void tick(); // Run a single frame of simulation void emit(); // Emit a particle + void cloud(int , float); // Make a cloud void applyWind(float*); // Apply a force to all the particles @@ -65,7 +72,7 @@ class ParticleEmitter void turnGravityOff(); bool isGravityOn(); - ParticleEmitter(void); // Defaults + ParticleEmitter(Camera*); // Defaults ParticleEmitter(char*); // Load from *.pec file ~ParticleEmitter(void);
38 Render.h
 @@ -0,0 +1,38 @@ +//--------------------------------------------------------------------------- +// +// Copyright (c) 2012 Matthew Betts +// +// Written by Matthew Betts +// +// This software is provided 'as-is' for the BetaFX C308 project +// in ECS, Victoria University of Wellington, +// without any express or implied warranty. +// In no event will the authors be held liable for any +// damages arising from the use of this software. +// +// The contents of this file may not be copied or duplicated in any form +// without the prior permission of its owner. +// +//---------------------------------------------------------------------------- + + +/* + * Since we have to turn of the depth buffer to render the alpha in particles, we need to order everything before we draw it. + */ +#pragma once + +#include "define.h" +#include +#include + +class Render +{ + + public: + Render() {} + ~Render() {} + virtual void RenderMe() = 0; + virtual float Dist(float*) = 0; +}; + +
12 main.cpp
 @@ -87,7 +87,7 @@ int main(int argc, char** argv) { glutDisplayFunc(G308_display); glutReshapeFunc(G308_Reshape); - particeEmitter = new ParticleEmitter(); + particeEmitter = new ParticleEmitter(camera); float* v = new float[3]; v[0] = 0; v[1] = 1; @@ -149,7 +149,7 @@ void tick (){ * Simulate a frame in the particle emitter */ particeEmitter->tick(); - particeEmitter->emit(); + //particeEmitter->emit(); for(int i = 0; i < maxBalls; i ++){ balls[i]->tick(); } @@ -333,6 +333,12 @@ void G308_keyboardListener(unsigned char key, int x, int y) { float* wind = new float [3]; wind[0] = 0; wind[1] = 0; wind[2] = 0; + if(key == 'c') + { + particeEmitter->cloud(1000,10); + } + + /* if(key == 'i') { wind[1] = 0.1f; @@ -360,7 +366,7 @@ void G308_keyboardListener(unsigned char key, int x, int y) { particeEmitter->applyWind(wind); } - + */ if(key == 'g'){ if(particeEmitter->isGravityOn()) particeEmitter->turnGravityOff();