From 2ad3aea729c37157208484f66e288207ca48759b Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 2 Jan 2014 17:02:04 -0800 Subject: [PATCH] Cleanup to move BuckyBalls prototype to own class file --- BuckyBalls.cpp | 9 - BuckyBalls.h | 14 - interface/src/BuckyBalls.cpp | 162 +++++++++ interface/src/BuckyBalls.h | 47 +++ interface/src/ParticleSystem.cpp | 547 ------------------------------- interface/src/ParticleSystem.h | 143 -------- interface/src/avatar/Hand.cpp | 149 +-------- interface/src/avatar/Hand.h | 18 +- 8 files changed, 217 insertions(+), 872 deletions(-) delete mode 100644 BuckyBalls.cpp delete mode 100644 BuckyBalls.h create mode 100644 interface/src/BuckyBalls.cpp create mode 100644 interface/src/BuckyBalls.h delete mode 100644 interface/src/ParticleSystem.cpp delete mode 100644 interface/src/ParticleSystem.h diff --git a/BuckyBalls.cpp b/BuckyBalls.cpp deleted file mode 100644 index 82a375a0f8..0000000000 --- a/BuckyBalls.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// -// BuckyBalls.cpp -// hifi -// -// Created by Philip on 1/2/14. -// -// - -#include "BuckyBalls.h" diff --git a/BuckyBalls.h b/BuckyBalls.h deleted file mode 100644 index a97fddea57..0000000000 --- a/BuckyBalls.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// BuckyBalls.h -// hifi -// -// Created by Philip on 1/2/14. -// -// - -#ifndef __hifi__BuckyBalls__ -#define __hifi__BuckyBalls__ - -#include - -#endif /* defined(__hifi__BuckyBalls__) */ diff --git a/interface/src/BuckyBalls.cpp b/interface/src/BuckyBalls.cpp new file mode 100644 index 0000000000..8227205523 --- /dev/null +++ b/interface/src/BuckyBalls.cpp @@ -0,0 +1,162 @@ +// +// BuckyBalls.cpp +// hifi +// +// Created by Philip on 1/2/14. +// +// + +#include "BuckyBalls.h" + +#include "Util.h" +#include "world.h" + +const int NUM_ELEMENTS = 3; +const float RANGE_BBALLS = 0.5f; +const float SIZE_BBALLS = 0.02f; +const float CORNER_BBALLS = 2.f; +const float GRAVITY_BBALLS = -0.25f; +const float BBALLS_ATTRACTION_DISTANCE = SIZE_BBALLS / 2.f; +const float COLLISION_RADIUS = 0.01f; +const float INITIAL_VELOCITY = 0.3f; + +glm::vec3 colors[NUM_ELEMENTS]; + +// Make some bucky balls for the avatar +BuckyBalls::BuckyBalls() { + _bballIsGrabbed[0] = 0; + _bballIsGrabbed[1] = 0; + colors[0] = glm::vec3(0.13f, 0.55f, 0.13f); + colors[1] = glm::vec3(0.64f, 0.16f, 0.16f); + colors[2] = glm::vec3(0.31f, 0.58f, 0.80f); + + qDebug("Creating buckyballs...\n"); + for (int i = 0; i < NUM_BBALLS; i++) { + _bballPosition[i] = CORNER_BBALLS + randVector() * RANGE_BBALLS; + int element = (rand() % NUM_ELEMENTS); + if (element == 0) { + _bballRadius[i] = SIZE_BBALLS; + _bballColor[i] = colors[0]; + } else if (element == 1) { + _bballRadius[i] = SIZE_BBALLS / 2.f; + _bballColor[i] = colors[1]; + } else { + _bballRadius[i] = SIZE_BBALLS * 2.f; + _bballColor[i] = colors[2]; + } + _bballColliding[i] = 0.f; + _bballElement[i] = element; + if (_bballElement[i] != 1) { + _bballVelocity[i] = randVector() * INITIAL_VELOCITY; + } else { + _bballVelocity[i] = glm::vec3(0); + } + } +} + +void BuckyBalls::grab(PalmData& palm, const glm::vec3& fingerTipPosition, glm::quat avatarOrientation, float deltaTime) { + float penetration; + glm::vec3 diff; + if (palm.getControllerButtons() & BUTTON_FWD) { + if (!_bballIsGrabbed[palm.getSixenseID()]) { + // Look for a ball to grab + for (int i = 0; i < NUM_BBALLS; i++) { + diff = _bballPosition[i] - fingerTipPosition; + penetration = glm::length(diff) - (_bballRadius[i] + COLLISION_RADIUS); + if (penetration < 0.f) { + _bballIsGrabbed[palm.getSixenseID()] = i; + } + } + } + if (_bballIsGrabbed[palm.getSixenseID()]) { + // If ball being grabbed, move with finger + diff = _bballPosition[_bballIsGrabbed[palm.getSixenseID()]] - fingerTipPosition; + penetration = glm::length(diff) - (_bballRadius[_bballIsGrabbed[palm.getSixenseID()]] + COLLISION_RADIUS); + _bballPosition[_bballIsGrabbed[palm.getSixenseID()]] -= glm::normalize(diff) * penetration; + glm::vec3 fingerTipVelocity = avatarOrientation * palm.getTipVelocity(); + if (_bballElement[_bballIsGrabbed[palm.getSixenseID()]] != 1) { + _bballVelocity[_bballIsGrabbed[palm.getSixenseID()]] = fingerTipVelocity; + } + _bballPosition[_bballIsGrabbed[palm.getSixenseID()]] = fingerTipPosition; + _bballColliding[_bballIsGrabbed[palm.getSixenseID()]] = 1.f; + } + } else { + _bballIsGrabbed[palm.getSixenseID()] = 0; + } +} + +const float COLLISION_BLEND_RATE = 0.5f; +const float ATTRACTION_BLEND_RATE = 0.9f; +const float ATTRACTION_VELOCITY_BLEND_RATE = 0.10f; + +void BuckyBalls::simulate(float deltaTime) { + // Look for collisions + for (int i = 0; i < NUM_BBALLS; i++) { + if (_bballElement[i] != 1) { + // For 'interacting' elements, look for other balls to interact with + for (int j = 0; j < NUM_BBALLS; j++) { + if (i != j) { + glm::vec3 diff = _bballPosition[i] - _bballPosition[j]; + float penetration = glm::length(diff) - (_bballRadius[i] + _bballRadius[j]); + if (penetration < 0.f) { + // Colliding - move away and transfer velocity + _bballPosition[i] -= glm::normalize(diff) * penetration * COLLISION_BLEND_RATE; + if (glm::dot(_bballVelocity[i], diff) < 0.f) { + _bballVelocity[i] = _bballVelocity[i] * (1.f - COLLISION_BLEND_RATE) + + glm::reflect(_bballVelocity[i], glm::normalize(diff)) * COLLISION_BLEND_RATE; + } + } + else if ((penetration > EPSILON) && (penetration < BBALLS_ATTRACTION_DISTANCE)) { + // If they get close to each other, bring them together with magnetic force + _bballPosition[i] -= glm::normalize(diff) * penetration * ATTRACTION_BLEND_RATE; + // Also make their velocities more similar + _bballVelocity[i] = _bballVelocity[i] * (1.f - ATTRACTION_VELOCITY_BLEND_RATE) + _bballVelocity[j] * ATTRACTION_VELOCITY_BLEND_RATE; + } + } + } + } + } + // Update position and bounce on walls + const float BBALL_CONTINUOUS_DAMPING = 0.00f; + const float BBALL_WALL_COLLISION_DAMPING = 0.2f; + const float COLLISION_DECAY_RATE = 0.8f; + + for (int i = 0; i < NUM_BBALLS; i++) { + _bballPosition[i] += _bballVelocity[i] * deltaTime; + if (_bballElement[i] != 1) { + _bballVelocity[i].y += GRAVITY_BBALLS * deltaTime; + } + _bballVelocity[i] -= _bballVelocity[i] * BBALL_CONTINUOUS_DAMPING * deltaTime; + for (int j = 0; j < 3; j++) { + if ((_bballPosition[i][j] + _bballRadius[i]) > (CORNER_BBALLS + RANGE_BBALLS)) { + _bballPosition[i][j] = (CORNER_BBALLS + RANGE_BBALLS) - _bballRadius[i]; + _bballVelocity[i][j] *= -(1.f - BBALL_WALL_COLLISION_DAMPING); + } + if ((_bballPosition[i][j] - _bballRadius[i]) < (CORNER_BBALLS -RANGE_BBALLS)) { + _bballPosition[i][j] = (CORNER_BBALLS -RANGE_BBALLS) + _bballRadius[i]; + _bballVelocity[i][j] *= -(1.f - BBALL_WALL_COLLISION_DAMPING); + } + } + _bballColliding[i] *= COLLISION_DECAY_RATE; + if (_bballColliding[i] < 0.1f) { + _bballColliding[i] = 0.f; + } + } +} + +void BuckyBalls::render() { + for (int i = 0; i < NUM_BBALLS; i++) { + if (_bballColliding[i] > 0.f) { + const float GRAB_BRIGHTEN = 1.15f; + glColor3f(_bballColor[i].x * GRAB_BRIGHTEN, _bballColor[i].y * GRAB_BRIGHTEN, _bballColor[i].z * GRAB_BRIGHTEN); + } else { + glColor3f(_bballColor[i].x, _bballColor[i].y, _bballColor[i].z); + } + glPushMatrix(); + glTranslatef(_bballPosition[i].x, _bballPosition[i].y, _bballPosition[i].z); + glutSolidSphere(_bballRadius[i], 15, 15); + glPopMatrix(); + } +} + + diff --git a/interface/src/BuckyBalls.h b/interface/src/BuckyBalls.h new file mode 100644 index 0000000000..19a589035d --- /dev/null +++ b/interface/src/BuckyBalls.h @@ -0,0 +1,47 @@ +// +// BuckyBalls.h +// hifi +// +// Created by Philip on 1/2/14. +// +// + +#ifndef __hifi__BuckyBalls__ +#define __hifi__BuckyBalls__ + +#include + +#include + +#include +#include + +#include "GeometryUtil.h" +#include "InterfaceConfig.h" +#include "Util.h" + + +const int NUM_BBALLS = 200; + +class BuckyBalls { +public: + BuckyBalls(); + void grab(PalmData& palm, const glm::vec3& fingerTipPosition, glm::quat avatarOrientation, float deltaTime); + void simulate(float deltaTime); + void render(); + + +private: + + glm::vec3 _bballPosition[NUM_BBALLS]; + glm::vec3 _bballVelocity[NUM_BBALLS]; + glm::vec3 _bballColor[NUM_BBALLS]; + float _bballRadius[NUM_BBALLS]; + float _bballColliding[NUM_BBALLS]; + int _bballElement[NUM_BBALLS]; + int _bballIsGrabbed[2]; + + +}; + +#endif /* defined(__hifi__BuckyBalls__) */ diff --git a/interface/src/ParticleSystem.cpp b/interface/src/ParticleSystem.cpp deleted file mode 100644 index 48a27c4fd1..0000000000 --- a/interface/src/ParticleSystem.cpp +++ /dev/null @@ -1,547 +0,0 @@ -// -// ParticleSystem.cpp -// hifi -// -// Created by Jeffrey on July 10, 2013 -// - -#include -#include "InterfaceConfig.h" -#include -#include "ParticleSystem.h" -#include "Application.h" - -const float DEFAULT_PARTICLE_RADIUS = 0.01f; -const float DEFAULT_PARTICLE_BOUNCE = 1.0f; -const float DEFAULT_PARTICLE_AIR_FRICTION = 2.0f; -const float DEFAULT_PARTICLE_LIFESPAN = 1.0f; -const int DEFAULT_PARTICLE_SPHERE_RESOLUTION = 6; -const float DEFAULT_EMITTER_RENDER_LENGTH = 0.2f; -const float DEFAULT_PARTICLE_CONNECT_DISTANCE = 0.03f; - -ParticleSystem::ParticleSystem() { - - _timer = 0.0f; - _numEmitters = 0; - _upDirection = glm::vec3(0.0f, 1.0f, 0.0f); // default - - for (unsigned int emitterIndex = 0; emitterIndex < MAX_EMITTERS; emitterIndex++) { - - Emitter * e = &_emitter[emitterIndex]; - e->active = false; - e->position = glm::vec3(0.0f, 0.0f, 0.0f); - e->previousPosition = glm::vec3(0.0f, 0.0f, 0.0f); - e->direction = glm::vec3(0.0f, 1.0f, 0.0f); - e->visible = false; - e->particleResolution = DEFAULT_PARTICLE_SPHERE_RESOLUTION; - e->particleLifespan = DEFAULT_PARTICLE_LIFESPAN; - e->showingBaseParticle = false; - e->emitReserve = 0.0; - e->thrust = 0.0f; - e->rate = 0.0f; - e->currentParticle = 0; - e->particleRenderStyle = PARTICLE_RENDER_STYLE_SPHERE; - e->numParticlesEmittedThisTime = 0; - e->maxParticleConnectDistance = DEFAULT_PARTICLE_CONNECT_DISTANCE; - - for (int lifeStage = 0; lifeStage < NUM_PARTICLE_LIFE_STAGES; lifeStage++) { - setParticleAttributesToDefault(&_emitter[emitterIndex].particleAttributes[lifeStage]); - } - }; - - for (unsigned int p = 0; p < MAX_PARTICLES; p++) { - _particle[p].alive = false; - _particle[p].age = 0.0f; - _particle[p].radius = 0.0f; - _particle[p].emitterIndex = 0; - _particle[p].previousParticle = NULL_PARTICLE; - _particle[p].position = glm::vec3(0.0f, 0.0f, 0.0f); - _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f); - } -} - -int ParticleSystem::addEmitter() { - - if (_numEmitters < MAX_EMITTERS) { - _numEmitters ++; - return _numEmitters - 1; - } - - return NULL_EMITTER; -} - - -void ParticleSystem::simulate(float deltaTime) { - - _timer += deltaTime; - - // update emitters - for (int emitterIndex = 0; emitterIndex < _numEmitters; emitterIndex++) { - assert(emitterIndex <= MAX_EMITTERS); - - if (_emitter[emitterIndex].active) { - updateEmitter(emitterIndex, deltaTime); - } - } - - // update particles - for (int p = 0; p < MAX_PARTICLES; p++) { - if (_particle[p].alive) { - if (_particle[p].age > _emitter[_particle[p].emitterIndex].particleLifespan) { - killParticle(p); - } else { - updateParticle(p, deltaTime); - } - } - } -} - - -void ParticleSystem::updateEmitter(int emitterIndex, float deltaTime) { - - _emitter[emitterIndex].emitReserve += _emitter[emitterIndex].rate * deltaTime; - _emitter[emitterIndex].numParticlesEmittedThisTime = (int)_emitter[emitterIndex].emitReserve; - _emitter[emitterIndex].emitReserve -= _emitter[emitterIndex].numParticlesEmittedThisTime; - - for (int p = 0; p < _emitter[emitterIndex].numParticlesEmittedThisTime; p++) { - float timeFraction = (float)p / (float)_emitter[emitterIndex].numParticlesEmittedThisTime; - createParticle(emitterIndex, timeFraction); - } -} - - -void ParticleSystem::createParticle(int e, float timeFraction) { - - float maxConnectDistSqr = _emitter[e].maxParticleConnectDistance * _emitter[e].maxParticleConnectDistance; - for (unsigned int p = 0; p < MAX_PARTICLES; p++) { - if (!_particle[p].alive) { - - _particle[p].emitterIndex = e; - _particle[p].alive = true; - _particle[p].age = 0.0f; - _particle[p].velocity = _emitter[e].direction * _emitter[e].thrust; - _particle[p].position = _emitter[e].previousPosition + timeFraction * (_emitter[e].position - _emitter[e].previousPosition); - _particle[p].radius = _emitter[e].particleAttributes[PARTICLE_LIFESTAGE_0].radius; - _particle[p].color = _emitter[e].particleAttributes[PARTICLE_LIFESTAGE_0].color; - _particle[p].previousParticle = NULL_PARTICLE; - - Particle& prev = _particle[_emitter[e].currentParticle]; - if (prev.alive) { - if (prev.emitterIndex == e) { - glm::vec3 diff = prev.position - _particle[p].position; - float sqrDist = glm::dot(diff, diff); - if (sqrDist < maxConnectDistSqr) { - _particle[p].previousParticle = _emitter[e].currentParticle; - } - } - } - - _emitter[e].currentParticle = p; - - break; - } - } -} - -void ParticleSystem::killParticle(int p) { - - assert(p >= 0); - assert(p < MAX_PARTICLES); - - _particle[p].alive = false; - _particle[p].previousParticle = NULL_PARTICLE; - _particle[p].position = _emitter[_particle[p].emitterIndex].position; - _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f); - _particle[p].age = 0.0f; - _particle[p].emitterIndex = NULL_PARTICLE; - _particle[p].color = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f); - _particle[p].radius = 0.0f; - } - - -void ParticleSystem::setEmitterPosition(int emitterIndex, glm::vec3 position) { - _emitter[emitterIndex].previousPosition = _emitter[emitterIndex].position; - _emitter[emitterIndex].position = position; -} - - -void ParticleSystem::setParticleAttributes(int emitterIndex, ParticleAttributes attributes) { - - for (int lifeStage = 0; lifeStage < NUM_PARTICLE_LIFE_STAGES; lifeStage ++) { - setParticleAttributes(emitterIndex, (ParticleLifeStage)lifeStage, attributes); - } -} - -void ParticleSystem::setParticleAttributesToDefault(ParticleAttributes * a) { - - a->radius = DEFAULT_PARTICLE_RADIUS; - a->color = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f); - a->bounce = DEFAULT_PARTICLE_BOUNCE; - a->airFriction = DEFAULT_PARTICLE_AIR_FRICTION; - a->gravity = 0.0f; - a->jitter = 0.0f; - a->emitterAttraction = 0.0f; - a->tornadoForce = 0.0f; - a->neighborAttraction = 0.0f; - a->neighborRepulsion = 0.0f; - a->collisionSphereRadius = 0.0f; - a->collisionSpherePosition = glm::vec3(0.0f, 0.0f, 0.0f); - a->usingCollisionSphere = false; - a->collisionPlaneNormal = _upDirection; - a->collisionPlanePosition = glm::vec3(0.0f, 0.0f, 0.0f); - a->usingCollisionPlane = false; - a->modulationAmplitude = 0.0f; - a->modulationRate = 0.0; - a->modulationStyle = COLOR_MODULATION_STYLE_NULL; - -} - - -void ParticleSystem::setParticleAttributes(int emitterIndex, ParticleLifeStage lifeStage, ParticleAttributes attributes) { - - assert(lifeStage >= 0); - assert(lifeStage < NUM_PARTICLE_LIFE_STAGES); - - ParticleAttributes * a = &_emitter[emitterIndex].particleAttributes[lifeStage]; - - a->radius = attributes.radius; - a->color = attributes.color; - a->bounce = attributes.bounce; - a->gravity = attributes.gravity; - a->airFriction = attributes.airFriction; - a->jitter = attributes.jitter; - a->emitterAttraction = attributes.emitterAttraction; - a->tornadoForce = attributes.tornadoForce; - a->neighborAttraction = attributes.neighborAttraction; - a->neighborRepulsion = attributes.neighborRepulsion; - a->usingCollisionSphere = attributes.usingCollisionSphere; - a->collisionSpherePosition = attributes.collisionSpherePosition; - a->collisionSphereRadius = attributes.collisionSphereRadius; - a->usingCollisionPlane = attributes.usingCollisionPlane; - a->collisionPlanePosition = attributes.collisionPlanePosition; - a->collisionPlaneNormal = attributes.collisionPlaneNormal; - a->modulationAmplitude = attributes.modulationAmplitude; - a->modulationRate = attributes.modulationRate; - a->modulationStyle = attributes.modulationStyle; -} - - -void ParticleSystem::updateParticle(int p, float deltaTime) { - - Emitter myEmitter = _emitter[_particle[p].emitterIndex]; - - assert(_particle[p].age <= myEmitter.particleLifespan); - - float ageFraction = 0.0f; - int lifeStage = 0; - float lifeStageFraction = 0.0f; - - if (_emitter[_particle[p].emitterIndex].particleLifespan > 0.0) { - - ageFraction = _particle[p].age / myEmitter.particleLifespan; - lifeStage = (int)(ageFraction * (NUM_PARTICLE_LIFE_STAGES - 1)); - lifeStageFraction = ageFraction * (NUM_PARTICLE_LIFE_STAGES - 1) - lifeStage; - - // adjust radius - _particle[p].radius - = myEmitter.particleAttributes[lifeStage ].radius * (1.0f - lifeStageFraction) - + myEmitter.particleAttributes[lifeStage+1].radius * lifeStageFraction; - - // apply random jitter - float j = myEmitter.particleAttributes[lifeStage].jitter; - _particle[p].velocity += - glm::vec3 - ( - -j * ONE_HALF + j * randFloat(), - -j * ONE_HALF + j * randFloat(), - -j * ONE_HALF + j * randFloat() - ) * deltaTime; - - // apply attraction to home position - glm::vec3 vectorToHome = myEmitter.position - _particle[p].position; - _particle[p].velocity += vectorToHome * myEmitter.particleAttributes[lifeStage].emitterAttraction * deltaTime; - - // apply neighbor attraction - int neighbor = p + 1; - if (neighbor == MAX_PARTICLES) { - neighbor = 0; - } - - if (_particle[neighbor].emitterIndex == _particle[p].emitterIndex) { - glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position; - - _particle[p].velocity -= vectorToNeighbor * myEmitter.particleAttributes[lifeStage].neighborAttraction * deltaTime; - - float distanceToNeighbor = glm::length(vectorToNeighbor); - if (distanceToNeighbor > 0.0f) { - _particle[neighbor].velocity += (vectorToNeighbor / (1.0f + distanceToNeighbor * distanceToNeighbor)) * myEmitter.particleAttributes[lifeStage].neighborRepulsion * deltaTime; - } - } - - // apply tornado force - glm::vec3 tornadoDirection = glm::cross(vectorToHome, myEmitter.direction); - _particle[p].velocity += tornadoDirection * myEmitter.particleAttributes[lifeStage].tornadoForce * deltaTime; - - // apply air friction - float drag = 1.0 - myEmitter.particleAttributes[lifeStage].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 -= _upDirection * myEmitter.particleAttributes[lifeStage].gravity * deltaTime; - - // update position by velocity - _particle[p].position += _particle[p].velocity; - - // collision with the plane surface - if (myEmitter.particleAttributes[lifeStage].usingCollisionPlane) { - glm::vec3 vectorFromParticleToPlanePosition = _particle[p].position - myEmitter.particleAttributes[lifeStage].collisionPlanePosition; - glm::vec3 normal = myEmitter.particleAttributes[lifeStage].collisionPlaneNormal; - float dot = glm::dot(vectorFromParticleToPlanePosition, normal); - if (dot < _particle[p].radius) { - _particle[p].position += normal * (_particle[p].radius - dot); - float planeNormalComponentOfVelocity = glm::dot(_particle[p].velocity, normal); - _particle[p].velocity -= normal * planeNormalComponentOfVelocity * (1.0f + myEmitter.particleAttributes[lifeStage].bounce); - } - } - - // collision with sphere - if (myEmitter.particleAttributes[lifeStage].usingCollisionSphere) { - glm::vec3 vectorToSphereCenter = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - _particle[p].position; - float distanceToSphereCenter = glm::length(vectorToSphereCenter); - float combinedRadius = myEmitter.particleAttributes[lifeStage].collisionSphereRadius + _particle[p].radius; - if (distanceToSphereCenter < combinedRadius) { - - if (distanceToSphereCenter > 0.0f){ - glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter; - _particle[p].position = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - directionToSphereCenter * combinedRadius; - } - } - } - } - - // adjust color - _particle[p].color - = myEmitter.particleAttributes[lifeStage ].color * (1.0f - lifeStageFraction) - + myEmitter.particleAttributes[lifeStage+1].color * lifeStageFraction; - - // apply color modulation - if (myEmitter.particleAttributes[lifeStage ].modulationAmplitude > 0.0f) { - float redModulation = 0.0f; - float greenModulation = 0.0f; - float bueModulation = 0.0f; - float radian = _timer * myEmitter.particleAttributes[lifeStage ].modulationRate * PI_TIMES_TWO; - - if (myEmitter.particleAttributes[lifeStage ].modulationStyle == COLOR_MODULATION_STYLE_LIGHNTESS_PULSE) { - if (sinf(radian) > 0.0f) { - redModulation = myEmitter.particleAttributes[lifeStage].modulationAmplitude; - greenModulation = myEmitter.particleAttributes[lifeStage].modulationAmplitude; - bueModulation = myEmitter.particleAttributes[lifeStage].modulationAmplitude; - } - - } else if (myEmitter.particleAttributes[lifeStage].modulationStyle == COLOR_MODULATION_STYLE_LIGHTNESS_WAVE) { - float amp = myEmitter.particleAttributes[lifeStage].modulationAmplitude; - float brightness = amp * ONE_HALF + sinf(radian) * amp * ONE_HALF; - redModulation = brightness; - greenModulation = brightness; - bueModulation = brightness; - - } else if (myEmitter.particleAttributes[lifeStage].modulationStyle == COLOR_MODULATION_STYLE_RAINBOW_CYCLE) { - - float amp = myEmitter.particleAttributes[lifeStage].modulationAmplitude * ONE_HALF; - redModulation = sinf(radian * RAINBOW_CYCLE_RED_RATE ) * amp; - greenModulation = sinf(radian * RAINBOW_CYCLE_GREEN_RATE) * amp; - bueModulation = sinf(radian * RAINBOW_CYCLE_BLUE_RATE ) * amp; - } - - _particle[p].color.r += redModulation; - _particle[p].color.g += greenModulation; - _particle[p].color.b += bueModulation; - _particle[p].color.a = 1.0f; - - if (_particle[p].color.r > 1.0f) {_particle[p].color.r = 1.0f;} - if (_particle[p].color.g > 1.0f) {_particle[p].color.g = 1.0f;} - if (_particle[p].color.b > 1.0f) {_particle[p].color.b = 1.0f;} - if (_particle[p].color.a > 1.0f) {_particle[p].color.a = 1.0f;} - - if (_particle[p].color.r < 0.0f) {_particle[p].color.r = 0.0f;} - if (_particle[p].color.g < 0.0f) {_particle[p].color.g = 0.0f;} - if (_particle[p].color.b < 0.0f) {_particle[p].color.b = 0.0f;} - if (_particle[p].color.a < 0.0f) {_particle[p].color.a = 0.0f;} - } - - // do this at the end... - _particle[p].age += deltaTime; -} - - -void ParticleSystem::killAllParticles() { - - for (int e = 0; e < _numEmitters; e++) { - _emitter[e].currentParticle = NULL_PARTICLE; - _emitter[e].emitReserve = 0.0f; - _emitter[e].previousPosition = _emitter[e].position; - _emitter[e].rate = 0.0f; - _emitter[e].currentParticle = 0; - _emitter[e].numParticlesEmittedThisTime = 0; - } - - for (int p = 0; p < MAX_PARTICLES; p++) { - killParticle(p); - } -} - -void ParticleSystem::render() { - - // render the emitters - for (int e = 0; e < MAX_EMITTERS; e++) { - - if (_emitter[e].active) { - if (_emitter[e].showingBaseParticle) { - glColor4f(_particle[0].color.r, _particle[0].color.g, _particle[0].color.b, _particle[0].color.a); - glPushMatrix(); - glTranslatef(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z); - glutSolidSphere(_particle[0].radius, _emitter[e].particleResolution, _emitter[e].particleResolution); - glPopMatrix(); - } - } - - if (_emitter[e].visible) { - renderEmitter(e, DEFAULT_EMITTER_RENDER_LENGTH); - } - }; - - // render the particles - for (int p = 0; p < MAX_PARTICLES; p++) { - if (_particle[p].alive) { - if (_emitter[_particle[p].emitterIndex].particleLifespan > 0.0) { - renderParticle(p); - } - } - } -} - -void ParticleSystem::renderParticle(int p) { - - glColor4f(_particle[p].color.r, _particle[p].color.g, _particle[p].color.b, _particle[p].color.a); - - if (_emitter[_particle[p].emitterIndex].particleRenderStyle == PARTICLE_RENDER_STYLE_BILLBOARD) { - glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition(); - glm::vec3 viewVector = _particle[p].position - cameraPosition; - float distance = glm::length(viewVector); - - if (distance >= 0.0f) { - viewVector /= distance; - glm::vec3 up = glm::vec3(viewVector.y, viewVector.z, viewVector.x); - glm::vec3 right = glm::vec3(viewVector.z, viewVector.x, viewVector.y); - - glm::vec3 p0 = _particle[p].position - right * _particle[p].radius - up * _particle[p].radius; - glm::vec3 p1 = _particle[p].position + right * _particle[p].radius - up * _particle[p].radius; - glm::vec3 p2 = _particle[p].position + right * _particle[p].radius + up * _particle[p].radius; - glm::vec3 p3 = _particle[p].position - right * _particle[p].radius + up * _particle[p].radius; - - glBegin(GL_TRIANGLES); - glVertex3f(p0.x, p0.y, p0.z); - glVertex3f(p1.x, p1.y, p1.z); - glVertex3f(p2.x, p2.y, p2.z); - glEnd(); - - glBegin(GL_TRIANGLES); - glVertex3f(p0.x, p0.y, p0.z); - glVertex3f(p2.x, p2.y, p2.z); - glVertex3f(p3.x, p3.y, p3.z); - glEnd(); - } - } else if (_emitter[_particle[p].emitterIndex].particleRenderStyle == PARTICLE_RENDER_STYLE_SPHERE) { - - glPushMatrix(); - glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z); - glutSolidSphere(_particle[p].radius, _emitter[_particle[p].emitterIndex].particleResolution, _emitter[_particle[p].emitterIndex].particleResolution); - glPopMatrix(); - - } else if (_emitter[_particle[p].emitterIndex].particleRenderStyle == PARTICLE_RENDER_STYLE_RIBBON) { - - if (_particle[p].previousParticle != NULL_PARTICLE) { - if ((_particle[p].alive) - && (_particle[_particle[p].previousParticle].alive) - && (_particle[_particle[p].previousParticle].emitterIndex == _particle[p].emitterIndex)) { - - glm::vec3 vectorFromPreviousParticle = _particle[p].position - _particle[_particle[p].previousParticle].position; - float distance = glm::length(vectorFromPreviousParticle); - - if (distance > 0.0f) { - - vectorFromPreviousParticle /= distance; - - glm::vec3 up = glm::normalize(glm::cross(vectorFromPreviousParticle, _upDirection)) * _particle[p].radius; - glm::vec3 right = glm::normalize(glm::cross(up, vectorFromPreviousParticle )) * _particle[p].radius; - - glm::vec3 p0Left = _particle[p ].position - right; - glm::vec3 p0Right = _particle[p ].position + right; - glm::vec3 p0Down = _particle[p ].position - up; - glm::vec3 p0Up = _particle[p ].position + up; - - glm::vec3 ppLeft = _particle[_particle[p].previousParticle].position - right; - glm::vec3 ppRight = _particle[_particle[p].previousParticle].position + right; - glm::vec3 ppDown = _particle[_particle[p].previousParticle].position - up; - glm::vec3 ppUp = _particle[_particle[p].previousParticle].position + up; - - glBegin(GL_TRIANGLES); - - glVertex3f(p0Left.x, p0Left.y, p0Left.z ); - glVertex3f(p0Right.x, p0Right.y, p0Right.z); - glVertex3f(ppLeft.x, ppLeft.y, ppLeft.z ); - - glVertex3f(p0Right.x, p0Right.y, p0Right.z); - glVertex3f(ppLeft.x, ppLeft.y, ppLeft.z ); - glVertex3f(ppRight.x, ppRight.y, ppRight.z); - - glVertex3f(p0Up.x, p0Up.y, p0Up.z ); - glVertex3f(p0Down.x, p0Down.y, p0Down.z ); - glVertex3f(ppDown.x, ppDown.y, ppDown.z ); - - glVertex3f(p0Up.x, p0Up.y, p0Up.z ); - glVertex3f(ppUp.x, ppUp.y, ppUp.z ); - glVertex3f(ppDown.x, ppDown.y, ppDown.z ); - - glVertex3f(p0Up.x, p0Up.y, p0Left.z ); - glVertex3f(p0Right.x, p0Right.y, p0Right.z); - glVertex3f(p0Down.x, p0Down.y, p0Down.z ); - - glVertex3f(p0Up.x, p0Up.y, p0Left.z ); - glVertex3f(p0Left.x, p0Left.y, p0Left.z ); - glVertex3f(p0Down.x, p0Down.y, p0Down.z ); - - glVertex3f(ppUp.x, ppUp.y, ppLeft.z ); - glVertex3f(ppRight.x, ppRight.y, ppRight.z); - glVertex3f(ppDown.x, ppDown.y, ppDown.z ); - - glVertex3f(ppUp.x, ppUp.y, ppLeft.z ); - glVertex3f(ppLeft.x, ppLeft.y, ppLeft.z ); - glVertex3f(ppDown.x, ppDown.y, ppDown.z ); - - glEnd(); - } - } - } - } -} - -void ParticleSystem::renderEmitter(int e, float size) { - - glm::vec3 v = _emitter[e].direction * size; - - 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 + v.x, _emitter[e].position.y + v.y, _emitter[e].position.z + v.z); - glEnd(); -} - - - - - diff --git a/interface/src/ParticleSystem.h b/interface/src/ParticleSystem.h deleted file mode 100644 index 8b83d6606a..0000000000 --- a/interface/src/ParticleSystem.h +++ /dev/null @@ -1,143 +0,0 @@ -// -// ParticleSystem.h -// hifi -// -// Created by Jeffrey on July 10, 2013 -// - -#ifndef hifi_ParticleSystem_h -#define hifi_ParticleSystem_h - -#include - -const int NULL_EMITTER = -1; -const int NULL_PARTICLE = -1; -const int MAX_EMITTERS = 100; -const int MAX_PARTICLES = 5000; - -const float RAINBOW_CYCLE_RED_RATE = 0.5f; -const float RAINBOW_CYCLE_GREEN_RATE = 0.7f; -const float RAINBOW_CYCLE_BLUE_RATE = 1.0f; - -enum ParticleRenderStyle -{ - PARTICLE_RENDER_STYLE_SPHERE = 0, - PARTICLE_RENDER_STYLE_BILLBOARD, - PARTICLE_RENDER_STYLE_RIBBON, - NUM_PARTICLE_RENDER_STYLES -}; - -enum ColorModulationStyle -{ - COLOR_MODULATION_STYLE_NULL = -1, - COLOR_MODULATION_STYLE_LIGHNTESS_PULSE, - COLOR_MODULATION_STYLE_LIGHTNESS_WAVE, - COLOR_MODULATION_STYLE_RAINBOW_CYCLE, - NUM_COLOR_MODULATION_STYLES -}; - -enum ParticleLifeStage -{ - PARTICLE_LIFESTAGE_0 = 0, - PARTICLE_LIFESTAGE_1, - PARTICLE_LIFESTAGE_2, - PARTICLE_LIFESTAGE_3, - NUM_PARTICLE_LIFE_STAGES -}; - -class ParticleSystem { -public: - - struct ParticleAttributes { - float radius; // radius of the particle - glm::vec4 color; // color (rgba) of the particle - float bounce; // how much reflection when the particle collides with floor/ground - float gravity; // force opposite of up direction - float airFriction; // continual dampening of velocity - float jitter; // random forces on velocity - float emitterAttraction; // an attraction to the emitter position - float tornadoForce; // force perpendicular to direction axis - float neighborAttraction; // causes particle to be pulled towards next particle in list - float neighborRepulsion; // causes particle to be repelled by previous particle in list - bool usingCollisionSphere; // set to true to allow collision with a sphere - glm::vec3 collisionSpherePosition; // position of the collision sphere - float collisionSphereRadius; // radius of the collision sphere - bool usingCollisionPlane; // set to true to allow collision with a plane - glm::vec3 collisionPlanePosition; // reference position of the collision plane - glm::vec3 collisionPlaneNormal; // the surface normal of the collision plane - float modulationAmplitude; // sets the degree (from 0 to 1) of the modulating effect - float modulationRate; // the period of modulation, in seconds - ColorModulationStyle modulationStyle; // to choose between color modulation styles - }; - - // public methods... - ParticleSystem(); - - int addEmitter(); // add (create new) emitter and get its unique id - void simulate(float deltaTime); - void killAllParticles(); - void render(); - - void setUpDirection(glm::vec3 upDirection) {_upDirection = upDirection;} // tell particle system which direction is up - void setParticleAttributesToDefault(ParticleAttributes * attributes); // set these attributes to their default values - void setParticleAttributes (int emitterIndex, ParticleAttributes attributes); // set attributes for whole life of particles - void setParticleAttributes (int emitterIndex, ParticleLifeStage lifeStage, ParticleAttributes attributes); // set attributes for this life stage - void setEmitterPosition (int emitterIndex, glm::vec3 position ); - void setEmitterActive (int emitterIndex, bool active ) {_emitter[emitterIndex].active = active; } - void setEmitterParticleResolution (int emitterIndex, int resolution ) {_emitter[emitterIndex].particleResolution = resolution; } - void setEmitterDirection (int emitterIndex, glm::vec3 direction ) {_emitter[emitterIndex].direction = direction; } - void setShowingEmitter (int emitterIndex, bool showing ) {_emitter[emitterIndex].visible = showing; } - void setEmitterParticleLifespan (int emitterIndex, float lifespan ) {_emitter[emitterIndex].particleLifespan = lifespan; } - void setParticleRenderStyle (int emitterIndex, ParticleRenderStyle renderStyle ) {_emitter[emitterIndex].particleRenderStyle = renderStyle; } - void setEmitterThrust (int emitterIndex, float thrust ) {_emitter[emitterIndex].thrust = thrust; } - void setEmitterRate (int emitterIndex, float rate ) {_emitter[emitterIndex].rate = rate; } - void setShowingEmitterBaseParticle(int emitterIndex, bool showing ) {_emitter[emitterIndex].showingBaseParticle = showing; } - -private: - - 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 - int emitterIndex; // which emitter created this particle? - int previousParticle; // the last particle that this particle's emitter emitted; - }; - - struct Emitter { - bool active; // if false, the emitter is disabled - allows for easy switching on and off - glm::vec3 position; // the position of the emitter in world coordinates - glm::vec3 previousPosition; // the position of the emitter in the previous time step - glm::vec3 direction; // a normalized vector used as an axis for particle emission and other effects - bool visible; // whether or not a line is shown indicating the emitter (indicating its direction) - float particleLifespan; // how long the particle shall live, in seconds - int particleResolution; // for sphere-based particles - float emitReserve; // baed on 'rate', this is the number of particles that need to be emitted at a given time step - int numParticlesEmittedThisTime; //the integer number of particles to emit at the preent time step - float thrust; // the initial velocity upon emitting along the emitter direction - float rate; // currently, how many particles emitted during a simulation time step - bool showingBaseParticle; // if true, a copy of particle 0 is shown on the emitter position - int currentParticle; // the index of the most recently-emitted particle - ParticleAttributes particleAttributes[NUM_PARTICLE_LIFE_STAGES]; // the attributes of particles emitted from this emitter - ParticleRenderStyle particleRenderStyle; - float maxParticleConnectDistance; // past this, don't connect the particles. - }; - - glm::vec3 _upDirection; - Emitter _emitter[MAX_EMITTERS]; - Particle _particle[MAX_PARTICLES]; - int _numEmitters; - float _timer; - - // private methods - void updateEmitter(int emitterIndex, float deltaTime); - void updateParticle(int index, float deltaTime); - void createParticle(int e, float timeFraction); - void killParticle(int p); - void renderEmitter(int emitterIndex, float size); - void renderParticle(int p); -}; - -#endif diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index e63c4fc4ee..20f96b2509 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -19,13 +19,7 @@ using namespace std; -const float RANGE_BBALLS = 0.5f; -const float SIZE_BBALLS = 0.02f; -const float CORNER_BBALLS = 2.f; -const float GRAVITY_BBALLS = -0.25f; -const float BBALLS_ATTRACTION_DISTANCE = SIZE_BBALLS / 2.f; - -const float FINGERTIP_COLLISION_RADIUS = SIZE_BBALLS / 2.f; +const float FINGERTIP_COLLISION_RADIUS = 0.01; const float FINGERTIP_VOXEL_SIZE = 0.05; const int TOY_BALL_HAND = 1; const float TOY_BALL_RADIUS = 0.05f; @@ -71,35 +65,6 @@ Hand::Hand(Avatar* owningAvatar) : _whichBallColor[i] = 0; } _lastControllerButtons = 0; - - // Make some bucky balls for the avatar - _bballIsGrabbed[0] = 0; - _bballIsGrabbed[1] = 0; - if (_owningAvatar && _owningAvatar->getOwningNode() == NULL) { - printf("Creating buckyballs...\n"); - for (int i = 0; i < NUM_BBALLS; i++) { - _bballPosition[i] = CORNER_BBALLS + randVector() * RANGE_BBALLS; - int element = (rand() % 3); - if (element == 0) { - _bballRadius[i] = SIZE_BBALLS; - _bballColor[i] = glm::vec3(0.13f, 0.55f, 0.13f); - } else if (element == 1) { - _bballRadius[i] = SIZE_BBALLS / 2.f; - _bballColor[i] = glm::vec3(0.64f, 0.16f, 0.16f); - - } else { - _bballRadius[i] = SIZE_BBALLS * 2.f; - _bballColor[i] = glm::vec3(0.31f, 0.58f, 0.80f); - } - _bballColliding[i] = 0.f; - _bballElement[i] = element; - if (_bballElement[i] != 1) { - _bballVelocity[i] = randVector() * 0.3f; - } else { - _bballVelocity[i] = glm::vec3(0); - } - } - } } void Hand::init() { @@ -115,111 +80,6 @@ void Hand::init() { void Hand::reset() { } -void Hand::grabBuckyBalls(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime) { - float penetration; - glm::vec3 diff; - if (palm.getControllerButtons() & BUTTON_FWD) { - if (!_bballIsGrabbed[palm.getSixenseID()]) { - // Look for a ball to grab - for (int i = 0; i < NUM_BBALLS; i++) { - diff = _bballPosition[i] - fingerTipPosition; - penetration = glm::length(diff) - (_bballRadius[i] + FINGERTIP_COLLISION_RADIUS); - if (penetration < 0.f) { - _bballIsGrabbed[palm.getSixenseID()] = i; - } - } - } - if (_bballIsGrabbed[palm.getSixenseID()]) { - // If ball being grabbed, move with finger - diff = _bballPosition[_bballIsGrabbed[palm.getSixenseID()]] - fingerTipPosition; - penetration = glm::length(diff) - (_bballRadius[_bballIsGrabbed[palm.getSixenseID()]] + FINGERTIP_COLLISION_RADIUS); - _bballPosition[_bballIsGrabbed[palm.getSixenseID()]] -= glm::normalize(diff) * penetration; - glm::vec3 fingerTipVelocity = _owningAvatar->getOrientation() * palm.getTipVelocity(); - if (_bballElement[_bballIsGrabbed[palm.getSixenseID()]] != 1) { - _bballVelocity[_bballIsGrabbed[palm.getSixenseID()]] = fingerTipVelocity; - } - _bballPosition[_bballIsGrabbed[palm.getSixenseID()]] = fingerTipPosition; - _bballColliding[_bballIsGrabbed[palm.getSixenseID()]] = 1.f; - } - } else { - _bballIsGrabbed[palm.getSixenseID()] = 0; - } -} - -const float COLLISION_BLEND_RATE = 0.5f; -const float ATTRACTION_BLEND_RATE = 0.9f; -const float ATTRACTION_VELOCITY_BLEND_RATE = 0.10f; - -void Hand::simulateBuckyBalls(float deltaTime) { - // Look for collisions - for (int i = 0; i < NUM_BBALLS; i++) { - if (_bballElement[i] != 1) { - // For 'interacting' elements, look for other balls to interact with - for (int j = 0; j < NUM_BBALLS; j++) { - if (i != j) { - glm::vec3 diff = _bballPosition[i] - _bballPosition[j]; - float penetration = glm::length(diff) - (_bballRadius[i] + _bballRadius[j]); - if (penetration < 0.f) { - // Colliding - move away and transfer velocity - _bballPosition[i] -= glm::normalize(diff) * penetration * COLLISION_BLEND_RATE; - if (glm::dot(_bballVelocity[i], diff) < 0.f) { - _bballVelocity[i] = _bballVelocity[i] * (1.f - COLLISION_BLEND_RATE) + - glm::reflect(_bballVelocity[i], glm::normalize(diff)) * COLLISION_BLEND_RATE; - } - } - else if ((penetration > EPSILON) && (penetration < BBALLS_ATTRACTION_DISTANCE)) { - // If they get close to each other, bring them together with magnetic force - _bballPosition[i] -= glm::normalize(diff) * penetration * ATTRACTION_BLEND_RATE; - // Also make their velocities more similar - _bballVelocity[i] = _bballVelocity[i] * (1.f - ATTRACTION_VELOCITY_BLEND_RATE) + _bballVelocity[j] * ATTRACTION_VELOCITY_BLEND_RATE; - } - } - } - } - } - // Update position and bounce on walls - const float BBALL_CONTINUOUS_DAMPING = 0.00f; - const float BBALL_WALL_COLLISION_DAMPING = 0.2f; - - for (int i = 0; i < NUM_BBALLS; i++) { - _bballPosition[i] += _bballVelocity[i] * deltaTime; - if (_bballElement[i] != 1) { - _bballVelocity[i].y += GRAVITY_BBALLS * deltaTime; - } - _bballVelocity[i] -= _bballVelocity[i] * BBALL_CONTINUOUS_DAMPING * deltaTime; - for (int j = 0; j < 3; j++) { - if ((_bballPosition[i][j] + _bballRadius[i]) > (CORNER_BBALLS + RANGE_BBALLS)) { - _bballPosition[i][j] = (CORNER_BBALLS + RANGE_BBALLS) - _bballRadius[i]; - _bballVelocity[i][j] *= -(1.f - BBALL_WALL_COLLISION_DAMPING); - } - if ((_bballPosition[i][j] - _bballRadius[i]) < (CORNER_BBALLS -RANGE_BBALLS)) { - _bballPosition[i][j] = (CORNER_BBALLS -RANGE_BBALLS) + _bballRadius[i]; - _bballVelocity[i][j] *= -(1.f - BBALL_WALL_COLLISION_DAMPING); - } - } - _bballColliding[i] *= 0.8f; - if (_bballColliding[i] < 0.1f) { - _bballColliding[i] = 0.f; - } - } -} - -void Hand::renderBuckyBalls() { - for (int i = 0; i < NUM_BBALLS; i++) { - if (_bballColliding[i] > 0.f) { - glColor3f(_bballColor[i].x * 1.15f, _bballColor[i].y * 1.15f, _bballColor[i].z * 1.15f); - } else { - glColor3f(_bballColor[i].x, _bballColor[i].y, _bballColor[i].z); - } - glPushMatrix(); - glTranslatef(_bballPosition[i].x, _bballPosition[i].y, _bballPosition[i].z); - glutSolidSphere(_bballRadius[i], 15, 15); - //glutSolidCube(_bballRadius[i] * 2.f); - glPopMatrix(); - } -} - - void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime) { Application* app = Application::getInstance(); ParticleTree* particles = app->getParticles()->getTree(); @@ -399,7 +259,7 @@ void Hand::simulate(float deltaTime, bool isMine) { } if (isMine) { - simulateBuckyBalls(deltaTime); + _buckyBalls.simulate(deltaTime); } const glm::vec3 leapHandsOffsetFromFace(0.0, -0.2, -0.3); // place the hand in front of the face where we can see it @@ -425,7 +285,8 @@ void Hand::simulate(float deltaTime, bool isMine) { glm::vec3 fingerTipPosition = finger.getTipPosition(); simulateToyBall(palm, fingerTipPosition, deltaTime); - grabBuckyBalls(palm, fingerTipPosition, deltaTime); + + _buckyBalls.grab(palm, fingerTipPosition, _owningAvatar->getOrientation(), deltaTime); if (palm.getControllerButtons() & BUTTON_4) { _grabDelta += palm.getRawVelocity() * deltaTime; @@ -642,7 +503,7 @@ void Hand::render(bool isMine) { _renderAlpha = 1.0; if (isMine) { - renderBuckyBalls(); + _buckyBalls.render(); } if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) { diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 3ed7beb2d7..eb757612ee 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -21,6 +21,7 @@ #include #include +#include "BuckyBalls.h" #include "InterfaceConfig.h" #include "world.h" #include "devices/SerialInterface.h" @@ -30,9 +31,6 @@ class Avatar; class ProgramObject; -const int NUM_BBALLS = 200; - - class Hand : public HandData { public: Hand(Avatar* owningAvatar); @@ -87,6 +85,8 @@ private: float _collisionAge; float _collisionDuration; + BuckyBalls _buckyBalls; + // private methods void setLeapHands(const std::vector& handPositions, const std::vector& handNormals); @@ -100,10 +100,6 @@ private: void handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPosition, VoxelTreeElement* voxel, float deltaTime); void simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime); - void grabBuckyBalls(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime); - - void simulateBuckyBalls(float deltaTime); - void renderBuckyBalls(); #define MAX_HANDS 2 bool _toyBallInHand[MAX_HANDS]; @@ -121,14 +117,6 @@ private: Sound _throwSound; Sound _catchSound; - glm::vec3 _bballPosition[NUM_BBALLS]; - glm::vec3 _bballVelocity[NUM_BBALLS]; - glm::vec3 _bballColor[NUM_BBALLS]; - float _bballRadius[NUM_BBALLS]; - float _bballColliding[NUM_BBALLS]; - int _bballElement[NUM_BBALLS]; - int _bballIsGrabbed[2]; - }; #endif