// // Hand.cpp // interface // // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. #include #include #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(); 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& handPositions, const std::vector& 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); } } }