From 3dfefefeae9a74e0352bed5701f27c81125a7923 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 22 Aug 2013 14:00:50 -0700 Subject: [PATCH 1/3] Make the surrounding spheres glow when moving, too. --- interface/src/avatar/Avatar.cpp | 36 +++++++++++++++++---------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 08533666f3..9f2ac37518 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -486,22 +486,27 @@ void Avatar::render(bool lookingInMirror, bool renderAvatarBalls) { // render a simple round on the ground projected down from the avatar's position renderDiskShadow(_position, glm::vec3(0.0f, 1.0f, 0.0f), _scale * 0.1f, 0.2f); - // render body - renderBody(lookingInMirror, renderAvatarBalls); + { + // glow when moving + Glower glower(_moving ? 1.0f : 0.0f); + + // render body + renderBody(lookingInMirror, renderAvatarBalls); - // render sphere when far away - const float MAX_ANGLE = 10.f; - glm::vec3 toTarget = _position - Application::getInstance()->getAvatar()->getPosition(); - glm::vec3 delta = _height * (_head.getCameraOrientation() * IDENTITY_UP) / 2.f; - float angle = abs(angleBetween(toTarget + delta, toTarget - delta)); + // render sphere when far away + const float MAX_ANGLE = 10.f; + glm::vec3 toTarget = _position - Application::getInstance()->getAvatar()->getPosition(); + glm::vec3 delta = _height * (_head.getCameraOrientation() * IDENTITY_UP) / 2.f; + float angle = abs(angleBetween(toTarget + delta, toTarget - delta)); - if (angle < MAX_ANGLE) { - glColor4f(0.5f, 0.8f, 0.8f, 1.f - angle / MAX_ANGLE); - 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); - glPopMatrix(); + if (angle < MAX_ANGLE) { + glColor4f(0.5f, 0.8f, 0.8f, 1.f - angle / MAX_ANGLE); + 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); + glPopMatrix(); + } } // Render the balls @@ -697,9 +702,6 @@ float Avatar::getBallRenderAlpha(int ball, bool lookingInMirror) const { void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { - // glow when moving - Glower glower(_moving ? 1.0f : 0.0f); - if (_head.getFace().isFullFrame()) { // Render the full-frame video float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, lookingInMirror); From 2cff4b6b3a1c293771a0fc92f1673823d7ea556a Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 22 Aug 2013 17:09:23 -0700 Subject: [PATCH 2/3] "Laser pointer" for transmitter. --- interface/src/Application.cpp | 59 ++++++++++++++++++++++++++++++++- interface/src/Application.h | 3 ++ interface/src/Util.cpp | 36 ++++++++++++++++---- interface/src/Util.h | 3 +- interface/src/avatar/Avatar.cpp | 15 +++++++++ interface/src/avatar/Avatar.h | 7 ++++ 6 files changed, 114 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d69770678c..de9759959a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1384,7 +1384,9 @@ Avatar* Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3 if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { Avatar* avatar = (Avatar *) node->getLinkedData(); glm::vec3 headPosition = avatar->getHead().getPosition(); - if (rayIntersectsSphere(mouseRayOrigin, mouseRayDirection, headPosition, HEAD_SPHERE_RADIUS * avatar->getScale())) { + float distance; + if (rayIntersectsSphere(mouseRayOrigin, mouseRayDirection, headPosition, + HEAD_SPHERE_RADIUS * avatar->getScale(), distance)) { eyePosition = avatar->getHead().getEyePosition(); _lookatIndicatorScale = avatar->getScale(); _lookatOtherPosition = headPosition; @@ -1722,6 +1724,40 @@ void Application::update(float deltaTime) { _myAvatar.simulate(deltaTime, NULL, Menu::getInstance()->getGyroCameraSensitivity()); } + // no transmitter drive implies transmitter pick + if (!Menu::getInstance()->isOptionChecked(MenuOption::TransmitterDrive) && _myTransmitter.isConnected()) { + _transmitterPickStart = _myAvatar.getSkeleton().joint[AVATAR_JOINT_CHEST].position; + glm::vec3 direction = _myAvatar.getOrientation() * + glm::quat(glm::radians(_myTransmitter.getEstimatedRotation())) * IDENTITY_FRONT; + + // check against voxels, avatars + const float MAX_PICK_DISTANCE = 100.0f; + float minDistance = MAX_PICK_DISTANCE; + VoxelDetail detail; + float distance; + BoxFace face; + if (_voxels.findRayIntersection(_transmitterPickStart, direction, detail, distance, face)) { + minDistance = min(minDistance, distance); + } + for(NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + node->lock(); + if (node->getLinkedData() != NULL) { + Avatar *avatar = (Avatar*)node->getLinkedData(); + if (!avatar->isInitialized()) { + avatar->init(); + } + if (avatar->findRayIntersection(_transmitterPickStart, direction, distance)) { + minDistance = min(minDistance, distance); + } + } + node->unlock(); + } + _transmitterPickEnd = _transmitterPickStart + direction * minDistance; + + } else { + _transmitterPickStart = _transmitterPickEnd = glm::vec3(); + } + if (!OculusManager::isConnected()) { if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { if (_myCamera.getMode() != CAMERA_MODE_MIRROR) { @@ -2271,6 +2307,27 @@ void Application::displaySide(Camera& whichCamera) { } renderFollowIndicator(); + + // render transmitter pick ray, if non-empty + if (_transmitterPickStart != _transmitterPickEnd) { + Glower glower; + float TRANSMITTER_PICK_COLOR[] = { 1.0f, 1.0f, 0.0f }; + glColor3fv(TRANSMITTER_PICK_COLOR); + glLineWidth(3.0f); + glBegin(GL_LINES); + glVertex3f(_transmitterPickStart.x, _transmitterPickStart.y, _transmitterPickStart.z); + glVertex3f(_transmitterPickEnd.x, _transmitterPickEnd.y, _transmitterPickEnd.z); + glEnd(); + glLineWidth(1.0f); + + glPushMatrix(); + glTranslatef(_transmitterPickEnd.x, _transmitterPickEnd.y, _transmitterPickEnd.z); + + float PICK_END_RADIUS = 0.025f; + glutSolidSphere(PICK_END_RADIUS, 8, 8); + + glPopMatrix(); + } } void Application::displayOverlay() { diff --git a/interface/src/Application.h b/interface/src/Application.h index a88ea3269f..7ad64ca707 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -298,6 +298,9 @@ private: glm::vec3 _lookatOtherPosition; float _lookatIndicatorScale; + glm::vec3 _transmitterPickStart; + glm::vec3 _transmitterPickEnd; + bool _perfStatsOn; // Do we want to display perfStats? ChatEntry _chatEntry; // chat entry field diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 743957128c..dc825ca765 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -598,13 +598,35 @@ float loadSetting(QSettings* settings, const char* name, float defaultValue) { return value; } -bool rayIntersectsSphere(glm::vec3& rayStarting, glm::vec3& rayNormalizedDirection, glm::vec3& sphereCenter, double sphereRadius) { - glm::vec3 vecFromRayToSphereCenter = sphereCenter - rayStarting; - double projection = glm::dot(vecFromRayToSphereCenter, rayNormalizedDirection); - double shortestDistance = sqrt(glm::dot(vecFromRayToSphereCenter, vecFromRayToSphereCenter) - projection * projection); - if (shortestDistance <= sphereRadius) { - return true; +bool rayIntersectsSphere(const glm::vec3& rayStarting, const glm::vec3& rayNormalizedDirection, + const glm::vec3& sphereCenter, float sphereRadius, float& distance) { + glm::vec3 relativeOrigin = rayStarting - sphereCenter; + + // compute the b, c terms of the quadratic equation (a is dot(direction, direction), which is one) + float b = 2.0f * glm::dot(rayNormalizedDirection, relativeOrigin); + float c = glm::dot(relativeOrigin, relativeOrigin) - sphereRadius * sphereRadius; + + // compute the radicand of the quadratic. if less than zero, there's no intersection + float radicand = b * b - 4.0f * c; + if (radicand < 0.0f) { + return false; } + + // compute the first solution of the quadratic + float root = sqrtf(radicand); + float firstSolution = -b - root; + if (firstSolution > 0.0f) { + distance = firstSolution / 2.0f; + return true; // origin is outside the sphere + } + + // now try the second solution + float secondSolution = -b + root; + if (secondSolution > 0.0f) { + distance = 0.0f; + return true; // origin is inside the sphere + } + return false; } @@ -615,4 +637,4 @@ bool pointInSphere(glm::vec3& point, glm::vec3& sphereCenter, double sphereRadiu return true; } return false; -} \ No newline at end of file +} diff --git a/interface/src/Util.h b/interface/src/Util.h index c1bb2949fa..2926d5bfc4 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -74,7 +74,8 @@ void runTimingTests(); float loadSetting(QSettings* settings, const char* name, float defaultValue); -bool rayIntersectsSphere(glm::vec3& rayStarting, glm::vec3& rayNormalizedDirection, glm::vec3& sphereCenter, double sphereRadius); +bool rayIntersectsSphere(const glm::vec3& rayStarting, const glm::vec3& rayNormalizedDirection, + const glm::vec3& sphereCenter, float sphereRadius, float& distance); bool pointInSphere(glm::vec3& point, glm::vec3& sphereCenter, double sphereRadius); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 9f2ac37518..4635be7357 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -800,6 +800,21 @@ void Avatar::getBodyBallTransform(AvatarJointID jointID, glm::vec3& position, gl rotation = _bodyBall[jointID].rotation; } +bool Avatar::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { + float minDistance = FLT_MAX; + for (int i = 0; i < NUM_AVATAR_BODY_BALLS; i++) { + float distance; + if (rayIntersectsSphere(origin, direction, _bodyBall[i].position, _bodyBall[i].radius, distance)) { + minDistance = min(minDistance, distance); + } + } + if (minDistance == FLT_MAX) { + return false; + } + distance = minDistance; + return true; +} + int Avatar::parseData(unsigned char* sourceBuffer, int numBytes) { // change in position implies movement glm::vec3 oldPosition = _position; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 4048f15d0f..b04f9f04b8 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -164,6 +164,13 @@ public: // Get the position/rotation of a single body ball void getBodyBallTransform(AvatarJointID jointID, glm::vec3& position, glm::quat& rotation) const; + /// Checks for an intersection between the described ray and any of the avatar's body balls. + /// \param origin the origin of the ray + /// \param direction the unit direction vector + /// \param[out] distance the variable in which to store the distance to intersection + /// \return whether or not the ray intersected + bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; + virtual int parseData(unsigned char* sourceBuffer, int numBytes); static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2); From 3682e32eb15ae4cf508a741a67690022e52b5d33 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 22 Aug 2013 17:40:55 -0700 Subject: [PATCH 3/3] Yes, these should be consts. --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index de9759959a..cc95aec1fd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2311,7 +2311,7 @@ void Application::displaySide(Camera& whichCamera) { // render transmitter pick ray, if non-empty if (_transmitterPickStart != _transmitterPickEnd) { Glower glower; - float TRANSMITTER_PICK_COLOR[] = { 1.0f, 1.0f, 0.0f }; + const float TRANSMITTER_PICK_COLOR[] = { 1.0f, 1.0f, 0.0f }; glColor3fv(TRANSMITTER_PICK_COLOR); glLineWidth(3.0f); glBegin(GL_LINES); @@ -2323,7 +2323,7 @@ void Application::displaySide(Camera& whichCamera) { glPushMatrix(); glTranslatef(_transmitterPickEnd.x, _transmitterPickEnd.y, _transmitterPickEnd.z); - float PICK_END_RADIUS = 0.025f; + const float PICK_END_RADIUS = 0.025f; glutSolidSphere(PICK_END_RADIUS, 8, 8); glPopMatrix();