From f28fc5f79b6d42cb375494edd15f109aa237da6a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 14 Jan 2014 16:08:40 -0800 Subject: [PATCH 01/16] Adding palm accessor method that fetches left or right, as specified. --- libraries/avatars/src/HandData.cpp | 12 ++++++++++++ libraries/avatars/src/HandData.h | 1 + 2 files changed, 13 insertions(+) diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index e8b2c97ff0..62a15efb1a 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -41,6 +41,18 @@ PalmData& HandData::addNewPalm() { const int SIXENSE_CONTROLLER_ID_LEFT_HAND = 0; const int SIXENSE_CONTROLLER_ID_RIGHT_HAND = 1; +const PalmData* HandData::getPalm(int sixSenseID) const { + // the palms are not necessarily added in left-right order, + // so we have to search for the right SixSenseID + for (int i = 0; i < _palms.size(); i++) { + const PalmData* palm = &(_palms[i]); + if (palm->getSixenseID() == sixSenseID) { + return palm->isActive() ? palm : NULL; + } + } + return NULL; +} + void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) const { leftPalmIndex = -1; rightPalmIndex = -1; diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index a0c8fed980..8de0c2d9f8 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -55,6 +55,7 @@ public: std::vector& getPalms() { return _palms; } const std::vector& getPalms() const { return _palms; } + const PalmData* getPalm(int sixSenseID) const; size_t getNumPalms() const { return _palms.size(); } PalmData& addNewPalm(); From eb207efe329969ece56af7df81dff29104677e51 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 14 Jan 2014 16:11:27 -0800 Subject: [PATCH 02/16] Adding simple CollisionInfo class as data wrapper and a findSphereCollision() method to AgentData API. --- libraries/avatars/src/AvatarData.cpp | 1 - libraries/avatars/src/AvatarData.h | 7 ++++- libraries/shared/src/CollisionInfo.h | 44 ++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 libraries/shared/src/CollisionInfo.h diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 14115ced47..5963a335ce 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -303,5 +303,4 @@ void AvatarData::setNewScale(float newScale) { newScale = MIN_SCALE; } _newScale = newScale; - qDebug() << "Changed scale to " << _newScale << "\n"; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index e7f359aff2..171863810a 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -20,9 +20,10 @@ #include #include +#include #include - #include + #include "HeadData.h" #include "HandData.h" @@ -119,6 +120,10 @@ public: /// \return whether or not the sphere penetrated virtual bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration, int skeletonSkipIndex = -1) const { return false; } + + virtual bool findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) { + return false; + } protected: QUuid _uuid; diff --git a/libraries/shared/src/CollisionInfo.h b/libraries/shared/src/CollisionInfo.h new file mode 100644 index 0000000000..b9d064f2ea --- /dev/null +++ b/libraries/shared/src/CollisionInfo.h @@ -0,0 +1,44 @@ +// +// CollisionInfo.h +// hifi +// +// Created by Andrew Meadows on 2014.01.13 +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __hifi__CollisionInfo__ +#define __hifi__CollisionInfo__ + +/* +#include +#include + +#ifdef _WIN32 +#include "Syssocket.h" +#else +#include +#endif + +#include +#include + +#include "HifiSockAddr.h" +#include "NodeData.h" +#include "SimpleMovingAverage.h" +*/ + +#include + +class CollisionInfo { +public: + CollisionInfo() : _penetration(0.f), _addedVelocity(0.f) { } + ~CollisionInfo() {} + + //glm::vec3 _point; + //glm::vec3 _normal; + glm::vec3 _penetration; + glm::vec3 _addedVelocity; +}; + + +#endif /* defined(__hifi__CollisionInfo__) */ From a08b7b3fd80779ed59e41e217670b1866f859cd5 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 14 Jan 2014 16:15:41 -0800 Subject: [PATCH 03/16] Adding initial Agent::findSphereCollision() implementation and removing some debug log spam. --- interface/src/avatar/Avatar.cpp | 44 +++++++++++++++++++++++++++++++-- interface/src/avatar/Avatar.h | 2 ++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index b3b4793b39..b02c01acee 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -376,6 +376,48 @@ bool Avatar::findSpherePenetration(const glm::vec3& penetratorCenter, float pene return false; } +bool Avatar::findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) { + // TODO: provide an early exit using bounding sphere of entire avatar + + const HandData* handData = getHandData(); + if (handData) { + int jointIndices[2] = { _skeletonModel.getLeftHandJointIndex(), _skeletonModel.getRightHandJointIndex() }; + for (int i = 0; i < 2; i++) { + const PalmData* palm = handData->getPalm(i); + if (palm) { + int jointIndex = jointIndices[i]; + /* + // TODO: create a disk where the hand is + glm::vec3 position; + glm::quat rotation; + if (i == 0) { + _skeletonModel.getLeftHandPosition(position); + _skeletonModel.getLeftHandRotation(rotation); + } + else { + _skeletonModel.getRightHandPosition(position); + _skeletonModel.getRightHandRotation(rotation); + } + */ + // HACK: we temporarily boost the size of the hand so it is easier to collide with it + float handScaleFactor = 5.f; + if (_skeletonModel.findSpherePenetrationWithJoint(sphereCenter, sphereRadius, collision._penetration, jointIndex, handScaleFactor)) { + collision._addedVelocity = palm->getVelocity(); + return true; + } + } + } + } + + if (_skeletonModel.findSpherePenetration(sphereCenter, sphereRadius, collision._penetration)) { + // apply hard collision when particle collides with avatar + collision._penetration /= (float)(TREE_SCALE); + collision._addedVelocity = getVelocity(); + return true; + } + return false; +} + int Avatar::parseData(unsigned char* sourceBuffer, int numBytes) { // change in position implies movement glm::vec3 oldPosition = _position; @@ -441,14 +483,12 @@ void Avatar::goHome() { void Avatar::increaseSize() { if ((1.f + SCALING_RATIO) * _newScale < MAX_SCALE) { _newScale *= (1.f + SCALING_RATIO); - qDebug("Changed scale to %f\n", _newScale); } } void Avatar::decreaseSize() { if (MIN_SCALE < (1.f - SCALING_RATIO) * _newScale) { _newScale *= (1.f - SCALING_RATIO); - qDebug("Changed scale to %f\n", _newScale); } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 1a4511275a..f5dd0a2555 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -169,6 +169,8 @@ public: bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration, int skeletonSkipIndex = -1) const; + virtual bool findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision); + virtual int parseData(unsigned char* sourceBuffer, int numBytes); static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2); From 22679687c57d16a74a742e20703046dc5e24f2f1 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 14 Jan 2014 16:17:37 -0800 Subject: [PATCH 04/16] Minor cleanup: moved #include out of header and into cpp file. --- interface/src/avatar/SkeletonModel.cpp | 2 ++ interface/src/avatar/SkeletonModel.h | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 6723b766e8..6ab740b8c7 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -8,6 +8,8 @@ #include +#include + #include "Application.h" #include "Avatar.h" #include "Menu.h" diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index caf08c823b..e0f69cf55b 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -9,7 +9,6 @@ #ifndef __interface__SkeletonModel__ #define __interface__SkeletonModel__ -#include #include "renderer/Model.h" From 761fdc9d84d193f753e79f8a302cc12246944552 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 14 Jan 2014 16:19:57 -0800 Subject: [PATCH 05/16] Adding methods to Model for accessing hand info and computing hand collisions. --- interface/src/renderer/Model.cpp | 39 ++++++++++++++++++++++++++++++++ interface/src/renderer/Model.h | 19 ++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index e7fb6c7c1d..b84c283b2c 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -487,6 +487,22 @@ bool Model::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePos return getJointPosition(geometry.leftEyeJointIndex, firstEyePosition) && getJointPosition(geometry.rightEyeJointIndex, secondEyePosition); } + +bool Model::getLeftHandPosition(glm::vec3& position) const { + return getJointPosition(getLeftHandJointIndex(), position); +} + +bool Model::getLeftHandRotation(glm::quat& rotation) const { + return getJointRotation(getLeftHandJointIndex(), rotation); +} + +bool Model::getRightHandPosition(glm::vec3& position) const { + return getJointPosition(getRightHandJointIndex(), position); +} + +bool Model::getRightHandRotation(glm::quat& rotation) const { + return getJointRotation(getRightHandJointIndex(), rotation); +} bool Model::setLeftHandPosition(const glm::vec3& position) { return setJointPosition(getLeftHandJointIndex(), position); @@ -617,6 +633,29 @@ bool Model::findSpherePenetration(const glm::vec3& penetratorCenter, float penet return false; } +// TODO: purge this once we get proper collisions against hand paddles +bool Model::findSpherePenetrationWithJoint(const glm::vec3& sphereCenter, float sphereRadius, + glm::vec3& penetration, int jointIndex, float boneScale) const { + if (jointIndex < 0 || jointIndex > _jointStates.size()) { + return false; + } + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + const FBXJoint& joint = geometry.joints[jointIndex]; + glm::vec3 end = extractTranslation(_jointStates[jointIndex].transform); + float radiusScale = extractUniformScale(_scale) * boneScale; + float endRadius = joint.boneRadius * radiusScale; + glm::vec3 start = end; + float startRadius = joint.boneRadius * radiusScale; + glm::vec3 bonePenetration; + if (joint.parentIndex != -1) { + start = extractTranslation(_jointStates[joint.parentIndex].transform); + startRadius = geometry.joints[joint.parentIndex].boneRadius * radiusScale; + } + const glm::vec3 relativeCenter = sphereCenter - _translation; + return findSphereCapsuleConePenetration(relativeCenter, sphereRadius, start, end, + startRadius, endRadius, penetration); +} + void Model::updateJointState(int index) { JointState& state = _jointStates[index]; const FBXGeometry& geometry = _geometry->getFBXGeometry(); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 3b1f66938b..620eb59f8d 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -82,6 +82,22 @@ public: /// \return whether or not both eye meshes were found bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const; + /// Retrieve the position of the left hand + /// \return true whether or not the position was found + bool getLeftHandPosition(glm::vec3&) const; + + /// Retrieve the rotation of the left hand + /// \return true whether or not the rotation was found + bool getLeftHandRotation(glm::quat&) const; + + /// Retrieve the position of the right hand + /// \return true whether or not the position was found + bool getRightHandPosition(glm::vec3&) const; + + /// Retrieve the rotation of the right hand + /// \return true whether or not the rotation was found + bool getRightHandRotation(glm::quat&) const; + /// Sets the position of the left hand using inverse kinematics. /// \return whether or not the left hand joint was found bool setLeftHandPosition(const glm::vec3& position); @@ -130,6 +146,9 @@ public: bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration, float boneScale = 1.0f, int skipIndex = -1) const; + bool findSpherePenetrationWithJoint(const glm::vec3& sphereCenter, float sphereRadius, + glm::vec3& penetration, int jointIndex, float boneScale = 1.0f) const; + protected: QSharedPointer _geometry; From 9847ab3bfd8237c5f7e18ae18630a53644d384c0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 14 Jan 2014 16:23:35 -0800 Subject: [PATCH 06/16] Adding findSphereDiskPenetration() method for hand paddle experiment. --- libraries/shared/src/GeometryUtil.cpp | 19 +++++++++++++++++++ libraries/shared/src/GeometryUtil.h | 11 +++++++++++ 2 files changed, 30 insertions(+) diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index 7ffe4edfde..5a756b8e71 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -116,6 +116,25 @@ bool findSpherePlanePenetration(const glm::vec3& sphereCenter, float sphereRadiu return false; } +bool findSphereDiskPenetration(const glm::vec3& sphereCenter, float sphereRadius, + const glm::vec3& diskCenter, float diskRadius, const glm::vec3& diskNormal, + glm::vec3& penetration) { + glm::vec3 localCenter = sphereCenter - diskCenter; + float verticalDistance = glm::dot(localCenter, diskNormal); + if (abs(verticalDistance) < sphereRadius) { + // sphere hits the plane, but does it hit the disk? + // Note: this algorithm ignores edge hits. + glm::vec3 verticalOffset = verticalDistance * diskNormal; + if (glm::length(localCenter - verticalOffset) < diskRadius) { + penetration = (sphereRadius - abs(verticalDistance)) * diskNormal; + if (verticalDistance < 0.f) { + penetration *= -1.f; + } + } + } + return false; +} + bool findCapsuleSpherePenetration(const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius, const glm::vec3& sphereCenter, float sphereRadius, glm::vec3& penetration) { if (findSphereCapsulePenetration(sphereCenter, sphereRadius, diff --git a/libraries/shared/src/GeometryUtil.h b/libraries/shared/src/GeometryUtil.h index 2b782b43ae..59ad055445 100644 --- a/libraries/shared/src/GeometryUtil.h +++ b/libraries/shared/src/GeometryUtil.h @@ -47,6 +47,17 @@ bool findSphereCapsuleConePenetration(const glm::vec3& sphereCenter, float spher bool findSpherePlanePenetration(const glm::vec3& sphereCenter, float sphereRadius, const glm::vec4& plane, glm::vec3& penetration); +/// Computes the penetration between a sphere and a disk. +/// \param sphereCenter center of sphere +/// \param sphereRadius radius of sphere +/// \param diskCenter center of disk +/// \param diskRadius radius of disk +/// \param diskNormal normal of disk plan +/// \return true if sphere touches disk (does not handle collisions with disk edge) +bool findSphereDiskPenetration(const glm::vec3& sphereCenter, float sphereRadius, + const glm::vec3& diskCenter, float diskRadius, const glm::vec3& diskNormal, + glm::vec3& penetration); + bool findCapsuleSpherePenetration(const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius, const glm::vec3& sphereCenter, float sphereRadius, glm::vec3& penetration); From b51699bb2fcc2f45fe0d3823895c3139834804da Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 14 Jan 2014 16:25:31 -0800 Subject: [PATCH 07/16] First pass at particle-hand collisions using hacked hand capsules. --- .../particles/src/ParticleCollisionSystem.cpp | 40 +++++-------------- .../particles/src/ParticleCollisionSystem.h | 2 +- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index 6711dc2d13..7cbdd74942 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -153,39 +154,20 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { // first check the selfAvatar if set... if (_selfAvatar) { AvatarData* avatar = (AvatarData*)_selfAvatar; - //printf("updateCollisionWithAvatars()..._selfAvatar=%p\n", avatar); - - // check hands... - const HandData* handData = avatar->getHandData(); - - // TODO: combine hand and collision check into one. Note: would need to supply - // CollisionInfo class rather than just vec3 (penetration) so we can get back - // added velocity. - - if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) { - // TODO: dot collidingPalm and hand velocities and skip collision when they are moving apart. - // apply a hard collision when ball collides with hand - penetration /= (float)(TREE_SCALE); - updateCollisionSound(particle, penetration, COLLISION_FREQUENCY); - - // determine if the palm that collided was moving, if so, then we add that palm velocity as well... - glm::vec3 addedVelocity = NO_ADDED_VELOCITY; - if (collidingPalm) { - glm::vec3 palmVelocity = collidingPalm->getVelocity() / (float)(TREE_SCALE); - //printf("collidingPalm Velocity=%f,%f,%f\n", palmVelocity.x, palmVelocity.y, palmVelocity.z); - addedVelocity = palmVelocity; + CollisionInfo collision; + if (avatar->findSphereCollision(center, radius, collision)) { + if (glm::dot(particle->getVelocity(), collision._addedVelocity) < 0.f) { + collision._penetration /= (float)(TREE_SCALE); + collision._addedVelocity /= (float)(TREE_SCALE); + glm::vec3 pv = particle->getVelocity(); + updateCollisionSound(particle, collision._penetration, COLLISION_FREQUENCY); + applyHardCollision(particle, collision._penetration, ELASTICITY, DAMPING, collision._addedVelocity); } - - applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity); - } else if (avatar->findSpherePenetration(center, radius, penetration)) { - // apply hard collision when particle collides with avatar - penetration /= (float)(TREE_SCALE); - updateCollisionSound(particle, penetration, COLLISION_FREQUENCY); - glm::vec3 addedVelocity = avatar->getVelocity(); - applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity); } } + // TODO: convert other avatars to collide like _selfAvatar + // loop through all the other avatars for potential interactions... NodeList* nodeList = NodeList::getInstance(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { diff --git a/libraries/particles/src/ParticleCollisionSystem.h b/libraries/particles/src/ParticleCollisionSystem.h index 920b89c053..13766a0264 100644 --- a/libraries/particles/src/ParticleCollisionSystem.h +++ b/libraries/particles/src/ParticleCollisionSystem.h @@ -61,4 +61,4 @@ private: AvatarData* _selfAvatar; }; -#endif /* defined(__hifi__ParticleCollisionSystem__) */ \ No newline at end of file +#endif /* defined(__hifi__ParticleCollisionSystem__) */ From e4730790c03be4037aa289a443258a5df8d02361 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 15 Jan 2014 14:00:32 -0800 Subject: [PATCH 08/16] bugfix: findSphereDiskPenetration() would never return true --- libraries/shared/src/GeometryUtil.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index 5a756b8e71..833e597c4b 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -121,15 +121,20 @@ bool findSphereDiskPenetration(const glm::vec3& sphereCenter, float sphereRadius glm::vec3& penetration) { glm::vec3 localCenter = sphereCenter - diskCenter; float verticalDistance = glm::dot(localCenter, diskNormal); + + if (abs(verticalDistance) < sphereRadius) { - // sphere hits the plane, but does it hit the disk? + // sphere hit the plane, but does it hit the disk? // Note: this algorithm ignores edge hits. glm::vec3 verticalOffset = verticalDistance * diskNormal; if (glm::length(localCenter - verticalOffset) < diskRadius) { + // yes, hit the disk penetration = (sphereRadius - abs(verticalDistance)) * diskNormal; if (verticalDistance < 0.f) { + // hit the backside of the disk, so negate penetration vector penetration *= -1.f; } + return true; } } return false; From ee6a3263bc5542334dc1feddbee265d9f2b969dc Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 15 Jan 2014 14:02:17 -0800 Subject: [PATCH 09/16] Changing where the "hand palms" are drawn. Will back them up with collision proxies soon. --- interface/src/avatar/Hand.cpp | 41 +++++++++++++++++++++++------------ interface/src/avatar/Hand.h | 4 ++++ 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 2784e0a115..16693f88e2 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -616,23 +616,36 @@ void Hand::renderLeapHands(bool isMine) { } } - // Draw the palms - for (size_t i = 0; i < getNumPalms(); ++i) { - PalmData& palm = getPalms()[i]; - if (palm.isActive()) { - const float palmThickness = 0.02f; - if (palm.getIsCollidingWithPalm()) { - glColor4f(1, 0, 0, 0.50); - } else { - glColor4f(handColor.r, handColor.g, handColor.b, 0.25); + // Draw the hand paddles + glColor4f(handColor.r, handColor.g, handColor.b, 0.3f); + for (int i = 0; i < 2; i++) { + const PalmData* palm = getPalm(i); + if (palm) { + // compute finger axis + glm::vec3 fingerAxis(0.f); + for (size_t f = 0; f < palm->getNumFingers(); ++f) { + const FingerData& finger = (palm->getFingers())[f]; + if (finger.isActive()) { + glm::vec3 fingerTip = finger.getTipPosition(); + glm::vec3 fingerRoot = finger.getRootPosition(); + fingerAxis = glm::normalize(fingerTip - fingerRoot); + break; + } } - glm::vec3 tip = palm.getPosition(); - glm::vec3 root = palm.getPosition() + palm.getNormal() * palmThickness; - const float radiusA = 0.05f; - const float radiusB = 0.03f; - Avatar::renderJointConnectingCone(root, tip, radiusA, radiusB); + // compute paddle position + glm::vec3 handPosition; + if (i == 0) { + _owningAvatar->getSkeletonModel().getLeftHandPosition(handPosition); + } else { + _owningAvatar->getSkeletonModel().getRightHandPosition(handPosition); + } + glm::vec3 tip = handPosition + HAND_PADDLE_OFFSET * fingerAxis; + glm::vec3 root = tip + palm->getNormal() * HAND_PADDLE_THICKNESS; + // render a very shallow cone as the paddle + Avatar::renderJointConnectingCone(root, tip, HAND_PADDLE_RADIUS, 0.f); } } + glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 8c368a4c37..541eece025 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -31,6 +31,10 @@ class Avatar; class ProgramObject; +const float HAND_PADDLE_OFFSET = 0.1f; +const float HAND_PADDLE_THICKNESS = 0.05f; +const float HAND_PADDLE_RADIUS = 0.15f; + class Hand : public HandData { public: Hand(Avatar* owningAvatar); From 235b6f0c3637b80d21486a96335895fdf8836ad7 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 15 Jan 2014 14:05:57 -0800 Subject: [PATCH 10/16] Adding disk collision proxy for hand paddles. --- interface/src/avatar/Avatar.cpp | 35 ++++++++++++++++++++------------- interface/src/avatar/Avatar.h | 5 +++++ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 2bc14c1a1b..4fe620229a 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -364,23 +364,31 @@ bool Avatar::findSphereCollision(const glm::vec3& sphereCenter, float sphereRadi for (int i = 0; i < 2; i++) { const PalmData* palm = handData->getPalm(i); if (palm) { - int jointIndex = jointIndices[i]; - /* - // TODO: create a disk where the hand is - glm::vec3 position; - glm::quat rotation; + // create a disk collision proxy where the hand is + glm::vec3 fingerAxis(0.f); + for (size_t f = 0; f < palm->getNumFingers(); ++f) { + const FingerData& finger = (palm->getFingers())[f]; + if (finger.isActive()) { + // compute finger axis + glm::vec3 fingerTip = finger.getTipPosition(); + glm::vec3 fingerRoot = finger.getRootPosition(); + fingerAxis = glm::normalize(fingerTip - fingerRoot); + break; + } + } + glm::vec3 handPosition; if (i == 0) { - _skeletonModel.getLeftHandPosition(position); - _skeletonModel.getLeftHandRotation(rotation); + _skeletonModel.getLeftHandPosition(handPosition); } else { - _skeletonModel.getRightHandPosition(position); - _skeletonModel.getRightHandRotation(rotation); + _skeletonModel.getRightHandPosition(handPosition); } - */ - // HACK: we temporarily boost the size of the hand so it is easier to collide with it - float handScaleFactor = 5.f; - if (_skeletonModel.findSpherePenetrationWithJoint(sphereCenter, sphereRadius, collision._penetration, jointIndex, handScaleFactor)) { + glm::vec3 diskCenter = handPosition + HAND_PADDLE_OFFSET * fingerAxis; + glm::vec3 diskNormal = palm->getNormal(); + + // collide against the disk + if (findSphereDiskPenetration(sphereCenter, sphereRadius, + diskCenter, HAND_PADDLE_RADIUS, diskNormal, collision._penetration)) { collision._addedVelocity = palm->getVelocity(); return true; } @@ -389,7 +397,6 @@ bool Avatar::findSphereCollision(const glm::vec3& sphereCenter, float sphereRadi } if (_skeletonModel.findSpherePenetration(sphereCenter, sphereRadius, collision._penetration)) { - // apply hard collision when particle collides with avatar collision._penetration /= (float)(TREE_SCALE); collision._addedVelocity = getVelocity(); return true; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index c7389b7edb..f167f6b31b 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -168,6 +168,11 @@ public: bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration, int skeletonSkipIndex = -1) const; + /// Checks for collision between the a sphere and the avatar. + /// \param collisionCenter the center of the penetration test sphere + /// \param collisionRadius the radius of the penetration test sphere + /// \param collision[out] the details of the collision point + /// \return whether or not the sphere collided virtual bool findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision); virtual int parseData(unsigned char* sourceBuffer, int numBytes); From 09bce076cc950e836ad79f6120ad2b95c069749a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 15 Jan 2014 14:06:31 -0800 Subject: [PATCH 11/16] All avatars now have disk collision proxies at their hands. --- .../particles/src/ParticleCollisionSystem.cpp | 47 ++++++------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index 7d199d3c38..417c1e0667 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -137,15 +137,14 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA) void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { - // particles that are in hand, don't collide with other avatar parts + // particles that are in hand, don't collide with avatars if (particle->getInHand()) { return; } - //printf("updateCollisionWithAvatars()...\n"); glm::vec3 center = particle->getPosition() * (float)(TREE_SCALE); float radius = particle->getRadius() * (float)(TREE_SCALE); - const float ELASTICITY = 0.4f; + const float ELASTICITY = 0.95f; const float DAMPING = 0.0f; const float COLLISION_FREQUENCY = 0.5f; glm::vec3 penetration; @@ -157,55 +156,37 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { CollisionInfo collision; if (avatar->findSphereCollision(center, radius, collision)) { if (glm::dot(particle->getVelocity(), collision._addedVelocity) < 0.f) { + // only collide when particle and collision point are moving toward each other collision._penetration /= (float)(TREE_SCALE); collision._addedVelocity /= (float)(TREE_SCALE); - glm::vec3 pv = particle->getVelocity(); updateCollisionSound(particle, collision._penetration, COLLISION_FREQUENCY); applyHardCollision(particle, collision._penetration, ELASTICITY, DAMPING, collision._addedVelocity); } } } - // TODO: convert other avatars to collide like _selfAvatar - // loop through all the other avatars for potential interactions... - foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { //qDebug() << "updateCollisionWithAvatars()... node:" << *node << "\n"; if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { - // TODO: dot collidingPalm and hand velocities and skip collision when they are moving apart. AvatarData* avatar = static_cast(node->getLinkedData()); - //printf("updateCollisionWithAvatars()...avatar=%p\n", avatar); - - // check hands... - const HandData* handData = avatar->getHandData(); - - if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) { - // apply a hard collision when ball collides with hand - penetration /= (float)(TREE_SCALE); - updateCollisionSound(particle, penetration, COLLISION_FREQUENCY); - - // determine if the palm that collided was moving, if so, then we add that palm velocity as well... - glm::vec3 addedVelocity = NO_ADDED_VELOCITY; - if (collidingPalm) { - glm::vec3 palmVelocity = collidingPalm->getVelocity() / (float)(TREE_SCALE); - //printf("collidingPalm Velocity=%f,%f,%f\n", palmVelocity.x, palmVelocity.y, palmVelocity.z); - addedVelocity = palmVelocity; + + CollisionInfo collision; + if (avatar->findSphereCollision(center, radius, collision)) { + if (glm::dot(particle->getVelocity(), collision._addedVelocity) < 0.f) { + // only collide when particle and collision point are moving toward each other + collision._penetration /= (float)(TREE_SCALE); + collision._addedVelocity /= (float)(TREE_SCALE); + updateCollisionSound(particle, collision._penetration, COLLISION_FREQUENCY); + applyHardCollision(particle, collision._penetration, ELASTICITY, DAMPING, collision._addedVelocity); } - - applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity); - - } else if (avatar->findSpherePenetration(center, radius, penetration)) { - penetration /= (float)(TREE_SCALE); - updateCollisionSound(particle, penetration, COLLISION_FREQUENCY); - glm::vec3 addedVelocity = avatar->getVelocity(); - applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity); } } } } +// TODO: convert applyHardCollision() to take a CollisionInfo& instead of penetration + addedVelocity void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm::vec3& penetration, float elasticity, float damping, const glm::vec3& addedVelocity) { // @@ -221,7 +202,7 @@ void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm:: const float EPSILON = 0.0f; float velocityDotPenetration = glm::dot(velocity, penetration); if (velocityDotPenetration > EPSILON) { - position -= penetration; + //position -= penetration; static float HALTING_VELOCITY = 0.2f / (float)(TREE_SCALE); // cancel out the velocity component in the direction of penetration From 76e8eb2bfc4ae11d0fbaf8cba798d755c3d474c2 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 15 Jan 2014 16:53:27 -0800 Subject: [PATCH 12/16] Moving SIXENSE_CONTROLLER_ID* constants into header to help eliminate magic numbers in other code (to be committed later). --- libraries/avatars/src/HandData.cpp | 3 --- libraries/avatars/src/HandData.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 62a15efb1a..7b0be95abe 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -38,9 +38,6 @@ PalmData& HandData::addNewPalm() { return _palms.back(); } -const int SIXENSE_CONTROLLER_ID_LEFT_HAND = 0; -const int SIXENSE_CONTROLLER_ID_RIGHT_HAND = 1; - const PalmData* HandData::getPalm(int sixSenseID) const { // the palms are not necessarily added in left-right order, // so we have to search for the right SixSenseID diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 8de0c2d9f8..1aa60da927 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -35,6 +35,9 @@ const int BUTTON_FWD = 128; const float LEAP_UNIT_SCALE = 0.001f; ///< convert mm to meters +const int SIXENSE_CONTROLLER_ID_LEFT_HAND = 0; +const int SIXENSE_CONTROLLER_ID_RIGHT_HAND = 1; + class HandData { public: HandData(AvatarData* owningAvatar); From 989b733de6abf64548afa9ec02f1d363e4402bac Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 15 Jan 2014 16:59:49 -0800 Subject: [PATCH 13/16] Removing magic numbers, but still only supporting 2 hands (the SkeletonModel currently has two hands hardcoded). --- interface/src/avatar/Hand.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 16693f88e2..b56e2c0c3d 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -617,8 +617,9 @@ void Hand::renderLeapHands(bool isMine) { } // Draw the hand paddles + int MAX_NUM_PADDLES = 2; // one for left and one for right glColor4f(handColor.r, handColor.g, handColor.b, 0.3f); - for (int i = 0; i < 2; i++) { + for (int i = 0; i < MAX_NUM_PADDLES; i++) { const PalmData* palm = getPalm(i); if (palm) { // compute finger axis @@ -634,9 +635,9 @@ void Hand::renderLeapHands(bool isMine) { } // compute paddle position glm::vec3 handPosition; - if (i == 0) { + if (i == SIXENSE_CONTROLLER_ID_LEFT_HAND) { _owningAvatar->getSkeletonModel().getLeftHandPosition(handPosition); - } else { + } else if (i == SIXENSE_CONTROLLER_ID_RIGHT_HAND) { _owningAvatar->getSkeletonModel().getRightHandPosition(handPosition); } glm::vec3 tip = handPosition + HAND_PADDLE_OFFSET * fingerAxis; From 4b94e53acf8c5058d9d6aa3e609907cf6783ca23 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 15 Jan 2014 17:02:02 -0800 Subject: [PATCH 14/16] Removing Model::findSpherePenetrationWithJoint() which was experimental method that was not finally used. --- interface/src/renderer/Model.cpp | 23 ----------------------- interface/src/renderer/Model.h | 11 ++++------- 2 files changed, 4 insertions(+), 30 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 8779672c25..3509357b0c 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -634,29 +634,6 @@ bool Model::findSpherePenetration(const glm::vec3& penetratorCenter, float penet return false; } -// TODO: purge this once we get proper collisions against hand paddles -bool Model::findSpherePenetrationWithJoint(const glm::vec3& sphereCenter, float sphereRadius, - glm::vec3& penetration, int jointIndex, float boneScale) const { - if (jointIndex < 0 || jointIndex > _jointStates.size()) { - return false; - } - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - const FBXJoint& joint = geometry.joints[jointIndex]; - glm::vec3 end = extractTranslation(_jointStates[jointIndex].transform); - float radiusScale = extractUniformScale(_scale) * boneScale; - float endRadius = joint.boneRadius * radiusScale; - glm::vec3 start = end; - float startRadius = joint.boneRadius * radiusScale; - glm::vec3 bonePenetration; - if (joint.parentIndex != -1) { - start = extractTranslation(_jointStates[joint.parentIndex].transform); - startRadius = geometry.joints[joint.parentIndex].boneRadius * radiusScale; - } - const glm::vec3 relativeCenter = sphereCenter - _translation; - return findSphereCapsuleConePenetration(relativeCenter, sphereRadius, start, end, - startRadius, endRadius, penetration); -} - void Model::updateJointState(int index) { JointState& state = _jointStates[index]; const FBXGeometry& geometry = _geometry->getFBXGeometry(); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index c0d3ea0fbc..ae4303caea 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -84,19 +84,19 @@ public: /// Retrieve the position of the left hand /// \return true whether or not the position was found - bool getLeftHandPosition(glm::vec3&) const; + bool getLeftHandPosition(glm::vec3& position) const; /// Retrieve the rotation of the left hand /// \return true whether or not the rotation was found - bool getLeftHandRotation(glm::quat&) const; + bool getLeftHandRotation(glm::quat& rotation) const; /// Retrieve the position of the right hand /// \return true whether or not the position was found - bool getRightHandPosition(glm::vec3&) const; + bool getRightHandPosition(glm::vec3& position) const; /// Retrieve the rotation of the right hand /// \return true whether or not the rotation was found - bool getRightHandRotation(glm::quat&) const; + bool getRightHandRotation(glm::quat& rotation) const; /// Sets the position of the left hand using inverse kinematics. /// \return whether or not the left hand joint was found @@ -146,9 +146,6 @@ public: bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration, float boneScale = 1.0f, int skipIndex = -1) const; - bool findSpherePenetrationWithJoint(const glm::vec3& sphereCenter, float sphereRadius, - glm::vec3& penetration, int jointIndex, float boneScale = 1.0f) const; - protected: QSharedPointer _geometry; From 221f830b5fed2abcc800f3f4ddc3aa38b744da35 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 15 Jan 2014 17:03:07 -0800 Subject: [PATCH 15/16] Uncommenting particle shift on penetration. --- libraries/particles/src/ParticleCollisionSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index 417c1e0667..78b1402461 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -202,7 +202,7 @@ void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm:: const float EPSILON = 0.0f; float velocityDotPenetration = glm::dot(velocity, penetration); if (velocityDotPenetration > EPSILON) { - //position -= penetration; + position -= penetration; static float HALTING_VELOCITY = 0.2f / (float)(TREE_SCALE); // cancel out the velocity component in the direction of penetration From a7600c06dd5b0c49b20eead85dfccdc383f49b18 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 15 Jan 2014 17:12:53 -0800 Subject: [PATCH 16/16] cruft removal --- libraries/shared/src/CollisionInfo.h | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/libraries/shared/src/CollisionInfo.h b/libraries/shared/src/CollisionInfo.h index b9d064f2ea..4f46a6bfd3 100644 --- a/libraries/shared/src/CollisionInfo.h +++ b/libraries/shared/src/CollisionInfo.h @@ -9,24 +9,6 @@ #ifndef __hifi__CollisionInfo__ #define __hifi__CollisionInfo__ -/* -#include -#include - -#ifdef _WIN32 -#include "Syssocket.h" -#else -#include -#endif - -#include -#include - -#include "HifiSockAddr.h" -#include "NodeData.h" -#include "SimpleMovingAverage.h" -*/ - #include class CollisionInfo {