From c957dcceb50f4a6ae3995a826fc4f811f84c70bc Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Sat, 8 Feb 2014 02:21:00 +0100 Subject: [PATCH 01/83] ADDED the fields in interface-preferences for display name editting --- interface/src/Menu.cpp | 5 +++++ interface/src/avatar/Profile.cpp | 5 +++++ interface/src/avatar/Profile.h | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 709f848a2f..6e48da0070 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -770,6 +770,11 @@ void Menu::editPreferences() { skeletonURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); form->addRow("Skeleton URL:", skeletonURLEdit); + QString displayNameString = applicationInstance->getProfile()->getDisplayName(); + QLineEdit* displayNameEdit = new QLineEdit(displayNameString); + displayNameEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); + form->addRow("Display name:", displayNameEdit); + QSlider* pupilDilation = new QSlider(Qt::Horizontal); pupilDilation->setValue(applicationInstance->getAvatar()->getHead().getPupilDilation() * pupilDilation->maximum()); form->addRow("Pupil Dilation:", pupilDilation); diff --git a/interface/src/avatar/Profile.cpp b/interface/src/avatar/Profile.cpp index 902a0ea12a..f0dcbec9c1 100644 --- a/interface/src/avatar/Profile.cpp +++ b/interface/src/avatar/Profile.cpp @@ -17,6 +17,7 @@ Profile::Profile(const QString &username) : _username(), + _displayName(), _uuid(), _lastDomain(), _lastPosition(0.0, 0.0, 0.0), @@ -211,3 +212,7 @@ void Profile::processDataServerResponse(const QString& userString, const QString void Profile::setUsername(const QString& username) { _username = username; } + +void Profile::setDisplayName(const QString& displayName) { + _displayName = displayName; +} diff --git a/interface/src/avatar/Profile.h b/interface/src/avatar/Profile.h index 5cb2295f5b..1709bbde04 100644 --- a/interface/src/avatar/Profile.h +++ b/interface/src/avatar/Profile.h @@ -27,6 +27,8 @@ public: QString getUserString() const; const QString& getUsername() const { return _username; } + + const QString& getDisplayName() const { return _displayName; } void setUUID(const QUuid& uuid); const QUuid& getUUID() { return _uuid; } @@ -51,8 +53,11 @@ public: private: void setUsername(const QString& username); + + void setDisplayName(const QString& displaName); QString _username; + QString _displayName; QUuid _uuid; QString _lastDomain; glm::vec3 _lastPosition; From d05fb392e0f8b74e78decfcdd347d13242f4d0a2 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Sun, 9 Feb 2014 23:39:53 +0100 Subject: [PATCH 02/83] Always facing camera billboard TODO: having constant fix size --- interface/src/avatar/AvatarManager.cpp | 86 ++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index a4a85f5770..5bad11d4c5 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -8,6 +8,7 @@ #include #include +#include #include "Application.h" #include "Avatar.h" @@ -74,6 +75,91 @@ void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { "Application::renderAvatars()"); bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors); + // ------------------------------------------------------------------------------------- + // Josecpujol(begin): test code, as I dont seem to get any avatar. Render some text here + // ------------------------------------------------------------------------------------- + glm::dvec3 textPosition(100.0, 50.0, 100.0); + char text[] = "my string"; + + // Draw a fake avatar + glPushMatrix(); + glColor3f(1.0,0,0); + double radius = 10.0; + glTranslated(textPosition.x, textPosition.y - 2 * radius, textPosition.z); + glutSolidSphere(radius, 10, 10); + glPopMatrix(); + + // Draw a mark where the text should be + glPushMatrix(); + glColor3f(1.0,1.0,0); + glTranslated(textPosition.x, textPosition.y, textPosition.z); + glutSolidSphere(1.0, 10, 10); + glPopMatrix(); + + glPushMatrix(); + glTranslated(textPosition.x, textPosition.y, textPosition.z); + // Extract rotation matrix from the modelview matrix + glm::dmat4 modelViewMatrix; + + glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&modelViewMatrix); + glm::dmat4 modelViewMatrix2(modelViewMatrix); + glm::dvec3 upVector(modelViewMatrix[1]); + + // Delete rotation info + modelViewMatrix[0][0] = modelViewMatrix[1][1] = modelViewMatrix[2][2] = 1.0; + modelViewMatrix[0][1] = modelViewMatrix[0][2] = 0.0; + modelViewMatrix[1][0] = modelViewMatrix[1][2] = 0.0; + modelViewMatrix[2][0] = modelViewMatrix[2][1] = 0.0; + + glLoadMatrixd((GLdouble*)&modelViewMatrix); // Override current matrix with our own + glScalef(1.0, -1.0, 1.0); // TextRenderer::draw paints the text upside down. This fixes that + + // We need to compute the scale factor such as the text remains with fixed size respect to window coordinates + // We project y = 0 and y = 1 and check the difference in projection coordinates + + GLdouble projectionMatrix[16]; + GLint viewportMatrix[4]; + GLdouble result0[3]; + GLdouble result1[3]; + glGetDoublev(GL_PROJECTION_MATRIX, (GLdouble*)&projectionMatrix); + glGetIntegerv(GL_VIEWPORT, viewportMatrix); + + glm::dvec3 testPoint0 = textPosition; + glm::dvec3 testPoint1 = textPosition + upVector; + + bool success; + success = gluProject(testPoint0.x, testPoint0.y, testPoint0.z, + (GLdouble*)&modelViewMatrix2, projectionMatrix, viewportMatrix, + &result0[0], &result0[1], &result0[2]); + success = success && + gluProject(testPoint1.x, testPoint1.y, testPoint1.z, + (GLdouble*)&modelViewMatrix2, projectionMatrix, viewportMatrix, + &result1[0], &result1[1], &result1[2]); + + if (success) { + double textWindowHeight = abs(result1[1] - result0[1]); + std::cout << "diff x=" << result1[0] - result0[0] << " diff y="<< result1[1] - result0[1] << " diff z="<< result1[2] - result0[2] << std::endl; + float textPointSize = 12.0; + float scaleFactor = textPointSize / textWindowHeight; + + // glScalef(scaleFactor, scaleFactor, 1.0); + + glColor3f(0.0f, 1.0f, 0.0f); + + // TextRenderer, based on QT opengl text rendering functions + TextRenderer* renderer = new TextRenderer(SANS_FONT_FAMILY, 24, -1, false, TextRenderer::SHADOW_EFFECT); + renderer->draw(0,0, text); + delete renderer; + } + + glPopMatrix(); + + // ------------------------------------------------------------------------------------- + // josecpujol(end) + // ------------------------------------------------------------------------------------- + + + if (!selfAvatarOnly) { foreach (const AvatarSharedPointer& avatarPointer, _avatarHash) { Avatar* avatar = static_cast(avatarPointer.data()); From 4aa053befe3d4f2c81266f0c2a75c0c41c531414 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Sun, 9 Feb 2014 23:59:51 +0100 Subject: [PATCH 03/83] Constant size in 3D world billboard text --- interface/src/avatar/AvatarManager.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 5bad11d4c5..985a642e56 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -97,13 +97,12 @@ void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { glPopMatrix(); glPushMatrix(); + glm::dmat4 modelViewMatrix2; + glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&modelViewMatrix2); glTranslated(textPosition.x, textPosition.y, textPosition.z); // Extract rotation matrix from the modelview matrix glm::dmat4 modelViewMatrix; - glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&modelViewMatrix); - glm::dmat4 modelViewMatrix2(modelViewMatrix); - glm::dvec3 upVector(modelViewMatrix[1]); // Delete rotation info modelViewMatrix[0][0] = modelViewMatrix[1][1] = modelViewMatrix[2][2] = 1.0; @@ -116,16 +115,17 @@ void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { // We need to compute the scale factor such as the text remains with fixed size respect to window coordinates // We project y = 0 and y = 1 and check the difference in projection coordinates - GLdouble projectionMatrix[16]; GLint viewportMatrix[4]; GLdouble result0[3]; GLdouble result1[3]; + + glm::dvec3 upVector(modelViewMatrix2[1]); glGetDoublev(GL_PROJECTION_MATRIX, (GLdouble*)&projectionMatrix); glGetIntegerv(GL_VIEWPORT, viewportMatrix); glm::dvec3 testPoint0 = textPosition; - glm::dvec3 testPoint1 = textPosition + upVector; + glm::dvec3 testPoint1 = textPosition + upVector; bool success; success = gluProject(testPoint0.x, testPoint0.y, testPoint0.z, @@ -138,16 +138,15 @@ void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { if (success) { double textWindowHeight = abs(result1[1] - result0[1]); - std::cout << "diff x=" << result1[0] - result0[0] << " diff y="<< result1[1] - result0[1] << " diff z="<< result1[2] - result0[2] << std::endl; - float textPointSize = 12.0; - float scaleFactor = textPointSize / textWindowHeight; + float textScale = 1.0; + float scaleFactor = textScale / textWindowHeight; - // glScalef(scaleFactor, scaleFactor, 1.0); + glScalef(scaleFactor, scaleFactor, 1.0); - glColor3f(0.0f, 1.0f, 0.0f); + glColor3f(1.0, 1.0, 0.0); // TextRenderer, based on QT opengl text rendering functions - TextRenderer* renderer = new TextRenderer(SANS_FONT_FAMILY, 24, -1, false, TextRenderer::SHADOW_EFFECT); + TextRenderer* renderer = new TextRenderer(SANS_FONT_FAMILY, 24, -1, false, TextRenderer::NO_EFFECT); renderer->draw(0,0, text); delete renderer; } From b42c2a9dbea8a0175fe03d58526089827b807989 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Mon, 10 Feb 2014 23:55:43 +0100 Subject: [PATCH 04/83] Centered text --- interface/src/avatar/AvatarManager.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 985a642e56..71f963a211 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -5,7 +5,7 @@ // Created by Stephen Birarda on 1/23/2014. // Copyright (c) 2014 HighFidelity, Inc. All rights reserved. // - +#include #include #include #include @@ -79,7 +79,7 @@ void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { // Josecpujol(begin): test code, as I dont seem to get any avatar. Render some text here // ------------------------------------------------------------------------------------- glm::dvec3 textPosition(100.0, 50.0, 100.0); - char text[] = "my string"; + std::string text("my string"); // Draw a fake avatar glPushMatrix(); @@ -143,12 +143,16 @@ void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { glScalef(scaleFactor, scaleFactor, 1.0); - glColor3f(1.0, 1.0, 0.0); - + glColor3f(0.93, 0.93, 0.93); + // TextRenderer, based on QT opengl text rendering functions - TextRenderer* renderer = new TextRenderer(SANS_FONT_FAMILY, 24, -1, false, TextRenderer::NO_EFFECT); - renderer->draw(0,0, text); - delete renderer; + TextRenderer* textRenderer = new TextRenderer(SANS_FONT_FAMILY, 12, -1, false, TextRenderer::NO_EFFECT); + int width = 0; + for (std::string::iterator it = text.begin(); it != text.end(); it++) { + width += (textRenderer->computeWidth(*it)); + } + textRenderer->draw(-width/2.0, 0, text.c_str()); + delete textRenderer; } glPopMatrix(); From 319d1f67959922a2cd47d6b9ef7779aedfca7913 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Wed, 12 Feb 2014 00:54:50 +0100 Subject: [PATCH 05/83] Wired up the send of the display data to the servers Added the renderDisplayName in Avatar --- interface/src/Menu.cpp | 7 ++ interface/src/avatar/Avatar.cpp | 113 ++++++++++++++++++++++--- interface/src/avatar/Avatar.h | 8 ++ interface/src/avatar/AvatarManager.cpp | 86 ------------------- libraries/avatars/src/AvatarData.cpp | 18 +++- libraries/avatars/src/AvatarData.h | 3 + 6 files changed, 135 insertions(+), 100 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 49c2df15c3..6dbbf176ee 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -858,7 +858,14 @@ void Menu::editPreferences() { applicationInstance->getAvatar()->setSkeletonModelURL(skeletonModelURL); shouldDispatchIdentityPacket = true; } + + QString displayNameStr(displayNameEdit->text()); + if (displayNameStr != displayNameString) { + applicationInstance->getAvatar()->setDisplayName(displayNameStr); + shouldDispatchIdentityPacket = true; + } + if (shouldDispatchIdentityPacket) { applicationInstance->getAvatar()->sendIdentityPacket(); } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 131eb4d37f..dc92d1eed9 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -28,6 +28,7 @@ #include "devices/OculusManager.h" #include "ui/TextRenderer.h" + using namespace std; const glm::vec3 DEFAULT_UP_DIRECTION(0.0f, 1.0f, 0.0f); @@ -74,7 +75,8 @@ Avatar::Avatar() : _mouseRayDirection(0.0f, 0.0f, 0.0f), _moving(false), _owningAvatarMixer(), - _initialized(false) + _initialized(false), + _displayNameWidth(0) { // we may have been created in the network thread, but we live in the main thread moveToThread(Application::getInstance()->thread()); @@ -82,6 +84,8 @@ Avatar::Avatar() : // give the pointer to our head to inherited _headData variable from AvatarData _headData = &_head; _handData = &_hand; + + } Avatar::~Avatar() { @@ -145,22 +149,27 @@ void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction) { _mouseRayDirection = direction; } -static TextRenderer* textRenderer() { +static TextRenderer* chatTextRenderer() { static TextRenderer* renderer = new TextRenderer(SANS_FONT_FAMILY, 24, -1, false, TextRenderer::SHADOW_EFFECT); return renderer; } +static TextRenderer* displayNameTextRenderer() { + static TextRenderer* renderer = new TextRenderer(SANS_FONT_FAMILY, 12, -1, false, TextRenderer::SHADOW_EFFECT); + return renderer; +} + void Avatar::render(bool forceRenderHead) { - + { // glow when moving in the distance glm::vec3 toTarget = _position - Application::getInstance()->getAvatar()->getPosition(); const float GLOW_DISTANCE = 5.0f; Glower glower(_moving && glm::length(toTarget) > GLOW_DISTANCE ? 1.0f : 0.0f); - + // render body renderBody(forceRenderHead); - + // render sphere when far away const float MAX_ANGLE = 10.f; float height = getHeight(); @@ -176,13 +185,15 @@ void Avatar::render(bool forceRenderHead) { glPopMatrix(); } } - - + + // render display name + renderDisplayName(); + if (!_chatMessage.empty()) { int width = 0; int lastWidth = 0; for (string::iterator it = _chatMessage.begin(); it != _chatMessage.end(); it++) { - width += (lastWidth = textRenderer()->computeWidth(*it)); + width += (lastWidth = chatTextRenderer()->computeWidth(*it)); } glPushMatrix(); @@ -201,7 +212,7 @@ void Avatar::render(bool forceRenderHead) { glDisable(GL_LIGHTING); glDepthMask(false); if (_keyState == NO_KEY_DOWN) { - textRenderer()->draw(-width / 2.0f, 0, _chatMessage.c_str()); + chatTextRenderer()->draw(-width / 2.0f, 0, _chatMessage.c_str()); } else { // rather than using substr and allocating a new string, just replace the last @@ -209,10 +220,10 @@ void Avatar::render(bool forceRenderHead) { int lastIndex = _chatMessage.size() - 1; char lastChar = _chatMessage[lastIndex]; _chatMessage[lastIndex] = '\0'; - textRenderer()->draw(-width / 2.0f, 0, _chatMessage.c_str()); + chatTextRenderer()->draw(-width / 2.0f, 0, _chatMessage.c_str()); _chatMessage[lastIndex] = lastChar; glColor3f(0, 1, 0); - textRenderer()->draw(width / 2.0f - lastWidth, 0, _chatMessage.c_str() + lastIndex); + chatTextRenderer()->draw(width / 2.0f - lastWidth, 0, _chatMessage.c_str() + lastIndex); } glEnable(GL_LIGHTING); glDepthMask(true); @@ -248,6 +259,77 @@ void Avatar::renderBody(bool forceRenderHead) { _hand.render(false); } +void Avatar::renderDisplayName() { + + if (_displayNameStr.isEmpty()) { + return; + } + + glm::vec3 textPosition = _head.getPosition(); //+ glm::vec3(0,50,0); + glPushMatrix(); + glDepthMask(false); + + glm::dmat4 modelViewMatrix2; + glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&modelViewMatrix2); + glTranslatef(textPosition.x, textPosition.y, textPosition.z); + // Extract rotation matrix from the modelview matrix + glm::dmat4 modelViewMatrix; + glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&modelViewMatrix); + + // Delete rotation info + modelViewMatrix[0][0] = modelViewMatrix[1][1] = modelViewMatrix[2][2] = 1.0; + modelViewMatrix[0][1] = modelViewMatrix[0][2] = 0.0; + modelViewMatrix[1][0] = modelViewMatrix[1][2] = 0.0; + modelViewMatrix[2][0] = modelViewMatrix[2][1] = 0.0; + + glLoadMatrixd((GLdouble*)&modelViewMatrix); // Override current matrix with our own + glScalef(1.0, -1.0, 1.0); // TextRenderer::draw paints the text upside down. This fixes that + + // We need to compute the scale factor such as the text remains with fixed size respect to window coordinates + // We project y = 0 and y = 1 and check the difference in projection coordinates + GLdouble projectionMatrix[16]; + GLint viewportMatrix[4]; + GLdouble result0[3]; + GLdouble result1[3]; + + glm::dvec3 upVector(modelViewMatrix2[1]); + glGetDoublev(GL_PROJECTION_MATRIX, (GLdouble*)&projectionMatrix); + glGetIntegerv(GL_VIEWPORT, viewportMatrix); + + glm::dvec3 testPoint0 = glm::dvec3(textPosition); + glm::dvec3 testPoint1 = glm::dvec3(textPosition) + upVector; + + bool success; + success = gluProject(testPoint0.x, testPoint0.y, testPoint0.z, + (GLdouble*)&modelViewMatrix2, projectionMatrix, viewportMatrix, + &result0[0], &result0[1], &result0[2]); + success = success && + gluProject(testPoint1.x, testPoint1.y, testPoint1.z, + (GLdouble*)&modelViewMatrix2, projectionMatrix, viewportMatrix, + &result1[0], &result1[1], &result1[2]); + + if (success) { + double textWindowHeight = abs(result1[1] - result0[1]); + float textScale = 1.0; + float scaleFactor = 1.0; + if (textWindowHeight > EPSILON) { + scaleFactor = textScale / textWindowHeight; + } + + glScalef(scaleFactor, scaleFactor, 1.0); + + glColor3f(0.93, 0.93, 0.93); + + // TextRenderer, based on QT opengl text rendering functions + + QByteArray ba = _displayNameStr.toLocal8Bit(); + const char *text = ba.data(); + displayNameTextRenderer()->draw(-_displayNameWidth/2.0, 0, text); + } + glDepthMask(true); + glPopMatrix(); +} + bool Avatar::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { float minDistance = FLT_MAX; float modelDistance; @@ -346,6 +428,15 @@ void Avatar::setSkeletonModelURL(const QUrl &skeletonModelURL) { _skeletonModel.setURL(skeletonModelURL); } +void Avatar::setDisplayName(const QString& displayName) { + AvatarData::setDisplayNameStr(displayName); + int width = 0; + for (int i = 0; i < displayName.size(); i++) { + width += (displayNameTextRenderer()->computeWidth(displayName[i].toLatin1())); + } + _displayNameWidth = width; +} + int Avatar::parseData(const QByteArray& packet) { // change in position implies movement glm::vec3 oldPosition = _position; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index dfe72fdc18..41b821838c 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -21,6 +21,7 @@ #include "SkeletonModel.h" #include "world.h" + static const float SCALING_RATIO = .05f; static const float SMOOTHING_RATIO = .05f; // 0 < ratio < 1 static const float RESCALING_TOLERANCE = .02f; @@ -114,6 +115,7 @@ public: virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); + virtual void setDisplayName(const QString& displayName); int parseData(const QByteArray& packet); @@ -152,7 +154,13 @@ private: bool _initialized; + int _displayNameWidth; + + + void renderBody(bool forceRenderHead); + + void renderDisplayName(); }; #endif diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index c9b84a15df..a03492bc9b 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -75,93 +75,7 @@ void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { "Application::renderAvatars()"); bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors); - // ------------------------------------------------------------------------------------- - // Josecpujol(begin): test code, as I dont seem to get any avatar. Render some text here - // ------------------------------------------------------------------------------------- - glm::dvec3 textPosition(100.0, 50.0, 100.0); - std::string text("my string"); - - // Draw a fake avatar - glPushMatrix(); - glColor3f(1.0,0,0); - double radius = 10.0; - glTranslated(textPosition.x, textPosition.y - 2 * radius, textPosition.z); - glutSolidSphere(radius, 10, 10); - glPopMatrix(); - - // Draw a mark where the text should be - glPushMatrix(); - glColor3f(1.0,1.0,0); - glTranslated(textPosition.x, textPosition.y, textPosition.z); - glutSolidSphere(1.0, 10, 10); - glPopMatrix(); - - glPushMatrix(); - glm::dmat4 modelViewMatrix2; - glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&modelViewMatrix2); - glTranslated(textPosition.x, textPosition.y, textPosition.z); - // Extract rotation matrix from the modelview matrix - glm::dmat4 modelViewMatrix; - glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&modelViewMatrix); - // Delete rotation info - modelViewMatrix[0][0] = modelViewMatrix[1][1] = modelViewMatrix[2][2] = 1.0; - modelViewMatrix[0][1] = modelViewMatrix[0][2] = 0.0; - modelViewMatrix[1][0] = modelViewMatrix[1][2] = 0.0; - modelViewMatrix[2][0] = modelViewMatrix[2][1] = 0.0; - - glLoadMatrixd((GLdouble*)&modelViewMatrix); // Override current matrix with our own - glScalef(1.0, -1.0, 1.0); // TextRenderer::draw paints the text upside down. This fixes that - - // We need to compute the scale factor such as the text remains with fixed size respect to window coordinates - // We project y = 0 and y = 1 and check the difference in projection coordinates - GLdouble projectionMatrix[16]; - GLint viewportMatrix[4]; - GLdouble result0[3]; - GLdouble result1[3]; - - glm::dvec3 upVector(modelViewMatrix2[1]); - glGetDoublev(GL_PROJECTION_MATRIX, (GLdouble*)&projectionMatrix); - glGetIntegerv(GL_VIEWPORT, viewportMatrix); - - glm::dvec3 testPoint0 = textPosition; - glm::dvec3 testPoint1 = textPosition + upVector; - - bool success; - success = gluProject(testPoint0.x, testPoint0.y, testPoint0.z, - (GLdouble*)&modelViewMatrix2, projectionMatrix, viewportMatrix, - &result0[0], &result0[1], &result0[2]); - success = success && - gluProject(testPoint1.x, testPoint1.y, testPoint1.z, - (GLdouble*)&modelViewMatrix2, projectionMatrix, viewportMatrix, - &result1[0], &result1[1], &result1[2]); - - if (success) { - double textWindowHeight = abs(result1[1] - result0[1]); - float textScale = 1.0; - float scaleFactor = textScale / textWindowHeight; - - glScalef(scaleFactor, scaleFactor, 1.0); - - glColor3f(0.93, 0.93, 0.93); - - // TextRenderer, based on QT opengl text rendering functions - TextRenderer* textRenderer = new TextRenderer(SANS_FONT_FAMILY, 12, -1, false, TextRenderer::NO_EFFECT); - int width = 0; - for (std::string::iterator it = text.begin(); it != text.end(); it++) { - width += (textRenderer->computeWidth(*it)); - } - textRenderer->draw(-width/2.0, 0, text.c_str()); - delete textRenderer; - } - - glPopMatrix(); - - // ------------------------------------------------------------------------------------- - // josecpujol(end) - // ------------------------------------------------------------------------------------- - - if (!selfAvatarOnly) { foreach (const AvatarSharedPointer& avatarPointer, _avatarHash) { diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index b2cd1cf076..3c711dc127 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -274,7 +274,8 @@ bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) { QUuid avatarUUID; QUrl faceModelURL, skeletonModelURL; - packetStream >> avatarUUID >> faceModelURL >> skeletonModelURL; + QString displayNameStr; + packetStream >> avatarUUID >> faceModelURL >> skeletonModelURL >> displayNameStr; bool hasIdentityChanged = false; @@ -287,7 +288,12 @@ bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) { setSkeletonModelURL(skeletonModelURL); hasIdentityChanged = true; } - + + if (displayNameStr != _displayNameStr) { + setDisplayNameStr(displayNameStr); + hasIdentityChanged = true; + } + return hasIdentityChanged; } @@ -295,7 +301,7 @@ QByteArray AvatarData::identityByteArray() { QByteArray identityData; QDataStream identityStream(&identityData, QIODevice::Append); - identityStream << QUuid() << _faceModelURL << _skeletonModelURL; + identityStream << QUuid() << _faceModelURL << _skeletonModelURL << _displayNameStr; return identityData; } @@ -310,6 +316,12 @@ void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) { _skeletonModelURL = skeletonModelURL; } +void AvatarData::setDisplayNameStr(const QString& displayName) { + qDebug() << "Changing display name for avatar to" << displayName; + _displayNameStr = displayName; +} + + void AvatarData::setClampedTargetScale(float targetScale) { targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 5c3c9ad9af..4fc4e1f4f7 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -149,8 +149,10 @@ public: const QUrl& getFaceModelURL() const { return _faceModelURL; } const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; } + const QString& getDisplayNameStr() const { return _displayNameStr; } virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); + virtual void setDisplayNameStr(const QString& displayName); protected: glm::vec3 _position; @@ -180,6 +182,7 @@ protected: QUrl _faceModelURL; QUrl _skeletonModelURL; + QString _displayNameStr; private: // privatize the copy constructor and assignment operator so they cannot be called AvatarData(const AvatarData&); From 78e15e021268d5bc3ed3a3f9b9dc1f3779e51d08 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Feb 2014 16:03:23 -0800 Subject: [PATCH 06/83] Starting on Visage support. --- cmake/modules/FindVisage.cmake | 0 interface/external/visage/readme.txt | 8 ++++++++ 2 files changed, 8 insertions(+) create mode 100644 cmake/modules/FindVisage.cmake create mode 100644 interface/external/visage/readme.txt diff --git a/cmake/modules/FindVisage.cmake b/cmake/modules/FindVisage.cmake new file mode 100644 index 0000000000..e69de29bb2 diff --git a/interface/external/visage/readme.txt b/interface/external/visage/readme.txt new file mode 100644 index 0000000000..fe2e81f87b --- /dev/null +++ b/interface/external/visage/readme.txt @@ -0,0 +1,8 @@ + +Instructions for adding the Visage driver to Interface +Andrzej Kapolka, February 11, 2014 + +1. Copy the Visage sdk folders (lib, include) into the interface/external/visage folder. This readme.txt should be there as well. + +2. Delete your build directory, run cmake and build, and you should be all set. + From 25066f8b4f81f2d11427d996896c76452a343a00 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Feb 2014 16:44:25 -0800 Subject: [PATCH 07/83] Starting on Visage integration. --- cmake/modules/FindVisage.cmake | 44 ++++++++++++++++++++++++++++ interface/CMakeLists.txt | 14 ++++++++- interface/external/visage/readme.txt | 10 +++++-- interface/src/Application.h | 2 ++ interface/src/devices/Visage.cpp | 36 +++++++++++++++++++++++ interface/src/devices/Visage.h | 28 ++++++++++++++++++ 6 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 interface/src/devices/Visage.cpp create mode 100644 interface/src/devices/Visage.h diff --git a/cmake/modules/FindVisage.cmake b/cmake/modules/FindVisage.cmake index e69de29bb2..a8d1acc30b 100644 --- a/cmake/modules/FindVisage.cmake +++ b/cmake/modules/FindVisage.cmake @@ -0,0 +1,44 @@ +# Try to find the Visage controller library +# +# You must provide a VISAGE_ROOT_DIR which contains lib and include directories +# +# Once done this will define +# +# VISAGE_FOUND - system found Visage +# VISAGE_INCLUDE_DIRS - the Visage include directory +# VISAGE_LIBRARIES - Link this to use Visage +# +# Created on 2/11/2014 by Andrzej Kapolka +# Copyright (c) 2014 High Fidelity +# + +if (VISAGE_LIBRARIES AND VISAGE_INCLUDE_DIRS) + # in cache already + set(VISAGE_FOUND TRUE) +else (VISAGE_LIBRARIES AND VISAGE_INCLUDE_DIRS) + find_path(VISAGE_INCLUDE_DIRS VisageTracker2.h ${VISAGE_ROOT_DIR}/include) + + if (APPLE) + find_library(VISAGE_LIBRARIES libvscore.a ${VISAGE_ROOT_DIR}/lib) + elseif (WIN32) + find_library(VISAGE_LIBRARIES vscore.dll ${VISAGE_ROOT_DIR}/lib) + endif () + + if (VISAGE_INCLUDE_DIRS AND VISAGE_LIBRARIES) + set(VISAGE_FOUND TRUE) + endif (VISAGE_INCLUDE_DIRS AND VISAGE_LIBRARIES) + + if (VISAGE_FOUND) + if (NOT VISAGE_FIND_QUIETLY) + message(STATUS "Found Visage: ${VISAGE_LIBRARIES}") + endif (NOT VISAGE_FIND_QUIETLY) + else (VISAGE_FOUND) + if (VISAGE_FIND_REQUIRED) + message(FATAL_ERROR "Could not find Visage") + endif (VISAGE_FIND_REQUIRED) + endif (VISAGE_FOUND) + + # show the VISAGE_INCLUDE_DIRS and VISAGE_LIBRARIES variables only in the advanced view + mark_as_advanced(VISAGE_INCLUDE_DIRS VISAGE_LIBRARIES) + +endif (VISAGE_LIBRARIES AND VISAGE_INCLUDE_DIRS) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 6af6ed478d..188e7a6995 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -11,6 +11,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake set(FACESHIFT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/faceshift) set(LIBOVR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/LibOVR) set(SIXENSE_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/Sixense) +set(VISAGE_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/visage) if (DEFINED ENV{JOB_ID}) set(BUILD_SEQ $ENV{JOB_ID}) @@ -132,9 +133,10 @@ find_package(Faceshift) find_package(GLM REQUIRED) find_package(LibOVR) find_package(Sixense) +find_package(Visage) find_package(ZLIB) -# likewise with Sixense library for Razer Hydra +# include the Sixense library for Razer Hydra if available if (SIXENSE_FOUND AND NOT DISABLE_SIXENSE) add_definitions(-DHAVE_SIXENSE) include_directories(SYSTEM ${SIXENSE_INCLUDE_DIRS}) @@ -144,6 +146,16 @@ if (SIXENSE_FOUND AND NOT DISABLE_SIXENSE) target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES}) endif (SIXENSE_FOUND AND NOT DISABLE_SIXENSE) +# likewise with Visage library for webcam feature tracking +if (VISAGE_FOUND AND NOT DISABLE_VISAGE) + add_definitions(-DHAVE_VISAGE) + include_directories(SYSTEM ${VISAGE_INCLUDE_DIRS}) + if (APPLE OR UNIX) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${VISAGE_INCLUDE_DIRS}") + endif (APPLE OR UNIX) + target_link_libraries(${TARGET_NAME} ${VISAGE_LIBRARIES}) +endif (VISAGE_FOUND AND NOT DISABLE_VISAGE) + # and with LibOVR for Oculus Rift if (LIBOVR_FOUND AND NOT DISABLE_LIBOVR) add_definitions(-DHAVE_LIBOVR) diff --git a/interface/external/visage/readme.txt b/interface/external/visage/readme.txt index fe2e81f87b..dfb3da3969 100644 --- a/interface/external/visage/readme.txt +++ b/interface/external/visage/readme.txt @@ -2,7 +2,13 @@ Instructions for adding the Visage driver to Interface Andrzej Kapolka, February 11, 2014 -1. Copy the Visage sdk folders (lib, include) into the interface/external/visage folder. This readme.txt should be there as well. +1. Copy the Visage sdk folders (lib, include) into the interface/external/visage folder. + This readme.txt should be there as well. -2. Delete your build directory, run cmake and build, and you should be all set. +2. Copy the Visage configuration data folder (visageSDK-MacOS/Samples/MacOSX/data/) to interface/resources/visage + (i.e., so that interface/resources/visage/candide3.wfm is accessible) + +3. Copy the Visage license file to interface/resources/visage/license.vlc. + +4. Delete your build directory, run cmake and build, and you should be all set. diff --git a/interface/src/Application.h b/interface/src/Application.h index ff6e08758b..b2af223edc 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -55,6 +55,7 @@ #include "avatar/Profile.h" #include "devices/Faceshift.h" #include "devices/SixenseManager.h" +#include "devices/Visage.h" #include "renderer/AmbientOcclusionEffect.h" #include "renderer/GeometryCache.h" #include "renderer/GlowEffect.h" @@ -378,6 +379,7 @@ private: Profile _profile; // The data-server linked profile for this user Faceshift _faceshift; + Visage _visage; SixenseManager _sixenseManager; QStringList _activeScripts; diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp new file mode 100644 index 0000000000..4b986d7db4 --- /dev/null +++ b/interface/src/devices/Visage.cpp @@ -0,0 +1,36 @@ +// +// Visage.cpp +// interface +// +// Created by Andrzej Kapolka on 2/11/14. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifdef HAVE_VISAGE +#include +#endif + +#include + +#include "Visage.h" + +namespace VisageSDK { + void initializeLicenseManager(char* licenseKeyFileName); +} + +using namespace VisageSDK; + +Visage::Visage() { +#ifdef HAVE_VISAGE + switchToResourcesParentIfRequired(); + initializeLicenseManager("resources/visage/license.vlc"); + _tracker = new VisageTracker2("resources/visage/Facial Features Tracker - Asymmetric.cfg"); + _tracker->trackFromCam(); +#endif +} + +Visage::~Visage() { +#ifdef HAVE_VISAGE + delete _tracker; +#endif +} diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h new file mode 100644 index 0000000000..1b9d283bb3 --- /dev/null +++ b/interface/src/devices/Visage.h @@ -0,0 +1,28 @@ +// +// Visage.h +// interface +// +// Created by Andrzej Kapolka on 2/11/14. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__Visage__ +#define __interface__Visage__ + +namespace VisageSDK { + class VisageTracker2; +} + +/// Handles input from the Visage webcam feature tracking software. +class Visage { +public: + + Visage(); + ~Visage(); + +private: + + VisageSDK::VisageTracker2* _tracker; +}; + +#endif /* defined(__interface__Visage__) */ From b3fba320fcd3dced1f9252637eff016a89b23482 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Feb 2014 17:03:24 -0800 Subject: [PATCH 08/83] We need the dependencies, too. --- cmake/modules/FindVisage.cmake | 32 ++++++++++++++++++++++++---- interface/external/visage/readme.txt | 2 +- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/cmake/modules/FindVisage.cmake b/cmake/modules/FindVisage.cmake index a8d1acc30b..600164908c 100644 --- a/cmake/modules/FindVisage.cmake +++ b/cmake/modules/FindVisage.cmake @@ -16,12 +16,36 @@ if (VISAGE_LIBRARIES AND VISAGE_INCLUDE_DIRS) # in cache already set(VISAGE_FOUND TRUE) else (VISAGE_LIBRARIES AND VISAGE_INCLUDE_DIRS) - find_path(VISAGE_INCLUDE_DIRS VisageTracker2.h ${VISAGE_ROOT_DIR}/include) - + find_path(VISAGE_INCLUDE_DIR VisageTracker2.h ${VISAGE_ROOT_DIR}/include) + if (APPLE) - find_library(VISAGE_LIBRARIES libvscore.a ${VISAGE_ROOT_DIR}/lib) + find_path(VISAGE_OPENCV_INCLUDE_DIR cv.h ${VISAGE_ROOT_DIR}/dependencies/OpenCV_MacOSX/include) + if (VISAGE_INCLUDE_DIR AND VISAGE_OPENCV_INCLUDE_DIR) + set(VISAGE_INCLUDE_DIRS "${VISAGE_INCLUDE_DIR};${VISAGE_OPENCV_INCLUDE_DIR}" CACHE INTERNAL "Visage include dirs") + endif (VISAGE_INCLUDE_DIR AND VISAGE_OPENCV_INCLUDE_DIR) + + find_library(VISAGE_CORE_LIBRARY libvscore.a ${VISAGE_ROOT_DIR}/lib) + find_library(VISAGE_VISION_LIBRARY libvsvision.a ${VISAGE_ROOT_DIR}/lib) + find_library(VISAGE_OPENCV_LIBRARY libOpenCV.a ${VISAGE_ROOT_DIR}/dependencies/OpenCV_MacOSX/lib) + if (VISAGE_CORE_LIBRARY AND VISAGE_VISION_LIBRARY AND VISAGE_OPENCV_LIBRARY) + set(VISAGE_LIBRARIES "${VISAGE_CORE_LIBRARY};${VISAGE_VISION_LIBRARY};${VISAGE_OPENCV_LIBRARY}" + CACHE INTERNAL "Visage libraries") + endif (VISAGE_CORE_LIBRARY AND VISAGE_VISION_LIBRARY AND VISAGE_OPENCV_LIBRARY) + elseif (WIN32) - find_library(VISAGE_LIBRARIES vscore.dll ${VISAGE_ROOT_DIR}/lib) + find_path(VISAGE_OPENCV_INCLUDE_DIR cv.h ${VISAGE_ROOT_DIR}/dependencies/OpenCV_Win32/include) + if (VISAGE_INCLUDE_DIR AND VISAGE_OPENCV_INCLUDE_DIR) + set(VISAGE_INCLUDE_DIRS "${VISAGE_INCLUDE_DIR};${VISAGE_OPENCV_INCLUDE_DIR}" CACHE INTERNAL "Visage include dirs") + endif (VISAGE_INCLUDE_DIR AND VISAGE_OPENCV_INCLUDE_DIR) + + find_library(VISAGE_CORE_LIBRARY vscore.lib ${VISAGE_ROOT_DIR}/lib) + find_library(VISAGE_VISION_LIBRARY vsvision.lib ${VISAGE_ROOT_DIR}/lib) + find_library(VISAGE_OPENCV_LIBRARY OpenCV.lib ${VISAGE_ROOT_DIR}/dependencies/OpenCV_Win32/lib) + if (VISAGE_CORE_LIBRARY AND VISAGE_VISION_LIBRARY AND VISAGE_OPENCV_LIBRARY) + set(VISAGE_LIBRARIES "${VISAGE_CORE_LIBRARY};${VISAGE_VISION_LIBRARY};${VISAGE_OPENCV_LIBRARY}" + CACHE INTERNAL "Visage libraries") + endif (VISAGE_CORE_LIBRARY AND VISAGE_VISION_LIBRARY AND VISAGE_OPENCV_LIBRARY) + endif () if (VISAGE_INCLUDE_DIRS AND VISAGE_LIBRARIES) diff --git a/interface/external/visage/readme.txt b/interface/external/visage/readme.txt index dfb3da3969..8aa28f81c4 100644 --- a/interface/external/visage/readme.txt +++ b/interface/external/visage/readme.txt @@ -2,7 +2,7 @@ Instructions for adding the Visage driver to Interface Andrzej Kapolka, February 11, 2014 -1. Copy the Visage sdk folders (lib, include) into the interface/external/visage folder. +1. Copy the Visage sdk folders (lib, include, dependencies) into the interface/external/visage folder. This readme.txt should be there as well. 2. Copy the Visage configuration data folder (visageSDK-MacOS/Samples/MacOSX/data/) to interface/resources/visage From a9b415b0f9dc309677109cf792ede2e6a81d1a01 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Feb 2014 17:22:40 -0800 Subject: [PATCH 09/83] More build settings. --- cmake/modules/FindVisage.cmake | 10 +++++++--- interface/CMakeLists.txt | 5 +++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/cmake/modules/FindVisage.cmake b/cmake/modules/FindVisage.cmake index 600164908c..0b5ac5f563 100644 --- a/cmake/modules/FindVisage.cmake +++ b/cmake/modules/FindVisage.cmake @@ -19,10 +19,14 @@ else (VISAGE_LIBRARIES AND VISAGE_INCLUDE_DIRS) find_path(VISAGE_INCLUDE_DIR VisageTracker2.h ${VISAGE_ROOT_DIR}/include) if (APPLE) + find_path(VISAGE_XML_INCLUDE_DIR libxml/xmlreader.h /usr/include/libxml2) find_path(VISAGE_OPENCV_INCLUDE_DIR cv.h ${VISAGE_ROOT_DIR}/dependencies/OpenCV_MacOSX/include) - if (VISAGE_INCLUDE_DIR AND VISAGE_OPENCV_INCLUDE_DIR) - set(VISAGE_INCLUDE_DIRS "${VISAGE_INCLUDE_DIR};${VISAGE_OPENCV_INCLUDE_DIR}" CACHE INTERNAL "Visage include dirs") - endif (VISAGE_INCLUDE_DIR AND VISAGE_OPENCV_INCLUDE_DIR) + find_path(VISAGE_OPENCV2_INCLUDE_DIR cv.h ${VISAGE_ROOT_DIR}/dependencies/OpenCV_MacOSX/include/opencv2) + if (VISAGE_INCLUDE_DIR AND VISAGE_XML_INCLUDE_DIR AND VISAGE_OPENCV_INCLUDE_DIR AND VISAGE_OPENCV2_INCLUDE_DIR) + set(VISAGE_INCLUDE_DIRS + "${VISAGE_INCLUDE_DIR};${VISAGE_XML_INCLUDE_DIR};${VISAGE_OPENCV_INCLUDE_DIR};${VISAGE_OPENCV2_INCLUDE_DIR}" + CACHE INTERNAL "Visage include dirs") + endif (VISAGE_INCLUDE_DIR AND VISAGE_XML_INCLUDE_DIR AND VISAGE_OPENCV_INCLUDE_DIR AND VISAGE_OPENCV2_INCLUDE_DIR) find_library(VISAGE_CORE_LIBRARY libvscore.a ${VISAGE_ROOT_DIR}/lib) find_library(VISAGE_VISION_LIBRARY libvsvision.a ${VISAGE_ROOT_DIR}/lib) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 188e7a6995..81170b0a57 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -148,10 +148,11 @@ endif (SIXENSE_FOUND AND NOT DISABLE_SIXENSE) # likewise with Visage library for webcam feature tracking if (VISAGE_FOUND AND NOT DISABLE_VISAGE) - add_definitions(-DHAVE_VISAGE) + add_definitions(-DHAVE_VISAGE -DVISAGE_STATIC) include_directories(SYSTEM ${VISAGE_INCLUDE_DIRS}) if (APPLE OR UNIX) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${VISAGE_INCLUDE_DIRS}") + add_definitions(_DMAC_OS_X) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment -isystem ${VISAGE_INCLUDE_DIRS}") endif (APPLE OR UNIX) target_link_libraries(${TARGET_NAME} ${VISAGE_LIBRARIES}) endif (VISAGE_FOUND AND NOT DISABLE_VISAGE) From 87f7e2465fd5bbbdd9fa399627c5d171e547607f Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Feb 2014 17:25:25 -0800 Subject: [PATCH 10/83] Missed a spot. --- cmake/modules/FindVisage.cmake | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cmake/modules/FindVisage.cmake b/cmake/modules/FindVisage.cmake index 0b5ac5f563..4c600755cd 100644 --- a/cmake/modules/FindVisage.cmake +++ b/cmake/modules/FindVisage.cmake @@ -21,7 +21,7 @@ else (VISAGE_LIBRARIES AND VISAGE_INCLUDE_DIRS) if (APPLE) find_path(VISAGE_XML_INCLUDE_DIR libxml/xmlreader.h /usr/include/libxml2) find_path(VISAGE_OPENCV_INCLUDE_DIR cv.h ${VISAGE_ROOT_DIR}/dependencies/OpenCV_MacOSX/include) - find_path(VISAGE_OPENCV2_INCLUDE_DIR cv.h ${VISAGE_ROOT_DIR}/dependencies/OpenCV_MacOSX/include/opencv2) + find_path(VISAGE_OPENCV2_INCLUDE_DIR opencv.hpp ${VISAGE_ROOT_DIR}/dependencies/OpenCV_MacOSX/include/opencv2) if (VISAGE_INCLUDE_DIR AND VISAGE_XML_INCLUDE_DIR AND VISAGE_OPENCV_INCLUDE_DIR AND VISAGE_OPENCV2_INCLUDE_DIR) set(VISAGE_INCLUDE_DIRS "${VISAGE_INCLUDE_DIR};${VISAGE_XML_INCLUDE_DIR};${VISAGE_OPENCV_INCLUDE_DIR};${VISAGE_OPENCV2_INCLUDE_DIR}" @@ -37,10 +37,14 @@ else (VISAGE_LIBRARIES AND VISAGE_INCLUDE_DIRS) endif (VISAGE_CORE_LIBRARY AND VISAGE_VISION_LIBRARY AND VISAGE_OPENCV_LIBRARY) elseif (WIN32) + find_path(VISAGE_XML_INCLUDE_DIR libxml/xmlreader.h /usr/include/libxml2) find_path(VISAGE_OPENCV_INCLUDE_DIR cv.h ${VISAGE_ROOT_DIR}/dependencies/OpenCV_Win32/include) - if (VISAGE_INCLUDE_DIR AND VISAGE_OPENCV_INCLUDE_DIR) - set(VISAGE_INCLUDE_DIRS "${VISAGE_INCLUDE_DIR};${VISAGE_OPENCV_INCLUDE_DIR}" CACHE INTERNAL "Visage include dirs") - endif (VISAGE_INCLUDE_DIR AND VISAGE_OPENCV_INCLUDE_DIR) + find_path(VISAGE_OPENCV2_INCLUDE_DIR opencv.hpp ${VISAGE_ROOT_DIR}/dependencies/OpenCV_Win32/include/opencv2) + if (VISAGE_INCLUDE_DIR AND VISAGE_XML_INCLUDE_DIR AND VISAGE_OPENCV_INCLUDE_DIR AND VISAGE_OPENCV2_INCLUDE_DIR) + set(VISAGE_INCLUDE_DIRS + "${VISAGE_INCLUDE_DIR};${VISAGE_XML_INCLUDE_DIR};${VISAGE_OPENCV_INCLUDE_DIR};${VISAGE_OPENCV2_INCLUDE_DIR}" + CACHE INTERNAL "Visage include dirs") + endif (VISAGE_INCLUDE_DIR AND VISAGE_XML_INCLUDE_DIR AND VISAGE_OPENCV_INCLUDE_DIR AND VISAGE_OPENCV2_INCLUDE_DIR) find_library(VISAGE_CORE_LIBRARY vscore.lib ${VISAGE_ROOT_DIR}/lib) find_library(VISAGE_VISION_LIBRARY vsvision.lib ${VISAGE_ROOT_DIR}/lib) From c07801261415bee79711ddb97ba4ef69b2fb245b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Feb 2014 17:26:31 -0800 Subject: [PATCH 11/83] Sniffing glue, wrong day, etc. --- interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 81170b0a57..e000efa695 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -151,7 +151,7 @@ if (VISAGE_FOUND AND NOT DISABLE_VISAGE) add_definitions(-DHAVE_VISAGE -DVISAGE_STATIC) include_directories(SYSTEM ${VISAGE_INCLUDE_DIRS}) if (APPLE OR UNIX) - add_definitions(_DMAC_OS_X) + add_definitions(-DMAC_OS_X) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment -isystem ${VISAGE_INCLUDE_DIRS}") endif (APPLE OR UNIX) target_link_libraries(${TARGET_NAME} ${VISAGE_LIBRARIES}) From 8206f8d2b3ef4f972aaa8abc8732dda697678ea2 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Feb 2014 19:00:41 -0800 Subject: [PATCH 12/83] Fixes for Windows. Compiles, but the license doesn't work yet. --- cmake/modules/FindVisage.cmake | 8 ++++---- interface/src/devices/Visage.cpp | 12 ++++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/cmake/modules/FindVisage.cmake b/cmake/modules/FindVisage.cmake index 4c600755cd..84f672525d 100644 --- a/cmake/modules/FindVisage.cmake +++ b/cmake/modules/FindVisage.cmake @@ -37,9 +37,9 @@ else (VISAGE_LIBRARIES AND VISAGE_INCLUDE_DIRS) endif (VISAGE_CORE_LIBRARY AND VISAGE_VISION_LIBRARY AND VISAGE_OPENCV_LIBRARY) elseif (WIN32) - find_path(VISAGE_XML_INCLUDE_DIR libxml/xmlreader.h /usr/include/libxml2) - find_path(VISAGE_OPENCV_INCLUDE_DIR cv.h ${VISAGE_ROOT_DIR}/dependencies/OpenCV_Win32/include) - find_path(VISAGE_OPENCV2_INCLUDE_DIR opencv.hpp ${VISAGE_ROOT_DIR}/dependencies/OpenCV_Win32/include/opencv2) + find_path(VISAGE_XML_INCLUDE_DIR libxml/xmlreader.h ${VISAGE_ROOT_DIR}/dependencies/libxml2/include) + find_path(VISAGE_OPENCV_INCLUDE_DIR opencv/cv.h ${VISAGE_ROOT_DIR}/dependencies/OpenCV/include) + find_path(VISAGE_OPENCV2_INCLUDE_DIR cv.h ${VISAGE_ROOT_DIR}/dependencies/OpenCV/include/opencv) if (VISAGE_INCLUDE_DIR AND VISAGE_XML_INCLUDE_DIR AND VISAGE_OPENCV_INCLUDE_DIR AND VISAGE_OPENCV2_INCLUDE_DIR) set(VISAGE_INCLUDE_DIRS "${VISAGE_INCLUDE_DIR};${VISAGE_XML_INCLUDE_DIR};${VISAGE_OPENCV_INCLUDE_DIR};${VISAGE_OPENCV2_INCLUDE_DIR}" @@ -48,7 +48,7 @@ else (VISAGE_LIBRARIES AND VISAGE_INCLUDE_DIRS) find_library(VISAGE_CORE_LIBRARY vscore.lib ${VISAGE_ROOT_DIR}/lib) find_library(VISAGE_VISION_LIBRARY vsvision.lib ${VISAGE_ROOT_DIR}/lib) - find_library(VISAGE_OPENCV_LIBRARY OpenCV.lib ${VISAGE_ROOT_DIR}/dependencies/OpenCV_Win32/lib) + find_library(VISAGE_OPENCV_LIBRARY opencv_core243.lib ${VISAGE_ROOT_DIR}/dependencies/OpenCV/lib) if (VISAGE_CORE_LIBRARY AND VISAGE_VISION_LIBRARY AND VISAGE_OPENCV_LIBRARY) set(VISAGE_LIBRARIES "${VISAGE_CORE_LIBRARY};${VISAGE_VISION_LIBRARY};${VISAGE_OPENCV_LIBRARY}" CACHE INTERNAL "Visage libraries") diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 4b986d7db4..f69121bf7f 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -6,16 +6,20 @@ // Copyright (c) 2014 High Fidelity, Inc. All rights reserved. // +#include + #ifdef HAVE_VISAGE #include #endif -#include - #include "Visage.h" namespace VisageSDK { - void initializeLicenseManager(char* licenseKeyFileName); +#ifdef WIN32 + void __declspec(dllimport) initializeLicenseManager(char* licenseKeyFileName); +#else + void initializeLicenseManager(char* licenseKeyFileName); +#endif } using namespace VisageSDK; @@ -23,7 +27,7 @@ using namespace VisageSDK; Visage::Visage() { #ifdef HAVE_VISAGE switchToResourcesParentIfRequired(); - initializeLicenseManager("resources/visage/license.vlc"); + initializeLicenseManager("resources/visage"); _tracker = new VisageTracker2("resources/visage/Facial Features Tracker - Asymmetric.cfg"); _tracker->trackFromCam(); #endif From b899834c54a89437544fcc4a3bc0d8acf99448c9 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Fri, 14 Feb 2014 00:23:21 +0100 Subject: [PATCH 13/83] Show "displayname" in correct position Show "displayname" when on mouse hover Persistant displayname data --- interface/src/Menu.cpp | 2 +- interface/src/avatar/Avatar.cpp | 28 +++++++++++++++++++--------- interface/src/avatar/Avatar.h | 6 ++++++ interface/src/avatar/MyAvatar.cpp | 7 +++++++ interface/src/avatar/Profile.cpp | 5 ----- interface/src/avatar/Profile.h | 3 --- libraries/avatars/src/AvatarData.cpp | 14 +++++++------- libraries/avatars/src/AvatarData.h | 6 +++--- 8 files changed, 43 insertions(+), 28 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6dbbf176ee..394ca4febd 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -781,7 +781,7 @@ void Menu::editPreferences() { skeletonURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); form->addRow("Skeleton URL:", skeletonURLEdit); - QString displayNameString = applicationInstance->getProfile()->getDisplayName(); + QString displayNameString = applicationInstance->getAvatar()->getDisplayNameStr(); QLineEdit* displayNameEdit = new QLineEdit(displayNameString); displayNameEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); form->addRow("Display name:", displayNameEdit); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index dc92d1eed9..29d9011bac 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -76,7 +76,8 @@ Avatar::Avatar() : _moving(false), _owningAvatarMixer(), _initialized(false), - _displayNameWidth(0) + _displayNameWidth(0), + _isShowDisplayName(false) { // we may have been created in the network thread, but we live in the main thread moveToThread(Application::getInstance()->thread()); @@ -187,7 +188,9 @@ void Avatar::render(bool forceRenderHead) { } // render display name - renderDisplayName(); + if (_isShowDisplayName) { + renderDisplayName(); + } if (!_chatMessage.empty()) { int width = 0; @@ -261,11 +264,14 @@ void Avatar::renderBody(bool forceRenderHead) { void Avatar::renderDisplayName() { - if (_displayNameStr.isEmpty()) { - return; + QString displayName; + if (_displayName.isEmpty()) { + displayName = "test string"; + } else { + displayName = _displayName; } - - glm::vec3 textPosition = _head.getPosition(); //+ glm::vec3(0,50,0); + + glm::vec3 textPosition = getPosition() + getBodyUpDirection() * getHeight(); // Scale is already considered in getHeight glPushMatrix(); glDepthMask(false); @@ -318,11 +324,11 @@ void Avatar::renderDisplayName() { glScalef(scaleFactor, scaleFactor, 1.0); - glColor3f(0.93, 0.93, 0.93); + glColor3f((GLfloat)0.93, (GLfloat)0.93, (GLfloat)0.93); // TextRenderer, based on QT opengl text rendering functions - QByteArray ba = _displayNameStr.toLocal8Bit(); + QByteArray ba = displayName.toLocal8Bit(); const char *text = ba.data(); displayNameTextRenderer()->draw(-_displayNameWidth/2.0, 0, text); } @@ -429,7 +435,7 @@ void Avatar::setSkeletonModelURL(const QUrl &skeletonModelURL) { } void Avatar::setDisplayName(const QString& displayName) { - AvatarData::setDisplayNameStr(displayName); + AvatarData::setDisplayName(displayName); int width = 0; for (int i = 0; i < displayName.size(); i++) { width += (displayNameTextRenderer()->computeWidth(displayName[i].toLatin1())); @@ -519,3 +525,7 @@ float Avatar::getPelvisToHeadLength() const { return glm::distance(_position, _head.getPosition()); } +void Avatar::setShowDisplayName(bool showDisplayName) { + _isShowDisplayName = showDisplayName; +} + diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 41b821838c..0ac5668555 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -116,6 +116,8 @@ public: virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); virtual void setDisplayName(const QString& displayName); + + void setShowDisplayName(bool showDisplayName); int parseData(const QByteArray& packet); @@ -150,11 +152,15 @@ protected: float getPelvisFloatingHeight() const; float getPelvisToHeadLength() const; + + + private: bool _initialized; int _displayNameWidth; + bool _isShowDisplayName; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 98eb9a4431..59055e259e 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -63,6 +63,7 @@ MyAvatar::MyAvatar() : for (int i = 0; i < MAX_DRIVE_KEYS; i++) { _driveKeys[i] = 0.0f; } + setShowDisplayName(true); } MyAvatar::~MyAvatar() { @@ -611,6 +612,7 @@ void MyAvatar::saveData(QSettings* settings) { settings->setValue("faceModelURL", _faceModelURL); settings->setValue("skeletonModelURL", _skeletonModelURL); + settings->setValue("displayName", _displayName); settings->endGroup(); } @@ -638,6 +640,7 @@ void MyAvatar::loadData(QSettings* settings) { setFaceModelURL(settings->value("faceModelURL").toUrl()); setSkeletonModelURL(settings->value("skeletonModelURL").toUrl()); + setDisplayName(settings->value("displayName").toString()); settings->endGroup(); } @@ -689,8 +692,12 @@ void MyAvatar::updateLookAtTargetAvatar(glm::vec3 &eyePosition) { eyePosition = (avatar->getHead().calculateAverageEyePosition() - avatar->getHead().getScalePivot()) * (avatar->getScale() / avatar->getHead().getScale()) + avatar->getHead().getScalePivot(); _lookAtTargetAvatar = avatarPointer; + avatar->setShowDisplayName(true); return; + } else { + avatar->setShowDisplayName(false); } + } _lookAtTargetAvatar.clear(); } diff --git a/interface/src/avatar/Profile.cpp b/interface/src/avatar/Profile.cpp index b910b56f76..a2a412199e 100644 --- a/interface/src/avatar/Profile.cpp +++ b/interface/src/avatar/Profile.cpp @@ -17,7 +17,6 @@ Profile::Profile(const QString &username) : _username(), - _displayName(), _uuid(), _lastDomain(), _lastPosition(0.0, 0.0, 0.0), @@ -166,7 +165,3 @@ void Profile::processDataServerResponse(const QString& userString, const QString void Profile::setUsername(const QString& username) { _username = username; } - -void Profile::setDisplayName(const QString& displayName) { - _displayName = displayName; -} diff --git a/interface/src/avatar/Profile.h b/interface/src/avatar/Profile.h index 41e6b671fb..c1f3f3c4de 100644 --- a/interface/src/avatar/Profile.h +++ b/interface/src/avatar/Profile.h @@ -28,8 +28,6 @@ public: const QString& getUsername() const { return _username; } - const QString& getDisplayName() const { return _displayName; } - void setUUID(const QUuid& uuid) { _uuid = uuid; } const QUuid& getUUID() { return _uuid; } @@ -51,7 +49,6 @@ private: void setDisplayName(const QString& displaName); QString _username; - QString _displayName; QUuid _uuid; QString _lastDomain; glm::vec3 _lastPosition; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 3c711dc127..a16feb8514 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -274,8 +274,8 @@ bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) { QUuid avatarUUID; QUrl faceModelURL, skeletonModelURL; - QString displayNameStr; - packetStream >> avatarUUID >> faceModelURL >> skeletonModelURL >> displayNameStr; + QString displayName; + packetStream >> avatarUUID >> faceModelURL >> skeletonModelURL >> displayName; bool hasIdentityChanged = false; @@ -289,8 +289,8 @@ bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) { hasIdentityChanged = true; } - if (displayNameStr != _displayNameStr) { - setDisplayNameStr(displayNameStr); + if (displayName != _displayName) { + setDisplayName(displayName); hasIdentityChanged = true; } @@ -301,7 +301,7 @@ QByteArray AvatarData::identityByteArray() { QByteArray identityData; QDataStream identityStream(&identityData, QIODevice::Append); - identityStream << QUuid() << _faceModelURL << _skeletonModelURL << _displayNameStr; + identityStream << QUuid() << _faceModelURL << _skeletonModelURL << _displayName; return identityData; } @@ -316,9 +316,9 @@ void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) { _skeletonModelURL = skeletonModelURL; } -void AvatarData::setDisplayNameStr(const QString& displayName) { +void AvatarData::setDisplayName(const QString& displayName) { qDebug() << "Changing display name for avatar to" << displayName; - _displayNameStr = displayName; + _displayName = displayName; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 4fc4e1f4f7..289fd2b21c 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -149,10 +149,10 @@ public: const QUrl& getFaceModelURL() const { return _faceModelURL; } const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; } - const QString& getDisplayNameStr() const { return _displayNameStr; } + const QString& getDisplayNameStr() const { return _displayName; } virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); - virtual void setDisplayNameStr(const QString& displayName); + virtual void setDisplayName(const QString& displayName); protected: glm::vec3 _position; @@ -182,7 +182,7 @@ protected: QUrl _faceModelURL; QUrl _skeletonModelURL; - QString _displayNameStr; + QString _displayName; private: // privatize the copy constructor and assignment operator so they cannot be called AvatarData(const AvatarData&); From 861ae12151c93f69293a49e50d5eea098b378154 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 13 Feb 2014 16:53:17 -0800 Subject: [PATCH 14/83] Added Visage stuff to .gitignore. --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index 62686287bc..087e24208d 100644 --- a/.gitignore +++ b/.gitignore @@ -39,5 +39,11 @@ interface/external/Leap/util/ interface/external/Sixense/include/ interface/external/Sixense/lib/ +# Ignore Visage +interface/external/visage/dependencies/ +interface/external/visage/include/ +interface/external/visage/lib/ +interface/resources/visage/ + # Ignore interfaceCache for Linux users interface/interfaceCache/ From 19cb20f0cd1301449c36c54428c5cf7999472cb2 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Sat, 15 Feb 2014 01:05:21 +0100 Subject: [PATCH 15/83] Added rect around the display name with proper size, paying attention to QFontMetrics data Fully wired up the message sending and receiving from server --- interface/src/Menu.cpp | 2 +- interface/src/avatar/Avatar.cpp | 39 +++++++++++++++++++------- interface/src/avatar/AvatarManager.cpp | 9 ++++-- libraries/avatars/src/AvatarData.cpp | 5 ++-- libraries/avatars/src/AvatarData.h | 2 +- 5 files changed, 41 insertions(+), 16 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 86ab8d0714..bf98738097 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -782,7 +782,7 @@ void Menu::editPreferences() { skeletonURLEdit->setPlaceholderText(DEFAULT_BODY_MODEL_URL.toString()); form->addRow("Skeleton URL:", skeletonURLEdit); - QString displayNameString = applicationInstance->getAvatar()->getDisplayNameStr(); + QString displayNameString = applicationInstance->getAvatar()->getDisplayName(); QLineEdit* displayNameEdit = new QLineEdit(displayNameString); displayNameEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); form->addRow("Display name:", displayNameEdit); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 4c071adf15..837c77b970 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -270,7 +270,7 @@ void Avatar::renderDisplayName() { QString displayName; if (_displayName.isEmpty()) { - displayName = "test string"; + displayName = "test string"; // just for debugging } else { displayName = _displayName; } @@ -278,7 +278,12 @@ void Avatar::renderDisplayName() { glm::vec3 textPosition = getPosition() + getBodyUpDirection() * getHeight(); // Scale is already considered in getHeight glPushMatrix(); glDepthMask(false); + glDisable(GL_LIGHTING); + // Set the correct modelview matrix: set the identity matrix in the rotation part + // [R|t1] = current modelview matrix (the camera rotation and translation) + // [I|t2] = the translation for the text + // We want this final model view matrix: [I | t1 + R*t2] glm::dmat4 modelViewMatrix2; glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&modelViewMatrix2); glTranslatef(textPosition.x, textPosition.y, textPosition.z); @@ -293,7 +298,7 @@ void Avatar::renderDisplayName() { modelViewMatrix[2][0] = modelViewMatrix[2][1] = 0.0; glLoadMatrixd((GLdouble*)&modelViewMatrix); // Override current matrix with our own - glScalef(1.0, -1.0, 1.0); // TextRenderer::draw paints the text upside down. This fixes that + // We need to compute the scale factor such as the text remains with fixed size respect to window coordinates // We project y = 0 and y = 1 and check the difference in projection coordinates @@ -320,22 +325,36 @@ void Avatar::renderDisplayName() { if (success) { double textWindowHeight = abs(result1[1] - result0[1]); - float textScale = 1.0; - float scaleFactor = 1.0; - if (textWindowHeight > EPSILON) { - scaleFactor = textScale / textWindowHeight; - } + float scaleFactor = (textWindowHeight > EPSILON) ? 1.0f / textWindowHeight : 1.0f; + glScalef(scaleFactor, scaleFactor, 1.0); - glScalef(scaleFactor, scaleFactor, 1.0); + // draw a gray background so that we can actually see what we're typing + QFontMetrics metrics = displayNameTextRenderer()->metrics(); + int bottom = -metrics.descent(), top = bottom + metrics.height(); + int left = -_displayNameWidth/2, right = _displayNameWidth/2; + int border = 5; + bottom -= border; + left -= border; + top += border; + right += border; - glColor3f((GLfloat)0.93, (GLfloat)0.93, (GLfloat)0.93); + glColor3f(0.2f, 0.2f, 0.2f); + glBegin(GL_QUADS); + glVertex2f(left, bottom); + glVertex2f(right, bottom); + glVertex2f(right, top); + glVertex2f(left, top); + glEnd(); - // TextRenderer, based on QT opengl text rendering functions + glScalef(1.0f, -1.0f, 1.0f); // TextRenderer::draw paints the text upside down in y axis + glColor3f(0.93f, 0.93f, 0.93f); + QByteArray ba = displayName.toLocal8Bit(); const char *text = ba.data(); displayNameTextRenderer()->draw(-_displayNameWidth/2.0, 0, text); } + glEnable(GL_LIGHTING); glDepthMask(true); glPopMatrix(); } diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 551734666f..026a5d6291 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -187,8 +187,9 @@ void AvatarManager::processAvatarIdentityPacket(const QByteArray &packet) { while (!identityStream.atEnd()) { QUrl faceMeshURL, skeletonURL; - identityStream >> nodeUUID >> faceMeshURL >> skeletonURL; - + QString displayName; + identityStream >> nodeUUID >> faceMeshURL >> skeletonURL >> displayName; + // mesh URL for a UUID, find avatar in our list AvatarSharedPointer matchingAvatar = _avatarHash.value(nodeUUID); if (matchingAvatar) { @@ -201,6 +202,10 @@ void AvatarManager::processAvatarIdentityPacket(const QByteArray &packet) { if (avatar->getSkeletonModelURL() != skeletonURL) { avatar->setSkeletonModelURL(skeletonURL); } + + if (avatar->getDisplayName() != displayName) { + avatar->setDisplayName(displayName); + } } } } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 3cb5a6f0b1..548129b871 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -300,7 +300,7 @@ bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) { QByteArray AvatarData::identityByteArray() { QByteArray identityData; QDataStream identityStream(&identityData, QIODevice::Append); - + identityStream << QUuid() << _faceModelURL << _skeletonModelURL << _displayName; return identityData; @@ -319,8 +319,9 @@ void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) { } void AvatarData::setDisplayName(const QString& displayName) { - qDebug() << "Changing display name for avatar to" << displayName; _displayName = displayName; + + qDebug() << "Changing display name for avatar to" << displayName; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 01cfa6dd58..f5d9da2447 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -148,7 +148,7 @@ public: const QUrl& getFaceModelURL() const { return _faceModelURL; } const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; } - const QString& getDisplayNameStr() const { return _displayName; } + const QString& getDisplayName() const { return _displayName; } virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); virtual void setDisplayName(const QString& displayName); From af48998cc783ddf60d6ee3e8eeed53923abd9e02 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Sat, 15 Feb 2014 18:40:36 +0100 Subject: [PATCH 16/83] Fixed position of display name: we take into account skeleton and head's height Saved opengl state in renderDisplayName Moved display data to AvatarData Unified static chat function for chat and display name --- interface/src/avatar/Avatar.cpp | 99 +++++++++++++++------------- interface/src/avatar/Avatar.h | 9 +-- interface/src/avatar/MyAvatar.cpp | 10 +-- libraries/avatars/src/AvatarData.cpp | 4 +- libraries/avatars/src/AvatarData.h | 4 ++ 5 files changed, 70 insertions(+), 56 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 837c77b970..21aee11936 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -75,9 +75,7 @@ Avatar::Avatar() : _moving(false), _owningAvatarMixer(), _collisionFlags(0), - _initialized(false), - _displayNameWidth(0), - _isShowDisplayName(false) + _initialized(false) { // we may have been created in the network thread, but we live in the main thread moveToThread(Application::getInstance()->thread()); @@ -148,14 +146,23 @@ void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction) { _mouseRayDirection = direction; } -static TextRenderer* chatTextRenderer() { - static TextRenderer* renderer = new TextRenderer(SANS_FONT_FAMILY, 24, -1, false, TextRenderer::SHADOW_EFFECT); - return renderer; -} +enum TextRendererType { + CHAT, + DISPLAYNAME +}; -static TextRenderer* displayNameTextRenderer() { - static TextRenderer* renderer = new TextRenderer(SANS_FONT_FAMILY, 12, -1, false, TextRenderer::SHADOW_EFFECT); - return renderer; +static TextRenderer* textRenderer(TextRendererType type) { + static TextRenderer* chatRenderer = new TextRenderer(SANS_FONT_FAMILY, 24, -1, false, TextRenderer::SHADOW_EFFECT); + static TextRenderer* displayNameRenderer = new TextRenderer(SANS_FONT_FAMILY, 12, -1, false, TextRenderer::NO_EFFECT); + + switch(type) { + case CHAT: + return chatRenderer; + case DISPLAYNAME: + return displayNameRenderer; + } + + return displayNameRenderer; } void Avatar::render(bool forceRenderHead) { @@ -177,7 +184,7 @@ void Avatar::render(bool forceRenderHead) { // render sphere when far away const float MAX_ANGLE = 10.f; - float height = getHeight(); + float height = getSkeletonHeight(); glm::vec3 delta = height * (_head.getCameraOrientation() * IDENTITY_UP) / 2.f; float angle = abs(angleBetween(toTarget + delta, toTarget - delta)); @@ -200,7 +207,7 @@ void Avatar::render(bool forceRenderHead) { int width = 0; int lastWidth = 0; for (string::iterator it = _chatMessage.begin(); it != _chatMessage.end(); it++) { - width += (lastWidth = chatTextRenderer()->computeWidth(*it)); + width += (lastWidth = textRenderer(CHAT)->computeWidth(*it)); } glPushMatrix(); @@ -219,7 +226,7 @@ void Avatar::render(bool forceRenderHead) { glDisable(GL_LIGHTING); glDepthMask(false); if (_keyState == NO_KEY_DOWN) { - chatTextRenderer()->draw(-width / 2.0f, 0, _chatMessage.c_str()); + textRenderer(CHAT)->draw(-width / 2.0f, 0, _chatMessage.c_str()); } else { // rather than using substr and allocating a new string, just replace the last @@ -227,10 +234,10 @@ void Avatar::render(bool forceRenderHead) { int lastIndex = _chatMessage.size() - 1; char lastChar = _chatMessage[lastIndex]; _chatMessage[lastIndex] = '\0'; - chatTextRenderer()->draw(-width / 2.0f, 0, _chatMessage.c_str()); + textRenderer(CHAT)->draw(-width / 2.0f, 0, _chatMessage.c_str()); _chatMessage[lastIndex] = lastChar; glColor3f(0, 1, 0); - chatTextRenderer()->draw(width / 2.0f - lastWidth, 0, _chatMessage.c_str() + lastIndex); + textRenderer(CHAT)->draw(width / 2.0f - lastWidth, 0, _chatMessage.c_str() + lastIndex); } glEnable(GL_LIGHTING); glDepthMask(true); @@ -267,38 +274,32 @@ void Avatar::renderBody(bool forceRenderHead) { } void Avatar::renderDisplayName() { - QString displayName; if (_displayName.isEmpty()) { displayName = "test string"; // just for debugging } else { displayName = _displayName; } - - glm::vec3 textPosition = getPosition() + getBodyUpDirection() * getHeight(); // Scale is already considered in getHeight + + glm::vec3 textPosition = getPosition() + getBodyUpDirection() * (getSkeletonHeight() + getHeadHeight()); glPushMatrix(); + + // save opengl state + GLboolean isDepthMaskEnabled; + glGetBooleanv(GL_DEPTH_WRITEMASK, &isDepthMaskEnabled); + GLboolean isLightingEnabled = glIsEnabled(GL_LIGHTING); + glDepthMask(false); glDisable(GL_LIGHTING); - - // Set the correct modelview matrix: set the identity matrix in the rotation part - // [R|t1] = current modelview matrix (the camera rotation and translation) - // [I|t2] = the translation for the text - // We want this final model view matrix: [I | t1 + R*t2] + glm::dmat4 modelViewMatrix2; glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&modelViewMatrix2); glTranslatef(textPosition.x, textPosition.y, textPosition.z); - // Extract rotation matrix from the modelview matrix - glm::dmat4 modelViewMatrix; - glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&modelViewMatrix); - - // Delete rotation info - modelViewMatrix[0][0] = modelViewMatrix[1][1] = modelViewMatrix[2][2] = 1.0; - modelViewMatrix[0][1] = modelViewMatrix[0][2] = 0.0; - modelViewMatrix[1][0] = modelViewMatrix[1][2] = 0.0; - modelViewMatrix[2][0] = modelViewMatrix[2][1] = 0.0; - glLoadMatrixd((GLdouble*)&modelViewMatrix); // Override current matrix with our own - + // we need "always facing camera": we must remove the camera rotation from the stack + glm::quat rotation = Application::getInstance()->getCamera()->getRotation(); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z); // We need to compute the scale factor such as the text remains with fixed size respect to window coordinates // We project y = 0 and y = 1 and check the difference in projection coordinates @@ -328,8 +329,8 @@ void Avatar::renderDisplayName() { float scaleFactor = (textWindowHeight > EPSILON) ? 1.0f / textWindowHeight : 1.0f; glScalef(scaleFactor, scaleFactor, 1.0); - // draw a gray background so that we can actually see what we're typing - QFontMetrics metrics = displayNameTextRenderer()->metrics(); + // draw a gray background + QFontMetrics metrics = textRenderer(DISPLAYNAME)->metrics(); int bottom = -metrics.descent(), top = bottom + metrics.height(); int left = -_displayNameWidth/2, right = _displayNameWidth/2; int border = 5; @@ -338,7 +339,7 @@ void Avatar::renderDisplayName() { top += border; right += border; - glColor3f(0.2f, 0.2f, 0.2f); + glColor4f(0.2f, 0.2f, 0.2f, 0.95f); glBegin(GL_QUADS); glVertex2f(left, bottom); glVertex2f(right, bottom); @@ -346,16 +347,21 @@ void Avatar::renderDisplayName() { glVertex2f(left, top); glEnd(); - glScalef(1.0f, -1.0f, 1.0f); // TextRenderer::draw paints the text upside down in y axis - glColor3f(0.93f, 0.93f, 0.93f); + glColor4f(0.93f, 0.93f, 0.93f, 0.95f); QByteArray ba = displayName.toLocal8Bit(); const char *text = ba.data(); - displayNameTextRenderer()->draw(-_displayNameWidth/2.0, 0, text); + textRenderer(DISPLAYNAME)->draw(-_displayNameWidth/2.0, 0, text); + } + + // restore state + if (isLightingEnabled) { + glEnable(GL_LIGHTING); + } + if (isDepthMaskEnabled) { + glDepthMask(true); } - glEnable(GL_LIGHTING); - glDepthMask(true); glPopMatrix(); } @@ -466,7 +472,7 @@ void Avatar::setDisplayName(const QString& displayName) { AvatarData::setDisplayName(displayName); int width = 0; for (int i = 0; i < displayName.size(); i++) { - width += (displayNameTextRenderer()->computeWidth(displayName[i].toLatin1())); + width += (textRenderer(DISPLAYNAME)->computeWidth(displayName[i].toLatin1())); } _displayNameWidth = width; } @@ -556,11 +562,16 @@ void Avatar::setScale(float scale) { } } -float Avatar::getHeight() const { +float Avatar::getSkeletonHeight() const { Extents extents = _skeletonModel.getBindExtents(); return extents.maximum.y - extents.minimum.y; } +float Avatar::getHeadHeight() const { + Extents extents = _head.getFaceModel().getBindExtents(); + return extents.maximum.y - extents.minimum.y; +} + bool Avatar::collisionWouldMoveAvatar(ModelCollisionInfo& collision) const { // ATM only the Skeleton is pokeable // TODO: make poke affect head diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 19e720f771..5c19b8b60f 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -130,7 +130,9 @@ public: static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2); - float getHeight() const; + float getSkeletonHeight() const; + + float getHeadHeight() const; /// \return true if we expect the avatar would move as a result of the collision bool collisionWouldMoveAvatar(ModelCollisionInfo& collision) const; @@ -178,11 +180,6 @@ private: bool _initialized; - int _displayNameWidth; - bool _isShowDisplayName; - - - void renderBody(bool forceRenderHead); void renderDisplayName(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c97cc96ea8..72ab283da8 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -197,7 +197,7 @@ void MyAvatar::simulate(float deltaTime) { if (_collisionFlags != 0) { Camera* myCamera = Application::getInstance()->getCamera(); - float radius = getHeight() * COLLISION_RADIUS_SCALE; + float radius = getSkeletonHeight() * COLLISION_RADIUS_SCALE; if (myCamera->getMode() == CAMERA_MODE_FIRST_PERSON && !OculusManager::isConnected()) { radius = myCamera->getAspectRatio() * (myCamera->getNearClip() / cos(myCamera->getFieldOfView() / 2.f)); radius *= COLLISION_RADIUS_SCALAR; @@ -840,7 +840,7 @@ void MyAvatar::updateCollisionWithEnvironment(float deltaTime, float radius) { float pelvisFloatingHeight = getPelvisFloatingHeight(); if (Application::getInstance()->getEnvironment()->findCapsulePenetration( _position - up * (pelvisFloatingHeight - radius), - _position + up * (getHeight() - pelvisFloatingHeight + radius), radius, penetration)) { + _position + up * (getSkeletonHeight() - pelvisFloatingHeight + radius), radius, penetration)) { _lastCollisionPosition = _position; updateCollisionSound(penetration, deltaTime, ENVIRONMENT_COLLISION_FREQUENCY); applyHardCollision(penetration, ENVIRONMENT_SURFACE_ELASTICITY, ENVIRONMENT_SURFACE_DAMPING); @@ -855,7 +855,7 @@ void MyAvatar::updateCollisionWithVoxels(float deltaTime, float radius) { float pelvisFloatingHeight = getPelvisFloatingHeight(); if (Application::getInstance()->getVoxels()->findCapsulePenetration( _position - glm::vec3(0.0f, pelvisFloatingHeight - radius, 0.0f), - _position + glm::vec3(0.0f, getHeight() - pelvisFloatingHeight + radius, 0.0f), radius, penetration)) { + _position + glm::vec3(0.0f, getSkeletonHeight() - pelvisFloatingHeight + radius, 0.0f), radius, penetration)) { _lastCollisionPosition = _position; updateCollisionSound(penetration, deltaTime, VOXEL_COLLISION_FREQUENCY); applyHardCollision(penetration, VOXEL_ELASTICITY, VOXEL_DAMPING); @@ -962,7 +962,7 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) { // no need to compute a bunch of stuff if we have one or fewer avatars return; } - float myBoundingRadius = 0.5f * getHeight(); + float myBoundingRadius = 0.5f * getSkeletonHeight(); // HACK: body-body collision uses two coaxial capsules with axes parallel to y-axis // TODO: make the collision work without assuming avatar orientation @@ -982,7 +982,7 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) { if (_distanceToNearestAvatar > distance) { _distanceToNearestAvatar = distance; } - float theirBoundingRadius = 0.5f * avatar->getHeight(); + float theirBoundingRadius = 0.5f * avatar->getSkeletonHeight(); if (distance < myBoundingRadius + theirBoundingRadius) { Extents theirStaticExtents = _skeletonModel.getStaticExtents(); glm::vec3 staticScale = theirStaticExtents.maximum - theirStaticExtents.minimum; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 548129b871..5a71f7c3d2 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -35,7 +35,9 @@ AvatarData::AvatarData() : _keyState(NO_KEY_DOWN), _isChatCirclingEnabled(false), _headData(NULL), - _handData(NULL) + _handData(NULL), + _displayNameWidth(0), + _isShowDisplayName(false) { } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index f5d9da2447..6b3de797bb 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -182,6 +182,10 @@ protected: QUrl _faceModelURL; QUrl _skeletonModelURL; QString _displayName; + + int _displayNameWidth; + bool _isShowDisplayName; + private: // privatize the copy constructor and assignment operator so they cannot be called AvatarData(const AvatarData&); From a8f1f9a00ae1342e81e1d0a3d2f47484fb8818b1 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Sun, 16 Feb 2014 14:25:41 +0100 Subject: [PATCH 17/83] Added animation for fade out --- interface/src/avatar/Avatar.cpp | 79 ++++++++++++++++------------ interface/src/avatar/MyAvatar.cpp | 1 - libraries/avatars/src/AvatarData.cpp | 3 +- libraries/avatars/src/AvatarData.h | 1 + 4 files changed, 49 insertions(+), 35 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 21aee11936..681876550b 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -56,6 +56,8 @@ const float HEAD_RATE_MAX = 50.f; const int NUM_BODY_CONE_SIDES = 9; const float CHAT_MESSAGE_SCALE = 0.0015f; const float CHAT_MESSAGE_HEIGHT = 0.1f; +const float DISPLAYNAME_FADEOUT_TIME = 0.5f; +const float DISPLAYNAME_ALPHA = 0.95f; Avatar::Avatar() : AvatarData(), @@ -111,7 +113,7 @@ void Avatar::simulate(float deltaTime) { if (_scale != _targetScale) { setScale(_targetScale); } - + // copy velocity so we can use it later for acceleration glm::vec3 oldVelocity = getVelocity(); @@ -138,7 +140,15 @@ void Avatar::simulate(float deltaTime) { // Zero thrust out now that we've added it to velocity in this frame _thrust = glm::vec3(0, 0, 0); - + + // update animation for display name fadeout + if (!_isShowDisplayName && _displayNameAlpha > 0.0) { + // the alpha function is alpha = coef ^ time(zero based) + // We can make this function recursive: alpha(t) = alpha(t-dt) * coef^(dt) + float coef = pow(0.01f, 1.0f / DISPLAYNAME_FADEOUT_TIME); + _displayNameAlpha *= pow(coef, deltaTime); + _displayNameAlpha = _displayNameAlpha > 0.01? _displayNameAlpha : 0.0f; // The function is asymptotic to zero. 0.01 is 0 to us + } } void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction) { @@ -199,9 +209,8 @@ void Avatar::render(bool forceRenderHead) { } // render display name - if (_isShowDisplayName) { - renderDisplayName(); - } + renderDisplayName(); + if (!_chatMessage.empty()) { int width = 0; @@ -274,16 +283,11 @@ void Avatar::renderBody(bool forceRenderHead) { } void Avatar::renderDisplayName() { - QString displayName; - if (_displayName.isEmpty()) { - displayName = "test string"; // just for debugging - } else { - displayName = _displayName; - } - - glm::vec3 textPosition = getPosition() + getBodyUpDirection() * (getSkeletonHeight() + getHeadHeight()); - glPushMatrix(); + if (_displayName.isEmpty() || _displayNameAlpha == 0.0f) { + return; + } + // save opengl state GLboolean isDepthMaskEnabled; glGetBooleanv(GL_DEPTH_WRITEMASK, &isDepthMaskEnabled); @@ -291,9 +295,17 @@ void Avatar::renderDisplayName() { glDepthMask(false); glDisable(GL_LIGHTING); - - glm::dmat4 modelViewMatrix2; - glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&modelViewMatrix2); + + // save the matrices for later scale correction factor + glm::dmat4 modelViewMatrix; + GLdouble projectionMatrix[16]; + GLint viewportMatrix[4]; + glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&modelViewMatrix); + glGetDoublev(GL_PROJECTION_MATRIX, (GLdouble*)&projectionMatrix); + glGetIntegerv(GL_VIEWPORT, viewportMatrix); + + glPushMatrix(); + glm::vec3 textPosition = getPosition() + getBodyUpDirection() * (getSkeletonHeight() + getHeadHeight()); glTranslatef(textPosition.x, textPosition.y, textPosition.z); // we need "always facing camera": we must remove the camera rotation from the stack @@ -302,26 +314,22 @@ void Avatar::renderDisplayName() { glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z); // We need to compute the scale factor such as the text remains with fixed size respect to window coordinates - // We project y = 0 and y = 1 and check the difference in projection coordinates - GLdouble projectionMatrix[16]; - GLint viewportMatrix[4]; - GLdouble result0[3]; - GLdouble result1[3]; - - glm::dvec3 upVector(modelViewMatrix2[1]); - glGetDoublev(GL_PROJECTION_MATRIX, (GLdouble*)&projectionMatrix); - glGetIntegerv(GL_VIEWPORT, viewportMatrix); + // We project a unit vector and check the difference in screen coordinates, to check which is the + // correction scale needed + GLdouble result0[3], result1[3]; + glm::dvec3 upVector(modelViewMatrix[1]); + glm::dvec3 testPoint0 = glm::dvec3(textPosition); glm::dvec3 testPoint1 = glm::dvec3(textPosition) + upVector; bool success; success = gluProject(testPoint0.x, testPoint0.y, testPoint0.z, - (GLdouble*)&modelViewMatrix2, projectionMatrix, viewportMatrix, + (GLdouble*)&modelViewMatrix, projectionMatrix, viewportMatrix, &result0[0], &result0[1], &result0[2]); success = success && gluProject(testPoint1.x, testPoint1.y, testPoint1.z, - (GLdouble*)&modelViewMatrix2, projectionMatrix, viewportMatrix, + (GLdouble*)&modelViewMatrix, projectionMatrix, viewportMatrix, &result1[0], &result1[1], &result1[2]); if (success) { @@ -339,7 +347,7 @@ void Avatar::renderDisplayName() { top += border; right += border; - glColor4f(0.2f, 0.2f, 0.2f, 0.95f); + glColor4f(0.2f, 0.2f, 0.2f, _displayNameAlpha); glBegin(GL_QUADS); glVertex2f(left, bottom); glVertex2f(right, bottom); @@ -348,21 +356,23 @@ void Avatar::renderDisplayName() { glEnd(); glScalef(1.0f, -1.0f, 1.0f); // TextRenderer::draw paints the text upside down in y axis - glColor4f(0.93f, 0.93f, 0.93f, 0.95f); + glColor4f(0.93f, 0.93f, 0.93f, _displayNameAlpha); - QByteArray ba = displayName.toLocal8Bit(); + QByteArray ba = _displayName.toLocal8Bit(); const char *text = ba.data(); textRenderer(DISPLAYNAME)->draw(-_displayNameWidth/2.0, 0, text); } - // restore state + glPopMatrix(); + + // restore opengl state if (isLightingEnabled) { glEnable(GL_LIGHTING); } if (isDepthMaskEnabled) { glDepthMask(true); } - glPopMatrix(); + } bool Avatar::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { @@ -612,5 +622,8 @@ float Avatar::getPelvisToHeadLength() const { void Avatar::setShowDisplayName(bool showDisplayName) { _isShowDisplayName = showDisplayName; + if (showDisplayName) { + _displayNameAlpha = DISPLAYNAME_ALPHA; + } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 72ab283da8..266051e22d 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -63,7 +63,6 @@ MyAvatar::MyAvatar() : for (int i = 0; i < MAX_DRIVE_KEYS; i++) { _driveKeys[i] = 0.0f; } - setShowDisplayName(true); } MyAvatar::~MyAvatar() { diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 5a71f7c3d2..106ac38702 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -37,7 +37,8 @@ AvatarData::AvatarData() : _headData(NULL), _handData(NULL), _displayNameWidth(0), - _isShowDisplayName(false) + _isShowDisplayName(false), + _displayNameAlpha(0.0f) { } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 6b3de797bb..fe5a890614 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -185,6 +185,7 @@ protected: int _displayNameWidth; bool _isShowDisplayName; + float _displayNameAlpha; private: // privatize the copy constructor and assignment operator so they cannot be called From 73e0c0ccf52b44cdef39b38151c3fbd796884ab1 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Sun, 16 Feb 2014 21:33:46 +0100 Subject: [PATCH 18/83] Moving pow evaluation to const --- interface/src/avatar/Avatar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 681876550b..7028e30a7e 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -57,6 +57,7 @@ const int NUM_BODY_CONE_SIDES = 9; const float CHAT_MESSAGE_SCALE = 0.0015f; const float CHAT_MESSAGE_HEIGHT = 0.1f; const float DISPLAYNAME_FADEOUT_TIME = 0.5f; +const float DISPLAYNAME_FADEOUT_FACTOR = pow(0.01f, 1.0f / DISPLAYNAME_FADEOUT_TIME); const float DISPLAYNAME_ALPHA = 0.95f; Avatar::Avatar() : @@ -145,8 +146,7 @@ void Avatar::simulate(float deltaTime) { if (!_isShowDisplayName && _displayNameAlpha > 0.0) { // the alpha function is alpha = coef ^ time(zero based) // We can make this function recursive: alpha(t) = alpha(t-dt) * coef^(dt) - float coef = pow(0.01f, 1.0f / DISPLAYNAME_FADEOUT_TIME); - _displayNameAlpha *= pow(coef, deltaTime); + _displayNameAlpha *= pow(DISPLAYNAME_FADEOUT_FACTOR, deltaTime); _displayNameAlpha = _displayNameAlpha > 0.01? _displayNameAlpha : 0.0f; // The function is asymptotic to zero. 0.01 is 0 to us } } From 6ce028bbab4faa1193d2b774dac5dbf3279ae73e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 17 Feb 2014 10:27:33 -0800 Subject: [PATCH 19/83] Simplifiy API for camera mode transitions Specify the "period" for the transition rather than the "rate". --- interface/src/Application.cpp | 8 ++++---- interface/src/Camera.cpp | 30 +++++++++++++----------------- interface/src/Camera.h | 4 ++-- 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 160d6b7c2c..c922120e48 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1799,7 +1799,7 @@ void Application::init() { // TODO: move _myAvatar out of Application. Move relevant code to MyAvataar or AvatarManager _avatarManager.init(); _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); - _myCamera.setModeShiftRate(1.0f); + _myCamera.setModeShiftPeriod(1.0f); _mirrorCamera.setMode(CAMERA_MODE_MIRROR); _mirrorCamera.setAspectRatio((float)MIRROR_VIEW_WIDTH / (float)MIRROR_VIEW_HEIGHT); @@ -2168,17 +2168,17 @@ void Application::cameraMenuChanged() { if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { if (_myCamera.getMode() != CAMERA_MODE_MIRROR) { _myCamera.setMode(CAMERA_MODE_MIRROR); - _myCamera.setModeShiftRate(100.0f); + _myCamera.setModeShiftPeriod(0.00f); } } else if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) { if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON) { _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); - _myCamera.setModeShiftRate(1.0f); + _myCamera.setModeShiftPeriod(1.0f); } } else { if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) { _myCamera.setMode(CAMERA_MODE_THIRD_PERSON); - _myCamera.setModeShiftRate(1.0f); + _myCamera.setModeShiftPeriod(1.0f); } } } diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index 694fd30f50..8729ef58b6 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -15,8 +15,6 @@ #include "Menu.h" #include "Util.h" -const float CAMERA_MINIMUM_MODE_SHIFT_RATE = 0.5f; - const float CAMERA_FIRST_PERSON_MODE_UP_SHIFT = 0.0f; const float CAMERA_FIRST_PERSON_MODE_DISTANCE = 0.0f; const float CAMERA_FIRST_PERSON_MODE_TIGHTNESS = 100.0f; @@ -57,7 +55,7 @@ Camera::Camera() : _newTightness(0.0f), _modeShift(1.0f), _linearModeShift(0.0f), - _modeShiftRate(1.0f), + _modeShiftPeriod(1.0f), _scale(1.0f), _lookingAt(0.0f, 0.0f, 0.0f), _isKeepLookingAt(false) @@ -75,18 +73,18 @@ void Camera::update(float deltaTime) { // use iterative forces to keep the camera at the desired position and angle void Camera::updateFollowMode(float deltaTime) { if (_linearModeShift < 1.0f) { - _linearModeShift += _modeShiftRate * deltaTime; - _modeShift = ONE_HALF - ONE_HALF * cosf(_linearModeShift * PIE ); - _upShift = _previousUpShift * (1.0f - _modeShift) + _newUpShift * _modeShift; - _distance = _previousDistance * (1.0f - _modeShift) + _newDistance * _modeShift; - _tightness = _previousTightness * (1.0f - _modeShift) + _newTightness * _modeShift; - + _linearModeShift += deltaTime / _modeShiftPeriod; if (_needsToInitialize || _linearModeShift > 1.0f) { _linearModeShift = 1.0f; _modeShift = 1.0f; _upShift = _newUpShift; _distance = _newDistance; _tightness = _newTightness; + } else { + _modeShift = ONE_HALF - ONE_HALF * cosf(_linearModeShift * PIE ); + _upShift = _previousUpShift * (1.0f - _modeShift) + _newUpShift * _modeShift; + _distance = _previousDistance * (1.0f - _modeShift) + _newDistance * _modeShift; + _tightness = _previousTightness * (1.0f - _modeShift) + _newTightness * _modeShift; } } @@ -121,13 +119,10 @@ float Camera::getFarClip() const { : std::numeric_limits::max() - 1; } -void Camera::setModeShiftRate ( float rate ) { - - _modeShiftRate = rate; - - if (_modeShiftRate < CAMERA_MINIMUM_MODE_SHIFT_RATE ) { - _modeShiftRate = CAMERA_MINIMUM_MODE_SHIFT_RATE; - } +void Camera::setModeShiftPeriod (float period) { + const float MIN_PERIOD = 0.001f; + const float MAX_PERIOD = 3.0f; + _modeShiftPeriod = glm::clamp(period, MIN_PERIOD, MAX_PERIOD); } void Camera::setMode(CameraMode m) { @@ -307,7 +302,8 @@ void CameraScriptableObject::setMode(const QString& mode) { } if (currentMode != targetMode) { _camera->setMode(targetMode); - _camera->setModeShiftRate(10.0f); + const float DEFAULT_MODE_SHIFT_PERIOD = 0.5f; // half second + _camera->setModeShiftPeriod(DEFAULT_MODE_SHIFT_PERIOD); } } diff --git a/interface/src/Camera.h b/interface/src/Camera.h index b4ba3dbe05..7b95ce97f1 100644 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -43,7 +43,7 @@ public: void setTargetRotation(const glm::quat& rotation); void setMode(CameraMode m); - void setModeShiftRate(float r); + void setModeShiftPeriod(float r); void setFieldOfView(float f); void setAspectRatio(float a); void setNearClip(float n); @@ -109,7 +109,7 @@ private: float _newTightness; float _modeShift; float _linearModeShift; - float _modeShiftRate; + float _modeShiftPeriod; float _scale; glm::vec3 _lookingAt; From d635ffaaba3825376212a80f407718584ab5473d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 17 Feb 2014 10:40:32 -0800 Subject: [PATCH 20/83] Remove cruft: old avatar-avatar collision option --- interface/src/avatar/MyAvatar.cpp | 1 - interface/src/avatar/MyAvatar.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 5628740770..da5ad0b902 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -53,7 +53,6 @@ MyAvatar::MyAvatar() : _elapsedTimeSinceCollision(0.0f), _lastCollisionPosition(0, 0, 0), _speedBrakes(false), - _isCollisionsOn(true), _isThrustOn(false), _thrustMultiplier(1.0f), _moveTarget(0,0,0), diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index b912f6b0a7..36448a5529 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -90,7 +90,6 @@ public: public slots: void goHome(); - void setWantCollisionsOn(bool wantCollisionsOn) { _isCollisionsOn = wantCollisionsOn; } void increaseSize(); void decreaseSize(); void resetSize(); @@ -110,7 +109,6 @@ private: float _elapsedTimeSinceCollision; glm::vec3 _lastCollisionPosition; bool _speedBrakes; - bool _isCollisionsOn; bool _isThrustOn; float _thrustMultiplier; glm::vec3 _moveTarget; From bca50a5b70ecede42b55bdc7b0cbe431ab6fcc17 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 17 Feb 2014 11:23:01 -0800 Subject: [PATCH 21/83] Split render options for head/body collision proxy This makes the poor proxy shapes easier to see. --- interface/src/Menu.cpp | 3 ++- interface/src/Menu.h | 3 ++- interface/src/avatar/Avatar.cpp | 8 +++++--- interface/src/avatar/FaceModel.cpp | 3 --- interface/src/avatar/Hand.cpp | 3 ++- interface/src/avatar/MyAvatar.cpp | 5 ++++- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 7eb5807c6f..136f94166b 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -337,7 +337,8 @@ Menu::Menu() : QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options"); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Avatars, 0, true); - addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::CollisionProxies); + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderSkeletonCollisionProxies); + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderHeadCollisionProxies); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::LookAtVectors, 0, true); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 742b9fc66f..3df986d29a 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -165,7 +165,6 @@ namespace MenuOption { const QString Bandwidth = "Bandwidth Display"; const QString BandwidthDetails = "Bandwidth Details"; const QString ChatCircling = "Chat Circling"; - const QString CollisionProxies = "Collision Proxies"; const QString Collisions = "Collisions"; const QString CollideWithAvatars = "Collide With Avatars"; const QString CollideWithParticles = "Collide With Particles"; @@ -246,6 +245,8 @@ namespace MenuOption { const QString PipelineWarnings = "Show Render Pipeline Warnings"; const QString Preferences = "Preferences..."; const QString RandomizeVoxelColors = "Randomize Voxel TRUE Colors"; + const QString RenderSkeletonCollisionProxies = "Skeleton Collision Proxies"; + const QString RenderHeadCollisionProxies = "Head Collision Proxies"; const QString ResetAvatarSize = "Reset Avatar Size"; const QString ResetSwatchColors = "Reset Swatch Colors"; const QString RunTimingTests = "Run Timing Tests"; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 761ed59db9..bc7f56f534 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -160,10 +160,12 @@ void Avatar::render(bool forceRenderHead) { Glower glower(_moving && glm::length(toTarget) > GLOW_DISTANCE ? 1.0f : 0.0f); // render body - if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) { - _skeletonModel.renderCollisionProxies(1.f); + if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) { + _skeletonModel.renderCollisionProxies(0.7f); + } + if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionProxies)) { + _head.getFaceModel().renderCollisionProxies(0.7f); } - if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { renderBody(forceRenderHead); } diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index b9803c17cd..076ad074f2 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -47,9 +47,6 @@ bool FaceModel::render(float alpha) { if (!Model::render(alpha)) { return false; } - if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) { - renderCollisionProxies(alpha); - } return true; } diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index c2ea3f8f31..939ebaeae9 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -328,7 +328,8 @@ void Hand::render(bool isMine) { _buckyBalls.render(); } - if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) { + // draw a green sphere at hand joint location, which is actually near the wrist) for (size_t i = 0; i < getNumPalms(); i++) { PalmData& palm = getPalms()[i]; if (!palm.isActive()) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index da5ad0b902..3b1fa90959 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -480,7 +480,10 @@ void MyAvatar::renderDebugBodyPoints() { void MyAvatar::render(bool forceRenderHead) { // render body - if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) { + _skeletonModel.renderCollisionProxies(1.f); + } + if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionProxies)) { _skeletonModel.renderCollisionProxies(1.f); } if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { From ab3e1af64d82f708364f2620625482b55046bb6d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 17 Feb 2014 12:02:11 -0800 Subject: [PATCH 22/83] fix the sometime voxels don't show when you move bug --- interface/src/VoxelSystem.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index a3352f36e7..693a010182 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -2105,7 +2105,7 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) { bool VoxelSystem::hideAllSubTreeOperation(OctreeElement* element, void* extraData) { VoxelTreeElement* voxel = (VoxelTreeElement*)element; hideOutOfViewArgs* args = (hideOutOfViewArgs*)extraData; - + // If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not // consider that case. @@ -2141,7 +2141,7 @@ bool VoxelSystem::hideAllSubTreeOperation(OctreeElement* element, void* extraDat bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraData) { VoxelTreeElement* voxel = (VoxelTreeElement*)element; hideOutOfViewArgs* args = (hideOutOfViewArgs*)extraData; - + // If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not // consider that case. @@ -2184,7 +2184,7 @@ bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraDat bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData) { VoxelTreeElement* voxel = (VoxelTreeElement*)element; hideOutOfViewArgs* args = (hideOutOfViewArgs*)extraData; - + // If we're still recursing the tree using this operator, then we don't know if we're inside or outside... // so before we move forward we need to determine our frustum location ViewFrustum::location inFrustum = voxel->inFrustum(args->thisViewFrustum); @@ -2201,7 +2201,6 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData // ok, now do some processing for this node... switch (inFrustum) { case ViewFrustum::OUTSIDE: { - // If this node is outside the current view, then we might want to hide it... unless it was previously OUTSIDE, // if it was previously outside, then we can safely assume it's already hidden, and we can also safely assume // that all of it's children are outside both of our views, in which case we can just stop recursing... @@ -2215,12 +2214,10 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData // we need to hide it. Additionally we know that ALL of it's children are also fully OUTSIDE so we can recurse // the children and simply mark them as hidden args->tree->recurseNodeWithOperation(voxel, hideAllSubTreeOperation, args ); - return false; } break; case ViewFrustum::INSIDE: { - // If this node is INSIDE the current view, then we might want to show it... unless it was previously INSIDE, // if it was previously INSIDE, then we can safely assume it's already shown, and we can also safely assume // that all of it's children are INSIDE both of our views, in which case we can just stop recursing... @@ -2234,12 +2231,10 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData // we need to show it. Additionally we know that ALL of it's children are also fully INSIDE so we can recurse // the children and simply mark them as visible (as appropriate based on LOD) args->tree->recurseNodeWithOperation(voxel, showAllSubTreeOperation, args); - return false; } break; case ViewFrustum::INTERSECT: { args->nodesScanned++; - // If this node INTERSECTS the current view, then we might want to show it... unless it was previously INSIDE // the last known view, in which case it will already be visible, and we know that all it's children are also // previously INSIDE and visible. So in this case stop recursing @@ -2253,8 +2248,15 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData // if the child node INTERSECTs the view, then we want to check to see if it thinks it should render // if it should render but is missing it's VBO index, then we want to flip it on, and we can stop recursing from // here because we know will block any children anyway + + float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale(); + int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust(); + bool shouldRender = voxel->calculateShouldRender(&args->thisViewFrustum, voxelSizeScale, boundaryLevelAdjust); + voxel->setShouldRender(shouldRender); + if (voxel->getShouldRender() && !voxel->isKnownBufferIndex()) { voxel->setDirtyBit(); // will this make it draw? + voxel->markWithChangedTime(); // both are needed to force redraw args->nodesShown++; return false; } @@ -2267,7 +2269,6 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData } break; } // switch - return true; // keep going! } From 96a160bade8b46a99f9dbd5deb8d90f6b26ea10b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 17 Feb 2014 12:35:42 -0800 Subject: [PATCH 23/83] Moved some code in ImportDialog.cpp for consistency --- interface/src/ImportDialog.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/interface/src/ImportDialog.cpp b/interface/src/ImportDialog.cpp index ac7853629c..c276a4da6b 100644 --- a/interface/src/ImportDialog.cpp +++ b/interface/src/ImportDialog.cpp @@ -104,19 +104,6 @@ ImportDialog::ImportDialog(QWidget* parent) : setFileMode(QFileDialog::ExistingFile); setViewMode(QFileDialog::Detail); -#ifdef Q_OS_MAC - QString cmdString = ("Command"); -#else - QString cmdString = ("Control"); -#endif - QLabel* infoLabel = new QLabel(QString(INFO_LABEL_TEXT).arg(cmdString)); - infoLabel->setObjectName("infoLabel"); - - QGridLayout* gridLayout = (QGridLayout*) layout(); - gridLayout->addWidget(infoLabel, 2, 0, 2, 1); - gridLayout->addWidget(&_cancelButton, 2, 1, 2, 1); - gridLayout->addWidget(&_importButton, 2, 2, 2, 1); - setImportTypes(); setLayout(); @@ -175,6 +162,19 @@ void ImportDialog::saveCurrentFile(QString filename) { } void ImportDialog::setLayout() { + +#ifdef Q_OS_MAC + QString cmdString = ("Command"); +#else + QString cmdString = ("Control"); +#endif + QLabel* infoLabel = new QLabel(QString(INFO_LABEL_TEXT).arg(cmdString)); + infoLabel->setObjectName("infoLabel"); + + QGridLayout* gridLayout = (QGridLayout*) layout(); + gridLayout->addWidget(infoLabel, 2, 0, 2, 1); + gridLayout->addWidget(&_cancelButton, 2, 1, 2, 1); + gridLayout->addWidget(&_importButton, 2, 2, 2, 1); // set ObjectName used in qss for styling _importButton.setObjectName("importButton"); From 0ec554ec82ae1804fcbbd5a6124a5341b4bd5ff5 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Tue, 18 Feb 2014 00:49:26 +0100 Subject: [PATCH 24/83] Added fadein and fadeout animations for display name --- interface/src/avatar/Avatar.cpp | 30 ++++++++++++++++++---------- interface/src/avatar/Avatar.h | 2 +- libraries/avatars/src/AvatarData.cpp | 2 +- libraries/avatars/src/AvatarData.h | 2 +- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 86ffb2e5d4..55afe1905c 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -56,8 +56,8 @@ const float HEAD_RATE_MAX = 50.f; const int NUM_BODY_CONE_SIDES = 9; const float CHAT_MESSAGE_SCALE = 0.0015f; const float CHAT_MESSAGE_HEIGHT = 0.1f; -const float DISPLAYNAME_FADEOUT_TIME = 0.5f; -const float DISPLAYNAME_FADEOUT_FACTOR = pow(0.01f, 1.0f / DISPLAYNAME_FADEOUT_TIME); +const float DISPLAYNAME_FADE_TIME = 0.5f; +const float DISPLAYNAME_FADE_FACTOR = pow(0.01f, 1.0f / DISPLAYNAME_FADE_TIME); const float DISPLAYNAME_ALPHA = 0.95f; Avatar::Avatar() : @@ -142,12 +142,21 @@ void Avatar::simulate(float deltaTime) { // Zero thrust out now that we've added it to velocity in this frame _thrust = glm::vec3(0, 0, 0); - // update animation for display name fadeout - if (!_isShowDisplayName && _displayNameAlpha > 0.0) { - // the alpha function is alpha = coef ^ time(zero based) - // We can make this function recursive: alpha(t) = alpha(t-dt) * coef^(dt) - _displayNameAlpha *= pow(DISPLAYNAME_FADEOUT_FACTOR, deltaTime); - _displayNameAlpha = _displayNameAlpha > 0.01? _displayNameAlpha : 0.0f; // The function is asymptotic to zero. 0.01 is 0 to us + // update animation for display name fade in/out + if ( _displayNameTargetAlpha != _displayNameAlpha) { + // the alpha function is + // Fade out => alpha(t) = factor ^ t => alpha(t+dt) = alpha(t) * factor^(dt) + // Fade in => alpha(t) = 1 - factor^t => alpha(t+dt) = 1-(1-alpha(t))*coef^(dt) + // factor^(dt) = coef + float coef = pow(DISPLAYNAME_FADE_FACTOR, deltaTime); + if (_displayNameTargetAlpha < _displayNameAlpha) { + // Fading out + _displayNameAlpha *= coef; + } else { + // Fading in + _displayNameAlpha = 1 - (1 - _displayNameAlpha) * coef; + } + _displayNameAlpha = abs(_displayNameAlpha - _displayNameTargetAlpha) < 0.01? _displayNameTargetAlpha : _displayNameAlpha; } } @@ -628,9 +637,10 @@ float Avatar::getPelvisToHeadLength() const { } void Avatar::setShowDisplayName(bool showDisplayName) { - _isShowDisplayName = showDisplayName; if (showDisplayName) { - _displayNameAlpha = DISPLAYNAME_ALPHA; + _displayNameTargetAlpha = DISPLAYNAME_ALPHA; + } else { + _displayNameTargetAlpha = 0.0f; } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 7a9df0cdbb..c7b52301e3 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -128,7 +128,7 @@ public: /// \param collision a data structure for storing info about collisions against Models void applyCollision(CollisionInfo& collision); - float getBoundingRadius() const { return 0.5f * getHeight(); } + float getBoundingRadius() const { return 0.5f * getSkeletonHeight(); } public slots: void updateCollisionFlags(); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 106ac38702..a49bd83df6 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -37,7 +37,7 @@ AvatarData::AvatarData() : _headData(NULL), _handData(NULL), _displayNameWidth(0), - _isShowDisplayName(false), + _displayNameTargetAlpha(0.0f), _displayNameAlpha(0.0f) { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 48892647f5..6850af80a2 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -182,7 +182,7 @@ protected: QString _displayName; int _displayNameWidth; - bool _isShowDisplayName; + float _displayNameTargetAlpha; float _displayNameAlpha; private: From 8be17bf02aa3e76cc576baca011a2a160f240b07 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Feb 2014 14:27:06 -0800 Subject: [PATCH 25/83] Attempting to get Visage building in on OS X. --- interface/CMakeLists.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index c3f7ebc286..13238d5c56 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -156,10 +156,13 @@ endif (SIXENSE_FOUND AND NOT DISABLE_SIXENSE) if (VISAGE_FOUND AND NOT DISABLE_VISAGE) add_definitions(-DHAVE_VISAGE -DVISAGE_STATIC) include_directories(SYSTEM ${VISAGE_INCLUDE_DIRS}) - if (APPLE OR UNIX) + if (APPLE) add_definitions(-DMAC_OS_X) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment -isystem ${VISAGE_INCLUDE_DIRS}") - endif (APPLE OR UNIX) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment -isystem -std=c++0x ${VISAGE_INCLUDE_DIRS}") + find_library(AVFoundation AVFoundation) + find_library(CoreMedia CoreMedia) + target_link_libraries(${TARGET_NAME} ${AVFoundation} ${CoreMedia}) + endif (APPLE) target_link_libraries(${TARGET_NAME} ${VISAGE_LIBRARIES}) endif (VISAGE_FOUND AND NOT DISABLE_VISAGE) From 46ed5061961470deaad523fa000306343871709a Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Wed, 19 Feb 2014 00:04:00 +0100 Subject: [PATCH 26/83] Display names are shown when distance is below a threshold Used polygon offset to render display names Saved model view and projection matrices in order to save glGetDoublev calls --- interface/src/Application.cpp | 12 +++++++ interface/src/Application.h | 4 +++ interface/src/avatar/Avatar.cpp | 55 ++++++++++++++----------------- interface/src/avatar/MyAvatar.cpp | 2 -- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 36fd8f9635..8f591d47ed 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -647,6 +647,9 @@ void Application::updateProjectionMatrix(Camera& camera, bool updateViewFrustum) } glFrustum(left, right, bottom, top, nearVal, farVal); + // save matrix + glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat*)&_projectionMatrix); + glMatrixMode(GL_MODELVIEW); } @@ -2894,6 +2897,15 @@ void Application::loadTranslatedViewMatrix(const glm::vec3& translation) { translation.z + _viewMatrixTranslation.z); } +void Application::getModelViewMatrix(glm::dmat4* modelViewMatrix) { + (*modelViewMatrix) =_untranslatedViewMatrix; + (*modelViewMatrix)[3] = _untranslatedViewMatrix * glm::vec4(_viewMatrixTranslation, 1); +} + +void Application::getProjectionMatrix(glm::dmat4* projectionMatrix) { + *projectionMatrix = _projectionMatrix; +} + void Application::computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { diff --git a/interface/src/Application.h b/interface/src/Application.h index a9c20ac00d..016fe0cbe8 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -188,6 +188,9 @@ public: const glm::mat4& getShadowMatrix() const { return _shadowMatrix; } + void getModelViewMatrix(glm::dmat4* modelViewMatrix); + void getProjectionMatrix(glm::dmat4* projectionMatrix); + /// Computes the off-axis frustum parameters for the view frustum, taking mirroring into account. void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; @@ -391,6 +394,7 @@ private: glm::mat4 _untranslatedViewMatrix; glm::vec3 _viewMatrixTranslation; + glm::mat4 _projectionMatrix; glm::mat4 _shadowMatrix; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 55afe1905c..2b7cc94c86 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -185,12 +185,14 @@ static TextRenderer* textRenderer(TextRendererType type) { } void Avatar::render(bool forceRenderHead) { - + glm::vec3 toTarget = _position - Application::getInstance()->getAvatar()->getPosition(); + float lengthToTarget = glm::length(toTarget); + { // glow when moving in the distance - glm::vec3 toTarget = _position - Application::getInstance()->getAvatar()->getPosition(); + const float GLOW_DISTANCE = 5.0f; - Glower glower(_moving && glm::length(toTarget) > GLOW_DISTANCE ? 1.0f : 0.0f); + Glower glower(_moving && lengthToTarget > GLOW_DISTANCE ? 1.0f : 0.0f); // render body if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) { @@ -217,11 +219,10 @@ void Avatar::render(bool forceRenderHead) { glPopMatrix(); } } - - // render display name + const float DISPLAYNAME_DISTANCE = 4.0f; + setShowDisplayName(lengthToTarget < DISPLAYNAME_DISTANCE); renderDisplayName(); - if (!_chatMessage.empty()) { int width = 0; int lastWidth = 0; @@ -298,22 +299,8 @@ void Avatar::renderDisplayName() { return; } - // save opengl state - GLboolean isDepthMaskEnabled; - glGetBooleanv(GL_DEPTH_WRITEMASK, &isDepthMaskEnabled); - GLboolean isLightingEnabled = glIsEnabled(GL_LIGHTING); - - glDepthMask(false); glDisable(GL_LIGHTING); - // save the matrices for later scale correction factor - glm::dmat4 modelViewMatrix; - GLdouble projectionMatrix[16]; - GLint viewportMatrix[4]; - glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&modelViewMatrix); - glGetDoublev(GL_PROJECTION_MATRIX, (GLdouble*)&projectionMatrix); - glGetIntegerv(GL_VIEWPORT, viewportMatrix); - glPushMatrix(); glm::vec3 textPosition = getPosition() + getBodyUpDirection() * (getSkeletonHeight() + getHeadHeight()); glTranslatef(textPosition.x, textPosition.y, textPosition.z); @@ -326,6 +313,13 @@ void Avatar::renderDisplayName() { // We need to compute the scale factor such as the text remains with fixed size respect to window coordinates // We project a unit vector and check the difference in screen coordinates, to check which is the // correction scale needed + // save the matrices for later scale correction factor + glm::dmat4 modelViewMatrix; + glm::dmat4 projectionMatrix; + GLint viewportMatrix[4]; + Application::getInstance()->getModelViewMatrix(&modelViewMatrix); + Application::getInstance()->getProjectionMatrix(&projectionMatrix); + glGetIntegerv(GL_VIEWPORT, viewportMatrix); GLdouble result0[3], result1[3]; glm::dvec3 upVector(modelViewMatrix[1]); @@ -335,11 +329,11 @@ void Avatar::renderDisplayName() { bool success; success = gluProject(testPoint0.x, testPoint0.y, testPoint0.z, - (GLdouble*)&modelViewMatrix, projectionMatrix, viewportMatrix, + (GLdouble*)&modelViewMatrix, (GLdouble*)&projectionMatrix, viewportMatrix, &result0[0], &result0[1], &result0[2]); success = success && gluProject(testPoint1.x, testPoint1.y, testPoint1.z, - (GLdouble*)&modelViewMatrix, projectionMatrix, viewportMatrix, + (GLdouble*)&modelViewMatrix, (GLdouble*)&projectionMatrix, viewportMatrix, &result1[0], &result1[1], &result1[2]); if (success) { @@ -357,6 +351,10 @@ void Avatar::renderDisplayName() { top += border; right += border; + // We are drawing coplanar textures with depth: need the polygon offset + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0f, 1.0f); + glColor4f(0.2f, 0.2f, 0.2f, _displayNameAlpha); glBegin(GL_QUADS); glVertex2f(left, bottom); @@ -370,19 +368,16 @@ void Avatar::renderDisplayName() { QByteArray ba = _displayName.toLocal8Bit(); const char *text = ba.data(); + + glDisable(GL_POLYGON_OFFSET_FILL); textRenderer(DISPLAYNAME)->draw(-_displayNameWidth/2.0, 0, text); + + } glPopMatrix(); - // restore opengl state - if (isLightingEnabled) { - glEnable(GL_LIGHTING); - } - if (isDepthMaskEnabled) { - glDepthMask(true); - } - + glEnable(GL_LIGHTING); } bool Avatar::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index cef6f20b1e..f86afaa090 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -670,10 +670,8 @@ void MyAvatar::updateLookAtTargetAvatar(glm::vec3 &eyePosition) { eyePosition = (avatar->getHead().calculateAverageEyePosition() - avatar->getHead().getScalePivot()) * (avatar->getScale() / avatar->getHead().getScale()) + avatar->getHead().getScalePivot(); _lookAtTargetAvatar = avatarPointer; - avatar->setShowDisplayName(true); return; } else { - avatar->setShowDisplayName(false); } } From a89959cd4768799c423e9a1b714d6d9884743c1f Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Feb 2014 15:09:34 -0800 Subject: [PATCH 27/83] Get rid of this line. --- interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 13238d5c56..0c94be59f3 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -158,7 +158,7 @@ if (VISAGE_FOUND AND NOT DISABLE_VISAGE) include_directories(SYSTEM ${VISAGE_INCLUDE_DIRS}) if (APPLE) add_definitions(-DMAC_OS_X) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment -isystem -std=c++0x ${VISAGE_INCLUDE_DIRS}") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment -isystem ${VISAGE_INCLUDE_DIRS}") find_library(AVFoundation AVFoundation) find_library(CoreMedia CoreMedia) target_link_libraries(${TARGET_NAME} ${AVFoundation} ${CoreMedia}) From 0547fa61b4b18218400e222b5c491c893ed7d7db Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Feb 2014 15:17:16 -0800 Subject: [PATCH 28/83] Link in the new standard library, which Visage uses. --- interface/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 0c94be59f3..a0a9033187 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -161,7 +161,8 @@ if (VISAGE_FOUND AND NOT DISABLE_VISAGE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment -isystem ${VISAGE_INCLUDE_DIRS}") find_library(AVFoundation AVFoundation) find_library(CoreMedia CoreMedia) - target_link_libraries(${TARGET_NAME} ${AVFoundation} ${CoreMedia}) + find_library(NEW_STD_LIBRARY libc++.dylib /usr/lib/) + target_link_libraries(${TARGET_NAME} ${AVFoundation} ${CoreMedia} ${NEW_STD_LIBRARY}) endif (APPLE) target_link_libraries(${TARGET_NAME} ${VISAGE_LIBRARIES}) endif (VISAGE_FOUND AND NOT DISABLE_VISAGE) From 490b9149fad8bcf94fecf005dda18a728b73241c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 18 Feb 2014 15:18:27 -0800 Subject: [PATCH 29/83] Moving "play slaps" code into its own method. Cleaning up hand collision code in prep for more correct collisions. --- interface/src/avatar/Hand.cpp | 74 +++++++++++++++++++---------------- interface/src/avatar/Hand.h | 3 ++ 2 files changed, 43 insertions(+), 34 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index eb9a8d2cb0..999551eb48 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -125,6 +125,41 @@ void Hand::simulate(float deltaTime, bool isMine) { } } +void Hand::playSlaps(PalmData& palm, Avatar* avatar) +{ + // Check for palm collisions + glm::vec3 myPalmPosition = palm.getPosition(); + float palmCollisionDistance = 0.1f; + bool wasColliding = palm.getIsCollidingWithPalm(); + palm.setIsCollidingWithPalm(false); + // If 'Play Slaps' is enabled, look for palm-to-palm collisions and make sound + for (size_t j = 0; j < avatar->getHand().getNumPalms(); j++) { + PalmData& otherPalm = avatar->getHand().getPalms()[j]; + if (!otherPalm.isActive()) { + continue; + } + glm::vec3 otherPalmPosition = otherPalm.getPosition(); + if (glm::length(otherPalmPosition - myPalmPosition) < palmCollisionDistance) { + palm.setIsCollidingWithPalm(true); + if (!wasColliding) { + const float PALM_COLLIDE_VOLUME = 1.f; + const float PALM_COLLIDE_FREQUENCY = 1000.f; + const float PALM_COLLIDE_DURATION_MAX = 0.75f; + const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.01f; + Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME, + PALM_COLLIDE_FREQUENCY, + PALM_COLLIDE_DURATION_MAX, + PALM_COLLIDE_DECAY_PER_SAMPLE); + // If the other person's palm is in motion, move mine downward to show I was hit + const float MIN_VELOCITY_FOR_SLAP = 0.05f; + if (glm::length(otherPalm.getVelocity()) > MIN_VELOCITY_FOR_SLAP) { + // add slapback here + } + } + } + } +} + // We create a static CollisionList that is recycled for each collision test. const float MAX_COLLISIONS_PER_AVATAR = 32; static CollisionList handCollisions(MAX_COLLISIONS_PER_AVATAR); @@ -139,41 +174,12 @@ void Hand::collideAgainstAvatar(Avatar* avatar, bool isMyHand) { PalmData& palm = getPalms()[i]; if (!palm.isActive()) { continue; - } - glm::vec3 totalPenetration; - if (isMyHand && Menu::getInstance()->isOptionChecked(MenuOption::PlaySlaps)) { - // Check for palm collisions - glm::vec3 myPalmPosition = palm.getPosition(); - float palmCollisionDistance = 0.1f; - bool wasColliding = palm.getIsCollidingWithPalm(); - palm.setIsCollidingWithPalm(false); - // If 'Play Slaps' is enabled, look for palm-to-palm collisions and make sound - for (size_t j = 0; j < avatar->getHand().getNumPalms(); j++) { - PalmData& otherPalm = avatar->getHand().getPalms()[j]; - if (!otherPalm.isActive()) { - continue; - } - glm::vec3 otherPalmPosition = otherPalm.getPosition(); - if (glm::length(otherPalmPosition - myPalmPosition) < palmCollisionDistance) { - palm.setIsCollidingWithPalm(true); - if (!wasColliding) { - const float PALM_COLLIDE_VOLUME = 1.f; - const float PALM_COLLIDE_FREQUENCY = 1000.f; - const float PALM_COLLIDE_DURATION_MAX = 0.75f; - const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.01f; - Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME, - PALM_COLLIDE_FREQUENCY, - PALM_COLLIDE_DURATION_MAX, - PALM_COLLIDE_DECAY_PER_SAMPLE); - // If the other person's palm is in motion, move mine downward to show I was hit - const float MIN_VELOCITY_FOR_SLAP = 0.05f; - if (glm::length(otherPalm.getVelocity()) > MIN_VELOCITY_FOR_SLAP) { - // add slapback here - } - } - } - } } + if (isMyHand && Menu::getInstance()->isOptionChecked(MenuOption::PlaySlaps)) { + playSlaps(palm, avatar); + } + + glm::vec3 totalPenetration; handCollisions.clear(); if (avatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, handCollisions)) { for (int j = 0; j < handCollisions.size(); ++j) { diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 5a423630b4..0ce1e836a2 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -61,6 +61,9 @@ public: void collideAgainstAvatar(Avatar* avatar, bool isMyHand); void collideAgainstOurself(); +private: + void playSlaps(PalmData& palm, Avatar* avatar); + private: // disallow copies of the Hand, copy of owning Avatar is disallowed too Hand(const Hand&); From cc6b663ea6619f98e228272be573583f0348e12c Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Feb 2014 15:37:40 -0800 Subject: [PATCH 30/83] Use the ABI-compatible library (hopefully). --- interface/CMakeLists.txt | 2 +- interface/src/devices/Visage.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index a0a9033187..32e75c9f34 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -161,7 +161,7 @@ if (VISAGE_FOUND AND NOT DISABLE_VISAGE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment -isystem ${VISAGE_INCLUDE_DIRS}") find_library(AVFoundation AVFoundation) find_library(CoreMedia CoreMedia) - find_library(NEW_STD_LIBRARY libc++.dylib /usr/lib/) + find_library(NEW_STD_LIBRARY libc++abi.dylib /usr/lib/) target_link_libraries(${TARGET_NAME} ${AVFoundation} ${CoreMedia} ${NEW_STD_LIBRARY}) endif (APPLE) target_link_libraries(${TARGET_NAME} ${VISAGE_LIBRARIES}) diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index f69121bf7f..6a612eb59d 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -27,7 +27,7 @@ using namespace VisageSDK; Visage::Visage() { #ifdef HAVE_VISAGE switchToResourcesParentIfRequired(); - initializeLicenseManager("resources/visage"); + initializeLicenseManager("resources/visage/license.vlc"); _tracker = new VisageTracker2("resources/visage/Facial Features Tracker - Asymmetric.cfg"); _tracker->trackFromCam(); #endif @@ -35,6 +35,7 @@ Visage::Visage() { Visage::~Visage() { #ifdef HAVE_VISAGE + _tracker->stop(); delete _tracker; #endif } From 4565599fb35fe853c2be9627b0f900b63f58382a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 18 Feb 2014 15:40:38 -0800 Subject: [PATCH 31/83] Removing unused cruft: setHeadData() and friend --- libraries/avatars/src/AvatarData.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 079c14a513..7bd2bf57e7 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -139,9 +139,6 @@ public: const HeadData* getHeadData() const { return _headData; } const HandData* getHandData() const { return _handData; } - void setHeadData(HeadData* headData) { _headData = headData; } - void setHandData(HandData* handData) { _handData = handData; } - virtual const glm::vec3& getVelocity() const { return vec3Zero; } virtual bool findParticleCollisions(const glm::vec3& particleCenter, float particleRadius, CollisionList& collisions) { From f83254882aff25e823a1d19c64962616736c1492 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Feb 2014 16:07:08 -0800 Subject: [PATCH 32/83] Attempting to get the head rotation from Visage. --- interface/src/Application.cpp | 10 ++++++++++ interface/src/Application.h | 2 ++ interface/src/avatar/MyAvatar.cpp | 24 +++++++++++++++++------- interface/src/devices/Visage.cpp | 28 ++++++++++++++++++++++++---- interface/src/devices/Visage.h | 16 ++++++++++++++++ 5 files changed, 69 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b316548ad4..098b42dccf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2041,6 +2041,15 @@ void Application::updateFaceshift() { } } +void Application::updateVisage() { + + bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); + PerformanceWarning warn(showWarnings, "Application::updateVisage()"); + + // Update Visage + _visage.update(); +} + void Application::updateMyAvatarLookAtPosition(glm::vec3& lookAtSpot) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); @@ -2318,6 +2327,7 @@ void Application::update(float deltaTime) { glm::vec3 lookAtSpot; updateFaceshift(); + updateVisage(); _myAvatar->updateLookAtTargetAvatar(lookAtSpot); updateMyAvatarLookAtPosition(lookAtSpot); diff --git a/interface/src/Application.h b/interface/src/Application.h index f9c1005c13..06a19f13b1 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -161,6 +161,7 @@ public: const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } Faceshift* getFaceshift() { return &_faceshift; } + Visage* getVisage() { return &_visage; } SixenseManager* getSixenseManager() { return &_sixenseManager; } BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; } QSettings* getSettings() { return _settings; } @@ -284,6 +285,7 @@ private: // Various helper functions called during update() void updateMouseRay(); void updateFaceshift(); + void updateVisage(); void updateMyAvatarLookAtPosition(glm::vec3& lookAtSpot); void updateHoverVoxels(float deltaTime, float& distance, BoxFace& face); void updateMouseVoxels(float deltaTime, float& distance, BoxFace& face); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 17b80089a7..51de5a944c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -337,22 +337,32 @@ const float MAX_PITCH = 90.0f; // Update avatar head rotation with sensor data void MyAvatar::updateFromGyros(float deltaTime) { Faceshift* faceshift = Application::getInstance()->getFaceshift(); + Visage* visage = Application::getInstance()->getVisage(); glm::vec3 estimatedPosition, estimatedRotation; + bool trackerActive = false; if (faceshift->isActive()) { estimatedPosition = faceshift->getHeadTranslation(); estimatedRotation = safeEulerAngles(faceshift->getHeadRotation()); + trackerActive = true; + + } else if (visage->isActive()) { + estimatedPosition = visage->getHeadTranslation(); + estimatedRotation = safeEulerAngles(visage->getHeadRotation()); + trackerActive = true; + } + if (trackerActive) { // Rotate the body if the head is turned beyond the screen if (Menu::getInstance()->isOptionChecked(MenuOption::TurnWithHead)) { - const float FACESHIFT_YAW_TURN_SENSITIVITY = 0.5f; - const float FACESHIFT_MIN_YAW_TURN = 15.f; - const float FACESHIFT_MAX_YAW_TURN = 50.f; - if ( (fabs(estimatedRotation.y) > FACESHIFT_MIN_YAW_TURN) && - (fabs(estimatedRotation.y) < FACESHIFT_MAX_YAW_TURN) ) { + const float TRACKER_YAW_TURN_SENSITIVITY = 0.5f; + const float TRACKER_MIN_YAW_TURN = 15.f; + const float TRACKER_MAX_YAW_TURN = 50.f; + if ( (fabs(estimatedRotation.y) > TRACKER_MIN_YAW_TURN) && + (fabs(estimatedRotation.y) < TRACKER_MAX_YAW_TURN) ) { if (estimatedRotation.y > 0.f) { - _bodyYawDelta += (estimatedRotation.y - FACESHIFT_MIN_YAW_TURN) * FACESHIFT_YAW_TURN_SENSITIVITY; + _bodyYawDelta += (estimatedRotation.y - TRACKER_MIN_YAW_TURN) * TRACKER_YAW_TURN_SENSITIVITY; } else { - _bodyYawDelta += (estimatedRotation.y + FACESHIFT_MIN_YAW_TURN) * FACESHIFT_YAW_TURN_SENSITIVITY; + _bodyYawDelta += (estimatedRotation.y + TRACKER_MIN_YAW_TURN) * TRACKER_YAW_TURN_SENSITIVITY; } } } diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 6a612eb59d..59b3ac06f8 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -24,18 +24,38 @@ namespace VisageSDK { using namespace VisageSDK; -Visage::Visage() { +Visage::Visage() : + _active(false) { #ifdef HAVE_VISAGE switchToResourcesParentIfRequired(); initializeLicenseManager("resources/visage/license.vlc"); _tracker = new VisageTracker2("resources/visage/Facial Features Tracker - Asymmetric.cfg"); - _tracker->trackFromCam(); + if (_tracker->trackFromCam()) { + _data = new FaceData(); + + } else { + delete _tracker; + _tracker = NULL; + } #endif } Visage::~Visage() { #ifdef HAVE_VISAGE - _tracker->stop(); - delete _tracker; + if (_tracker) { + _tracker->stop(); + delete _tracker; + delete _data; + } +#endif +} + +void Visage::update() { +#ifdef HAVE_VISAGE + _active = (_tracker->getTrackingData(_data) == TRACK_STAT_OK); + if (!_active) { + return; + } + _headRotation = glm::quat(glm::vec3(_data->faceRotation[0], _data->faceRotation[1], _data->faceRotation[2])); #endif } diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 1b9d283bb3..f16119cdbd 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -9,7 +9,11 @@ #ifndef __interface__Visage__ #define __interface__Visage__ +#include +#include + namespace VisageSDK { + class FaceData; class VisageTracker2; } @@ -20,9 +24,21 @@ public: Visage(); ~Visage(); + bool isActive() const { return _active; } + + const glm::quat& getHeadRotation() const { return _headRotation; } + const glm::vec3& getHeadTranslation() const { return _headTranslation; } + + void update(); + private: VisageSDK::VisageTracker2* _tracker; + VisageSDK::FaceData* _data; + + bool _active; + glm::quat _headRotation; + glm::vec3 _headTranslation; }; #endif /* defined(__interface__Visage__) */ From baa1762056264b558c1c7aa3c8c43da751c8cd1b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 18 Feb 2014 16:23:34 -0800 Subject: [PATCH 33/83] added support for overlays to editVoxels.js --- examples/editVoxels.js | 319 +++++++++++++++--- .../src/ControllerScriptingInterface.cpp | 4 + interface/src/ControllerScriptingInterface.h | 2 + 3 files changed, 285 insertions(+), 40 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index c1f0c8dc49..c67ff0dcfa 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -16,14 +16,7 @@ // Click and drag to create more new voxels in the same direction // -function vLength(v) { - return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); -} - -function vMinus(a, b) { - var rval = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z }; - return rval; -} +var windowDimensions = Controller.getViewportDimensions(); var NEW_VOXEL_SIZE = 1.0; var NEW_VOXEL_DISTANCE_FROM_CAMERA = 3.0; @@ -76,6 +69,52 @@ var clickSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-publ var audioOptions = new AudioInjectionOptions();
 audioOptions.volume = 0.5; +var editToolsOn = false; // starts out off + + +var voxelPreview = Overlays.addOverlay("cube", { + position: { x: 0, y: 0, z: 0}, + size: 1, + color: { red: 255, green: 0, blue: 0}, + alpha: 1, + solid: false, + visible: false, + lineWidth: 4 + }); + + +// These will be our "overlay IDs" +var swatches = new Array(); +var swatchHeight = 54; +var swatchWidth = 31; +var swatchesWidth = swatchWidth * numColors; +var swatchesX = (windowDimensions.x - swatchesWidth) / 2; +var swatchesY = windowDimensions.y - swatchHeight; + +// create the overlays, position them in a row, set their colors, and for the selected one, use a different source image +// location so that it displays the "selected" marker +for (s = 0; s < numColors; s++) { + var imageFromX = 12 + (s * 27); + var imageFromY = 0; + if (s == whichColor) { + imageFromY = 55; + } + var swatchX = swatchesX + (30 * s); + + swatches[s] = Overlays.addOverlay("image", { + x: swatchX, + y: swatchesY, + width: swatchWidth, + height: swatchHeight, + subImage: { x: imageFromX, y: imageFromY, width: (swatchWidth - 1), height: swatchHeight }, + imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", + color: colors[s], + alpha: 1, + visible: editToolsOn + }); +} + + function setAudioPosition() { var camera = Camera.getPosition(); var forwardVector = Quat.getFront(MyAvatar.orientation); @@ -101,7 +140,141 @@ function fixEulerAngles(eulers) { return rVal; } +var trackLastMouseX = 0; +var trackLastMouseY = 0; +var trackAsDelete = false; +var trackAsRecolor = false; + +function showPreviewVoxel() { + if (editToolsOn) { + var voxelColor; + + var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); + var intersection = Voxels.findRayIntersection(pickRay); + + if (whichColor == -1) { + // Copy mode - use clicked voxel color + voxelColor = { red: intersection.voxel.red, + green: intersection.voxel.green, + blue: intersection.voxel.blue }; + } else { + voxelColor = { red: colors[whichColor].red, + green: colors[whichColor].green, + blue: colors[whichColor].blue }; + } + + var guidePosition; + + if (trackAsDelete) { + guidePosition = { x: intersection.voxel.x, + y: intersection.voxel.y, + z: intersection.voxel.z }; + Overlays.editOverlay(voxelPreview, { + position: guidePosition, + size: intersection.voxel.s, + visible: true, + color: { red: 255, green: 0, blue: 0 }, + solid: false, + alpha: 1 + }); + } else if (trackAsRecolor) { + guidePosition = { x: intersection.voxel.x - 0.001, + y: intersection.voxel.y - 0.001, + z: intersection.voxel.z - 0.001 }; + + Overlays.editOverlay(voxelPreview, { + position: guidePosition, + size: intersection.voxel.s + 0.002, + visible: true, + color: voxelColor, + solid: true, + alpha: 0.8 + }); + + } else if (!isExtruding) { + guidePosition = { x: intersection.voxel.x, + y: intersection.voxel.y, + z: intersection.voxel.z }; + + if (intersection.face == "MIN_X_FACE") { + guidePosition.x -= intersection.voxel.s; + } else if (intersection.face == "MAX_X_FACE") { + guidePosition.x += intersection.voxel.s; + } else if (intersection.face == "MIN_Y_FACE") { + guidePosition.y -= intersection.voxel.s; + } else if (intersection.face == "MAX_Y_FACE") { + guidePosition.y += intersection.voxel.s; + } else if (intersection.face == "MIN_Z_FACE") { + guidePosition.z -= intersection.voxel.s; + } else if (intersection.face == "MAX_Z_FACE") { + guidePosition.z += intersection.voxel.s; + } + + Overlays.editOverlay(voxelPreview, { + position: guidePosition, + size: intersection.voxel.s, + visible: true, + color: voxelColor, + solid: true, + alpha: 0.7 + }); + } else if (isExtruding) { + Overlays.editOverlay(voxelPreview, { visible: false }); + } + } else { + Overlays.editOverlay(voxelPreview, { visible: false }); + } +} + +function trackMouseEvent(event) { + trackLastMouseX = event.x; + trackLastMouseY = event.y; + trackAsDelete = event.isControl; + trackAsRecolor = event.isShifted; + showPreviewVoxel(); +} + +function trackKeyPressEvent(event) { + if (event.text == "CONTROL") { + trackAsDelete = true; + showPreviewVoxel(); + } + if (event.text == "SHIFT") { + trackAsRecolor = true; + } + showPreviewVoxel(); +} + +function trackKeyReleaseEvent(event) { + if (event.text == "CONTROL") { + trackAsDelete = false; + showPreviewVoxel(); + } + if (event.text == "SHIFT") { + trackAsRecolor = false; + } + + // on TAB release, toggle our tool state + if (event.text == "TAB") { + editToolsOn = !editToolsOn; + moveTools(); + Audio.playSound(clickSound, audioOptions); + } + showPreviewVoxel(); +} + function mousePressEvent(event) { + + // if our tools are off, then don't do anything + if (!editToolsOn) { + return; + } + + if (event.isRightButton) { + // debugging of right button click on mac... + print(">>>> RIGHT BUTTON <<<<<"); + } + trackMouseEvent(event); // used by preview support mouseX = event.x; mouseY = event.y; var pickRay = Camera.computePickRay(event.x, event.y); @@ -118,16 +291,17 @@ function mousePressEvent(event) { // get position for initial azimuth, elevation orbitCenter = intersection.intersection; var orbitVector = Vec3.subtract(cameraPosition, orbitCenter); - orbitRadius = vLength(orbitVector); + orbitRadius = Vec3.length(orbitVector); orbitAzimuth = Math.atan2(orbitVector.z, orbitVector.x); orbitAltitude = Math.asin(orbitVector.y / Vec3.length(orbitVector)); - } else if (event.isRightButton || event.isControl) { + } else if (trackAsDelete || event.isRightButton) { // Delete voxel Voxels.eraseVoxel(intersection.voxel.x, intersection.voxel.y, intersection.voxel.z, intersection.voxel.s); Audio.playSound(deleteSound, audioOptions); + Overlays.editOverlay(voxelPreview, { visible: false }); - } else if (event.isShifted) { + } else if (trackAsRecolor) { // Recolor Voxel Voxels.setVoxel(intersection.voxel.x, intersection.voxel.y, @@ -135,6 +309,7 @@ function mousePressEvent(event) { intersection.voxel.s, colors[whichColor].red, colors[whichColor].green, colors[whichColor].blue); Audio.playSound(changeColorSound, audioOptions); + Overlays.editOverlay(voxelPreview, { visible: false }); } else { // Add voxel on face if (whichColor == -1) { @@ -178,6 +353,7 @@ function mousePressEvent(event) { lastVoxelScale = newVoxel.s; Audio.playSound(addSound, audioOptions); + Overlays.editOverlay(voxelPreview, { visible: false }); dragStart = { x: event.x, y: event.y }; isAdding = true; } @@ -185,42 +361,52 @@ function mousePressEvent(event) { } function keyPressEvent(event) { - key_alt = event.isAlt; - key_shift = event.isShifted; - var nVal = parseInt(event.text); - if (event.text == "0") { - print("Color = Copy"); - whichColor = -1; - Audio.playSound(clickSound, audioOptions); - } else if ((nVal > 0) && (nVal <= numColors)) { - whichColor = nVal - 1; - print("Color = " + (whichColor + 1)); - Audio.playSound(clickSound, audioOptions); - } else if (event.text == "9") { - // Create a brand new 1 meter voxel in front of your avatar - var color = whichColor; - if (color == -1) color = 0; - var newPosition = getNewVoxelPosition(); - var newVoxel = { - x: newPosition.x, - y: newPosition.y , - z: newPosition.z, - s: NEW_VOXEL_SIZE, - red: colors[color].red, - green: colors[color].green, - blue: colors[color].blue }; - Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue); - setAudioPosition(); - Audio.playSound(addSound, audioOptions); - } else if (event.text == " ") { + // if our tools are off, then don't do anything + if (editToolsOn) { + key_alt = event.isAlt; + key_shift = event.isShifted; + var nVal = parseInt(event.text); + if (event.text == "0") { + print("Color = Copy"); + whichColor = -1; + Audio.playSound(clickSound, audioOptions); + moveTools(); + } else if ((nVal > 0) && (nVal <= numColors)) { + whichColor = nVal - 1; + print("Color = " + (whichColor + 1)); + Audio.playSound(clickSound, audioOptions); + moveTools(); + } else if (event.text == "9") { + // Create a brand new 1 meter voxel in front of your avatar + var color = whichColor; + if (color == -1) color = 0; + var newPosition = getNewVoxelPosition(); + var newVoxel = { + x: newPosition.x, + y: newPosition.y , + z: newPosition.z, + s: NEW_VOXEL_SIZE, + red: colors[color].red, + green: colors[color].green, + blue: colors[color].blue }; + Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue); + setAudioPosition(); + Audio.playSound(addSound, audioOptions); + } + } + + // do this even if not in edit tools + if (event.text == " ") { // Reset my orientation! var orientation = { x:0, y:0, z:0, w:1 }; Camera.setOrientation(orientation); MyAvatar.orientation = orientation; } + trackKeyPressEvent(event); // used by preview support } function keyReleaseEvent(event) { + trackKeyReleaseEvent(event); // used by preview support key_alt = false; key_shift = false; } @@ -248,7 +434,7 @@ function mouseMoveEvent(event) { var lastVoxelDistance = { x: pickRay.origin.x - lastVoxelPosition.x, y: pickRay.origin.y - lastVoxelPosition.y, z: pickRay.origin.z - lastVoxelPosition.z }; - var distance = vLength(lastVoxelDistance); + var distance = Vec3.length(lastVoxelDistance); var mouseSpot = { x: pickRay.direction.x * distance, y: pickRay.direction.y * distance, z: pickRay.direction.z * distance }; mouseSpot.x += pickRay.origin.x; mouseSpot.y += pickRay.origin.y; @@ -279,9 +465,17 @@ function mouseMoveEvent(event) { } } } + + // update the add voxel/delete voxel overlay preview + trackMouseEvent(event); } function mouseReleaseEvent(event) { + // if our tools are off, then don't do anything + if (!editToolsOn) { + return; + } + if (isOrbiting) { var cameraOrientation = Camera.getOrientation(); var eulers = Quat.safeEulerAngles(cameraOrientation); @@ -296,6 +490,41 @@ function mouseReleaseEvent(event) { isExtruding = false; } +function moveTools() { + swatchesX = (windowDimensions.x - swatchesWidth) / 2; + swatchesY = windowDimensions.y - swatchHeight; + + // create the overlays, position them in a row, set their colors, and for the selected one, use a different source image + // location so that it displays the "selected" marker + for (s = 0; s < numColors; s++) { + var imageFromX = 12 + (s * 27); + var imageFromY = 0; + if (s == whichColor) { + imageFromY = 55; + } + var swatchX = swatchesX + ((swatchWidth - 1) * s); + + Overlays.editOverlay(swatches[s], { + x: swatchX, + y: swatchesY, + subImage: { x: imageFromX, y: imageFromY, width: (swatchWidth - 1), height: swatchHeight }, + color: colors[s], + alpha: 1, + visible: editToolsOn + }); + } +} + + +function update() { + var newWindowDimensions = Controller.getViewportDimensions(); + if (newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y) { + windowDimensions = newWindowDimensions; + print("window resized..."); + moveTools(); + } +} + Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); Controller.mouseMoveEvent.connect(mouseMoveEvent); @@ -303,5 +532,15 @@ Controller.keyPressEvent.connect(keyPressEvent); Controller.keyReleaseEvent.connect(keyReleaseEvent); function scriptEnding() { + Overlays.deleteOverlay(voxelPreview); + for (s = 0; s < numColors; s++) { + Overlays.deleteOverlay(swatches[s]); + } } Script.scriptEnding.connect(scriptEnding); + + +Script.willSendVisualDataCallback.connect(update); + + + diff --git a/interface/src/ControllerScriptingInterface.cpp b/interface/src/ControllerScriptingInterface.cpp index b3d6170bff..b60615f124 100644 --- a/interface/src/ControllerScriptingInterface.cpp +++ b/interface/src/ControllerScriptingInterface.cpp @@ -250,3 +250,7 @@ void ControllerScriptingInterface::releaseJoystick(int joystickIndex) { } } +glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { + QGLWidget* widget = Application::getInstance()->getGLWidget(); + return glm::vec2(widget->width(), widget->height()); +} diff --git a/interface/src/ControllerScriptingInterface.h b/interface/src/ControllerScriptingInterface.h index f0a50559f9..6fe5a60fa4 100644 --- a/interface/src/ControllerScriptingInterface.h +++ b/interface/src/ControllerScriptingInterface.h @@ -74,6 +74,8 @@ public slots: virtual void captureJoystick(int joystickIndex); virtual void releaseJoystick(int joystickIndex); + virtual glm::vec2 getViewportDimensions() const; + private: const PalmData* getPrimaryPalm() const; const PalmData* getPalm(int palmIndex) const; From ada2594ad17462ef92c625877a544be0594fe517 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Feb 2014 16:36:54 -0800 Subject: [PATCH 34/83] Working on getting the head translation, too. --- interface/src/Application.cpp | 1 + interface/src/devices/Visage.cpp | 17 +++++++++++++---- interface/src/devices/Visage.h | 5 ++++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 098b42dccf..fc8bf8e899 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3831,6 +3831,7 @@ void Application::resetSensors() { _mouseY = _glWidget->height() / 2; _faceshift.reset(); + _visage.reset(); if (OculusManager::isConnected()) { OculusManager::reset(); diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 59b3ac06f8..94992417f4 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -24,11 +24,15 @@ namespace VisageSDK { using namespace VisageSDK; +const glm::vec3 DEFAULT_HEAD_ORIGIN(0.0f, 0.0f, 0.3f); + Visage::Visage() : - _active(false) { + _active(false), + _headOrigin(DEFAULT_HEAD_ORIGIN) { #ifdef HAVE_VISAGE switchToResourcesParentIfRequired(); - initializeLicenseManager("resources/visage/license.vlc"); + QByteArray licensePath = "resources/visage/license.vlc"; + initializeLicenseManager(licensePath); _tracker = new VisageTracker2("resources/visage/Facial Features Tracker - Asymmetric.cfg"); if (_tracker->trackFromCam()) { _data = new FaceData(); @@ -52,10 +56,15 @@ Visage::~Visage() { void Visage::update() { #ifdef HAVE_VISAGE - _active = (_tracker->getTrackingData(_data) == TRACK_STAT_OK); + _active = (_tracker && _tracker->getTrackingData(_data) == TRACK_STAT_OK); if (!_active) { return; } - _headRotation = glm::quat(glm::vec3(_data->faceRotation[0], _data->faceRotation[1], _data->faceRotation[2])); + _headRotation = glm::quat(glm::vec3(-_data->faceRotation[0], -_data->faceRotation[1], _data->faceRotation[2])); + _headTranslation = glm::vec3(_data->faceTranslation[0], _data->faceTranslation[1], _data->faceTranslation[2]) - _headOrigin; #endif } + +void Visage::reset() { + _headOrigin += _headTranslation; +} diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index f16119cdbd..20c361bda0 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -13,8 +13,8 @@ #include namespace VisageSDK { - class FaceData; class VisageTracker2; + struct FaceData; } /// Handles input from the Visage webcam feature tracking software. @@ -30,6 +30,7 @@ public: const glm::vec3& getHeadTranslation() const { return _headTranslation; } void update(); + void reset(); private: @@ -39,6 +40,8 @@ private: bool _active; glm::quat _headRotation; glm::vec3 _headTranslation; + + glm::vec3 _headOrigin; }; #endif /* defined(__interface__Visage__) */ From fe7970665389307d22f6c285f56de89b0e7b55d0 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Feb 2014 16:42:30 -0800 Subject: [PATCH 35/83] Working on the translation scale. --- interface/src/devices/Visage.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 94992417f4..cce5f66340 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -32,7 +32,7 @@ Visage::Visage() : #ifdef HAVE_VISAGE switchToResourcesParentIfRequired(); QByteArray licensePath = "resources/visage/license.vlc"; - initializeLicenseManager(licensePath); + initializeLicenseManager(licensePath.data()); _tracker = new VisageTracker2("resources/visage/Facial Features Tracker - Asymmetric.cfg"); if (_tracker->trackFromCam()) { _data = new FaceData(); @@ -54,17 +54,20 @@ Visage::~Visage() { #endif } +const float TRANSLATION_SCALE = 50.0f; + void Visage::update() { #ifdef HAVE_VISAGE _active = (_tracker && _tracker->getTrackingData(_data) == TRACK_STAT_OK); if (!_active) { return; } - _headRotation = glm::quat(glm::vec3(-_data->faceRotation[0], -_data->faceRotation[1], _data->faceRotation[2])); - _headTranslation = glm::vec3(_data->faceTranslation[0], _data->faceTranslation[1], _data->faceTranslation[2]) - _headOrigin; + _headRotation = glm::quat(glm::vec3(-_data->faceRotation[0], -_data->faceRotation[1], _data->faceRotation[2])); + _headTranslation = (glm::vec3(_data->faceTranslation[0], _data->faceTranslation[1], _data->faceTranslation[2]) - + _headOrigin) * TRANSLATION_SCALE; #endif } void Visage::reset() { - _headOrigin += _headTranslation; + _headOrigin += _headTranslation / TRANSLATION_SCALE; } From 866b3dbb6315850b07647a9ef2ac1e3dc5a1ffcf Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 18 Feb 2014 16:47:50 -0800 Subject: [PATCH 36/83] scripting additions --- .../script-engine/src/AbstractControllerScriptingInterface.h | 4 ++++ libraries/script-engine/src/EventTypes.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/libraries/script-engine/src/AbstractControllerScriptingInterface.h b/libraries/script-engine/src/AbstractControllerScriptingInterface.h index d9878d0b71..1878edd4d6 100644 --- a/libraries/script-engine/src/AbstractControllerScriptingInterface.h +++ b/libraries/script-engine/src/AbstractControllerScriptingInterface.h @@ -52,6 +52,10 @@ public slots: virtual void captureWheelEvents() = 0; virtual void releaseWheelEvents() = 0; + virtual void captureJoystick(int joystickIndex) = 0; + virtual void releaseJoystick(int joystickIndex) = 0; + + virtual glm::vec2 getViewportDimensions() const = 0; signals: void keyPressEvent(const KeyEvent& event); diff --git a/libraries/script-engine/src/EventTypes.cpp b/libraries/script-engine/src/EventTypes.cpp index 963912fd34..8fac2bcd2a 100644 --- a/libraries/script-engine/src/EventTypes.cpp +++ b/libraries/script-engine/src/EventTypes.cpp @@ -102,6 +102,8 @@ KeyEvent::KeyEvent(const QKeyEvent& event) { text = "END"; } else if (key == Qt::Key_Help) { text = "HELP"; + } else if (key == Qt::Key_CapsLock) { + text = "CAPS LOCK"; } } @@ -208,6 +210,8 @@ void keyEventFromScriptValue(const QScriptValue& object, KeyEvent& event) { event.key = Qt::Key_End; } else if (event.text.toUpper() == "HELP") { event.key = Qt::Key_Help; + } else if (event.text.toUpper() == "CAPS LOCK") { + event.key = Qt::Key_CapsLock; } else { event.key = event.text.at(0).unicode(); } From 9c4143e1beb7234ec03852b5001e850739f257e2 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Feb 2014 17:03:43 -0800 Subject: [PATCH 37/83] Working on gaze deflection. --- interface/src/Application.cpp | 14 +++++++++++++- interface/src/devices/Visage.cpp | 10 +++++++--- interface/src/devices/Visage.h | 6 ++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fc8bf8e899..88c7af102b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2070,13 +2070,25 @@ void Application::updateMyAvatarLookAtPosition(glm::vec3& lookAtSpot) { } lookAtSpot = _mouseRayOrigin + _mouseRayDirection * distance; } + bool trackerActive = false; + float eyePitch, eyeYaw; if (_faceshift.isActive()) { + eyePitch = _faceshift.getEstimatedEyePitch(); + eyeYaw = _faceshift.getEstimatedEyeYaw(); + trackerActive = true; + + } else if (_visage.isActive()) { + eyePitch = _visage.getEstimatedEyePitch(); + eyeYaw = _visage.getEstimatedEyeYaw(); + trackerActive = true; + } + if (trackerActive) { // deflect using Faceshift gaze data glm::vec3 origin = _myAvatar->getHead().calculateAverageEyePosition(); float pitchSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? -1.0f : 1.0f; float deflection = Menu::getInstance()->getFaceshiftEyeDeflection(); lookAtSpot = origin + _myCamera.getRotation() * glm::quat(glm::radians(glm::vec3( - _faceshift.getEstimatedEyePitch() * pitchSign * deflection, _faceshift.getEstimatedEyeYaw() * deflection, 0.0f))) * + eyePitch * pitchSign * deflection, eyeYaw * deflection, 0.0f))) * glm::inverse(_myCamera.getRotation()) * (lookAtSpot - origin); } _myAvatar->getHead().setLookAtPosition(lookAtSpot); diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index cce5f66340..8696db3af4 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -24,11 +24,13 @@ namespace VisageSDK { using namespace VisageSDK; -const glm::vec3 DEFAULT_HEAD_ORIGIN(0.0f, 0.0f, 0.3f); +const glm::vec3 DEFAULT_HEAD_ORIGIN(0.0f, 0.0f, 0.7f); Visage::Visage() : _active(false), - _headOrigin(DEFAULT_HEAD_ORIGIN) { + _headOrigin(DEFAULT_HEAD_ORIGIN), + _estimatedEyePitch(0.0f), + _estimatedEyeYaw(0.0f) { #ifdef HAVE_VISAGE switchToResourcesParentIfRequired(); QByteArray licensePath = "resources/visage/license.vlc"; @@ -54,7 +56,7 @@ Visage::~Visage() { #endif } -const float TRANSLATION_SCALE = 50.0f; +const float TRANSLATION_SCALE = 20.0f; void Visage::update() { #ifdef HAVE_VISAGE @@ -65,6 +67,8 @@ void Visage::update() { _headRotation = glm::quat(glm::vec3(-_data->faceRotation[0], -_data->faceRotation[1], _data->faceRotation[2])); _headTranslation = (glm::vec3(_data->faceTranslation[0], _data->faceTranslation[1], _data->faceTranslation[2]) - _headOrigin) * TRANSLATION_SCALE; + _estimatedEyePitch = glm::degrees(_data->gazeDirection[1]); + _estimatedEyeYaw = glm::degrees(_data->gazeDirection[0]); #endif } diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 20c361bda0..966c41335e 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -29,6 +29,9 @@ public: const glm::quat& getHeadRotation() const { return _headRotation; } const glm::vec3& getHeadTranslation() const { return _headTranslation; } + float getEstimatedEyePitch() const { return _estimatedEyePitch; } + float getEstimatedEyeYaw() const { return _estimatedEyeYaw; } + void update(); void reset(); @@ -42,6 +45,9 @@ private: glm::vec3 _headTranslation; glm::vec3 _headOrigin; + + float _estimatedEyePitch; + float _estimatedEyeYaw; }; #endif /* defined(__interface__Visage__) */ From c134b8de5b46b9a20156037c06d1de91bb41349a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 18 Feb 2014 17:08:12 -0800 Subject: [PATCH 38/83] Remove Avatar::_hand, use AvatarData::_handData --- interface/src/avatar/Avatar.cpp | 10 ++++------ interface/src/avatar/Avatar.h | 4 ++-- interface/src/avatar/Hand.cpp | 4 ++-- interface/src/avatar/MyAvatar.cpp | 12 ++++++------ interface/src/avatar/SkeletonModel.cpp | 13 ++++++------ interface/src/devices/SixenseManager.cpp | 18 ++++++++--------- libraries/avatars/src/AvatarData.cpp | 10 +++------- libraries/avatars/src/HandData.cpp | 25 ++++++++++++++++++------ libraries/avatars/src/HandData.h | 4 ++++ 9 files changed, 55 insertions(+), 45 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 4edead7b32..26cb17c7b1 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -60,7 +60,6 @@ const float CHAT_MESSAGE_HEIGHT = 0.1f; Avatar::Avatar() : AvatarData(), _head(this), - _hand(this), _skeletonModel(this), _bodyYawDelta(0.0f), _mode(AVATAR_MODE_STANDING), @@ -82,17 +81,16 @@ Avatar::Avatar() : // give the pointer to our head to inherited _headData variable from AvatarData _headData = &_head; - _handData = &_hand; + _handData = static_cast(new Hand(this)); } Avatar::~Avatar() { _headData = NULL; - _handData = NULL; } void Avatar::init() { _head.init(); - _hand.init(); + getHand()->init(); _skeletonModel.init(); _initialized = true; } @@ -115,7 +113,7 @@ void Avatar::simulate(float deltaTime) { // copy velocity so we can use it later for acceleration glm::vec3 oldVelocity = getVelocity(); - _hand.simulate(deltaTime, false); + getHand()->simulate(deltaTime, false); _skeletonModel.simulate(deltaTime); _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); glm::vec3 headPosition; @@ -254,7 +252,7 @@ void Avatar::renderBody(bool forceRenderHead) { if (forceRenderHead) { _head.render(1.0f); } - _hand.render(false); + getHand()->render(false); } bool Avatar::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index cc1168ca88..1df4ae1d74 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -84,7 +84,7 @@ public: float getScale() const { return _scale; } const glm::vec3& getVelocity() const { return _velocity; } Head& getHead() { return _head; } - Hand& getHand() { return _hand; } + Hand* getHand() { return static_cast(_handData); } glm::quat getWorldAlignedOrientation() const; Node* getOwningAvatarMixer() { return _owningAvatarMixer.data(); } @@ -130,7 +130,7 @@ public slots: protected: Head _head; - Hand _hand; + //Hand _hand; SkeletonModel _skeletonModel; float _bodyYawDelta; AvatarMode _mode; diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 999551eb48..efbdfa2438 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -133,8 +133,8 @@ void Hand::playSlaps(PalmData& palm, Avatar* avatar) bool wasColliding = palm.getIsCollidingWithPalm(); palm.setIsCollidingWithPalm(false); // If 'Play Slaps' is enabled, look for palm-to-palm collisions and make sound - for (size_t j = 0; j < avatar->getHand().getNumPalms(); j++) { - PalmData& otherPalm = avatar->getHand().getPalms()[j]; + for (size_t j = 0; j < avatar->getHand()->getNumPalms(); j++) { + PalmData& otherPalm = avatar->getHand()->getPalms()[j]; if (!otherPalm.isActive()) { continue; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 41ad4b22b1..0e8438610b 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -73,7 +73,7 @@ void MyAvatar::reset() { //_headMouseX = _glWidget->width() / 2; //_headMouseY = _glWidget->height() / 2; _head.reset(); - _hand.reset(); + getHand()->reset(); setVelocity(glm::vec3(0,0,0)); setThrust(glm::vec3(0,0,0)); @@ -314,8 +314,8 @@ void MyAvatar::simulate(float deltaTime) { _position += _velocity * deltaTime; // update avatar skeleton and simulate hand and head - _hand.collideAgainstOurself(); - _hand.simulate(deltaTime, true); + getHand()->collideAgainstOurself(); + getHand()->simulate(deltaTime, true); _skeletonModel.simulate(deltaTime); _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); glm::vec3 headPosition; @@ -701,7 +701,7 @@ void MyAvatar::renderBody(bool forceRenderHead) { if (forceRenderHead || (glm::length(myCamera->getPosition() - _head.calculateAverageEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE)) { _head.render(1.0f); } - _hand.render(true); + getHand()->render(true); } void MyAvatar::updateThrust(float deltaTime) { @@ -994,10 +994,10 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) { } // collide our hands against them - _hand.collideAgainstAvatar(avatar, true); + getHand()->collideAgainstAvatar(avatar, true); // collide their hands against us - avatar->getHand().collideAgainstAvatar(this, false); + avatar->getHand()->collideAgainstAvatar(this, false); } } } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 9bf2e0f727..474cefdab5 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -8,10 +8,9 @@ #include -#include - #include "Application.h" #include "Avatar.h" +#include "Hand.h" #include "Menu.h" #include "SkeletonModel.h" @@ -33,8 +32,8 @@ void SkeletonModel::simulate(float deltaTime) { // find the left and rightmost active Leap palms int leftPalmIndex, rightPalmIndex; - HandData& hand = _owningAvatar->getHand(); - hand.getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex); + Hand* hand = _owningAvatar->getHand(); + hand->getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex); const float HAND_RESTORATION_PERIOD = 1.f; // seconds float handRestorePercent = glm::clamp(deltaTime / HAND_RESTORATION_PERIOD, 0.f, 1.f); @@ -52,14 +51,14 @@ void SkeletonModel::simulate(float deltaTime) { } else if (leftPalmIndex == rightPalmIndex) { // right hand only applyPalmData(geometry.rightHandJointIndex, geometry.rightFingerJointIndices, geometry.rightFingertipJointIndices, - hand.getPalms()[leftPalmIndex]); + hand->getPalms()[leftPalmIndex]); restoreLeftHandPosition(handRestorePercent); } else { applyPalmData(geometry.leftHandJointIndex, geometry.leftFingerJointIndices, geometry.leftFingertipJointIndices, - hand.getPalms()[leftPalmIndex]); + hand->getPalms()[leftPalmIndex]); applyPalmData(geometry.rightHandJointIndex, geometry.rightFingerJointIndices, geometry.rightFingertipJointIndices, - hand.getPalms()[rightPalmIndex]); + hand->getPalms()[rightPalmIndex]); } } diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 79feb5eb3f..9ff34e698e 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -45,7 +45,7 @@ void SixenseManager::update(float deltaTime) { return; } MyAvatar* avatar = Application::getInstance()->getAvatar(); - Hand& hand = avatar->getHand(); + Hand* hand = avatar->getHand(); int maxControllers = sixenseGetMaxControllers(); for (int i = 0; i < maxControllers; i++) { @@ -60,16 +60,16 @@ void SixenseManager::update(float deltaTime) { // Either find a palm matching the sixense controller, or make a new one PalmData* palm; bool foundHand = false; - for (int j = 0; j < hand.getNumPalms(); j++) { - if (hand.getPalms()[j].getSixenseID() == data.controller_index) { - palm = &hand.getPalms()[j]; + for (int j = 0; j < hand->getNumPalms(); j++) { + if (hand->getPalms()[j].getSixenseID() == data.controller_index) { + palm = &(hand->getPalms()[j]); foundHand = true; } } if (!foundHand) { - PalmData newPalm(&hand); - hand.getPalms().push_back(newPalm); - palm = &hand.getPalms()[hand.getNumPalms() - 1]; + PalmData newPalm(hand); + hand->getPalms().push_back(newPalm); + palm = &(hand->getPalms()[hand->getNumPalms() - 1]); palm->setSixenseID(data.controller_index); printf("Found new Sixense controller, ID %i\n", data.controller_index); } @@ -107,7 +107,7 @@ void SixenseManager::update(float deltaTime) { } // initialize the "finger" based on the direction - FingerData finger(palm, &hand); + FingerData finger(palm, hand); finger.setActive(true); finger.setRawRootPosition(position); const float FINGER_LENGTH = 300.0f; // Millimeters @@ -130,7 +130,7 @@ void SixenseManager::update(float deltaTime) { // if the controllers haven't been moved in a while, disable const int MOVEMENT_DISABLE_DURATION = 30 * 1000 * 1000; if (usecTimestampNow() - _lastMovement > MOVEMENT_DISABLE_DURATION) { - for (vector::iterator it = hand.getPalms().begin(); it != hand.getPalms().end(); it++) { + for (vector::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) { it->setActive(false); } } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index c375f8b82d..3c89f45d23 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -63,10 +63,6 @@ QByteArray AvatarData::toByteArray() { if (!_headData) { _headData = new HeadData(this); } - // lazily allocate memory for HandData in case we're not an Avatar instance - if (!_handData) { - _handData = new HandData(this); - } QByteArray avatarDataByteArray; avatarDataByteArray.resize(MAX_PACKET_SIZE); @@ -152,8 +148,8 @@ QByteArray AvatarData::toByteArray() { // pupil dilation destinationBuffer += packFloatToByte(destinationBuffer, _headData->_pupilDilation, 1.0f); - // leap hand data - destinationBuffer += _handData->encodeRemoteData(destinationBuffer); + // hand data + destinationBuffer += HandData::encodeData(_handData, destinationBuffer); return avatarDataByteArray.left(destinationBuffer - startPosition); } @@ -259,7 +255,7 @@ int AvatarData::parseData(const QByteArray& packet) { // pupil dilation sourceBuffer += unpackFloatFromByte(sourceBuffer, _headData->_pupilDilation, 1.0f); - // leap hand data + // hand data if (sourceBuffer - startPosition < packet.size()) { // check passed, bytes match sourceBuffer += _handData->decodeRemoteData(packet.mid(sourceBuffer - startPosition)); diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 5a923eea93..e4bb187f28 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -113,17 +113,30 @@ _owningHandData(owningHandData) setTrailLength(standardTrailLength); } +// static +int HandData::encodeData(HandData* hand, unsigned char* destinationBuffer) { + if (hand) { + return hand->encodeRemoteData(destinationBuffer); + } + // else encode empty data: + // One byte for zero hands + // One byte for error checking. + *destinationBuffer = 0; + *(destinationBuffer + 1) = 1; + return 2; +} + int HandData::encodeRemoteData(unsigned char* destinationBuffer) { const unsigned char* startPosition = destinationBuffer; - unsigned int numHands = 0; + unsigned int numPalms = 0; for (unsigned int handIndex = 0; handIndex < getNumPalms(); ++handIndex) { PalmData& palm = getPalms()[handIndex]; if (palm.isActive()) { - numHands++; + numPalms++; } } - *destinationBuffer++ = numHands; + *destinationBuffer++ = numPalms; for (unsigned int handIndex = 0; handIndex < getNumPalms(); ++handIndex) { PalmData& palm = getPalms()[handIndex]; @@ -162,9 +175,9 @@ int HandData::encodeRemoteData(unsigned char* destinationBuffer) { int HandData::decodeRemoteData(const QByteArray& dataByteArray) { const unsigned char* startPosition; const unsigned char* sourceBuffer = startPosition = reinterpret_cast(dataByteArray.data()); - unsigned int numHands = *sourceBuffer++; + unsigned int numPalms = *sourceBuffer++; - for (unsigned int handIndex = 0; handIndex < numHands; ++handIndex) { + for (unsigned int handIndex = 0; handIndex < numPalms; ++handIndex) { if (handIndex >= getNumPalms()) addNewPalm(); PalmData& palm = getPalms()[handIndex]; @@ -203,7 +216,7 @@ int HandData::decodeRemoteData(const QByteArray& dataByteArray) { } } // Turn off any hands which weren't used. - for (unsigned int handIndex = numHands; handIndex < getNumPalms(); ++handIndex) { + for (unsigned int handIndex = numPalms; handIndex < getNumPalms(); ++handIndex) { PalmData& palm = getPalms()[handIndex]; palm.setActive(false); } diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 550c62e829..4046a0a875 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -71,6 +71,10 @@ public: void setFingerTrailLength(unsigned int length); void updateFingerTrails(); + // use these static methods for safety + static int encodeData(HandData* hand, unsigned char* destinationBuffer); + static int decodeData(HandData* hand, const QByteArray& dataByteArray); + // Use these for sending and receiving hand data int encodeRemoteData(unsigned char* destinationBuffer); int decodeRemoteData(const QByteArray& dataByteArray); From e97a912d9746600afd880cf74bab4d5b64e592ac Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Feb 2014 17:19:29 -0800 Subject: [PATCH 39/83] Working on blendshape coefficients. --- interface/src/avatar/Head.cpp | 26 +++++++++++--------------- interface/src/devices/Visage.cpp | 11 +++++++++-- interface/src/devices/Visage.h | 6 ++++++ 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index ddb0660364..5c6100764a 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -62,24 +62,20 @@ void Head::simulate(float deltaTime, bool isMine) { // Update audio trailing average for rendering facial animations Faceshift* faceshift = Application::getInstance()->getFaceshift(); + Visage* visage = Application::getInstance()->getVisage(); if (isMine) { - _isFaceshiftConnected = faceshift->isActive(); + _isFaceshiftConnected = false; + if (faceshift->isActive()) { + _blendshapeCoefficients = faceshift->getBlendshapeCoefficients(); + _isFaceshiftConnected = true; + + } else if (visage->isActive()) { + _blendshapeCoefficients = visage->getBlendshapeCoefficients(); + _isFaceshiftConnected = true; + } } - if (isMine && faceshift->isActive()) { - const float EYE_OPEN_SCALE = 0.5f; - _leftEyeBlink = faceshift->getLeftBlink() - EYE_OPEN_SCALE * faceshift->getLeftEyeOpen(); - _rightEyeBlink = faceshift->getRightBlink() - EYE_OPEN_SCALE * faceshift->getRightEyeOpen(); - - // set these values based on how they'll be used. if we use faceshift in the long term, we'll want a complete - // mapping between their blendshape coefficients and our avatar features - const float MOUTH_SIZE_SCALE = 2500.0f; - _averageLoudness = faceshift->getMouthSize() * faceshift->getMouthSize() * MOUTH_SIZE_SCALE; - const float BROW_HEIGHT_SCALE = 0.005f; - _browAudioLift = faceshift->getBrowUpCenter() * BROW_HEIGHT_SCALE; - _blendshapeCoefficients = faceshift->getBlendshapeCoefficients(); - - } else if (!_isFaceshiftConnected) { + if (!_isFaceshiftConnected) { // Update eye saccades const float AVERAGE_MICROSACCADE_INTERVAL = 0.50f; const float AVERAGE_SACCADE_INTERVAL = 4.0f; diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 8696db3af4..c6fb5b9668 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -67,8 +67,15 @@ void Visage::update() { _headRotation = glm::quat(glm::vec3(-_data->faceRotation[0], -_data->faceRotation[1], _data->faceRotation[2])); _headTranslation = (glm::vec3(_data->faceTranslation[0], _data->faceTranslation[1], _data->faceTranslation[2]) - _headOrigin) * TRANSLATION_SCALE; - _estimatedEyePitch = glm::degrees(_data->gazeDirection[1]); - _estimatedEyeYaw = glm::degrees(_data->gazeDirection[0]); + _estimatedEyePitch = glm::degrees(-_data->gazeDirection[1]); + _estimatedEyeYaw = glm::degrees(-_data->gazeDirection[0]); + + for (int i = 0; i < _data->actionUnitCount; i++) { + if (!_data->actionUnitsUsed[i]) { + continue; + } + qDebug() << _data->actionUnitsNames[i] << _data->actionUnits[i]; + } #endif } diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 966c41335e..383c81be54 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -9,6 +9,8 @@ #ifndef __interface__Visage__ #define __interface__Visage__ +#include + #include #include @@ -32,6 +34,8 @@ public: float getEstimatedEyePitch() const { return _estimatedEyePitch; } float getEstimatedEyeYaw() const { return _estimatedEyeYaw; } + const std::vector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } + void update(); void reset(); @@ -48,6 +52,8 @@ private: float _estimatedEyePitch; float _estimatedEyeYaw; + + std::vector _blendshapeCoefficients; }; #endif /* defined(__interface__Visage__) */ From 4010f3ab3f0d18b5d4333ad96728e69b9915c418 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 18 Feb 2014 17:41:46 -0800 Subject: [PATCH 40/83] Remove Avatar::_head, use AvatarData::_headData --- interface/src/Application.cpp | 40 ++++++------ interface/src/Audio.cpp | 4 +- interface/src/Menu.cpp | 6 +- interface/src/avatar/Avatar.cpp | 39 ++++++----- interface/src/avatar/Avatar.h | 7 +- interface/src/avatar/MyAvatar.cpp | 89 ++++++++++++++------------ interface/src/avatar/SkeletonModel.cpp | 4 +- interface/src/ui/Snapshot.cpp | 2 +- 8 files changed, 98 insertions(+), 93 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 406a4929d7..7c8d6e3a34 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -450,22 +450,22 @@ void Application::paintGL() { _myCamera.setUpShift(0.0f); _myCamera.setDistance(0.0f); _myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing - _myCamera.setTargetPosition(_myAvatar->getHead().calculateAverageEyePosition()); - _myCamera.setTargetRotation(_myAvatar->getHead().getOrientation()); + _myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition()); + _myCamera.setTargetRotation(_myAvatar->getHead()->getOrientation()); } else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { _myCamera.setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay - _myCamera.setTargetPosition(_myAvatar->getHead().calculateAverageEyePosition()); - _myCamera.setTargetRotation(_myAvatar->getHead().getCameraOrientation()); + _myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition()); + _myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation()); } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { _myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing _myCamera.setTargetPosition(_myAvatar->getUprightHeadPosition()); - _myCamera.setTargetRotation(_myAvatar->getHead().getCameraOrientation()); + _myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation()); } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { _myCamera.setTightness(0.0f); - float headHeight = _myAvatar->getHead().calculateAverageEyePosition().y - _myAvatar->getPosition().y; + float headHeight = _myAvatar->getHead()->calculateAverageEyePosition().y - _myAvatar->getPosition().y; _myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _myAvatar->getScale()); _myCamera.setTargetPosition(_myAvatar->getPosition() + glm::vec3(0, headHeight, 0)); _myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PIf, 0.0f))); @@ -529,14 +529,14 @@ void Application::paintGL() { _mirrorCamera.setTargetPosition(_myAvatar->getChestPosition()); } else { // HEAD zoom level _mirrorCamera.setDistance(MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale()); - if (_myAvatar->getSkeletonModel().isActive() && _myAvatar->getHead().getFaceModel().isActive()) { + if (_myAvatar->getSkeletonModel().isActive() && _myAvatar->getHead()->getFaceModel().isActive()) { // as a hack until we have a better way of dealing with coordinate precision issues, reposition the // face/body so that the average eye position lies at the origin eyeRelativeCamera = true; _mirrorCamera.setTargetPosition(glm::vec3()); } else { - _mirrorCamera.setTargetPosition(_myAvatar->getHead().calculateAverageEyePosition()); + _mirrorCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition()); } } @@ -558,26 +558,26 @@ void Application::paintGL() { if (eyeRelativeCamera) { // save absolute translations glm::vec3 absoluteSkeletonTranslation = _myAvatar->getSkeletonModel().getTranslation(); - glm::vec3 absoluteFaceTranslation = _myAvatar->getHead().getFaceModel().getTranslation(); + glm::vec3 absoluteFaceTranslation = _myAvatar->getHead()->getFaceModel().getTranslation(); // get the eye positions relative to the neck and use them to set the face translation glm::vec3 leftEyePosition, rightEyePosition; - _myAvatar->getHead().getFaceModel().setTranslation(glm::vec3()); - _myAvatar->getHead().getFaceModel().getEyePositions(leftEyePosition, rightEyePosition); - _myAvatar->getHead().getFaceModel().setTranslation((leftEyePosition + rightEyePosition) * -0.5f); + _myAvatar->getHead()->getFaceModel().setTranslation(glm::vec3()); + _myAvatar->getHead()->getFaceModel().getEyePositions(leftEyePosition, rightEyePosition); + _myAvatar->getHead()->getFaceModel().setTranslation((leftEyePosition + rightEyePosition) * -0.5f); // get the neck position relative to the body and use it to set the skeleton translation glm::vec3 neckPosition; _myAvatar->getSkeletonModel().setTranslation(glm::vec3()); _myAvatar->getSkeletonModel().getNeckPosition(neckPosition); - _myAvatar->getSkeletonModel().setTranslation(_myAvatar->getHead().getFaceModel().getTranslation() - + _myAvatar->getSkeletonModel().setTranslation(_myAvatar->getHead()->getFaceModel().getTranslation() - neckPosition); displaySide(_mirrorCamera, true); // restore absolute translations _myAvatar->getSkeletonModel().setTranslation(absoluteSkeletonTranslation); - _myAvatar->getHead().getFaceModel().setTranslation(absoluteFaceTranslation); + _myAvatar->getHead()->getFaceModel().setTranslation(absoluteFaceTranslation); } else { displaySide(_mirrorCamera, true); } @@ -1975,8 +1975,8 @@ const float MAX_VOXEL_EDIT_DISTANCE = 50.0f; const float HEAD_SPHERE_RADIUS = 0.07f; bool Application::isLookingAtMyAvatar(Avatar* avatar) { - glm::vec3 theirLookat = avatar->getHead().getLookAtPosition(); - glm::vec3 myHeadPosition = _myAvatar->getHead().getPosition(); + glm::vec3 theirLookat = avatar->getHead()->getLookAtPosition(); + glm::vec3 myHeadPosition = _myAvatar->getHead()->getPosition(); if (pointInSphere(theirLookat, myHeadPosition, HEAD_SPHERE_RADIUS * _myAvatar->getScale())) { return true; @@ -2037,7 +2037,7 @@ void Application::updateFaceshift() { // Copy angular velocity if measured by faceshift, to the head if (_faceshift.isActive()) { - _myAvatar->getHead().setAngularVelocity(_faceshift.getHeadAngularVelocity()); + _myAvatar->getHead()->setAngularVelocity(_faceshift.getHeadAngularVelocity()); } } @@ -2054,7 +2054,7 @@ void Application::updateMyAvatarLookAtPosition(glm::vec3& lookAtSpot) { float distance = TREE_SCALE; if (_myAvatar->getLookAtTargetAvatar()) { distance = glm::distance(_mouseRayOrigin, - static_cast(_myAvatar->getLookAtTargetAvatar())->getHead().calculateAverageEyePosition()); + static_cast(_myAvatar->getLookAtTargetAvatar())->getHead()->calculateAverageEyePosition()); } else if (_isHoverVoxel) { distance = glm::distance(_mouseRayOrigin, getMouseVoxelWorldCoordinates(_hoverVoxel)); @@ -2063,14 +2063,14 @@ void Application::updateMyAvatarLookAtPosition(glm::vec3& lookAtSpot) { } if (_faceshift.isActive()) { // deflect using Faceshift gaze data - glm::vec3 origin = _myAvatar->getHead().calculateAverageEyePosition(); + glm::vec3 origin = _myAvatar->getHead()->calculateAverageEyePosition(); float pitchSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? -1.0f : 1.0f; float deflection = Menu::getInstance()->getFaceshiftEyeDeflection(); lookAtSpot = origin + _myCamera.getRotation() * glm::quat(glm::radians(glm::vec3( _faceshift.getEstimatedEyePitch() * pitchSign * deflection, _faceshift.getEstimatedEyeYaw() * deflection, 0.0f))) * glm::inverse(_myCamera.getRotation()) * (lookAtSpot - origin); } - _myAvatar->getHead().setLookAtPosition(lookAtSpot); + _myAvatar->getHead()->setLookAtPosition(lookAtSpot); } void Application::updateHoverVoxels(float deltaTime, float& distance, BoxFace& face) { diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 0cf67be2bf..22148609c8 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -467,8 +467,8 @@ void Audio::handleAudioInput() { if (audioMixer && audioMixer->getActiveSocket()) { MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar(); - glm::vec3 headPosition = interfaceAvatar->getHead().getPosition(); - glm::quat headOrientation = interfaceAvatar->getHead().getOrientation(); + glm::vec3 headPosition = interfaceAvatar->getHead()->getPosition(); + glm::quat headOrientation = interfaceAvatar->getHead()->getOrientation(); // we need the amount of bytes in the buffer + 1 for type // + 12 for 3 floats for position + float for bearing + 1 attenuation byte diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 81ed4b589c..5b92630d91 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -773,7 +773,7 @@ void Menu::editPreferences() { QFormLayout* form = new QFormLayout(); layout->addLayout(form, 1); - QString faceURLString = applicationInstance->getAvatar()->getHead().getFaceModel().getURL().toString(); + QString faceURLString = applicationInstance->getAvatar()->getHead()->getFaceModel().getURL().toString(); QLineEdit* faceURLEdit = new QLineEdit(faceURLString); faceURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); faceURLEdit->setPlaceholderText(DEFAULT_HEAD_MODEL_URL.toString()); @@ -786,7 +786,7 @@ void Menu::editPreferences() { form->addRow("Skeleton URL:", skeletonURLEdit); QSlider* pupilDilation = new QSlider(Qt::Horizontal); - pupilDilation->setValue(applicationInstance->getAvatar()->getHead().getPupilDilation() * pupilDilation->maximum()); + pupilDilation->setValue(applicationInstance->getAvatar()->getHead()->getPupilDilation() * pupilDilation->maximum()); form->addRow("Pupil Dilation:", pupilDilation); QSlider* faceshiftEyeDeflection = new QSlider(Qt::Horizontal); @@ -862,7 +862,7 @@ void Menu::editPreferences() { applicationInstance->getAvatar()->sendIdentityPacket(); } - applicationInstance->getAvatar()->getHead().setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum()); + applicationInstance->getAvatar()->getHead()->setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum()); _maxVoxels = maxVoxels->value(); applicationInstance->getVoxels()->setMaxVoxels(_maxVoxels); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 26cb17c7b1..cea6a5029f 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -59,7 +59,6 @@ const float CHAT_MESSAGE_HEIGHT = 0.1f; Avatar::Avatar() : AvatarData(), - _head(this), _skeletonModel(this), _bodyYawDelta(0.0f), _mode(AVATAR_MODE_STANDING), @@ -80,16 +79,15 @@ Avatar::Avatar() : moveToThread(Application::getInstance()->thread()); // give the pointer to our head to inherited _headData variable from AvatarData - _headData = &_head; + _headData = static_cast(new Head(this)); _handData = static_cast(new Hand(this)); } Avatar::~Avatar() { - _headData = NULL; } void Avatar::init() { - _head.init(); + getHead()->init(); getHand()->init(); _skeletonModel.init(); _initialized = true; @@ -115,14 +113,15 @@ void Avatar::simulate(float deltaTime) { getHand()->simulate(deltaTime, false); _skeletonModel.simulate(deltaTime); - _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); + Head* head = getHead(); + head->setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); glm::vec3 headPosition; if (!_skeletonModel.getHeadPosition(headPosition)) { headPosition = _position; } - _head.setPosition(headPosition); - _head.setScale(_scale); - _head.simulate(deltaTime, false); + head->setPosition(headPosition); + head->setScale(_scale); + getHead()->simulate(deltaTime, false); // use speed and angular velocity to determine walking vs. standing if (_speed + fabs(_bodyYawDelta) > 0.2) { @@ -162,7 +161,7 @@ void Avatar::render(bool forceRenderHead) { _skeletonModel.renderCollisionProxies(0.7f); } if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionProxies)) { - _head.getFaceModel().renderCollisionProxies(0.7f); + getHead()->getFaceModel().renderCollisionProxies(0.7f); } if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { renderBody(forceRenderHead); @@ -171,7 +170,7 @@ void Avatar::render(bool forceRenderHead) { // render sphere when far away const float MAX_ANGLE = 10.f; float height = getHeight(); - glm::vec3 delta = height * (_head.getCameraOrientation() * IDENTITY_UP) / 2.f; + glm::vec3 delta = height * (getHead()->getCameraOrientation() * IDENTITY_UP) / 2.f; float angle = abs(angleBetween(toTarget + delta, toTarget - delta)); if (angle < MAX_ANGLE) { @@ -179,7 +178,7 @@ void Avatar::render(bool forceRenderHead) { glPushMatrix(); glTranslatef(_position.x, _position.y, _position.z); glScalef(height / 2.f, height / 2.f, height / 2.f); - glutSolidSphere(1.2f + _head.getAverageLoudness() * .0005f, 20, 20); + glutSolidSphere(1.2f + getHead()->getAverageLoudness() * .0005f, 20, 20); glPopMatrix(); } } @@ -193,7 +192,7 @@ void Avatar::render(bool forceRenderHead) { } glPushMatrix(); - glm::vec3 chatPosition = getHead().getEyePosition() + getBodyUpDirection() * CHAT_MESSAGE_HEIGHT * _scale; + glm::vec3 chatPosition = getHead()->getEyePosition() + getBodyUpDirection() * CHAT_MESSAGE_HEIGHT * _scale; glTranslatef(chatPosition.x, chatPosition.y, chatPosition.z); glm::quat chatRotation = Application::getInstance()->getCamera()->getRotation(); glm::vec3 chatAxis = glm::axis(chatRotation); @@ -250,7 +249,7 @@ void Avatar::renderBody(bool forceRenderHead) { //printf("Render other at %.3f, %.2f, %.2f\n", pos.x, pos.y, pos.z); _skeletonModel.render(1.0f); if (forceRenderHead) { - _head.render(1.0f); + getHead()->render(1.0f); } getHand()->render(false); } @@ -261,7 +260,7 @@ bool Avatar::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc if (_skeletonModel.findRayIntersection(origin, direction, modelDistance)) { minDistance = qMin(minDistance, modelDistance); } - if (_head.getFaceModel().findRayIntersection(origin, direction, modelDistance)) { + if (getHead()->getFaceModel().findRayIntersection(origin, direction, modelDistance)) { minDistance = qMin(minDistance, modelDistance); } if (minDistance < FLT_MAX) { @@ -276,7 +275,7 @@ bool Avatar::findSphereCollisions(const glm::vec3& penetratorCenter, float penet // Temporarily disabling collisions against the skeleton because the collision proxies up // near the neck are bad and prevent the hand from hitting the face. //return _skeletonModel.findSphereCollisions(penetratorCenter, penetratorRadius, collisions, 1.0f, skeletonSkipIndex); - return _head.getFaceModel().findSphereCollisions(penetratorCenter, penetratorRadius, collisions); + return getHead()->getFaceModel().findSphereCollisions(penetratorCenter, penetratorRadius, collisions); } bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float particleRadius, CollisionList& collisions) { @@ -355,7 +354,7 @@ bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float parti void Avatar::setFaceModelURL(const QUrl &faceModelURL) { AvatarData::setFaceModelURL(faceModelURL); const QUrl DEFAULT_FACE_MODEL_URL = QUrl::fromLocalFile("resources/meshes/defaultAvatar_head.fst"); - _head.getFaceModel().setURL(_faceModelURL, DEFAULT_FACE_MODEL_URL); + getHead()->getFaceModel().setURL(_faceModelURL, DEFAULT_FACE_MODEL_URL); } void Avatar::setSkeletonModelURL(const QUrl &skeletonModelURL) { @@ -466,7 +465,7 @@ bool Avatar::collisionWouldMoveAvatar(CollisionInfo& collision) const { return false; //return _skeletonModel.collisionHitsMoveableJoint(collision); } - if (model == &(_head.getFaceModel())) { + if (model == &(getHead()->getFaceModel())) { // ATM we always handle MODEL_COLLISIONS against the face. return true; } @@ -479,8 +478,8 @@ void Avatar::applyCollision(CollisionInfo& collision) { } // TODO: make skeleton also respond to collisions Model* model = static_cast(collision._data); - if (model == &(_head.getFaceModel())) { - _head.applyCollision(collision); + if (model == &(getHead()->getFaceModel())) { + getHead()->applyCollision(collision); } } @@ -489,6 +488,6 @@ float Avatar::getPelvisFloatingHeight() const { } float Avatar::getPelvisToHeadLength() const { - return glm::distance(_position, _head.getPosition()); + return glm::distance(_position, getHead()->getPosition()); } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 1df4ae1d74..9d854e4cf8 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -74,7 +74,7 @@ public: void render(bool forceRenderHead); //setters - void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors); } + void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); } void setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction); //getters @@ -83,7 +83,8 @@ public: glm::vec3 getChestPosition() const; float getScale() const { return _scale; } const glm::vec3& getVelocity() const { return _velocity; } - Head& getHead() { return _head; } + const Head* getHead() const { return static_cast(_headData); } + Head* getHead() { return static_cast(_headData); } Hand* getHand() { return static_cast(_handData); } glm::quat getWorldAlignedOrientation() const; @@ -129,8 +130,6 @@ public slots: void updateCollisionFlags(); protected: - Head _head; - //Hand _hand; SkeletonModel _skeletonModel; float _bodyYawDelta; AvatarMode _mode; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0e8438610b..e7f7dd236f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -72,7 +72,7 @@ void MyAvatar::reset() { // TODO? resurrect headMouse stuff? //_headMouseX = _glWidget->width() / 2; //_headMouseY = _glWidget->height() / 2; - _head.reset(); + getHead()->reset(); getHand()->reset(); setVelocity(glm::vec3(0,0,0)); @@ -130,19 +130,20 @@ void MyAvatar::update(float deltaTime) { //_headMouseY = glm::clamp(_headMouseY, 0, _glWidget->height()); } + Head* head = getHead(); if (OculusManager::isConnected()) { float yaw, pitch, roll; OculusManager::getEulerAngles(yaw, pitch, roll); - _head.setYaw(yaw); - _head.setPitch(pitch); - _head.setRoll(roll); + head->setYaw(yaw); + head->setPitch(pitch); + head->setRoll(roll); } // Get audio loudness data from audio input device Audio* audio = Application::getInstance()->getAudio(); - _head.setAudioLoudness(audio->getLastInputLoudness()); - _head.setAudioAverageLoudness(audio->getAudioAverageInputLoudness()); + head->setAudioLoudness(audio->getLastInputLoudness()); + head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness()); if (Menu::getInstance()->isOptionChecked(MenuOption::Gravity)) { setGravity(Application::getInstance()->getEnvironment()->getGravity(getPosition())); @@ -266,7 +267,7 @@ void MyAvatar::simulate(float deltaTime) { if (!Application::getInstance()->getFaceshift()->isActive() && OculusManager::isConnected() && fabsf(forwardAcceleration) > OCULUS_ACCELERATION_PULL_THRESHOLD && - fabs(_head.getYaw()) > OCULUS_YAW_OFFSET_THRESHOLD) { + fabs(getHead()->getYaw()) > OCULUS_YAW_OFFSET_THRESHOLD) { // if we're wearing the oculus // and this acceleration is above the pull threshold @@ -276,7 +277,7 @@ void MyAvatar::simulate(float deltaTime) { _bodyYaw = getAbsoluteHeadYaw(); // set the head yaw to zero for this draw - _head.setYaw(0); + getHead()->setYaw(0); // correct the oculus yaw offset OculusManager::updateYawOffset(); @@ -316,15 +317,18 @@ void MyAvatar::simulate(float deltaTime) { // update avatar skeleton and simulate hand and head getHand()->collideAgainstOurself(); getHand()->simulate(deltaTime, true); + _skeletonModel.simulate(deltaTime); - _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); + + Head* head = getHead(); + head->setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); glm::vec3 headPosition; if (!_skeletonModel.getHeadPosition(headPosition)) { headPosition = _position; } - _head.setPosition(headPosition); - _head.setScale(_scale); - _head.simulate(deltaTime, true); + head->setPosition(headPosition); + head->setScale(_scale); + head->simulate(deltaTime, true); // Zero thrust out now that we've added it to velocity in this frame _thrust = glm::vec3(0, 0, 0); @@ -338,6 +342,8 @@ void MyAvatar::updateFromGyros(float deltaTime) { Faceshift* faceshift = Application::getInstance()->getFaceshift(); glm::vec3 estimatedPosition, estimatedRotation; + Head* head = getHead(); + if (faceshift->isActive()) { estimatedPosition = faceshift->getHeadTranslation(); estimatedRotation = safeEulerAngles(faceshift->getHeadRotation()); @@ -359,10 +365,10 @@ void MyAvatar::updateFromGyros(float deltaTime) { // restore rotation, lean to neutral positions const float RESTORE_PERIOD = 1.f; // seconds float restorePercentage = glm::clamp(deltaTime/RESTORE_PERIOD, 0.f, 1.f); - _head.setYaw(glm::mix(_head.getYaw(), 0.0f, restorePercentage)); - _head.setRoll(glm::mix(_head.getRoll(), 0.0f, restorePercentage)); - _head.setLeanSideways(glm::mix(_head.getLeanSideways(), 0.0f, restorePercentage)); - _head.setLeanForward(glm::mix(_head.getLeanForward(), 0.0f, restorePercentage)); + head->setYaw(glm::mix(head->getYaw(), 0.0f, restorePercentage)); + head->setRoll(glm::mix(head->getRoll(), 0.0f, restorePercentage)); + head->setLeanSideways(glm::mix(head->getLeanSideways(), 0.0f, restorePercentage)); + head->setLeanForward(glm::mix(head->getLeanForward(), 0.0f, restorePercentage)); return; } @@ -371,17 +377,17 @@ void MyAvatar::updateFromGyros(float deltaTime) { const float AVATAR_HEAD_PITCH_MAGNIFY = 1.0f; const float AVATAR_HEAD_YAW_MAGNIFY = 1.0f; const float AVATAR_HEAD_ROLL_MAGNIFY = 1.0f; - _head.tweakPitch(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY); - _head.tweakYaw(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY); - _head.tweakRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY); + head->tweakPitch(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY); + head->tweakYaw(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY); + head->tweakRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY); // Update torso lean distance based on accelerometer data const float TORSO_LENGTH = 0.5f; glm::vec3 relativePosition = estimatedPosition - glm::vec3(0.0f, -TORSO_LENGTH, 0.0f); const float MAX_LEAN = 45.0f; - _head.setLeanSideways(glm::clamp(glm::degrees(atanf(relativePosition.x * _leanScale / TORSO_LENGTH)), + head->setLeanSideways(glm::clamp(glm::degrees(atanf(relativePosition.x * _leanScale / TORSO_LENGTH)), -MAX_LEAN, MAX_LEAN)); - _head.setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)), + head->setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)), -MAX_LEAN, MAX_LEAN)); // if Faceshift drive is enabled, set the avatar drive based on the head position @@ -390,11 +396,11 @@ void MyAvatar::updateFromGyros(float deltaTime) { } // Move with Lean by applying thrust proportional to leaning - glm::quat orientation = _head.getCameraOrientation(); + glm::quat orientation = head->getCameraOrientation(); glm::vec3 front = orientation * IDENTITY_FRONT; glm::vec3 right = orientation * IDENTITY_RIGHT; - float leanForward = _head.getLeanForward(); - float leanSideways = _head.getLeanSideways(); + float leanForward = head->getLeanForward(); + float leanSideways = head->getLeanSideways(); // Degrees of 'dead zone' when leaning, and amount of acceleration to apply to lean angle const float LEAN_FWD_DEAD_ZONE = 15.f; @@ -425,7 +431,7 @@ static TextRenderer* textRenderer() { void MyAvatar::renderDebugBodyPoints() { glm::vec3 torsoPosition(getPosition()); - glm::vec3 headPosition(getHead().getEyePosition()); + glm::vec3 headPosition(getHead()->getEyePosition()); float torsoToHead = glm::length(headPosition - torsoPosition); glm::vec3 position; printf("head-above-torso %.2f, scale = %0.2f\n", torsoToHead, getScale()); @@ -471,7 +477,7 @@ void MyAvatar::render(bool forceRenderHead) { } glPushMatrix(); - glm::vec3 chatPosition = getHead().getEyePosition() + getBodyUpDirection() * CHAT_MESSAGE_HEIGHT * _scale; + glm::vec3 chatPosition = getHead()->getEyePosition() + getBodyUpDirection() * CHAT_MESSAGE_HEIGHT * _scale; glTranslatef(chatPosition.x, chatPosition.y, chatPosition.z); glm::quat chatRotation = Application::getInstance()->getCamera()->getRotation(); glm::vec3 chatAxis = glm::axis(chatRotation); @@ -581,13 +587,13 @@ void MyAvatar::saveData(QSettings* settings) { settings->setValue("bodyPitch", _bodyPitch); settings->setValue("bodyRoll", _bodyRoll); - settings->setValue("headPitch", _head.getPitch()); + settings->setValue("headPitch", getHead()->getPitch()); settings->setValue("position_x", _position.x); settings->setValue("position_y", _position.y); settings->setValue("position_z", _position.z); - settings->setValue("pupilDilation", _head.getPupilDilation()); + settings->setValue("pupilDilation", getHead()->getPupilDilation()); settings->setValue("leanScale", _leanScale); settings->setValue("scale", _targetScale); @@ -606,13 +612,13 @@ void MyAvatar::loadData(QSettings* settings) { _bodyPitch = loadSetting(settings, "bodyPitch", 0.0f); _bodyRoll = loadSetting(settings, "bodyRoll", 0.0f); - _head.setPitch(loadSetting(settings, "headPitch", 0.0f)); + getHead()->setPitch(loadSetting(settings, "headPitch", 0.0f)); _position.x = loadSetting(settings, "position_x", 0.0f); _position.y = loadSetting(settings, "position_y", 0.0f); _position.z = loadSetting(settings, "position_z", 0.0f); - _head.setPupilDilation(loadSetting(settings, "pupilDilation", 0.0f)); + getHead()->setPupilDilation(loadSetting(settings, "pupilDilation", 0.0f)); _leanScale = loadSetting(settings, "leanScale", 0.05f); _targetScale = loadSetting(settings, "scale", 1.0f); @@ -647,9 +653,9 @@ void MyAvatar::orbit(const glm::vec3& position, int deltaX, int deltaY) { setOrientation(orientation); // then vertically - float oldPitch = _head.getPitch(); - _head.setPitch(oldPitch + deltaY * -ANGULAR_SCALE); - rotation = glm::angleAxis(_head.getPitch() - oldPitch, orientation * IDENTITY_RIGHT); + float oldPitch = getHead()->getPitch(); + getHead()->setPitch(oldPitch + deltaY * -ANGULAR_SCALE); + rotation = glm::angleAxis(getHead()->getPitch() - oldPitch, orientation * IDENTITY_RIGHT); setPosition(position + rotation * (getPosition() - position)); } @@ -669,8 +675,8 @@ void MyAvatar::updateLookAtTargetAvatar(glm::vec3 &eyePosition) { float distance; if (avatar->findRayIntersection(mouseOrigin, mouseDirection, distance)) { // rescale to compensate for head embiggening - eyePosition = (avatar->getHead().calculateAverageEyePosition() - avatar->getHead().getScalePivot()) * - (avatar->getScale() / avatar->getHead().getScale()) + avatar->getHead().getScalePivot(); + eyePosition = (avatar->getHead()->calculateAverageEyePosition() - avatar->getHead()->getScalePivot()) * + (avatar->getScale() / avatar->getHead()->getScale()) + avatar->getHead()->getScalePivot(); _lookAtTargetAvatar = avatarPointer; return; } @@ -684,7 +690,8 @@ void MyAvatar::clearLookAtTargetAvatar() { } float MyAvatar::getAbsoluteHeadYaw() const { - return glm::yaw(_head.getOrientation()); + const Head* head = static_cast(_headData); + return glm::yaw(head->getOrientation()); } glm::vec3 MyAvatar::getUprightHeadPosition() const { @@ -698,8 +705,8 @@ void MyAvatar::renderBody(bool forceRenderHead) { // Render head so long as the camera isn't inside it const float RENDER_HEAD_CUTOFF_DISTANCE = 0.10f; Camera* myCamera = Application::getInstance()->getCamera(); - if (forceRenderHead || (glm::length(myCamera->getPosition() - _head.calculateAverageEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE)) { - _head.render(1.0f); + if (forceRenderHead || (glm::length(myCamera->getPosition() - getHead()->calculateAverageEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE)) { + getHead()->render(1.0f); } getHand()->render(true); } @@ -708,7 +715,7 @@ void MyAvatar::updateThrust(float deltaTime) { // // Gather thrust information from keyboard and sensors to apply to avatar motion // - glm::quat orientation = getHead().getCameraOrientation(); + glm::quat orientation = getHead()->getCameraOrientation(); glm::vec3 front = orientation * IDENTITY_FRONT; glm::vec3 right = orientation * IDENTITY_RIGHT; glm::vec3 up = orientation * IDENTITY_UP; @@ -729,7 +736,7 @@ void MyAvatar::updateThrust(float deltaTime) { _thrust -= _driveKeys[DOWN] * _scale * THRUST_MAG_DOWN * _thrustMultiplier * deltaTime * up; _bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_MAG * deltaTime; _bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_MAG * deltaTime; - _head.setPitch(_head.getPitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_MAG * deltaTime); + getHead()->setPitch(getHead()->getPitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_MAG * deltaTime); // If thrust keys are being held down, slowly increase thrust to allow reaching great speeds if (_driveKeys[FWD] || _driveKeys[BACK] || _driveKeys[RIGHT] || _driveKeys[LEFT] || _driveKeys[UP] || _driveKeys[DOWN]) { @@ -1112,7 +1119,7 @@ void MyAvatar::updateChatCircle(float deltaTime) { void MyAvatar::setGravity(glm::vec3 gravity) { _gravity = gravity; - _head.setGravity(_gravity); + getHead()->setGravity(_gravity); // use the gravity to determine the new world up direction, if possible float gravityLength = glm::length(gravity); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 474cefdab5..0396b80e58 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -181,8 +181,8 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const glm::mat3 axes = glm::mat3_cast(_rotation); glm::mat3 inverse = glm::mat3(glm::inverse(parentState.transform * glm::translate(state.translation) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation))); - state.rotation = glm::angleAxis(-_owningAvatar->getHead().getLeanSideways(), glm::normalize(inverse * axes[2])) * - glm::angleAxis(-_owningAvatar->getHead().getLeanForward(), glm::normalize(inverse * axes[0])) * joint.rotation; + state.rotation = glm::angleAxis(-_owningAvatar->getHead()->getLeanSideways(), glm::normalize(inverse * axes[2])) * + glm::angleAxis(-_owningAvatar->getHead()->getLeanForward(), glm::normalize(inverse * axes[0])) * joint.rotation; } void SkeletonModel::stretchArm(int jointIndex, const glm::vec3& position) { diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index e16b0c570d..6ffaf23564 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -64,7 +64,7 @@ void Snapshot::saveSnapshot(QGLWidget* widget, Profile* profile, Avatar* avatar) QImage shot = widget->grabFrameBuffer(); glm::vec3 location = avatar->getPosition(); - glm::quat orientation = avatar->getHead().getOrientation(); + glm::quat orientation = avatar->getHead()->getOrientation(); // add metadata shot.setText(LOCATION_X, QString::number(location.x)); From 636e3b1910952a5ce0d1ff92c89554603cc24d7a Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Feb 2014 18:24:25 -0800 Subject: [PATCH 41/83] Working on blendshape integration. --- interface/src/devices/Visage.cpp | 56 +++++++++++++++++++++++++++++- interface/src/devices/Visage.h | 4 +++ interface/src/renderer/FBXReader.h | 3 ++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index c6fb5b9668..2ed36e9594 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -6,6 +6,8 @@ // Copyright (c) 2014 High Fidelity, Inc. All rights reserved. // +#include + #include #ifdef HAVE_VISAGE @@ -13,6 +15,7 @@ #endif #include "Visage.h" +#include "renderer/FBXReader.h" namespace VisageSDK { #ifdef WIN32 @@ -56,6 +59,43 @@ Visage::~Visage() { #endif } +static QHash createBlendshapeIndices() { + QHash blendshapeMap; + blendshapeMap.insert("Sneer", "au_nose_wrinkler"); + blendshapeMap.insert("JawFwd", "au_jaw_z_push"); + blendshapeMap.insert("JawLeft", "au_jaw_x_push"); + blendshapeMap.insert("JawOpen", "au_jaw_drop"); + blendshapeMap.insert("LipsLowerDown", "au_lower_lip_drop"); + blendshapeMap.insert("LipsUpperUp", "au_upper_lip_raiser"); + blendshapeMap.insert("LipsStretch_L", "au_lip_stretcher_left"); + blendshapeMap.insert("BrowsU_L", "au_left_outer_brow_raiser"); + blendshapeMap.insert("BrowsU_C", "au_left_inner_brow_raiser"); + blendshapeMap.insert("BrowsD_L", "au_left_brow_lowerer"); + blendshapeMap.insert("LipsStretch_R", "au_lip_stretcher_right"); + blendshapeMap.insert("BrowsU_R", "au_right_outer_brow_raiser"); + blendshapeMap.insert("BrowsU_C", "au_right_inner_brow_raiser"); + blendshapeMap.insert("BrowsD_R", "au_right_brow_lowerer"); + + QHash blendshapeIndices; + for (int i = 0;; i++) { + QByteArray blendshape = FACESHIFT_BLENDSHAPES[i]; + if (blendshape.isEmpty()) { + break; + } + QByteArray mapping = blendshapeMap.value(blendshape); + if (!mapping.isEmpty()) { + blendshapeIndices.insert(mapping, i + 1); + } + } + + return blendshapeIndices; +} + +static const QHash& getBlendshapeIndices() { + static QHash blendshapeIndices = createBlendshapeIndices(); + return blendshapeIndices; +} + const float TRANSLATION_SCALE = 20.0f; void Visage::update() { @@ -70,11 +110,25 @@ void Visage::update() { _estimatedEyePitch = glm::degrees(-_data->gazeDirection[1]); _estimatedEyeYaw = glm::degrees(-_data->gazeDirection[0]); + if (_blendshapeIndices.isEmpty()) { + _blendshapeIndices.resize(_data->actionUnitCount); + int maxIndex = -1; + for (int i = 0; i < _data->actionUnitCount; i++) { + int index = getBlendshapeIndices().value(_data->actionUnitsNames[i]) - 1; + maxIndex = qMax(maxIndex, _blendshapeIndices[i] = index); + } + _blendshapeCoefficients.resize(maxIndex + 1); + } + + qFill(_blendshapeCoefficients.begin(), _blendshapeCoefficients.end(), 0.0f); for (int i = 0; i < _data->actionUnitCount; i++) { if (!_data->actionUnitsUsed[i]) { continue; } - qDebug() << _data->actionUnitsNames[i] << _data->actionUnits[i]; + int index = _blendshapeIndices.at(i); + if (index != -1) { + _blendshapeCoefficients[index] = _data->actionUnits[i]; + } } #endif } diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 383c81be54..0559a859de 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -11,6 +11,8 @@ #include +#include + #include #include @@ -54,6 +56,8 @@ private: float _estimatedEyeYaw; std::vector _blendshapeCoefficients; + + QVector _blendshapeIndices; }; #endif /* defined(__interface__Visage__) */ diff --git a/interface/src/renderer/FBXReader.h b/interface/src/renderer/FBXReader.h index 8efb23c98c..b89d0954b4 100644 --- a/interface/src/renderer/FBXReader.h +++ b/interface/src/renderer/FBXReader.h @@ -21,6 +21,9 @@ class FBXNode; typedef QList FBXNodeList; +/// The names of the blendshapes expected by Faceshift, terminated with an empty string. +extern const char* FACESHIFT_BLENDSHAPES[]; + /// A node within an FBX document. class FBXNode { public: From 8076f571fd5ea93aedfd91047e2e776458c5e3bc Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Feb 2014 18:39:38 -0800 Subject: [PATCH 42/83] Working on blinking, etc. --- interface/src/devices/Visage.cpp | 28 +++++++++++++++++++++++++++- interface/src/devices/Visage.h | 2 ++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 2ed36e9594..8a6b9d5947 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -33,7 +33,10 @@ Visage::Visage() : _active(false), _headOrigin(DEFAULT_HEAD_ORIGIN), _estimatedEyePitch(0.0f), - _estimatedEyeYaw(0.0f) { + _estimatedEyeYaw(0.0f), + _leftInnerBrowIndex(0), + _rightInnerBrowIndex(0) { + #ifdef HAVE_VISAGE switchToResourcesParentIfRequired(); QByteArray licensePath = "resources/visage/license.vlc"; @@ -59,6 +62,10 @@ Visage::~Visage() { #endif } +static int leftEyeBlinkIndex = 0; +static int rightEyeBlinkIndex = 1; +static int centerBrowIndex = 16; + static QHash createBlendshapeIndices() { QHash blendshapeMap; blendshapeMap.insert("Sneer", "au_nose_wrinkler"); @@ -82,6 +89,15 @@ static QHash createBlendshapeIndices() { if (blendshape.isEmpty()) { break; } + if (blendshape == "EyeBlink_L") { + leftEyeBlinkIndex = i; + + } else if (blendshape == "EyeBlink_R") { + rightEyeBlinkIndex = i; + + } else if (blendshape == "BrowsU_C") { + centerBrowIndex = i; + } QByteArray mapping = blendshapeMap.value(blendshape); if (!mapping.isEmpty()) { blendshapeIndices.insert(mapping, i + 1); @@ -114,6 +130,12 @@ void Visage::update() { _blendshapeIndices.resize(_data->actionUnitCount); int maxIndex = -1; for (int i = 0; i < _data->actionUnitCount; i++) { + QByteArray name = _data->actionUnitsNames[i]; + if (name == "au_left_inner_brow_raiser") { + _leftInnerBrowIndex = i; + } else if (name == "au_right_inner_brow_raiser") { + _rightInnerBrowIndex = i; + } int index = getBlendshapeIndices().value(_data->actionUnitsNames[i]) - 1; maxIndex = qMax(maxIndex, _blendshapeIndices[i] = index); } @@ -130,6 +152,10 @@ void Visage::update() { _blendshapeCoefficients[index] = _data->actionUnits[i]; } } + _blendshapeCoefficients[leftEyeBlinkIndex] = 1.0f - _data->eyeClosure[0]; + _blendshapeCoefficients[rightEyeBlinkIndex] = 1.0f - _data->eyeClosure[1]; + _blendshapeCoefficients[centerBrowIndex] = (_data->actionUnits[_leftInnerBrowIndex] + + _data->actionUnits[_rightInnerBrowIndex]) * 0.5f; #endif } diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 0559a859de..124ef29e3b 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -58,6 +58,8 @@ private: std::vector _blendshapeCoefficients; QVector _blendshapeIndices; + int _leftInnerBrowIndex; + int _rightInnerBrowIndex; }; #endif /* defined(__interface__Visage__) */ From c4e643e3a4f6155c18eef4ee9e19c6017bfc129f Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Feb 2014 18:43:45 -0800 Subject: [PATCH 43/83] Eyes were reversed. --- interface/src/devices/Visage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 8a6b9d5947..b1a041c0dc 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -152,8 +152,8 @@ void Visage::update() { _blendshapeCoefficients[index] = _data->actionUnits[i]; } } - _blendshapeCoefficients[leftEyeBlinkIndex] = 1.0f - _data->eyeClosure[0]; - _blendshapeCoefficients[rightEyeBlinkIndex] = 1.0f - _data->eyeClosure[1]; + _blendshapeCoefficients[leftEyeBlinkIndex] = 1.0f - _data->eyeClosure[1]; + _blendshapeCoefficients[rightEyeBlinkIndex] = 1.0f - _data->eyeClosure[0]; _blendshapeCoefficients[centerBrowIndex] = (_data->actionUnits[_leftInnerBrowIndex] + _data->actionUnits[_rightInnerBrowIndex]) * 0.5f; #endif From a89983a1c0f28f5b8d8d8cb6bb273e8273e7e459 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Feb 2014 18:49:34 -0800 Subject: [PATCH 44/83] Removed tab, variable fix. --- interface/src/devices/Visage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index b1a041c0dc..26e7993ecb 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -21,7 +21,7 @@ namespace VisageSDK { #ifdef WIN32 void __declspec(dllimport) initializeLicenseManager(char* licenseKeyFileName); #else - void initializeLicenseManager(char* licenseKeyFileName); + void initializeLicenseManager(char* licenseKeyFileName); #endif } @@ -136,7 +136,7 @@ void Visage::update() { } else if (name == "au_right_inner_brow_raiser") { _rightInnerBrowIndex = i; } - int index = getBlendshapeIndices().value(_data->actionUnitsNames[i]) - 1; + int index = getBlendshapeIndices().value(name) - 1; maxIndex = qMax(maxIndex, _blendshapeIndices[i] = index); } _blendshapeCoefficients.resize(maxIndex + 1); From bf814410ac8bf5fd78313dd537f5d48f00d18d07 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 19 Feb 2014 00:10:16 -0800 Subject: [PATCH 45/83] first cut at exposing clipboard support to JavaScript --- interface/src/Application.cpp | 48 ++++++++++++--- interface/src/Application.h | 13 +++- interface/src/ClipboardScriptingInterface.cpp | 59 +++++++++++++++++++ interface/src/ClipboardScriptingInterface.h | 31 ++++++++++ .../voxels/src/VoxelEditPacketSender.cpp | 4 +- libraries/voxels/src/VoxelEditPacketSender.h | 2 +- 6 files changed, 142 insertions(+), 15 deletions(-) create mode 100644 interface/src/ClipboardScriptingInterface.cpp create mode 100644 interface/src/ClipboardScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b316548ad4..433158f413 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -62,6 +62,7 @@ #include #include "Application.h" +#include "ClipboardScriptingInterface.h" #include "DataServerClient.h" #include "InterfaceVersion.h" #include "Menu.h" @@ -1686,6 +1687,10 @@ bool Application::sendVoxelsOperation(OctreeElement* element, void* extraData) { } void Application::exportVoxels() { + exportVoxels(_mouseVoxel); +} + +void Application::exportVoxels(const VoxelDetail& sourceVoxel) { QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); QString suggestedName = desktopLocation.append("/voxels.svo"); @@ -1693,7 +1698,7 @@ void Application::exportVoxels() { tr("Sparse Voxel Octree Files (*.svo)")); QByteArray fileNameAscii = fileNameString.toLocal8Bit(); const char* fileName = fileNameAscii.data(); - VoxelTreeElement* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + VoxelTreeElement* selectedNode = _voxels.getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); if (selectedNode) { VoxelTree exportTree; _voxels.copySubTreeIntoNewTree(selectedNode, &exportTree, true); @@ -1721,11 +1726,19 @@ void Application::importVoxels() { } void Application::cutVoxels() { - copyVoxels(); - deleteVoxelUnderCursor(); + cutVoxels(_mouseVoxel); +} + +void Application::cutVoxels(const VoxelDetail& sourceVoxel) { + copyVoxels(sourceVoxel); + deleteVoxelAt(sourceVoxel); } void Application::copyVoxels() { + copyVoxels(_mouseVoxel); +} + +void Application::copyVoxels(const VoxelDetail& sourceVoxel) { // switch to and clear the clipboard first... _sharedVoxelSystem.killLocalVoxels(); if (_sharedVoxelSystem.getTree() != &_clipboard) { @@ -1734,7 +1747,7 @@ void Application::copyVoxels() { } // then copy onto it if there is something to copy - VoxelTreeElement* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + VoxelTreeElement* selectedNode = _voxels.getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); if (selectedNode) { _voxels.copySubTreeIntoNewTree(selectedNode, &_sharedVoxelSystem, true); } @@ -1756,8 +1769,12 @@ void Application::pasteVoxelsToOctalCode(const unsigned char* octalCodeDestinati } void Application::pasteVoxels() { + pasteVoxels(_mouseVoxel); +} + +void Application::pasteVoxels(const VoxelDetail& sourceVoxel) { unsigned char* calculatedOctCode = NULL; - VoxelTreeElement* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + VoxelTreeElement* selectedNode = _voxels.getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); // we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the // voxel size/position details. If we don't have an actual selectedNode then use the mouseVoxel to create a @@ -1766,7 +1783,7 @@ void Application::pasteVoxels() { if (selectedNode) { octalCodeDestination = selectedNode->getOctalCode(); } else { - octalCodeDestination = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + octalCodeDestination = calculatedOctCode = pointToVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); } pasteVoxelsToOctalCode(octalCodeDestination); @@ -3789,18 +3806,27 @@ bool Application::maybeEditVoxelUnderCursor() { } void Application::deleteVoxelUnderCursor() { - if (_mouseVoxel.s != 0) { + deleteVoxelAt(_mouseVoxel); +} + +void Application::deleteVoxels(const VoxelDetail& voxel) { + deleteVoxelAt(voxel); +} + +void Application::deleteVoxelAt(const VoxelDetail& voxel) { + if (voxel.s != 0) { // sending delete to the server is sufficient, server will send new version so we see updates soon enough - _voxelEditSender.sendVoxelEditMessage(PacketTypeVoxelErase, _mouseVoxel); + _voxelEditSender.sendVoxelEditMessage(PacketTypeVoxelErase, voxel); // delete it locally to see the effect immediately (and in case no voxel server is present) - _voxels.deleteVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + _voxels.deleteVoxelAt(voxel.x, voxel.y, voxel.z, voxel.s); } // remember the position for drag detection _justEditedVoxel = true; } + void Application::eyedropperVoxelUnderCursor() { VoxelTreeElement* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); if (selectedNode && selectedNode->isColored()) { @@ -4138,6 +4164,10 @@ void Application::loadScript(const QString& fileNameString) { scriptEngine->registerGlobalObject("Camera", cameraScriptable); connect(scriptEngine, SIGNAL(finished(const QString&)), cameraScriptable, SLOT(deleteLater())); + ClipboardScriptingInterface* clipboardScriptable = new ClipboardScriptingInterface(); + scriptEngine->registerGlobalObject("Clipboard", clipboardScriptable); + connect(scriptEngine, SIGNAL(finished(const QString&)), clipboardScriptable, SLOT(deleteLater())); + scriptEngine->registerGlobalObject("Overlays", &_overlays); QThread* workerThread = new QThread(this); diff --git a/interface/src/Application.h b/interface/src/Application.h index 0b6907e0f5..7de1b74609 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -222,13 +222,19 @@ public slots: void nodeKilled(SharedNodePointer node); void packetSent(quint64 length); - void exportVoxels(); - void importVoxels(); void cutVoxels(); void copyVoxels(); void pasteVoxels(); - void nudgeVoxels(); void deleteVoxels(); + void exportVoxels(); + void importVoxels(); + void nudgeVoxels(); + + void cutVoxels(const VoxelDetail& sourceVoxel); + void copyVoxels(const VoxelDetail& sourceVoxel); + void pasteVoxels(const VoxelDetail& sourceVoxel); + void deleteVoxels(const VoxelDetail& sourceVoxel); + void exportVoxels(const VoxelDetail& sourceVoxel); void setRenderVoxels(bool renderVoxels); void doKillLocalVoxels(); @@ -322,6 +328,7 @@ private: bool maybeEditVoxelUnderCursor(); void deleteVoxelUnderCursor(); + void deleteVoxelAt(const VoxelDetail& voxel); void eyedropperVoxelUnderCursor(); void setMenuShortcutsEnabled(bool enabled); diff --git a/interface/src/ClipboardScriptingInterface.cpp b/interface/src/ClipboardScriptingInterface.cpp new file mode 100644 index 0000000000..c2a1a945a1 --- /dev/null +++ b/interface/src/ClipboardScriptingInterface.cpp @@ -0,0 +1,59 @@ +// +// ClipboardScriptingInterface.cpp +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#include "Application.h" +#include "ClipboardScriptingInterface.h" + +ClipboardScriptingInterface::ClipboardScriptingInterface() { +} + +void ClipboardScriptingInterface::cutVoxels(float x, float y, float z, float s) { + VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, + y / (float)TREE_SCALE, + z / (float)TREE_SCALE, + s / (float)TREE_SCALE }; + Application::getInstance()->cutVoxels(sourceVoxel); +} + +void ClipboardScriptingInterface::copyVoxels(float x, float y, float z, float s) { + VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, + y / (float)TREE_SCALE, + z / (float)TREE_SCALE, + s / (float)TREE_SCALE }; + Application::getInstance()->copyVoxels(sourceVoxel); +} + +void ClipboardScriptingInterface::pasteVoxels(float x, float y, float z, float s) { + VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, + y / (float)TREE_SCALE, + z / (float)TREE_SCALE, + s / (float)TREE_SCALE }; + + Application::getInstance()->pasteVoxels(sourceVoxel); +} + +void ClipboardScriptingInterface::deleteVoxels(float x, float y, float z, float s) { + VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, + y / (float)TREE_SCALE, + z / (float)TREE_SCALE, + s / (float)TREE_SCALE }; + Application::getInstance()->deleteVoxels(sourceVoxel); +} + +void ClipboardScriptingInterface::exportVoxels(float x, float y, float z, float s) { + VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, + y / (float)TREE_SCALE, + z / (float)TREE_SCALE, + s / (float)TREE_SCALE }; + + Application::getInstance()->exportVoxels(sourceVoxel); +} + +void ClipboardScriptingInterface::importVoxels() { + Application::getInstance()->importVoxels(); +} + diff --git a/interface/src/ClipboardScriptingInterface.h b/interface/src/ClipboardScriptingInterface.h new file mode 100644 index 0000000000..0b2908f173 --- /dev/null +++ b/interface/src/ClipboardScriptingInterface.h @@ -0,0 +1,31 @@ +// +// ClipboardScriptingInterface.h +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// +// Scriptable interface for the Application clipboard +// + +#ifndef __interface__Clipboard__ +#define __interface__Clipboard__ + +#include +#include + +class ClipboardScriptingInterface : public QObject { + Q_OBJECT +public: + ClipboardScriptingInterface(); + +public slots: + void cutVoxels(float x, float y, float z, float s); + void copyVoxels(float x, float y, float z, float s); + void pasteVoxels(float x, float y, float z, float s); + void deleteVoxels(float x, float y, float z, float s); + + void exportVoxels(float x, float y, float z, float s); + void importVoxels(); +}; + +#endif // __interface__Clipboard__ diff --git a/libraries/voxels/src/VoxelEditPacketSender.cpp b/libraries/voxels/src/VoxelEditPacketSender.cpp index a6d3668207..90884f19f4 100644 --- a/libraries/voxels/src/VoxelEditPacketSender.cpp +++ b/libraries/voxels/src/VoxelEditPacketSender.cpp @@ -22,7 +22,7 @@ /// PacketTypeVoxelSet, PacketTypeVoxelSetDestructive, or PacketTypeVoxelErase. The buffer is returned to caller becomes /// responsibility of caller and MUST be deleted by caller. bool createVoxelEditMessage(PacketType command, short int sequence, - int voxelCount, VoxelDetail* voxelDetails, unsigned char*& bufferOut, int& sizeOut) { + int voxelCount, const VoxelDetail* voxelDetails, unsigned char*& bufferOut, int& sizeOut) { bool success = true; // assume the best int messageSize = MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE; // just a guess for now @@ -102,7 +102,7 @@ bool encodeVoxelEditMessageDetails(PacketType, int voxelCount, VoxelDetail* voxe return success; } -void VoxelEditPacketSender::sendVoxelEditMessage(PacketType type, VoxelDetail& detail) { +void VoxelEditPacketSender::sendVoxelEditMessage(PacketType type, const VoxelDetail& detail) { // allows app to disable sending if for example voxels have been disabled if (!_shouldSend) { return; // bail early diff --git a/libraries/voxels/src/VoxelEditPacketSender.h b/libraries/voxels/src/VoxelEditPacketSender.h index 90085635b0..4a1aa87a1c 100644 --- a/libraries/voxels/src/VoxelEditPacketSender.h +++ b/libraries/voxels/src/VoxelEditPacketSender.h @@ -19,7 +19,7 @@ class VoxelEditPacketSender : public OctreeEditPacketSender { Q_OBJECT public: /// Send voxel edit message immediately - void sendVoxelEditMessage(PacketType type, VoxelDetail& detail); + void sendVoxelEditMessage(PacketType type, const VoxelDetail& detail); /// Queues a single voxel edit message. Will potentially send a pending multi-command packet. Determines which voxel-server /// node or nodes the packet should be sent to. Can be called even before voxel servers are known, in which case up to From a6b202ccbeeb91146ef0f9bc6381167b9d8decf0 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Wed, 19 Feb 2014 10:01:15 +0100 Subject: [PATCH 46/83] My Avatar's display name is shown --- interface/src/avatar/Avatar.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 2b7cc94c86..91d91e7219 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -632,10 +632,20 @@ float Avatar::getPelvisToHeadLength() const { } void Avatar::setShowDisplayName(bool showDisplayName) { + // For myAvatar, the alpha update is not done (called in simulate for other avatars) + if (Application::getInstance()->getAvatar() == this) { + if (showDisplayName) { + _displayNameAlpha = DISPLAYNAME_ALPHA; + } else { + _displayNameAlpha = 0.0f; + } + } + if (showDisplayName) { _displayNameTargetAlpha = DISPLAYNAME_ALPHA; } else { _displayNameTargetAlpha = 0.0f; } + } From 85e05539ad5c0c0d6b601c64263e63ae40124e91 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 19 Feb 2014 08:59:17 -0800 Subject: [PATCH 47/83] Adding comment about bug as a reminder to fix. --- interface/src/renderer/FBXReader.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/src/renderer/FBXReader.cpp b/interface/src/renderer/FBXReader.cpp index 35512d88da..8b881940ca 100644 --- a/interface/src/renderer/FBXReader.cpp +++ b/interface/src/renderer/FBXReader.cpp @@ -1405,6 +1405,11 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) cluster.jointIndex = 0; } extracted.mesh.clusters.append(cluster); + // BUG: joints that fall into this context do not get their bindTransform and + // inverseBindRotation data members properly set. This causes bad boneRadius + // and boneLength calculations for collision proxies. Affected joints are usually: + // hair, teeth, tongue. I tried to figure out how to fix this but was going + // crosseyed trying to understand FBX so I gave up for the time being -- Andrew. } // whether we're skinned depends on how many clusters are attached From 07a12c1bd422f4565f74265bafe6f22f0c7e82b3 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 19 Feb 2014 09:28:34 -0800 Subject: [PATCH 48/83] Removing unused declaration of static method --- libraries/avatars/src/HandData.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 4046a0a875..5f7a49e0a2 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -71,9 +71,7 @@ public: void setFingerTrailLength(unsigned int length); void updateFingerTrails(); - // use these static methods for safety static int encodeData(HandData* hand, unsigned char* destinationBuffer); - static int decodeData(HandData* hand, const QByteArray& dataByteArray); // Use these for sending and receiving hand data int encodeRemoteData(unsigned char* destinationBuffer); From a2e0fa674fe10f3190224636df4fe88abe868ed1 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 19 Feb 2014 10:14:58 -0800 Subject: [PATCH 49/83] Putting new private method next to others. --- interface/src/avatar/Hand.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 0ce1e836a2..9888c9f054 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -61,9 +61,6 @@ public: void collideAgainstAvatar(Avatar* avatar, bool isMyHand); void collideAgainstOurself(); -private: - void playSlaps(PalmData& palm, Avatar* avatar); - private: // disallow copies of the Hand, copy of owning Avatar is disallowed too Hand(const Hand&); @@ -96,6 +93,8 @@ private: void calculateGeometry(); void handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPosition, VoxelTreeElement* voxel, float deltaTime); + + void playSlaps(PalmData& palm, Avatar* avatar); }; #endif From ad8a5265021c52875a8a7f5f86947332064471f6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 19 Feb 2014 11:33:43 -0800 Subject: [PATCH 50/83] fix right mouse click --- libraries/script-engine/src/EventTypes.cpp | 25 ++++++++++------------ 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/libraries/script-engine/src/EventTypes.cpp b/libraries/script-engine/src/EventTypes.cpp index 8fac2bcd2a..d0ba160add 100644 --- a/libraries/script-engine/src/EventTypes.cpp +++ b/libraries/script-engine/src/EventTypes.cpp @@ -262,10 +262,17 @@ MouseEvent::MouseEvent() : }; -MouseEvent::MouseEvent(const QMouseEvent& event) { - x = event.x(); - y = event.y(); - +MouseEvent::MouseEvent(const QMouseEvent& event) : + x(event.x()), + y(event.y()), + isLeftButton(event.buttons().testFlag(Qt::LeftButton)), + isRightButton(event.buttons().testFlag(Qt::RightButton)), + isMiddleButton(event.buttons().testFlag(Qt::MiddleButton)), + isShifted(event.modifiers().testFlag(Qt::ShiftModifier)), + isControl(event.modifiers().testFlag(Qt::ControlModifier)), + isMeta(event.modifiers().testFlag(Qt::MetaModifier)), + isAlt(event.modifiers().testFlag(Qt::AltModifier)) +{ // single button that caused the event switch (event.button()) { case Qt::LeftButton: @@ -284,16 +291,6 @@ MouseEvent::MouseEvent(const QMouseEvent& event) { button = "NONE"; break; } - // button pressed state - isLeftButton = isLeftButton || (event.buttons().testFlag(Qt::LeftButton)); - isRightButton = isRightButton || (event.buttons().testFlag(Qt::RightButton)); - isMiddleButton = isMiddleButton || (event.buttons().testFlag(Qt::MiddleButton)); - - // keyboard modifiers - isShifted = event.modifiers().testFlag(Qt::ShiftModifier); - isMeta = event.modifiers().testFlag(Qt::MetaModifier); - isControl = event.modifiers().testFlag(Qt::ControlModifier); - isAlt = event.modifiers().testFlag(Qt::AltModifier); } QScriptValue mouseEventToScriptValue(QScriptEngine* engine, const MouseEvent& event) { From 3bec67ecfd5ff369ec0aa2ae11bc0eeb937b64a2 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 19 Feb 2014 11:33:43 -0800 Subject: [PATCH 51/83] fix right mouse click --- libraries/script-engine/src/EventTypes.cpp | 25 ++++++++++------------ 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/libraries/script-engine/src/EventTypes.cpp b/libraries/script-engine/src/EventTypes.cpp index 8fac2bcd2a..d0ba160add 100644 --- a/libraries/script-engine/src/EventTypes.cpp +++ b/libraries/script-engine/src/EventTypes.cpp @@ -262,10 +262,17 @@ MouseEvent::MouseEvent() : }; -MouseEvent::MouseEvent(const QMouseEvent& event) { - x = event.x(); - y = event.y(); - +MouseEvent::MouseEvent(const QMouseEvent& event) : + x(event.x()), + y(event.y()), + isLeftButton(event.buttons().testFlag(Qt::LeftButton)), + isRightButton(event.buttons().testFlag(Qt::RightButton)), + isMiddleButton(event.buttons().testFlag(Qt::MiddleButton)), + isShifted(event.modifiers().testFlag(Qt::ShiftModifier)), + isControl(event.modifiers().testFlag(Qt::ControlModifier)), + isMeta(event.modifiers().testFlag(Qt::MetaModifier)), + isAlt(event.modifiers().testFlag(Qt::AltModifier)) +{ // single button that caused the event switch (event.button()) { case Qt::LeftButton: @@ -284,16 +291,6 @@ MouseEvent::MouseEvent(const QMouseEvent& event) { button = "NONE"; break; } - // button pressed state - isLeftButton = isLeftButton || (event.buttons().testFlag(Qt::LeftButton)); - isRightButton = isRightButton || (event.buttons().testFlag(Qt::RightButton)); - isMiddleButton = isMiddleButton || (event.buttons().testFlag(Qt::MiddleButton)); - - // keyboard modifiers - isShifted = event.modifiers().testFlag(Qt::ShiftModifier); - isMeta = event.modifiers().testFlag(Qt::MetaModifier); - isControl = event.modifiers().testFlag(Qt::ControlModifier); - isAlt = event.modifiers().testFlag(Qt::AltModifier); } QScriptValue mouseEventToScriptValue(QScriptEngine* engine, const MouseEvent& event) { From f7fcbc234e82d6beb00db65b8e6998f184a3c154 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 19 Feb 2014 11:47:40 -0800 Subject: [PATCH 52/83] Fixes for Xcode warnings with no Visage, explanatory comments for Model's base geometry pointer. --- interface/src/devices/Visage.cpp | 10 +++++++--- interface/src/devices/Visage.h | 11 ++++++----- interface/src/renderer/Model.cpp | 1 + interface/src/renderer/Model.h | 2 +- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 26e7993ecb..4727aac1fe 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -30,12 +30,14 @@ using namespace VisageSDK; const glm::vec3 DEFAULT_HEAD_ORIGIN(0.0f, 0.0f, 0.7f); Visage::Visage() : +#ifdef HAVE_VISAGE + _leftInnerBrowIndex(0), + _rightInnerBrowIndex(0), +#endif _active(false), _headOrigin(DEFAULT_HEAD_ORIGIN), _estimatedEyePitch(0.0f), - _estimatedEyeYaw(0.0f), - _leftInnerBrowIndex(0), - _rightInnerBrowIndex(0) { + _estimatedEyeYaw(0.0f) { #ifdef HAVE_VISAGE switchToResourcesParentIfRequired(); @@ -62,6 +64,7 @@ Visage::~Visage() { #endif } +#ifdef HAVE_VISAGE static int leftEyeBlinkIndex = 0; static int rightEyeBlinkIndex = 1; static int centerBrowIndex = 16; @@ -111,6 +114,7 @@ static const QHash& getBlendshapeIndices() { static QHash blendshapeIndices = createBlendshapeIndices(); return blendshapeIndices; } +#endif const float TRANSLATION_SCALE = 20.0f; diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 124ef29e3b..a5c826d1bf 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -42,9 +42,14 @@ public: void reset(); private: - + +#ifdef HAVE_VISAGE VisageSDK::VisageTracker2* _tracker; VisageSDK::FaceData* _data; + int _leftInnerBrowIndex; + int _rightInnerBrowIndex; + QVector _blendshapeIndices; +#endif bool _active; glm::quat _headRotation; @@ -56,10 +61,6 @@ private: float _estimatedEyeYaw; std::vector _blendshapeCoefficients; - - QVector _blendshapeIndices; - int _leftInnerBrowIndex; - int _rightInnerBrowIndex; }; #endif /* defined(__interface__Visage__) */ diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 48e1d0f70c..f1916db4d1 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -421,6 +421,7 @@ void Model::setURL(const QUrl& url, const QUrl& fallback) { _dilatedTextures.clear(); _lodHysteresis = NetworkGeometry::NO_HYSTERESIS; + // we retain a reference to the base geometry so that its reference count doesn't fall to zero _baseGeometry = _geometry = Application::getInstance()->getGeometryCache()->getGeometry(url, fallback); } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 1d1cdc22a7..28189d0379 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -227,7 +227,7 @@ private: void deleteGeometry(); void renderMeshes(float alpha, bool translucent); - QSharedPointer _baseGeometry; + QSharedPointer _baseGeometry; ///< reference required to prevent collection of base float _lodHysteresis; float _pupilDilation; From 5f9139dcd05ac25fa82a9524c15c3047deaeb890 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 19 Feb 2014 11:54:27 -0800 Subject: [PATCH 53/83] Fixed some left/right issues. --- interface/src/devices/Visage.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 4727aac1fe..c3dfeab6b2 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -77,14 +77,12 @@ static QHash createBlendshapeIndices() { blendshapeMap.insert("JawOpen", "au_jaw_drop"); blendshapeMap.insert("LipsLowerDown", "au_lower_lip_drop"); blendshapeMap.insert("LipsUpperUp", "au_upper_lip_raiser"); - blendshapeMap.insert("LipsStretch_L", "au_lip_stretcher_left"); - blendshapeMap.insert("BrowsU_L", "au_left_outer_brow_raiser"); - blendshapeMap.insert("BrowsU_C", "au_left_inner_brow_raiser"); - blendshapeMap.insert("BrowsD_L", "au_left_brow_lowerer"); - blendshapeMap.insert("LipsStretch_R", "au_lip_stretcher_right"); - blendshapeMap.insert("BrowsU_R", "au_right_outer_brow_raiser"); - blendshapeMap.insert("BrowsU_C", "au_right_inner_brow_raiser"); - blendshapeMap.insert("BrowsD_R", "au_right_brow_lowerer"); + blendshapeMap.insert("LipsStretch_R", "au_lip_stretcher_left"); + blendshapeMap.insert("BrowsU_R", "au_left_outer_brow_raiser"); + blendshapeMap.insert("BrowsD_R", "au_left_brow_lowerer"); + blendshapeMap.insert("LipsStretch_L", "au_lip_stretcher_right"); + blendshapeMap.insert("BrowsU_L", "au_right_outer_brow_raiser"); + blendshapeMap.insert("BrowsD_L", "au_right_brow_lowerer"); QHash blendshapeIndices; for (int i = 0;; i++) { From bf12cdddf5a75afa57b0ea06137f693370b7c52f Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 19 Feb 2014 12:03:14 -0800 Subject: [PATCH 54/83] We need libc++, not libc++abi. --- interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 32e75c9f34..a0a9033187 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -161,7 +161,7 @@ if (VISAGE_FOUND AND NOT DISABLE_VISAGE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment -isystem ${VISAGE_INCLUDE_DIRS}") find_library(AVFoundation AVFoundation) find_library(CoreMedia CoreMedia) - find_library(NEW_STD_LIBRARY libc++abi.dylib /usr/lib/) + find_library(NEW_STD_LIBRARY libc++.dylib /usr/lib/) target_link_libraries(${TARGET_NAME} ${AVFoundation} ${CoreMedia} ${NEW_STD_LIBRARY}) endif (APPLE) target_link_libraries(${TARGET_NAME} ${VISAGE_LIBRARIES}) From 64031701e1bf07f9940be817191ef2fa9851439e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 19 Feb 2014 12:33:05 -0800 Subject: [PATCH 55/83] Added icons for import dialog buttons --- interface/resources/icons/backButton.svg | 18 ++++++++++++++++++ interface/resources/icons/forwardButton.svg | 19 +++++++++++++++++++ interface/resources/icons/toParentButton.svg | 18 ++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 interface/resources/icons/backButton.svg create mode 100644 interface/resources/icons/forwardButton.svg create mode 100644 interface/resources/icons/toParentButton.svg diff --git a/interface/resources/icons/backButton.svg b/interface/resources/icons/backButton.svg new file mode 100644 index 0000000000..0c9fceccc4 --- /dev/null +++ b/interface/resources/icons/backButton.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + diff --git a/interface/resources/icons/forwardButton.svg b/interface/resources/icons/forwardButton.svg new file mode 100644 index 0000000000..73e6439f11 --- /dev/null +++ b/interface/resources/icons/forwardButton.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/interface/resources/icons/toParentButton.svg b/interface/resources/icons/toParentButton.svg new file mode 100644 index 0000000000..cfbe054234 --- /dev/null +++ b/interface/resources/icons/toParentButton.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + From f24cd0ceba270f83d63c8797fa51ffed45c27f7b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 19 Feb 2014 12:34:38 -0800 Subject: [PATCH 56/83] Added switch to pasteMode after successful import. --- interface/src/Application.cpp | 41 +++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b316548ad4..6495b17633 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -309,8 +309,13 @@ Application::~Application() { delete idleTimer; Menu::getInstance()->saveSettings(); - _rearMirrorTools->saveSettings(_settings); + + _sharedVoxelSystem.changeTree(new VoxelTree); + if (_voxelImporter) { + _voxelImporter->saveSettings(_settings); + delete _voxelImporter; + } _settings->sync(); // let the avatar mixer know we're out @@ -331,7 +336,6 @@ Application::~Application() { storeSizeAndPosition(); saveScripts(); - _sharedVoxelSystem.changeTree(new VoxelTree); VoxelTreeElement::removeDeleteHook(&_voxels); // we don't need to do this processing on shutdown Menu::getInstance()->deleteLater(); @@ -1296,8 +1300,14 @@ void Application::mousePressEvent(QMouseEvent* event) { pasteVoxels(); } - } else if (event->button() == Qt::RightButton && Menu::getInstance()->isVoxelModeActionChecked()) { - deleteVoxelUnderCursor(); + } else if (event->button() == Qt::RightButton) { + if (Menu::getInstance()->isVoxelModeActionChecked()) { + deleteVoxelUnderCursor(); + } + if (_pasteMode) { + _pasteMode = false; + } + } } } @@ -1707,13 +1717,19 @@ void Application::exportVoxels() { void Application::importVoxels() { if (!_voxelImporter) { _voxelImporter = new VoxelImporter(_window); - _voxelImporter->init(_settings); + _voxelImporter->loadSettings(_settings); } - if (_voxelImporter->exec()) { - qDebug("[DEBUG] Import succeeded."); + if (!_voxelImporter->exec()) { + qDebug() << "[DEBUG] Import succeeded." << endl; + Menu::getInstance()->setIsOptionChecked(MenuOption::VoxelSelectMode, true); + _pasteMode = true; } else { - qDebug("[DEBUG] Import failed."); + qDebug() << "[DEBUG] Import failed." << endl; + if (_sharedVoxelSystem.getTree() == _voxelImporter->getVoxelTree()) { + _sharedVoxelSystem.killLocalVoxels(); + _sharedVoxelSystem.changeTree(&_clipboard); + } } // restore the main window's active state @@ -1770,10 +1786,11 @@ void Application::pasteVoxels() { } pasteVoxelsToOctalCode(octalCodeDestination); - + if (calculatedOctCode) { delete[] calculatedOctCode; } + _pasteMode = false; } void Application::findAxisAlignment() { @@ -1845,6 +1862,7 @@ void Application::init() { VoxelTreeElement::removeUpdateHook(&_sharedVoxelSystem); + // Cleanup of the original shared tree _sharedVoxelSystem.init(); VoxelTree* tmpTree = _sharedVoxelSystem.getTree(); _sharedVoxelSystem.changeTree(&_clipboard); @@ -1936,12 +1954,11 @@ void Application::init() { _audio.init(_glWidget); _rearMirrorTools = new RearMirrorTools(_glWidget, _mirrorViewRect, _settings); + connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView())); connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView())); connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors())); - - } void Application::closeMirrorView() { @@ -2090,7 +2107,7 @@ void Application::updateMouseVoxels(float deltaTime, float& distance, BoxFace& f PerformanceWarning warn(showWarnings, "Application::updateMouseVoxels()"); _mouseVoxel.s = 0.0f; - bool wasInitialized = _mouseVoxelScaleInitialized; + bool wasInitialized = _mouseVoxelScaleInitialized ; if (Menu::getInstance()->isVoxelModeActionChecked() && (fabs(_myAvatar->getVelocity().x) + fabs(_myAvatar->getVelocity().y) + From 7bce649080064fdbea4638b4c91fc7e971c8a528 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 19 Feb 2014 12:35:45 -0800 Subject: [PATCH 57/83] Fix for voxelImporter --- interface/src/VoxelImporter.cpp | 192 +++++++++++++------------------- interface/src/VoxelImporter.h | 17 ++- 2 files changed, 85 insertions(+), 124 deletions(-) diff --git a/interface/src/VoxelImporter.cpp b/interface/src/VoxelImporter.cpp index 653d04cee4..3949ee96d2 100644 --- a/interface/src/VoxelImporter.cpp +++ b/interface/src/VoxelImporter.cpp @@ -12,6 +12,9 @@ #include #include +const QString SETTINGS_GROUP_NAME = "VoxelImport"; +const QString IMPORT_DIALOG_SETTINGS_KEY = "ImportDialogSettings"; + class ImportTask : public QObject, public QRunnable { public: ImportTask(const QString &filename); @@ -21,18 +24,16 @@ private: QString _filename; }; -const QString SETTINGS_GROUP_NAME = "VoxelImport"; -const QString IMPORT_DIALOG_SETTINGS_KEY = "ImportDialogSettings"; - VoxelImporter::VoxelImporter(QWidget* parent) : QObject(parent), _voxelTree(true), _importDialog(parent), - _currentTask(NULL), - _nextTask(NULL) + _task(NULL), + _didImport(false) { - connect(&_importDialog, &QFileDialog::currentChanged, this, &VoxelImporter::preImport); - connect(&_importDialog, &QFileDialog::accepted, this, &VoxelImporter::import); + connect(&_voxelTree, SIGNAL(importProgress(int)), &_importDialog, SLOT(setProgressBarValue(int))); + connect(&_importDialog, SIGNAL(canceled()), this, SLOT(cancel())); + connect(&_importDialog, SIGNAL(accepted()), this, SLOT(import())); } void VoxelImporter::saveSettings(QSettings* settings) { @@ -41,145 +42,106 @@ void VoxelImporter::saveSettings(QSettings* settings) { settings->endGroup(); } -void VoxelImporter::init(QSettings* settings) { +void VoxelImporter::loadSettings(QSettings* settings) { settings->beginGroup(SETTINGS_GROUP_NAME); _importDialog.restoreState(settings->value(IMPORT_DIALOG_SETTINGS_KEY).toByteArray()); settings->endGroup(); } VoxelImporter::~VoxelImporter() { - if (_nextTask) { - delete _nextTask; - _nextTask = NULL; - } - - if (_currentTask) { - disconnect(_currentTask, 0, 0, 0); - _voxelTree.cancelImport(); - _currentTask = NULL; - } + cleanupTask(); } void VoxelImporter::reset() { _voxelTree.eraseAllOctreeElements(); _importDialog.reset(); - _filename = ""; - if (_nextTask) { - delete _nextTask; - _nextTask = NULL; - } - - if (_currentTask) { - _voxelTree.cancelImport(); - } + cleanupTask(); } int VoxelImporter::exec() { reset(); - - int ret = _importDialog.exec(); - - if (!ret) { - reset(); - } else { - _importDialog.reset(); - - VoxelSystem* voxelSystem = Application::getInstance()->getSharedVoxelSystem(); - - voxelSystem->copySubTreeIntoNewTree(voxelSystem->getTree()->getRoot(), - Application::getInstance()->getClipboard(), - true); - voxelSystem->changeTree(Application::getInstance()->getClipboard()); - } - - return ret; -} - -int VoxelImporter::preImport() { - QString filename = _importDialog.getCurrentFile(); - - if (!QFileInfo(filename).isFile()) { - return 0; - } + _importDialog.exec(); - _filename = filename; - - if (_nextTask) { - delete _nextTask; - } - - _nextTask = new ImportTask(_filename); - connect(_nextTask, SIGNAL(destroyed()), SLOT(launchTask())); - - if (_currentTask != NULL) { - _voxelTree.cancelImport(); - } else { - launchTask(); - } - - return 1; -} - -int VoxelImporter::import() { - QString filename = _importDialog.getCurrentFile(); - - if (!QFileInfo(filename).isFile()) { - _importDialog.reject(); - return 0; - } - - if (_filename == filename) { - if (_currentTask) { - connect(_currentTask, SIGNAL(destroyed()), &_importDialog, SLOT(accept())); - } else { - _importDialog.accept(); - } + if (!_didImport) { + // if the import is rejected, we make sure to cleanup before leaving + cleanupTask(); return 1; - } - - _filename = filename; - - if (_nextTask) { - delete _nextTask; - } - - _nextTask = new ImportTask(_filename); - connect(_nextTask, SIGNAL(destroyed()), SLOT(launchTask())); - connect(_nextTask, SIGNAL(destroyed()), &_importDialog, SLOT(accept())); - - if (_currentTask != NULL) { - _voxelTree.cancelImport(); } else { - launchTask(); + _didImport = false; + return 0; } - - return 1; } -void VoxelImporter::launchTask() { - if (_nextTask != NULL) { - _currentTask = _nextTask; - _nextTask = NULL; +void VoxelImporter::import() { + switch (_importDialog.getMode()) { + case loadingMode: + _importDialog.setMode(placeMode); + return; + case placeMode: + // Means the user chose to import + _didImport = true; + _importDialog.close(); + return; + case importMode: + default: + QString filename = _importDialog.getCurrentFile(); + // if it's not a file, we ignore the call + if (!QFileInfo(filename).isFile()) { + return; + } + + // Let's prepare the dialog window for import + _importDialog.setMode(loadingMode); + + // If not already done, we switch to the local tree + if (Application::getInstance()->getSharedVoxelSystem()->getTree() != &_voxelTree) { + Application::getInstance()->getSharedVoxelSystem()->changeTree(&_voxelTree); + } + + // Creation and launch of the import task on the thread pool + _task = new ImportTask(filename); + connect(_task, SIGNAL(destroyed()), SLOT(import())); + QThreadPool::globalInstance()->start(_task); + break; + } +} - if (Application::getInstance()->getSharedVoxelSystem()->getTree() != &_voxelTree) { - Application::getInstance()->getSharedVoxelSystem()->changeTree(&_voxelTree); - } +void VoxelImporter::cancel() { + switch (_importDialog.getMode()) { + case loadingMode: + disconnect(_task, 0, 0, 0); + cleanupTask(); + case placeMode: + _importDialog.setMode(importMode); + break; + case importMode: + default: + _importDialog.close(); + break; + } +} - QThreadPool::globalInstance()->start(_currentTask); - } else { - _currentTask = NULL; +void VoxelImporter::cleanupTask() { + // If a task is running, we cancel it and put the pointer to null + if (_task) { + _task = NULL; + _voxelTree.cancelImport(); } } ImportTask::ImportTask(const QString &filename) - : _filename(filename) { + : _filename(filename) +{ + setAutoDelete(true); } void ImportTask::run() { VoxelSystem* voxelSystem = Application::getInstance()->getSharedVoxelSystem(); + // We start by cleaning up the shared voxel system just in case voxelSystem->killLocalVoxels(); + // Then we call the righ method for the job if (_filename.endsWith(".png", Qt::CaseInsensitive)) { voxelSystem->readFromSquareARGB32Pixels(_filename.toLocal8Bit().data()); } else if (_filename.endsWith(".svo", Qt::CaseInsensitive)) { @@ -187,8 +149,10 @@ void ImportTask::run() { } else if (_filename.endsWith(".schematic", Qt::CaseInsensitive)) { voxelSystem->readFromSchematicFile(_filename.toLocal8Bit().data()); } else { - qDebug("[ERROR] Invalid file extension."); + // We should never get here. + qDebug() << "[ERROR] Invalid file extension." << endl; } - + + // Here we reaverage the tree so that he is ready for preview voxelSystem->getTree()->reaverageOctreeElements(); } diff --git a/interface/src/VoxelImporter.h b/interface/src/VoxelImporter.h index 43a3835e68..e77abaf18d 100644 --- a/interface/src/VoxelImporter.h +++ b/interface/src/VoxelImporter.h @@ -23,28 +23,25 @@ public: VoxelImporter(QWidget* parent = NULL); ~VoxelImporter(); - void init(QSettings* settings); void reset(); + void loadSettings(QSettings* settings); void saveSettings(QSettings* settings); VoxelTree* getVoxelTree() { return &_voxelTree; } public slots: int exec(); - int preImport(); - int import(); - -private slots: - void launchTask(); + void import(); + void cancel(); private: VoxelTree _voxelTree; ImportDialog _importDialog; - QString _filename; - - ImportTask* _currentTask; - ImportTask* _nextTask; + ImportTask* _task; + bool _didImport; + + void cleanupTask(); }; #endif /* defined(__hifi__VoxelImporter__) */ From 0ed7b959d770fc0e90af2a5361c3e5e0ca5add06 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 19 Feb 2014 12:36:27 -0800 Subject: [PATCH 58/83] Changed import dialog UI --- interface/src/ImportDialog.cpp | 158 ++++++++++++++++----------------- interface/src/ImportDialog.h | 32 ++++--- 2 files changed, 97 insertions(+), 93 deletions(-) diff --git a/interface/src/ImportDialog.cpp b/interface/src/ImportDialog.cpp index c276a4da6b..192e7fbf86 100644 --- a/interface/src/ImportDialog.cpp +++ b/interface/src/ImportDialog.cpp @@ -16,14 +16,13 @@ const QString WINDOW_NAME = QObject::tr("Import Voxels"); const QString IMPORT_BUTTON_NAME = QObject::tr("Import"); +const QString LOADING_BUTTON_NAME = QObject::tr("Loading ..."); +const QString PLACE_BUTTON_NAME = QObject::tr("Place voxels"); const QString IMPORT_INFO = QObject::tr("Import %1 as voxels"); const QString CANCEL_BUTTON_NAME = QObject::tr("Cancel"); -const QString INFO_LABEL_TEXT = QObject::tr("
" - "This will load the selected file into Hifi and allow you
" - "to place it with %1-V; you must be in select or
" - "add mode (S or V keys will toggle mode) to place.
"); -const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); + +const QString DOWNLOAD_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation); const int SHORT_FILE_EXTENSION = 4; const int SECOND_INDEX_LETTER = 1; @@ -66,7 +65,7 @@ QIcon HiFiIconProvider::icon(const QFileInfo &info) const { if (info.isDir()) { if (info.absoluteFilePath() == QDir::homePath()) { return QIcon("resources/icons/home.svg"); - } else if (info.absoluteFilePath() == DESKTOP_LOCATION) { + } else if (info.absoluteFilePath() == QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)) { return QIcon("resources/icons/desktop.svg"); } else if (info.absoluteFilePath() == QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)) { return QIcon("resources/icons/documents.svg"); @@ -95,10 +94,11 @@ QString HiFiIconProvider::type(const QFileInfo &info) const { } ImportDialog::ImportDialog(QWidget* parent) : - QFileDialog(parent, WINDOW_NAME, DESKTOP_LOCATION, NULL), + QFileDialog(parent, WINDOW_NAME, DOWNLOAD_LOCATION, NULL), + _progressBar(this), _importButton(IMPORT_BUTTON_NAME, this), _cancelButton(CANCEL_BUTTON_NAME, this), - fileAccepted(false) { + _mode(importMode) { setOption(QFileDialog::DontUseNativeDialog, true); setFileMode(QFileDialog::ExistingFile); @@ -107,96 +107,89 @@ ImportDialog::ImportDialog(QWidget* parent) : setImportTypes(); setLayout(); - connect(&_importButton, SIGNAL(pressed()), SLOT(import())); - connect(this, SIGNAL(currentChanged(QString)), SLOT(saveCurrentFile(QString))); - - connect(&_cancelButton, SIGNAL(pressed()), SLOT(close())); - connect(this, SIGNAL(currentChanged(QString)), SLOT(saveCurrentFile(QString))); -} - -ImportDialog::~ImportDialog() { - deleteLater(); -} - -void ImportDialog::import() { - fileAccepted = true; - emit accepted(); -} - -void ImportDialog::accept() { - // do nothing if import is not enable - if (!_importButton.isEnabled()) { - return; - } + _progressBar.setRange(0, 100); - if (!fileAccepted) { - fileAccepted = true; - emit accepted(); - } else { - QFileDialog::accept(); - } -} - -void ImportDialog::reject() { - QFileDialog::reject(); -} - -int ImportDialog::exec() { - // deselect selected file - selectFile(" "); - return QFileDialog::exec(); + connect(&_importButton, SIGNAL(pressed()), SLOT(accept())); + connect(&_cancelButton, SIGNAL(pressed()), SIGNAL(canceled())); + connect(this, SIGNAL(currentChanged(QString)), SLOT(saveCurrentFile(QString))); } void ImportDialog::reset() { - _importButton.setEnabled(false); + setMode(importMode); + _progressBar.setValue(0); } -void ImportDialog::saveCurrentFile(QString filename) { - if (!filename.isEmpty() && QFileInfo(filename).isFile()) { - _currentFile = filename; - _importButton.setEnabled(true); - } else { - _currentFile.clear(); - _importButton.setEnabled(false); +void ImportDialog::setMode(dialogMode mode) { + _mode = mode; + + switch (_mode) { + case loadingMode: + _importButton.setEnabled(false); + _importButton.setText(LOADING_BUTTON_NAME); + findChild("sidebar")->setEnabled(false); + findChild("treeView")->setEnabled(false); + findChild("backButton")->setEnabled(false); + findChild("forwardButton")->setEnabled(false); + findChild("toParentButton")->setEnabled(false); + break; + case placeMode: + _progressBar.setValue(100); + _importButton.setEnabled(true); + _importButton.setText(PLACE_BUTTON_NAME); + findChild("sidebar")->setEnabled(false); + findChild("treeView")->setEnabled(false); + findChild("backButton")->setEnabled(false); + findChild("forwardButton")->setEnabled(false); + findChild("toParentButton")->setEnabled(false); + break; + case importMode: + default: + _progressBar.setValue(0); + _importButton.setEnabled(true); + _importButton.setText(IMPORT_BUTTON_NAME); + findChild("sidebar")->setEnabled(true); + findChild("treeView")->setEnabled(true); + findChild("backButton")->setEnabled(true); + findChild("forwardButton")->setEnabled(true); + findChild("toParentButton")->setEnabled(true); + break; } } +void ImportDialog::setProgressBarValue(int value) { + _progressBar.setValue(value); +} + +void ImportDialog::accept() { + emit accepted(); +} + +void ImportDialog::saveCurrentFile(QString filename) { + _currentFile = QFileInfo(filename).isFile() ? filename : ""; +} +#include void ImportDialog::setLayout() { - -#ifdef Q_OS_MAC - QString cmdString = ("Command"); -#else - QString cmdString = ("Control"); -#endif - QLabel* infoLabel = new QLabel(QString(INFO_LABEL_TEXT).arg(cmdString)); - infoLabel->setObjectName("infoLabel"); - QGridLayout* gridLayout = (QGridLayout*) layout(); - gridLayout->addWidget(infoLabel, 2, 0, 2, 1); + gridLayout->addWidget(&_progressBar, 2, 0, 2, 1); gridLayout->addWidget(&_cancelButton, 2, 1, 2, 1); gridLayout->addWidget(&_importButton, 2, 2, 2, 1); - + // set ObjectName used in qss for styling + _progressBar.setObjectName("progressBar"); _importButton.setObjectName("importButton"); _cancelButton.setObjectName("cancelButton"); // set fixed size _importButton.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); _cancelButton.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + + _progressBar.setFixedHeight(7); + _progressBar.setTextVisible(false); // hide unused embedded widgets in QFileDialog QWidget* widget = findChild("lookInCombo"); widget->hide(); - - widget = findChild("backButton"); - widget->hide(); - - widget = findChild("forwardButton"); - widget->hide(); - - widget = findChild("toParentButton"); - widget->hide(); - + widget = findChild("newFolderButton"); widget->hide(); @@ -230,8 +223,18 @@ void ImportDialog::setLayout() { widget = findChild("treeView"); widget->setAttribute(Qt::WA_MacShowFocusRect, false); - + switchToResourcesParentIfRequired(); + + QIcon icon = QIcon("resources/icons/backButton.svg"); + QPushButton* button = (QPushButton*) findChild("backButton"); + //button->setIcon(icon); + + button = (QPushButton*) findChild("forwardButton"); + button = (QPushButton*) findChild("toParentButton"); + + + QFile styleSheet("resources/styles/import_dialog.qss"); if (styleSheet.open(QIODevice::ReadOnly)) { setStyleSheet(styleSheet.readAll()); @@ -281,11 +284,6 @@ void ImportDialog::setImportTypes() { setIconProvider(new HiFiIconProvider(iconsMap)); setNameFilter(importFormatsFilterList); -#ifdef Q_OS_MAC - QString cmdString = ("Command"); -#else - QString cmdString = ("Control"); -#endif setLabelText(QFileDialog::LookIn, QString(IMPORT_INFO).arg(importFormatsInfo)); } } diff --git a/interface/src/ImportDialog.h b/interface/src/ImportDialog.h index 5cfc49e51e..910cd8f789 100644 --- a/interface/src/ImportDialog.h +++ b/interface/src/ImportDialog.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -26,37 +27,42 @@ public: QHash iconsMap; }; +enum dialogMode { + importMode, + loadingMode, + placeMode +}; + class ImportDialog : public QFileDialog { Q_OBJECT public: ImportDialog(QWidget* parent = NULL); - ~ImportDialog(); - void reset(); - + QString getCurrentFile() const { return _currentFile; } - + dialogMode getMode() const { return _mode; } + void setMode(dialogMode mode); + signals: - void accepted(); - + void canceled(); + public slots: - int exec(); - void import(); - void accept(); - void reject(); + void setProgressBarValue(int value); private slots: - void saveCurrentFile(QString); + void accept(); + void saveCurrentFile(QString filename); private: QString _currentFile; + QProgressBar _progressBar; QPushButton _importButton; QPushButton _cancelButton; - + dialogMode _mode; + void setLayout(); void setImportTypes(); - bool fileAccepted; }; #endif /* defined(__hifi__ImportDialog__) */ From a732cbf3005b7f2b4c2b406211fc64aa0b800054 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 19 Feb 2014 12:37:08 -0800 Subject: [PATCH 59/83] Modified QSS for new UI (QProgressBar) --- interface/resources/styles/import_dialog.qss | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/interface/resources/styles/import_dialog.qss b/interface/resources/styles/import_dialog.qss index dd9761b7ed..e5046f8b77 100644 --- a/interface/resources/styles/import_dialog.qss +++ b/interface/resources/styles/import_dialog.qss @@ -20,12 +20,23 @@ QLabel#infoLabel { color: #666666; } +QProgressBar { + border: 0px; + border-radius: 0px; + background-color: #BFE4E4; + margin-right: 60px; +} + +QProgressBar::chunk { + background-color: #000000; +} + QPushButton { border-width: 0; border-radius: 9px; font-size: 18px; padding: 17px 0px 15px; - width: 107px; + width: 120px; margin-top: 20px; margin-bottom: 18px; } From 4fd735e28fe84ba70dba83757179a402b78c571e Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Wed, 19 Feb 2014 22:08:47 +0100 Subject: [PATCH 60/83] Added a factor to correct display name position for non default models For the default avatar, the position is wrong --- interface/src/avatar/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 91d91e7219..031084b11a 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -302,7 +302,7 @@ void Avatar::renderDisplayName() { glDisable(GL_LIGHTING); glPushMatrix(); - glm::vec3 textPosition = getPosition() + getBodyUpDirection() * (getSkeletonHeight() + getHeadHeight()); + glm::vec3 textPosition = getPosition() + getBodyUpDirection() * ((getSkeletonHeight() + getHeadHeight()) / 1.5f); glTranslatef(textPosition.x, textPosition.y, textPosition.z); // we need "always facing camera": we must remove the camera rotation from the stack From 406768bf120cfda1ca689073f385d86e6d57002d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 19 Feb 2014 13:13:17 -0800 Subject: [PATCH 61/83] Code style fixes --- interface/src/Application.cpp | 2 +- interface/src/ImportDialog.cpp | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3e30d5bfb4..bdffcd1dec 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2128,7 +2128,7 @@ void Application::updateMouseVoxels(float deltaTime, float& distance, BoxFace& f PerformanceWarning warn(showWarnings, "Application::updateMouseVoxels()"); _mouseVoxel.s = 0.0f; - bool wasInitialized = _mouseVoxelScaleInitialized ; + bool wasInitialized = _mouseVoxelScaleInitialized; if (Menu::getInstance()->isVoxelModeActionChecked() && (fabs(_myAvatar->getVelocity().x) + fabs(_myAvatar->getVelocity().y) + diff --git a/interface/src/ImportDialog.cpp b/interface/src/ImportDialog.cpp index 192e7fbf86..0911f7c184 100644 --- a/interface/src/ImportDialog.cpp +++ b/interface/src/ImportDialog.cpp @@ -21,7 +21,6 @@ const QString PLACE_BUTTON_NAME = QObject::tr("Place voxels"); const QString IMPORT_INFO = QObject::tr("Import %1 as voxels"); const QString CANCEL_BUTTON_NAME = QObject::tr("Cancel"); - const QString DOWNLOAD_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation); const int SHORT_FILE_EXTENSION = 4; const int SECOND_INDEX_LETTER = 1; @@ -167,7 +166,7 @@ void ImportDialog::accept() { void ImportDialog::saveCurrentFile(QString filename) { _currentFile = QFileInfo(filename).isFile() ? filename : ""; } -#include + void ImportDialog::setLayout() { QGridLayout* gridLayout = (QGridLayout*) layout(); gridLayout->addWidget(&_progressBar, 2, 0, 2, 1); @@ -225,7 +224,6 @@ void ImportDialog::setLayout() { widget->setAttribute(Qt::WA_MacShowFocusRect, false); switchToResourcesParentIfRequired(); - QIcon icon = QIcon("resources/icons/backButton.svg"); QPushButton* button = (QPushButton*) findChild("backButton"); //button->setIcon(icon); @@ -233,8 +231,6 @@ void ImportDialog::setLayout() { button = (QPushButton*) findChild("forwardButton"); button = (QPushButton*) findChild("toParentButton"); - - QFile styleSheet("resources/styles/import_dialog.qss"); if (styleSheet.open(QIODevice::ReadOnly)) { setStyleSheet(styleSheet.readAll()); From ba0b01d02883f43ae79dfd3bc1dd4c5cffcc63ac Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Wed, 19 Feb 2014 22:51:40 +0100 Subject: [PATCH 62/83] Style changes after ZappoMan's comments --- interface/src/avatar/Avatar.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 031084b11a..f0dbcc8dbc 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -345,7 +345,7 @@ void Avatar::renderDisplayName() { QFontMetrics metrics = textRenderer(DISPLAYNAME)->metrics(); int bottom = -metrics.descent(), top = bottom + metrics.height(); int left = -_displayNameWidth/2, right = _displayNameWidth/2; - int border = 5; + const int border = 5; bottom -= border; left -= border; top += border; @@ -367,10 +367,10 @@ void Avatar::renderDisplayName() { glColor4f(0.93f, 0.93f, 0.93f, _displayNameAlpha); QByteArray ba = _displayName.toLocal8Bit(); - const char *text = ba.data(); + const char* text = ba.data(); glDisable(GL_POLYGON_OFFSET_FILL); - textRenderer(DISPLAYNAME)->draw(-_displayNameWidth/2.0, 0, text); + textRenderer(DISPLAYNAME)->draw(-_displayNameWidth / 2, 0, text); } From 241214ba37bba81fefa409e90e8f10db8fd4bae0 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Wed, 19 Feb 2014 23:08:19 +0100 Subject: [PATCH 63/83] Fixed compilation after merged from upstream --- interface/src/avatar/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 9eb5e0d577..9ff1ec8cb1 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -587,7 +587,7 @@ float Avatar::getSkeletonHeight() const { } float Avatar::getHeadHeight() const { - Extents extents = _head.getFaceModel().getBindExtents(); + Extents extents = getHead()->getFaceModel().getBindExtents(); return extents.maximum.y - extents.minimum.y; } From ee7b5844b84ae7bdc3ac1db44c6913ad556df68c Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Wed, 19 Feb 2014 23:24:26 +0100 Subject: [PATCH 64/83] Minor cosmetic change --- interface/src/avatar/AvatarManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 026a5d6291..d910e51e35 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -6,8 +6,10 @@ // Copyright (c) 2014 HighFidelity, Inc. All rights reserved. // #include + #include #include + #include #include "Application.h" From 2a57080191390a863e1386f628e22af269da98b5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 19 Feb 2014 15:06:10 -0800 Subject: [PATCH 65/83] add clipboard example --- examples/clipboardExample.js | 142 +++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 examples/clipboardExample.js diff --git a/examples/clipboardExample.js b/examples/clipboardExample.js new file mode 100644 index 0000000000..c6864a91b3 --- /dev/null +++ b/examples/clipboardExample.js @@ -0,0 +1,142 @@ +// +// clipboardExample.js +// hifi +// +// Created by Brad Hefta-Gaub on 1/28/14. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// +// This is an example script that demonstrates use of the Clipboard class +// +// + +var selectedVoxel = { x: 0, y: 0, z: 0, s: 0 }; +var selectedSize = 4; + +function printKeyEvent(eventName, event) { + print(eventName); + print(" event.key=" + event.key); + print(" event.text=" + event.text); + print(" event.isShifted=" + event.isShifted); + print(" event.isControl=" + event.isControl); + print(" event.isMeta=" + event.isMeta); + print(" event.isAlt=" + event.isAlt); + print(" event.isKeypad=" + event.isKeypad); +} + + +function keyPressEvent(event) { + var debug = true; + if (debug) { + printKeyEvent("keyPressEvent", event); + } +} + +function keyReleaseEvent(event) { + var debug = false; + if (debug) { + printKeyEvent("keyReleaseEvent", event); + } + + // Note: this sample uses Alt+ as the key codes for these clipboard items + if ((event.key == 199 || event.key == 67 || event.text == "C" || event.text == "c") && event.isAlt) { + print("the Alt+C key was pressed"); + Clipboard.copyVoxels(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + } + if ((event.key == 8776 || event.key == 88 || event.text == "X" || event.text == "x") && event.isAlt) { + print("the Alt+X key was pressed"); + Clipboard.cutVoxels(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + } + if ((event.key == 8730 || event.key == 86 || event.text == "V" || event.text == "v") && event.isAlt) { + print("the Alt+V key was pressed"); + Clipboard.pasteVoxels(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + } + if (event.text == "DELETE" || event.text == "BACKSPACE") { + print("the DELETE/BACKSPACE key was pressed"); + Clipboard.deleteVoxels(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + } + if ((event.key == 199 || event.key == 67 || event.text == "C" || event.text == "c") && event.isAlt) { + print("the Alt+C key was pressed"); + Clipboard.copyVoxels(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + } +} + +// Map keyPress and mouse move events to our callbacks +Controller.keyPressEvent.connect(keyPressEvent); +Controller.keyReleaseEvent.connect(keyReleaseEvent); + +var selectCube = Overlays.addOverlay("cube", { + position: { x: 0, y: 0, z: 0}, + size: selectedSize, + color: { red: 255, green: 255, blue: 0}, + alpha: 1, + solid: false, + visible: false, + lineWidth: 4 + }); + + +function mouseMoveEvent(event) { + + var pickRay = Camera.computePickRay(event.x, event.y); + + var debug = false; + if (debug) { + print("mouseMoveEvent event.x,y=" + event.x + ", " + event.y); + print("called Camera.computePickRay()"); + print("computePickRay origin=" + pickRay.origin.x + ", " + pickRay.origin.y + ", " + pickRay.origin.z); + print("computePickRay direction=" + pickRay.direction.x + ", " + pickRay.direction.y + ", " + pickRay.direction.z); + } + + var intersection = Voxels.findRayIntersection(pickRay); + + if (intersection.intersects) { + if (debug) { + print("intersection voxel.red/green/blue=" + intersection.voxel.red + ", " + + intersection.voxel.green + ", " + intersection.voxel.blue); + print("intersection voxel.x/y/z/s=" + intersection.voxel.x + ", " + + intersection.voxel.y + ", " + intersection.voxel.z+ ": " + intersection.voxel.s); + print("intersection face=" + intersection.face); + print("intersection distance=" + intersection.distance); + print("intersection intersection.x/y/z=" + intersection.intersection.x + ", " + + intersection.intersection.y + ", " + intersection.intersection.z); + } + + + + var x = Math.floor(intersection.voxel.x / selectedSize) * selectedSize; + var y = Math.floor(intersection.voxel.y / selectedSize) * selectedSize; + var z = Math.floor(intersection.voxel.z / selectedSize) * selectedSize; + selectedVoxel = { x: x, y: y, z: z, s: selectedSize }; + Overlays.editOverlay(selectCube, { position: selectedVoxel, size: selectedSize, visible: true } ); + } else { + Overlays.editOverlay(selectCube, { visible: false } ); + selectedVoxel = { x: 0, y: 0, z: 0, s: 0 }; + } +} + +Controller.mouseMoveEvent.connect(mouseMoveEvent); + +function wheelEvent(event) { + var debug = false; + if (debug) { + print("wheelEvent"); + print(" event.x,y=" + event.x + ", " + event.y); + print(" event.delta=" + event.delta); + print(" event.orientation=" + event.orientation); + print(" event.isLeftButton=" + event.isLeftButton); + print(" event.isRightButton=" + event.isRightButton); + print(" event.isMiddleButton=" + event.isMiddleButton); + print(" event.isShifted=" + event.isShifted); + print(" event.isControl=" + event.isControl); + print(" event.isMeta=" + event.isMeta); + print(" event.isAlt=" + event.isAlt); + } +} + +Controller.wheelEvent.connect(wheelEvent); + +function scriptEnding() { + Overlays.deleteOverlay(selectCube); +} + +Script.scriptEnding.connect(scriptEnding); From 44d5b9b2f8f67c65992c25e9830b5938a7063e41 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Thu, 20 Feb 2014 00:22:29 +0100 Subject: [PATCH 66/83] cosmetic change --- interface/src/avatar/AvatarManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index d910e51e35..4cc568cf18 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -7,11 +7,11 @@ // #include +#include + #include #include -#include - #include "Application.h" #include "Avatar.h" #include "Menu.h" From af3e19e6402c643b998e88d5c784dd4f65d2861b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 19 Feb 2014 16:01:14 -0800 Subject: [PATCH 67/83] Added style and pngs for the buttons --- interface/resources/styles/import_dialog.qss | 15 +++++++++++++ interface/src/ImportDialog.cpp | 23 ++++++++++++-------- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/interface/resources/styles/import_dialog.qss b/interface/resources/styles/import_dialog.qss index e5046f8b77..d7d661399d 100644 --- a/interface/resources/styles/import_dialog.qss +++ b/interface/resources/styles/import_dialog.qss @@ -62,6 +62,21 @@ QPushButton#cancelButton { margin-right: 11px; } +#backButton { + background-image: url(resources/icons/backButton.svg); + border-radius: 0px; +} + +#forwardButton { + background-image: url(resources/icons/forwardButton.svg); + border-radius: 0px; +} + +#toParentButton { + background-image: url(resources/icons/toParentButton.svg); + border-radius: 0px; +} + QSidebar, QTreeView { border: 1px solid #C5C5C5; font-size: 14px; diff --git a/interface/src/ImportDialog.cpp b/interface/src/ImportDialog.cpp index 0911f7c184..2e0173fb9f 100644 --- a/interface/src/ImportDialog.cpp +++ b/interface/src/ImportDialog.cpp @@ -181,9 +181,21 @@ void ImportDialog::setLayout() { // set fixed size _importButton.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); _cancelButton.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - - _progressBar.setFixedHeight(7); + _cancelButton.setFlat(true); + int progressBarHeight = 7; + _progressBar.setFixedHeight(progressBarHeight); _progressBar.setTextVisible(false); + + QSize BUTTON_SIZE = QSize(43, 33); + QPushButton* button = (QPushButton*) findChild("backButton"); + button->setIcon(QIcon()); + button->setFixedSize(BUTTON_SIZE); + button = (QPushButton*) findChild("forwardButton"); + button->setIcon(QIcon()); + button->setFixedSize(BUTTON_SIZE); + button = (QPushButton*) findChild("toParentButton"); + button->setIcon(QIcon()); + button->setFixedSize(BUTTON_SIZE); // hide unused embedded widgets in QFileDialog QWidget* widget = findChild("lookInCombo"); @@ -224,13 +236,6 @@ void ImportDialog::setLayout() { widget->setAttribute(Qt::WA_MacShowFocusRect, false); switchToResourcesParentIfRequired(); - QIcon icon = QIcon("resources/icons/backButton.svg"); - QPushButton* button = (QPushButton*) findChild("backButton"); - //button->setIcon(icon); - - button = (QPushButton*) findChild("forwardButton"); - button = (QPushButton*) findChild("toParentButton"); - QFile styleSheet("resources/styles/import_dialog.qss"); if (styleSheet.open(QIODevice::ReadOnly)) { setStyleSheet(styleSheet.readAll()); From 7662264af83d1d2e7d65df75bba13ba8aeed8617 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 19 Feb 2014 17:48:38 -0800 Subject: [PATCH 68/83] more work on clipboard example --- examples/clipboardExample.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/examples/clipboardExample.js b/examples/clipboardExample.js index c6864a91b3..8afe5ad315 100644 --- a/examples/clipboardExample.js +++ b/examples/clipboardExample.js @@ -32,7 +32,7 @@ function keyPressEvent(event) { } function keyReleaseEvent(event) { - var debug = false; + var debug = true; if (debug) { printKeyEvent("keyReleaseEvent", event); } @@ -54,9 +54,14 @@ function keyReleaseEvent(event) { print("the DELETE/BACKSPACE key was pressed"); Clipboard.deleteVoxels(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); } - if ((event.key == 199 || event.key == 67 || event.text == "C" || event.text == "c") && event.isAlt) { - print("the Alt+C key was pressed"); - Clipboard.copyVoxels(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + + if ((event.text == "E" || event.text == "e") && event.isMeta) { + print("the Ctl+E key was pressed"); + Clipboard.exportVoxels(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + } + if ((event.text == "I" || event.text == "i") && event.isMeta) { + print("the Ctl+I key was pressed"); + Clipboard.importVoxels(); } } From f6fba54dda963cae9284f5a3b4ee18735886308a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 19 Feb 2014 17:49:00 -0800 Subject: [PATCH 69/83] improved text mapping in keyboard events --- libraries/script-engine/src/EventTypes.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libraries/script-engine/src/EventTypes.cpp b/libraries/script-engine/src/EventTypes.cpp index d0ba160add..b06e53e0dd 100644 --- a/libraries/script-engine/src/EventTypes.cpp +++ b/libraries/script-engine/src/EventTypes.cpp @@ -104,6 +104,16 @@ KeyEvent::KeyEvent(const QKeyEvent& event) { text = "HELP"; } else if (key == Qt::Key_CapsLock) { text = "CAPS LOCK"; + } else if (key >= Qt::Key_A && key <= Qt::Key_Z && (isMeta || isControl || isAlt)) { + // this little bit of hacker will fix the text character keys like a-z in cases of control/alt/meta where + // qt doesn't always give you the key characters and will sometimes give you crazy non-printable characters + const int lowerCaseAdjust = 0x20; + QString unicode; + if (isShifted) { + text = QString(QChar(key)); + } else { + text = QString(QChar(key + lowerCaseAdjust)); + } } } From 91d79f65f203839c200d422d973873c7213b228d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 19 Feb 2014 17:57:28 -0800 Subject: [PATCH 70/83] fix crash on import from JS --- examples/clipboardExample.js | 4 ++-- interface/src/ClipboardScriptingInterface.cpp | 4 +++- libraries/script-engine/src/EventTypes.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/clipboardExample.js b/examples/clipboardExample.js index 8afe5ad315..e468c7ab95 100644 --- a/examples/clipboardExample.js +++ b/examples/clipboardExample.js @@ -25,14 +25,14 @@ function printKeyEvent(eventName, event) { function keyPressEvent(event) { - var debug = true; + var debug = false; if (debug) { printKeyEvent("keyPressEvent", event); } } function keyReleaseEvent(event) { - var debug = true; + var debug = false; if (debug) { printKeyEvent("keyReleaseEvent", event); } diff --git a/interface/src/ClipboardScriptingInterface.cpp b/interface/src/ClipboardScriptingInterface.cpp index c2a1a945a1..7faedd1bce 100644 --- a/interface/src/ClipboardScriptingInterface.cpp +++ b/interface/src/ClipboardScriptingInterface.cpp @@ -50,10 +50,12 @@ void ClipboardScriptingInterface::exportVoxels(float x, float y, float z, float z / (float)TREE_SCALE, s / (float)TREE_SCALE }; + // TODO: should we be calling invokeMethod() in all these cases? Application::getInstance()->exportVoxels(sourceVoxel); } void ClipboardScriptingInterface::importVoxels() { - Application::getInstance()->importVoxels(); + QMetaObject::invokeMethod(Application::getInstance(), "importVoxels"); } + diff --git a/libraries/script-engine/src/EventTypes.cpp b/libraries/script-engine/src/EventTypes.cpp index b06e53e0dd..c8451d84a7 100644 --- a/libraries/script-engine/src/EventTypes.cpp +++ b/libraries/script-engine/src/EventTypes.cpp @@ -105,7 +105,7 @@ KeyEvent::KeyEvent(const QKeyEvent& event) { } else if (key == Qt::Key_CapsLock) { text = "CAPS LOCK"; } else if (key >= Qt::Key_A && key <= Qt::Key_Z && (isMeta || isControl || isAlt)) { - // this little bit of hacker will fix the text character keys like a-z in cases of control/alt/meta where + // this little bit of hackery will fix the text character keys like a-z in cases of control/alt/meta where // qt doesn't always give you the key characters and will sometimes give you crazy non-printable characters const int lowerCaseAdjust = 0x20; QString unicode; From 0e8cab7349aa49d80e0c512ffba8b4088c7d2a4b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 19 Feb 2014 20:09:35 -0800 Subject: [PATCH 71/83] added Clipboard.nudgeVoxel() and added support for calling clipboard opertations with VoxelDetail as well as xyzs --- examples/clipboardExample.js | 14 +++--- interface/src/Application.cpp | 12 +++--- interface/src/Application.h | 1 + interface/src/ClipboardScriptingInterface.cpp | 43 ++++++++++++++++--- interface/src/ClipboardScriptingInterface.h | 22 +++++++--- 5 files changed, 72 insertions(+), 20 deletions(-) diff --git a/examples/clipboardExample.js b/examples/clipboardExample.js index e468c7ab95..81f0daae10 100644 --- a/examples/clipboardExample.js +++ b/examples/clipboardExample.js @@ -40,29 +40,33 @@ function keyReleaseEvent(event) { // Note: this sample uses Alt+ as the key codes for these clipboard items if ((event.key == 199 || event.key == 67 || event.text == "C" || event.text == "c") && event.isAlt) { print("the Alt+C key was pressed"); - Clipboard.copyVoxels(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + Clipboard.copyVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); } if ((event.key == 8776 || event.key == 88 || event.text == "X" || event.text == "x") && event.isAlt) { print("the Alt+X key was pressed"); - Clipboard.cutVoxels(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + Clipboard.cutVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); } if ((event.key == 8730 || event.key == 86 || event.text == "V" || event.text == "v") && event.isAlt) { print("the Alt+V key was pressed"); - Clipboard.pasteVoxels(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + Clipboard.pasteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); } if (event.text == "DELETE" || event.text == "BACKSPACE") { print("the DELETE/BACKSPACE key was pressed"); - Clipboard.deleteVoxels(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + Clipboard.deleteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); } if ((event.text == "E" || event.text == "e") && event.isMeta) { print("the Ctl+E key was pressed"); - Clipboard.exportVoxels(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + Clipboard.exportVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); } if ((event.text == "I" || event.text == "i") && event.isMeta) { print("the Ctl+I key was pressed"); Clipboard.importVoxels(); } + if ((event.key == 78 || event.text == "N" || event.text == "n") && event.isMeta) { + print("the Ctl+N key was pressed, nudging to left 1 meter"); + Clipboard.nudgeVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s, { x: -1, y: 0, z: 0 }); + } } // Map keyPress and mouse move events to our callbacks diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index faa0a9cff0..dfd98863a7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1847,12 +1847,14 @@ void Application::nudgeVoxels() { // calculate nudgeVec glm::vec3 nudgeVec(_nudgeGuidePosition.x - _nudgeVoxel.x, _nudgeGuidePosition.y - _nudgeVoxel.y, _nudgeGuidePosition.z - _nudgeVoxel.z); - VoxelTreeElement* nodeToNudge = _voxels.getVoxelAt(_nudgeVoxel.x, _nudgeVoxel.y, _nudgeVoxel.z, _nudgeVoxel.s); + nudgeVoxelsByVector(_nudgeVoxel, nudgeVec); + } +} - if (nodeToNudge) { - _voxels.getTree()->nudgeSubTree(nodeToNudge, nudgeVec, _voxelEditSender); - _nudgeStarted = false; - } +void Application::nudgeVoxelsByVector(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec) { + VoxelTreeElement* nodeToNudge = _voxels.getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); + if (nodeToNudge) { + _voxels.getTree()->nudgeSubTree(nodeToNudge, nudgeVec, _voxelEditSender); } } diff --git a/interface/src/Application.h b/interface/src/Application.h index d5e1e25f62..abe51b8bb1 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -240,6 +240,7 @@ public slots: void pasteVoxels(const VoxelDetail& sourceVoxel); void deleteVoxels(const VoxelDetail& sourceVoxel); void exportVoxels(const VoxelDetail& sourceVoxel); + void nudgeVoxelsByVector(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec); void setRenderVoxels(bool renderVoxels); void doKillLocalVoxels(); diff --git a/interface/src/ClipboardScriptingInterface.cpp b/interface/src/ClipboardScriptingInterface.cpp index 7faedd1bce..644ea84cdb 100644 --- a/interface/src/ClipboardScriptingInterface.cpp +++ b/interface/src/ClipboardScriptingInterface.cpp @@ -11,7 +11,11 @@ ClipboardScriptingInterface::ClipboardScriptingInterface() { } -void ClipboardScriptingInterface::cutVoxels(float x, float y, float z, float s) { +void ClipboardScriptingInterface::cutVoxel(const VoxelDetail& sourceVoxel) { + cutVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); +} + +void ClipboardScriptingInterface::cutVoxel(float x, float y, float z, float s) { VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE, @@ -19,7 +23,11 @@ void ClipboardScriptingInterface::cutVoxels(float x, float y, float z, float s) Application::getInstance()->cutVoxels(sourceVoxel); } -void ClipboardScriptingInterface::copyVoxels(float x, float y, float z, float s) { +void ClipboardScriptingInterface::copyVoxel(const VoxelDetail& sourceVoxel) { + copyVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); +} + +void ClipboardScriptingInterface::copyVoxel(float x, float y, float z, float s) { VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE, @@ -27,7 +35,11 @@ void ClipboardScriptingInterface::copyVoxels(float x, float y, float z, float s) Application::getInstance()->copyVoxels(sourceVoxel); } -void ClipboardScriptingInterface::pasteVoxels(float x, float y, float z, float s) { +void ClipboardScriptingInterface::pasteVoxel(const VoxelDetail& destinationVoxel) { + pasteVoxel(destinationVoxel.x, destinationVoxel.y, destinationVoxel.z, destinationVoxel.s); +} + +void ClipboardScriptingInterface::pasteVoxel(float x, float y, float z, float s) { VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE, @@ -36,7 +48,11 @@ void ClipboardScriptingInterface::pasteVoxels(float x, float y, float z, float s Application::getInstance()->pasteVoxels(sourceVoxel); } -void ClipboardScriptingInterface::deleteVoxels(float x, float y, float z, float s) { +void ClipboardScriptingInterface::deleteVoxel(const VoxelDetail& sourceVoxel) { + deleteVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); +} + +void ClipboardScriptingInterface::deleteVoxel(float x, float y, float z, float s) { VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE, @@ -44,7 +60,11 @@ void ClipboardScriptingInterface::deleteVoxels(float x, float y, float z, float Application::getInstance()->deleteVoxels(sourceVoxel); } -void ClipboardScriptingInterface::exportVoxels(float x, float y, float z, float s) { +void ClipboardScriptingInterface::exportVoxel(const VoxelDetail& sourceVoxel) { + exportVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); +} + +void ClipboardScriptingInterface::exportVoxel(float x, float y, float z, float s) { VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE, @@ -58,4 +78,17 @@ void ClipboardScriptingInterface::importVoxels() { QMetaObject::invokeMethod(Application::getInstance(), "importVoxels"); } +void ClipboardScriptingInterface::nudgeVoxel(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec) { + nudgeVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s, nudgeVec); +} + +void ClipboardScriptingInterface::nudgeVoxel(float x, float y, float z, float s, const glm::vec3& nudgeVec) { + glm::vec3 nudgeVecInTreeSpace = nudgeVec / (float)TREE_SCALE; + VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, + y / (float)TREE_SCALE, + z / (float)TREE_SCALE, + s / (float)TREE_SCALE }; + + Application::getInstance()->nudgeVoxelsByVector(sourceVoxel, nudgeVecInTreeSpace); +} diff --git a/interface/src/ClipboardScriptingInterface.h b/interface/src/ClipboardScriptingInterface.h index 0b2908f173..99747f56f6 100644 --- a/interface/src/ClipboardScriptingInterface.h +++ b/interface/src/ClipboardScriptingInterface.h @@ -19,13 +19,25 @@ public: ClipboardScriptingInterface(); public slots: - void cutVoxels(float x, float y, float z, float s); - void copyVoxels(float x, float y, float z, float s); - void pasteVoxels(float x, float y, float z, float s); - void deleteVoxels(float x, float y, float z, float s); + void cutVoxel(const VoxelDetail& sourceVoxel); + void cutVoxel(float x, float y, float z, float s); + + void copyVoxel(const VoxelDetail& sourceVoxel); + void copyVoxel(float x, float y, float z, float s); + + void pasteVoxel(const VoxelDetail& destinationVoxel); + void pasteVoxel(float x, float y, float z, float s); + + void deleteVoxel(const VoxelDetail& sourceVoxel); + void deleteVoxel(float x, float y, float z, float s); + + void exportVoxel(const VoxelDetail& sourceVoxel); + void exportVoxel(float x, float y, float z, float s); - void exportVoxels(float x, float y, float z, float s); void importVoxels(); + + void nudgeVoxel(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec); + void nudgeVoxel(float x, float y, float z, float s, const glm::vec3& nudgeVec); }; #endif // __interface__Clipboard__ From f506c215907042a731209b86a2ace812cb247415 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 19 Feb 2014 20:57:58 -0800 Subject: [PATCH 72/83] add line preview mode to editVoxels.js and make that the default mode --- examples/editVoxels.js | 295 +++++++++++++++++++++++++++++++---------- 1 file changed, 224 insertions(+), 71 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index c67ff0dcfa..f5d8612be9 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -72,6 +72,10 @@ audioOptions.volume = 0.5; var editToolsOn = false; // starts out off +// previewAsVoxel - by default, we will preview adds/deletes/recolors as just 4 lines on the intersecting face. But if you +// the preview to show a full voxel then set this to true and the voxel will be displayed for voxel editing +var previewAsVoxel = false; + var voxelPreview = Overlays.addOverlay("cube", { position: { x: 0, y: 0, z: 0}, size: 1, @@ -81,6 +85,42 @@ var voxelPreview = Overlays.addOverlay("cube", { visible: false, lineWidth: 4 }); + +var linePreviewTop = Overlays.addOverlay("line3d", { + position: { x: 0, y: 0, z: 0}, + end: { x: 0, y: 0, z: 0}, + color: { red: 255, green: 255, blue: 255}, + alpha: 1, + visible: false, + lineWidth: 1 + }); + +var linePreviewBottom = Overlays.addOverlay("line3d", { + position: { x: 0, y: 0, z: 0}, + end: { x: 0, y: 0, z: 0}, + color: { red: 255, green: 255, blue: 255}, + alpha: 1, + visible: false, + lineWidth: 1 + }); + +var linePreviewLeft = Overlays.addOverlay("line3d", { + position: { x: 0, y: 0, z: 0}, + end: { x: 0, y: 0, z: 0}, + color: { red: 255, green: 255, blue: 255}, + alpha: 1, + visible: false, + lineWidth: 1 + }); + +var linePreviewRight = Overlays.addOverlay("line3d", { + position: { x: 0, y: 0, z: 0}, + end: { x: 0, y: 0, z: 0}, + color: { red: 255, green: 255, blue: 255}, + alpha: 1, + visible: false, + lineWidth: 1 + }); // These will be our "overlay IDs" @@ -146,83 +186,186 @@ var trackAsDelete = false; var trackAsRecolor = false; function showPreviewVoxel() { - if (editToolsOn) { - var voxelColor; + var voxelColor; - var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); - var intersection = Voxels.findRayIntersection(pickRay); + var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); + var intersection = Voxels.findRayIntersection(pickRay); - if (whichColor == -1) { - // Copy mode - use clicked voxel color - voxelColor = { red: intersection.voxel.red, - green: intersection.voxel.green, - blue: intersection.voxel.blue }; - } else { - voxelColor = { red: colors[whichColor].red, - green: colors[whichColor].green, - blue: colors[whichColor].blue }; + if (whichColor == -1) { + // Copy mode - use clicked voxel color + voxelColor = { red: intersection.voxel.red, + green: intersection.voxel.green, + blue: intersection.voxel.blue }; + } else { + voxelColor = { red: colors[whichColor].red, + green: colors[whichColor].green, + blue: colors[whichColor].blue }; + } + + var guidePosition; + + if (trackAsDelete) { + guidePosition = { x: intersection.voxel.x, + y: intersection.voxel.y, + z: intersection.voxel.z }; + + Overlays.editOverlay(voxelPreview, { + position: guidePosition, + size: intersection.voxel.s, + visible: true, + color: { red: 255, green: 0, blue: 0 }, + solid: false, + alpha: 1 + }); + } else if (trackAsRecolor) { + guidePosition = { x: intersection.voxel.x - 0.001, + y: intersection.voxel.y - 0.001, + z: intersection.voxel.z - 0.001 }; + + Overlays.editOverlay(voxelPreview, { + position: guidePosition, + size: intersection.voxel.s + 0.002, + visible: true, + color: voxelColor, + solid: true, + alpha: 0.8 + }); + } else if (!isExtruding) { + guidePosition = { x: intersection.voxel.x, + y: intersection.voxel.y, + z: intersection.voxel.z }; + + if (intersection.face == "MIN_X_FACE") { + guidePosition.x -= intersection.voxel.s; + } else if (intersection.face == "MAX_X_FACE") { + guidePosition.x += intersection.voxel.s; + } else if (intersection.face == "MIN_Y_FACE") { + guidePosition.y -= intersection.voxel.s; + } else if (intersection.face == "MAX_Y_FACE") { + guidePosition.y += intersection.voxel.s; + } else if (intersection.face == "MIN_Z_FACE") { + guidePosition.z -= intersection.voxel.s; + } else if (intersection.face == "MAX_Z_FACE") { + guidePosition.z += intersection.voxel.s; } - var guidePosition; - - if (trackAsDelete) { - guidePosition = { x: intersection.voxel.x, - y: intersection.voxel.y, - z: intersection.voxel.z }; - Overlays.editOverlay(voxelPreview, { - position: guidePosition, - size: intersection.voxel.s, - visible: true, - color: { red: 255, green: 0, blue: 0 }, - solid: false, - alpha: 1 - }); - } else if (trackAsRecolor) { - guidePosition = { x: intersection.voxel.x - 0.001, - y: intersection.voxel.y - 0.001, - z: intersection.voxel.z - 0.001 }; + Overlays.editOverlay(voxelPreview, { + position: guidePosition, + size: intersection.voxel.s, + visible: true, + color: voxelColor, + solid: true, + alpha: 0.7 + }); + } else if (isExtruding) { + Overlays.editOverlay(voxelPreview, { visible: false }); + } +} - Overlays.editOverlay(voxelPreview, { - position: guidePosition, - size: intersection.voxel.s + 0.002, - visible: true, - color: voxelColor, - solid: true, - alpha: 0.8 - }); - } else if (!isExtruding) { - guidePosition = { x: intersection.voxel.x, - y: intersection.voxel.y, - z: intersection.voxel.z }; - - if (intersection.face == "MIN_X_FACE") { - guidePosition.x -= intersection.voxel.s; - } else if (intersection.face == "MAX_X_FACE") { - guidePosition.x += intersection.voxel.s; - } else if (intersection.face == "MIN_Y_FACE") { - guidePosition.y -= intersection.voxel.s; - } else if (intersection.face == "MAX_Y_FACE") { - guidePosition.y += intersection.voxel.s; - } else if (intersection.face == "MIN_Z_FACE") { - guidePosition.z -= intersection.voxel.s; - } else if (intersection.face == "MAX_Z_FACE") { - guidePosition.z += intersection.voxel.s; - } +function showPreviewLines() { + var voxelColor; - Overlays.editOverlay(voxelPreview, { - position: guidePosition, - size: intersection.voxel.s, - visible: true, - color: voxelColor, - solid: true, - alpha: 0.7 - }); - } else if (isExtruding) { + var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); + var intersection = Voxels.findRayIntersection(pickRay); + + if (intersection.intersects) { + + // TODO: add support for changing size here + var previewVoxelSize = intersection.voxel.s; + + var x = Math.floor(intersection.intersection.x / previewVoxelSize) * previewVoxelSize; + var y = Math.floor(intersection.intersection.y / previewVoxelSize) * previewVoxelSize; + var z = Math.floor(intersection.intersection.z / previewVoxelSize) * previewVoxelSize; + previewVoxel = { x: x, y: y, z: z, s: previewVoxelSize }; + + var bottomLeft; + var bottomRight; + var topLeft; + var topRight; + + if (intersection.face == "MIN_X_FACE") { + + bottomLeft = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; + bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s }; + topLeft = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z }; + topRight = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z + previewVoxel.s }; + + } else if (intersection.face == "MAX_X_FACE") { + + // because we intersected with the MAX_X face, our previewVoxel will be the voxel to the +X side of the + // voxel we intersect, so we don't need to adjust the x coordinates + bottomLeft = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; + bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s }; + topLeft = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z }; + topRight = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z + previewVoxel.s }; + + } else if (intersection.face == "MIN_Y_FACE") { + + bottomLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z }; + bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; + topLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s}; + topRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s}; + + } else if (intersection.face == "MAX_Y_FACE") { + + bottomLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z }; + bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; + topLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s}; + topRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s}; + + } else if (intersection.face == "MIN_Z_FACE") { + + bottomLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z }; + bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; + topLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z}; + topRight = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z}; + + } else if (intersection.face == "MAX_Z_FACE") { + + bottomLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z }; + bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; + topLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z}; + topRight = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z}; + + } + + Overlays.editOverlay(linePreviewTop, { position: topLeft, end: topRight, visible: true }); + Overlays.editOverlay(linePreviewBottom, { position: bottomLeft, end: bottomRight, visible: true }); + Overlays.editOverlay(linePreviewLeft, { position: topLeft, end: bottomLeft, visible: true }); + Overlays.editOverlay(linePreviewRight, { position: topRight, end: bottomRight, visible: true }); + + } else { + Overlays.editOverlay(linePreviewTop, { visible: false }); + Overlays.editOverlay(linePreviewBottom, { visible: false }); + Overlays.editOverlay(linePreviewLeft, { visible: false }); + Overlays.editOverlay(linePreviewRight, { visible: false }); + } +} + +function showPreviewGuides() { + if (editToolsOn) { + if (previewAsVoxel) { + showPreviewVoxel(); + + // make sure alternative is hidden + Overlays.editOverlay(linePreviewTop, { visible: false }); + Overlays.editOverlay(linePreviewBottom, { visible: false }); + Overlays.editOverlay(linePreviewLeft, { visible: false }); + Overlays.editOverlay(linePreviewRight, { visible: false }); + } else { + showPreviewLines(); + + // make sure alternative is hidden Overlays.editOverlay(voxelPreview, { visible: false }); } } else { + // make sure all previews are off Overlays.editOverlay(voxelPreview, { visible: false }); + Overlays.editOverlay(linePreviewTop, { visible: false }); + Overlays.editOverlay(linePreviewBottom, { visible: false }); + Overlays.editOverlay(linePreviewLeft, { visible: false }); + Overlays.editOverlay(linePreviewRight, { visible: false }); } } @@ -231,24 +374,24 @@ function trackMouseEvent(event) { trackLastMouseY = event.y; trackAsDelete = event.isControl; trackAsRecolor = event.isShifted; - showPreviewVoxel(); + showPreviewGuides(); } function trackKeyPressEvent(event) { if (event.text == "CONTROL") { trackAsDelete = true; - showPreviewVoxel(); + showPreviewGuides(); } if (event.text == "SHIFT") { trackAsRecolor = true; } - showPreviewVoxel(); + showPreviewGuides(); } function trackKeyReleaseEvent(event) { if (event.text == "CONTROL") { trackAsDelete = false; - showPreviewVoxel(); + showPreviewGuides(); } if (event.text == "SHIFT") { trackAsRecolor = false; @@ -260,7 +403,13 @@ function trackKeyReleaseEvent(event) { moveTools(); Audio.playSound(clickSound, audioOptions); } - showPreviewVoxel(); + + // on F1 toggle the preview mode between cubes and lines + if (event.text == "F1") { + previewAsVoxel = !previewAsVoxel; + } + + showPreviewGuides(); } function mousePressEvent(event) { @@ -533,6 +682,10 @@ Controller.keyReleaseEvent.connect(keyReleaseEvent); function scriptEnding() { Overlays.deleteOverlay(voxelPreview); + Overlays.deleteOverlay(linePreviewTop); + Overlays.deleteOverlay(linePreviewBottom); + Overlays.deleteOverlay(linePreviewLeft); + Overlays.deleteOverlay(linePreviewRight); for (s = 0; s < numColors; s++) { Overlays.deleteOverlay(swatches[s]); } From cbf1b095524d5e4ee4f93204f5f6cb73079013ae Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 19 Feb 2014 21:07:52 -0800 Subject: [PATCH 73/83] fix small bug in line preview mode --- examples/editVoxels.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index f5d8612be9..db6091f245 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -271,8 +271,9 @@ function showPreviewLines() { if (intersection.intersects) { - // TODO: add support for changing size here - var previewVoxelSize = intersection.voxel.s; + // TODO: add support for changing size here, if you set this size to any arbitrary size, + // the preview should correctly handle it + var previewVoxelSize = intersection.voxel.s; var x = Math.floor(intersection.intersection.x / previewVoxelSize) * previewVoxelSize; var y = Math.floor(intersection.intersection.y / previewVoxelSize) * previewVoxelSize; @@ -285,16 +286,14 @@ function showPreviewLines() { var topRight; if (intersection.face == "MIN_X_FACE") { - + previewVoxel.x = Math.floor(intersection.voxel.x / previewVoxelSize) * previewVoxelSize; bottomLeft = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s }; topLeft = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z }; topRight = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z + previewVoxel.s }; } else if (intersection.face == "MAX_X_FACE") { - - // because we intersected with the MAX_X face, our previewVoxel will be the voxel to the +X side of the - // voxel we intersect, so we don't need to adjust the x coordinates + previewVoxel.x = Math.floor((intersection.voxel.x + intersection.voxel.s) / previewVoxelSize) * previewVoxelSize; bottomLeft = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s }; topLeft = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z }; @@ -302,6 +301,7 @@ function showPreviewLines() { } else if (intersection.face == "MIN_Y_FACE") { + previewVoxel.y = Math.floor(intersection.voxel.y / previewVoxelSize) * previewVoxelSize; bottomLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z }; bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; topLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s}; @@ -309,6 +309,7 @@ function showPreviewLines() { } else if (intersection.face == "MAX_Y_FACE") { + previewVoxel.y = Math.floor((intersection.voxel.y + intersection.voxel.s) / previewVoxelSize) * previewVoxelSize; bottomLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z }; bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; topLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s}; @@ -316,6 +317,7 @@ function showPreviewLines() { } else if (intersection.face == "MIN_Z_FACE") { + previewVoxel.z = Math.floor(intersection.voxel.z / previewVoxelSize) * previewVoxelSize; bottomLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z }; bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; topLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z}; @@ -323,6 +325,7 @@ function showPreviewLines() { } else if (intersection.face == "MAX_Z_FACE") { + previewVoxel.z = Math.floor((intersection.voxel.z + intersection.voxel.s) / previewVoxelSize) * previewVoxelSize; bottomLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z }; bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; topLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z}; From 61d9ea44af782f06b15ffc75f7b7922400941af5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 19 Feb 2014 22:17:19 -0800 Subject: [PATCH 74/83] add tool palette and eye dropper mode --- examples/editVoxels.js | 149 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 143 insertions(+), 6 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index db6091f245..d15c9d33d9 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -155,6 +155,68 @@ for (s = 0; s < numColors; s++) { } +// These will be our tool palette overlays +var numberOfTools = 5; +var toolHeight = 40; +var toolWidth = 62; +var toolsHeight = toolHeight * numberOfTools; +var toolsX = 0; +var toolsY = (windowDimensions.y - toolsHeight) / 2; + +var addToolAt = 0; +var deleteToolAt = 1; +var recolorToolAt = 2; +var eyedropperToolAt = 3; +var selectToolAt = 4; +var toolSelectedColor = { red: 255, green: 255, blue: 255 }; +var notSelectedColor = { red: 128, green: 128, blue: 128 }; + +var addTool = Overlays.addOverlay("image", { + x: 0, y: 0, width: toolWidth, height: toolHeight, + subImage: { x: 0, y: toolHeight * addToolAt, width: toolWidth, height: toolHeight }, + imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg", + color: toolSelectedColor, + visible: false, + alpha: 0.9 + }); + +var deleteTool = Overlays.addOverlay("image", { + x: 0, y: 0, width: toolWidth, height: toolHeight, + subImage: { x: 0, y: toolHeight * deleteToolAt, width: toolWidth, height: toolHeight }, + imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg", + color: toolSelectedColor, + visible: false, + alpha: 0.9 + }); + +var recolorTool = Overlays.addOverlay("image", { + x: 0, y: 0, width: toolWidth, height: toolHeight, + subImage: { x: 0, y: toolHeight * recolorToolAt, width: toolWidth, height: toolHeight }, + imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg", + color: toolSelectedColor, + visible: false, + alpha: 0.9 + }); + +var eyedropperTool = Overlays.addOverlay("image", { + x: 0, y: 0, width: toolWidth, height: toolHeight, + subImage: { x: 0, y: toolHeight * eyedropperToolAt, width: toolWidth, height: toolHeight }, + imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg", + color: toolSelectedColor, + visible: false, + alpha: 0.9 + }); + +var selectTool = Overlays.addOverlay("image", { + x: 0, y: 0, width: toolWidth, height: toolHeight, + subImage: { x: 0, y: toolHeight * selectToolAt, width: toolWidth, height: toolHeight }, + imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg", + color: toolSelectedColor, + visible: false, + alpha: 0.9 + }); + + function setAudioPosition() { var camera = Camera.getPosition(); var forwardVector = Quat.getFront(MyAvatar.orientation); @@ -184,6 +246,7 @@ var trackLastMouseX = 0; var trackLastMouseY = 0; var trackAsDelete = false; var trackAsRecolor = false; +var trackAsEyedropper = false; function showPreviewVoxel() { var voxelColor; @@ -217,7 +280,7 @@ function showPreviewVoxel() { solid: false, alpha: 1 }); - } else if (trackAsRecolor) { + } else if (trackAsRecolor || trackAsEyedropper) { guidePosition = { x: intersection.voxel.x - 0.001, y: intersection.voxel.y - 0.001, z: intersection.voxel.z - 0.001 }; @@ -264,7 +327,6 @@ function showPreviewVoxel() { function showPreviewLines() { - var voxelColor; var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); var intersection = Voxels.findRayIntersection(pickRay); @@ -377,16 +439,22 @@ function trackMouseEvent(event) { trackLastMouseY = event.y; trackAsDelete = event.isControl; trackAsRecolor = event.isShifted; + trackAsEyedropper = event.isMeta; showPreviewGuides(); } function trackKeyPressEvent(event) { if (event.text == "CONTROL") { trackAsDelete = true; - showPreviewGuides(); + moveTools(); } if (event.text == "SHIFT") { trackAsRecolor = true; + moveTools(); + } + if (event.text == "META") { + trackAsEyedropper = true; + moveTools(); } showPreviewGuides(); } @@ -394,10 +462,15 @@ function trackKeyPressEvent(event) { function trackKeyReleaseEvent(event) { if (event.text == "CONTROL") { trackAsDelete = false; - showPreviewGuides(); + moveTools(); } if (event.text == "SHIFT") { trackAsRecolor = false; + moveTools(); + } + if (event.text == "META") { + trackAsEyedropper = false; + moveTools(); } // on TAB release, toggle our tool state @@ -447,12 +520,21 @@ function mousePressEvent(event) { orbitAzimuth = Math.atan2(orbitVector.z, orbitVector.x); orbitAltitude = Math.asin(orbitVector.y / Vec3.length(orbitVector)); - } else if (trackAsDelete || event.isRightButton) { + } else if (trackAsDelete || (event.isRightButton && !trackAsEyedropper)) { // Delete voxel Voxels.eraseVoxel(intersection.voxel.x, intersection.voxel.y, intersection.voxel.z, intersection.voxel.s); Audio.playSound(deleteSound, audioOptions); Overlays.editOverlay(voxelPreview, { visible: false }); - + } else if (trackAsEyedropper) { + + print("Grab color!!!"); + if (whichColor != -1) { + colors[whichColor].red = intersection.voxel.red; + colors[whichColor].green = intersection.voxel.green; + colors[whichColor].blue = intersection.voxel.blue; + moveTools(); + } + } else if (trackAsRecolor) { // Recolor Voxel Voxels.setVoxel(intersection.voxel.x, @@ -643,6 +725,7 @@ function mouseReleaseEvent(event) { } function moveTools() { + // move the swatches swatchesX = (windowDimensions.x - swatchesWidth) / 2; swatchesY = windowDimensions.y - swatchHeight; @@ -665,6 +748,55 @@ function moveTools() { visible: editToolsOn }); } + + // move the tools + toolsY = (windowDimensions.y - toolsHeight) / 2; + addToolColor = notSelectedColor; + deleteToolColor = notSelectedColor; + recolorToolColor = notSelectedColor; + eyedropperToolColor = notSelectedColor; + selectToolColor = notSelectedColor; + + if (trackAsDelete) { + deleteToolColor = toolSelectedColor; + } else if (trackAsRecolor) { + recolorToolColor = toolSelectedColor; + } else if (trackAsEyedropper) { + eyedropperToolColor = toolSelectedColor; + } else { + addToolColor = toolSelectedColor; + } + + Overlays.editOverlay(addTool, { + x: 0, y: toolsY + (toolHeight * addToolAt), width: toolWidth, height: toolHeight, + color: addToolColor, + visible: editToolsOn + }); + + Overlays.editOverlay(deleteTool, { + x: 0, y: toolsY + (toolHeight * deleteToolAt), width: toolWidth, height: toolHeight, + color: deleteToolColor, + visible: editToolsOn + }); + + Overlays.editOverlay(recolorTool, { + x: 0, y: toolsY + (toolHeight * recolorToolAt), width: toolWidth, height: toolHeight, + color: recolorToolColor, + visible: editToolsOn + }); + + Overlays.editOverlay(eyedropperTool, { + x: 0, y: toolsY + (toolHeight * eyedropperToolAt), width: toolWidth, height: toolHeight, + color: eyedropperToolColor, + visible: editToolsOn + }); + + Overlays.editOverlay(selectTool, { + x: 0, y: toolsY + (toolHeight * selectToolAt), width: toolWidth, height: toolHeight, + color: selectToolColor, + visible: editToolsOn + }); + } @@ -692,6 +824,11 @@ function scriptEnding() { for (s = 0; s < numColors; s++) { Overlays.deleteOverlay(swatches[s]); } + Overlays.deleteOverlay(addTool); + Overlays.deleteOverlay(deleteTool); + Overlays.deleteOverlay(recolorTool); + Overlays.deleteOverlay(eyedropperTool); + Overlays.deleteOverlay(selectTool); } Script.scriptEnding.connect(scriptEnding); From cbacf5f328ef4742a3268d5891edfc46d08cd2b4 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 19 Feb 2014 22:30:28 -0800 Subject: [PATCH 75/83] correctly draw tools when in orbit mode --- examples/editVoxels.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index d15c9d33d9..eea5faf1fc 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -247,6 +247,7 @@ var trackLastMouseY = 0; var trackAsDelete = false; var trackAsRecolor = false; var trackAsEyedropper = false; +var trackAsOrbit = false; function showPreviewVoxel() { var voxelColor; @@ -293,6 +294,8 @@ function showPreviewVoxel() { solid: true, alpha: 0.8 }); + } else if (trackAsOrbit) { + Overlays.editOverlay(voxelPreview, { visible: false }); } else if (!isExtruding) { guidePosition = { x: intersection.voxel.x, y: intersection.voxel.y, @@ -440,6 +443,7 @@ function trackMouseEvent(event) { trackAsDelete = event.isControl; trackAsRecolor = event.isShifted; trackAsEyedropper = event.isMeta; + trackAsOrbit = event.isAlt; showPreviewGuides(); } @@ -456,6 +460,10 @@ function trackKeyPressEvent(event) { trackAsEyedropper = true; moveTools(); } + if (event.text == "ALT") { + trackAsOrbit = true; + moveTools(); + } showPreviewGuides(); } @@ -472,6 +480,10 @@ function trackKeyReleaseEvent(event) { trackAsEyedropper = false; moveTools(); } + if (event.text == "ALT") { + trackAsOrbit = false; + moveTools(); + } // on TAB release, toggle our tool state if (event.text == "TAB") { @@ -763,6 +775,8 @@ function moveTools() { recolorToolColor = toolSelectedColor; } else if (trackAsEyedropper) { eyedropperToolColor = toolSelectedColor; + } else if (trackAsOrbit) { + // nothing gets selected in this case... } else { addToolColor = toolSelectedColor; } From 546ab51ed58f0165e4d528a8c06dafc9d927e093 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 19 Feb 2014 22:37:43 -0800 Subject: [PATCH 76/83] add click support to color swatchs in editVoxels.js --- examples/editVoxels.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index eea5faf1fc..82481a84e6 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -506,11 +506,23 @@ function mousePressEvent(event) { if (!editToolsOn) { return; } - - if (event.isRightButton) { - // debugging of right button click on mac... - print(">>>> RIGHT BUTTON <<<<<"); + + var clickedOnSwatch = false; + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + + // if the user clicked on one of the color swatches, update the selectedSwatch + for (s = 0; s < numColors; s++) { + if (clickedOverlay == swatches[s]) { + whichColor = s; + moveTools(); + clickedOnSwatch = true; + } } + if (clickedOnSwatch) { + return; // no further processing + } + + trackMouseEvent(event); // used by preview support mouseX = event.x; mouseY = event.y; From 66d757863cc673db0b42c9d03412b1cea9f0f364 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 19 Feb 2014 23:52:29 -0800 Subject: [PATCH 77/83] adding first cut at voxel size slider to editVoxels.js --- examples/editVoxels.js | 145 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 129 insertions(+), 16 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index 82481a84e6..001f74a563 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -123,12 +123,16 @@ var linePreviewRight = Overlays.addOverlay("line3d", { }); +// these will be used below +var sliderWidth = 158; +var sliderHeight = 35; + // These will be our "overlay IDs" var swatches = new Array(); var swatchHeight = 54; var swatchWidth = 31; var swatchesWidth = swatchWidth * numColors; -var swatchesX = (windowDimensions.x - swatchesWidth) / 2; +var swatchesX = (windowDimensions.x - (swatchesWidth + sliderWidth)) / 2; var swatchesY = windowDimensions.y - swatchHeight; // create the overlays, position them in a row, set their colors, and for the selected one, use a different source image @@ -215,6 +219,69 @@ var selectTool = Overlays.addOverlay("image", { visible: false, alpha: 0.9 }); + + +// This will create a couple of image overlays that make a "slider", we will demonstrate how to trap mouse messages to +// move the slider + +// see above... +//var sliderWidth = 158; +//var sliderHeight = 35; + +var sliderX = swatchesX + swatchesWidth; +var sliderY = windowDimensions.y - sliderHeight; +var slider = Overlays.addOverlay("image", { + // alternate form of expressing bounds + bounds: { x: sliderX, y: sliderY, width: sliderWidth, height: sliderHeight}, + imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/slider.png", + color: { red: 255, green: 255, blue: 255}, + alpha: 1, + visible: false + }); + + +// The slider is handled in the mouse event callbacks. +var isMovingSlider = false; +var thumbClickOffsetX = 0; + +// This is the thumb of our slider +var minThumbX = 30; // relative to the x of the slider +var maxThumbX = minThumbX + 65; +var thumbX = (minThumbX + maxThumbX) / 2; +var thumbY = sliderY + 9; +var thumb = Overlays.addOverlay("image", { + x: sliderX + thumbX, + y: thumbY, + width: 18, + height: 17, + imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png", + color: { red: 255, green: 255, blue: 255}, + alpha: 1, + visible: false + }); + +var pointerVoxelScale = 0; // this is the voxel scale used for click to add or delete +var pointerVoxelScaleSet = false; // if voxel scale has not yet been set, we use the intersection size + +var pointerVoxelScaleSteps = 10; // the number of slider position steps +var pointerVoxelScaleOriginStep = 4; // the position of slider for the 1 meter size voxel +var pointerVoxelScaleMin = Math.pow(2, (1-pointerVoxelScaleOriginStep)); +var pointerVoxelScaleMax = Math.pow(2, (pointerVoxelScaleSteps-pointerVoxelScaleOriginStep)); + +function calcThumbFromScale(scale) { + var scaleLog = Math.log(scale)/Math.log(2); + var thumbStep = scaleLog + pointerVoxelScaleOriginStep; + if (thumbStep < 1) { + thumbStep = 1; + } + if (thumbStep > pointerVoxelScaleSteps) { + thumbStep = pointerVoxelScaleSteps; + } + thumbX = (((maxThumbX - minThumbX) / pointerVoxelScaleSteps) * (thumbStep - 1)) + minThumbX; + Overlays.editOverlay(thumb, { x: thumbX + sliderX } ); +} + + function setAudioPosition() { @@ -255,6 +322,11 @@ function showPreviewVoxel() { var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); var intersection = Voxels.findRayIntersection(pickRay); + // if the user hasn't updated the + if (!pointerVoxelScaleSet) { + calcThumbFromScale(intersection.voxel.s); + } + if (whichColor == -1) { // Copy mode - use clicked voxel color voxelColor = { red: intersection.voxel.red, @@ -335,6 +407,11 @@ function showPreviewLines() { var intersection = Voxels.findRayIntersection(pickRay); if (intersection.intersects) { + + // if the user hasn't updated the + if (!pointerVoxelScaleSet) { + calcThumbFromScale(intersection.voxel.s); + } // TODO: add support for changing size here, if you set this size to any arbitrary size, // the preview should correctly handle it @@ -509,17 +586,24 @@ function mousePressEvent(event) { var clickedOnSwatch = false; var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - - // if the user clicked on one of the color swatches, update the selectedSwatch - for (s = 0; s < numColors; s++) { - if (clickedOverlay == swatches[s]) { - whichColor = s; - moveTools(); - clickedOnSwatch = true; - } - } - if (clickedOnSwatch) { + + // If the user clicked on the thumb, handle the slider logic + if (clickedOverlay == thumb) { + isMovingSlider = true; + thumbClickOffsetX = event.x - (sliderX + thumbX); // this should be the position of the mouse relative to the thumb return; // no further processing + } else { + // if the user clicked on one of the color swatches, update the selectedSwatch + for (s = 0; s < numColors; s++) { + if (clickedOverlay == swatches[s]) { + whichColor = s; + moveTools(); + clickedOnSwatch = true; + } + } + if (clickedOnSwatch) { + return; // no further processing + } } @@ -530,6 +614,11 @@ function mousePressEvent(event) { var intersection = Voxels.findRayIntersection(pickRay); audioOptions.position = Vec3.sum(pickRay.origin, pickRay.direction); if (intersection.intersects) { + // if the user hasn't updated the + if (!pointerVoxelScaleSet) { + calcThumbFromScale(intersection.voxel.s); + } + if (event.isAlt) { // start orbit camera! var cameraPosition = Camera.getPosition(); @@ -668,8 +757,21 @@ function keyReleaseEvent(event) { key_alt = false; key_shift = false; } + + function mouseMoveEvent(event) { - if (isOrbiting) { + if (isMovingSlider) { + thumbX = (event.x - thumbClickOffsetX) - sliderX; + if (thumbX < minThumbX) { + thumbX = minThumbX; + } + if (thumbX > maxThumbX) { + thumbX = maxThumbX; + } + // TODO: hook this up to the voxel size in some meaningful way + Overlays.editOverlay(thumb, { x: thumbX + sliderX } ); + + } else if (isOrbiting) { var cameraOrientation = Camera.getOrientation(); var origEulers = Quat.safeEulerAngles(cameraOrientation); var newEulers = fixEulerAngles(Quat.safeEulerAngles(cameraOrientation)); @@ -684,8 +786,7 @@ function mouseMoveEvent(event) { Camera.setPosition(orbitPosition); mouseX = event.x; mouseY = event.y; - } - if (isAdding) { + } else if (isAdding) { // Watch the drag direction to tell which way to 'extrude' this voxel if (!isExtruding) { var pickRay = Camera.computePickRay(event.x, event.y); @@ -734,6 +835,10 @@ function mouseReleaseEvent(event) { return; } + if (isMovingSlider) { + isMovingSlider = false; + } + if (isOrbiting) { var cameraOrientation = Camera.getOrientation(); var eulers = Quat.safeEulerAngles(cameraOrientation); @@ -750,7 +855,7 @@ function mouseReleaseEvent(event) { function moveTools() { // move the swatches - swatchesX = (windowDimensions.x - swatchesWidth) / 2; + swatchesX = (windowDimensions.x - (swatchesWidth + sliderWidth)) / 2; swatchesY = windowDimensions.y - swatchHeight; // create the overlays, position them in a row, set their colors, and for the selected one, use a different source image @@ -823,6 +928,15 @@ function moveTools() { visible: editToolsOn }); + + sliderX = swatchesX + swatchesWidth; + sliderY = windowDimensions.y - sliderHeight; + Overlays.editOverlay(slider, { x: sliderX, y: sliderY, visible: editToolsOn }); + + // This is the thumb of our slider + thumbY = sliderY + 9; + Overlays.editOverlay(thumb, { x: sliderX + thumbX, y: thumbY, visible: editToolsOn }); + } @@ -830,7 +944,6 @@ function update() { var newWindowDimensions = Controller.getViewportDimensions(); if (newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y) { windowDimensions = newWindowDimensions; - print("window resized..."); moveTools(); } } From 7cab5013cc5af2aaf8ed14a9e34e93d6ad4c4aea Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 20 Feb 2014 01:20:56 -0800 Subject: [PATCH 78/83] more work to wire up voxel size slider and +/- keys --- examples/editVoxels.js | 79 ++++++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 18 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index 001f74a563..8ac22413b3 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -247,6 +247,7 @@ var thumbClickOffsetX = 0; // This is the thumb of our slider var minThumbX = 30; // relative to the x of the slider var maxThumbX = minThumbX + 65; +var thumbExtents = maxThumbX - minThumbX; var thumbX = (minThumbX + maxThumbX) / 2; var thumbY = sliderY + 9; var thumb = Overlays.addOverlay("image", { @@ -263,10 +264,11 @@ var thumb = Overlays.addOverlay("image", { var pointerVoxelScale = 0; // this is the voxel scale used for click to add or delete var pointerVoxelScaleSet = false; // if voxel scale has not yet been set, we use the intersection size -var pointerVoxelScaleSteps = 10; // the number of slider position steps -var pointerVoxelScaleOriginStep = 4; // the position of slider for the 1 meter size voxel +var pointerVoxelScaleSteps = 8; // the number of slider position steps +var pointerVoxelScaleOriginStep = 3; // the position of slider for the 1 meter size voxel var pointerVoxelScaleMin = Math.pow(2, (1-pointerVoxelScaleOriginStep)); var pointerVoxelScaleMax = Math.pow(2, (pointerVoxelScaleSteps-pointerVoxelScaleOriginStep)); +var thumbDeltaPerStep = thumbExtents / (pointerVoxelScaleSteps - 1); function calcThumbFromScale(scale) { var scaleLog = Math.log(scale)/Math.log(2); @@ -277,12 +279,22 @@ function calcThumbFromScale(scale) { if (thumbStep > pointerVoxelScaleSteps) { thumbStep = pointerVoxelScaleSteps; } - thumbX = (((maxThumbX - minThumbX) / pointerVoxelScaleSteps) * (thumbStep - 1)) + minThumbX; + thumbX = (thumbDeltaPerStep * (thumbStep - 1)) + minThumbX; Overlays.editOverlay(thumb, { x: thumbX + sliderX } ); } - - +function calcScaleFromThumb(newThumbX) { + // newThumbX is the pixel location relative to start of slider, + // we need to figure out the actual offset in the allowed slider area + thumbAt = newThumbX - minThumbX; + thumbStep = Math.floor((thumbAt/ thumbExtents) * (pointerVoxelScaleSteps-1)) + 1; + pointerVoxelScale = Math.pow(2, (thumbStep-pointerVoxelScaleOriginStep)); + // now reset the display accordingly... + calcThumbFromScale(pointerVoxelScale); + + // if the user moved the thumb, then they are fixing the voxel scale + pointerVoxelScaleSet = true; +} function setAudioPosition() { var camera = Camera.getPosition(); @@ -326,6 +338,14 @@ function showPreviewVoxel() { if (!pointerVoxelScaleSet) { calcThumbFromScale(intersection.voxel.s); } + + var previewVoxelSize; + if (pointerVoxelScaleSet) { + previewVoxelSize = pointerVoxelScale; + } else { + previewVoxelSize = intersection.voxel.s; + } + if (whichColor == -1) { // Copy mode - use clicked voxel color @@ -347,7 +367,7 @@ function showPreviewVoxel() { Overlays.editOverlay(voxelPreview, { position: guidePosition, - size: intersection.voxel.s, + size: previewVoxelSize, visible: true, color: { red: 255, green: 0, blue: 0 }, solid: false, @@ -360,7 +380,7 @@ function showPreviewVoxel() { Overlays.editOverlay(voxelPreview, { position: guidePosition, - size: intersection.voxel.s + 0.002, + size: previewVoxelSize + 0.002, visible: true, color: voxelColor, solid: true, @@ -374,22 +394,22 @@ function showPreviewVoxel() { z: intersection.voxel.z }; if (intersection.face == "MIN_X_FACE") { - guidePosition.x -= intersection.voxel.s; + guidePosition.x -= previewVoxelSize; } else if (intersection.face == "MAX_X_FACE") { guidePosition.x += intersection.voxel.s; } else if (intersection.face == "MIN_Y_FACE") { - guidePosition.y -= intersection.voxel.s; + guidePosition.y -= previewVoxelSize; } else if (intersection.face == "MAX_Y_FACE") { guidePosition.y += intersection.voxel.s; } else if (intersection.face == "MIN_Z_FACE") { - guidePosition.z -= intersection.voxel.s; + guidePosition.z -= previewVoxelSize; } else if (intersection.face == "MAX_Z_FACE") { guidePosition.z += intersection.voxel.s; } Overlays.editOverlay(voxelPreview, { position: guidePosition, - size: intersection.voxel.s, + size: previewVoxelSize, visible: true, color: voxelColor, solid: true, @@ -415,7 +435,12 @@ function showPreviewLines() { // TODO: add support for changing size here, if you set this size to any arbitrary size, // the preview should correctly handle it - var previewVoxelSize = intersection.voxel.s; + var previewVoxelSize; + if (pointerVoxelScaleSet) { + previewVoxelSize = pointerVoxelScale; + } else { + previewVoxelSize = intersection.voxel.s; + } var x = Math.floor(intersection.intersection.x / previewVoxelSize) * previewVoxelSize; var y = Math.floor(intersection.intersection.y / previewVoxelSize) * previewVoxelSize; @@ -545,6 +570,17 @@ function trackKeyPressEvent(event) { } function trackKeyReleaseEvent(event) { + if (event.text == "ESC") { + pointerVoxelScaleSet = false; + } + if (event.text == "-") { + thumbX -= thumbDeltaPerStep; + calcScaleFromThumb(thumbX); + } + if (event.text == "+") { + thumbX += thumbDeltaPerStep; + calcScaleFromThumb(thumbX); + } if (event.text == "CONTROL") { trackAsDelete = false; moveTools(); @@ -618,6 +654,14 @@ function mousePressEvent(event) { if (!pointerVoxelScaleSet) { calcThumbFromScale(intersection.voxel.s); } + + // TODO: This would be a good place to use the "set" voxel size... but the add/delete/color logic below assumes that + // the "edit" size is the same as the intersect.voxel.s. So we need to fix that to really wire up the voxel size + // slider + var editVoxelSize = intersection.voxel.s; + if (pointerVoxelScaleSet) { + //editVoxelSize = pointerVoxelScale; + } if (event.isAlt) { // start orbit camera! @@ -635,7 +679,7 @@ function mousePressEvent(event) { } else if (trackAsDelete || (event.isRightButton && !trackAsEyedropper)) { // Delete voxel - Voxels.eraseVoxel(intersection.voxel.x, intersection.voxel.y, intersection.voxel.z, intersection.voxel.s); + Voxels.eraseVoxel(intersection.voxel.x, intersection.voxel.y, intersection.voxel.z, editVoxelSize); Audio.playSound(deleteSound, audioOptions); Overlays.editOverlay(voxelPreview, { visible: false }); } else if (trackAsEyedropper) { @@ -653,7 +697,7 @@ function mousePressEvent(event) { Voxels.setVoxel(intersection.voxel.x, intersection.voxel.y, intersection.voxel.z, - intersection.voxel.s, + editVoxelSize, colors[whichColor].red, colors[whichColor].green, colors[whichColor].blue); Audio.playSound(changeColorSound, audioOptions); Overlays.editOverlay(voxelPreview, { visible: false }); @@ -665,7 +709,7 @@ function mousePressEvent(event) { x: intersection.voxel.x, y: intersection.voxel.y, z: intersection.voxel.z, - s: intersection.voxel.s, + s: editVoxelSize, red: intersection.voxel.red, green: intersection.voxel.green, blue: intersection.voxel.blue }; @@ -674,7 +718,7 @@ function mousePressEvent(event) { x: intersection.voxel.x, y: intersection.voxel.y, z: intersection.voxel.z, - s: intersection.voxel.s, + s: editVoxelSize, red: colors[whichColor].red, green: colors[whichColor].green, blue: colors[whichColor].blue }; @@ -768,8 +812,7 @@ function mouseMoveEvent(event) { if (thumbX > maxThumbX) { thumbX = maxThumbX; } - // TODO: hook this up to the voxel size in some meaningful way - Overlays.editOverlay(thumb, { x: thumbX + sliderX } ); + calcScaleFromThumb(thumbX); } else if (isOrbiting) { var cameraOrientation = Camera.getOrientation(); From d04166811e0e0105c6443ae0c048facd1f300948 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 20 Feb 2014 02:24:26 -0800 Subject: [PATCH 79/83] wired up voxel size slider to actually change voxel size --- examples/editVoxels.js | 280 +++++++++++++++++++---------------------- 1 file changed, 130 insertions(+), 150 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index 8ac22413b3..81e3000566 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -328,6 +328,110 @@ var trackAsRecolor = false; var trackAsEyedropper = false; var trackAsOrbit = false; +function calculateVoxelFromIntersection(intersection, operation) { + //print("calculateVoxelFromIntersection() operation="+operation); + var resultVoxel; + + var voxelSize; + if (pointerVoxelScaleSet) { + voxelSize = pointerVoxelScale; + } else { + voxelSize = intersection.voxel.s; + } + + // first, calculate the enclosed voxel of size voxelSize that the intersection point falls inside of. + // if you have a voxelSize that's smaller than the voxel you're intersecting, this calculation will result + // in the subvoxel that the intersection point falls in + var x = Math.floor(intersection.intersection.x / voxelSize) * voxelSize; + var y = Math.floor(intersection.intersection.y / voxelSize) * voxelSize; + var z = Math.floor(intersection.intersection.z / voxelSize) * voxelSize; + resultVoxel = { x: x, y: y, z: z, s: voxelSize }; + highlightAt = { x: x, y: y, z: z, s: voxelSize }; + + // now we also want to calculate the "edge square" for the face for this voxel + if (intersection.face == "MIN_X_FACE") { + highlightAt.x = intersection.voxel.x; + resultVoxel.x = intersection.voxel.x; + if (operation == "add") { + resultVoxel.x -= voxelSize; + } + + resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; + resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z + voxelSize }; + resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z }; + resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z + voxelSize }; + + } else if (intersection.face == "MAX_X_FACE") { + highlightAt.x = intersection.voxel.x + intersection.voxel.s; + resultVoxel.x = intersection.voxel.x + intersection.voxel.s; + if (operation != "add") { + resultVoxel.x -= voxelSize; + } + + resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; + resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z + voxelSize }; + resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z }; + resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z + voxelSize }; + + } else if (intersection.face == "MIN_Y_FACE") { + + highlightAt.y = intersection.voxel.y; + resultVoxel.y = intersection.voxel.y; + + if (operation == "add") { + resultVoxel.y -= voxelSize; + } + + resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; + resultVoxel.bottomRight = {x: highlightAt.x + voxelSize , y: highlightAt.y, z: highlightAt.z}; + resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z + voxelSize }; + resultVoxel.topRight = {x: highlightAt.x + voxelSize , y: highlightAt.y, z: highlightAt.z + voxelSize}; + + } else if (intersection.face == "MAX_Y_FACE") { + + highlightAt.y = intersection.voxel.y + intersection.voxel.s; + resultVoxel.y = intersection.voxel.y + intersection.voxel.s; + if (operation != "add") { + resultVoxel.y -= voxelSize; + } + + resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; + resultVoxel.bottomRight = {x: highlightAt.x + voxelSize , y: highlightAt.y, z: highlightAt.z}; + resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z + voxelSize }; + resultVoxel.topRight = {x: highlightAt.x + voxelSize , y: highlightAt.y, z: highlightAt.z + voxelSize}; + + } else if (intersection.face == "MIN_Z_FACE") { + + highlightAt.z = intersection.voxel.z; + resultVoxel.z = intersection.voxel.z; + + if (operation == "add") { + resultVoxel.z -= voxelSize; + } + + resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; + resultVoxel.bottomRight = {x: highlightAt.x + voxelSize , y: highlightAt.y, z: highlightAt.z}; + resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z }; + resultVoxel.topRight = {x: highlightAt.x + voxelSize , y: highlightAt.y + voxelSize, z: highlightAt.z}; + + } else if (intersection.face == "MAX_Z_FACE") { + + highlightAt.z = intersection.voxel.z + intersection.voxel.s; + resultVoxel.z = intersection.voxel.z + intersection.voxel.s; + if (operation != "add") { + resultVoxel.z -= voxelSize; + } + + resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; + resultVoxel.bottomRight = {x: highlightAt.x + voxelSize , y: highlightAt.y, z: highlightAt.z}; + resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z }; + resultVoxel.topRight = {x: highlightAt.x + voxelSize , y: highlightAt.y + voxelSize, z: highlightAt.z}; + + } + + return resultVoxel; +} + function showPreviewVoxel() { var voxelColor; @@ -338,14 +442,6 @@ function showPreviewVoxel() { if (!pointerVoxelScaleSet) { calcThumbFromScale(intersection.voxel.s); } - - var previewVoxelSize; - if (pointerVoxelScaleSet) { - previewVoxelSize = pointerVoxelScale; - } else { - previewVoxelSize = intersection.voxel.s; - } - if (whichColor == -1) { // Copy mode - use clicked voxel color @@ -361,26 +457,21 @@ function showPreviewVoxel() { var guidePosition; if (trackAsDelete) { - guidePosition = { x: intersection.voxel.x, - y: intersection.voxel.y, - z: intersection.voxel.z }; - + guidePosition = calculateVoxelFromIntersection(intersection,"delete"); Overlays.editOverlay(voxelPreview, { position: guidePosition, - size: previewVoxelSize, + size: guidePosition.s, visible: true, color: { red: 255, green: 0, blue: 0 }, solid: false, alpha: 1 }); } else if (trackAsRecolor || trackAsEyedropper) { - guidePosition = { x: intersection.voxel.x - 0.001, - y: intersection.voxel.y - 0.001, - z: intersection.voxel.z - 0.001 }; + guidePosition = calculateVoxelFromIntersection(intersection,"recolor"); Overlays.editOverlay(voxelPreview, { position: guidePosition, - size: previewVoxelSize + 0.002, + size: guidePosition.s + 0.002, visible: true, color: voxelColor, solid: true, @@ -389,27 +480,11 @@ function showPreviewVoxel() { } else if (trackAsOrbit) { Overlays.editOverlay(voxelPreview, { visible: false }); } else if (!isExtruding) { - guidePosition = { x: intersection.voxel.x, - y: intersection.voxel.y, - z: intersection.voxel.z }; - - if (intersection.face == "MIN_X_FACE") { - guidePosition.x -= previewVoxelSize; - } else if (intersection.face == "MAX_X_FACE") { - guidePosition.x += intersection.voxel.s; - } else if (intersection.face == "MIN_Y_FACE") { - guidePosition.y -= previewVoxelSize; - } else if (intersection.face == "MAX_Y_FACE") { - guidePosition.y += intersection.voxel.s; - } else if (intersection.face == "MIN_Z_FACE") { - guidePosition.z -= previewVoxelSize; - } else if (intersection.face == "MAX_Z_FACE") { - guidePosition.z += intersection.voxel.s; - } + guidePosition = calculateVoxelFromIntersection(intersection,"add"); Overlays.editOverlay(voxelPreview, { position: guidePosition, - size: previewVoxelSize, + size: guidePosition.s, visible: true, color: voxelColor, solid: true, @@ -420,7 +495,6 @@ function showPreviewVoxel() { } } - function showPreviewLines() { var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); @@ -432,78 +506,12 @@ function showPreviewLines() { if (!pointerVoxelScaleSet) { calcThumbFromScale(intersection.voxel.s); } - - // TODO: add support for changing size here, if you set this size to any arbitrary size, - // the preview should correctly handle it - var previewVoxelSize; - if (pointerVoxelScaleSet) { - previewVoxelSize = pointerVoxelScale; - } else { - previewVoxelSize = intersection.voxel.s; - } - var x = Math.floor(intersection.intersection.x / previewVoxelSize) * previewVoxelSize; - var y = Math.floor(intersection.intersection.y / previewVoxelSize) * previewVoxelSize; - var z = Math.floor(intersection.intersection.z / previewVoxelSize) * previewVoxelSize; - previewVoxel = { x: x, y: y, z: z, s: previewVoxelSize }; - - var bottomLeft; - var bottomRight; - var topLeft; - var topRight; - - if (intersection.face == "MIN_X_FACE") { - previewVoxel.x = Math.floor(intersection.voxel.x / previewVoxelSize) * previewVoxelSize; - bottomLeft = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; - bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s }; - topLeft = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z }; - topRight = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z + previewVoxel.s }; - - } else if (intersection.face == "MAX_X_FACE") { - previewVoxel.x = Math.floor((intersection.voxel.x + intersection.voxel.s) / previewVoxelSize) * previewVoxelSize; - bottomLeft = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; - bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s }; - topLeft = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z }; - topRight = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z + previewVoxel.s }; - - } else if (intersection.face == "MIN_Y_FACE") { - - previewVoxel.y = Math.floor(intersection.voxel.y / previewVoxelSize) * previewVoxelSize; - bottomLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z }; - bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; - topLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s}; - topRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s}; - - } else if (intersection.face == "MAX_Y_FACE") { - - previewVoxel.y = Math.floor((intersection.voxel.y + intersection.voxel.s) / previewVoxelSize) * previewVoxelSize; - bottomLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z }; - bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; - topLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s}; - topRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z + previewVoxel.s}; - - } else if (intersection.face == "MIN_Z_FACE") { - - previewVoxel.z = Math.floor(intersection.voxel.z / previewVoxelSize) * previewVoxelSize; - bottomLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z }; - bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; - topLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z}; - topRight = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z}; - - } else if (intersection.face == "MAX_Z_FACE") { - - previewVoxel.z = Math.floor((intersection.voxel.z + intersection.voxel.s) / previewVoxelSize) * previewVoxelSize; - bottomLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y, z: previewVoxel.z }; - bottomRight = {x: previewVoxel.x, y: previewVoxel.y, z: previewVoxel.z }; - topLeft = {x: previewVoxel.x + previewVoxel.s, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z}; - topRight = {x: previewVoxel.x, y: previewVoxel.y + previewVoxel.s, z: previewVoxel.z}; - - } - - Overlays.editOverlay(linePreviewTop, { position: topLeft, end: topRight, visible: true }); - Overlays.editOverlay(linePreviewBottom, { position: bottomLeft, end: bottomRight, visible: true }); - Overlays.editOverlay(linePreviewLeft, { position: topLeft, end: bottomLeft, visible: true }); - Overlays.editOverlay(linePreviewRight, { position: topRight, end: bottomRight, visible: true }); + resultVoxel = calculateVoxelFromIntersection(intersection,""); + Overlays.editOverlay(linePreviewTop, { position: resultVoxel.topLeft, end: resultVoxel.topRight, visible: true }); + Overlays.editOverlay(linePreviewBottom, { position: resultVoxel.bottomLeft, end: resultVoxel.bottomRight, visible: true }); + Overlays.editOverlay(linePreviewLeft, { position: resultVoxel.topLeft, end: resultVoxel.bottomLeft, visible: true }); + Overlays.editOverlay(linePreviewRight, { position: resultVoxel.topRight, end: resultVoxel.bottomRight, visible: true }); } else { Overlays.editOverlay(linePreviewTop, { visible: false }); @@ -655,14 +663,6 @@ function mousePressEvent(event) { calcThumbFromScale(intersection.voxel.s); } - // TODO: This would be a good place to use the "set" voxel size... but the add/delete/color logic below assumes that - // the "edit" size is the same as the intersect.voxel.s. So we need to fix that to really wire up the voxel size - // slider - var editVoxelSize = intersection.voxel.s; - if (pointerVoxelScaleSet) { - //editVoxelSize = pointerVoxelScale; - } - if (event.isAlt) { // start orbit camera! var cameraPosition = Camera.getPosition(); @@ -679,12 +679,11 @@ function mousePressEvent(event) { } else if (trackAsDelete || (event.isRightButton && !trackAsEyedropper)) { // Delete voxel - Voxels.eraseVoxel(intersection.voxel.x, intersection.voxel.y, intersection.voxel.z, editVoxelSize); + voxelDetails = calculateVoxelFromIntersection(intersection,"delete"); + Voxels.eraseVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s); Audio.playSound(deleteSound, audioOptions); Overlays.editOverlay(voxelPreview, { visible: false }); } else if (trackAsEyedropper) { - - print("Grab color!!!"); if (whichColor != -1) { colors[whichColor].red = intersection.voxel.red; colors[whichColor].green = intersection.voxel.green; @@ -694,10 +693,11 @@ function mousePressEvent(event) { } else if (trackAsRecolor) { // Recolor Voxel - Voxels.setVoxel(intersection.voxel.x, - intersection.voxel.y, - intersection.voxel.z, - editVoxelSize, + voxelDetails = calculateVoxelFromIntersection(intersection,"recolor"); + + // doing this erase then set will make sure we only recolor just the target voxel + Voxels.eraseVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s); + Voxels.setVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s, colors[whichColor].red, colors[whichColor].green, colors[whichColor].blue); Audio.playSound(changeColorSound, audioOptions); Overlays.editOverlay(voxelPreview, { visible: false }); @@ -705,43 +705,23 @@ function mousePressEvent(event) { // Add voxel on face if (whichColor == -1) { // Copy mode - use clicked voxel color - var newVoxel = { - x: intersection.voxel.x, - y: intersection.voxel.y, - z: intersection.voxel.z, - s: editVoxelSize, + newColor = { red: intersection.voxel.red, green: intersection.voxel.green, blue: intersection.voxel.blue }; } else { - var newVoxel = { - x: intersection.voxel.x, - y: intersection.voxel.y, - z: intersection.voxel.z, - s: editVoxelSize, + newColor = { red: colors[whichColor].red, green: colors[whichColor].green, blue: colors[whichColor].blue }; } - if (intersection.face == "MIN_X_FACE") { - newVoxel.x -= newVoxel.s; - } else if (intersection.face == "MAX_X_FACE") { - newVoxel.x += newVoxel.s; - } else if (intersection.face == "MIN_Y_FACE") { - newVoxel.y -= newVoxel.s; - } else if (intersection.face == "MAX_Y_FACE") { - newVoxel.y += newVoxel.s; - } else if (intersection.face == "MIN_Z_FACE") { - newVoxel.z -= newVoxel.s; - } else if (intersection.face == "MAX_Z_FACE") { - newVoxel.z += newVoxel.s; - } - - Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue); - lastVoxelPosition = { x: newVoxel.x, y: newVoxel.y, z: newVoxel.z }; - lastVoxelColor = { red: newVoxel.red, green: newVoxel.green, blue: newVoxel.blue }; - lastVoxelScale = newVoxel.s; + voxelDetails = calculateVoxelFromIntersection(intersection,"add"); + Voxels.setVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s, + newColor.red, newColor.green, newColor.blue); + lastVoxelPosition = { x: voxelDetails.x, y: voxelDetails.y, z: voxelDetails.z }; + lastVoxelColor = { red: newColor.red, green: newColor.green, blue: newColor.blue }; + lastVoxelScale = voxelDetails.s; Audio.playSound(addSound, audioOptions); Overlays.editOverlay(voxelPreview, { visible: false }); From 4022d9f4c46c8dc8e68b001977d5604e980126de Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 20 Feb 2014 11:36:16 -0800 Subject: [PATCH 80/83] fix metavoxel interest list, keep node alive with ping --- assignment-client/src/metavoxels/MetavoxelServer.cpp | 3 +++ libraries/shared/src/NodeList.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp index fa934142d3..c10215cb57 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ b/assignment-client/src/metavoxels/MetavoxelServer.cpp @@ -37,6 +37,9 @@ const char METAVOXEL_SERVER_LOGGING_NAME[] = "metavoxel-server"; void MetavoxelServer::run() { commonInit(METAVOXEL_SERVER_LOGGING_NAME, NodeType::MetavoxelServer); + NodeList* nodeList = NodeList::getInstance(); + nodeList->addNodeTypeToInterestSet(NodeType::Agent); + _lastSend = QDateTime::currentMSecsSinceEpoch(); _sendTimer.start(SEND_INTERVAL); } diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 8dd3857198..bbb7750a2f 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -229,6 +229,7 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr // send back a reply SharedNodePointer matchingNode = sendingNodeForPacket(packet); if (matchingNode) { + matchingNode->setLastHeardMicrostamp(usecTimestampNow()); QByteArray replyPacket = constructPingReplyPacket(packet); writeDatagram(replyPacket, matchingNode, senderSockAddr); } @@ -239,6 +240,8 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr SharedNodePointer sendingNode = sendingNodeForPacket(packet); if (sendingNode) { + sendingNode->setLastHeardMicrostamp(usecTimestampNow()); + // activate the appropriate socket for this node, if not yet updated activateSocketFromNodeCommunication(packet, sendingNode); From fa490acb8d27dc8ac466f3864fc84c2fe276c983 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Thu, 20 Feb 2014 20:45:32 +0100 Subject: [PATCH 81/83] Changed the display name background alpha to 0.2 (was 0.95) --- 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 9ff1ec8cb1..f3229ce450 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -59,6 +59,7 @@ const float CHAT_MESSAGE_HEIGHT = 0.1f; const float DISPLAYNAME_FADE_TIME = 0.5f; const float DISPLAYNAME_FADE_FACTOR = pow(0.01f, 1.0f / DISPLAYNAME_FADE_TIME); const float DISPLAYNAME_ALPHA = 0.95f; +const float DISPLAYNAME_BACKGROUND_ALPHA = 0.2f; Avatar::Avatar() : AvatarData(), @@ -353,7 +354,7 @@ void Avatar::renderDisplayName() { glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0f, 1.0f); - glColor4f(0.2f, 0.2f, 0.2f, _displayNameAlpha); + glColor4f(0.2f, 0.2f, 0.2f, _displayNameAlpha * DISPLAYNAME_BACKGROUND_ALPHA / DISPLAYNAME_ALPHA); glBegin(GL_QUADS); glVertex2f(left, bottom); glVertex2f(right, bottom); From 354c9bff099bb575437c8f1839d25296fe086de0 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Fri, 21 Feb 2014 00:29:52 +0100 Subject: [PATCH 82/83] Correct text position for default and non default meshes Bounding box for text background is now text dependent, much nicer now --- interface/src/avatar/Avatar.cpp | 35 +++++++++++++++++----------- libraries/avatars/src/AvatarData.cpp | 2 +- libraries/avatars/src/AvatarData.h | 3 ++- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index f3229ce450..54a0dc5654 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -59,7 +59,7 @@ const float CHAT_MESSAGE_HEIGHT = 0.1f; const float DISPLAYNAME_FADE_TIME = 0.5f; const float DISPLAYNAME_FADE_FACTOR = pow(0.01f, 1.0f / DISPLAYNAME_FADE_TIME); const float DISPLAYNAME_ALPHA = 0.95f; -const float DISPLAYNAME_BACKGROUND_ALPHA = 0.2f; +const float DISPLAYNAME_BACKGROUND_ALPHA = 0.4f; Avatar::Avatar() : AvatarData(), @@ -218,7 +218,7 @@ void Avatar::render(bool forceRenderHead) { glPopMatrix(); } } - const float DISPLAYNAME_DISTANCE = 4.0f; + const float DISPLAYNAME_DISTANCE = 10.0f; setShowDisplayName(lengthToTarget < DISPLAYNAME_DISTANCE); renderDisplayName(); @@ -301,7 +301,10 @@ void Avatar::renderDisplayName() { glDisable(GL_LIGHTING); glPushMatrix(); - glm::vec3 textPosition = getPosition() + getBodyUpDirection() * ((getSkeletonHeight() + getHeadHeight()) / 1.5f); + glm::vec3 textPosition; + getSkeletonModel().getNeckPosition(textPosition); + textPosition += getBodyUpDirection() * getHeadHeight() * 1.1f; + glTranslatef(textPosition.x, textPosition.y, textPosition.z); // we need "always facing camera": we must remove the camera rotation from the stack @@ -340,11 +343,19 @@ void Avatar::renderDisplayName() { float scaleFactor = (textWindowHeight > EPSILON) ? 1.0f / textWindowHeight : 1.0f; glScalef(scaleFactor, scaleFactor, 1.0); + glScalef(1.0f, -1.0f, 1.0f); // TextRenderer::draw paints the text upside down in y axis + + int text_x = -_displayNameBoundingRect.width() / 2; + int text_y = -_displayNameBoundingRect.height() / 2; + // draw a gray background - QFontMetrics metrics = textRenderer(DISPLAYNAME)->metrics(); - int bottom = -metrics.descent(), top = bottom + metrics.height(); - int left = -_displayNameWidth/2, right = _displayNameWidth/2; - const int border = 5; + QRect rect = textRenderer(DISPLAYNAME)->metrics().tightBoundingRect(_displayName); + + int left = text_x + rect.x(); + int right = left + rect.width(); + int bottom = text_y + rect.y(); + int top = bottom + rect.height(); + const int border = 8; bottom -= border; left -= border; top += border; @@ -362,14 +373,14 @@ void Avatar::renderDisplayName() { glVertex2f(left, top); glEnd(); - glScalef(1.0f, -1.0f, 1.0f); // TextRenderer::draw paints the text upside down in y axis + glColor4f(0.93f, 0.93f, 0.93f, _displayNameAlpha); QByteArray ba = _displayName.toLocal8Bit(); const char* text = ba.data(); glDisable(GL_POLYGON_OFFSET_FILL); - textRenderer(DISPLAYNAME)->draw(-_displayNameWidth / 2, 0, text); + textRenderer(DISPLAYNAME)->draw(text_x, text_y, text); } @@ -490,11 +501,7 @@ void Avatar::setSkeletonModelURL(const QUrl &skeletonModelURL) { void Avatar::setDisplayName(const QString& displayName) { AvatarData::setDisplayName(displayName); - int width = 0; - for (int i = 0; i < displayName.size(); i++) { - width += (textRenderer(DISPLAYNAME)->computeWidth(displayName[i].toLatin1())); - } - _displayNameWidth = width; + _displayNameBoundingRect = textRenderer(DISPLAYNAME)->metrics().tightBoundingRect(displayName); } int Avatar::parseData(const QByteArray& packet) { diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 8e9eb430e8..da176f3fd9 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -36,7 +36,7 @@ AvatarData::AvatarData() : _isChatCirclingEnabled(false), _headData(NULL), _handData(NULL), - _displayNameWidth(0), + _displayNameBoundingRect(), _displayNameTargetAlpha(0.0f), _displayNameAlpha(0.0f) { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index a889b52bd0..1345a69f8e 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -33,6 +33,7 @@ typedef unsigned long long quint64; #include #include #include +#include #include #include @@ -187,7 +188,7 @@ protected: QUrl _skeletonModelURL; QString _displayName; - int _displayNameWidth; + QRect _displayNameBoundingRect; float _displayNameTargetAlpha; float _displayNameAlpha; From 10c9b902b9fd2b5e36972fe90083b46f9650ef95 Mon Sep 17 00:00:00 2001 From: Jose Carlos Date: Fri, 21 Feb 2014 00:37:29 +0100 Subject: [PATCH 83/83] Removed duplicated calculation of bounding rect for display name --- interface/src/avatar/Avatar.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 54a0dc5654..dcecd0258d 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -349,12 +349,10 @@ void Avatar::renderDisplayName() { int text_y = -_displayNameBoundingRect.height() / 2; // draw a gray background - QRect rect = textRenderer(DISPLAYNAME)->metrics().tightBoundingRect(_displayName); - - int left = text_x + rect.x(); - int right = left + rect.width(); - int bottom = text_y + rect.y(); - int top = bottom + rect.height(); + int left = text_x + _displayNameBoundingRect.x(); + int right = left + _displayNameBoundingRect.width(); + int bottom = text_y + _displayNameBoundingRect.y(); + int top = bottom + _displayNameBoundingRect.height(); const int border = 8; bottom -= border; left -= border;