mirror of
https://github.com/overte-org/overte.git
synced 2025-07-18 22:47:12 +02:00
added more API for the particle system
This commit is contained in:
parent
d93edf0aca
commit
ae99ca5ec8
3 changed files with 116 additions and 66 deletions
|
@ -2011,23 +2011,37 @@ void Application::update(float deltaTime) {
|
||||||
_audio.eventuallyAnalyzePing();
|
_audio.eventuallyAnalyzePing();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (TESTING_PARTICLE_SYSTEM) {
|
if (TESTING_PARTICLE_SYSTEM) {
|
||||||
if (_particleSystemInitialized) {
|
if (_particleSystemInitialized) {
|
||||||
_particleSystem.simulate(deltaTime);
|
|
||||||
} else {
|
|
||||||
int coolDemoEmitter = _particleSystem.addEmitter();
|
|
||||||
|
|
||||||
|
// update the particle system
|
||||||
|
_particleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
_particleSystem.simulate(deltaTime);
|
||||||
|
_particleSystem.runSpecialEffectsTest(deltaTime);
|
||||||
|
} else {
|
||||||
|
// create a stable test emitter and spit out a bunch of particles
|
||||||
|
int coolDemoEmitter = _particleSystem.addEmitter();
|
||||||
if (coolDemoEmitter != -1) {
|
if (coolDemoEmitter != -1) {
|
||||||
glm::vec3 particleEmitterPosition = glm::vec3(5.0f, 1.3f, 5.0f);
|
glm::vec3 particleEmitterPosition = glm::vec3(5.0f, 1.0f, 5.0f);
|
||||||
_particleSystem.setEmitterPosition(coolDemoEmitter, particleEmitterPosition);
|
_particleSystem.setEmitterPosition(coolDemoEmitter, particleEmitterPosition);
|
||||||
_particleSystem.emitParticlesNow(coolDemoEmitter, 1500);
|
float radius = 0.01f;
|
||||||
|
glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
glm::vec3 velocity(0.0f, 0.1f, 0.0f);
|
||||||
|
float lifespan = 100000.0f;
|
||||||
|
_particleSystem.emitParticlesNow(coolDemoEmitter, 1500, radius, color, velocity, lifespan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// determine a collision sphere
|
||||||
glm::vec3 collisionSpherePosition = glm::vec3( 5.0f, 0.5f, 5.0f );
|
glm::vec3 collisionSpherePosition = glm::vec3( 5.0f, 0.5f, 5.0f );
|
||||||
float collisionSphereRadius = 0.5f;
|
float collisionSphereRadius = 0.5f;
|
||||||
_particleSystem.setCollisionSphere(collisionSpherePosition, collisionSphereRadius);
|
_particleSystem.setCollisionSphere(collisionSpherePosition, collisionSphereRadius);
|
||||||
|
|
||||||
|
// signal that the particle system has been initialized
|
||||||
_particleSystemInitialized = true;
|
_particleSystemInitialized = true;
|
||||||
_particleSystem.useOrangeBlueColorPalette();
|
|
||||||
|
// apply a preset color palette
|
||||||
|
_particleSystem.setOrangeBlueColorPalette();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,22 +11,28 @@
|
||||||
#include "ParticleSystem.h"
|
#include "ParticleSystem.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
|
const float DEFAULT_PARTICLE_BOUNCE = 1.0f;
|
||||||
|
const float DEFAULT_PARTICLE_AIR_FRICTION = 2.0f;
|
||||||
|
const float DEFAULT_PARTICLE_JITTER = 0.05f;
|
||||||
|
const float DEFAULT_PARTICLE_GRAVITY = 0.05f;
|
||||||
|
|
||||||
ParticleSystem::ParticleSystem() {
|
ParticleSystem::ParticleSystem() {
|
||||||
|
|
||||||
_gravity = 0.005;
|
|
||||||
_numEmitters = 0;
|
|
||||||
_bounce = 0.9f;
|
|
||||||
_timer = 0.0f;
|
_timer = 0.0f;
|
||||||
_airFriction = 6.0f;
|
_numEmitters = 0;
|
||||||
_jitter = 0.1f;
|
_gravity = DEFAULT_PARTICLE_GRAVITY;
|
||||||
_homeAttraction = 0.0f;
|
_bounce = DEFAULT_PARTICLE_BOUNCE;
|
||||||
|
_airFriction = DEFAULT_PARTICLE_AIR_FRICTION;
|
||||||
|
_jitter = DEFAULT_PARTICLE_JITTER;
|
||||||
|
_emitterAttraction = 0.0f;
|
||||||
_tornadoForce = 0.0f;
|
_tornadoForce = 0.0f;
|
||||||
_neighborAttraction = 0.02f;
|
_neighborAttraction = 0.0f;
|
||||||
_neighborRepulsion = 0.9f;
|
_neighborRepulsion = 0.0f;
|
||||||
_collisionSphereRadius = 0.0f;
|
_collisionSphereRadius = 0.0f;
|
||||||
_collisionSpherePosition = glm::vec3(0.0f, 0.0f, 0.0f);
|
_collisionSpherePosition = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
_numParticles = 0;
|
_numParticles = 0;
|
||||||
_usingCollisionSphere = false;
|
_usingCollisionSphere = false;
|
||||||
|
_upDirection = glm::vec3(0.0f, 1.0f, 0.0f); // default
|
||||||
|
|
||||||
for (unsigned int e = 0; e < MAX_EMITTERS; e++) {
|
for (unsigned int e = 0; e < MAX_EMITTERS; e++) {
|
||||||
_emitter[e].position = glm::vec3(0.0f, 0.0f, 0.0f);
|
_emitter[e].position = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
|
@ -39,7 +45,8 @@ ParticleSystem::ParticleSystem() {
|
||||||
for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
|
for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
|
||||||
_particle[p].alive = false;
|
_particle[p].alive = false;
|
||||||
_particle[p].age = 0.0f;
|
_particle[p].age = 0.0f;
|
||||||
_particle[p].radius = 0.01f;
|
_particle[p].lifespan = 0.0f;
|
||||||
|
_particle[p].radius = 0.0f;
|
||||||
_particle[p].emitterIndex = 0;
|
_particle[p].emitterIndex = 0;
|
||||||
_particle[p].position = glm::vec3(0.0f, 0.0f, 0.0f);
|
_particle[p].position = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
_particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
_particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
|
@ -71,9 +78,6 @@ void ParticleSystem::simulate(float deltaTime) {
|
||||||
updateParticle(p, deltaTime);
|
updateParticle(p, deltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply special effects
|
|
||||||
runSpecialEffectsTest(deltaTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleSystem::updateEmitter(int e, float deltaTime) {
|
void ParticleSystem::updateEmitter(int e, float deltaTime) {
|
||||||
|
@ -84,39 +88,63 @@ void ParticleSystem::updateEmitter(int e, float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ParticleSystem::emitParticlesNow(int e, int num, float radius, glm::vec4 color, glm::vec3 velocity, float lifespan) {
|
||||||
void ParticleSystem::emitParticlesNow(int e, int num) {
|
|
||||||
|
|
||||||
_numParticles = num;
|
|
||||||
|
|
||||||
if (_numParticles > MAX_PARTICLES) {
|
|
||||||
_numParticles = MAX_PARTICLES;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int p = 0; p < num; p++) {
|
for (unsigned int p = 0; p < num; p++) {
|
||||||
_particle[p].alive = true;
|
createParticle(_emitter[e].position, velocity, radius, color, lifespan);
|
||||||
_particle[p].position = _emitter[e].position;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleSystem::useOrangeBlueColorPalette() {
|
void ParticleSystem::createParticle(glm::vec3 position, glm::vec3 velocity, float radius, glm::vec4 color, float lifespan) {
|
||||||
|
|
||||||
|
for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
|
||||||
|
if (!_particle[p].alive) {
|
||||||
|
|
||||||
|
_particle[p].lifespan = lifespan;
|
||||||
|
_particle[p].alive = true;
|
||||||
|
_particle[p].age = 0.0f;
|
||||||
|
_particle[p].position = position;
|
||||||
|
_particle[p].velocity = velocity;
|
||||||
|
_particle[p].radius = radius;
|
||||||
|
_particle[p].color = color;
|
||||||
|
|
||||||
|
_numParticles ++;
|
||||||
|
|
||||||
|
assert(_numParticles <= MAX_PARTICLES);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleSystem::killParticle(int p) {
|
||||||
|
|
||||||
|
assert( p >= 0);
|
||||||
|
assert( p < MAX_PARTICLES);
|
||||||
|
assert( _numParticles > 0);
|
||||||
|
|
||||||
|
_particle[p].alive = false;
|
||||||
|
_numParticles --;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ParticleSystem::setOrangeBlueColorPalette() {
|
||||||
|
|
||||||
for (unsigned int p = 0; p < _numParticles; p++) {
|
for (unsigned int p = 0; p < _numParticles; p++) {
|
||||||
|
|
||||||
float radian = ((float)p / (float)_numParticles) * PI_TIMES_TWO;
|
float radian = ((float)p / (float)_numParticles) * PI_TIMES_TWO;
|
||||||
float wave = sinf(radian);
|
float wave = sinf(radian);
|
||||||
|
|
||||||
float red = 0.5f + 0.5f * wave;
|
float red = 0.5f + 0.5f * wave;
|
||||||
float green = 0.3f + 0.3f * wave;
|
float green = 0.3f + 0.3f * wave;
|
||||||
float blue = 0.2f - 0.2f * wave;
|
float blue = 0.2f - 0.2f * wave;
|
||||||
_particle[p].color = glm::vec3(red, green, blue);
|
float alpha = 1.0f;
|
||||||
|
|
||||||
|
_particle[p].color = glm::vec4(red, green, blue, alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ParticleSystem::runSpecialEffectsTest(float deltaTime) {
|
void ParticleSystem::runSpecialEffectsTest(float deltaTime) {
|
||||||
|
|
||||||
_timer += deltaTime;
|
_timer += deltaTime;
|
||||||
|
@ -130,13 +158,13 @@ void ParticleSystem::runSpecialEffectsTest(float deltaTime) {
|
||||||
|
|
||||||
_emitter[0].rotation = glm::quat(glm::radians(tilt));
|
_emitter[0].rotation = glm::quat(glm::radians(tilt));
|
||||||
|
|
||||||
_gravity = 0.0f + 0.02f * sinf( _timer * 0.52f );
|
_gravity = 0.0f + DEFAULT_PARTICLE_GRAVITY * sinf( _timer * 0.52f );
|
||||||
_airFriction = 3.0f + 1.0f * sinf( _timer * 0.32f );
|
_airFriction = (DEFAULT_PARTICLE_AIR_FRICTION + 0.5f) + 2.0f * sinf( _timer * 0.32f );
|
||||||
_jitter = 0.05f + 0.05f * sinf( _timer * 0.42f );
|
_jitter = DEFAULT_PARTICLE_JITTER + DEFAULT_PARTICLE_JITTER * sinf( _timer * 0.42f );
|
||||||
_homeAttraction = 0.01f + 0.01f * cosf( _timer * 0.6f );
|
_emitterAttraction = 0.015f + 0.015f * cosf( _timer * 0.6f );
|
||||||
_tornadoForce = 0.0f + 0.03f * sinf( _timer * 0.7f );
|
_tornadoForce = 0.0f + 0.03f * sinf( _timer * 0.7f );
|
||||||
_neighborAttraction = 0.1f + 0.1f * cosf( _timer * 0.8f );
|
_neighborAttraction = 0.1f + 0.1f * cosf( _timer * 0.8f );
|
||||||
_neighborRepulsion = 0.4f + 0.3f * sinf( _timer * 0.4f );
|
_neighborRepulsion = 0.2f + 0.2f * sinf( _timer * 0.4f );
|
||||||
|
|
||||||
if (_gravity < 0.0f) {
|
if (_gravity < 0.0f) {
|
||||||
_gravity = 0.0f;
|
_gravity = 0.0f;
|
||||||
|
@ -144,11 +172,14 @@ void ParticleSystem::runSpecialEffectsTest(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ParticleSystem::updateParticle(int p, float deltaTime) {
|
void ParticleSystem::updateParticle(int p, float deltaTime) {
|
||||||
|
|
||||||
_particle[p].age += deltaTime;
|
_particle[p].age += deltaTime;
|
||||||
|
|
||||||
|
if (_particle[p].age > _particle[p].lifespan) {
|
||||||
|
killParticle(p);
|
||||||
|
}
|
||||||
|
|
||||||
// apply random jitter
|
// apply random jitter
|
||||||
_particle[p].velocity +=
|
_particle[p].velocity +=
|
||||||
glm::vec3
|
glm::vec3
|
||||||
|
@ -160,7 +191,7 @@ void ParticleSystem::updateParticle(int p, float deltaTime) {
|
||||||
|
|
||||||
// apply attraction to home position
|
// apply attraction to home position
|
||||||
glm::vec3 vectorToHome = _emitter[_particle[p].emitterIndex].position - _particle[p].position;
|
glm::vec3 vectorToHome = _emitter[_particle[p].emitterIndex].position - _particle[p].position;
|
||||||
_particle[p].velocity += vectorToHome * _homeAttraction * deltaTime;
|
_particle[p].velocity += vectorToHome * _emitterAttraction * deltaTime;
|
||||||
|
|
||||||
// apply neighbor attraction
|
// apply neighbor attraction
|
||||||
int neighbor = p + 1;
|
int neighbor = p + 1;
|
||||||
|
@ -189,7 +220,7 @@ void ParticleSystem::updateParticle(int p, float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply gravity
|
// apply gravity
|
||||||
_particle[p].velocity.y -= _gravity * deltaTime;
|
_particle[p].velocity -= _upDirection * _gravity * deltaTime;
|
||||||
|
|
||||||
// update position by velocity
|
// update position by velocity
|
||||||
_particle[p].position += _particle[p].velocity;
|
_particle[p].position += _particle[p].velocity;
|
||||||
|
@ -239,11 +270,9 @@ void ParticleSystem::render() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ParticleSystem::renderParticle(int p) {
|
void ParticleSystem::renderParticle(int p) {
|
||||||
|
|
||||||
glColor3f(_particle[p].color.x, _particle[p].color.y, _particle[p].color.z);
|
glColor4f(_particle[p].color.r, _particle[p].color.g, _particle[p].color.b, _particle[p].color.a );
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
|
glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
|
||||||
glutSolidSphere(_particle[p].radius, 6, 6);
|
glutSolidSphere(_particle[p].radius, 6, 6);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
const int MAX_PARTICLES = 5000;
|
const int MAX_PARTICLES = 10000;
|
||||||
const int MAX_EMITTERS = 10;
|
const int MAX_EMITTERS = 10;
|
||||||
|
|
||||||
class ParticleSystem {
|
class ParticleSystem {
|
||||||
|
@ -19,25 +19,19 @@ public:
|
||||||
ParticleSystem();
|
ParticleSystem();
|
||||||
|
|
||||||
int addEmitter(); // add (create) an emitter and get its unique id
|
int addEmitter(); // add (create) an emitter and get its unique id
|
||||||
void useOrangeBlueColorPalette(); // apply a nice preset color palette to the particles
|
void emitParticlesNow(int e, int numParticles, float radius, glm::vec4 color, glm::vec3 velocity, float lifespan);
|
||||||
|
void simulate(float deltaTime);
|
||||||
|
void render();
|
||||||
|
void runSpecialEffectsTest(float deltaTime); // for debugging and artistic exploration
|
||||||
|
|
||||||
|
void setOrangeBlueColorPalette(); // apply a nice preset color palette to the particles
|
||||||
void setCollisionSphere(glm::vec3 position, float radius); // specify a sphere for the particles to collide with
|
void setCollisionSphere(glm::vec3 position, float radius); // specify a sphere for the particles to collide with
|
||||||
void emitParticlesNow(int e, int numParticles); // tell this emitter to generate this many particles right now
|
|
||||||
void simulate(float deltaTime); // run it
|
|
||||||
void render(); // show it
|
|
||||||
void setEmitterPosition(int e, glm::vec3 position) { _emitter[e].position = position; } // set the position of this emitter
|
void setEmitterPosition(int e, glm::vec3 position) { _emitter[e].position = position; } // set the position of this emitter
|
||||||
|
void setEmitterRotation(int e, glm::quat rotation) { _emitter[e].rotation = rotation; } // set the rotation of this emitter
|
||||||
|
void setUpDirection(glm::vec3 upDirection) {_upDirection = upDirection;} // tell particle system which direction is up
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct Particle {
|
|
||||||
bool alive;
|
|
||||||
glm::vec3 position;
|
|
||||||
glm::vec3 velocity;
|
|
||||||
glm::vec3 color;
|
|
||||||
float age;
|
|
||||||
float radius;
|
|
||||||
int emitterIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Emitter {
|
struct Emitter {
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
glm::quat rotation;
|
glm::quat rotation;
|
||||||
|
@ -46,6 +40,18 @@ private:
|
||||||
glm::vec3 front;
|
glm::vec3 front;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Particle {
|
||||||
|
bool alive; // is the particle active?
|
||||||
|
glm::vec3 position; // position
|
||||||
|
glm::vec3 velocity; // velocity
|
||||||
|
glm::vec4 color; // color (rgba)
|
||||||
|
float age; // age in seconds
|
||||||
|
float radius; // radius
|
||||||
|
float lifespan; // how long this particle stays alive (in seconds)
|
||||||
|
int emitterIndex; // which emitter created this particle?
|
||||||
|
};
|
||||||
|
|
||||||
|
glm::vec3 _upDirection;
|
||||||
float _bounce;
|
float _bounce;
|
||||||
float _gravity;
|
float _gravity;
|
||||||
float _timer;
|
float _timer;
|
||||||
|
@ -55,7 +61,7 @@ private:
|
||||||
int _numEmitters;
|
int _numEmitters;
|
||||||
float _airFriction;
|
float _airFriction;
|
||||||
float _jitter;
|
float _jitter;
|
||||||
float _homeAttraction;
|
float _emitterAttraction;
|
||||||
float _tornadoForce;
|
float _tornadoForce;
|
||||||
float _neighborAttraction;
|
float _neighborAttraction;
|
||||||
float _neighborRepulsion;
|
float _neighborRepulsion;
|
||||||
|
@ -66,7 +72,8 @@ private:
|
||||||
// private methods
|
// private methods
|
||||||
void updateEmitter(int e, float deltaTime);
|
void updateEmitter(int e, float deltaTime);
|
||||||
void updateParticle(int index, float deltaTime);
|
void updateParticle(int index, float deltaTime);
|
||||||
void runSpecialEffectsTest(float deltaTime);
|
void createParticle(glm::vec3 position, glm::vec3 velocity, float radius, glm::vec4 color, float lifespan);
|
||||||
|
void killParticle(int p);
|
||||||
void renderEmitter(int emitterIndex, float size);
|
void renderEmitter(int emitterIndex, float size);
|
||||||
void renderParticle(int p);
|
void renderParticle(int p);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue