diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7d87d3d744..635e5c16d7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -81,9 +81,9 @@ const int MIRROR_VIEW_TOP_PADDING = 5; const int MIRROR_VIEW_LEFT_PADDING = 10; const int MIRROR_VIEW_WIDTH = 265; const int MIRROR_VIEW_HEIGHT = 215; -const float MIRROR_FULLSCREEN_DISTANCE = 0.2f; -const float MIRROR_REARVIEW_DISTANCE = 0.3f; -const float MIRROR_REARVIEW_BODY_DISTANCE = 1.f; +const float MIRROR_FULLSCREEN_DISTANCE = 0.35f; +const float MIRROR_REARVIEW_DISTANCE = 0.65f; +const float MIRROR_REARVIEW_BODY_DISTANCE = 2.3f; void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message) { diff --git a/interface/src/BendyLine.cpp b/interface/src/BendyLine.cpp deleted file mode 100644 index 8aca07dfac..0000000000 --- a/interface/src/BendyLine.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// -// BendyLine.cpp -// interface -// -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. - -#include "BendyLine.h" -#include "Util.h" -#include "world.h" - -const float DEFAULT_BENDY_LINE_SPRING_FORCE = 10.0f; -const float DEFAULT_BENDY_LINE_TORQUE_FORCE = 0.1f; -const float DEFAULT_BENDY_LINE_DRAG = 10.0f; -const float DEFAULT_BENDY_LINE_LENGTH = 0.09f; -const float DEFAULT_BENDY_LINE_THICKNESS = 0.03f; - -BendyLine::BendyLine(){ - - _springForce = DEFAULT_BENDY_LINE_SPRING_FORCE; - _torqueForce = DEFAULT_BENDY_LINE_TORQUE_FORCE; - _drag = DEFAULT_BENDY_LINE_DRAG; - _length = DEFAULT_BENDY_LINE_LENGTH; - _thickness = DEFAULT_BENDY_LINE_THICKNESS; - - _gravityForce = glm::vec3(0.0f, 0.0f, 0.0f); - _basePosition = glm::vec3(0.0f, 0.0f, 0.0f); - _baseDirection = glm::vec3(0.0f, 1.0f, 0.0f); - _midPosition = glm::vec3(0.0f, 0.0f, 0.0f); - _endPosition = glm::vec3(0.0f, 0.0f, 0.0f); - _midVelocity = glm::vec3(0.0f, 0.0f, 0.0f); - _endVelocity = glm::vec3(0.0f, 0.0f, 0.0f); -} - -void BendyLine::reset() { - - _midPosition = _basePosition + _baseDirection * _length * ONE_HALF; - _endPosition = _midPosition + _baseDirection * _length * ONE_HALF; - _midVelocity = glm::vec3(0.0f, 0.0f, 0.0f); - _endVelocity = glm::vec3(0.0f, 0.0f, 0.0f); -} - -void BendyLine::update(float deltaTime) { - - glm::vec3 midAxis = _midPosition - _basePosition; - glm::vec3 endAxis = _endPosition - _midPosition; - - float midLength = glm::length(midAxis); - float endLength = glm::length(endAxis); - - glm::vec3 midDirection; - glm::vec3 endDirection; - - if (midLength > 0.0f) { - midDirection = midAxis / midLength; - } else { - midDirection = _baseDirection; - } - - if (endLength > 0.0f) { - endDirection = endAxis / endLength; - } else { - endDirection = _baseDirection; - } - - // add spring force - float midForce = midLength - _length * ONE_HALF; - float endForce = endLength - _length * ONE_HALF; - _midVelocity -= midDirection * midForce * _springForce * deltaTime; - _endVelocity -= endDirection * endForce * _springForce * deltaTime; - - // add gravity force - _midVelocity += _gravityForce; - _endVelocity += _gravityForce; - - // add torque force - _midVelocity += _baseDirection * _torqueForce * deltaTime; - _endVelocity += midDirection * _torqueForce * deltaTime; - - // add drag force - float momentum = 1.0f - (_drag * deltaTime); - if (momentum < 0.0f) { - _midVelocity = glm::vec3(0.0f, 0.0f, 0.0f); - _endVelocity = glm::vec3(0.0f, 0.0f, 0.0f); - } else { - _midVelocity *= momentum; - _endVelocity *= momentum; - } - - // update position by velocity - _midPosition += _midVelocity; - _endPosition += _endVelocity; - - // clamp lengths - glm::vec3 newMidVector = _midPosition - _basePosition; - glm::vec3 newEndVector = _endPosition - _midPosition; - - float newMidLength = glm::length(newMidVector); - float newEndLength = glm::length(newEndVector); - - glm::vec3 newMidDirection; - glm::vec3 newEndDirection; - - if (newMidLength > 0.0f) { - newMidDirection = newMidVector/newMidLength; - } else { - newMidDirection = _baseDirection; - } - - if (newEndLength > 0.0f) { - newEndDirection = newEndVector/newEndLength; - } else { - newEndDirection = _baseDirection; - } - - _endPosition = _midPosition + newEndDirection * _length * ONE_HALF; - _midPosition = _basePosition + newMidDirection * _length * ONE_HALF; -} - - diff --git a/interface/src/BendyLine.h b/interface/src/BendyLine.h deleted file mode 100644 index 47a86595ff..0000000000 --- a/interface/src/BendyLine.h +++ /dev/null @@ -1,52 +0,0 @@ -// -// BendyLine.h -// interface -// -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -#ifndef hifi_bendyLine_h -#define hifi_bendyLine_h - -#include -#include -#include - -class BendyLine { -public: - BendyLine(); - - void update(float deltaTime); - void reset(); - - void setLength (float length ) { _length = length; } - void setThickness (float thickness ) { _thickness = thickness; } - void setSpringForce (float springForce ) { _springForce = springForce; } - void setTorqueForce (float torqueForce ) { _torqueForce = torqueForce; } - void setDrag (float drag ) { _drag = drag; } - void setBasePosition (glm::vec3 basePosition ) { _basePosition = basePosition; } - void setBaseDirection(glm::vec3 baseDirection) { _baseDirection = baseDirection;} - void setGravityForce (glm::vec3 gravityForce ) { _gravityForce = gravityForce; } - - glm::vec3 getBasePosition() { return _basePosition; } - glm::vec3 getMidPosition () { return _midPosition; } - glm::vec3 getEndPosition () { return _endPosition; } - float getThickness () { return _thickness; } - -private: - - float _springForce; - float _torqueForce; - float _drag; - float _length; - float _thickness; - glm::vec3 _gravityForce; - glm::vec3 _basePosition; - glm::vec3 _baseDirection; - glm::vec3 _midPosition; - glm::vec3 _endPosition; - glm::vec3 _midVelocity; - glm::vec3 _endVelocity; -}; - -#endif 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 9b75b78b46..2cbbd6fa51 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -19,6 +19,7 @@ using namespace std; +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; @@ -40,6 +41,7 @@ const xColor TOY_BALL_ON_SERVER_COLOR[] = { 255, 0, 255 }, }; + Hand::Hand(Avatar* owningAvatar) : HandData((AvatarData*)owningAvatar), @@ -86,10 +88,8 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f const int NEW_BALL_BUTTON = BUTTON_3; - float trigger = palm.getTrigger(); bool grabButtonPressed = ((palm.getControllerButtons() & BUTTON_FWD) || - (palm.getControllerButtons() & BUTTON_3) || - (trigger > 0.f)); + (palm.getControllerButtons() & BUTTON_3)); bool ballAlreadyInHand = _toyBallInHand[handID]; @@ -256,6 +256,10 @@ void Hand::simulate(float deltaTime, bool isMine) { _collisionAge += deltaTime; } + if (isMine) { + _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 Head& head = _owningAvatar->getHead(); @@ -280,6 +284,8 @@ void Hand::simulate(float deltaTime, bool isMine) { simulateToyBall(palm, fingerTipPosition, deltaTime); + _buckyBalls.grab(palm, fingerTipPosition, _owningAvatar->getOrientation(), deltaTime); + if (palm.getControllerButtons() & BUTTON_4) { _grabDelta += palm.getRawVelocity() * deltaTime; _grabCurrentRotation = palm.getRawRotation(); @@ -453,7 +459,7 @@ void Hand::calculateGeometry() { for (size_t f = 0; f < palm.getNumFingers(); ++f) { FingerData& finger = palm.getFingers()[f]; if (finger.isActive()) { - const float standardBallRadius = 0.010f; + const float standardBallRadius = FINGERTIP_COLLISION_RADIUS; _leapFingerTipBalls.resize(_leapFingerTipBalls.size() + 1); HandBall& ball = _leapFingerTipBalls.back(); ball.rotation = _baseOrientation; @@ -493,6 +499,11 @@ void Hand::calculateGeometry() { void Hand::render(bool isMine) { _renderAlpha = 1.0; + + if (isMine) { + _buckyBalls.render(); + } + if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) { for (int i = 0; i < getNumPalms(); i++) { PalmData& palm = getPalms()[i]; diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 60d7dd26ac..8c368a4c37 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -21,8 +21,8 @@ #include #include +#include "BuckyBalls.h" #include "InterfaceConfig.h" -#include "ParticleSystem.h" #include "world.h" #include "devices/SerialInterface.h" #include "VoxelSystem.h" @@ -31,7 +31,6 @@ class Avatar; class ProgramObject; - class Hand : public HandData { public: Hand(Avatar* owningAvatar); @@ -86,6 +85,8 @@ private: float _collisionAge; float _collisionDuration; + BuckyBalls _buckyBalls; + // private methods void setLeapHands(const std::vector& handPositions, const std::vector& handNormals); @@ -99,7 +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); - #define MAX_HANDS 2 bool _toyBallInHand[MAX_HANDS]; @@ -116,6 +116,7 @@ private: Sound _throwSound; Sound _catchSound; + }; #endif diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index b14baca3ef..8f285cfd77 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -17,7 +17,6 @@ using namespace std; -const bool USING_PHYSICAL_MOHAWK = true; const float EYE_RIGHT_OFFSET = 0.27f; const float EYE_UP_OFFSET = 0.36f; const float EYE_FRONT_OFFSET = 0.8f; @@ -73,7 +72,6 @@ Head::Head(Avatar* owningAvatar) : _bodyRotation(0.0f, 0.0f, 0.0f), _angularVelocity(0,0,0), _renderLookatVectors(false), - _mohawkInitialized(false), _saccade(0.0f, 0.0f, 0.0f), _saccadeTarget(0.0f, 0.0f, 0.0f), _leftEyeBlinkVelocity(0.0f), @@ -86,9 +84,7 @@ Head::Head(Avatar* owningAvatar) : _videoFace(this), _faceModel(this) { - if (USING_PHYSICAL_MOHAWK) { - resetHairPhysics(); - } + } void Head::init() { @@ -111,29 +107,10 @@ void Head::reset() { _yaw = _pitch = _roll = 0.0f; _mousePitch = 0.0f; _leanForward = _leanSideways = 0.0f; - - if (USING_PHYSICAL_MOHAWK) { - resetHairPhysics(); - } - _faceModel.reset(); } -void Head::resetHairPhysics() { - for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { - for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { - _hairTuft[t].setSpringForce (HAIR_SPRING_FORCE); - _hairTuft[t].setTorqueForce (HAIR_TORQUE_FORCE); - _hairTuft[t].setGravityForce (HAIR_GRAVITY_FORCE * _gravity); - _hairTuft[t].setDrag (HAIR_DRAG); - _hairTuft[t].setLength (_scale * HAIR_LENGTH ); - _hairTuft[t].setThickness (_scale * HAIR_THICKNESS); - _hairTuft[t].setBaseDirection(getUpDirection()); - _hairTuft[t].reset(); - } - } -} void Head::simulate(float deltaTime, bool isMine) { @@ -240,11 +217,6 @@ void Head::simulate(float deltaTime, bool isMine) { glm::clamp(sqrt(_averageLoudness * JAW_OPEN_SCALE) - JAW_OPEN_DEAD_ZONE, 0.0f, 1.0f), _blendshapeCoefficients); } - // based on the nature of the lookat position, determine if the eyes can look / are looking at it. - if (USING_PHYSICAL_MOHAWK) { - updateHairPhysics(deltaTime); - } - _faceModel.simulate(deltaTime); calculateGeometry(); @@ -304,7 +276,6 @@ void Head::render(float alpha, bool renderAvatarBalls) { glEnable(GL_DEPTH_TEST); glEnable(GL_RESCALE_NORMAL); - renderMohawk(); renderHeadSphere(); renderEyeBalls(); renderEars(); @@ -326,16 +297,6 @@ void Head::setScale (float scale) { return; } _scale = scale; - - createMohawk(); - - if (USING_PHYSICAL_MOHAWK) { - for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { - - _hairTuft[t].setLength (_scale * HAIR_LENGTH ); - _hairTuft[t].setThickness(_scale * HAIR_THICKNESS); - } - } } void Head::setMousePitch(float mousePitch) { @@ -343,79 +304,7 @@ void Head::setMousePitch(float mousePitch) { _mousePitch = glm::clamp(mousePitch, -MAX_PITCH, MAX_PITCH); } -void Head::createMohawk() { - srand(time(NULL)); - float height = _scale * (0.08f + randFloat() * 0.05f); - float variance = 0.03 + randFloat() * 0.03f; - const float RAD_PER_TRIANGLE = (2.3f + randFloat() * 0.2f) / (float)MOHAWK_TRIANGLES; - _mohawkTriangleFan[0] = glm::vec3(0, 0, 0); - glm::vec3 basicColor(randFloat(), randFloat(), randFloat()); - _mohawkColors[0] = basicColor; - - for (int i = 1; i < MOHAWK_TRIANGLES; i++) { - _mohawkTriangleFan[i] = glm::vec3((randFloat() - 0.5f) * variance, - height * cosf(i * RAD_PER_TRIANGLE - PIf / 2.f) - + (randFloat() - 0.5f) * variance, - height * sinf(i * RAD_PER_TRIANGLE - PIf / 2.f) - + (randFloat() - 0.5f) * variance); - _mohawkColors[i] = randFloat() * basicColor; - } -} - -void Head::renderMohawk() { - - if (!_mohawkInitialized) { - createMohawk(); - _mohawkInitialized = true; - } - - if (USING_PHYSICAL_MOHAWK) { - for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { - - glm::vec3 baseAxis = _hairTuft[t].getMidPosition() - _hairTuft[t].getBasePosition(); - glm::vec3 midAxis = _hairTuft[t].getEndPosition() - _hairTuft[t].getMidPosition(); - glm::vec3 viewVector = _hairTuft[t].getBasePosition() - Application::getInstance()->getCamera()->getPosition(); - - glm::vec3 basePerpendicular = glm::normalize(glm::cross(baseAxis, viewVector)); - glm::vec3 midPerpendicular = glm::normalize(glm::cross(midAxis, viewVector)); - - glm::vec3 base1 = _hairTuft[t].getBasePosition() - basePerpendicular * _hairTuft[t].getThickness() * ONE_HALF; - glm::vec3 base2 = _hairTuft[t].getBasePosition() + basePerpendicular * _hairTuft[t].getThickness() * ONE_HALF; - glm::vec3 mid1 = _hairTuft[t].getMidPosition() - midPerpendicular * _hairTuft[t].getThickness() * ONE_HALF * ONE_HALF; - glm::vec3 mid2 = _hairTuft[t].getMidPosition() + midPerpendicular * _hairTuft[t].getThickness() * ONE_HALF * ONE_HALF; - - glColor3f(_mohawkColors[t].x, _mohawkColors[t].y, _mohawkColors[t].z); - - glBegin(GL_TRIANGLES); - glVertex3f(base1.x, base1.y, base1.z ); - glVertex3f(base2.x, base2.y, base2.z ); - glVertex3f(mid1.x, mid1.y, mid1.z ); - glVertex3f(base2.x, base2.y, base2.z ); - glVertex3f(mid1.x, mid1.y, mid1.z ); - glVertex3f(mid2.x, mid2.y, mid2.z ); - glVertex3f(mid1.x, mid1.y, mid1.z ); - glVertex3f(mid2.x, mid2.y, mid2.z ); - glVertex3f(_hairTuft[t].getEndPosition().x, _hairTuft[t].getEndPosition().y, _hairTuft[t].getEndPosition().z ); - glEnd(); - } - } else { - glPushMatrix(); - glTranslatef(_position.x, _position.y, _position.z); - glRotatef(_bodyRotation.y + _yaw, 0, 1, 0); - glRotatef(-_roll, 0, 0, 1); - glRotatef(-_pitch - _bodyRotation.x, 1, 0, 0); - - glBegin(GL_TRIANGLE_FAN); - for (int i = 0; i < MOHAWK_TRIANGLES; i++) { - glColor3f(_mohawkColors[i].x, _mohawkColors[i].y, _mohawkColors[i].z); - glVertex3fv(&_mohawkTriangleFan[i].x); - glNormal3fv(&_mohawkColors[i].x); - } - glEnd(); - glPopMatrix(); - } -} glm::quat Head::getOrientation() const { return glm::quat(glm::radians(_bodyRotation)) * glm::quat(glm::radians(glm::vec3(_pitch, _yaw, _roll))); @@ -750,19 +639,4 @@ void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosi Application::getInstance()->getGlowEffect()->end(); } -void Head::updateHairPhysics(float deltaTime) { - - glm::quat orientation = getOrientation(); - glm::vec3 up = orientation * IDENTITY_UP; - glm::vec3 front = orientation * IDENTITY_FRONT; - for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { - float fraction = (float)t / (float)(NUM_HAIR_TUFTS - 1); - float angle = -20.0f + 40.0f * fraction; - float radian = angle * PI_OVER_180; - glm::vec3 baseDirection = front * sinf(radian) + up * cosf(radian); - _hairTuft[t].setBasePosition (_position + _scale * BODY_BALL_RADIUS_HEAD_BASE * 0.9f * baseDirection); - _hairTuft[t].setBaseDirection(baseDirection); - _hairTuft[t].update(deltaTime); - } -} diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index afbf06e68c..55c3dffc50 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -17,7 +17,6 @@ #include -#include "BendyLine.h" #include "FaceModel.h" #include "InterfaceConfig.h" #include "VideoFace.h" @@ -31,9 +30,6 @@ enum eyeContactTargets { MOUTH }; -const int MOHAWK_TRIANGLES = 50; -const int NUM_HAIR_TUFTS = 4; - class Avatar; class ProgramObject; @@ -45,8 +41,6 @@ public: void reset(); void simulate(float deltaTime, bool isMine); void render(float alpha, bool renderAvatarBalls); - void renderMohawk(); - void setScale(float scale); void setPosition(glm::vec3 position) { _position = position; } void setBodyRotation(glm::vec3 bodyRotation) { _bodyRotation = bodyRotation; } @@ -123,10 +117,7 @@ private: glm::vec3 _bodyRotation; glm::vec3 _angularVelocity; bool _renderLookatVectors; - BendyLine _hairTuft[NUM_HAIR_TUFTS]; - bool _mohawkInitialized; - glm::vec3 _mohawkTriangleFan[MOHAWK_TRIANGLES]; - glm::vec3 _mohawkColors[MOHAWK_TRIANGLES]; + //BendyLine _hairTuft[NUM_HAIR_TUFTS]; glm::vec3 _saccade; glm::vec3 _saccadeTarget; float _leftEyeBlinkVelocity; @@ -146,7 +137,6 @@ private: static int _eyePositionLocation; // private methods - void createMohawk(); void renderHeadSphere(); void renderEyeBalls(); void renderEyeBrows(); @@ -155,8 +145,6 @@ private: void renderMouth(); void renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition); void calculateGeometry(); - void resetHairPhysics(); - void updateHairPhysics(float deltaTime); friend class FaceModel; }; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b42a6ba165..91b88e427c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -26,11 +26,11 @@ using namespace std; const glm::vec3 DEFAULT_UP_DIRECTION(0.0f, 1.0f, 0.0f); -const float YAW_MAG = 500.0; +const float YAW_MAG = 500.0f; const float PITCH_MAG = 100.0f; const float COLLISION_RADIUS_SCALAR = 1.2; // pertains to avatar-to-avatar collisions -const float COLLISION_BALL_FORCE = 200.0; // pertains to avatar-to-avatar collisions -const float COLLISION_BODY_FORCE = 30.0; // pertains to avatar-to-avatar collisions +const float COLLISION_BALL_FORCE = 200.0f; // pertains to avatar-to-avatar collisions +const float COLLISION_BODY_FORCE = 30.0f; // pertains to avatar-to-avatar collisions const float COLLISION_RADIUS_SCALE = 0.125f; const float MOUSE_RAY_TOUCH_RANGE = 0.01f; const bool USING_HEAD_LEAN = false; @@ -575,7 +575,13 @@ void MyAvatar::renderBody(bool forceRenderHead) { } else { // Render the body's voxels and head _skeletonModel.render(1.0f); - _head.render(1.0f, false); + + // Render head so long as the camera isn't inside it + const float RENDER_HEAD_CUTOFF_DISTANCE = 0.10f; + Camera* myCamera = Application::getInstance()->getCamera(); + if (forceRenderHead || (glm::length(myCamera->getPosition() - _head.calculateAverageEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE)) { + _head.render(1.0f, false); + } } _hand.render(true); } @@ -779,7 +785,7 @@ void MyAvatar::updateCollisionWithEnvironment(float deltaTime) { glm::vec3 up = getBodyUpDirection(); float radius = _collisionRadius; const float ENVIRONMENT_SURFACE_ELASTICITY = 1.0f; - const float ENVIRONMENT_SURFACE_DAMPING = 0.01; + const float ENVIRONMENT_SURFACE_DAMPING = 0.01f; const float ENVIRONMENT_COLLISION_FREQUENCY = 0.05f; glm::vec3 penetration; if (Application::getInstance()->getEnvironment()->findCapsulePenetration( @@ -794,8 +800,8 @@ void MyAvatar::updateCollisionWithEnvironment(float deltaTime) { void MyAvatar::updateCollisionWithVoxels(float deltaTime) { float radius = _collisionRadius; - const float VOXEL_ELASTICITY = 1.4f; - const float VOXEL_DAMPING = 0.0; + const float VOXEL_ELASTICITY = 0.4f; + const float VOXEL_DAMPING = 0.0f; const float VOXEL_COLLISION_FREQUENCY = 0.5f; glm::vec3 penetration; if (Application::getInstance()->getVoxels()->findCapsulePenetration( diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index d57ce99761..9c757a1e45 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -102,7 +102,7 @@ void SixenseManager::update(float deltaTime) { FingerData finger(palm, &hand); finger.setActive(true); finger.setRawRootPosition(position); - const float FINGER_LENGTH = 300.0f; // Millimeters + const float FINGER_LENGTH = 150.0f; // Millimeters const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH); const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR; finger.setRawTipPosition(position + rotation * FINGER_VECTOR); diff --git a/libraries/audio/src/AudioInjectorOptions.h b/libraries/audio/src/AudioInjectorOptions.h index 7da0c9f2a0..0c70ad43cb 100644 --- a/libraries/audio/src/AudioInjectorOptions.h +++ b/libraries/audio/src/AudioInjectorOptions.h @@ -22,6 +22,7 @@ class AudioInjectorOptions : public QObject { Q_OBJECT Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition) + Q_PROPERTY(float volume READ getVolume WRITE setVolume) public: AudioInjectorOptions(QObject* parent = 0); AudioInjectorOptions(const AudioInjectorOptions& other); diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index 173bd0738b..1e1f3955fe 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -69,9 +69,9 @@ void ParticleCollisionSystem::checkParticle(Particle* particle) { void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) { glm::vec3 center = particle->getPosition() * static_cast(TREE_SCALE); float radius = particle->getRadius() * static_cast(TREE_SCALE); - const float VOXEL_ELASTICITY = 0.4f; // fraction of momentum conserved at collision - const float VOXEL_DAMPING = 0.0f; - const float VOXEL_COLLISION_FREQUENCY = 0.5f; + const float ELASTICITY = 0.4f; + const float DAMPING = 0.0f; + const float COLLISION_FREQUENCY = 0.5f; glm::vec3 penetration; VoxelDetail* voxelDetails = NULL; if (_voxels->findSpherePenetration(center, radius, penetration, (void**)&voxelDetails)) { @@ -79,9 +79,9 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) { // let the particles run their collision scripts if they have them particle->collisionWithVoxel(voxelDetails); - penetration /= (float)TREE_SCALE; - updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY); - applyHardCollision(particle, penetration, VOXEL_ELASTICITY, VOXEL_DAMPING); + penetration /= static_cast(TREE_SCALE); + updateCollisionSound(particle, penetration, COLLISION_FREQUENCY); + applyHardCollision(particle, penetration, ELASTICITY, DAMPING); delete voxelDetails; // cleanup returned details } @@ -90,9 +90,9 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) { void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) { glm::vec3 center = particle->getPosition() * static_cast(TREE_SCALE); float radius = particle->getRadius() * static_cast(TREE_SCALE); - const float VOXEL_ELASTICITY = 1.4f; - const float VOXEL_DAMPING = 0.0f; - const float VOXEL_COLLISION_FREQUENCY = 0.5f; + const float ELASTICITY = 1.4f; + const float DAMPING = 0.0f; + const float COLLISION_FREQUENCY = 0.5f; glm::vec3 penetration; Particle* penetratedParticle; if (_particles->findSpherePenetration(center, radius, penetration, (void**)&penetratedParticle)) { @@ -101,8 +101,9 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) { particle->collisionWithParticle(penetratedParticle); penetratedParticle->collisionWithParticle(particle); - penetration /= (float)TREE_SCALE; - updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY); + penetration /= static_cast(TREE_SCALE); + updateCollisionSound(particle, penetration, COLLISION_FREQUENCY); + // apply a hard collision to both particles of half the penetration each float particleShare, penetratedParticleShare; @@ -119,8 +120,8 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) { particleShare = 0.5f; penetratedParticleShare = -0.5f; } - applyHardCollision(particle, penetration * particleShare, VOXEL_ELASTICITY, VOXEL_DAMPING); - applyHardCollision(penetratedParticle, penetration * penetratedParticleShare, VOXEL_ELASTICITY, VOXEL_DAMPING); + applyHardCollision(particle, penetration * particleShare, ELASTICITY, DAMPING); + applyHardCollision(penetratedParticle, penetration * penetratedParticleShare, ELASTICITY, DAMPING); } } @@ -134,9 +135,9 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { //printf("updateCollisionWithAvatars()...\n"); glm::vec3 center = particle->getPosition() * static_cast(TREE_SCALE); float radius = particle->getRadius() * static_cast(TREE_SCALE); - const float VOXEL_ELASTICITY = 1.4f; - const float VOXEL_DAMPING = 0.0f; - const float VOXEL_COLLISION_FREQUENCY = 0.5f; + const float ELASTICITY = 0.4f; + const float DAMPING = 0.0f; + const float COLLISION_FREQUENCY = 0.5f; glm::vec3 penetration; const PalmData* collidingPalm = NULL; @@ -155,8 +156,8 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) { // TODO: dot collidingPalm and hand velocities and skip collision when they are moving apart. // apply a hard collision when ball collides with hand - penetration /= (float)TREE_SCALE; - updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY); + penetration /= static_cast(TREE_SCALE); + updateCollisionSound(particle, penetration, COLLISION_FREQUENCY); // determine if the palm that collided was moving, if so, then we add that palm velocity as well... glm::vec3 addedVelocity = NO_ADDED_VELOCITY; @@ -166,13 +167,13 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { addedVelocity = palmVelocity; } - applyHardCollision(particle, penetration, VOXEL_ELASTICITY, VOXEL_DAMPING, addedVelocity); + applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity); } else if (avatar->findSpherePenetration(center, radius, penetration)) { // apply hard collision when particle collides with avatar - penetration /= (float)TREE_SCALE; - updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY); + penetration /= static_cast(TREE_SCALE); + updateCollisionSound(particle, penetration, COLLISION_FREQUENCY); glm::vec3 addedVelocity = avatar->getVelocity(); - applyHardCollision(particle, penetration, VOXEL_ELASTICITY, VOXEL_DAMPING, addedVelocity); + applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity); } } @@ -190,8 +191,8 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) { // apply a hard collision when ball collides with hand - penetration /= (float)TREE_SCALE; - updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY); + penetration /= static_cast(TREE_SCALE); + updateCollisionSound(particle, penetration, COLLISION_FREQUENCY); // determine if the palm that collided was moving, if so, then we add that palm velocity as well... glm::vec3 addedVelocity = NO_ADDED_VELOCITY; @@ -201,13 +202,13 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { addedVelocity = palmVelocity; } - applyHardCollision(particle, penetration, VOXEL_ELASTICITY, VOXEL_DAMPING, addedVelocity); + applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity); } else if (avatar->findSpherePenetration(center, radius, penetration)) { - penetration /= (float)TREE_SCALE; - updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY); + penetration /= static_cast(TREE_SCALE); + updateCollisionSound(particle, penetration, COLLISION_FREQUENCY); glm::vec3 addedVelocity = avatar->getVelocity(); - applyHardCollision(particle, penetration, VOXEL_ELASTICITY, VOXEL_DAMPING, addedVelocity); + applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity); } } }