Merge branch 'master' of https://github.com/worklist/hifi into multiple_voxel_servers

This commit is contained in:
ZappoMan 2013-08-02 14:40:39 -07:00
commit db55160f9a
16 changed files with 618 additions and 159 deletions

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="152px" height="152px" viewBox="0 0 152 152" enable-background="new 0 0 152 152" xml:space="preserve">
<path fill="#333333" d="M76,13.441C41.45,13.441,13.442,41.45,13.442,76S41.45,138.558,76,138.558S138.558,110.55,138.558,76
S110.55,13.441,76,13.441z M76,107.279c-17.275,0-31.279-14.004-31.279-31.279S58.725,44.721,76,44.721S107.279,58.725,107.279,76
S93.275,107.279,76,107.279z"/>
<g id="XMLID_46_">
<g>
<path fill="#EAEAEA" d="M41.465,38.653c0.483-0.558-1.506-5.81-0.071-6.338c1.041-0.38,0.971,1.524,1.041,2.08
c0.102,1.143,0.346,2.528,0.727,3.567c0.346-1.663,0.312-3.36,0.381-5.056c0.034-0.521,0.173-1.697,0.865-1.629
c1.628,0.105-0.242,5.576,0.832,6.269c0.727-0.832,0.935-2.979,1.212-4.052c0.104-0.45,0.245-1.873,1.246-1.281
c0.763,0.451,0.138,3.291-0.103,4.19c-0.244,0.935-0.244,1.592-0.521,2.667c-0.067,0.728-0.206,1.524,0.277,2.078
c0.867,0,2.859-2.46,3.829-1.699c0.658,0.485,0.331,1.109-0.12,1.403c-3.326,2.149-2.808,4.815-4.402,5.126
c0,2.73-0.165,2.833,0.11,5.551c-1.731,0.287-3.542,0.216-5.199,0.106c0-0.001,0-0.001,0-0.001
c0.113-1.432,0.067-0.342,0.173-1.931c0.079-1.235,0.103-2.339,0.139-3.551l-0.036-0.138c-1.038-0.278-1.349-2.095-1.696-3.307
c-0.38-1.318,0.069-2.495-0.416-3.775c-0.308-0.97-1.62-3.381-0.795-4.086c0.487-0.417,0.761-0.07,1.142,0.83
C40.392,36.408,40.549,38.549,41.465,38.653z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -196,8 +196,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
_isTouchPressed(false),
_yawFromTouch(0.0f),
_pitchFromTouch(0.0f),
_groundPlaneImpact(0.0f),
_mousePressed(false),
_isHoverVoxel(false),
_isHoverVoxelSounding(false),
_mouseVoxelScale(1.0f / 1024.0f),
_justEditedVoxel(false),
_isLookingAtOtherAvatar(false),
@ -851,9 +852,16 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
deleteVoxelUnderCursor();
}
}
_pieMenu.mouseMoveEvent(_mouseX, _mouseY);
}
}
const bool MAKE_SOUND_ON_VOXEL_HOVER = false;
const bool MAKE_SOUND_ON_VOXEL_CLICK = true;
const float HOVER_VOXEL_FREQUENCY = 14080.f;
const float HOVER_VOXEL_DECAY = 0.999f;
void Application::mousePressEvent(QMouseEvent* event) {
if (activeWindow() == _window) {
if (event->button() == Qt::LeftButton) {
@ -863,7 +871,20 @@ void Application::mousePressEvent(QMouseEvent* event) {
_mouseDragStartedY = _mouseY;
_mouseVoxelDragging = _mouseVoxel;
_mousePressed = true;
maybeEditVoxelUnderCursor();
if (!maybeEditVoxelUnderCursor()) {
_pieMenu.mousePressEvent(_mouseX, _mouseY);
}
if (MAKE_SOUND_ON_VOXEL_CLICK && _isHoverVoxel && !_isHoverVoxelSounding) {
_hoverVoxelOriginalColor[0] = _hoverVoxel.red;
_hoverVoxelOriginalColor[1] = _hoverVoxel.green;
_hoverVoxelOriginalColor[2] = _hoverVoxel.blue;
_hoverVoxelOriginalColor[3] = 1;
_audio.startCollisionSound(1.0, HOVER_VOXEL_FREQUENCY * _hoverVoxel.s * TREE_SCALE, 0.0, HOVER_VOXEL_DECAY);
_isHoverVoxelSounding = true;
}
} else if (event->button() == Qt::RightButton && checkedVoxelModeAction() != 0) {
deleteVoxelUnderCursor();
@ -878,6 +899,8 @@ void Application::mouseReleaseEvent(QMouseEvent* event) {
_mouseY = event->y();
_mousePressed = false;
checkBandwidthMeterClick();
_pieMenu.mouseReleaseEvent(_mouseX, _mouseY);
}
}
}
@ -918,8 +941,10 @@ void Application::touchEndEvent(QTouchEvent* event) {
_isTouchPressed = false;
}
const bool USE_MOUSEWHEEL = false;
void Application::wheelEvent(QWheelEvent* event) {
if (activeWindow() == _window) {
// Wheel Events disabled for now because they are also activated by touch look pitch up/down.
if (USE_MOUSEWHEEL && (activeWindow() == _window)) {
if (checkedVoxelModeAction() == 0) {
event->ignore();
return;
@ -2046,7 +2071,15 @@ void Application::init() {
_palette.addTool(&_swatch);
_palette.addAction(_colorVoxelMode, 0, 2);
_palette.addAction(_eyedropperMode, 0, 3);
_palette.addAction(_selectVoxelMode, 0, 4);
_palette.addAction(_selectVoxelMode, 0, 4);
_pieMenu.init("./resources/images/hifi-interface-tools-v2-pie.svg",
_glWidget->width(),
_glWidget->height());
_followMode = new QAction(this);
connect(_followMode, SIGNAL(triggered()), this, SLOT(toggleFollowMode()));
_pieMenu.addAction(_followMode);
}
@ -2058,7 +2091,7 @@ const float HEAD_SPHERE_RADIUS = 0.07;
static uint16_t DEFAULT_NODE_ID_REF = 1;
bool Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection,
Avatar* Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection,
glm::vec3& eyePosition, uint16_t& nodeID = DEFAULT_NODE_ID_REF) {
NodeList* nodeList = NodeList::getInstance();
@ -2071,11 +2104,11 @@ bool Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& m
_lookatIndicatorScale = avatar->getScale();
_lookatOtherPosition = headPosition;
nodeID = avatar->getOwningNode()->getNodeID();
return true;
return avatar;
}
}
}
return false;
return NULL;
}
void Application::renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera) {
@ -2090,6 +2123,7 @@ void Application::renderLookatIndicator(glm::vec3 pointOfInterest, Camera& which
}
void Application::update(float deltaTime) {
// Use Transmitter Hand to move hand if connected, else use mouse
if (_myTransmitter.isConnected()) {
const float HAND_FORCE_SCALING = 0.01f;
@ -2122,11 +2156,46 @@ void Application::update(float deltaTime) {
// If the mouse is over another avatar's head...
glm::vec3 myLookAtFromMouse(eyePosition);
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
} else if (_isHoverVoxel) {
// Look at the hovered voxel
glm::vec3 lookAtSpot = getMouseVoxelWorldCoordinates(_hoverVoxel);
_myAvatar.getHead().setLookAtPosition(lookAtSpot);
} else {
// Just look in direction of the mouse ray
glm::vec3 myLookAtFromMouse(mouseRayOrigin + mouseRayDirection);
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
}
// Find the voxel we are hovering over, and respond if clicked
float distance;
BoxFace face;
// If we have clicked on a voxel, update it's color
if (_isHoverVoxelSounding) {
VoxelNode* hoveredNode = _voxels.getVoxelAt(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s);
float bright = _audio.getCollisionSoundMagnitude();
nodeColor clickColor = { 255 * bright + _hoverVoxelOriginalColor[0] * (1.f - bright),
_hoverVoxelOriginalColor[1] * (1.f - bright),
_hoverVoxelOriginalColor[2] * (1.f - bright), 1 };
hoveredNode->setColor(clickColor);
if (bright < 0.01f) {
hoveredNode->setColor(_hoverVoxelOriginalColor);
_isHoverVoxelSounding = false;
}
} else {
// Check for a new hover voxel
glm::vec4 oldVoxel(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s);
_isHoverVoxel = _voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _hoverVoxel, distance, face);
if (MAKE_SOUND_ON_VOXEL_HOVER && _isHoverVoxel && glm::vec4(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s) != oldVoxel) {
_hoverVoxelOriginalColor[0] = _hoverVoxel.red;
_hoverVoxelOriginalColor[1] = _hoverVoxel.green;
_hoverVoxelOriginalColor[2] = _hoverVoxel.blue;
_hoverVoxelOriginalColor[3] = 1;
_audio.startCollisionSound(1.0, HOVER_VOXEL_FREQUENCY * _hoverVoxel.s * TREE_SCALE, 0.0, HOVER_VOXEL_DECAY);
_isHoverVoxelSounding = true;
}
}
// If we are dragging on a voxel, add thrust according to the amount the mouse is dragging
const float VOXEL_GRAB_THRUST = 0.0f;
if (_mousePressed && (_mouseVoxel.s != 0)) {
@ -2152,8 +2221,6 @@ void Application::update(float deltaTime) {
(fabs(_myAvatar.getVelocity().x) +
fabs(_myAvatar.getVelocity().y) +
fabs(_myAvatar.getVelocity().z)) / 3 < MAX_AVATAR_EDIT_VELOCITY) {
float distance;
BoxFace face;
if (_voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _mouseVoxel, distance, face)) {
if (distance < MAX_VOXEL_EDIT_DISTANCE) {
// find the nearest voxel with the desired scale
@ -2340,20 +2407,18 @@ void Application::update(float deltaTime) {
}
void Application::updateAvatar(float deltaTime) {
// When head is rotated via touch/mouse look, slowly turn body to follow
const float BODY_FOLLOW_HEAD_RATE = 0.5f;
// update body yaw by body yaw delta
// rotate body yaw for yaw received from multitouch
_myAvatar.setOrientation(_myAvatar.getOrientation()
* glm::quat(glm::vec3(0, _yawFromTouch * deltaTime * BODY_FOLLOW_HEAD_RATE, 0) * deltaTime));
_yawFromTouch -= _yawFromTouch * deltaTime * BODY_FOLLOW_HEAD_RATE;
* glm::quat(glm::vec3(0, _yawFromTouch * deltaTime, 0)));
_yawFromTouch = 0.f;
// Update my avatar's state from gyros and/or webcam
_myAvatar.updateFromGyrosAndOrWebcam(_gyroLook->isChecked(),
glm::vec3(_headCameraPitchYawScale,
_headCameraPitchYawScale,
_headCameraPitchYawScale),
_yawFromTouch,
0.f,
_pitchFromTouch);
if (_serialHeadSensor.isActive()) {
@ -2812,8 +2877,12 @@ void Application::displayOverlay() {
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
// Display a single screen-size quad to
renderCollisionOverlay(_glWidget->width(), _glWidget->height(), _audio.getCollisionSoundMagnitude());
// Display a single screen-size quad to create an alpha blended 'collision' flash
float collisionSoundMagnitude = _audio.getCollisionSoundMagnitude();
const float VISIBLE_COLLISION_SOUND_MAGNITUDE = 0.5f;
if (collisionSoundMagnitude > VISIBLE_COLLISION_SOUND_MAGNITUDE) {
renderCollisionOverlay(_glWidget->width(), _glWidget->height(), _audio.getCollisionSoundMagnitude());
}
#ifndef _WIN32
_audio.render(_glWidget->width(), _glWidget->height());
@ -2945,6 +3014,10 @@ void Application::displayOverlay() {
_swatch.checkColor();
}
if (_pieMenu.isDisplayed()) {
_pieMenu.render();
}
glPopMatrix();
}
@ -3360,7 +3433,7 @@ void Application::shiftPaintingColor() {
}
void Application::maybeEditVoxelUnderCursor() {
bool Application::maybeEditVoxelUnderCursor() {
if (_addVoxelMode->isChecked() || _colorVoxelMode->isChecked()) {
if (_mouseVoxel.s != 0) {
PACKET_TYPE message = (_destructiveAddVoxel->isChecked() ?
@ -3431,7 +3504,11 @@ void Application::maybeEditVoxelUnderCursor() {
deleteVoxelUnderCursor();
} else if (_eyedropperMode->isChecked()) {
eyedropperVoxelUnderCursor();
} else {
return false;
}
return true;
}
void Application::deleteVoxelUnderCursor() {
@ -3474,6 +3551,22 @@ void Application::goHome() {
_myAvatar.setPosition(START_LOCATION);
}
void Application::toggleFollowMode() {
glm::vec3 mouseRayOrigin, mouseRayDirection;
_viewFrustum.computePickRay(_pieMenu.getX() / (float)_glWidget->width(),
_pieMenu.getY() / (float)_glWidget->height(),
mouseRayOrigin, mouseRayDirection);
glm::vec3 eyePositionIgnored;
uint16_t nodeIDIgnored;
Avatar* leadingAvatar = isLookingAtOtherAvatar(mouseRayOrigin,
mouseRayDirection,
eyePositionIgnored,
nodeIDIgnored);
_myAvatar.follow(leadingAvatar);
}
void Application::resetSensors() {
_headMouseX = _mouseX = _glWidget->width() / 2;
_headMouseY = _mouseY = _glWidget->height() / 2;

View file

@ -39,6 +39,7 @@
#include "ViewFrustum.h"
#include "VoxelSystem.h"
#include "Webcam.h"
#include "PieMenu.h"
#include "avatar/Avatar.h"
#include "avatar/HandControl.h"
#include "ui/BandwidthDialog.h"
@ -109,8 +110,6 @@ public slots:
void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data);
void setGroundPlaneImpact(float groundPlaneImpact) { _groundPlaneImpact = groundPlaneImpact; }
private slots:
@ -189,6 +188,8 @@ private slots:
glm::vec2 getScaledScreenPoint(glm::vec2 projectedPoint);
void goHome();
void toggleFollowMode();
private:
static void controlledBroadcastToNodes(unsigned char* broadcastData, size_t dataBytes,
@ -208,7 +209,7 @@ private:
void init();
void update(float deltaTime);
bool isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection,
Avatar* isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection,
glm::vec3& eyePosition, uint16_t& nodeID);
void renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera);
@ -225,7 +226,7 @@ private:
void setupPaintingVoxel();
void shiftPaintingColor();
void maybeEditVoxelUnderCursor();
bool maybeEditVoxelUnderCursor();
void deleteVoxelUnderCursor();
void eyedropperVoxelUnderCursor();
void resetSensors();
@ -293,6 +294,8 @@ private:
QAction* _simulateLeapHand; // When there's no Leap, use this to pretend there is one and feed fake hand data
QAction* _testRaveGlove; // Test fancy sparkle-rave-glove mode
QAction* _followMode;
BandwidthMeter _bandwidthMeter;
BandwidthDialog* _bandwidthDialog;
@ -372,14 +375,16 @@ private:
float _yawFromTouch;
float _pitchFromTouch;
float _groundPlaneImpact;
VoxelDetail _mouseVoxelDragging;
glm::vec3 _voxelThrust;
bool _mousePressed; // true if mouse has been pressed (clear when finished)
VoxelDetail _hoverVoxel; // Stuff about the voxel I am hovering or clicking
bool _isHoverVoxel;
bool _isHoverVoxelSounding;
nodeColor _hoverVoxelOriginalColor;
VoxelDetail _mouseVoxel; // details of the voxel under the mouse cursor
VoxelDetail _mouseVoxel; // details of the voxel to be edited
float _mouseVoxelScale; // the scale for adding/removing voxels
glm::vec3 _lastMouseVoxelPos; // the position of the last mouse voxel edit
bool _justEditedVoxel; // set when we've just added/deleted/colored a voxel
@ -430,6 +435,8 @@ private:
ToolsPalette _palette;
Swatch _swatch;
PieMenu _pieMenu;
VoxelSceneStats _voxelSceneStats;
};

View file

@ -27,6 +27,7 @@ ParticleSystem::ParticleSystem() {
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);
@ -72,25 +73,16 @@ void ParticleSystem::simulate(float deltaTime) {
_timer += deltaTime;
// emit particles
for (int e = 0; e < _numEmitters; e++) {
// update emitters
for (int emitterIndex = 0; emitterIndex < _numEmitters; emitterIndex++) {
assert(emitterIndex <= MAX_EMITTERS);
assert(e >= 0);
assert(e <= MAX_EMITTERS);
assert(_emitter[e].rate >= 0);
_emitter[e].emitReserve += _emitter[e].rate * deltaTime;
_emitter[e].numParticlesEmittedThisTime = (int)_emitter[e].emitReserve;
_emitter[e].emitReserve -= _emitter[e].numParticlesEmittedThisTime;
for (int p = 0; p < _emitter[e].numParticlesEmittedThisTime; p++) {
float timeFraction = (float)p / (float)_emitter[e].numParticlesEmittedThisTime;
createParticle(e, timeFraction);
if (_emitter[emitterIndex].active) {
updateEmitter(emitterIndex, deltaTime);
}
}
// update particles
// update particles
for (int p = 0; p < MAX_PARTICLES; p++) {
if (_particle[p].alive) {
if (_particle[p].age > _emitter[_particle[p].emitterIndex].particleLifespan) {
@ -102,6 +94,20 @@ void ParticleSystem::simulate(float 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) {
for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
@ -212,7 +218,6 @@ void ParticleSystem::setParticleAttributes(int emitterIndex, ParticleLifeStage l
}
void ParticleSystem::updateParticle(int p, float deltaTime) {
Emitter myEmitter = _emitter[_particle[p].emitterIndex];
@ -363,14 +368,16 @@ void ParticleSystem::killAllParticles() {
void ParticleSystem::render() {
// render the emitters
for (int e = 0; e < _numEmitters; e++) {
for (int e = 0; e < MAX_EMITTERS; e++) {
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].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) {

View file

@ -10,10 +10,10 @@
#include <glm/gtc/quaternion.hpp>
const int MAX_PARTICLES = 5000;
const int NULL_EMITTER = -1;
const int NULL_PARTICLE = -1;
const int MAX_EMITTERS = 100;
const int MAX_PARTICLES = 5000;
enum ParticleRenderStyle
{
@ -78,6 +78,7 @@ public:
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; }
@ -101,6 +102,7 @@ private:
};
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
@ -124,6 +126,7 @@ private:
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);

View file

@ -38,3 +38,7 @@ void applyDamping(float deltaTime, glm::vec3& velocity, float linearStrength, fl
}
}
void applyDampedSpring(float deltaTime, glm::vec3& velocity, glm::vec3& position, glm::vec3& targetPosition, float k, float damping) {
}

138
interface/src/PieMenu.cpp Normal file
View file

@ -0,0 +1,138 @@
//
// PieMenu.cpp
// hifi
//
// Created by Clement Brisset on 7/18/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#include "PieMenu.h"
#include <cmath>
#include <QAction>
#include <QSvgRenderer>
#include <QPainter>
#include <QGLWidget>
#include <SharedUtil.h>
PieMenu::PieMenu() :
_radiusIntern(30),
_radiusExtern(70),
_magnification(1.2f),
_isDisplayed(false) {
}
void PieMenu::init(const char *fileName, int screenWidth, int screenHeight) {
// Load SVG
switchToResourcesParentIfRequired();
QSvgRenderer renderer((QString) QString(fileName));
// Prepare a QImage with desired characteritisc
QImage image(2 * _radiusExtern, 2 * _radiusExtern, QImage::Format_ARGB32);
image.fill(0x0);
// Get QPainter that paints to the image
QPainter painter(&image);
renderer.render(&painter);
//get the OpenGL-friendly image
_textureImage = QGLWidget::convertToGLFormat(image);
glGenTextures(1, &_textureID);
glBindTexture(GL_TEXTURE_2D, _textureID);
//generate the texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
_textureImage.width(),
_textureImage.height(),
0, GL_RGBA, GL_UNSIGNED_BYTE,
_textureImage.bits());
//texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
void PieMenu::addAction(QAction* action){
_actions.push_back(action);
}
void PieMenu::render() {
if (_actions.size() == 0) {
return;
}
float start = M_PI / 2.0f;
float end = start + 2.0f * M_PI;
float step = 2.0f * M_PI / 100.0f;
float distance = sqrt((_mouseX - _x) * (_mouseX - _x) +
(_mouseY - _y) * (_mouseY - _y));
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _textureID);
glColor3f(1.0f, 1.0f, 1.0f);
if (_radiusIntern < distance) {
float angle = atan2((_mouseY - _y), (_mouseX - _x)) - start;
angle = (0.0f < angle) ? angle : angle + 2.0f * M_PI;
_selectedAction = floor(angle / (2.0f * M_PI / _actions.size()));
start = start + _selectedAction * 2.0f * M_PI / _actions.size();
end = start + 2.0f * M_PI / _actions.size();
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0.5f, 0.5f);
glVertex2f(_x, _y);
for (float i = start; i < end; i += step) {
glTexCoord2f(0.5f + 0.5f * cos(i), 0.5f - 0.5f * sin(i));
glVertex2f(_x + _magnification * _radiusExtern * cos(i),
_y + _magnification * _radiusExtern * sin(i));
}
glTexCoord2f(0.5f + 0.5f * cos(end), 0.5f + - 0.5f * sin(end));
glVertex2f(_x + _magnification * _radiusExtern * cos(end),
_y + _magnification * _radiusExtern * sin(end));
glEnd();
} else {
_selectedAction = -1;
glBegin(GL_QUADS);
glTexCoord2f(1, 1);
glVertex2f(_x + _radiusExtern, _y - _radiusExtern);
glTexCoord2f(1, 0);
glVertex2f(_x + _radiusExtern, _y + _radiusExtern);
glTexCoord2f(0, 0);
glVertex2f(_x - _radiusExtern, _y + _radiusExtern);
glTexCoord2f(0, 1);
glVertex2f(_x - _radiusExtern, _y - _radiusExtern);
glEnd();
}
glDisable(GL_TEXTURE_2D);
}
void PieMenu::resize(int screenWidth, int screenHeight) {
}
void PieMenu::mouseMoveEvent(int x, int y) {
_mouseX = x;
_mouseY = y;
}
void PieMenu::mousePressEvent(int x, int y) {
_x = _mouseX = x;
_y = _mouseY = y;
_selectedAction = -1;
_isDisplayed = true;
}
void PieMenu::mouseReleaseEvent(int x, int y) {
if (0 <= _selectedAction && _selectedAction < _actions.size() && _actions[_selectedAction]) {
_actions[_selectedAction]->trigger();
}
_isDisplayed = false;
}

59
interface/src/PieMenu.h Normal file
View file

@ -0,0 +1,59 @@
//
// PieMenu.h
// hifi
//
// Created by Clement Brisset on 7/18/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __hifi__PieMenu__
#define __hifi__PieMenu__
#include <vector>
#include "InterfaceConfig.h"
#include "Util.h"
#include <QImage>
class QAction;
class PieMenu {
public:
PieMenu();
void init(const char* fileName, int screenWidth, int screenHeight);
void addAction(QAction* action);
void render();
void resize(int screenWidth, int screenHeight);
bool isDisplayed() const {return _isDisplayed;}
int getX () const {return _x;}
int getY () const {return _y;}
void mouseMoveEvent (int x, int y);
void mousePressEvent (int x, int y);
void mouseReleaseEvent(int x, int y);
private:
QImage _textureImage;
GLuint _textureID;
// position of the menu
int _x;
int _y;
int _radiusIntern;
int _radiusExtern;
float _magnification;
int _mouseX;
int _mouseY;
int _selectedAction;
bool _isDisplayed;
std::vector<QAction*> _actions;
};
#endif /* defined(__hifi__PieMenu__) */

View file

@ -339,6 +339,7 @@ void renderCollisionOverlay(int width, int height, float magnitude) {
}
void renderGroundPlaneGrid(float size, float impact) {
float IMPACT_SOUND_MAGNITUDE_FOR_RECOLOR = 1.f;
glLineWidth(2.0);
glm::vec4 impactColor(1, 0, 0, 1);
glm::vec3 lineColor(0.4, 0.5, 0.3);
@ -355,7 +356,12 @@ void renderGroundPlaneGrid(float size, float impact) {
}
// Draw the floor, colored for recent impact
glm::vec4 floorColor = impact * impactColor + (1.f - impact) * surfaceColor;
glm::vec4 floorColor;
if (impact > IMPACT_SOUND_MAGNITUDE_FOR_RECOLOR) {
floorColor = impact * impactColor + (1.f - impact) * surfaceColor;
} else {
floorColor = surfaceColor;
}
glColor4fv(&floorColor.x);
glBegin(GL_QUADS);
glVertex3f(0, 0, 0);

View file

@ -101,7 +101,8 @@ Avatar::Avatar(Node* owningNode) :
_lastCollisionPosition(0, 0, 0),
_speedBrakes(false),
_isThrustOn(false),
_voxels(this)
_voxels(this),
_leadingAvatar(NULL)
{
// give the pointer to our head to inherited _headData variable from AvatarData
_headData = &_head;
@ -404,6 +405,33 @@ void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) {
_thrust += _scale * THRUST_JUMP * up;
_shouldJump = false;
}
// Add thrusts from leading avatar
if (_leadingAvatar != NULL) {
glm::vec3 toTarget = _leadingAvatar->getPosition() - _position;
if (.5f < up.x * toTarget.x + up.y * toTarget.y + up.z * toTarget.z) {
_thrust += _scale * THRUST_MAG_UP * deltaTime * up;
} else if (up.x * toTarget.x + up.y * toTarget.y + up.z * toTarget.z < -.5f) {
_thrust -= _scale * THRUST_MAG_UP * deltaTime * up;
}
if (glm::length(_position - _leadingAvatar->getPosition()) > _scale * _stringLength) {
_thrust += _scale * THRUST_MAG_FWD * deltaTime * front;
} else {
toTarget = _leadingAvatar->getHead().getLookAtPosition() - _position;
getHead().setLookAtPosition(_leadingAvatar->getHead().getLookAtPosition());
}
float yawAngle = angleBetween(front, glm::vec3(toTarget.x, 0.f, toTarget.z));
if (yawAngle < -10.f || 10.f < yawAngle){
if (right.x * toTarget.x + right.y * toTarget.y + right.z * toTarget.z > 0) {
_bodyYawDelta -= YAW_MAG * deltaTime;
} else {
_bodyYawDelta += YAW_MAG * deltaTime;
}
}
}
// Add thrusts from Transmitter
if (transmitter) {
@ -447,6 +475,18 @@ void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) {
_isThrustOn = (glm::length(_thrust) > EPSILON);
}
void Avatar::follow(Avatar* leadingAvatar) {
const float MAX_STRING_LENGTH = 2;
_leadingAvatar = leadingAvatar;
if (_leadingAvatar != NULL) {
_stringLength = glm::length(_position - _leadingAvatar->getPosition()) / _scale;
if (_stringLength > MAX_STRING_LENGTH) {
_stringLength = MAX_STRING_LENGTH;
}
}
}
void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
glm::quat orientation = getOrientation();
@ -475,6 +515,13 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
if (isMyAvatar()) {
updateThrust(deltaTime, transmitter);
}
// Ajust, scale, thrust and lookAt position when following an other avatar
if (isMyAvatar() && _leadingAvatar && _scale != _leadingAvatar->getScale()) {
float scale = 0.95f * _scale + 0.05f * _leadingAvatar->getScale();
setScale(scale);
Application::getInstance()->getCamera()->setScale(scale);
}
// copy velocity so we can use it later for acceleration
glm::vec3 oldVelocity = getVelocity();
@ -681,7 +728,9 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
_head.setScale(_scale);
_head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2]));
_head.simulate(deltaTime, isMyAvatar());
// use speed and angular velocity to determine walking vs. standing
if (_speed + fabs(_bodyYawDelta) > 0.2) {
_mode = AVATAR_MODE_WALKING;
@ -889,21 +938,15 @@ void Avatar::updateCollisionWithSphere(glm::vec3 position, float radius, float d
}
void Avatar::updateCollisionWithEnvironment(float deltaTime) {
glm::vec3 up = getBodyUpDirection();
float radius = _height * 0.125f;
const float ENVIRONMENT_SURFACE_ELASTICITY = 1.0f;
const float ENVIRONMENT_SURFACE_DAMPING = 0.01;
const float ENVIRONMENT_COLLISION_FREQUENCY = 0.05f;
const float VISIBLE_GROUND_COLLISION_VELOCITY = 0.2f;
glm::vec3 penetration;
if (Application::getInstance()->getEnvironment()->findCapsulePenetration(
_position - up * (_pelvisFloatingHeight - radius),
_position + up * (_height - _pelvisFloatingHeight - radius), radius, penetration)) {
float velocityTowardCollision = glm::dot(_velocity, glm::normalize(penetration));
if (velocityTowardCollision > VISIBLE_GROUND_COLLISION_VELOCITY) {
Application::getInstance()->setGroundPlaneImpact(1.0f);
}
_lastCollisionPosition = _position;
updateCollisionSound(penetration, deltaTime, ENVIRONMENT_COLLISION_FREQUENCY);
applyHardCollision(penetration, ENVIRONMENT_SURFACE_ELASTICITY, ENVIRONMENT_SURFACE_DAMPING);

View file

@ -114,6 +114,7 @@ public:
void reset();
void simulate(float deltaTime, Transmitter* transmitter);
void updateThrust(float deltaTime, Transmitter * transmitter);
void follow(Avatar* leadingAvatar);
void updateFromGyrosAndOrWebcam(bool gyroLook,
const glm::vec3& amplifyAngle,
float yawFromTouch,
@ -157,18 +158,16 @@ public:
float getElapsedTimeMoving () const { return _elapsedTimeMoving;}
float getElapsedTimeSinceCollision() const { return _elapsedTimeSinceCollision;}
const glm::vec3& getLastCollisionPosition () const { return _lastCollisionPosition;}
float getAbsoluteHeadYaw () const;
float getAbsoluteHeadPitch () const;
Head& getHead () {return _head; }
Hand& getHand () {return _hand; }
glm::quat getOrientation () const;
glm::quat getWorldAlignedOrientation() const;
const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; }
const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; }
glm::vec3 getGravity () const { return _gravity; }
float getAbsoluteHeadYaw () const;
float getAbsoluteHeadPitch () const;
Head& getHead () {return _head; }
Hand& getHand () {return _hand; }
glm::quat getOrientation () const;
glm::quat getWorldAlignedOrientation() const;
const glm::vec3& getMouseRayOrigin () const { return _mouseRayOrigin; }
const glm::vec3& getMouseRayDirection () const { return _mouseRayDirection; }
Avatar* getLeadingAvatar () const { return _leadingAvatar; }
glm::vec3 getGravity () const { return _gravity; }
glm::vec3 getUprightHeadPosition() const;
glm::vec3 getUprightEyeLevelPosition() const;
@ -255,7 +254,10 @@ private:
glm::vec3 _lastCollisionPosition;
bool _speedBrakes;
bool _isThrustOn;
Avatar* _leadingAvatar;
float _stringLength;
AvatarVoxelSystem _voxels;
// private methods...

View file

@ -14,7 +14,7 @@
#include "Util.h"
#include "renderer/ProgramObject.h"
const bool SHOW_LEAP_HAND = true;
const bool SHOW_LEAP_HAND = false;
using namespace std;
@ -51,6 +51,7 @@ void Hand::reset() {
void Hand::simulate(float deltaTime, bool isMine) {
if (_isRaveGloveActive) {
updateRaveGloveParticles(deltaTime);
}
@ -63,7 +64,8 @@ void Hand::calculateGeometry() {
_basePosition = head.getPosition() + head.getOrientation() * offset;
_baseOrientation = head.getOrientation();
_leapBalls.clear();
// generate finger tip balls....
_leapFingerTipBalls.clear();
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
if (palm.isActive()) {
@ -71,8 +73,8 @@ void Hand::calculateGeometry() {
FingerData& finger = palm.getFingers()[f];
if (finger.isActive()) {
const float standardBallRadius = 0.01f;
_leapBalls.resize(_leapBalls.size() + 1);
HandBall& ball = _leapBalls.back();
_leapFingerTipBalls.resize(_leapFingerTipBalls.size() + 1);
HandBall& ball = _leapFingerTipBalls.back();
ball.rotation = _baseOrientation;
ball.position = finger.getTipPosition();
ball.radius = standardBallRadius;
@ -82,6 +84,27 @@ void Hand::calculateGeometry() {
}
}
}
// generate finger rot 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.01f;
_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;
}
}
}
}
}
void Hand::setRaveGloveEffectsMode(QKeyEvent* event) {
@ -120,8 +143,9 @@ void Hand::render(bool lookingInMirror) {
glEnable(GL_RESCALE_NORMAL);
if ( SHOW_LEAP_HAND ) {
renderFingerTrails();
renderHandSpheres();
//renderLeapHands();
renderLeapFingerTrails();
renderLeapHandSpheres();
}
}
@ -153,18 +177,64 @@ void Hand::renderRaveGloveStage() {
}
}
void Hand::renderHandSpheres() {
void Hand::renderLeapHands() {
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& hand = getPalms()[i];
if (hand.isActive()) {
renderLeapHand(hand);
}
}
}
void Hand::renderLeapHand(PalmData& hand) {
glPushMatrix();
const float palmThickness = 0.002f;
glColor4f(0.5f, 0.5f, 0.5f, 1.0);
glm::vec3 tip = hand.getPosition();
glm::vec3 root = hand.getPosition() + hand.getNormal() * palmThickness;
Avatar::renderJointConnectingCone(root, tip, 0.05, 0.03);
for (size_t f = 0; f < hand.getNumFingers(); ++f) {
FingerData& finger = hand.getFingers()[f];
if (finger.isActive()) {
glColor4f(_ballColor.r, _ballColor.g, _ballColor.b, 0.5);
glm::vec3 tip = finger.getTipPosition();
glm::vec3 root = finger.getRootPosition();
Avatar::renderJointConnectingCone(root, tip, 0.001, 0.003);
}
}
glPopMatrix();
}
void Hand::renderLeapHandSpheres() {
glPushMatrix();
// Draw the leap balls
for (size_t i = 0; i < _leapBalls.size(); i++) {
for (size_t i = 0; i < _leapFingerTipBalls.size(); i++) {
float alpha = 1.0f;
if (alpha > 0.0f) {
glColor4f(_ballColor.r, _ballColor.g, _ballColor.b, alpha);
glPushMatrix();
glTranslatef(_leapBalls[i].position.x, _leapBalls[i].position.y, _leapBalls[i].position.z);
glutSolidSphere(_leapBalls[i].radius, 20.0f, 20.0f);
glTranslatef(_leapFingerTipBalls[i].position.x, _leapFingerTipBalls[i].position.y, _leapFingerTipBalls[i].position.z);
glutSolidSphere(_leapFingerTipBalls[i].radius, 20.0f, 20.0f);
glPopMatrix();
}
}
for (size_t i = 0; i < _leapFingerRootBalls.size(); i++) {
float alpha = 1.0f;
if (alpha > 0.0f) {
glColor4f(0.3f, 0.4f, 0.6f, alpha);
glPushMatrix();
glTranslatef(_leapFingerRootBalls[i].position.x, _leapFingerRootBalls[i].position.y, _leapFingerRootBalls[i].position.z);
glutSolidSphere(_leapFingerRootBalls[i].radius, 20.0f, 20.0f);
glPopMatrix();
}
}
@ -200,7 +270,7 @@ void Hand::renderHandSpheres() {
glPopMatrix();
}
void Hand::renderFingerTrails() {
void Hand::renderLeapFingerTrails() {
// Draw the finger root cones
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
@ -229,6 +299,7 @@ void Hand::renderFingerTrails() {
}
}
void Hand::setLeapHands(const std::vector<glm::vec3>& handPositions,
const std::vector<glm::vec3>& handNormals) {
for (size_t i = 0; i < getNumPalms(); ++i) {
@ -244,69 +315,28 @@ void Hand::setLeapHands(const std::vector<glm::vec3>& handPositions,
}
}
// call this right after the geometry of the leap hands are set
// call this soon after the geometry of the leap hands are set
void Hand::updateRaveGloveEmitters() {
bool debug = false;
for (size_t i = 0; i < NUM_FINGERS; i++) {
_raveGloveParticleSystem.setEmitterActive(_raveGloveEmitter[i], false);
}
if (_raveGloveInitialized) {
if(debug) printf( "\n" );
if(debug) printf( "------------------------------------\n" );
if(debug) printf( "updating rave glove emitters:\n" );
if(debug) printf( "------------------------------------\n" );
int emitterIndex = 0;
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
for (size_t i = 0; i < _leapFingerTipBalls.size(); i++) {
if (i < NUM_FINGERS) {
glm::vec3 fingerDirection = _leapFingerTipBalls[i].position - _leapFingerRootBalls[i].position;
float fingerLength = glm::length(fingerDirection);
if(debug) printf( "\n" );
if(debug) printf( "palm %d ", (int)i );
if (palm.isActive()) {
if(debug) printf( "is active\n" );
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
FingerData& finger = palm.getFingers()[f];
if(debug) printf( "emitterIndex %d: ", emitterIndex );
if (finger.isActive()) {
if ((emitterIndex >=0)
&& (emitterIndex < NUM_FINGERS)) {
assert(emitterIndex >=0 );
assert(emitterIndex < NUM_FINGERS );
if(debug) printf( "_raveGloveEmitter[%d] = %d\n", emitterIndex, _raveGloveEmitter[emitterIndex] );
glm::vec3 fingerDirection = finger.getTipPosition() - finger.getRootPosition();
float fingerLength = glm::length(fingerDirection);
if (fingerLength > 0.0f) {
fingerDirection /= fingerLength;
} else {
fingerDirection = IDENTITY_UP;
}
assert(_raveGloveEmitter[emitterIndex] >=0 );
assert(_raveGloveEmitter[emitterIndex] < NUM_FINGERS );
_raveGloveParticleSystem.setEmitterPosition (_raveGloveEmitter[emitterIndex], finger.getTipPosition());
_raveGloveParticleSystem.setEmitterDirection(_raveGloveEmitter[emitterIndex], fingerDirection);
}
} else {
if(debug) printf( "BOGUS finger\n" );
}
emitterIndex ++;
}
if (fingerLength > 0.0f) {
fingerDirection /= fingerLength;
} else {
if(debug) printf( "is NOT active\n" );
fingerDirection = IDENTITY_UP;
}
_raveGloveParticleSystem.setEmitterActive (_raveGloveEmitter[i], true);
_raveGloveParticleSystem.setEmitterPosition (_raveGloveEmitter[i], _leapFingerTipBalls[i].position);
_raveGloveParticleSystem.setEmitterDirection(_raveGloveEmitter[i], fingerDirection);
}
}
}
@ -317,16 +347,11 @@ void Hand::updateRaveGloveParticles(float deltaTime) {
if (!_raveGloveInitialized) {
//printf( "Initializing rave glove emitters:\n" );
//printf( "The indices of the emitters are:\n" );
// start up the rave glove finger particles...
for ( int f = 0; f< NUM_FINGERS; f ++ ) {
_raveGloveEmitter[f] = _raveGloveParticleSystem.addEmitter();
_raveGloveEmitter[f] = _raveGloveParticleSystem.addEmitter();
assert( _raveGloveEmitter[f] >= 0 );
assert( _raveGloveEmitter[f] != NULL_EMITTER );
//printf( "%d\n", _raveGloveEmitter[f] );
}
setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_FIRE);
@ -339,13 +364,13 @@ void Hand::updateRaveGloveParticles(float deltaTime) {
// this rave glove effect oscillates though various colors and radii that are meant to show off some effects
if (_raveGloveMode == RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR) {
ParticleSystem::ParticleAttributes attributes;
float red = 0.5f + 0.5f * sinf(_raveGloveClock * 1.4f);
float green = 0.5f + 0.5f * cosf(_raveGloveClock * 1.7f);
float blue = 0.5f + 0.5f * sinf(_raveGloveClock * 2.0f);
float red = 0.5f + 0.5f * sinf(_raveGloveClock * 2.4f);
float green = 0.5f + 0.5f * cosf(_raveGloveClock * 2.7f);
float blue = 0.5f + 0.5f * sinf(_raveGloveClock * 3.0f);
float alpha = 1.0f;
attributes.color = glm::vec4(red, green, blue, alpha);
attributes.radius = 0.01f + 0.005f * sinf(_raveGloveClock * 2.2f);
attributes.radius = 0.01f + 0.003f * sinf(_raveGloveClock * 50.0f);
attributes.modulationAmplitude = 0.0f;
for ( int f = 0; f< NUM_FINGERS; f ++ ) {
@ -360,6 +385,8 @@ void Hand::updateRaveGloveParticles(float deltaTime) {
}
}
void Hand::setRaveGloveMode(int mode) {
_raveGloveMode = mode;
@ -376,7 +403,7 @@ void Hand::setRaveGloveMode(int mode) {
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.0f );
_raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 0.03f );
_raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.0f );
_raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 30.0f );
_raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 20 );
@ -650,7 +677,7 @@ void Hand::setRaveGloveMode(int mode) {
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes);
//-----------------------------------------
// throb
// long sparkler
//-----------------------------------------
} else if (mode == RAVE_GLOVE_EFFECTS_MODE_LONG_SPARKLER) {
@ -672,6 +699,30 @@ void Hand::setRaveGloveMode(int mode) {
_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);
}
}
}

View file

@ -65,8 +65,9 @@ public:
void setRaveGloveEffectsMode(QKeyEvent* event);
// getters
const glm::vec3& getLeapBallPosition (int ball) const { return _leapBalls[ball].position;}
bool isRaveGloveActive () const { return _isRaveGloveActive; }
const glm::vec3& getLeapFingerTipBallPosition (int ball) const { return _leapFingerTipBalls [ball].position;}
const glm::vec3& getLeapFingerRootBallPosition(int ball) const { return _leapFingerRootBalls[ball].position;}
bool isRaveGloveActive() const { return _isRaveGloveActive; }
private:
// disallow copies of the Hand, copy of owning Avatar is disallowed too
@ -84,7 +85,8 @@ private:
float _renderAlpha;
bool _lookingInMirror;
glm::vec3 _ballColor;
std::vector<HandBall> _leapBalls;
std::vector<HandBall> _leapFingerTipBalls;
std::vector<HandBall> _leapFingerRootBalls;
// private methods
void setLeapHands(const std::vector<glm::vec3>& handPositions,
@ -92,8 +94,10 @@ private:
void renderRaveGloveStage();
void setRaveGloveMode(int mode);
void renderHandSpheres();
void renderFingerTrails();
void renderLeapHandSpheres();
void renderLeapHands();
void renderLeapHand(PalmData& hand);
void renderLeapFingerTrails();
void calculateGeometry();
};

17
libraries/avatars/src/AvatarData.cpp Executable file → Normal file
View file

@ -130,6 +130,8 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
// leap hand data
std::vector<glm::vec3> fingerVectors;
//printf("about to call _handData->encodeRemoteData(fingerVectors);\n");
_handData->encodeRemoteData(fingerVectors);
if (fingerVectors.size() > 255)
@ -244,17 +246,32 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
// hand state, stored as a semi-nibble in the bitItems
_handState = getSemiNibbleAt(bitItems,HAND_STATE_START_BIT);
//printf("about to call leap hand data code in AvatarData::parseData...\n");
// leap hand data
if (sourceBuffer - startPosition < numBytes) {
//printf("got inside of 'if (sourceBuffer - startPosition < numBytes)'\n");
// check passed, bytes match
unsigned int numFingerVectors = *sourceBuffer++;
//printf("numFingerVectors = %d\n", numFingerVectors);
if (numFingerVectors > 0) {
//printf("ok, we got fingers in AvatarData::parseData\n");
std::vector<glm::vec3> fingerVectors(numFingerVectors);
for (size_t i = 0; i < numFingerVectors; ++i) {
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerVectors[i].x), fingerVectorRadix);
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerVectors[i].y), fingerVectorRadix);
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerVectors[i].z), fingerVectorRadix);
}
//printf("about to call _handData->decodeRemoteData(fingerVectors);\n");
_handData->decodeRemoteData(fingerVectors);
}
}

3
libraries/avatars/src/HandData.cpp Executable file → Normal file
View file

@ -51,7 +51,9 @@ _owningHandData(owningHandData)
void HandData::encodeRemoteData(std::vector<glm::vec3>& fingerVectors) {
fingerVectors.clear();
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
if (!palm.isActive()) {
continue;
@ -60,6 +62,7 @@ void HandData::encodeRemoteData(std::vector<glm::vec3>& fingerVectors) {
fingerVectors.push_back(palm.getRawNormal());
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
FingerData& finger = palm.getFingers()[f];
if (finger.isActive()) {
fingerVectors.push_back(finger.getTipRawPosition());
fingerVectors.push_back(finger.getRootRawPosition());

View file

@ -1,5 +1,5 @@
//
// Tags.h
// Tags.cpp
// hifi
//
// Created by Clement Brisset on 7/3/13.