more work on particle system

This commit is contained in:
Jeffrey Ventrella 2013-07-12 14:32:14 -07:00
parent c348c5ec35
commit e6b751e538
3 changed files with 138 additions and 61 deletions

View file

@ -73,7 +73,7 @@ using namespace std;
static char STAR_FILE[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt";
static char STAR_CACHE_FILE[] = "cachedStars.txt";
static const bool TESTING_PARTICLE_SYSTEM = false;
static const bool TESTING_PARTICLE_SYSTEM = true;
static const int BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH = 6; // farther dragged clicks are ignored
@ -2010,6 +2010,8 @@ void Application::update(float deltaTime) {
#endif
if (TESTING_PARTICLE_SYSTEM) {
glm::vec3 particleEmitterPosition = glm::vec3(5.0f, 1.0f, 5.0f);
_particleSystem.setEmitterPosition(0, particleEmitterPosition);
_particleSystem.simulate(deltaTime);
}
}

View file

@ -8,59 +8,91 @@
#include <glm/glm.hpp>
#include "InterfaceConfig.h"
#include <SharedUtil.h>
#include "ParticleSystem.h"
#include "Application.h"
ParticleSystem::ParticleSystem() {
_numberOfParticles = 1500;
assert(_numberOfParticles <= MAX_PARTICLES);
_bounce = 0.9f;
_timer = 0.0f;
_airFriction = 6.0f;
_jitter = 0.1f;
_homeAttraction = 0.0f;
_tornadoForce = 0.0f;
_neighborAttraction = 0.02f;
_neighborRepulsion = 0.9f;
_tornadoAxis = glm::normalize(glm::vec3(0.1f, 1.0f, 0.1f));
_home = glm::vec3(5.0f, 1.0f, 5.0f);
_TEST_bigSphereRadius = 0.5f;
_gravity = 0.005;
_numEmitters = 1;
_bounce = 0.9f;
_timer = 0.0f;
_airFriction = 6.0f;
_jitter = 0.1f;
_homeAttraction = 0.0f;
_tornadoForce = 0.0f;
_neighborAttraction = 0.02f;
_neighborRepulsion = 0.9f;
_TEST_bigSphereRadius = 0.5f;
_TEST_bigSpherePosition = glm::vec3( 5.0f, _TEST_bigSphereRadius, 5.0f);
for (unsigned int p = 0; p < _numberOfParticles; p++) {
_particle[p].position = _home;
_particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
_numParticles = 1500;
for (unsigned int e = 0; e < _numEmitters; e++) {
_emitter[e].position = glm::vec3(0.0f, 0.0f, 0.0f);
_emitter[e].rotation = glm::quat();
_emitter[e].right = IDENTITY_RIGHT;
_emitter[e].up = IDENTITY_UP;
_emitter[e].front = IDENTITY_FRONT;
};
for (unsigned int p = 0; p < _numParticles; p++) {
float radian = ((float)p / (float)_numberOfParticles) * PI_TIMES_TWO;
float radian = ((float)p / (float)_numParticles) * PI_TIMES_TWO;
float wave = sinf(radian);
float red = 0.5f + 0.5f * wave;
float green = 0.3f + 0.3f * wave;
float blue = 0.2f - 0.2f * wave;
_particle[p].color = glm::vec3(red, green, blue);
_particle[p].age = 0.0f;
_particle[p].radius = 0.01f;
_particle[p].color = glm::vec3(red, green, blue);
_particle[p].age = 0.0f;
_particle[p].radius = 0.01f;
_particle[p].emitterIndex = 0;
_particle[p].position = glm::vec3(0.0f, 0.0f, 0.0f);
_particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
}
assert(_numParticles <= MAX_PARTICLES);
assert(_numEmitters <= MAX_EMITTERS );
}
void ParticleSystem::simulate(float deltaTime) {
runSpecialEffectsTest(deltaTime);
for (unsigned int p = 0; p < _numberOfParticles; p++) {
// update emitters
for (unsigned int e = 0; e < _numEmitters; e++) {
updateEmitter(e, deltaTime);
}
// update particles
for (unsigned int p = 0; p < _numParticles; p++) {
updateParticle(p, deltaTime);
}
// apply special effects
runSpecialEffectsTest(deltaTime);
}
void ParticleSystem::updateEmitter(int e, float deltaTime) {
_emitter[e].front = _emitter[e].rotation * IDENTITY_FRONT;
_emitter[e].right = _emitter[e].rotation * IDENTITY_RIGHT;
_emitter[e].up = _emitter[e].rotation * IDENTITY_UP;
}
void ParticleSystem::runSpecialEffectsTest(float deltaTime) {
_timer += deltaTime;
glm::vec3 tilt = glm::vec3
(
30.0f * sinf( _timer * 0.55f ),
0.0f,
30.0f * cosf( _timer * 0.75f )
);
_emitter[0].rotation = glm::quat(glm::radians(tilt));
_gravity = 0.01f + 0.01f * sinf( _timer * 0.52f );
_airFriction = 3.0f + 2.0f * sinf( _timer * 0.32f );
@ -69,13 +101,6 @@ void ParticleSystem::runSpecialEffectsTest(float deltaTime) {
_tornadoForce = 0.0f + 0.03f * sinf( _timer * 0.7f );
_neighborAttraction = 0.1f + 0.1f * cosf( _timer * 0.8f );
_neighborRepulsion = 0.4f + 0.3f * sinf( _timer * 0.4f );
_tornadoAxis = glm::vec3
(
0.0f + 0.5f * sinf( _timer * 0.55f ),
1.0f,
0.0f + 0.5f * cosf( _timer * 0.75f )
);
}
@ -95,12 +120,12 @@ void ParticleSystem::updateParticle(int p, float deltaTime) {
// apply attraction to home position
glm::vec3 vectorToHome = _home - _particle[p].position;
glm::vec3 vectorToHome = _emitter[_particle[p].emitterIndex].position - _particle[p].position;
_particle[p].velocity += vectorToHome * _homeAttraction * deltaTime;
// apply neighbor attraction
int neighbor = p + 1;
if (neighbor == _numberOfParticles ) {
if (neighbor == _numParticles ) {
neighbor = 0;
}
glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position;
@ -113,8 +138,9 @@ void ParticleSystem::updateParticle(int p, float deltaTime) {
}
// apply tornado force
glm::vec3 tornadoDirection = glm::cross(vectorToHome, _tornadoAxis);
_particle[p].velocity += tornadoDirection * _tornadoForce * deltaTime;
//glm::vec3 tornadoDirection = glm::cross(vectorToHome, _emitter[_particle[p].emitterIndex].up);
//_particle[p].velocity += tornadoDirection * _tornadoForce * deltaTime;
//_particle[p].velocity += _emitter[_particle[p].emitterIndex].up * _tornadoForce * deltaTime;
// apply air friction
float drag = 1.0 - _airFriction * deltaTime;
@ -155,29 +181,69 @@ void ParticleSystem::updateParticle(int p, float deltaTime) {
void ParticleSystem::render() {
for (unsigned int p = 0; p < _numberOfParticles; p++) {
glColor3f(_particle[p].color.x, _particle[p].color.y, _particle[p].color.z);
glPushMatrix();
glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
glutSolidSphere(_particle[p].radius, 6, 6);
glPopMatrix();
// render velocity lines
glColor4f( _particle[p].color.x, _particle[p].color.y, _particle[p].color.z, 0.5f);
glm::vec3 end = _particle[p].position - _particle[p].velocity * 2.0f;
glBegin(GL_LINES);
glVertex3f(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
glVertex3f(end.x, end.y, end.z);
glEnd();
// render the emitters
for (unsigned int e = 0; e < _numEmitters; e++) {
renderEmitter(e, 0.2f);
};
// render the particles
for (unsigned int p = 0; p < _numParticles; p++) {
renderParticle(p);
}
}
void ParticleSystem::renderParticle(int p) {
glColor3f(_particle[p].color.x, _particle[p].color.y, _particle[p].color.z);
glPushMatrix();
glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
glutSolidSphere(_particle[p].radius, 6, 6);
glPopMatrix();
// render velocity lines
glColor4f( _particle[p].color.x, _particle[p].color.y, _particle[p].color.z, 0.5f);
glm::vec3 end = _particle[p].position - _particle[p].velocity * 2.0f;
glBegin(GL_LINES);
glVertex3f(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
glVertex3f(end.x, end.y, end.z);
glEnd();
}
void ParticleSystem::renderEmitter(int e, float size) {
glm::vec3 r = _emitter[e].right * size;
glm::vec3 u = _emitter[e].up * size;
glm::vec3 f = _emitter[e].front * size;
glLineWidth(2.0f);
glColor3f(0.8f, 0.4, 0.4);
glBegin(GL_LINES);
glVertex3f(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z);
glVertex3f(_emitter[e].position.x + r.x, _emitter[e].position.y + r.y, _emitter[e].position.z + r.z);
glEnd();
glColor3f(0.4f, 0.8, 0.4);
glBegin(GL_LINES);
glVertex3f(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z);
glVertex3f(_emitter[e].position.x + u.x, _emitter[e].position.y + u.y, _emitter[e].position.z + u.z);
glEnd();
glColor3f(0.4f, 0.4, 0.8);
glBegin(GL_LINES);
glVertex3f(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z);
glVertex3f(_emitter[e].position.x + f.x, _emitter[e].position.y + f.y, _emitter[e].position.z + f.z);
glEnd();
}

View file

@ -9,6 +9,8 @@
#ifndef hifi_ParticleSystem_h
#define hifi_ParticleSystem_h
#include <glm/gtc/quaternion.hpp>
const int MAX_PARTICLES = 5000;
const int MAX_EMITTERS = 10;
@ -16,6 +18,7 @@ class ParticleSystem {
public:
ParticleSystem();
void setEmitterPosition(int e, glm::vec3 position) { _emitter[e].position = position; }
void simulate(float deltaTime);
void render();
@ -27,11 +30,15 @@ private:
glm::vec3 color;
float age;
float radius;
int emitterIndex;
};
struct Emitter {
glm::vec3 position;
glm::vec3 direction;
glm::quat rotation;
glm::vec3 right;
glm::vec3 up;
glm::vec3 front;
};
float _bounce;
@ -39,9 +46,8 @@ private:
float _timer;
Emitter _emitter[MAX_EMITTERS];
Particle _particle[MAX_PARTICLES];
int _numberOfParticles;
glm::vec3 _home;
glm::vec3 _tornadoAxis;
int _numParticles;
int _numEmitters;
float _airFriction;
float _jitter;
float _homeAttraction;
@ -52,8 +58,11 @@ private:
glm::vec3 _TEST_bigSpherePosition;
// private methods
void updateEmitter(int e, float deltaTime);
void updateParticle(int index, float deltaTime);
void runSpecialEffectsTest(float deltaTime);
void renderEmitter(int emitterIndex, float size);
void renderParticle(int p);
};
#endif