From 84a7a78b8dee1d11319874482a7a22119ec870b5 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 10 Jul 2013 17:15:03 -0700 Subject: [PATCH 1/6] made a test particle system --- interface/src/Application.cpp | 10 ++ interface/src/Application.h | 3 + interface/src/ParticleSystem.cpp | 167 +++++++++++++++++++++++++++++++ interface/src/ParticleSystem.h | 52 ++++++++++ 4 files changed, 232 insertions(+) create mode 100644 interface/src/ParticleSystem.cpp create mode 100644 interface/src/ParticleSystem.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ae9466dabe..80eeaf546b 100755 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -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 = true; + 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 @@ -1964,6 +1966,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) { @@ -2373,6 +2379,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(); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 2bc2d93fc8..ceacd433e1 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -41,6 +41,7 @@ #include "ui/ChatEntry.h" #include "ToolsPalette.h" #include "Swatch.h" +#include "ParticleSystem.h" class QAction; class QActionGroup; @@ -351,6 +352,8 @@ private: GeometryCache _geometryCache; + ParticleSystem _particleSystem; + #ifndef _WIN32 Audio _audio; #endif diff --git a/interface/src/ParticleSystem.cpp b/interface/src/ParticleSystem.cpp new file mode 100644 index 0000000000..5e77f08a23 --- /dev/null +++ b/interface/src/ParticleSystem.cpp @@ -0,0 +1,167 @@ +// +// ParticleSystem.cpp +// hifi +// +// Created by Jeffrey on July 10, 2013 +// + +#include +#include "InterfaceConfig.h" +#include + +#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, 0.5f, 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 red = 0.5f + 0.5f * sinf(((float)p / (float)_numberOfParticles) * 3.141592 * 2.0f); + float green = 0.3f + 0.3f * sinf(((float)p / (float)_numberOfParticles) * 3.141592 * 2.0f); + float blue = 0.2f - 0.2f * sinf(((float)p / (float)_numberOfParticles) * 3.141592 * 2.0f); + + _particle[p].color = glm::vec3(red, green, blue); + _particle[p].age = 0; + _particle[p].radius = 0.01f; + } +} + +void ParticleSystem::simulate(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 ) + ); + + for (unsigned int p = 0; p < _numberOfParticles; p++) { + + // 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; + _particle[p].velocity.y += 0.005f; + } + } + } +} + + + +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(); + + } +} + + + + + + + + diff --git a/interface/src/ParticleSystem.h b/interface/src/ParticleSystem.h new file mode 100644 index 0000000000..4b04a89dcb --- /dev/null +++ b/interface/src/ParticleSystem.h @@ -0,0 +1,52 @@ +// +// ParticleSystem.h +// hifi +// +// Created by Jeffrey on July 10, 2013 +// +// + +#ifndef hifi_ParticleSystem_h +#define hifi_ParticleSystem_h + +const int MAX_PARTICLES = 2000; + +class ParticleSystem { +public: + ParticleSystem(); + + void simulate(float deltaTime); + void render(); + +private: + struct Particle { + glm::vec3 position; + glm::vec3 velocity; + glm::vec3 color; + int age; + float radius; + }; + + struct Emitter { + glm::vec3 position; + + }; + + float _bounce; + float _gravity; + float _timer; + 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; +}; + +#endif From 8ae10a66144962df70f471bdf68201e59e564e50 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 10 Jul 2013 17:55:42 -0700 Subject: [PATCH 2/6] added emitter --- interface/src/ParticleSystem.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/ParticleSystem.h b/interface/src/ParticleSystem.h index 4b04a89dcb..69ede27bc3 100644 --- a/interface/src/ParticleSystem.h +++ b/interface/src/ParticleSystem.h @@ -9,7 +9,8 @@ #ifndef hifi_ParticleSystem_h #define hifi_ParticleSystem_h -const int MAX_PARTICLES = 2000; +const int MAX_PARTICLES = 2000; +const int MAX_EMITTERS = 10; class ParticleSystem { public: @@ -29,12 +30,13 @@ private: 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; From 171c10dabe001a54eec87a2356fa7639f54eaa70 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 10 Jul 2013 18:04:19 -0700 Subject: [PATCH 3/6] raised home position --- interface/src/ParticleSystem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ParticleSystem.cpp b/interface/src/ParticleSystem.cpp index 5e77f08a23..0a0a82cd88 100644 --- a/interface/src/ParticleSystem.cpp +++ b/interface/src/ParticleSystem.cpp @@ -25,7 +25,7 @@ ParticleSystem::ParticleSystem() { _neighborAttraction = 0.02f; _neighborRepulsion = 0.9f; _tornadoAxis = glm::normalize(glm::vec3(0.1f, 1.0f, 0.1f)); - _home = glm::vec3(5.0f, 0.5f, 5.0f); + _home = glm::vec3(5.0f, 1.0f, 5.0f); _TEST_bigSphereRadius = 0.5f; _TEST_bigSpherePosition = glm::vec3( 5.0f, _TEST_bigSphereRadius, 5.0f); @@ -129,7 +129,7 @@ void ParticleSystem::simulate(float deltaTime) { if (distanceToSphereCenter > 0.0f){ glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter; _particle[p].position = _TEST_bigSpherePosition - directionToSphereCenter * combinedRadius; - _particle[p].velocity.y += 0.005f; + //_particle[p].velocity.y += 0.005f; } } } From 980a5b7980c81258a81cd9d85b077434184c312c Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 10 Jul 2013 18:32:17 -0700 Subject: [PATCH 4/6] cleanup --- interface/src/ParticleSystem.cpp | 158 +++++++++++++++++-------------- interface/src/ParticleSystem.h | 9 +- 2 files changed, 94 insertions(+), 73 deletions(-) diff --git a/interface/src/ParticleSystem.cpp b/interface/src/ParticleSystem.cpp index 0a0a82cd88..3c27f3a8df 100644 --- a/interface/src/ParticleSystem.cpp +++ b/interface/src/ParticleSystem.cpp @@ -15,7 +15,7 @@ ParticleSystem::ParticleSystem() { _numberOfParticles = 1500; assert(_numberOfParticles <= MAX_PARTICLES); - + _bounce = 0.9f; _timer = 0.0f; _airFriction = 6.0f; @@ -34,18 +34,32 @@ ParticleSystem::ParticleSystem() { _particle[p].position = _home; _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f); - float red = 0.5f + 0.5f * sinf(((float)p / (float)_numberOfParticles) * 3.141592 * 2.0f); - float green = 0.3f + 0.3f * sinf(((float)p / (float)_numberOfParticles) * 3.141592 * 2.0f); - float blue = 0.2f - 0.2f * sinf(((float)p / (float)_numberOfParticles) * 3.141592 * 2.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; + _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 ); @@ -62,81 +76,83 @@ void ParticleSystem::simulate(float deltaTime) { 1.0f, 0.0f + 0.5f * cosf( _timer * 0.75f ) ); +} - for (unsigned int p = 0; p < _numberOfParticles; p++) { - // apply random jitter - _particle[p].velocity += - glm::vec3 - ( - -_jitter * ONE_HALF + _jitter * randFloat(), - -_jitter * ONE_HALF + _jitter * randFloat(), - -_jitter * ONE_HALF + _jitter * randFloat() - ) * deltaTime; + +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; - - // 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; + if (_particle[p].velocity.y < 0.0f) { + _particle[p].velocity.y *= -_bounce; } - 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; - //_particle[p].velocity.y += 0.005f; - } + } + + // 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++) { diff --git a/interface/src/ParticleSystem.h b/interface/src/ParticleSystem.h index 69ede27bc3..38eb0a1777 100644 --- a/interface/src/ParticleSystem.h +++ b/interface/src/ParticleSystem.h @@ -9,7 +9,7 @@ #ifndef hifi_ParticleSystem_h #define hifi_ParticleSystem_h -const int MAX_PARTICLES = 2000; +const int MAX_PARTICLES = 5000; const int MAX_EMITTERS = 10; class ParticleSystem { @@ -20,11 +20,12 @@ public: void render(); private: + struct Particle { glm::vec3 position; glm::vec3 velocity; glm::vec3 color; - int age; + float age; float radius; }; @@ -49,6 +50,10 @@ private: float _neighborRepulsion; float _TEST_bigSphereRadius; glm::vec3 _TEST_bigSpherePosition; + + // private methods + void updateParticle(int index, float deltaTime); + void runSpecialEffectsTest(float deltaTime); }; #endif From 6c3644a2fc76fc924aa1385ccd673af479b2a57b Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 10 Jul 2013 18:32:59 -0700 Subject: [PATCH 5/6] merge --- interface/src/Application.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 interface/src/Application.cpp diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp old mode 100755 new mode 100644 From 106d7c225ad02ee999d3aa370dabafe79148bc50 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Fri, 12 Jul 2013 12:11:51 -0700 Subject: [PATCH 6/6] turned on particle system viewing for pull request --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8d442a4b34..6429a08f02 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -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 = true; +static const bool TESTING_PARTICLE_SYSTEM = false; static const int BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH = 6; // farther dragged clicks are ignored