Merge pull request #645 from Ventrella/particles

version 1 of particle system
This commit is contained in:
ZappoMan 2013-07-12 13:14:37 -07:00
commit 934fa2e158
4 changed files with 255 additions and 0 deletions

10
interface/src/Application.cpp Executable file → Normal file
View file

@ -73,6 +73,8 @@ 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 int BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH = 6; // farther dragged clicks are ignored
const glm::vec3 START_LOCATION(4.f, 0.f, 5.f); // Where one's own node begins in the world
@ -2006,6 +2008,10 @@ void Application::update(float deltaTime) {
_audio.setLastVelocity(_myAvatar.getVelocity());
_audio.eventuallyAnalyzePing();
#endif
if (TESTING_PARTICLE_SYSTEM) {
_particleSystem.simulate(deltaTime);
}
}
void Application::updateAvatar(float deltaTime) {
@ -2449,6 +2455,10 @@ void Application::displaySide(Camera& whichCamera) {
_myAvatar.render(_lookingInMirror->isChecked(), _renderAvatarBalls->isChecked());
_myAvatar.setDisplayingLookatVectors(_renderLookatOn->isChecked());
}
if (TESTING_PARTICLE_SYSTEM) {
_particleSystem.render();
}
// Render the world box
if (!_lookingInMirror->isChecked() && _renderStatsOn->isChecked()) { render_world_box(); }

View file

@ -41,6 +41,7 @@
#include "ui/ChatEntry.h"
#include "ToolsPalette.h"
#include "Swatch.h"
#include "ParticleSystem.h"
class QAction;
class QActionGroup;
@ -366,6 +367,8 @@ private:
GeometryCache _geometryCache;
ParticleSystem _particleSystem;
#ifndef _WIN32
Audio _audio;
#endif

View file

@ -0,0 +1,183 @@
//
// ParticleSystem.cpp
// hifi
//
// Created by Jeffrey on July 10, 2013
//
#include <glm/glm.hpp>
#include "InterfaceConfig.h"
#include <SharedUtil.h>
#include "ParticleSystem.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;
_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);
float radian = ((float)p / (float)_numberOfParticles) * 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;
}
}
void ParticleSystem::simulate(float deltaTime) {
runSpecialEffectsTest(deltaTime);
for (unsigned int p = 0; p < _numberOfParticles; p++) {
updateParticle(p, deltaTime);
}
}
void ParticleSystem::runSpecialEffectsTest(float deltaTime) {
_timer += deltaTime;
_gravity = 0.01f + 0.01f * sinf( _timer * 0.52f );
_airFriction = 3.0f + 2.0f * sinf( _timer * 0.32f );
_jitter = 0.05f + 0.05f * sinf( _timer * 0.42f );
_homeAttraction = 0.01f + 0.01f * cosf( _timer * 0.6f );
_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 )
);
}
void ParticleSystem::updateParticle(int p, float deltaTime) {
_particle[p].age += deltaTime;
// apply random jitter
_particle[p].velocity +=
glm::vec3
(
-_jitter * ONE_HALF + _jitter * randFloat(),
-_jitter * ONE_HALF + _jitter * randFloat(),
-_jitter * ONE_HALF + _jitter * randFloat()
) * deltaTime;
// apply attraction to home position
glm::vec3 vectorToHome = _home - _particle[p].position;
_particle[p].velocity += vectorToHome * _homeAttraction * deltaTime;
// apply neighbor attraction
int neighbor = p + 1;
if (neighbor == _numberOfParticles ) {
neighbor = 0;
}
glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position;
_particle[p].velocity -= vectorToNeighbor * _neighborAttraction * deltaTime;
float distanceToNeighbor = glm::length(vectorToNeighbor);
if (distanceToNeighbor > 0.0f) {
_particle[neighbor].velocity += (vectorToNeighbor / ( 1.0f + distanceToNeighbor * distanceToNeighbor)) * _neighborRepulsion * deltaTime;
}
// apply tornado force
glm::vec3 tornadoDirection = glm::cross(vectorToHome, _tornadoAxis);
_particle[p].velocity += tornadoDirection * _tornadoForce * deltaTime;
// apply air friction
float drag = 1.0 - _airFriction * deltaTime;
if (drag < 0.0f) {
_particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
} else {
_particle[p].velocity *= drag;
}
// apply gravity
_particle[p].velocity.y -= _gravity * deltaTime;
// update position by velocity
_particle[p].position += _particle[p].velocity;
// collision with ground
if (_particle[p].position.y < _particle[p].radius) {
_particle[p].position.y = _particle[p].radius;
if (_particle[p].velocity.y < 0.0f) {
_particle[p].velocity.y *= -_bounce;
}
}
// collision with sphere
glm::vec3 vectorToSphereCenter = _TEST_bigSpherePosition - _particle[p].position;
float distanceToSphereCenter = glm::length(vectorToSphereCenter);
float combinedRadius = _TEST_bigSphereRadius + _particle[p].radius;
if (distanceToSphereCenter < combinedRadius) {
if (distanceToSphereCenter > 0.0f){
glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter;
_particle[p].position = _TEST_bigSpherePosition - directionToSphereCenter * combinedRadius;
}
}
}
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();
}
}

View file

@ -0,0 +1,59 @@
//
// ParticleSystem.h
// hifi
//
// Created by Jeffrey on July 10, 2013
//
//
#ifndef hifi_ParticleSystem_h
#define hifi_ParticleSystem_h
const int MAX_PARTICLES = 5000;
const int MAX_EMITTERS = 10;
class ParticleSystem {
public:
ParticleSystem();
void simulate(float deltaTime);
void render();
private:
struct Particle {
glm::vec3 position;
glm::vec3 velocity;
glm::vec3 color;
float age;
float radius;
};
struct Emitter {
glm::vec3 position;
glm::vec3 direction;
};
float _bounce;
float _gravity;
float _timer;
Emitter _emitter[MAX_EMITTERS];
Particle _particle[MAX_PARTICLES];
int _numberOfParticles;
glm::vec3 _home;
glm::vec3 _tornadoAxis;
float _airFriction;
float _jitter;
float _homeAttraction;
float _tornadoForce;
float _neighborAttraction;
float _neighborRepulsion;
float _TEST_bigSphereRadius;
glm::vec3 _TEST_bigSpherePosition;
// private methods
void updateParticle(int index, float deltaTime);
void runSpecialEffectsTest(float deltaTime);
};
#endif