overte/interface/src/avatar/Hand.cpp

898 lines
42 KiB
C++
Executable file

//
// Hand.cpp
// interface
//
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include <QImage>
#include <NodeList.h>
#include "Application.h"
#include "Avatar.h"
#include "Hand.h"
#include "Menu.h"
#include "Util.h"
#include "renderer/ProgramObject.h"
using namespace std;
Hand::Hand(Avatar* owningAvatar) :
HandData((AvatarData*)owningAvatar),
_raveGloveClock(0.0f),
_raveGloveInitialized(false),
_owningAvatar(owningAvatar),
_renderAlpha(1.0),
_ballColor(0.0, 0.0, 0.4),
_collisionCenter(0,0,0),
_collisionAge(0),
_collisionDuration(0)
{
// initialize all finger particle emitters with an invalid id as default
for (int f = 0; f< NUM_FINGERS; f ++ ) {
_raveGloveEmitter[f] = NULL_EMITTER;
}
}
void Hand::init() {
// Different colors for my hand and others' hands
if (_owningAvatar && _owningAvatar->getOwningNode() == NULL) {
_ballColor = glm::vec3(0.0, 0.4, 0.0);
}
else {
_ballColor = glm::vec3(0.0, 0.0, 0.4);
}
_raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_FIRE;
_raveGloveEffectsModeChanged = false;
}
void Hand::reset() {
}
void Hand::simulate(float deltaTime, bool isMine) {
if (_collisionAge > 0.f) {
_collisionAge += deltaTime;
}
calculateGeometry();
if (_isRaveGloveActive) {
if (_raveGloveEffectsModeChanged && _raveGloveInitialized) {
activateNewRaveGloveMode();
_raveGloveEffectsModeChanged = false;
}
updateRaveGloveParticles(deltaTime);
}
// Create a voxel at fingertip if controller button is pressed
const float FINGERTIP_VOXEL_SIZE = 0.0125;
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
if (palm.isActive()) {
FingerData& finger = palm.getFingers()[0]; // Sixense has only one finger
glm::vec3 fingerTipPosition = finger.getTipPosition();
if (palm.getControllerButtons() & BUTTON_1) {
if (glm::length(fingerTipPosition - _lastFingerAddVoxel) > (FINGERTIP_VOXEL_SIZE / 2.f)) {
QColor paintColor = Menu::getInstance()->getActionForOption(MenuOption::VoxelPaintColor)->data().value<QColor>();
Application::getInstance()->makeVoxel(fingerTipPosition,
FINGERTIP_VOXEL_SIZE,
paintColor.red(),
paintColor.green(),
paintColor.blue(),
true);
_lastFingerAddVoxel = fingerTipPosition;
}
} else if (palm.getControllerButtons() & BUTTON_2) {
if (glm::length(fingerTipPosition - _lastFingerDeleteVoxel) > (FINGERTIP_VOXEL_SIZE / 2.f)) {
Application::getInstance()->removeVoxel(fingerTipPosition, FINGERTIP_VOXEL_SIZE);
_lastFingerDeleteVoxel = fingerTipPosition;
}
}
// Check if the finger is intersecting with a voxel in the client voxel tree
VoxelTreeElement* fingerNode = Application::getInstance()->getVoxels()->getVoxelEnclosing(
glm::vec3(fingerTipPosition / (float)TREE_SCALE));
if (fingerNode) {
if (!palm.getIsCollidingWithVoxel()) {
// Collision has just started
palm.setIsCollidingWithVoxel(true);
handleVoxelCollision(&palm, fingerTipPosition, fingerNode, deltaTime);
// Set highlight voxel
VoxelDetail voxel;
glm::vec3 pos = fingerNode->getCorner();
voxel.x = pos.x;
voxel.y = pos.y;
voxel.z = pos.z;
voxel.s = fingerNode->getScale();
voxel.red = fingerNode->getColor()[0];
voxel.green = fingerNode->getColor()[1];
voxel.blue = fingerNode->getColor()[2];
Application::getInstance()->setHighlightVoxel(voxel);
Application::getInstance()->setIsHighlightVoxel(true);
}
} else {
if (palm.getIsCollidingWithVoxel()) {
// Collision has just ended
palm.setIsCollidingWithVoxel(false);
Application::getInstance()->setIsHighlightVoxel(false);
}
}
}
}
}
void Hand::handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPosition, VoxelTreeElement* voxel, float deltaTime) {
// Collision between finger and a voxel plays sound
const float LOWEST_FREQUENCY = 100.f;
const float HERTZ_PER_RGB = 3.f;
const float DECAY_PER_SAMPLE = 0.0005f;
const float DURATION_MAX = 2.0f;
const float MIN_VOLUME = 0.1f;
float volume = MIN_VOLUME + glm::clamp(glm::length(palm->getVelocity()), 0.f, (1.f - MIN_VOLUME));
float duration = volume;
_collisionCenter = fingerTipPosition;
_collisionAge = deltaTime;
_collisionDuration = duration;
int voxelBrightness = voxel->getColor()[0] + voxel->getColor()[1] + voxel->getColor()[2];
float frequency = LOWEST_FREQUENCY + (voxelBrightness * HERTZ_PER_RGB);
Application::getInstance()->getAudio()->startDrumSound(volume,
frequency,
DURATION_MAX,
DECAY_PER_SAMPLE);
}
void Hand::calculateGeometry() {
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();
_baseOrientation = _owningAvatar->getOrientation();
_basePosition = head.calculateAverageEyePosition() + _baseOrientation * leapHandsOffsetFromFace * head.getScale();
// use position to obtain the left and right palm indices
int leftPalmIndex, rightPalmIndex;
getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex);
// check for collisions
for (int i = 0; i < getNumPalms(); i++) {
PalmData& palm = getPalms()[i];
if (!palm.isActive()) {
continue;
}
const float PALM_RADIUS = 0.01f;
glm::vec3 penetration;
const Model& skeletonModel = _owningAvatar->getSkeletonModel();
int skipIndex = skeletonModel.getParentJointIndex(
(i == leftPalmIndex) ? skeletonModel.getLeftHandJointIndex() :
(i == rightPalmIndex) ? skeletonModel.getRightHandJointIndex() : -1);
if (skeletonModel.findSpherePenetration(palm.getPosition(),
PALM_RADIUS * _owningAvatar->getScale(), penetration, skipIndex)) {
palm.addToPosition(-penetration);
}
}
// generate finger tip balls....
_leapFingerTipBalls.clear();
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
if (palm.isActive()) {
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
FingerData& finger = palm.getFingers()[f];
if (finger.isActive()) {
const float standardBallRadius = 0.010f;
_leapFingerTipBalls.resize(_leapFingerTipBalls.size() + 1);
HandBall& ball = _leapFingerTipBalls.back();
ball.rotation = _baseOrientation;
ball.position = finger.getTipPosition();
ball.radius = standardBallRadius;
ball.touchForce = 0.0;
ball.isCollidable = true;
ball.isColliding = false;
}
}
}
}
// generate finger root balls....
_leapFingerRootBalls.clear();
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
if (palm.isActive()) {
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
FingerData& finger = palm.getFingers()[f];
if (finger.isActive()) {
const float standardBallRadius = 0.005f;
_leapFingerRootBalls.resize(_leapFingerRootBalls.size() + 1);
HandBall& ball = _leapFingerRootBalls.back();
ball.rotation = _baseOrientation;
ball.position = finger.getRootPosition();
ball.radius = standardBallRadius;
ball.touchForce = 0.0;
ball.isCollidable = true;
ball.isColliding = false;
}
}
}
}
}
void Hand::setRaveGloveEffectsMode(QKeyEvent* event) {
_raveGloveEffectsModeChanged = true;
switch (event->key()) {
case Qt::Key_0: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR; break;
case Qt::Key_1: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_TRAILS; break;
case Qt::Key_2: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_FIRE; break;
case Qt::Key_3: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_WATER; break;
case Qt::Key_4: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_FLASHY; break;
case Qt::Key_5: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_BOZO_SPARKLER; break;
case Qt::Key_6: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_LONG_SPARKLER; break;
case Qt::Key_7: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_SNAKE; break;
case Qt::Key_8: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_PULSE; break;
case Qt::Key_9: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_THROB; break;
};
}
void Hand::render() {
_renderAlpha = 1.0;
if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayLeapHands)) {
if (!isRaveGloveActive()) {
renderLeapFingerTrails();
}
if (isRaveGloveActive()) {
// Use mood lighting for the hand itself
setRaveLights(RAVE_LIGHTS_AVATAR);
}
renderLeapHands();
}
if (_isRaveGloveActive) {
if (_raveGloveInitialized) {
updateRaveGloveEmitters(); // do this after calculateGeometry
// Use normal lighting for the particles
setRaveLights(RAVE_LIGHTS_PARTICLES);
_raveGloveParticleSystem.render();
}
}
// If hand/voxel collision has happened, render a little expanding sphere
if (_collisionAge > 0.f) {
float opacity = glm::clamp(1.f - (_collisionAge / _collisionDuration), 0.f, 1.f);
glColor4f(1, 0, 0, 0.5 * opacity);
glPushMatrix();
glTranslatef(_collisionCenter.x, _collisionCenter.y, _collisionCenter.z);
glutSolidSphere(_collisionAge * 0.25f, 20, 20);
glPopMatrix();
if (_collisionAge > _collisionDuration) {
_collisionAge = 0.f;
}
}
// If hand controller buttons pressed, render stuff as needed
if (getPalms().size() > 0) {
for (size_t i = 0; i < getPalms().size(); ++i) {
PalmData& palm = getPalms()[i];
// If trigger pulled, thrust in that direction and draw beam
const float MAX_THRUSTER_BEAM_LENGTH = 5.f;
const float THRUSTER_MARKER_SIZE = 0.0125f;
if (palm.getJoystickY() != 0.f) {
FingerData& finger = palm.getFingers()[0];
if (finger.isActive()) {
if (palm.getJoystickY() > 0.f) {
glColor3f(0, 1, 0);
} else {
glColor3f(1, 0, 0);
}
glm::vec3 palmPosition = palm.getPosition();
glm::vec3 pointerPosition = palmPosition +
glm::normalize(finger.getTipPosition() - palmPosition) *
MAX_THRUSTER_BEAM_LENGTH;
glPushMatrix();
glm::vec3 markerPosition = palmPosition +
glm::normalize(finger.getTipPosition() - palmPosition) *
MAX_THRUSTER_BEAM_LENGTH *
(0.5f + palm.getJoystickY() / 2.f);
glTranslatef(markerPosition.x, markerPosition.y, markerPosition.z);
glutSolidSphere(THRUSTER_MARKER_SIZE, 10, 10);
glPopMatrix();
glLineWidth(2.0);
glBegin(GL_LINES);
glVertex3f(palmPosition.x, palmPosition.y, palmPosition.z);
glVertex3f(pointerPosition.x, pointerPosition.y, pointerPosition.z);
glEnd();
}
}
}
}
glEnable(GL_DEPTH_TEST);
glEnable(GL_RESCALE_NORMAL);
}
void Hand::setRaveLights(RaveLightsSetting setting) {
if (setting == RAVE_LIGHTS_AVATAR) {
// Set some mood lighting
GLfloat ambient_color[] = { 0.0, 0.0, 0.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color);
GLfloat diffuse_color[] = { 0.4, 0.0, 0.0 };
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color);
GLfloat specular_color[] = { 0.0, 0.0, 0.0, 0.0};
glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color);
glMateriali(GL_FRONT, GL_SHININESS, 0);
}
else if (setting == RAVE_LIGHTS_PARTICLES) {
// particles use a brighter light setting
GLfloat ambient_color[] = { 0.7, 0.7, 0.8 };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color);
GLfloat diffuse_color[] = { 0.8, 0.7, 0.7 };
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color);
GLfloat specular_color[] = { 1.0, 1.0, 1.0, 1.0};
glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color);
glMateriali(GL_FRONT, GL_SHININESS, 96);
}
}
void Hand::renderRaveGloveStage() {
// Draw a simple fullscreen triangle fan, darkest in the center.
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glBegin(GL_TRIANGLE_FAN);
// Dark center vertex
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
// Lighter outer vertices
glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
glVertex3f(-1.0f,-1.0f, 0.0f);
glVertex3f( 1.0f,-1.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f,-1.0f, 0.0f);
glEnd();
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
void Hand::renderLeapHands() {
const float alpha = 1.0f;
//const glm::vec3 handColor = _ballColor;
const glm::vec3 handColor(1.0, 0.84, 0.66); // use the skin color
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glPushMatrix();
// Draw the leap balls
for (size_t i = 0; i < _leapFingerTipBalls.size(); i++) {
if (alpha > 0.0f) {
if (_leapFingerTipBalls[i].isColliding) {
glColor4f(handColor.r, 0, 0, alpha);
} else {
glColor4f(handColor.r, handColor.g, handColor.b, alpha);
}
glPushMatrix();
glTranslatef(_leapFingerTipBalls[i].position.x, _leapFingerTipBalls[i].position.y, _leapFingerTipBalls[i].position.z);
glutSolidSphere(_leapFingerTipBalls[i].radius, 20.0f, 20.0f);
glPopMatrix();
}
}
// Draw the finger root cones
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
if (palm.isActive()) {
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
FingerData& finger = palm.getFingers()[f];
if (finger.isActive()) {
glColor4f(handColor.r, handColor.g, handColor.b, 0.5);
glm::vec3 tip = finger.getTipPosition();
glm::vec3 root = finger.getRootPosition();
Avatar::renderJointConnectingCone(root, tip, 0.001, 0.003);
}
}
}
}
// Draw the palms
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
if (palm.isActive()) {
const float palmThickness = 0.02f;
glColor4f(handColor.r, handColor.g, handColor.b, 0.25);
glm::vec3 tip = palm.getPosition();
glm::vec3 root = palm.getPosition() + palm.getNormal() * palmThickness;
Avatar::renderJointConnectingCone(root, tip, 0.05, 0.03);
}
}
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glPopMatrix();
}
void Hand::renderLeapFingerTrails() {
// Draw the finger root cones
glDisable(GL_LIGHTING);
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
if (palm.isActive()) {
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
FingerData& finger = palm.getFingers()[f];
int numPositions = finger.getTrailNumPositions() - 1;
if (numPositions > 0) {
glBegin(GL_TRIANGLE_STRIP);
for (int t = 0; t < numPositions; ++t)
{
const glm::vec3& center = finger.getTrailPosition(t);
const float halfWidth = 0.004f;
const glm::vec3 edgeDirection(1.0f, 0.0f, 0.0f);
glm::vec3 edge0 = center + edgeDirection * halfWidth;
glm::vec3 edge1 = center - edgeDirection * halfWidth;
float alpha = 1.0f - ((float)t / (float)(numPositions - 1));
alpha *= 0.25f;
glColor4f(1.0f, 1.0f, 1.0f, alpha);
glVertex3fv((float*)&edge0);
glVertex3fv((float*)&edge1);
}
glEnd();
}
}
}
}
glEnable(GL_LIGHTING);
}
void Hand::setLeapHands(const std::vector<glm::vec3>& handPositions,
const std::vector<glm::vec3>& handNormals) {
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
if (i < handPositions.size()) {
palm.setActive(true);
palm.setRawPosition(handPositions[i]);
palm.setRawNormal(handNormals[i]);
}
else {
palm.setActive(false);
}
}
}
// call this soon after the geometry of the leap hands are set
void Hand::updateRaveGloveEmitters() {
int emitterIndex = 0;
for (size_t i = 0; i < NUM_FINGERS; i++) {
_raveGloveParticleSystem.setEmitterActive(_raveGloveEmitter[i], false);
}
for (size_t palmIndex = 0; palmIndex < getNumPalms(); ++palmIndex) {
PalmData& palm = getPalms()[palmIndex];
if (palm.isActive()) {
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
FingerData& finger = palm.getFingers()[f];
if (finger.isActive()) {
if (emitterIndex < NUM_FINGERS) { // safety, stop at the array size
glm::vec3 fingerDirection = finger.getTipPosition() - finger.getRootPosition();
float fingerLength = glm::length(fingerDirection);
if (fingerLength > 0.0f) {
fingerDirection /= fingerLength;
} else {
fingerDirection = IDENTITY_UP;
}
_raveGloveParticleSystem.setEmitterActive (_raveGloveEmitter[emitterIndex], true);
_raveGloveParticleSystem.setEmitterPosition (_raveGloveEmitter[emitterIndex], finger.getTipPosition());
_raveGloveParticleSystem.setEmitterDirection(_raveGloveEmitter[emitterIndex], fingerDirection);
}
}
emitterIndex++;
}
}
}
}
// call this from within the simulate method
void Hand::updateRaveGloveParticles(float deltaTime) {
if (!_raveGloveInitialized) {
// start up the rave glove finger particles...
for ( int f = 0; f< NUM_FINGERS; f ++ ) {
_raveGloveEmitter[f] = _raveGloveParticleSystem.addEmitter();
assert( _raveGloveEmitter[f] >= 0 );
assert( _raveGloveEmitter[f] != NULL_EMITTER );
}
setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_FIRE);
activateNewRaveGloveMode();
_raveGloveParticleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f));
_raveGloveInitialized = true;
} else {
_raveGloveParticleSystem.simulate(deltaTime);
}
}
// The rave glove mode has changed, so activate the effects.
void Hand::activateNewRaveGloveMode() {
if (!_raveGloveInitialized) {
return;
}
int mode = _raveGloveEffectsMode;
_raveGloveParticleSystem.killAllParticles();
for ( int f = 0; f< NUM_FINGERS; f ++ ) {
ParticleSystem::ParticleAttributes attributes;
//-----------------------------------------
// throbbing color cycle
//-----------------------------------------
if (mode == RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR) {
_raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE );
_raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], true );
_raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 0.03f );
_raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.0f );
_raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 30.0f );
_raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 20 );
_raveGloveParticleSystem.setParticleAttributesToDefault(&attributes);
attributes.modulationAmplitude = 1.0;
attributes.modulationRate = 0.33;
attributes.modulationStyle = COLOR_MODULATION_STYLE_RAINBOW_CYCLE;
attributes.color = glm::vec4( 0.5f, 0.5f, 0.5f, 1.0f);
attributes.radius = 0.02f;
attributes.gravity = 0.0f;
attributes.airFriction = 0.0f;
attributes.jitter = 0.0f;
attributes.bounce = 0.0f;
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes);
//-----------------------------------------
// trails
//-----------------------------------------
} else if (mode == RAVE_GLOVE_EFFECTS_MODE_TRAILS) {
_raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_RIBBON );
_raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], false );
_raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 1.0f );
_raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.0f );
_raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 50.0f );
_raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 5 );
_raveGloveParticleSystem.setParticleAttributesToDefault(&attributes);
attributes.radius = 0.001f;
attributes.color = glm::vec4( 1.0f, 0.5f, 0.2f, 1.0f);
attributes.gravity = 0.005f;
attributes.airFriction = 0.0f;
attributes.jitter = 0.0f;
attributes.bounce = 0.0f;
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes);
attributes.radius = 0.002f;
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes);
attributes.color = glm::vec4( 1.0f, 0.2f, 0.2f, 0.5f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes);
attributes.color = glm::vec4( 1.0f, 0.2f, 0.2f, 0.0f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes);
}
//-----------------------------------------
// Fire!
//-----------------------------------------
if (mode == RAVE_GLOVE_EFFECTS_MODE_FIRE) {
_raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE );
_raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], false );
_raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 1.0f );
_raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.002f );
_raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 120.0 );
_raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 6 );
_raveGloveParticleSystem.setParticleAttributesToDefault(&attributes);
attributes.radius = 0.005f;
attributes.color = glm::vec4( 1.0f, 1.0f, 0.5f, 0.5f);
attributes.airFriction = 0.0f;
attributes.jitter = 0.003f;
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes);
attributes.radius = 0.01f;
attributes.jitter = 0.0f;
attributes.gravity = -0.005f;
attributes.color = glm::vec4( 1.0f, 0.2f, 0.0f, 0.4f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes);
attributes.radius = 0.01f;
attributes.gravity = 0.0f;
attributes.color = glm::vec4( 0.4f, 0.4f, 0.4f, 0.2f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes);
attributes.radius = 0.02f;
attributes.color = glm::vec4( 0.4f, 0.6f, 0.9f, 0.0f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes);
//-----------------------------------------
// water
//-----------------------------------------
} else if (mode == RAVE_GLOVE_EFFECTS_MODE_WATER) {
_raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE );
_raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], true );
_raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 0.6f );
_raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.001f );
_raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 100.0 );
_raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 5 );
_raveGloveParticleSystem.setParticleAttributesToDefault(&attributes);
attributes.radius = 0.001f;
attributes.color = glm::vec4( 0.8f, 0.9f, 1.0f, 0.5f);
attributes.airFriction = 0.0f;
attributes.jitter = 0.004f;
attributes.bounce = 1.0f;
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes);
attributes.gravity = 0.01f;
attributes.jitter = 0.0f;
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes);
attributes.color = glm::vec4( 0.8f, 0.9f, 1.0f, 0.2f);
attributes.radius = 0.002f;
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes);
attributes.color = glm::vec4( 0.8f, 0.9f, 1.0f, 0.0f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes);
//-----------------------------------------
// flashy
//-----------------------------------------
} else if (mode == RAVE_GLOVE_EFFECTS_MODE_FLASHY) {
_raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE );
_raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], true );
_raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 0.1 );
_raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.002f );
_raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 100.0 );
_raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 12 );
_raveGloveParticleSystem.setParticleAttributesToDefault(&attributes);
attributes.radius = 0.0f;
attributes.color = glm::vec4( 1.0f, 1.0f, 1.0f, 1.0f);
attributes.airFriction = 0.0f;
attributes.jitter = 0.05f;
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes);
attributes.radius = 0.01f;
attributes.color = glm::vec4( 1.0f, 1.0f, 0.0f, 1.0f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes);
attributes.radius = 0.01f;
attributes.color = glm::vec4( 1.0f, 0.0f, 1.0f, 1.0f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes);
attributes.radius = 0.01f;
attributes.color = glm::vec4( 0.0f, 0.0f, 0.0f, 1.0f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes);
//-----------------------------------------
// Bozo sparkler
//-----------------------------------------
} else if (mode == RAVE_GLOVE_EFFECTS_MODE_BOZO_SPARKLER) {
_raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_RIBBON );
_raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], false );
_raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 0.2 );
_raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.002f );
_raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 100.0 );
_raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 12 );
_raveGloveParticleSystem.setParticleAttributesToDefault(&attributes);
attributes.radius = 0.0f;
attributes.color = glm::vec4( 1.0f, 1.0f, 1.0f, 1.0f);
attributes.airFriction = 0.0f;
attributes.jitter = 0.01f;
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes);
attributes.radius = 0.01f;
attributes.color = glm::vec4( 1.0f, 1.0f, 0.0f, 1.0f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes);
attributes.radius = 0.01f;
attributes.color = glm::vec4( 1.0f, 0.0f, .0f, 1.0f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes);
attributes.radius = 0.0f;
attributes.color = glm::vec4( 0.0f, 0.0f, 1.0f, 0.0f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes);
//-----------------------------------------
// long sparkler
//-----------------------------------------
} else if (mode == RAVE_GLOVE_EFFECTS_MODE_LONG_SPARKLER) {
_raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_RIBBON );
_raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], false );
_raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 1.0 );
_raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.002f );
_raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 100.0 );
_raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 7 );
_raveGloveParticleSystem.setParticleAttributesToDefault(&attributes);
attributes.color = glm::vec4( 0.3f, 0.3f, 0.3f, 0.4f);
attributes.radius = 0.0f;
attributes.airFriction = 0.0f;
attributes.jitter = 0.0001f;
attributes.bounce = 1.0f;
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes);
attributes.radius = 0.005f;
attributes.color = glm::vec4( 0.0f, 0.5f, 0.5f, 0.8f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes);
attributes.radius = 0.007f;
attributes.color = glm::vec4( 0.5f, 0.0f, 0.5f, 0.5f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes);
attributes.radius = 0.02f;
attributes.color = glm::vec4( 0.0f, 0.0f, 1.0f, 0.0f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes);
//-----------------------------------------
// bubble snake
//-----------------------------------------
} else if (mode == RAVE_GLOVE_EFFECTS_MODE_SNAKE) {
_raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE );
_raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], true );
_raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 1.0 );
_raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.002f );
_raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 100.0 );
_raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 7 );
_raveGloveParticleSystem.setParticleAttributesToDefault(&attributes);
attributes.radius = 0.001f;
attributes.color = glm::vec4( 0.5f, 1.0f, 0.5f, 1.0f);
attributes.airFriction = 0.01f;
attributes.jitter = 0.0f;
attributes.emitterAttraction = 0.0f;
attributes.tornadoForce = 1.1f;
attributes.neighborAttraction = 1.1f;
attributes.neighborRepulsion = 1.1f;
attributes.bounce = 0.0f;
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes);
attributes.radius = 0.002f;
attributes.color = glm::vec4( 1.0f, 1.0f, 1.0f, 1.0f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes);
attributes.radius = 0.003f;
attributes.color = glm::vec4( 0.3f, 0.3f, 0.3f, 0.5f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes);
attributes.radius = 0.004f;
attributes.color = glm::vec4( 0.3f, 0.3f, 0.3f, 0.0f);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes);
//-----------------------------------------
// pulse
//-----------------------------------------
} else if (mode == RAVE_GLOVE_EFFECTS_MODE_PULSE) {
_raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE );
_raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], true );
_raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 0.0 );
_raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.0f );
_raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 30.0 );
_raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 20 );
_raveGloveParticleSystem.setParticleAttributesToDefault(&attributes);
attributes.radius = 0.01f;
attributes.color = glm::vec4( 0.1f, 0.2f, 0.4f, 0.5f);
attributes.modulationAmplitude = 0.9;
attributes.modulationRate = 7.0;
attributes.modulationStyle = COLOR_MODULATION_STYLE_LIGHNTESS_PULSE;
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes);
//-----------------------------------------
// long sparkler
//-----------------------------------------
} else if (mode == RAVE_GLOVE_EFFECTS_MODE_LONG_SPARKLER) {
_raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE );
_raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], true );
_raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 0.0 );
_raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.0f );
_raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 30.0 );
_raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 20 );
_raveGloveParticleSystem.setParticleAttributesToDefault(&attributes);
attributes.radius = 0.01f;
attributes.color = glm::vec4( 0.5f, 0.4f, 0.3f, 0.5f);
attributes.modulationAmplitude = 0.3;
attributes.modulationRate = 1.0;
attributes.modulationStyle = COLOR_MODULATION_STYLE_LIGHTNESS_WAVE;
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes);
//-----------------------------------------
// throb
//-----------------------------------------
} else if (mode == RAVE_GLOVE_EFFECTS_MODE_THROB) {
_raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE );
_raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], true );
_raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 0.03 );
_raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.0f );
_raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 30.0 );
_raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 20 );
_raveGloveParticleSystem.setParticleAttributesToDefault(&attributes);
attributes.radius = 0.01f;
attributes.color = glm::vec4( 0.1f, 0.2f, 0.4f, 0.5f);
attributes.modulationAmplitude = 0.5;
attributes.modulationRate = 3.0;
attributes.modulationStyle = COLOR_MODULATION_STYLE_LIGHTNESS_WAVE;
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes);
}
}
}