Skip to content
Browse files

Working on particle effects

  • Loading branch information...
1 parent 9c68892 commit f5c5f43871321bf48e99818492d58bbf66f64652 @bettsmatt 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
View
29 Particle.cpp
@@ -20,18 +20,19 @@
#include <stdlib.h>
#include <math.h>
-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();
View
14 Particle.h
@@ -19,26 +19,27 @@
#include "define.h"
#include <GL/glut.h>
-#include <queue>
+#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();
};
View
149 ParticleEmitter.cpp
@@ -19,24 +19,33 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
+#include <queue>
+#include <string.h>
+#include <vector>
+#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<Particle, std::vector<Particle>, 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);
+*/
}
View
9 ParticleEmitter.h
@@ -22,6 +22,7 @@
#include "Particle.h"
#include "Ball.h"
#include "Collision.h"
+#include <vector>
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);
View
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 <GL/glut.h>
+#include <queue>
+
+class Render
+{
+
+ public:
+ Render() {}
+ ~Render() {}
+ virtual void RenderMe() = 0;
+ virtual float Dist(float*) = 0;
+};
+
+
View
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();

0 comments on commit f5c5f43

Please sign in to comment.
Something went wrong with that request. Please try again.