Showing the changes to interface/src/ParticleSystem.cpp (1 of 4 files). Show all
Unified · Split
| @@ -0,0 +1,167 @@ | ||
| 1 | +// | |
| 2 | +// ParticleSystem.cpp | |
| 3 | +// hifi | |
| 4 | +// | |
| 5 | +// Created by Jeffrey on July 10, 2013 | |
| 6 | +// | |
| 7 | + | |
| 8 | +#include <glm/glm.hpp> | |
| 9 | +#include "InterfaceConfig.h" | |
| 10 | +#include <SharedUtil.h> | |
| 11 | + | |
| 12 | +#include "ParticleSystem.h" | |
| 13 | + | |
| 14 | +ParticleSystem::ParticleSystem() { | |
| 15 | + | |
| 16 | + _numberOfParticles = 1500; | |
| 17 | + assert(_numberOfParticles <= MAX_PARTICLES); | |
| 18 | + | |
| 19 | + _bounce = 0.9f; | |
| 20 | + _timer = 0.0f; | |
| 21 | + _airFriction = 6.0f; | |
| 22 | + _jitter = 0.1f; | |
| 23 | + _homeAttraction = 0.0f; | |
| 24 | + _tornadoForce = 0.0f; | |
| 25 | + _neighborAttraction = 0.02f; | |
| 26 | + _neighborRepulsion = 0.9f; | |
| 27 | + _tornadoAxis = glm::normalize(glm::vec3(0.1f, 1.0f, 0.1f)); | |
| 28 | + _home = glm::vec3(5.0f, 0.5f, 5.0f); | |
| 29 | + | |
| 30 | + _TEST_bigSphereRadius = 0.5f; | |
| 31 | + _TEST_bigSpherePosition = glm::vec3( 5.0f, _TEST_bigSphereRadius, 5.0f); | |
| 32 | + | |
| 33 | + for (unsigned int p = 0; p < _numberOfParticles; p++) { | |
| 34 | + _particle[p].position = _home; | |
| 35 | + _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f); | |
| 36 | + | |
| 37 | + float red = 0.5f + 0.5f * sinf(((float)p / (float)_numberOfParticles) * 3.141592 * 2.0f); | |
| 38 | + float green = 0.3f + 0.3f * sinf(((float)p / (float)_numberOfParticles) * 3.141592 * 2.0f); | |
| 39 | + float blue = 0.2f - 0.2f * sinf(((float)p / (float)_numberOfParticles) * 3.141592 * 2.0f); | |
| 40 | + | |
| 41 | + _particle[p].color = glm::vec3(red, green, blue); | |
| 42 | + _particle[p].age = 0; | |
| 43 | + _particle[p].radius = 0.01f; | |
| 44 | + } | |
| 45 | +} | |
| 46 | + | |
| 47 | +void ParticleSystem::simulate(float deltaTime) { | |
| 48 | + | |
| 49 | + _timer += deltaTime; | |
| 50 | + | |
| 51 | + _gravity = 0.01f + 0.01f * sinf( _timer * 0.52f ); | |
| 52 | + _airFriction = 3.0f + 2.0f * sinf( _timer * 0.32f ); | |
| 53 | + _jitter = 0.05f + 0.05f * sinf( _timer * 0.42f ); | |
| 54 | + _homeAttraction = 0.01f + 0.01f * cosf( _timer * 0.6f ); | |
| 55 | + _tornadoForce = 0.0f + 0.03f * sinf( _timer * 0.7f ); | |
| 56 | + _neighborAttraction = 0.1f + 0.1f * cosf( _timer * 0.8f ); | |
| 57 | + _neighborRepulsion = 0.4f + 0.3f * sinf( _timer * 0.4f ); | |
| 58 | + | |
| 59 | + _tornadoAxis = glm::vec3 | |
| 60 | + ( | |
| 61 | + 0.0f + 0.5f * sinf( _timer * 0.55f ), | |
| 62 | + 1.0f, | |
| 63 | + 0.0f + 0.5f * cosf( _timer * 0.75f ) | |
| 64 | + ); | |
| 65 | + | |
| 66 | + for (unsigned int p = 0; p < _numberOfParticles; p++) { | |
| 67 | + | |
| 68 | + // apply random jitter | |
| 69 | + _particle[p].velocity += | |
| 70 | + glm::vec3 | |
| 71 | + ( | |
| 72 | + -_jitter * ONE_HALF + _jitter * randFloat(), | |
| 73 | + -_jitter * ONE_HALF + _jitter * randFloat(), | |
| 74 | + -_jitter * ONE_HALF + _jitter * randFloat() | |
| 75 | + ) * deltaTime; | |
| 76 | + | |
| 77 | + | |
| 78 | + // apply attraction to home position | |
| 79 | + glm::vec3 vectorToHome = _home - _particle[p].position; | |
| 80 | + _particle[p].velocity += vectorToHome * _homeAttraction * deltaTime; | |
| 81 | + | |
| 82 | + // apply neighbor attraction | |
| 83 | + int neighbor = p + 1; | |
| 84 | + if (neighbor == _numberOfParticles ) { | |
| 85 | + neighbor = 0; | |
| 86 | + } | |
| 87 | + glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position; | |
| 88 | + | |
| 89 | + _particle[p].velocity -= vectorToNeighbor * _neighborAttraction * deltaTime; | |
| 90 | + | |
| 91 | + float distanceToNeighbor = glm::length(vectorToNeighbor); | |
| 92 | + if (distanceToNeighbor > 0.0f) { | |
| 93 | + _particle[neighbor].velocity += (vectorToNeighbor / ( 1.0f + distanceToNeighbor * distanceToNeighbor)) * _neighborRepulsion * deltaTime; | |
| 94 | + } | |
| 95 | + | |
| 96 | + // apply tornado force | |
| 97 | + glm::vec3 tornadoDirection = glm::cross(vectorToHome, _tornadoAxis); | |
| 98 | + _particle[p].velocity += tornadoDirection * _tornadoForce * deltaTime; | |
| 99 | + | |
| 100 | + // apply air friction | |
| 101 | + float drag = 1.0 - _airFriction * deltaTime; | |
| 102 | + if (drag < 0.0f) { | |
| 103 | + _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f); | |
| 104 | + } else { | |
| 105 | + _particle[p].velocity *= drag; | |
| 106 | + } | |
| 107 | + | |
| 108 | + // apply gravity | |
| 109 | + _particle[p].velocity.y -= _gravity * deltaTime; | |
| 110 | + | |
| 111 | + // update position by velocity | |
| 112 | + _particle[p].position += _particle[p].velocity; | |
| 113 | + | |
| 114 | + // collision with ground | |
| 115 | + if (_particle[p].position.y < _particle[p].radius) { | |
| 116 | + _particle[p].position.y = _particle[p].radius; | |
| 117 | + | |
| 118 | + if (_particle[p].velocity.y < 0.0f) { | |
| 119 | + _particle[p].velocity.y *= -_bounce; | |
| 120 | + } | |
| 121 | + } | |
| 122 | + | |
| 123 | + // collision with sphere | |
| 124 | + glm::vec3 vectorToSphereCenter = _TEST_bigSpherePosition - _particle[p].position; | |
| 125 | + float distanceToSphereCenter = glm::length(vectorToSphereCenter); | |
| 126 | + float combinedRadius = _TEST_bigSphereRadius + _particle[p].radius; | |
| 127 | + if (distanceToSphereCenter < combinedRadius) { | |
| 128 | + | |
| 129 | + if (distanceToSphereCenter > 0.0f){ | |
| 130 | + glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter; | |
| 131 | + _particle[p].position = _TEST_bigSpherePosition - directionToSphereCenter * combinedRadius; | |
| 132 | + _particle[p].velocity.y += 0.005f; | |
| 133 | + } | |
| 134 | + } | |
| 135 | + } | |
| 136 | +} | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | +void ParticleSystem::render() { | |
| 141 | + | |
| 142 | + for (unsigned int p = 0; p < _numberOfParticles; p++) { | |
| 143 | + glColor3f(_particle[p].color.x, _particle[p].color.y, _particle[p].color.z); | |
| 144 | + glPushMatrix(); | |
| 145 | + glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z); | |
| 146 | + glutSolidSphere(_particle[p].radius, 6, 6); | |
| 147 | + glPopMatrix(); | |
| 148 | + | |
| 149 | + // render velocity lines | |
| 150 | + glColor4f( _particle[p].color.x, _particle[p].color.y, _particle[p].color.z, 0.5f); | |
| 151 | + glm::vec3 end = _particle[p].position - _particle[p].velocity * 2.0f; | |
| 152 | + glBegin(GL_LINES); | |
| 153 | + glVertex3f(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z); | |
| 154 | + glVertex3f(end.x, end.y, end.z); | |
| 155 | + | |
| 156 | + glEnd(); | |
| 157 | + | |
| 158 | + } | |
| 159 | +} | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |