From 72774a5e20535eac600b114ee98686df80d65cd1 Mon Sep 17 00:00:00 2001 From: atlante45 Date: Fri, 19 Jul 2013 17:01:38 -0700 Subject: [PATCH 01/26] First step toward pie menus --- interface/src/Application.cpp | 19 ++++++- interface/src/Application.h | 5 +- interface/src/PieMenu.cpp | 97 +++++++++++++++++++++++++++++++++++ interface/src/PieMenu.h | 48 +++++++++++++++++ 4 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 interface/src/PieMenu.cpp create mode 100644 interface/src/PieMenu.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index adb88147e9..632eb12404 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -835,6 +835,8 @@ void Application::mouseMoveEvent(QMouseEvent* event) { deleteVoxelUnderCursor(); } } + + _pieMenu.mouseMoveEvent(_mouseX, _mouseY); } } @@ -847,7 +849,10 @@ void Application::mousePressEvent(QMouseEvent* event) { _mouseDragStartedY = _mouseY; _mouseVoxelDragging = _mouseVoxel; _mousePressed = true; - maybeEditVoxelUnderCursor(); + + if (!maybeEditVoxelUnderCursor()) { + _pieMenu.mousePressEvent(_mouseX, _mouseY); + } } else if (event->button() == Qt::RightButton && checkedVoxelModeAction() != 0) { deleteVoxelUnderCursor(); @@ -862,6 +867,8 @@ void Application::mouseReleaseEvent(QMouseEvent* event) { _mouseY = event->y(); _mousePressed = false; checkBandwidthMeterClick(); + + _pieMenu.mouseReleaseEvent(_mouseX, _mouseY); } } } @@ -2740,6 +2747,10 @@ void Application::displayOverlay() { _swatch.checkColor(); } + if (_pieMenu.isDisplayed()) { + _pieMenu.render(); + } + glPopMatrix(); } @@ -3147,7 +3158,7 @@ void Application::shiftPaintingColor() { } -void Application::maybeEditVoxelUnderCursor() { +bool Application::maybeEditVoxelUnderCursor() { if (_addVoxelMode->isChecked() || _colorVoxelMode->isChecked()) { if (_mouseVoxel.s != 0) { PACKET_TYPE message = (_destructiveAddVoxel->isChecked() ? @@ -3218,7 +3229,11 @@ void Application::maybeEditVoxelUnderCursor() { deleteVoxelUnderCursor(); } else if (_eyedropperMode->isChecked()) { eyedropperVoxelUnderCursor(); + } else { + return false; } + + return true; } void Application::deleteVoxelUnderCursor() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 9333808a27..f5f9c17883 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -42,6 +42,7 @@ #include "ViewFrustum.h" #include "VoxelSystem.h" #include "Webcam.h" +#include "PieMenu.h" class QAction; @@ -208,7 +209,7 @@ private: void setupPaintingVoxel(); void shiftPaintingColor(); - void maybeEditVoxelUnderCursor(); + bool maybeEditVoxelUnderCursor(); void deleteVoxelUnderCursor(); void eyedropperVoxelUnderCursor(); void resetSensors(); @@ -406,6 +407,8 @@ private: ToolsPalette _palette; Swatch _swatch; + + PieMenu _pieMenu; }; #endif /* defined(__interface__Application__) */ diff --git a/interface/src/PieMenu.cpp b/interface/src/PieMenu.cpp new file mode 100644 index 0000000000..73be3d12c3 --- /dev/null +++ b/interface/src/PieMenu.cpp @@ -0,0 +1,97 @@ +// +// PieMenu.cpp +// hifi +// +// Created by Clement Brisset on 7/18/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#include "PieMenu.h" + +#include + +#include +#include + +PieMenu::PieMenu() : + _radiusIntern(30), + _radiusExtern(70), + _isDisplayed(false) { + + addAction(NULL); + addAction(NULL); + addAction(NULL); + addAction(NULL); + addAction(NULL); +} + +void PieMenu::init(const char *fileName, int screenWidth, int screenHeight) { + +} + +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)); + + glBegin(GL_QUAD_STRIP); + glColor3f(1.0f, 1.0f, 1.0f); + for (float i = start; i < end; i += step) { + glVertex2f(_x + _radiusIntern * cos(i), _y + _radiusIntern * sin(i)); + glVertex2f(_x + _radiusExtern * cos(i), _y + _radiusExtern * sin(i)); + } + glVertex2f(_x + _radiusIntern * cos(end), _y + _radiusIntern * sin(end)); + glVertex2f(_x + _radiusExtern * cos(end), _y + _radiusExtern * sin(end)); + glEnd(); + + 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_QUAD_STRIP); + glColor3f(0.0f, 0.0f, 0.0f); + for (float i = start; i < end; i += step) { + glVertex2f(_x + _radiusIntern * cos(i), _y + _radiusIntern * sin(i)); + glVertex2f(_x + _radiusExtern * cos(i), _y + _radiusExtern * sin(i)); + } + glVertex2f(_x + _radiusIntern * cos(end), _y + _radiusIntern * sin(end)); + glVertex2f(_x + _radiusExtern * cos(end), _y + _radiusExtern * sin(end)); + glEnd(); + } else { + _selectedAction = -1; + } +} + +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; + _isDisplayed = true; +} + +void PieMenu::mouseReleaseEvent(int x, int y) { + // TODO + + _isDisplayed = false; +} diff --git a/interface/src/PieMenu.h b/interface/src/PieMenu.h new file mode 100644 index 0000000000..0323af8f94 --- /dev/null +++ b/interface/src/PieMenu.h @@ -0,0 +1,48 @@ +// +// 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 + +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;} + + void mouseMoveEvent (int x, int y); + void mousePressEvent (int x, int y); + void mouseReleaseEvent(int x, int y); + +private: + // position of the menu + int _x; + int _y; + int _radiusIntern; + int _radiusExtern; + + int _mouseX; + int _mouseY; + + int _selectedAction; + + bool _isDisplayed; + + std::vector _actions; +}; + +#endif /* defined(__hifi__PieMenu__) */ From fc3aa2da9b5aebad18f5cc66ed92a480300c3506 Mon Sep 17 00:00:00 2001 From: atlante45 Date: Fri, 19 Jul 2013 17:02:45 -0700 Subject: [PATCH 02/26] Fixed typo in Tags.cpp top comments --- libraries/voxels/src/Tags.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/voxels/src/Tags.cpp b/libraries/voxels/src/Tags.cpp index e6875f36a6..7df6f227ad 100644 --- a/libraries/voxels/src/Tags.cpp +++ b/libraries/voxels/src/Tags.cpp @@ -1,5 +1,5 @@ // -// Tags.h +// Tags.cpp // hifi // // Created by Clement Brisset on 7/3/13. From 177471e83ba0ac310c8b7d73b4a9a58576932e1d Mon Sep 17 00:00:00 2001 From: atlante45 Date: Wed, 24 Jul 2013 11:24:28 -0700 Subject: [PATCH 03/26] First step toward follow mode --- interface/src/Application.cpp | 14 +++++++++++++- interface/src/Application.h | 4 ++++ interface/src/avatar/Avatar.cpp | 6 ++++++ interface/src/avatar/Avatar.h | 24 ++++++++++++------------ 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ed47262942..9edfeafcbf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1982,7 +1982,14 @@ 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); } @@ -3400,6 +3407,11 @@ void Application::goHome() { _myAvatar.setPosition(START_LOCATION); } + +void Application::toggleFollowMode() { + +} + void Application::resetSensors() { _headMouseX = _mouseX = _glWidget->width() / 2; _headMouseY = _mouseY = _glWidget->height() / 2; diff --git a/interface/src/Application.h b/interface/src/Application.h index 66f17dd9cb..6bc9c2acc2 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -189,6 +189,8 @@ private slots: glm::vec2 getScaledScreenPoint(glm::vec2 projectedPoint); void goHome(); + void toggleFollowMode(); + private: static void controlledBroadcastToNodes(unsigned char* broadcastData, size_t dataBytes, @@ -292,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; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index c2a2d5aadd..a23c082cca 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -446,6 +446,12 @@ void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) { _isThrustOn = (glm::length(_thrust) > EPSILON); } +void Avatar::follow(Avatar* leadingAvatar) { + _leadingAvatar = leadingAvatar; + + +} + void Avatar::simulate(float deltaTime, Transmitter* transmitter) { glm::quat orientation = getOrientation(); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ec0d5a2ce5..ddec983d97 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -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; @@ -254,6 +253,7 @@ private: glm::vec3 _lastCollisionPosition; bool _speedBrakes; bool _isThrustOn; + Avatar* _leadingAvatar; AvatarVoxelSystem _voxels; From d165891fe6c770bec9d39b8d189b15635a823f6e Mon Sep 17 00:00:00 2001 From: atlante45 Date: Wed, 24 Jul 2013 12:38:35 -0700 Subject: [PATCH 04/26] New design for pie menus --- interface/src/Application.cpp | 6 ++- interface/src/PieMenu.cpp | 83 ++++++++++++++++++++++++++--------- interface/src/PieMenu.h | 17 +++++-- 3 files changed, 80 insertions(+), 26 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ed47262942..0245585e42 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1982,7 +1982,11 @@ 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()); } diff --git a/interface/src/PieMenu.cpp b/interface/src/PieMenu.cpp index 73be3d12c3..1f79d46814 100644 --- a/interface/src/PieMenu.cpp +++ b/interface/src/PieMenu.cpp @@ -11,22 +11,47 @@ #include #include +#include +#include #include +#include PieMenu::PieMenu() : _radiusIntern(30), _radiusExtern(70), + _magnification(1.2f), _isDisplayed(false) { - - addAction(NULL); - addAction(NULL); - addAction(NULL); - addAction(NULL); - addAction(NULL); } 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){ @@ -44,15 +69,10 @@ void PieMenu::render() { float distance = sqrt((_mouseX - _x) * (_mouseX - _x) + (_mouseY - _y) * (_mouseY - _y)); - glBegin(GL_QUAD_STRIP); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, _textureID); + glColor3f(1.0f, 1.0f, 1.0f); - for (float i = start; i < end; i += step) { - glVertex2f(_x + _radiusIntern * cos(i), _y + _radiusIntern * sin(i)); - glVertex2f(_x + _radiusExtern * cos(i), _y + _radiusExtern * sin(i)); - } - glVertex2f(_x + _radiusIntern * cos(end), _y + _radiusIntern * sin(end)); - glVertex2f(_x + _radiusExtern * cos(end), _y + _radiusExtern * sin(end)); - glEnd(); if (_radiusIntern < distance) { float angle = atan2((_mouseY - _y), (_mouseX - _x)) - start; @@ -62,18 +82,36 @@ void PieMenu::render() { start = start + _selectedAction * 2.0f * M_PI / _actions.size(); end = start + 2.0f * M_PI / _actions.size(); - glBegin(GL_QUAD_STRIP); - glColor3f(0.0f, 0.0f, 0.0f); + glBegin(GL_TRIANGLE_FAN); + glTexCoord2f(0.5f, 0.5f); + glVertex2f(_x, _y); for (float i = start; i < end; i += step) { - glVertex2f(_x + _radiusIntern * cos(i), _y + _radiusIntern * sin(i)); - glVertex2f(_x + _radiusExtern * cos(i), _y + _radiusExtern * sin(i)); + glTexCoord2f(0.5f + 0.5f * cos(i), 0.5f - 0.5f * sin(i)); + glVertex2f(_x + _magnification * _radiusExtern * cos(i), + _y + _magnification * _radiusExtern * sin(i)); } - glVertex2f(_x + _radiusIntern * cos(end), _y + _radiusIntern * sin(end)); - glVertex2f(_x + _radiusExtern * cos(end), _y + _radiusExtern * sin(end)); + 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) { @@ -87,11 +125,14 @@ void PieMenu::mouseMoveEvent(int x, int 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) { - // TODO + if (0 <= _selectedAction && _selectedAction < _actions.size() && _actions[_selectedAction]) { + _actions[_selectedAction]->trigger(); + } _isDisplayed = false; } diff --git a/interface/src/PieMenu.h b/interface/src/PieMenu.h index 0323af8f94..863a91cb45 100644 --- a/interface/src/PieMenu.h +++ b/interface/src/PieMenu.h @@ -11,6 +11,11 @@ #include +#include "InterfaceConfig.h" +#include "Util.h" + +#include + class QAction; class PieMenu { @@ -29,11 +34,15 @@ public: void mouseReleaseEvent(int x, int y); private: + QImage _textureImage; + GLuint _textureID; + // position of the menu - int _x; - int _y; - int _radiusIntern; - int _radiusExtern; + int _x; + int _y; + int _radiusIntern; + int _radiusExtern; + float _magnification; int _mouseX; int _mouseY; From f3c87b81ec0363a42b977df1d3fa5956cfbd32bb Mon Sep 17 00:00:00 2001 From: atlante45 Date: Thu, 25 Jul 2013 16:14:47 -0700 Subject: [PATCH 05/26] Avatar can follow but don't look at the same point for the moment --- interface/src/Application.cpp | 1 - interface/src/avatar/Avatar.cpp | 47 ++++++++++++++++++++++++++++++--- interface/src/avatar/Avatar.h | 4 ++- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f3b1f4a304..c7be8c014a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3421,7 +3421,6 @@ void Application::toggleFollowMode() { eyePositionIgnored, nodeIDIgnored); - qDebug("[DEBUG] toggleFollowMode() %d\n", leadingAvatar); _myAvatar.follow(leadingAvatar); } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index a613822fbf..bf9b4bb732 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -404,6 +404,32 @@ 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(); + } + + 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) { @@ -448,9 +474,15 @@ void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) { } void Avatar::follow(Avatar* leadingAvatar) { - _leadingAvatar = leadingAvatar; + const float MAX_STRING_LENGTH = 2; - qDebug("[DEBUG] %d\n", _leadingAvatar); + _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) { @@ -481,6 +513,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(); @@ -687,7 +726,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; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 02f360f83f..c69cbbadbf 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -253,8 +253,10 @@ private: glm::vec3 _lastCollisionPosition; bool _speedBrakes; bool _isThrustOn; + Avatar* _leadingAvatar; - + float _stringLength; + AvatarVoxelSystem _voxels; // private methods... From 86bf268eef4f939ceb08f763a16742b8e0e906d0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 29 Jul 2013 14:56:33 -0700 Subject: [PATCH 06/26] first cut at multiple voxel servers --- interface/src/Application.cpp | 3 ++- libraries/shared/src/NodeList.cpp | 7 +++--- libraries/shared/src/NodeList.h | 2 +- libraries/voxels/src/VoxelTree.cpp | 2 +- voxel-server/src/main.cpp | 40 +++++++++++++++++++++++++++--- 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c56a58ce90..3122dcdb4f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3496,7 +3496,8 @@ void* Application::networkReceive(void* args) { } // fall through to piggyback message if (app->_renderVoxels->isChecked()) { - Node* voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER); + //Node* voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER); + Node* voxelServer = NodeList::getInstance()->nodeWithAddress(&senderAddress); if (voxelServer && socketMatch(voxelServer->getActiveSocket(), &senderAddress)) { voxelServer->lock(); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 9406c6b14d..4e24a6636c 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -24,10 +24,11 @@ #include #endif -const char SOLO_NODE_TYPES[3] = { +// NODE_TYPE_VOXEL_SERVER - removed! + +const char SOLO_NODE_TYPES[2] = { NODE_TYPE_AVATAR_MIXER, - NODE_TYPE_AUDIO_MIXER, - NODE_TYPE_VOXEL_SERVER + NODE_TYPE_AUDIO_MIXER }; const char DEFAULT_DOMAIN_HOSTNAME[MAX_HOSTNAME_BYTES] = "root.highfidelity.io"; diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 2a66fc7374..4c4795bdb0 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -32,7 +32,7 @@ const unsigned int NODE_SOCKET_LISTEN_PORT = 40103; const int NODE_SILENCE_THRESHOLD_USECS = 2 * 1000000; const int DOMAIN_SERVER_CHECK_IN_USECS = 1 * 1000000; -extern const char SOLO_NODE_TYPES[3]; +extern const char SOLO_NODE_TYPES[2]; const int MAX_HOSTNAME_BYTES = 256; diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index fe67a50dee..9df72e8f4b 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -306,7 +306,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, } - if (includeExistsBits) { + if (false && includeExistsBits) { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { // now also check the childrenInTreeMask, if the mask is missing the bit, then it means we need to delete this child // subtree/node, because it shouldn't actually exist in the tree. diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index c009eec2a5..58a1dd036b 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -32,8 +32,12 @@ const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo"; const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.svo"; +const int MAX_FILENAME_LENGTH = 1024; +char voxelPersistFilename[MAX_FILENAME_LENGTH]; const int VOXEL_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds +//::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE + const int VOXEL_LISTEN_PORT = 40106; @@ -375,7 +379,7 @@ void persistVoxelsWhenDirty() { "persistVoxelsWhenDirty() - writeToSVOFile()", ::shouldShowAnimationDebug); printf("saving voxels to file...\n"); - serverTree.writeToSVOFile(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); + serverTree.writeToSVOFile(::voxelPersistFilename); serverTree.clearDirtyBit(); // tree is clean after saving printf("DONE saving voxels to file...\n"); } @@ -431,7 +435,20 @@ int main(int argc, const char * argv[]) { qInstallMsgHandler(sharedMessageHandler); - NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, VOXEL_LISTEN_PORT); + int listenPort = VOXEL_LISTEN_PORT; + // Check to see if the user passed in a command line option for setting listen port + const char* PORT_PARAMETER = "--port"; + const char* portParameter = getCmdOption(argc, argv, PORT_PARAMETER); + if (portParameter) { + listenPort = atoi(portParameter); + if (listenPort < 1) { + listenPort = VOXEL_LISTEN_PORT; + } + printf("portParameter=%s listenPort=%d\n", portParameter, listenPort); + } + + + NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, listenPort); setvbuf(stdout, NULL, _IOLBF, 0); // Handle Local Domain testing with the --local command line @@ -473,8 +490,19 @@ int main(int argc, const char * argv[]) { // if we want Voxel Persistance, load the local file now... bool persistantFileRead = false; if (::wantVoxelPersist) { - printf("loading voxels from file...\n"); - persistantFileRead = ::serverTree.readFromSVOFile(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); + + // Check to see if the user passed in a command line option for setting packet send rate + const char* VOXELS_PERSIST_FILENAME = "--voxelsPersistFilename"; + const char* voxelsPersistFilenameParameter = getCmdOption(argc, argv, VOXELS_PERSIST_FILENAME); + if (voxelsPersistFilenameParameter) { + strcpy(voxelPersistFilename, voxelsPersistFilenameParameter); + } else { + strcpy(voxelPersistFilename, ::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); + } + + printf("loading voxels from file: %s...\n", voxelPersistFilename); + + persistantFileRead = ::serverTree.readFromSVOFile(::voxelPersistFilename); if (persistantFileRead) { PerformanceWarning warn(::shouldShowAnimationDebug, "persistVoxelsWhenDirty() - reaverageVoxelColors()", ::shouldShowAnimationDebug); @@ -672,11 +700,15 @@ int main(int argc, const char * argv[]) { nodeList->broadcastToNodes(packetData, receivedBytes, &NODE_TYPE_AGENT, 1); } } else if (packetData[0] == PACKET_TYPE_HEAD_DATA) { + // If we got a PACKET_TYPE_HEAD_DATA, then we're talking to an NODE_TYPE_AVATAR, and we // need to make sure we have it in our nodeList. uint16_t nodeID = 0; unpackNodeId(packetData + numBytesPacketHeader, &nodeID); + +printf("got PACKET_TYPE_HEAD_DATA... nodeID=%d\n", nodeID); + Node* node = nodeList->addOrUpdateNode(&nodePublicAddress, &nodePublicAddress, NODE_TYPE_AGENT, From 1b85ad1b828f0d247fe2e3ca673b949116487068 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 29 Jul 2013 16:15:37 -0700 Subject: [PATCH 07/26] cleanup --- voxel-server/src/main.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 58a1dd036b..9ae8f080cc 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -36,8 +36,6 @@ const int MAX_FILENAME_LENGTH = 1024; char voxelPersistFilename[MAX_FILENAME_LENGTH]; const int VOXEL_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds -//::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE - const int VOXEL_LISTEN_PORT = 40106; @@ -700,15 +698,11 @@ int main(int argc, const char * argv[]) { nodeList->broadcastToNodes(packetData, receivedBytes, &NODE_TYPE_AGENT, 1); } } else if (packetData[0] == PACKET_TYPE_HEAD_DATA) { - // If we got a PACKET_TYPE_HEAD_DATA, then we're talking to an NODE_TYPE_AVATAR, and we // need to make sure we have it in our nodeList. uint16_t nodeID = 0; unpackNodeId(packetData + numBytesPacketHeader, &nodeID); - -printf("got PACKET_TYPE_HEAD_DATA... nodeID=%d\n", nodeID); - Node* node = nodeList->addOrUpdateNode(&nodePublicAddress, &nodePublicAddress, NODE_TYPE_AGENT, From 95e6fb16d09b497b8324b4465523acacff97b2c3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 29 Jul 2013 16:17:57 -0700 Subject: [PATCH 08/26] cleanup --- libraries/shared/src/NodeList.cpp | 2 -- libraries/voxels/src/VoxelTree.cpp | 9 +++++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 4e24a6636c..48810f7521 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -24,8 +24,6 @@ #include #endif -// NODE_TYPE_VOXEL_SERVER - removed! - const char SOLO_NODE_TYPES[2] = { NODE_TYPE_AVATAR_MIXER, NODE_TYPE_AUDIO_MIXER diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index b758c8697d..7b8dd67dc2 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -305,8 +305,13 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, childIndex++; } - - if (false && includeExistsBits) { + // Here's where we need to handle the idea of multiple voxel servers. If we have multiple voxel + // servers, then we don't want to "honor" exists bits for portions of the tree that the server in + // question is responsible for. Maybe we can handle this in the server and not "remove" bits for + // portions of the server that the server is not responsible for.... or maybe we need to let the client + // manage this concept. + const bool singleVoxelServer = true; + if (singleVoxelServer && includeExistsBits) { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { // now also check the childrenInTreeMask, if the mask is missing the bit, then it means we need to delete this child // subtree/node, because it shouldn't actually exist in the tree. From 620fe12358cfa410c4e92f5c0759e727e1a754cb Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 29 Jul 2013 16:31:14 -0700 Subject: [PATCH 09/26] support for multiple voxel servers in ping stats --- interface/src/Application.cpp | 31 ++++++++++++++++++++++-------- libraries/voxels/src/VoxelTree.cpp | 2 +- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 42895db69b..70efa48356 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2883,19 +2883,35 @@ void Application::displayStats() { drawtext(10, statsVerticalOffset + 15, 0.10f, 0, 1.0, 0, stats); if (_testPing->isChecked()) { - int pingAudio = 0, pingAvatar = 0, pingVoxel = 0; + int pingAudio = 0, pingAvatar = 0, pingVoxel = 0, pingVoxelMax = 0; - NodeList *nodeList = NodeList::getInstance(); - Node *audioMixerNode = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER); - Node *avatarMixerNode = nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER); - Node *voxelServerNode = nodeList->soloNodeOfType(NODE_TYPE_VOXEL_SERVER); + NodeList* nodeList = NodeList::getInstance(); + Node* audioMixerNode = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER); + Node* avatarMixerNode = nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER); pingAudio = audioMixerNode ? audioMixerNode->getPingMs() : 0; pingAvatar = avatarMixerNode ? avatarMixerNode->getPingMs() : 0; - pingVoxel = voxelServerNode ? voxelServerNode->getPingMs() : 0; + + + // Now handle voxel servers, since there could be more than one, we average their ping times + unsigned long totalPingVoxel = 0; + int voxelServerCount = 0; + for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + if (node->getType() == NODE_TYPE_VOXEL_SERVER) { + totalPingVoxel += node->getPingMs(); + voxelServerCount++; + if (pingVoxelMax < node->getPingMs()) { + pingVoxelMax = node->getPingMs(); + } + } + } + if (voxelServerCount) { + pingVoxel = totalPingVoxel/voxelServerCount; + } + char pingStats[200]; - sprintf(pingStats, "Ping audio/avatar/voxel: %d / %d / %d ", pingAudio, pingAvatar, pingVoxel); + sprintf(pingStats, "Ping audio/avatar/voxel: %d / %d / %d avg %d max ", pingAudio, pingAvatar, pingVoxel, pingVoxelMax); drawtext(10, statsVerticalOffset + 35, 0.10f, 0, 1.0, 0, pingStats); } @@ -3495,7 +3511,6 @@ void* Application::networkReceive(void* args) { } // fall through to piggyback message if (app->_renderVoxels->isChecked()) { - //Node* voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER); Node* voxelServer = NodeList::getInstance()->nodeWithAddress(&senderAddress); if (voxelServer && socketMatch(voxelServer->getActiveSocket(), &senderAddress)) { voxelServer->lock(); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 7b8dd67dc2..6fa843fdfe 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -310,7 +310,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, // question is responsible for. Maybe we can handle this in the server and not "remove" bits for // portions of the server that the server is not responsible for.... or maybe we need to let the client // manage this concept. - const bool singleVoxelServer = true; + const bool singleVoxelServer = false; if (singleVoxelServer && includeExistsBits) { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { // now also check the childrenInTreeMask, if the mask is missing the bit, then it means we need to delete this child From c7e3fe5ef6a2b95242df5ea2dedae53fca6cee67 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 30 Jul 2013 11:08:48 -0700 Subject: [PATCH 10/26] Added false colorization by voxel server source - switched readBitstreamToTree() to take params struct for future expansion - switched readNodeData() to take params for future expansion - added sourceID to VoxelNode - fixed false colorize routines to correctly redraw by marking tree as dirty --- interface/src/Application.cpp | 7 ++ interface/src/Application.h | 1 + interface/src/VoxelSystem.cpp | 95 +++++++++++++++++++++- interface/src/VoxelSystem.h | 12 ++- interface/src/avatar/AvatarVoxelSystem.cpp | 3 +- libraries/voxels/src/VoxelNode.cpp | 3 + libraries/voxels/src/VoxelNode.h | 8 +- libraries/voxels/src/VoxelTree.cpp | 40 +++++---- libraries/voxels/src/VoxelTree.h | 26 ++++-- 9 files changed, 165 insertions(+), 30 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 70efa48356..f9b40f5ab4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1361,6 +1361,10 @@ void Application::doFalseColorizeOccludedV2() { _voxels.falseColorizeOccludedV2(); } +void Application::doFalseColorizeBySource() { + _voxels.falseColorizeBySource(); +} + void Application::doTrueVoxelColors() { _voxels.trueColorize(); } @@ -1837,6 +1841,7 @@ void Application::initMenu() { renderDebugMenu->addAction("FALSE Color Voxel Out of View", this, SLOT(doFalseColorizeInView())); renderDebugMenu->addAction("FALSE Color Occluded Voxels", this, SLOT(doFalseColorizeOccluded()), Qt::CTRL | Qt::Key_O); renderDebugMenu->addAction("FALSE Color Occluded V2 Voxels", this, SLOT(doFalseColorizeOccludedV2()), Qt::CTRL | Qt::Key_P); + renderDebugMenu->addAction("FALSE Color By Source", this, SLOT(doFalseColorizeBySource()), Qt::CTRL | Qt::SHIFT | Qt::Key_S); renderDebugMenu->addAction("Show TRUE Colors", this, SLOT(doTrueVoxelColors()), Qt::CTRL | Qt::Key_T); (_shouldLowPassFilter = debugMenu->addAction("Test: LowPass filter"))->setCheckable(true); @@ -3518,7 +3523,9 @@ void* Application::networkReceive(void* args) { if (messageData[0] == PACKET_TYPE_ENVIRONMENT_DATA) { app->_environment.parseData(&senderAddress, messageData, messageLength); } else { + app->_voxels.setDataSourceID(voxelServer->getNodeID()); app->_voxels.parseData(messageData, messageLength); + app->_voxels.setDataSourceID(UNKNOWN_NODE_ID); } voxelServer->unlock(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 80ebd34250..42da66bf93 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -151,6 +151,7 @@ private slots: void doFalseColorizeByDistance(); void doFalseColorizeOccluded(); void doFalseColorizeOccludedV2(); + void doFalseColorizeBySource(); void doFalseColorizeInView(); void doTrueVoxelColors(); void doTreeStats(); diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 2d1bfb577c..b30cf362c3 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "Application.h" #include "CoverageMap.h" @@ -61,6 +63,8 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) : VoxelNode::addDeleteHook(this); _abandonedVBOSlots = 0; + _falseColorizeBySource = false; + _dataSourceID = UNKNOWN_NODE_ID; } void VoxelSystem::nodeDeleted(VoxelNode* node) { @@ -153,13 +157,15 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { case PACKET_TYPE_VOXEL_DATA: { PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()"); // ask the VoxelTree to read the bitstream into the tree - _tree->readBitstreamToTree(voxelData, numBytes - numBytesPacketHeader, WANT_COLOR, WANT_EXISTS_BITS); + ReadBitstreamToTreeParams args(WANT_COLOR, WANT_EXISTS_BITS, NULL, getDataSourceID()); + _tree->readBitstreamToTree(voxelData, numBytes - numBytesPacketHeader, args); } break; case PACKET_TYPE_VOXEL_DATA_MONOCHROME: { PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()"); // ask the VoxelTree to read the MONOCHROME bitstream into the tree - _tree->readBitstreamToTree(voxelData, numBytes - numBytesPacketHeader, NO_COLOR, WANT_EXISTS_BITS); + ReadBitstreamToTreeParams args(NO_COLOR, WANT_EXISTS_BITS, NULL, getDataSourceID()); + _tree->readBitstreamToTree(voxelData, numBytes - numBytesPacketHeader, args); } break; case PACKET_TYPE_Z_COMMAND: @@ -747,6 +753,7 @@ void VoxelSystem::randomizeVoxelColors() { _nodeCount = 0; _tree->recurseTreeWithOperation(randomColorOperation); qDebug("setting randomized true color for %d nodes\n", _nodeCount); + _tree->setDirtyBit(); setupNewVoxelsForDrawing(); } @@ -761,6 +768,7 @@ void VoxelSystem::falseColorizeRandom() { _nodeCount = 0; _tree->recurseTreeWithOperation(falseColorizeRandomOperation); qDebug("setting randomized false color for %d nodes\n", _nodeCount); + _tree->setDirtyBit(); setupNewVoxelsForDrawing(); } @@ -775,6 +783,7 @@ void VoxelSystem::trueColorize() { _nodeCount = 0; _tree->recurseTreeWithOperation(trueColorizeOperation); qDebug("setting true color for %d nodes\n", _nodeCount); + _tree->setDirtyBit(); setupNewVoxelsForDrawing(); } @@ -795,6 +804,84 @@ void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) { _nodeCount = 0; _tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum); qDebug("setting in view false color for %d nodes\n", _nodeCount); + _tree->setDirtyBit(); + setupNewVoxelsForDrawing(); +} + +// combines the removeOutOfView args into a single class +class groupColor { +public: + unsigned char red, green, blue; + groupColor(unsigned char red, unsigned char green, unsigned char blue) : + red(red), green(green), blue(blue) { }; + + groupColor(const groupColor& color) : + red(color.red), green(color.green), blue(color.blue) { }; + + groupColor() : + red(0), green(0), blue(0) { }; + +}; + +class colorizeBySourceArgs { +public: + std::map colors; +}; + +// Will false colorize voxels that are not in view +bool VoxelSystem::falseColorizeBySourceOperation(VoxelNode* node, void* extraData) { + colorizeBySourceArgs* args = (colorizeBySourceArgs*)extraData; + _nodeCount++; + if (node->isColored()) { + // pick a color based on the source - we want each source to be obviously different + uint16_t nodeID = node->getSourceID(); + + //printf("false colorizing from source %d, color: %d, %d, %d\n", nodeID, + // args->colors[nodeID].red, args->colors[nodeID].green, args->colors[nodeID].blue); + + node->setFalseColor(args->colors[nodeID].red, args->colors[nodeID].green, args->colors[nodeID].blue); + } + return true; // keep going! +} + +void VoxelSystem::falseColorizeBySource() { + _nodeCount = 0; + colorizeBySourceArgs args; + const int NUMBER_OF_COLOR_GROUPS = 3; + const unsigned char MIN_COLOR = 128; + int voxelServerCount = 0; + groupColor groupColors[NUMBER_OF_COLOR_GROUPS] = { groupColor(255, 0, 0), + groupColor(0, 255, 0), + groupColor(0, 0, 255)}; + + // create a bunch of colors we'll use during colorization + NodeList* nodeList = NodeList::getInstance(); + for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + if (node->getType() == NODE_TYPE_VOXEL_SERVER) { + uint16_t nodeID = node->getNodeID(); + int groupColor = voxelServerCount % NUMBER_OF_COLOR_GROUPS; + args.colors[nodeID] = groupColors[groupColor]; + + //printf("assigning color for source %d, color: %d, %d, %d\n", nodeID, + // args.colors[nodeID].red, args.colors[nodeID].green, args.colors[nodeID].blue); + + if (groupColors[groupColor].red > 0) { + groupColors[groupColor].red = ((groupColors[groupColor].red - MIN_COLOR)/2) + MIN_COLOR; + } + if (groupColors[groupColor].green > 0) { + groupColors[groupColor].green = ((groupColors[groupColor].green - MIN_COLOR)/2) + MIN_COLOR; + } + if (groupColors[groupColor].blue > 0) { + groupColors[groupColor].blue = ((groupColors[groupColor].blue - MIN_COLOR)/2) + MIN_COLOR; + } + + voxelServerCount++; + } + } + + _tree->recurseTreeWithOperation(falseColorizeBySourceOperation, &args); + qDebug("setting false color by source for %d nodes\n", _nodeCount); + _tree->setDirtyBit(); setupNewVoxelsForDrawing(); } @@ -848,6 +935,7 @@ void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) { _nodeCount = 0; _tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum); qDebug("setting in distance false color for %d nodes\n", _nodeCount); + _tree->setDirtyBit(); setupNewVoxelsForDrawing(); } @@ -1027,6 +1115,7 @@ void VoxelSystem::falseColorizeRandomEveryOther() { _tree->recurseTreeWithOperation(falseColorizeRandomEveryOtherOperation,&args); qDebug("randomized false color for every other node: total %ld, colorable %ld, colored %ld\n", args.totalNodes, args.colorableNodes, args.coloredNodes); + _tree->setDirtyBit(); setupNewVoxelsForDrawing(); } @@ -1331,6 +1420,7 @@ void VoxelSystem::falseColorizeOccluded() { //myCoverageMap.erase(); + _tree->setDirtyBit(); setupNewVoxelsForDrawing(); } @@ -1447,6 +1537,7 @@ void VoxelSystem::falseColorizeOccludedV2() { //myCoverageMapV2.erase(); + _tree->setDirtyBit(); setupNewVoxelsForDrawing(); } diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index ca390a5a20..ef7c33ee43 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -33,6 +33,9 @@ public: VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = MAX_VOXELS_PER_SYSTEM); ~VoxelSystem(); + void setDataSourceID(int dataSourceID) { _dataSourceID = dataSourceID; }; + int getDataSourceID() const { return _dataSourceID; }; + int parseData(unsigned char* sourceBuffer, int numBytes); virtual void init(); @@ -62,6 +65,8 @@ public: void falseColorizeRandomEveryOther(); void falseColorizeOccluded(); void falseColorizeOccludedV2(); + void falseColorizeBySource(); + void killLocalVoxels(); void setRenderPipelineWarnings(bool on) { _renderWarningsOn = on; }; @@ -94,7 +99,7 @@ public: CoverageMap myCoverageMap; virtual void nodeDeleted(VoxelNode* node); - + protected: float _treeScale; int _maxVoxels; @@ -134,7 +139,7 @@ private: static bool falseColorizeOccludedOperation(VoxelNode* node, void* extraData); static bool falseColorizeSubTreeOperation(VoxelNode* node, void* extraData); static bool falseColorizeOccludedV2Operation(VoxelNode* node, void* extraData); - + static bool falseColorizeBySourceOperation(VoxelNode* node, void* extraData); int updateNodeInArraysAsFullVBO(VoxelNode* node); int updateNodeInArraysAsPartialVBO(VoxelNode* node); @@ -195,6 +200,9 @@ private: void freeBufferIndex(glBufferIndex index); void clearFreeBufferIndexes(); + + bool _falseColorizeBySource; + int _dataSourceID; }; #endif diff --git a/interface/src/avatar/AvatarVoxelSystem.cpp b/interface/src/avatar/AvatarVoxelSystem.cpp index c85ea1a343..9a48c7b320 100644 --- a/interface/src/avatar/AvatarVoxelSystem.cpp +++ b/interface/src/avatar/AvatarVoxelSystem.cpp @@ -250,7 +250,8 @@ void AvatarVoxelSystem::handleVoxelDownloadProgress(qint64 bytesReceived, qint64 _voxelReply->deleteLater(); _voxelReply = 0; - _tree->readBitstreamToTree((unsigned char*)entirety.data(), entirety.size(), WANT_COLOR, NO_EXISTS_BITS); + ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS); + _tree->readBitstreamToTree((unsigned char*)entirety.data(), entirety.size(), args); setupNewVoxelsForDrawing(); } diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 8a76d9dfe8..42b34dd542 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -12,6 +12,8 @@ #include +#include + #include "AABox.h" #include "OctalCode.h" #include "SharedUtil.h" @@ -51,6 +53,7 @@ void VoxelNode::init(unsigned char * octalCode) { _voxelSystem = NULL; _isDirty = true; _shouldRender = false; + _sourceID = UNKNOWN_NODE_ID; markWithChangedTime(); calculateAABox(); } diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index 38e9627848..5035dbaad3 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -93,8 +93,6 @@ public: void setColor(const nodeColor& color); const nodeColor& getTrueColor() const { return _trueColor; }; const nodeColor& getColor() const { return _currentColor; }; - void setDensity(float density) { _density = density; }; - float getDensity() const { return _density; }; #else void setFalseColor(colorPart red, colorPart green, colorPart blue) { /* no op */ }; void setFalseColored(bool isFalseColored) { /* no op */ }; @@ -105,6 +103,11 @@ public: const nodeColor& getColor() const { return _trueColor; }; #endif + void setDensity(float density) { _density = density; }; + float getDensity() const { return _density; }; + void setSourceID(uint16_t sourceID) { _sourceID = sourceID; }; + uint16_t getSourceID() const { return _sourceID; }; + static void addDeleteHook(VoxelNodeDeleteHook* hook); static void removeDeleteHook(VoxelNodeDeleteHook* hook); @@ -135,6 +138,7 @@ private: unsigned long _subtreeNodeCount; unsigned long _subtreeLeafNodeCount; float _density; // If leaf: density = 1, if internal node: 0-1 density of voxels inside + uint16_t _sourceID; static std::vector _hooks; }; diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 6fa843fdfe..14244ec1e4 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -231,7 +231,7 @@ VoxelNode* VoxelTree::createMissingNode(VoxelNode* lastParentNode, unsigned char } int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, int bytesLeftToRead, - bool includeColor, bool includeExistsBits) { + ReadBitstreamToTreeParams& args) { // give this destination node the child mask from the packet const unsigned char ALL_CHILDREN_ASSUMED_TO_EXIST = 0xFF; unsigned char colorInPacketMask = *nodeData; @@ -254,12 +254,13 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, // pull the color for this child nodeColor newColor = { 128, 128, 128, 1}; - if (includeColor) { + if (args.includeColor) { memcpy(newColor, nodeData + bytesRead, 3); bytesRead += 3; } bool nodeWasDirty = destinationNode->getChildAtIndex(i)->isDirty(); destinationNode->getChildAtIndex(i)->setColor(newColor); + destinationNode->getChildAtIndex(i)->setSourceID(args.sourceID); bool nodeIsDirty = destinationNode->getChildAtIndex(i)->isDirty(); if (nodeIsDirty) { _isDirty = true; @@ -273,11 +274,11 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, } // give this destination node the child mask from the packet - unsigned char childrenInTreeMask = includeExistsBits ? *(nodeData + bytesRead) : ALL_CHILDREN_ASSUMED_TO_EXIST; - unsigned char childMask = *(nodeData + bytesRead + (includeExistsBits ? sizeof(childrenInTreeMask) : 0)); + unsigned char childrenInTreeMask = args.includeExistsBits ? *(nodeData + bytesRead) : ALL_CHILDREN_ASSUMED_TO_EXIST; + unsigned char childMask = *(nodeData + bytesRead + (args.includeExistsBits ? sizeof(childrenInTreeMask) : 0)); int childIndex = 0; - bytesRead += includeExistsBits ? sizeof(childrenInTreeMask) + sizeof(childMask) : sizeof(childMask); + bytesRead += args.includeExistsBits ? sizeof(childrenInTreeMask) + sizeof(childMask) : sizeof(childMask); while (bytesLeftToRead - bytesRead > 0 && childIndex < NUMBER_OF_CHILDREN) { // check the exists mask to see if we have a child to traverse into @@ -300,7 +301,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, // tell the child to read the subsequent data bytesRead += readNodeData(destinationNode->getChildAtIndex(childIndex), - nodeData + bytesRead, bytesLeftToRead - bytesRead, includeColor, includeExistsBits); + nodeData + bytesRead, bytesLeftToRead - bytesRead, args); } childIndex++; } @@ -311,7 +312,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, // portions of the server that the server is not responsible for.... or maybe we need to let the client // manage this concept. const bool singleVoxelServer = false; - if (singleVoxelServer && includeExistsBits) { + if (singleVoxelServer && args.includeExistsBits) { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { // now also check the childrenInTreeMask, if the mask is missing the bit, then it means we need to delete this child // subtree/node, because it shouldn't actually exist in the tree. @@ -324,14 +325,14 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, return bytesRead; } -void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes, - bool includeColor, bool includeExistsBits, VoxelNode* destinationNode) { +void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes, + ReadBitstreamToTreeParams& args) { int bytesRead = 0; unsigned char* bitstreamAt = bitstream; // If destination node is not included, set it to root - if (!destinationNode) { - destinationNode = rootNode; + if (!args.destinationNode) { + args.destinationNode = rootNode; } _nodesChangedFromBitstream = 0; @@ -341,14 +342,14 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int // if there are more bytes after that, it's assumed to be another root relative tree while (bitstreamAt < bitstream + bufferSizeBytes) { - VoxelNode* bitstreamRootNode = nodeForOctalCode(destinationNode, (unsigned char *)bitstreamAt, NULL); + VoxelNode* bitstreamRootNode = nodeForOctalCode(args.destinationNode, (unsigned char *)bitstreamAt, NULL); if (*bitstreamAt != *bitstreamRootNode->getOctalCode()) { // if the octal code returned is not on the same level as // the code being searched for, we have VoxelNodes to create // Note: we need to create this node relative to root, because we're assuming that the bitstream for the initial // octal code is always relative to root! - bitstreamRootNode = createMissingNode(destinationNode, (unsigned char*) bitstreamAt); + bitstreamRootNode = createMissingNode(args.destinationNode, (unsigned char*) bitstreamAt); if (bitstreamRootNode->isDirty()) { _isDirty = true; _nodesChangedFromBitstream++; @@ -358,8 +359,8 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int int octalCodeBytes = bytesRequiredForCodeLength(*bitstreamAt); int theseBytesRead = 0; theseBytesRead += octalCodeBytes; - theseBytesRead += readNodeData(bitstreamRootNode, bitstreamAt + octalCodeBytes, - bufferSizeBytes - (bytesRead + octalCodeBytes), includeColor, includeExistsBits); + theseBytesRead += readNodeData(bitstreamRootNode, bitstreamAt + octalCodeBytes, + bufferSizeBytes - (bytesRead + octalCodeBytes), args); // skip bitstream to new startPoint bitstreamAt += theseBytesRead; @@ -1553,7 +1554,8 @@ bool VoxelTree::readFromSVOFile(const char* fileName) { // read the entire file into a buffer, WHAT!? Why not. unsigned char* entireFile = new unsigned char[fileLength]; file.read((char*)entireFile, fileLength); - readBitstreamToTree(entireFile, fileLength, WANT_COLOR, NO_EXISTS_BITS); + ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS); + readBitstreamToTree(entireFile, fileLength, args); delete[] entireFile; file.close(); @@ -1707,7 +1709,8 @@ void VoxelTree::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinat bytesWritten = encodeTreeBitstream(subTree, &outputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, nodeBag, params); // ask destination tree to read the bitstream - destinationTree->readBitstreamToTree(&outputBuffer[0], bytesWritten, WANT_COLOR, NO_EXISTS_BITS); + ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS); + destinationTree->readBitstreamToTree(&outputBuffer[0], bytesWritten, args); } } @@ -1727,7 +1730,8 @@ void VoxelTree::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destin bytesWritten = sourceTree->encodeTreeBitstream(subTree, &outputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, nodeBag, params); // ask destination tree to read the bitstream - readBitstreamToTree(&outputBuffer[0], bytesWritten, WANT_COLOR, NO_EXISTS_BITS, destinationNode); + ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, destinationNode); + readBitstreamToTree(&outputBuffer[0], bytesWritten, args); } } diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 88394bd825..4d3a906874 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -88,6 +88,25 @@ public: {} }; +class ReadBitstreamToTreeParams { +public: + bool includeColor; + bool includeExistsBits; + VoxelNode* destinationNode; + uint16_t sourceID; + + ReadBitstreamToTreeParams( + bool includeColor = WANT_COLOR, + bool includeExistsBits = WANT_EXISTS_BITS, + VoxelNode* destinationNode = NULL, + uint16_t sourceID = UNKNOWN_NODE_ID) : + includeColor (includeColor), + includeExistsBits (includeExistsBits), + destinationNode (destinationNode), + sourceID (sourceID) + {} +}; + class VoxelTree { public: // when a voxel is created in the tree (object new'd) @@ -109,9 +128,7 @@ public: void eraseAllVoxels(); void processRemoveVoxelBitstream(unsigned char* bitstream, int bufferSizeBytes); - void readBitstreamToTree(unsigned char* bitstream, unsigned long int bufferSizeBytes, - bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS, - VoxelNode* destinationNode = NULL); + void readBitstreamToTree(unsigned char* bitstream, unsigned long int bufferSizeBytes, ReadBitstreamToTreeParams& args); void readCodeColorBufferToTree(unsigned char* codeColorBuffer, bool destructive = false); void deleteVoxelCodeFromTree(unsigned char* codeBuffer, bool collapseEmptyTrees = DONT_COLLAPSE); void printTreeForDebugging(VoxelNode* startNode); @@ -181,8 +198,7 @@ private: VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const; VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate); - int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes, - bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS); + int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes, ReadBitstreamToTreeParams& args); bool _isDirty; unsigned long int _nodesChangedFromBitstream; From 93a8e1782d369a28f0436642b5d1cbcc5cc1616e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 30 Jul 2013 12:13:45 -0700 Subject: [PATCH 11/26] cleanup --- interface/src/VoxelSystem.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index b30cf362c3..2631e255fb 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -808,19 +808,15 @@ void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) { setupNewVoxelsForDrawing(); } -// combines the removeOutOfView args into a single class +// helper classes and args for falseColorizeBySource class groupColor { public: unsigned char red, green, blue; groupColor(unsigned char red, unsigned char green, unsigned char blue) : red(red), green(green), blue(blue) { }; - groupColor(const groupColor& color) : - red(color.red), green(color.green), blue(color.blue) { }; - groupColor() : red(0), green(0), blue(0) { }; - }; class colorizeBySourceArgs { From 1b2f236d42d009e9b71eb2500fdcf9f557785c6d Mon Sep 17 00:00:00 2001 From: atlante45 Date: Tue, 30 Jul 2013 12:30:15 -0700 Subject: [PATCH 12/26] Follow mode operationnal --- interface/src/avatar/Avatar.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index bf9b4bb732..f832b9276f 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -418,7 +418,8 @@ void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) { if (glm::length(_position - _leadingAvatar->getPosition()) > _scale * _stringLength) { _thrust += _scale * THRUST_MAG_FWD * deltaTime * front; } else { - toTarget = _leadingAvatar->getHead().getLookAtPosition(); + toTarget = _leadingAvatar->getHead().getLookAtPosition() - _position; + getHead().setLookAtPosition(_leadingAvatar->getHead().getLookAtPosition()); } float yawAngle = angleBetween(front, glm::vec3(toTarget.x, 0.f, toTarget.z)); From 5b2693f99c9373f0be2e1a581cf16370e32418c9 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 31 Jul 2013 17:59:15 -0700 Subject: [PATCH 13/26] added emitter active bool for switching emitters on/off when Leap loses fingers --- interface/src/ParticleSystem.cpp | 53 ++++++++++++++------------ interface/src/ParticleSystem.h | 5 ++- interface/src/avatar/Hand.cpp | 64 +++++++++++++++++++++----------- 3 files changed, 77 insertions(+), 45 deletions(-) diff --git a/interface/src/ParticleSystem.cpp b/interface/src/ParticleSystem.cpp index 5e2b92bb64..fcea8ca270 100644 --- a/interface/src/ParticleSystem.cpp +++ b/interface/src/ParticleSystem.cpp @@ -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) { diff --git a/interface/src/ParticleSystem.h b/interface/src/ParticleSystem.h index d79f621f69..a0131883a1 100644 --- a/interface/src/ParticleSystem.h +++ b/interface/src/ParticleSystem.h @@ -10,10 +10,10 @@ #include -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); diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 28b1af0603..3eec1925c0 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -244,6 +244,7 @@ void Hand::setLeapHands(const std::vector& handPositions, } } + // call this right after the geometry of the leap hands are set void Hand::updateRaveGloveEmitters() { @@ -253,7 +254,7 @@ void Hand::updateRaveGloveEmitters() { if(debug) printf( "\n" ); if(debug) printf( "------------------------------------\n" ); - if(debug) printf( "updating rave glove emitters:\n" ); + if(debug) printf( "updating rave glove emitters: \n" ); if(debug) printf( "------------------------------------\n" ); int emitterIndex = 0; @@ -271,16 +272,16 @@ void Hand::updateRaveGloveEmitters() { for (size_t f = 0; f < palm.getNumFingers(); ++f) { FingerData& finger = palm.getFingers()[f]; - if(debug) printf( "emitterIndex %d: ", emitterIndex ); + if(debug) printf( "emitterIndex %d: ", emitterIndex ); - if (finger.isActive()) { - - if ((emitterIndex >=0) - && (emitterIndex < NUM_FINGERS)) { - - assert(emitterIndex >=0 ); - assert(emitterIndex < NUM_FINGERS ); + if ((emitterIndex >=0) + && (emitterIndex < NUM_FINGERS)) { + _raveGloveParticleSystem.setEmitterActive(_raveGloveEmitter[emitterIndex], false); // set to false by default... + + if (finger.isActive()) { + _raveGloveParticleSystem.setEmitterActive(_raveGloveEmitter[emitterIndex], true); + if(debug) printf( "_raveGloveEmitter[%d] = %d\n", emitterIndex, _raveGloveEmitter[emitterIndex] ); glm::vec3 fingerDirection = finger.getTipPosition() - finger.getRootPosition(); @@ -317,16 +318,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 +335,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 +356,8 @@ void Hand::updateRaveGloveParticles(float deltaTime) { } } + + void Hand::setRaveGloveMode(int mode) { _raveGloveMode = mode; @@ -376,7 +374,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 +648,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 +670,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); } } } From 0cd1018e7624aaacc4dd80ecc8f85f354ecd718a Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Thu, 1 Aug 2013 10:53:20 -0700 Subject: [PATCH 14/26] some experimental work on hand rendering --- interface/src/avatar/Hand.cpp | 46 +++++++++++++++++++++++++++++++---- interface/src/avatar/Hand.h | 6 +++-- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 3eec1925c0..2e409a10bf 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -14,7 +14,7 @@ #include "Util.h" #include "renderer/ProgramObject.h" -const bool SHOW_LEAP_HAND = false; +const bool SHOW_LEAP_HAND = true; using namespace std; @@ -120,8 +120,9 @@ void Hand::render(bool lookingInMirror) { glEnable(GL_RESCALE_NORMAL); if ( SHOW_LEAP_HAND ) { - renderFingerTrails(); - renderHandSpheres(); + renderLeapHands(); + //renderFingerTrails(); + //renderHandSpheres(); } } @@ -153,7 +154,42 @@ 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++) { @@ -200,7 +236,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]; diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index a3a00beb96..2ee066d7b6 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -92,8 +92,10 @@ private: void renderRaveGloveStage(); void setRaveGloveMode(int mode); - void renderHandSpheres(); - void renderFingerTrails(); + void renderLeapHandSpheres(); + void renderLeapHands(); + void renderLeapHand(PalmData& hand); + void renderLeapFingerTrails(); void calculateGeometry(); }; From 1df7026b26b79216ea1b9b32f2af06ecb7335e81 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Thu, 1 Aug 2013 10:54:09 -0700 Subject: [PATCH 15/26] merge? --- libraries/avatars/src/AvatarData.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 libraries/avatars/src/AvatarData.cpp diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp old mode 100755 new mode 100644 From 75fe53263c22e4a28cca57d697a6ea4ccea059b5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 1 Aug 2013 12:40:40 -0700 Subject: [PATCH 16/26] first cut at jurisdiction maps, not working yet --- libraries/voxels/src/JurisdictionMap.cpp | 64 ++++++++++++++++++++++++ libraries/voxels/src/JurisdictionMap.h | 40 +++++++++++++++ libraries/voxels/src/VoxelTree.cpp | 25 +++++---- libraries/voxels/src/VoxelTree.h | 18 ++++--- 4 files changed, 130 insertions(+), 17 deletions(-) create mode 100644 libraries/voxels/src/JurisdictionMap.cpp create mode 100644 libraries/voxels/src/JurisdictionMap.h diff --git a/libraries/voxels/src/JurisdictionMap.cpp b/libraries/voxels/src/JurisdictionMap.cpp new file mode 100644 index 0000000000..1a2b57965b --- /dev/null +++ b/libraries/voxels/src/JurisdictionMap.cpp @@ -0,0 +1,64 @@ +// +// JurisdictionMap.cpp +// hifi +// +// Created by Brad Hefta-Gaub on 8/1/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#include + +#include "JurisdictionMap.h" +#include "VoxelNode.h" + +JurisdictionMap::~JurisdictionMap() { + clear(); +} + +void JurisdictionMap::clear() { + delete[] _rootOctalCode; + _rootOctalCode = NULL; + + for (int i = 0; i < _endNodes.size(); i++) { + delete[] _endNodes[i]; + } + _endNodes.clear(); +} + +JurisdictionMap::JurisdictionMap() { + unsigned char* rootCode = new unsigned char[1]; + *rootCode = 0; + + std::vector emptyEndNodes; + init(rootCode, emptyEndNodes); +} + +JurisdictionMap::JurisdictionMap(const char* filename) { + clear(); // clean up our own memory + readFromFile(filename); +} + + +JurisdictionMap::JurisdictionMap(unsigned char* rootOctalCode, const std::vector& endNodes) { + init(rootOctalCode, endNodes); +} + +void JurisdictionMap::init(unsigned char* rootOctalCode, const std::vector& endNodes) { + clear(); // clean up our own memory + _rootOctalCode = rootOctalCode; + _endNodes = endNodes; +} + +bool JurisdictionMap::isMyJurisdiction(VoxelNode* node, int childIndex) const { + return true; +} + + +bool JurisdictionMap::readFromFile(const char* filename) { + QSettings settings(QString(filename), QSettings::IniFormat); + QString rootCode = settings->value("root","").toString(); + qDebug("rootCode=%s\n",rootCode); +} + +bool JurisdictionMap::writeToFile(const char* filename) { +} diff --git a/libraries/voxels/src/JurisdictionMap.h b/libraries/voxels/src/JurisdictionMap.h new file mode 100644 index 0000000000..9c9ed9ec0a --- /dev/null +++ b/libraries/voxels/src/JurisdictionMap.h @@ -0,0 +1,40 @@ +// +// JurisdictionMap.h +// hifi +// +// Created by Brad Hefta-Gaub on 8/1/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __hifi__JurisdictionMap__ +#define __hifi__JurisdictionMap__ + +#include + +class VoxelNode; // forward declaration + +class JurisdictionMap { +public: + JurisdictionMap(); + JurisdictionMap(const char* filename); + JurisdictionMap(unsigned char* rootOctalCode, const std::vector& endNodes); + ~JurisdictionMap(); + + + bool isMyJurisdiction(VoxelNode* node, int childIndex) const; + +private: + void clear(); + void init(unsigned char* rootOctalCode, const std::vector& endNodes); + + bool writeToFile(const char* filename); + bool readFromFile(const char* filename); + + + unsigned char* _rootOctalCode; + std::vector _endNodes; +}; + +#endif /* defined(__hifi__JurisdictionMap__) */ + + diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 14244ec1e4..0b8812f850 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -306,13 +306,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, childIndex++; } - // Here's where we need to handle the idea of multiple voxel servers. If we have multiple voxel - // servers, then we don't want to "honor" exists bits for portions of the tree that the server in - // question is responsible for. Maybe we can handle this in the server and not "remove" bits for - // portions of the server that the server is not responsible for.... or maybe we need to let the client - // manage this concept. - const bool singleVoxelServer = false; - if (singleVoxelServer && args.includeExistsBits) { + if (args.includeExistsBits) { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { // now also check the childrenInTreeMask, if the mask is missing the bit, then it means we need to delete this child // subtree/node, because it shouldn't actually exist in the tree. @@ -1203,9 +1197,18 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { VoxelNode* childNode = node->getChildAtIndex(i); - // if the caller wants to include childExistsBits, then include them even if not in view - if (params.includeExistsBits && childNode) { - childrenExistInTreeBits += (1 << (7 - i)); + // if the caller wants to include childExistsBits, then include them even if not in view, if however, + // we're in a portion of the tree that's not our responsibility, then we assume the child nodes exist + // even if they don't in our local tree + bool notMyJurisdictionBro = false; + if (params.jurisdictionMap) { + notMyJurisdictionBro = !params.jurisdictionMap->isMyJurisdiction(node, i); + } + if (params.includeExistsBits) { + // If the child is known to exist, OR, it's not my jurisdiction, then we mark the bit as existing + if (childNode || notMyJurisdictionBro) { + childrenExistInTreeBits += (1 << (7 - i)); + } } if (params.wantOcclusionCulling) { @@ -1886,4 +1889,4 @@ void VoxelTree::computeBlockColor(int id, int data, int& red, int& green, int& b create = 0; break; } -} +} \ No newline at end of file diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 4d3a906874..f27543caa8 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -13,6 +13,7 @@ #include #include "CoverageMap.h" +#include "JurisdictionMap.h" #include "ViewFrustum.h" #include "VoxelNode.h" #include "VoxelNodeBag.h" @@ -36,9 +37,10 @@ const int NO_BOUNDARY_ADJUST = 0; const int LOW_RES_MOVING_ADJUST = 1; const uint64_t IGNORE_LAST_SENT = 0; -#define IGNORE_SCENE_STATS NULL -#define IGNORE_VIEW_FRUSTUM NULL -#define IGNORE_COVERAGE_MAP NULL +#define IGNORE_SCENE_STATS NULL +#define IGNORE_VIEW_FRUSTUM NULL +#define IGNORE_COVERAGE_MAP NULL +#define IGNORE_JURISDICTION_MAP NULL class EncodeBitstreamParams { public: @@ -56,6 +58,7 @@ public: bool forceSendScene; VoxelSceneStats* stats; CoverageMap* map; + JurisdictionMap* jurisdictionMap; EncodeBitstreamParams( int maxEncodeLevel = INT_MAX, @@ -70,7 +73,8 @@ public: int boundaryLevelAdjust = NO_BOUNDARY_ADJUST, uint64_t lastViewFrustumSent = IGNORE_LAST_SENT, bool forceSendScene = true, - VoxelSceneStats* stats = IGNORE_SCENE_STATS) : + VoxelSceneStats* stats = IGNORE_SCENE_STATS, + JurisdictionMap* jurisdictionMap = IGNORE_JURISDICTION_MAP) : maxEncodeLevel (maxEncodeLevel), maxLevelReached (0), viewFrustum (viewFrustum), @@ -84,7 +88,8 @@ public: lastViewFrustumSent (lastViewFrustumSent), forceSendScene (forceSendScene), stats (stats), - map (map) + map (map), + jurisdictionMap (jurisdictionMap) {} }; @@ -186,7 +191,8 @@ public: void recurseTreeWithOperationDistanceSortedTimed(PointerStack* stackOfNodes, long allowedTime, RecurseVoxelTreeOperation operation, const glm::vec3& point, void* extraData); - + + private: void deleteVoxelCodeFromTreeRecursion(VoxelNode* node, void* extraData); void readCodeColorBufferToTreeRecursion(VoxelNode* node, void* extraData); From 6a6c51f80ec919cc84e66a00559e1bc04f746ca5 Mon Sep 17 00:00:00 2001 From: Mark Peng Date: Thu, 1 Aug 2013 15:04:58 -0700 Subject: [PATCH 17/26] Add skeleton tracking toggle in options menu in interface. --- interface/src/Application.cpp | 1 + interface/src/Webcam.cpp | 4 ++-- interface/src/Webcam.h | 7 +++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7fc9bd7ac8..0de45b3dcf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1728,6 +1728,7 @@ void Application::initMenu() { _testPing->setChecked(true); (_fullScreenMode = optionsMenu->addAction("Fullscreen", this, SLOT(setFullscreen(bool)), Qt::Key_F))->setCheckable(true); optionsMenu->addAction("Webcam", &_webcam, SLOT(setEnabled(bool)))->setCheckable(true); + optionsMenu->addAction("Toggle Skeleton Tracking", &_webcam, SLOT(toggleSkeletonTracking(bool)))->setCheckable(true); optionsMenu->addAction("Go Home", this, SLOT(goHome())); QMenu* renderMenu = menuBar->addMenu("Render"); diff --git a/interface/src/Webcam.cpp b/interface/src/Webcam.cpp index d4fa015ba0..921f4f427b 100644 --- a/interface/src/Webcam.cpp +++ b/interface/src/Webcam.cpp @@ -32,7 +32,7 @@ int jointVectorMetaType = qRegisterMetaType("JointVector"); int matMetaType = qRegisterMetaType("cv::Mat"); int rotatedRectMetaType = qRegisterMetaType("cv::RotatedRect"); -Webcam::Webcam() : _enabled(false), _active(false), _colorTextureID(0), _depthTextureID(0) { +Webcam::Webcam() : _enabled(false), _active(false), _colorTextureID(0), _depthTextureID(0), _skeletonTrackingOn(false) { // the grabber simply runs as fast as possible _grabber = new FrameGrabber(); _grabber->moveToThread(&_grabberThread); @@ -194,7 +194,7 @@ void Webcam::setFrame(const Mat& color, int format, const Mat& depth, float mean // store our face rect and joints, update our frame count for fps computation _faceRect = faceRect; - _joints = joints; + if (_skeletonTrackingOn) _joints = joints; _frameCount++; const int MAX_FPS = 60; diff --git a/interface/src/Webcam.h b/interface/src/Webcam.h index 3910bb4a19..7e27fba189 100644 --- a/interface/src/Webcam.h +++ b/interface/src/Webcam.h @@ -45,7 +45,7 @@ public: ~Webcam(); bool isActive() const { return _active; } - + GLuint getColorTextureID() const { return _colorTextureID; } GLuint getDepthTextureID() const { return _depthTextureID; } const cv::Size2f& getTextureSize() const { return _textureSize; } @@ -57,13 +57,14 @@ public: const JointVector& getEstimatedJoints() const { return _estimatedJoints; } void reset(); - void renderPreview(int screenWidth, int screenHeight); + void renderPreview(int screenWidth, int screenHeight); public slots: void setEnabled(bool enabled); void setFrame(const cv::Mat& color, int format, const cv::Mat& depth, float meanFaceDepth, const cv::RotatedRect& faceRect, const JointVector& joints); + void toggleSkeletonTracking(bool toggle) { _skeletonTrackingOn = toggle; }; private: @@ -88,6 +89,8 @@ private: glm::vec3 _estimatedPosition; glm::vec3 _estimatedRotation; JointVector _estimatedJoints; + + bool _skeletonTrackingOn; }; class FrameGrabber : public QObject { From 81a363f053de0335c1b0bbcb5260fee6aeba28fb Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 1 Aug 2013 22:05:13 -0700 Subject: [PATCH 18/26] added reading/writing to jurisdiction files --- libraries/voxels/src/JurisdictionMap.cpp | 80 +++++++++++++++++++++--- libraries/voxels/src/JurisdictionMap.h | 8 ++- voxel-server/src/main.cpp | 21 ++++++- 3 files changed, 96 insertions(+), 13 deletions(-) diff --git a/libraries/voxels/src/JurisdictionMap.cpp b/libraries/voxels/src/JurisdictionMap.cpp index 1a2b57965b..b3ea5f21f5 100644 --- a/libraries/voxels/src/JurisdictionMap.cpp +++ b/libraries/voxels/src/JurisdictionMap.cpp @@ -7,6 +7,8 @@ // #include +#include +#include #include "JurisdictionMap.h" #include "VoxelNode.h" @@ -16,16 +18,20 @@ JurisdictionMap::~JurisdictionMap() { } void JurisdictionMap::clear() { - delete[] _rootOctalCode; - _rootOctalCode = NULL; + if (_rootOctalCode) { + delete[] _rootOctalCode; + _rootOctalCode = NULL; + } for (int i = 0; i < _endNodes.size(); i++) { - delete[] _endNodes[i]; + if (_endNodes[i]) { + delete[] _endNodes[i]; + } } _endNodes.clear(); } -JurisdictionMap::JurisdictionMap() { +JurisdictionMap::JurisdictionMap() : _rootOctalCode(NULL) { unsigned char* rootCode = new unsigned char[1]; *rootCode = 0; @@ -33,13 +39,14 @@ JurisdictionMap::JurisdictionMap() { init(rootCode, emptyEndNodes); } -JurisdictionMap::JurisdictionMap(const char* filename) { +JurisdictionMap::JurisdictionMap(const char* filename) : _rootOctalCode(NULL) { clear(); // clean up our own memory readFromFile(filename); } -JurisdictionMap::JurisdictionMap(unsigned char* rootOctalCode, const std::vector& endNodes) { +JurisdictionMap::JurisdictionMap(unsigned char* rootOctalCode, const std::vector& endNodes) + : _rootOctalCode(NULL) { init(rootOctalCode, endNodes); } @@ -55,10 +62,65 @@ bool JurisdictionMap::isMyJurisdiction(VoxelNode* node, int childIndex) const { bool JurisdictionMap::readFromFile(const char* filename) { - QSettings settings(QString(filename), QSettings::IniFormat); - QString rootCode = settings->value("root","").toString(); - qDebug("rootCode=%s\n",rootCode); + QString settingsFile(filename); + QSettings settings(settingsFile, QSettings::IniFormat); + QString rootCode = settings.value("root","").toString(); + qDebug() << "rootCode=" << rootCode << "\n"; + + unsigned char* rootOctCode = hexStringToOctalCode(rootCode); + printOctalCode(rootOctCode); + + settings.beginGroup("endNodes"); + const QStringList childKeys = settings.childKeys(); + QHash values; + foreach (const QString &childKey, childKeys) { + QString childValue = settings.value(childKey).toString(); + values.insert(childKey, childValue); + qDebug() << childKey << "=" << childValue << "\n"; + + unsigned char* octcode = hexStringToOctalCode(childValue); + printOctalCode(octcode); + + _endNodes.push_back(octcode); + } + settings.endGroup(); + return true; } bool JurisdictionMap::writeToFile(const char* filename) { + QString settingsFile(filename); + QSettings settings(settingsFile, QSettings::IniFormat); + + settings.setValue("root", "rootNodeValue"); + + settings.beginGroup("endNodes"); + for (int i = 0; i < _endNodes.size(); i++) { + QString key = QString("endnode%1").arg(i); + QString value = QString("valuenode%1").arg(i); + settings.setValue(key, value); + } + settings.endGroup(); + return true; } + + +unsigned char* JurisdictionMap::hexStringToOctalCode(const QString& input) { + // i variable used to hold position in string + int i = 0; + // x variable used to hold byte array element position + int x = 0; + // allocate byte array based on half of string length + unsigned char* bytes = new unsigned char[(input.length()) / 2]; + // loop through the string - 2 bytes at a time converting + // it to decimal equivalent and store in byte array + while (input.length() > i + 1) { + + bool ok; + uint value = input.mid(i, 2).toUInt(&ok,16); + bytes[x] = (unsigned char)value; + i += 2; + x += 1; + } + // return the finished byte array of decimal values + return bytes; +} \ No newline at end of file diff --git a/libraries/voxels/src/JurisdictionMap.h b/libraries/voxels/src/JurisdictionMap.h index 9c9ed9ec0a..dd0160e7a1 100644 --- a/libraries/voxels/src/JurisdictionMap.h +++ b/libraries/voxels/src/JurisdictionMap.h @@ -10,6 +10,7 @@ #define __hifi__JurisdictionMap__ #include +#include class VoxelNode; // forward declaration @@ -20,15 +21,16 @@ public: JurisdictionMap(unsigned char* rootOctalCode, const std::vector& endNodes); ~JurisdictionMap(); - bool isMyJurisdiction(VoxelNode* node, int childIndex) const; + + bool writeToFile(const char* filename); + bool readFromFile(const char* filename); private: void clear(); void init(unsigned char* rootOctalCode, const std::vector& endNodes); - bool writeToFile(const char* filename); - bool readFromFile(const char* filename); + unsigned char* hexStringToOctalCode(const QString& input); unsigned char* _rootOctalCode; diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 75eac7353b..ef0a785fc8 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -430,6 +430,7 @@ void attachVoxelNodeDataToNode(Node* newNode) { } int receivedPacketCount = 0; +JurisdictionMap* jurisdiction = NULL; int main(int argc, const char * argv[]) { pthread_mutex_init(&::treeLock, NULL); @@ -447,7 +448,21 @@ int main(int argc, const char * argv[]) { } printf("portParameter=%s listenPort=%d\n", portParameter, listenPort); } - + + const char* JURISDICTION_FILE = "--jurisdictionFile"; + const char* jurisdictionFile = getCmdOption(argc, argv, JURISDICTION_FILE); + if (jurisdictionFile) { + printf("jurisdictionFile=%s\n", jurisdictionFile); + + printf("about to readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); + jurisdiction = new JurisdictionMap(jurisdictionFile); + printf("after readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); + + // test writing the file... + //printf("about to writeToFile().... jurisdictionFile=%s\n", jurisdictionFile); + //jurisdiction->writeToFile(jurisdictionFile); + //printf("after writeToFile().... jurisdictionFile=%s\n", jurisdictionFile); + } NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, listenPort); setvbuf(stdout, NULL, _IOLBF, 0); @@ -733,6 +748,10 @@ int main(int argc, const char * argv[]) { pthread_join(sendVoxelThread, NULL); pthread_mutex_destroy(&::treeLock); + + if (jurisdiction) { + delete jurisdiction; + } return 0; } From f57d86ddb200d0313bbf1fb18c3ddb5b762ef8dc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 2 Aug 2013 08:56:55 -0700 Subject: [PATCH 19/26] writing jurisdiction map configs --- libraries/voxels/src/JurisdictionMap.cpp | 66 +++++++++++++++++------- libraries/voxels/src/JurisdictionMap.h | 3 +- voxel-server/src/main.cpp | 6 +-- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/libraries/voxels/src/JurisdictionMap.cpp b/libraries/voxels/src/JurisdictionMap.cpp index b3ea5f21f5..5c1fc5c52f 100644 --- a/libraries/voxels/src/JurisdictionMap.cpp +++ b/libraries/voxels/src/JurisdictionMap.cpp @@ -64,11 +64,11 @@ bool JurisdictionMap::isMyJurisdiction(VoxelNode* node, int childIndex) const { bool JurisdictionMap::readFromFile(const char* filename) { QString settingsFile(filename); QSettings settings(settingsFile, QSettings::IniFormat); - QString rootCode = settings.value("root","").toString(); + QString rootCode = settings.value("root","00").toString(); qDebug() << "rootCode=" << rootCode << "\n"; - unsigned char* rootOctCode = hexStringToOctalCode(rootCode); - printOctalCode(rootOctCode); + _rootOctalCode = hexStringToOctalCode(rootCode); + printOctalCode(_rootOctalCode); settings.beginGroup("endNodes"); const QStringList childKeys = settings.childKeys(); @@ -91,12 +91,15 @@ bool JurisdictionMap::writeToFile(const char* filename) { QString settingsFile(filename); QSettings settings(settingsFile, QSettings::IniFormat); - settings.setValue("root", "rootNodeValue"); + + QString rootNodeValue = octalCodeToHexString(_rootOctalCode); + + settings.setValue("root", rootNodeValue); settings.beginGroup("endNodes"); for (int i = 0; i < _endNodes.size(); i++) { QString key = QString("endnode%1").arg(i); - QString value = QString("valuenode%1").arg(i); + QString value = octalCodeToHexString(_endNodes[i]); settings.setValue(key, value); } settings.endGroup(); @@ -104,23 +107,46 @@ bool JurisdictionMap::writeToFile(const char* filename) { } -unsigned char* JurisdictionMap::hexStringToOctalCode(const QString& input) { - // i variable used to hold position in string - int i = 0; - // x variable used to hold byte array element position - int x = 0; +unsigned char* JurisdictionMap::hexStringToOctalCode(const QString& input) const { + const int HEX_NUMBER_BASE = 16; + const int HEX_BYTE_SIZE = 2; + int stringIndex = 0; + int byteArrayIndex = 0; + // allocate byte array based on half of string length - unsigned char* bytes = new unsigned char[(input.length()) / 2]; + unsigned char* bytes = new unsigned char[(input.length()) / HEX_BYTE_SIZE]; + // loop through the string - 2 bytes at a time converting // it to decimal equivalent and store in byte array - while (input.length() > i + 1) { - - bool ok; - uint value = input.mid(i, 2).toUInt(&ok,16); - bytes[x] = (unsigned char)value; - i += 2; - x += 1; + bool ok; + while (stringIndex < input.length()) { + uint value = input.mid(stringIndex, HEX_BYTE_SIZE).toUInt(&ok, HEX_NUMBER_BASE); + if (!ok) { + break; + } + bytes[byteArrayIndex] = (unsigned char)value; + stringIndex += HEX_BYTE_SIZE; + byteArrayIndex++; + } + + // something went wrong + if (!ok) { + delete[] bytes; + return NULL; } - // return the finished byte array of decimal values return bytes; -} \ No newline at end of file +} + +QString JurisdictionMap::octalCodeToHexString(unsigned char* octalCode) const { + const int HEX_NUMBER_BASE = 16; + const int HEX_BYTE_SIZE = 2; + QString output; + if (!octalCode) { + output = "00"; + } else { + for (int i = 0; i < bytesRequiredForCodeLength(*octalCode); i++) { + output.append(QString("%1").arg(octalCode[i], HEX_BYTE_SIZE, HEX_NUMBER_BASE, QChar('0')).toUpper()); + } + } + return output; +} diff --git a/libraries/voxels/src/JurisdictionMap.h b/libraries/voxels/src/JurisdictionMap.h index dd0160e7a1..bf091a6cce 100644 --- a/libraries/voxels/src/JurisdictionMap.h +++ b/libraries/voxels/src/JurisdictionMap.h @@ -30,7 +30,8 @@ private: void clear(); void init(unsigned char* rootOctalCode, const std::vector& endNodes); - unsigned char* hexStringToOctalCode(const QString& input); + unsigned char* hexStringToOctalCode(const QString& input) const; + QString octalCodeToHexString(unsigned char* octalCode) const; unsigned char* _rootOctalCode; diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index ef0a785fc8..0c82bd5f09 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -459,9 +459,9 @@ int main(int argc, const char * argv[]) { printf("after readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); // test writing the file... - //printf("about to writeToFile().... jurisdictionFile=%s\n", jurisdictionFile); - //jurisdiction->writeToFile(jurisdictionFile); - //printf("after writeToFile().... jurisdictionFile=%s\n", jurisdictionFile); + printf("about to writeToFile().... jurisdictionFile=%s\n", jurisdictionFile); + jurisdiction->writeToFile(jurisdictionFile); + printf("after writeToFile().... jurisdictionFile=%s\n", jurisdictionFile); } NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, listenPort); From 11664f94463a0bc4e73aa634a92a5af8930194a3 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 2 Aug 2013 10:12:21 -0700 Subject: [PATCH 20/26] Have the particle system default to off. --- interface/src/Application.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f37241a720..0f87e2f063 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1816,7 +1816,6 @@ void Application::initMenu() { (_renderLookatIndicatorOn = renderMenu->addAction("Lookat Indicator"))->setCheckable(true); _renderLookatIndicatorOn->setChecked(true); (_renderParticleSystemOn = renderMenu->addAction("Particle System"))->setCheckable(true); - _renderParticleSystemOn->setChecked(true); (_manualFirstPerson = renderMenu->addAction( "First Person", this, SLOT(setRenderFirstPerson(bool)), Qt::Key_P))->setCheckable(true); (_manualThirdPerson = renderMenu->addAction( From 8fc800acffbc4689a852ff13c5326cea35216999 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Fri, 2 Aug 2013 10:59:04 -0700 Subject: [PATCH 21/26] some work on hands --- interface/src/Application.cpp | 1 + interface/src/avatar/Hand.cpp | 10 +++++----- libraries/avatars/src/AvatarData.cpp | 17 +++++++++++++++++ libraries/avatars/src/HandData.cpp | 5 ++++- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9b292b3d50..8048d437b7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2024,6 +2024,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; diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 2e409a10bf..7e5652c5d5 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -51,6 +51,7 @@ void Hand::reset() { void Hand::simulate(float deltaTime, bool isMine) { + if (_isRaveGloveActive) { updateRaveGloveParticles(deltaTime); } @@ -120,9 +121,9 @@ void Hand::render(bool lookingInMirror) { glEnable(GL_RESCALE_NORMAL); if ( SHOW_LEAP_HAND ) { - renderLeapHands(); - //renderFingerTrails(); - //renderHandSpheres(); + //renderLeapHands(); + renderLeapFingerTrails(); + renderLeapHandSpheres(); } } @@ -155,7 +156,6 @@ void Hand::renderRaveGloveStage() { } - void Hand::renderLeapHands() { for (size_t i = 0; i < getNumPalms(); ++i) { PalmData& hand = getPalms()[i]; @@ -165,7 +165,6 @@ void Hand::renderLeapHands() { } } - void Hand::renderLeapHand(PalmData& hand) { glPushMatrix(); @@ -265,6 +264,7 @@ void Hand::renderLeapFingerTrails() { } } + void Hand::setLeapHands(const std::vector& handPositions, const std::vector& handNormals) { for (size_t i = 0; i < getNumPalms(); ++i) { diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 65ae0c6952..9c254453e1 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -130,6 +130,8 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { // leap hand data std::vector 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 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); } } diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 7bb6eebdc0..605442c926 100755 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -51,12 +51,15 @@ _owningHandData(owningHandData) void HandData::encodeRemoteData(std::vector& fingerVectors) { fingerVectors.clear(); + for (size_t i = 0; i < getNumPalms(); ++i) { + PalmData& palm = getPalms()[i]; fingerVectors.push_back(palm.getRawPosition()); 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()); @@ -82,7 +85,7 @@ void HandData::decodeRemoteData(const std::vector& fingerVectors) { if (palmActive) { palm.setRawPosition(fingerVectors[vectorIndex++]); palm.setRawNormal(fingerVectors[vectorIndex++]); - for (size_t f = 0; f < NUM_FINGERS_PER_HAND; ++f) { + for (size_t f = 0; f < NUM_FINGERS_PER_HAND; ++f) { FingerData& finger = palm.getFingers()[i]; finger.setRawTipPosition(fingerVectors[vectorIndex++]); finger.setRawRootPosition(fingerVectors[vectorIndex++]); From c60acfad28f2b8db157fc21e8e852786dfc63580 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Fri, 2 Aug 2013 11:00:53 -0700 Subject: [PATCH 22/26] merge --- libraries/avatars/src/HandData.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) mode change 100755 => 100644 libraries/avatars/src/HandData.cpp diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp old mode 100755 new mode 100644 index 541c223e4e..0b91191d92 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -88,8 +88,9 @@ void HandData::decodeRemoteData(const std::vector& fingerVectors) { if (palmActive) { palm.setRawPosition(fingerVectors[vectorIndex++]); palm.setRawNormal(fingerVectors[vectorIndex++]); - for (size_t f = 0; f < NUM_FINGERS_PER_HAND; ++f) { - FingerData& finger = palm.getFingers()[i]; + for (size_t f = 0; f < NUM_FINGERS_PER_HAND; ++f) { + FingerData& finger = palm.getFingers()[f]; + finger.setActive(true); finger.setRawTipPosition(fingerVectors[vectorIndex++]); finger.setRawRootPosition(fingerVectors[vectorIndex++]); } From 558fca79360c69e451e20a550bcdf345e73cd0f7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 2 Aug 2013 11:12:33 -0700 Subject: [PATCH 23/26] latest jurisdiction work --- libraries/shared/src/OctalCode.cpp | 39 ++++++++++++++++++++++++ libraries/shared/src/OctalCode.h | 4 ++- libraries/voxels/src/JurisdictionMap.cpp | 30 ++++++++++++++++-- libraries/voxels/src/JurisdictionMap.h | 11 ++++--- libraries/voxels/src/VoxelTree.cpp | 15 +++++++-- voxel-server/src/main.cpp | 7 ++--- 6 files changed, 92 insertions(+), 14 deletions(-) diff --git a/libraries/shared/src/OctalCode.cpp b/libraries/shared/src/OctalCode.cpp index b085a146a2..8acc9a922f 100644 --- a/libraries/shared/src/OctalCode.cpp +++ b/libraries/shared/src/OctalCode.cpp @@ -257,3 +257,42 @@ unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* return newCode; } +bool isAncestorOf(unsigned char* possibleAncestor, unsigned char* possibleDescendent, int descendentsChild) { + if (!possibleAncestor || !possibleDescendent) { + return false; + } + + int ancestorCodeLength = numberOfThreeBitSectionsInCode(possibleAncestor); + if (ancestorCodeLength == 0) { + return true; // this is the root, it's the anscestor of all + } + + int descendentCodeLength = numberOfThreeBitSectionsInCode(possibleDescendent); + + // if the caller also include a child, then our descendent length is actually one extra! + if (descendentsChild != CHECK_NODE_ONLY) { + descendentCodeLength++; + } + + if (ancestorCodeLength > descendentCodeLength) { + return false; // if the descendent is shorter, it can't be a descendent + } + + // compare the sections for the ancestor to the descendent + for (int section = 0; section < ancestorCodeLength; section++) { + char sectionValueAncestor = getOctalCodeSectionValue(possibleAncestor, section); + char sectionValueDescendent; + if (ancestorCodeLength <= descendentCodeLength) { + sectionValueDescendent = getOctalCodeSectionValue(possibleDescendent, section); + } else { + assert(descendentsChild != CHECK_NODE_ONLY); + sectionValueDescendent = descendentsChild; + } + if (sectionValueAncestor != sectionValueDescendent) { + return false; // first non-match, means they don't match + } + } + + // they all match, so we are an ancestor + return true; +} diff --git a/libraries/shared/src/OctalCode.h b/libraries/shared/src/OctalCode.h index 228d5f72b5..477751ea7c 100644 --- a/libraries/shared/src/OctalCode.h +++ b/libraries/shared/src/OctalCode.h @@ -21,7 +21,6 @@ const int BLUE_INDEX = 2; void printOctalCode(unsigned char * octalCode); int bytesRequiredForCodeLength(unsigned char threeBitCodes); -bool isDirectParentOfChild(unsigned char *parentOctalCode, unsigned char * childOctalCode); int branchIndexWithDescendant(unsigned char * ancestorOctalCode, unsigned char * descendantOctalCode); unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber); int numberOfThreeBitSectionsInCode(unsigned char * octalCode); @@ -29,6 +28,9 @@ unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels); unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode, bool includeColorSpace = false); +const int CHECK_NODE_ONLY = -1; +bool isAncestorOf(unsigned char* possibleAncestor, unsigned char* possibleDescendent, int descendentsChild = CHECK_NODE_ONLY); + // Note: copyFirstVertexForCode() is preferred because it doesn't allocate memory for the return // but other than that these do the same thing. float * firstVertexForCode(unsigned char * octalCode); diff --git a/libraries/voxels/src/JurisdictionMap.cpp b/libraries/voxels/src/JurisdictionMap.cpp index 5c1fc5c52f..b67963d8d6 100644 --- a/libraries/voxels/src/JurisdictionMap.cpp +++ b/libraries/voxels/src/JurisdictionMap.cpp @@ -56,8 +56,34 @@ void JurisdictionMap::init(unsigned char* rootOctalCode, const std::vector=0) - && (emitterIndex < NUM_FINGERS)) { - - _raveGloveParticleSystem.setEmitterActive(_raveGloveEmitter[emitterIndex], false); // set to false by default... - - if (finger.isActive()) { - _raveGloveParticleSystem.setEmitterActive(_raveGloveEmitter[emitterIndex], true); - - 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); } } } diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 2ee066d7b6..beb7b8d516 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -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 _leapBalls; + std::vector _leapFingerTipBalls; + std::vector _leapFingerRootBalls; // private methods void setLeapHands(const std::vector& handPositions, From 9bd4c84bfcbed2107b9176d98a641884a0a2352e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 2 Aug 2013 13:47:10 -0700 Subject: [PATCH 25/26] added README --- voxel-server/src/README | 80 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 voxel-server/src/README diff --git a/voxel-server/src/README b/voxel-server/src/README new file mode 100644 index 0000000000..81824d96a9 --- /dev/null +++ b/voxel-server/src/README @@ -0,0 +1,80 @@ +NAME + voxel-server - the High Fidelity Voxel Server + +SYNOPSIS + voxel-server [--local] [--jurisdictionFile ] [--port ] [--voxelsPersistFilename ] + [--displayVoxelStats] [--debugVoxelSending] [--debugVoxelReceiving] [--shouldShowAnimationDebug] + [--wantColorRandomizer] [--NoVoxelPersist] [--packetsPerSecond ] + [--AddRandomVoxels] [--AddScene] [--NoAddScene] + +DESCRIPTION + voxel-server is a compact, portable, scalable, distributed sparse voxel octree server + +OPTIONS + + --local + This will run the voxel server in "local domain mode" and will look for a domain-server running on the same IP + address as the voxel server + + --jurisdictionFile [filename] + Tells the server to load it's jurisdiction from the specified file. When a voxel server is running with a limited + "jurisdiction" it will only server voxels from that portion of the voxel tree. The jurisdiction file is a ".ini" style + file with the following options: [General/root] specifies the octal code for the node in the tree that this server will + use as it's "root". It will only server voxels under this root. [endNodes/...] a list or group of additional octalcodes + under the root, which will not be served. + + The following example jurisdiction file will server all voxels from the root and below, and exclude voxels from the + voxel of scale 0.25 and 0,0,0. + + ****** example jurisdiction.ini ********************************************************************** + [General] + root=00 + + [endNodes] + endnode0=0200 + + ****************************************************************************************************** + + + --port [port] + Specify the port the voxel-server will listen on. You must specify different ports to enable multiple voxel servers + running on a single machine. + + --voxelsPersistFilename [filename] + Specify and alternate file that the voxel server will read and write persistant voxels to. By default the voxel server + will use one of the following files: + + default: /etc/highfidelity/voxel-server/resources/voxels.svo + in local mode: ./resources/voxels.svo + + --displayVoxelStats + Displays additional voxel stats debugging + + --debugVoxelSending + Displays additional voxel sending debugging + + --debugVoxelReceiving + Displays additional voxel receiving debugging + + --shouldShowAnimationDebug + Displays additional verbose animation debugging + + --wantColorRandomizer + Adds color randomization to inserts into the local voxel tree + + --NoVoxelPersist + Disables voxel persisting + + --packetsPerSecond [value] + Specifies the packets per second that this voxel server will send to attached clients + + --AddRandomVoxels + Add random voxels to the surface on startup + + --AddScene + OBSOLETE: Adds an arbitrary scene with several "planet" spheres + + --NoAddScene + OBSOLETE: disables adding of scene + + \ No newline at end of file From 29c5511a543401ee1e0bbf2441cb68f947667d70 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Fri, 2 Aug 2013 13:49:50 -0700 Subject: [PATCH 26/26] test --- interface/src/avatar/Hand.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index e5afe7e654..45a2117285 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -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;