From e02c7bed186dda9ccaea9018d19b3bee9b64c082 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 21 Jan 2014 10:11:20 -0800 Subject: [PATCH 01/24] Removing a magic number and collapsing two identical variables that hard-code the number of hands. --- interface/src/avatar/Avatar.cpp | 2 +- interface/src/avatar/Hand.cpp | 2 +- interface/src/avatar/Hand.h | 7 +++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 6db0a15300..34f2c45c9d 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -311,7 +311,7 @@ bool Avatar::findSphereCollision(const glm::vec3& sphereCenter, float sphereRadi const HandData* handData = getHandData(); if (handData) { - for (int i = 0; i < 2; i++) { + for (int i = 0; i < NUM_HANDS; i++) { const PalmData* palm = handData->getPalm(i); if (palm && palm->hasPaddle()) { // create a disk collision proxy where the hand is diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index e5be719b40..d3dec9d9e7 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -59,7 +59,7 @@ Hand::Hand(Avatar* owningAvatar) : _throwSound(QUrl("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw")), _catchSound(QUrl("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw")) { - for (int i = 0; i < MAX_HANDS; i++) { + for (int i = 0; i < NUM_HANDS; i++) { _toyBallInHand[i] = false; _ballParticleEditHandles[i] = NULL; _whichBallColor[i] = 0; diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 0552c021f1..af0125931d 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -104,10 +104,9 @@ private: void simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime); - #define MAX_HANDS 2 - bool _toyBallInHand[MAX_HANDS]; - int _whichBallColor[MAX_HANDS]; - ParticleEditHandle* _ballParticleEditHandles[MAX_HANDS]; + bool _toyBallInHand[NUM_HANDS]; + int _whichBallColor[NUM_HANDS]; + ParticleEditHandle* _ballParticleEditHandles[NUM_HANDS]; int _lastControllerButtons; float _pitchUpdate; From 2a2f2f2da0df7aa09a97ea137a1475e0aba0efd4 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 21 Jan 2014 10:45:43 -0800 Subject: [PATCH 02/24] Remove debug cruft. --- interface/src/devices/SixenseManager.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index af1eafc85b..79feb5eb3f 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -98,15 +98,6 @@ void SixenseManager::update(float deltaTime) { // Compute current velocity from position change glm::vec3 rawVelocity = (position - palm->getRawPosition()) / deltaTime / 1000.f; palm->setRawVelocity(rawVelocity); // meters/sec - /* - if (i == 0) - { - printf("ADEBUG rawVelocity = [%e, %e, %e]\n", - rawVelocity.x, - rawVelocity.y, - rawVelocity.z); - } - */ palm->setRawPosition(position); // use the velocity to determine whether there's any movement (if the hand isn't new) From da0d2c4776d2d8b91eb67f35dd2e44656c17f38e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 21 Jan 2014 14:00:16 -0800 Subject: [PATCH 03/24] Removing unecessary #include. --- interface/src/Util.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index d557eb67b3..339d49939d 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -15,7 +15,6 @@ #include #include -#include #include #include "InterfaceConfig.h" From db0bd83ab5a00aa7efb5ca07d58462b18cb1d3d2 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 21 Jan 2014 14:00:53 -0800 Subject: [PATCH 04/24] fix copy-paste typo in comment --- libraries/avatars/src/AvatarData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 35e6c37e96..5066210c85 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -64,7 +64,7 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { if (!_headData) { _headData = new HeadData(this); } - // lazily allocate memory for HeadData in case we're not an Avatar instance + // lazily allocate memory for HandData in case we're not an Avatar instance if (!_handData) { _handData = new HandData(this); } From c40d93ddce3e5a282725400b53af0b40db14483c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 22 Jan 2014 10:40:37 -0800 Subject: [PATCH 05/24] Fixing elasticity to range [0,1] during collisions. --- interface/src/avatar/MyAvatar.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index d10cd1b17d..9466607260 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -578,11 +578,10 @@ void MyAvatar::updateThrust(float deltaTime, Transmitter * transmitter) { _bodyYawDelta += rotation.y * TRANSMITTER_YAW_SCALE * deltaTime; } if (transmitter->getTouchState()->state == 'D') { - _thrust += TRANSMITTER_UP_FORCE_SCALE * - (float)(transmitter->getTouchState()->y - TOUCH_POSITION_RANGE_HALF) / TOUCH_POSITION_RANGE_HALF * - TRANSMITTER_LIFT_SCALE * - deltaTime * - up; + _thrust += (TRANSMITTER_UP_FORCE_SCALE * + (float)(transmitter->getTouchState()->y - TOUCH_POSITION_RANGE_HALF) / TOUCH_POSITION_RANGE_HALF * + TRANSMITTER_LIFT_SCALE * deltaTime) * + up; } } // Add thrust and rotation from hand controllers @@ -665,7 +664,7 @@ void MyAvatar::updateHandMovementAndTouching(float deltaTime) { void MyAvatar::updateCollisionWithEnvironment(float deltaTime) { glm::vec3 up = getBodyUpDirection(); float radius = _collisionRadius; - const float ENVIRONMENT_SURFACE_ELASTICITY = 1.0f; + const float ENVIRONMENT_SURFACE_ELASTICITY = 0.0f; const float ENVIRONMENT_SURFACE_DAMPING = 0.01f; const float ENVIRONMENT_COLLISION_FREQUENCY = 0.05f; glm::vec3 penetration; @@ -701,8 +700,8 @@ void MyAvatar::applyHardCollision(const glm::vec3& penetration, float elasticity // Update the avatar in response to a hard collision. Position will be reset exactly // to outside the colliding surface. Velocity will be modified according to elasticity. // - // if elasticity = 1.0, collision is inelastic. - // if elasticity > 1.0, collision is elastic. + // if elasticity = 0.0, collision is 100% inelastic. + // if elasticity = 1.0, collision is elastic. // _position -= penetration; static float HALTING_VELOCITY = 0.2f; @@ -711,7 +710,7 @@ void MyAvatar::applyHardCollision(const glm::vec3& penetration, float elasticity if (penetrationLength > EPSILON) { _elapsedTimeSinceCollision = 0.0f; glm::vec3 direction = penetration / penetrationLength; - _velocity -= glm::dot(_velocity, direction) * direction * elasticity; + _velocity -= glm::dot(_velocity, direction) * direction * (1.f + elasticity); _velocity *= glm::clamp(1.f - damping, 0.0f, 1.0f); if ((glm::length(_velocity) < HALTING_VELOCITY) && (glm::length(_thrust) == 0.f)) { // If moving really slowly after a collision, and not applying forces, stop altogether From 82f212bc19a37f294117d74276f591164e41797d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 22 Jan 2014 13:29:43 -0800 Subject: [PATCH 06/24] close issue #1602 (particles overlap during collisions) --- libraries/particles/src/ParticleCollisionSystem.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index dee0259eb7..e5bdc43cf3 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -120,16 +120,18 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA) particleA->setVelocity(particleA->getVelocity() - axialVelocity * (2.0f * massB / totalMass)); ParticleEditHandle particleEditHandle(_packetSender, _particles, particleA->getID()); - particleEditHandle.updateParticle(particleA->getPosition(), particleA->getRadius(), particleA->getXColor(), particleA->getVelocity(), + penetration /= (float)(TREE_SCALE); + glm::vec3 position = particleA->getPosition() - 0.5f * penetration; + particleEditHandle.updateParticle(position, particleA->getRadius(), particleA->getXColor(), particleA->getVelocity(), particleA->getGravity(), particleA->getDamping(), particleA->getInHand(), particleA->getScript()); particleB->setVelocity(particleB->getVelocity() + axialVelocity * (2.0f * massA / totalMass)); ParticleEditHandle penetratedparticleEditHandle(_packetSender, _particles, particleB->getID()); - penetratedparticleEditHandle.updateParticle(particleB->getPosition(), particleB->getRadius(), particleB->getXColor(), particleB->getVelocity(), + position = particleB->getPosition() + 0.5f * penetration; + penetratedparticleEditHandle.updateParticle(position, particleB->getRadius(), particleB->getXColor(), particleB->getVelocity(), particleB->getGravity(), particleB->getDamping(), particleB->getInHand(), particleB->getScript()); - penetration /= (float)(TREE_SCALE); updateCollisionSound(particleA, penetration, COLLISION_FREQUENCY); } } From 09b2d4aa7819067accb9402defb8c902752e4aa8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 22 Jan 2014 13:34:13 -0800 Subject: [PATCH 07/24] Added menu options for more detailed collision preferences. --- interface/src/Menu.cpp | 16 ++++++++------ interface/src/Menu.h | 4 ++++ interface/src/avatar/Avatar.cpp | 18 +++++++++++++++- interface/src/avatar/Avatar.h | 5 +++-- interface/src/avatar/MyAvatar.cpp | 31 ++++++++++++++-------------- interface/src/avatar/MyAvatar.h | 6 ++---- libraries/shared/src/CollisionInfo.h | 7 ++++++- 7 files changed, 58 insertions(+), 29 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 87edfa82a2..77560c7837 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -161,14 +161,18 @@ Menu::Menu() : addDisabledActionAndSeparator(editMenu, "Physics"); addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::Gravity, Qt::SHIFT | Qt::Key_G, true); - addCheckableActionToQMenuAndActionHash(editMenu, - MenuOption::Collisions, - 0, - true, - appInstance->getAvatar(), - SLOT(setWantCollisionsOn(bool))); + addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::ClickToFly); + + QMenu* collisionsOptionsMenu = editMenu->addMenu("Collision Options"); + + QObject* avatar = appInstance->getAvatar(); + addCheckableActionToQMenuAndActionHash(collisionsOptionsMenu, MenuOption::CollideWithEnvironment, 0, false, avatar, SLOT(updateCollisionFlags())); + addCheckableActionToQMenuAndActionHash(collisionsOptionsMenu, MenuOption::CollideWithAvatars, 0, false, avatar, SLOT(updateCollisionFlags())); + addCheckableActionToQMenuAndActionHash(collisionsOptionsMenu, MenuOption::CollideWithVoxels, 0, false, avatar, SLOT(updateCollisionFlags())); + // TODO: make this option work + //addCheckableActionToQMenuAndActionHash(collisionsOptionsMenu, MenuOption::CollideWithParticles, 0, false, avatar, SLOT(updateCollisionFlags())); QMenu* toolsMenu = addMenu("Tools"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b356f29a85..d751e825a3 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -161,6 +161,10 @@ namespace MenuOption { 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"; + const QString CollideWithVoxels = "Collide With Voxels"; + const QString CollideWithEnvironment = "Collide With World Boundaries"; const QString CopyVoxels = "Copy"; const QString CoverageMap = "Render Coverage Map"; const QString CoverageMapV2 = "Render Coverage Map V2"; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 34f2c45c9d..9212e3c2fa 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -88,8 +88,8 @@ Avatar::Avatar(Node* owningNode) : _worldUpDirection(DEFAULT_UP_DIRECTION), _mouseRayOrigin(0.0f, 0.0f, 0.0f), _mouseRayDirection(0.0f, 0.0f, 0.0f), - _isCollisionsOn(true), _moving(false), + _collisionFlags(0), _initialized(false) { // we may have been created in the network thread, but we live in the main thread @@ -437,6 +437,22 @@ void Avatar::resetSize() { qDebug("Reseted scale to %f", _targetScale); } +void Avatar::updateCollisionFlags() { + _collisionFlags = 0; + if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithEnvironment)) { + _collisionFlags |= COLLISION_GROUP_ENVIRONMENT; + } + if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithAvatars)) { + _collisionFlags |= COLLISION_GROUP_AVATARS; + } + if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithVoxels)) { + _collisionFlags |= COLLISION_GROUP_VOXELS; + } + //if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithParticles)) { + // _collisionFlags |= COLLISION_GROUP_PARTICLES; + //} +} + void Avatar::setScale(float scale) { _scale = scale; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 3f1da6bc31..78e5485edc 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -117,11 +117,11 @@ public: static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2); public slots: - void setWantCollisionsOn(bool wantCollisionsOn) { _isCollisionsOn = wantCollisionsOn; } void goHome(); void increaseSize(); void decreaseSize(); void resetSize(); + void updateCollisionFlags(); friend class MyAvatar; @@ -140,11 +140,12 @@ protected: glm::vec3 _worldUpDirection; glm::vec3 _mouseRayOrigin; glm::vec3 _mouseRayDirection; - bool _isCollisionsOn; float _stringLength; bool _moving; ///< set when position is changing + uint32_t _collisionFlags; + // protected methods... glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9466607260..0619ff425a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -112,20 +112,24 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { } // Only collide if we are not moving to a target - if (_isCollisionsOn && (glm::length(_moveTarget) < EPSILON)) { - + if (_collisionFlags != 0) { Camera* myCamera = Application::getInstance()->getCamera(); + float radius = getHeight() * COLLISION_RADIUS_SCALE; if (myCamera->getMode() == CAMERA_MODE_FIRST_PERSON && !OculusManager::isConnected()) { - _collisionRadius = myCamera->getAspectRatio() * (myCamera->getNearClip() / cos(myCamera->getFieldOfView() / 2.f)); - _collisionRadius *= COLLISION_RADIUS_SCALAR; - } else { - _collisionRadius = getHeight() * COLLISION_RADIUS_SCALE; + radius = myCamera->getAspectRatio() * (myCamera->getNearClip() / cos(myCamera->getFieldOfView() / 2.f)); + radius *= COLLISION_RADIUS_SCALAR; } - updateCollisionWithEnvironment(deltaTime); - updateCollisionWithVoxels(deltaTime); - updateAvatarCollisions(deltaTime); + if (_collisionFlags & COLLISION_GROUP_ENVIRONMENT) { + updateCollisionWithEnvironment(deltaTime, radius); + } + if (_collisionFlags & COLLISION_GROUP_VOXELS) { + updateCollisionWithVoxels(deltaTime, radius); + } + if (_collisionFlags & COLLISION_GROUP_AVATARS) { + updateAvatarCollisions(deltaTime); + } } // add thrust to velocity @@ -661,9 +665,8 @@ void MyAvatar::updateHandMovementAndTouching(float deltaTime) { } } -void MyAvatar::updateCollisionWithEnvironment(float deltaTime) { +void MyAvatar::updateCollisionWithEnvironment(float deltaTime, float radius) { glm::vec3 up = getBodyUpDirection(); - float radius = _collisionRadius; const float ENVIRONMENT_SURFACE_ELASTICITY = 0.0f; const float ENVIRONMENT_SURFACE_DAMPING = 0.01f; const float ENVIRONMENT_COLLISION_FREQUENCY = 0.05f; @@ -679,8 +682,7 @@ void MyAvatar::updateCollisionWithEnvironment(float deltaTime) { } -void MyAvatar::updateCollisionWithVoxels(float deltaTime) { - float radius = _collisionRadius; +void MyAvatar::updateCollisionWithVoxels(float deltaTime, float radius) { const float VOXEL_ELASTICITY = 0.4f; const float VOXEL_DAMPING = 0.0f; const float VOXEL_COLLISION_FREQUENCY = 0.5f; @@ -750,10 +752,9 @@ void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTim } void MyAvatar::updateAvatarCollisions(float deltaTime) { - // Reset detector for nearest avatar _distanceToNearestAvatar = std::numeric_limits::max(); - // loop through all the other avatars for potential interactions + // TODO: loop through all the other avatars for potential interactions } class SortedAvatar { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 894913f824..aad2adc8a2 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -39,7 +39,6 @@ public: void setLeanScale(float scale) { _leanScale = scale; } void setGravity(glm::vec3 gravity); void setOrientation(const glm::quat& orientation); - void setWantCollisionsOn(bool wantCollisionsOn) { _isCollisionsOn = wantCollisionsOn; } void setMoveTarget(const glm::vec3 moveTarget); // getters @@ -84,7 +83,6 @@ private: bool _speedBrakes; bool _isThrustOn; float _thrustMultiplier; - float _collisionRadius; glm::vec3 _moveTarget; int _moveTargetStepCounter; @@ -93,8 +91,8 @@ private: void updateThrust(float deltaTime, Transmitter * transmitter); void updateHandMovementAndTouching(float deltaTime); void updateAvatarCollisions(float deltaTime); - void updateCollisionWithEnvironment(float deltaTime); - void updateCollisionWithVoxels(float deltaTime); + void updateCollisionWithEnvironment(float deltaTime, float radius); + void updateCollisionWithVoxels(float deltaTime, float radius); void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping); void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency); void updateChatCircle(float deltaTime); diff --git a/libraries/shared/src/CollisionInfo.h b/libraries/shared/src/CollisionInfo.h index 1e4801788e..8a1fc1f2c5 100644 --- a/libraries/shared/src/CollisionInfo.h +++ b/libraries/shared/src/CollisionInfo.h @@ -11,6 +11,11 @@ #include +const uint32_t COLLISION_GROUP_ENVIRONMENT = 1U << 0; +const uint32_t COLLISION_GROUP_AVATARS = 1U << 1; +const uint32_t COLLISION_GROUP_VOXELS = 1U << 2; +const uint32_t COLLISION_GROUP_PARTICLES = 1U << 3; + class CollisionInfo { public: CollisionInfo() : _penetration(0.f), _addedVelocity(0.f) { } @@ -18,7 +23,7 @@ public: //glm::vec3 _point; //glm::vec3 _normal; - glm::vec3 _penetration; // depth that bodyA is penetrates bodyB + glm::vec3 _penetration; // depth that bodyA penetrates bodyB glm::vec3 _addedVelocity; }; From e4e495889d05d81434cf289f61910280747f41de Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 22 Jan 2014 16:06:49 -0800 Subject: [PATCH 08/24] added initial avatar-avatar collision stub --- interface/src/avatar/MyAvatar.cpp | 13 ++++++++++++- libraries/particles/src/ParticleCollisionSystem.cpp | 3 +-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0619ff425a..f0f7eef080 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -754,7 +754,18 @@ void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTim void MyAvatar::updateAvatarCollisions(float deltaTime) { // Reset detector for nearest avatar _distanceToNearestAvatar = std::numeric_limits::max(); - // TODO: loop through all the other avatars for potential interactions + float myRadius = (0.5f + COLLISION_RADIUS_SCALE) * getHeight(); + foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { + //qDebug() << "updateCollisionWithAvatars()... node:" << *node << "\n"; + if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { + Avatar* avatar = static_cast(node->getLinkedData()); + float theirRadius = (0.5f + COLLISION_RADIUS_SCALE) * avatar->getHeight(); + float distance = glm::length(_position - avatar->_position); + if (distance < myRadius + theirRadius) { + //printf("potential avatar collision d = %e\n", distance); + } + } + } } class SortedAvatar { diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index e5bdc43cf3..8935a82409 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -157,9 +157,8 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { // first check the selfAvatar if set... if (_selfAvatar) { - AvatarData* avatar = (AvatarData*)_selfAvatar; CollisionInfo collisionInfo; - if (avatar->findSphereCollision(center, radius, collisionInfo)) { + if (_selfAvatar->findSphereCollision(center, radius, collisionInfo)) { collisionInfo._addedVelocity /= (float)(TREE_SCALE); glm::vec3 relativeVelocity = collisionInfo._addedVelocity - particle->getVelocity(); if (glm::dot(relativeVelocity, collisionInfo._penetration) < 0.f) { From b2d60ec1f8d2e7eb089724601d689fa966c8ed77 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 29 Jan 2014 14:36:22 -0800 Subject: [PATCH 09/24] Fixing iteration through list of avatars. --- interface/src/avatar/MyAvatar.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 425eb6098e..898708fa37 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -110,7 +110,6 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { _velocity += _scale * _gravity * (GRAVITY_EARTH * deltaTime); } - // Only collide if we are not moving to a target if (_collisionFlags != 0) { Camera* myCamera = Application::getInstance()->getCamera(); @@ -758,17 +757,18 @@ void MyAvatar::updateAvatarCollisions(float deltaTime) { // Reset detector for nearest avatar _distanceToNearestAvatar = std::numeric_limits::max(); float myRadius = (0.5f + COLLISION_RADIUS_SCALE) * getHeight(); - foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { - //qDebug() << "updateCollisionWithAvatars()... node:" << *node << "\n"; - if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { - Avatar* avatar = static_cast(node->getLinkedData()); - float theirRadius = (0.5f + COLLISION_RADIUS_SCALE) * avatar->getHeight(); - float distance = glm::length(_position - avatar->_position); - if (distance < myRadius + theirRadius) { - //printf("potential avatar collision d = %e\n", distance); - } + foreach (const AvatarSharedPointer& avatarPointer, Application::getInstance()->getAvatarManager().getAvatarHash()) { + Avatar* avatar = static_cast(avatarPointer.data()); + float distance = glm::length(_position - avatar->_position); + if (_distanceToNearestAvatar > distance) { + _distanceToNearestAvatar = distance; + } + float theirRadius = (0.5f + COLLISION_RADIUS_SCALE) * avatar->getHeight(); + if (distance < myRadius + theirRadius) { + //printf("potential avatar collision d = %e\n", distance); } } + } class SortedAvatar { From 570b872eda156ce49c1b8c11694dacb306d993e0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 29 Jan 2014 14:43:01 -0800 Subject: [PATCH 10/24] Removing build warning about out-of-order initialization in class ctor. --- interface/src/avatar/Avatar.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 53775124d6..68f15a3390 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -73,8 +73,8 @@ Avatar::Avatar() : _mouseRayOrigin(0.0f, 0.0f, 0.0f), _mouseRayDirection(0.0f, 0.0f, 0.0f), _moving(false), - _collisionFlags(0), _owningAvatarMixer(), + _collisionFlags(0), _initialized(false) { // we may have been created in the network thread, but we live in the main thread diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 898708fa37..e057c34a2d 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -757,8 +757,13 @@ void MyAvatar::updateAvatarCollisions(float deltaTime) { // Reset detector for nearest avatar _distanceToNearestAvatar = std::numeric_limits::max(); float myRadius = (0.5f + COLLISION_RADIUS_SCALE) * getHeight(); - foreach (const AvatarSharedPointer& avatarPointer, Application::getInstance()->getAvatarManager().getAvatarHash()) { + const AvatarHash& avatars = Application::getInstance()->getAvatarManager().getAvatarHash(); + foreach (const AvatarSharedPointer& avatarPointer, avatars) { Avatar* avatar = static_cast(avatarPointer.data()); + if (static_cast(this) == avatar) { + // don't collide with ourselves + continue; + } float distance = glm::length(_position - avatar->_position); if (_distanceToNearestAvatar > distance) { _distanceToNearestAvatar = distance; From f3f15391118c1ac945dff0fcbf217ffcbb12c6c2 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 30 Jan 2014 09:28:21 -0800 Subject: [PATCH 11/24] Splitting avatar collision check in two: vs hands and vs skeleton. --- interface/src/avatar/Avatar.cpp | 7 ++++--- interface/src/avatar/Avatar.h | 11 +++++++++-- libraries/avatars/src/AvatarData.h | 6 +++++- libraries/particles/src/ParticleCollisionSystem.cpp | 3 ++- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 68f15a3390..88c7e03011 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -285,9 +285,7 @@ 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 - +bool Avatar::findSphereCollisionWithHands(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) { const HandData* handData = getHandData(); if (handData) { for (int i = 0; i < NUM_HANDS; i++) { @@ -326,7 +324,10 @@ bool Avatar::findSphereCollision(const glm::vec3& sphereCenter, float sphereRadi } } } + return false; +} +bool Avatar::findSphereCollisionWithSkeleton(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) { if (_skeletonModel.findSpherePenetration(sphereCenter, sphereRadius, collision._penetration)) { collision._penetration /= (float)(TREE_SCALE); collision._addedVelocity = getVelocity(); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index f6ff411624..1d8d5a1604 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -105,12 +105,19 @@ 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. + /// Checks for collision between the a sphere and the avatar's (paddle) hands. /// \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); + bool findSphereCollisionWithHands(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision); + + /// Checks for collision between the a sphere and the avatar's skeleton (including hand capsules). + /// \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 + bool findSphereCollisionWithSkeleton(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision); virtual bool isMyAvatar() { return false; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 0869445090..aa21b6d9c4 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -138,7 +138,11 @@ public: 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) { + virtual bool findSphereCollisionWithHands(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) { + return false; + } + + virtual bool findSphereCollisionWithSkeleton(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) { return false; } diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index 65c61edaa1..a194aba6ef 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -170,7 +170,8 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { CollisionInfo collisionInfo; collisionInfo._damping = DAMPING; collisionInfo._elasticity = ELASTICITY; - if (avatar->findSphereCollision(center, radius, collisionInfo)) { + if (avatar->findSphereCollisionWithHands(center, radius, collisionInfo) || + avatar->findSphereCollisionWithSkeleton(center, radius, collisionInfo)) { collisionInfo._addedVelocity /= (float)(TREE_SCALE); glm::vec3 relativeVelocity = collisionInfo._addedVelocity - particle->getVelocity(); if (glm::dot(relativeVelocity, collisionInfo._penetration) < 0.f) { From 4b8e1f270fdf9e6f7ed9518b8ca3cd640cdf3a51 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 30 Jan 2014 09:31:07 -0800 Subject: [PATCH 12/24] Adding preliminary/temporary code for testing hand-vs-avatar collisions. --- interface/src/avatar/MyAvatar.cpp | 34 +++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e057c34a2d..ead77d52ff 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -756,8 +756,24 @@ void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTim void MyAvatar::updateAvatarCollisions(float deltaTime) { // Reset detector for nearest avatar _distanceToNearestAvatar = std::numeric_limits::max(); - float myRadius = (0.5f + COLLISION_RADIUS_SCALE) * getHeight(); const AvatarHash& avatars = Application::getInstance()->getAvatarManager().getAvatarHash(); + if (avatars.size() <= 1) { + // no need to compute a bunch of stuff if we have one or fewer avatars + return; + } + float myRadius = (0.5f + COLLISION_RADIUS_SCALE) * getHeight(); + + // precompute hand proxies before we start walking the avatarlist + QVector handPositions; + glm::vec3 position; + if (_skeletonModel.getLeftHandPosition(position)) { + handPositions.push_back(position); + } + if (_skeletonModel.getRightHandPosition(position)) { + handPositions.push_back(position); + } + + CollisionInfo collisionInfo; foreach (const AvatarSharedPointer& avatarPointer, avatars) { Avatar* avatar = static_cast(avatarPointer.data()); if (static_cast(this) == avatar) { @@ -771,9 +787,23 @@ void MyAvatar::updateAvatarCollisions(float deltaTime) { float theirRadius = (0.5f + COLLISION_RADIUS_SCALE) * avatar->getHeight(); if (distance < myRadius + theirRadius) { //printf("potential avatar collision d = %e\n", distance); + // collide the hands like spheres + for (int i = 0; i < handPositions.size(); ++i) { + glm::vec3 pos = handPositions[i]; + distance = glm::length(_position - handPositions[i]); + printf("i = %d p = [%e, %e, %e] d = %e\n", i, pos.x, pos.y, pos.z, distance); + + // give each hand a spherical collision proxy + const float DEFAULT_HAND_RADIUS = 0.1f; + + // query against avatar + if (avatar->findSphereCollisionWithSkeleton(pos, DEFAULT_HAND_RADIUS, collisionInfo)) { + // print results + printf("collision i = %d p = [%e, %e, %e] d = %e\n", i, pos.x, pos.y, pos.z, distance); + } + } } } - } class SortedAvatar { From 64ca66a2b7119d4e9ee74d97dad4bf07e335c76b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 6 Feb 2014 14:09:08 -0800 Subject: [PATCH 13/24] Making renderCollisionProxies() public and measuring bounding volumes of hands. --- interface/src/avatar/SkeletonModel.cpp | 4 -- interface/src/renderer/FBXReader.cpp | 72 ++++++++++++++++++++++++++ interface/src/renderer/Model.h | 4 +- 3 files changed, 74 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 60ba470c5b..ac08c52b49 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -70,10 +70,6 @@ bool SkeletonModel::render(float alpha) { Model::render(alpha); - if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) { - renderCollisionProxies(alpha); - } - return true; } diff --git a/interface/src/renderer/FBXReader.cpp b/interface/src/renderer/FBXReader.cpp index e2c3bfafdd..64e19580ca 100644 --- a/interface/src/renderer/FBXReader.cpp +++ b/interface/src/renderer/FBXReader.cpp @@ -819,6 +819,44 @@ QString getTopModelID(const QMultiHash& parentMap, } } +// VBox = helper class that measures a bounding box around a collection of vertices +// This is a work in progress -- Andrew +class VBox { +public: + VBox() : _maxCorner(-FLT_MAX), _minCorner(FLT_MAX) {} + + void addVertex(const glm::vec3& vertex) { + if (vertex.x > _maxCorner.x) { + _maxCorner.x = vertex.x; + } + if (vertex.y > _maxCorner.y) { + _maxCorner.y = vertex.y; + } + if (vertex.z > _maxCorner.z) { + _maxCorner.z = vertex.z; + } + if (vertex.x < _minCorner.x) { + _minCorner.x = vertex.x; + } + if (vertex.y < _minCorner.y) { + _minCorner.y = vertex.y; + } + if (vertex.z < _minCorner.z) { + _minCorner.z = vertex.z; + } + } + + glm::vec3 getCenter() const { return 0.5f * (_minCorner + _maxCorner); } + + float getMaxDimension() const { + glm::vec3 dim = _maxCorner - _minCorner; + return glm::max(glm::max(dim.x, dim.y), dim.z); + } + + glm::vec3 _maxCorner; + glm::vec3 _minCorner; +}; + FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) { QHash meshes; QVector blendshapes; @@ -1245,11 +1283,16 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) geometry.leftFingertipJointIndices = getIndices(jointLeftFingertipIDs, modelIDs); geometry.rightFingertipJointIndices = getIndices(jointRightFingertipIDs, modelIDs); + bool hasBothHands = (geometry.rightHandJointIndex != -1 && geometry.leftHandJointIndex != -1); + // extract the translation component of the neck transform if (geometry.neckJointIndex != -1) { const glm::mat4& transform = geometry.joints.at(geometry.neckJointIndex).transform; geometry.neckPivot = glm::vec3(transform[3][0], transform[3][1], transform[3][2]); } + + VBox rightHandBox; + VBox leftHandBox; geometry.bindExtents.minimum = glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX); geometry.bindExtents.maximum = glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX); @@ -1379,6 +1422,24 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) const FBXCluster& fbxCluster = extracted.mesh.clusters.at(i); int jointIndex = fbxCluster.jointIndex; FBXJoint& joint = geometry.joints[jointIndex]; + + bool isRightHand = hasBothHands && jointIndex == geometry.rightHandJointIndex; + bool isLeftHand = hasBothHands && jointIndex == geometry.leftHandJointIndex; + if (hasBothHands && !isRightHand && !isLeftHand) { + // check to see if this + int parentIndex = joint.parentIndex; + while (parentIndex != -1) { + if (parentIndex == geometry.rightHandJointIndex) { + isRightHand = true; + break; + } else if (parentIndex == geometry.leftHandJointIndex) { + isLeftHand = true; + break; + } + parentIndex = geometry.joints[parentIndex].parentIndex; + } + } + glm::vec3 boneEnd = extractTranslation(inverseModelTransform * joint.bindTransform); glm::vec3 boneDirection; float boneLength; @@ -1402,6 +1463,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) const float EXPANSION_WEIGHT_THRESHOLD = 0.25f; if (weight > EXPANSION_WEIGHT_THRESHOLD) { const glm::vec3& vertex = extracted.mesh.vertices.at(it.value()); + // track vertex if it is on one of the hands + if (isRightHand) { + rightHandBox.addVertex(radiusScale * vertex); + } else if (isLeftHand) { + leftHandBox.addVertex(radiusScale * vertex); + } float proj = glm::dot(boneDirection, vertex - boneEnd); if (proj < 0.0f && proj > -boneLength) { joint.boneRadius = glm::max(joint.boneRadius, radiusScale * glm::distance( @@ -1524,6 +1591,11 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } geometry.attachments.append(attachment); } + if (hasBothHands) { + // use measured sizes of "hands" for bone radius of the joints + geometry.joints[geometry.rightHandJointIndex].boneRadius = 0.5f * rightHandBox.getMaxDimension(); + geometry.joints[geometry.leftHandJointIndex].boneRadius = 0.5f * leftHandBox.getMaxDimension(); + } return geometry; } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 389020d1b1..a89c338e52 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -151,6 +151,8 @@ public: bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration, float boneScale = 1.0f, int skipIndex = -1) const; + + void renderCollisionProxies(float alpha); protected: @@ -209,8 +211,6 @@ protected: void applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain = true); - void renderCollisionProxies(float alpha); - private: void deleteGeometry(); From b230f046a7b6447490b0945675e4212fd6a3e9ae Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 6 Feb 2014 14:11:11 -0800 Subject: [PATCH 14/24] Minor formating fixes. --- libraries/shared/src/CollisionInfo.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/CollisionInfo.h b/libraries/shared/src/CollisionInfo.h index e19d113cb0..d48c22c876 100644 --- a/libraries/shared/src/CollisionInfo.h +++ b/libraries/shared/src/CollisionInfo.h @@ -22,8 +22,8 @@ public: : _damping(0.f), _elasticity(1.f), _penetration(0.f), - _addedVelocity(0.f) { - } + _addedVelocity(0.f) { + } ~CollisionInfo() {} From 802967512a744d01aed9b978df08b38a175d5412 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 6 Feb 2014 14:14:48 -0800 Subject: [PATCH 15/24] Splitting rendering of avatars and their collision proxies. Also disabling old hand-avatar interactions and trying to use new stuff. --- interface/src/avatar/Avatar.cpp | 8 +- interface/src/avatar/AvatarManager.cpp | 3 - interface/src/avatar/Hand.cpp | 106 ++++++++++++------------- interface/src/avatar/MyAvatar.cpp | 69 +++++++++++----- 4 files changed, 105 insertions(+), 81 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 88c7e03011..2452ea3ade 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -160,7 +160,13 @@ void Avatar::render(bool forceRenderHead) { Glower glower(_moving && glm::length(toTarget) > GLOW_DISTANCE ? 1.0f : 0.0f); // render body - renderBody(forceRenderHead); + if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) { + _skeletonModel.renderCollisionProxies(1.f); + } + + if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { + renderBody(forceRenderHead); + } // render sphere when far away const float MAX_ANGLE = 10.f; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 6a44eb98aa..ec4f01a80c 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -111,9 +111,6 @@ void AvatarManager::updateAvatars(float deltaTime) { } void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { - if (!Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { - return; - } PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::renderAvatars()"); bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors); diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index b441000cc1..366b03418e 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -84,15 +84,14 @@ void Hand::simulate(float deltaTime, bool isMine) { if (isMine) { _buckyBalls.simulate(deltaTime); - updateCollisions(); + // TODO: recover this stuff after avatar-avatar collisions work again - Andrew + //updateCollisions(); } calculateGeometry(); if (isMine) { - // Iterate hand controllers, take actions as needed - for (size_t i = 0; i < getNumPalms(); ++i) { PalmData& palm = getPalms()[i]; if (palm.isActive()) { @@ -182,52 +181,54 @@ void Hand::updateCollisions() { float scaledPalmRadius = PALM_COLLISION_RADIUS * _owningAvatar->getScale(); glm::vec3 totalPenetration; - // check other avatars - foreach (const AvatarSharedPointer& avatarPointer, Application::getInstance()->getAvatarManager().getAvatarHash()) { - Avatar* avatar = static_cast(avatarPointer.data()); - if (avatar == _owningAvatar) { - // don't collid with our own hands - continue; - } - if (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 (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithAvatars)) { + // check other avatars + foreach (const AvatarSharedPointer& avatarPointer, Application::getInstance()->getAvatarManager().getAvatarHash()) { + Avatar* avatar = static_cast(avatarPointer.data()); + if (avatar == _owningAvatar) { + // don't collid with our own hands + continue; + } + if (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 + } + } + + } - - } } - } - glm::vec3 avatarPenetration; - if (avatar->findSpherePenetration(palm.getPosition(), scaledPalmRadius, avatarPenetration)) { - totalPenetration = addPenetrations(totalPenetration, avatarPenetration); - // Check for collisions with the other avatar's leap palms + glm::vec3 avatarPenetration; + if (avatar->findSpherePenetration(palm.getPosition(), scaledPalmRadius, avatarPenetration)) { + totalPenetration = addPenetrations(totalPenetration, avatarPenetration); + // Check for collisions with the other avatar's leap palms + } } } @@ -278,14 +279,14 @@ void Hand::calculateGeometry() { FingerData& finger = palm.getFingers()[f]; if (finger.isActive()) { const float standardBallRadius = FINGERTIP_COLLISION_RADIUS; - _leapFingerTipBalls.resize(_leapFingerTipBalls.size() + 1); - HandBall& ball = _leapFingerTipBalls.back(); + HandBall ball; ball.rotation = getBaseOrientation(); ball.position = finger.getTipPosition(); ball.radius = standardBallRadius; ball.touchForce = 0.0; ball.isCollidable = true; ball.isColliding = false; + _leapFingerTipBalls.push_back(ball); } } } @@ -300,14 +301,14 @@ void Hand::calculateGeometry() { FingerData& finger = palm.getFingers()[f]; if (finger.isActive()) { const float standardBallRadius = 0.005f; - _leapFingerRootBalls.resize(_leapFingerRootBalls.size() + 1); - HandBall& ball = _leapFingerRootBalls.back(); + HandBall ball; ball.rotation = getBaseOrientation(); ball.position = finger.getRootPosition(); ball.radius = standardBallRadius; ball.touchForce = 0.0; ball.isCollidable = true; ball.isColliding = false; + _leapFingerRootBalls.push_back(ball); } } } @@ -473,8 +474,3 @@ void Hand::setLeapHands(const std::vector& handPositions, } } - - - - - diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ead77d52ff..ac73e71fe4 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -380,7 +380,12 @@ void MyAvatar::renderDebugBodyPoints() { void MyAvatar::render(bool forceRenderHead) { // render body - renderBody(forceRenderHead); + if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) { + _skeletonModel.renderCollisionProxies(1.f); + } + if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { + renderBody(forceRenderHead); + } //renderDebugBodyPoints(); @@ -753,6 +758,21 @@ void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTim } } +// this is a work in progress +class PalmCollisionProxy { +public: + PalmCollisionProxy() : _palmIndex(-1), _position(0.f), _radius(0.f) {} + + PalmCollisionProxy(int index, const glm::vec3& position, float radius) : + _palmIndex(index), _position(position), _radius(radius) {} + + int _palmIndex; + glm::vec3 _position; + float _radius; +}; + +const float DEFAULT_HAND_RADIUS = 0.1f; + void MyAvatar::updateAvatarCollisions(float deltaTime) { // Reset detector for nearest avatar _distanceToNearestAvatar = std::numeric_limits::max(); @@ -761,18 +781,28 @@ void MyAvatar::updateAvatarCollisions(float deltaTime) { // no need to compute a bunch of stuff if we have one or fewer avatars return; } - float myRadius = (0.5f + COLLISION_RADIUS_SCALE) * getHeight(); + float myRadius = getHeight(); // precompute hand proxies before we start walking the avatarlist - QVector handPositions; + QVector palmProxies; + std::vector& palms = getHand().getPalms(); + size_t numPalms = palms.size(); glm::vec3 position; - if (_skeletonModel.getLeftHandPosition(position)) { - handPositions.push_back(position); + for (int i = 0; i < numPalms; ++i) { + PalmData& palm = palms[i]; + if (palm.getSixenseID() == SIXENSE_CONTROLLER_ID_LEFT_HAND) { + if (_skeletonModel.getLeftHandPosition(position)) { + float radius = DEFAULT_HAND_RADIUS; + palmProxies.push_back(PalmCollisionProxy(i, position, radius)); + } + } else if (palm.getSixenseID() == SIXENSE_CONTROLLER_ID_RIGHT_HAND) { + if (_skeletonModel.getRightHandPosition(position)) { + float radius = DEFAULT_HAND_RADIUS; + palmProxies.push_back(PalmCollisionProxy(i, position, radius)); + } + } } - if (_skeletonModel.getRightHandPosition(position)) { - handPositions.push_back(position); - } - + CollisionInfo collisionInfo; foreach (const AvatarSharedPointer& avatarPointer, avatars) { Avatar* avatar = static_cast(avatarPointer.data()); @@ -784,22 +814,17 @@ void MyAvatar::updateAvatarCollisions(float deltaTime) { if (_distanceToNearestAvatar > distance) { _distanceToNearestAvatar = distance; } - float theirRadius = (0.5f + COLLISION_RADIUS_SCALE) * avatar->getHeight(); + float theirRadius = avatar->getHeight(); if (distance < myRadius + theirRadius) { - //printf("potential avatar collision d = %e\n", distance); - // collide the hands like spheres - for (int i = 0; i < handPositions.size(); ++i) { - glm::vec3 pos = handPositions[i]; - distance = glm::length(_position - handPositions[i]); - printf("i = %d p = [%e, %e, %e] d = %e\n", i, pos.x, pos.y, pos.z, distance); - - // give each hand a spherical collision proxy - const float DEFAULT_HAND_RADIUS = 0.1f; - + for (int i = 0; i < palmProxies.size(); ++i) { + glm::vec3 pos = palmProxies[i]._position; // query against avatar - if (avatar->findSphereCollisionWithSkeleton(pos, DEFAULT_HAND_RADIUS, collisionInfo)) { + if (avatar->findSphereCollisionWithSkeleton(pos, palmProxies[i]._radius, collisionInfo)) { + // push hand out of penetration + palms[palmProxies[i]._palmIndex].addToPosition(0.5f * collisionInfo._penetration); // print results - printf("collision i = %d p = [%e, %e, %e] d = %e\n", i, pos.x, pos.y, pos.z, distance); + //distance = glm::length(collisionInfo._penetration); + //printf("collision i = %d p = [%e, %e, %e] d = %e\n", i, pos.x, pos.y, pos.z, distance); } } } From d2d32d0ed9f03740c73dfcd4ef257c012834e5d5 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 6 Feb 2014 14:46:44 -0800 Subject: [PATCH 16/24] Changing updateAvatarCollisions() to be updateCollisionsWithAvatars() To agree with names of other similar methods. --- interface/src/avatar/MyAvatar.cpp | 4 ++-- interface/src/avatar/MyAvatar.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 2ea8b94336..f5626cc01a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -225,7 +225,7 @@ void MyAvatar::simulate(float deltaTime) { updateCollisionWithVoxels(deltaTime, radius); } if (_collisionFlags & COLLISION_GROUP_AVATARS) { - updateAvatarCollisions(deltaTime); + updateCollisionsWithAvatars(deltaTime); } } @@ -970,7 +970,7 @@ public: const float DEFAULT_HAND_RADIUS = 0.1f; -void MyAvatar::updateAvatarCollisions(float deltaTime) { +void MyAvatar::updateCollisionsWithAvatars(float deltaTime) { // Reset detector for nearest avatar _distanceToNearestAvatar = std::numeric_limits::max(); const AvatarHash& avatars = Application::getInstance()->getAvatarManager().getAvatarHash(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index faa8cc48e5..e6861b6bae 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -123,7 +123,7 @@ private: void renderBody(bool forceRenderHead); void updateThrust(float deltaTime); void updateHandMovementAndTouching(float deltaTime); - void updateAvatarCollisions(float deltaTime); + void updateCollisionsWithAvatars(float deltaTime); void updateCollisionWithEnvironment(float deltaTime, float radius); void updateCollisionWithVoxels(float deltaTime, float radius); void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping); From eae0f8b2e6cd4be97dbf2a8cddf5fe2988a0583e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 6 Feb 2014 14:49:25 -0800 Subject: [PATCH 17/24] updateCollisionsWithAvatars() --> updateCollisionWithAvatars() --- interface/src/avatar/MyAvatar.cpp | 4 ++-- interface/src/avatar/MyAvatar.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index f5626cc01a..0742922533 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -225,7 +225,7 @@ void MyAvatar::simulate(float deltaTime) { updateCollisionWithVoxels(deltaTime, radius); } if (_collisionFlags & COLLISION_GROUP_AVATARS) { - updateCollisionsWithAvatars(deltaTime); + updateCollisionWithAvatars(deltaTime); } } @@ -970,7 +970,7 @@ public: const float DEFAULT_HAND_RADIUS = 0.1f; -void MyAvatar::updateCollisionsWithAvatars(float deltaTime) { +void MyAvatar::updateCollisionWithAvatars(float deltaTime) { // Reset detector for nearest avatar _distanceToNearestAvatar = std::numeric_limits::max(); const AvatarHash& avatars = Application::getInstance()->getAvatarManager().getAvatarHash(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index e6861b6bae..06813b087f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -123,7 +123,7 @@ private: void renderBody(bool forceRenderHead); void updateThrust(float deltaTime); void updateHandMovementAndTouching(float deltaTime); - void updateCollisionsWithAvatars(float deltaTime); + void updateCollisionWithAvatars(float deltaTime); void updateCollisionWithEnvironment(float deltaTime, float radius); void updateCollisionWithVoxels(float deltaTime, float radius); void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping); From 0a4eec448e6a9ab85f285d42b01f34eed83f52d6 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 7 Feb 2014 10:47:00 -0800 Subject: [PATCH 18/24] Removing findSpherePenetration() from AvatarData class --- libraries/avatars/src/AvatarData.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index aa21b6d9c4..88c5a53c9a 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -129,15 +129,6 @@ public: virtual const glm::vec3& getVelocity() const { return vec3Zero; } - /// Checks for penetration between the described sphere and the avatar. - /// \param penetratorCenter the center of the penetration test sphere - /// \param penetratorRadius the radius of the penetration test sphere - /// \param penetration[out] the vector in which to store the penetration - /// \param skeletonSkipIndex if not -1, the index of a joint to skip (along with its descendents) in the skeleton model - /// \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 findSphereCollisionWithHands(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) { return false; } From 7a8186f1da50fca6791b36824717be9acef6e324 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 7 Feb 2014 10:48:30 -0800 Subject: [PATCH 19/24] Adding ModelCollisionInfo struct to get more info about collisions against avatars. Had to disable some collisions. Will go back and make them work again soon. --- interface/src/avatar/Avatar.cpp | 47 +++++++++++++------ interface/src/avatar/Avatar.h | 13 +++-- interface/src/avatar/Hand.cpp | 22 +++++---- interface/src/avatar/MyAvatar.cpp | 6 ++- interface/src/renderer/Model.cpp | 16 ++++--- interface/src/renderer/Model.h | 14 +++++- .../particles/src/ParticleCollisionSystem.cpp | 5 +- 7 files changed, 85 insertions(+), 38 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 73a72d8aba..4236e069d1 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -271,26 +271,26 @@ bool Avatar::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc return false; } -bool Avatar::findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, - glm::vec3& penetration, int skeletonSkipIndex) const { +bool Avatar::findSphereCollisions(const glm::vec3& penetratorCenter, float penetratorRadius, + ModelCollisionList& collisions, int skeletonSkipIndex) { bool didPenetrate = false; - glm::vec3 totalPenetration; glm::vec3 skeletonPenetration; - if (_skeletonModel.findSpherePenetration(penetratorCenter, penetratorRadius, - skeletonPenetration, 1.0f, skeletonSkipIndex)) { - totalPenetration = addPenetrations(totalPenetration, skeletonPenetration); + ModelCollisionInfo collisionInfo; + int jointIndex = _skeletonModel.findSphereCollision(penetratorCenter, penetratorRadius, + collisionInfo, 1.0f, skeletonSkipIndex); + if (jointIndex != -1) { + collisionInfo._model = &_skeletonModel; + collisions.push_back(collisionInfo); didPenetrate = true; } glm::vec3 facePenetration; - if (_head.getFaceModel().findSpherePenetration(penetratorCenter, penetratorRadius, facePenetration)) { - totalPenetration = addPenetrations(totalPenetration, facePenetration); + jointIndex = _head.getFaceModel().findSphereCollision(penetratorCenter, penetratorRadius, collisionInfo); + if (jointIndex != -1) { + collisionInfo._model = &(_head.getFaceModel()); + collisions.push_back(collisionInfo); didPenetrate = true; } - if (didPenetrate) { - penetration = totalPenetration; - return true; - } - return false; + return didPenetrate; } bool Avatar::findSphereCollisionWithHands(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) { @@ -335,14 +335,17 @@ bool Avatar::findSphereCollisionWithHands(const glm::vec3& sphereCenter, float s return false; } +/* adebug TODO: make this work again bool Avatar::findSphereCollisionWithSkeleton(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) { - if (_skeletonModel.findSpherePenetration(sphereCenter, sphereRadius, collision._penetration)) { + int jointIndex = _skeletonModel.findSphereCollision(sphereCenter, sphereRadius, collision._penetration); + if (jointIndex != -1) { collision._penetration /= (float)(TREE_SCALE); collision._addedVelocity = getVelocity(); return true; } return false; } +*/ int Avatar::parseData(const QByteArray& packet) { // change in position implies movement @@ -404,6 +407,22 @@ void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, glEnd(); } +void Avatar::updateCollisionFlags() { + _collisionFlags = 0; + if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithEnvironment)) { + _collisionFlags |= COLLISION_GROUP_ENVIRONMENT; + } + if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithAvatars)) { + _collisionFlags |= COLLISION_GROUP_AVATARS; + } + if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithVoxels)) { + _collisionFlags |= COLLISION_GROUP_VOXELS; + } + //if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithParticles)) { + // _collisionFlags |= COLLISION_GROUP_PARTICLES; + //} +} + void Avatar::setScale(float scale) { _scale = scale; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 0f91c54dbf..ca1b3cf49d 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -57,6 +57,8 @@ enum ScreenTintLayer { NUM_SCREEN_TINT_LAYERS }; +typedef QVector ModelCollisionList; + // Where one's own Avatar begins in the world (will be overwritten if avatar data file is found) // this is basically in the center of the ground plane. Slightly adjusted. This was asked for by // Grayson as he's building a street around here for demo dinner 2 @@ -96,11 +98,11 @@ public: /// Checks for penetration between the described sphere and the avatar. /// \param penetratorCenter the center of the penetration test sphere /// \param penetratorRadius the radius of the penetration test sphere - /// \param penetration[out] the vector in which to store the penetration + /// \param collisions[out] a list of collisions /// \param skeletonSkipIndex if not -1, the index of a joint to skip (along with its descendents) in the skeleton model /// \return whether or not the sphere penetrated - bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, - glm::vec3& penetration, int skeletonSkipIndex = -1) const; + bool findSphereCollisions(const glm::vec3& penetratorCenter, float penetratorRadius, + ModelCollisionList& collisions, int skeletonSkipIndex = -1); /// Checks for collision between the a sphere and the avatar's (paddle) hands. /// \param collisionCenter the center of the penetration test sphere @@ -114,7 +116,7 @@ public: /// \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 - bool findSphereCollisionWithSkeleton(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision); + //bool findSphereCollisionWithSkeleton(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision); virtual bool isMyAvatar() { return false; } @@ -124,6 +126,9 @@ public: float getHeight() const; +public slots: + void updateCollisionFlags(); + protected: Head _head; Hand _hand; diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 366b03418e..92eb5e5117 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -84,8 +84,7 @@ void Hand::simulate(float deltaTime, bool isMine) { if (isMine) { _buckyBalls.simulate(deltaTime); - // TODO: recover this stuff after avatar-avatar collisions work again - Andrew - //updateCollisions(); + updateCollisions(); } calculateGeometry(); @@ -172,6 +171,7 @@ void Hand::updateCollisions() { int leftPalmIndex, rightPalmIndex; getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex); + ModelCollisionList collisions; // check for collisions for (size_t i = 0; i < getNumPalms(); i++) { PalmData& palm = getPalms()[i]; @@ -224,9 +224,10 @@ void Hand::updateCollisions() { } } } - glm::vec3 avatarPenetration; - if (avatar->findSpherePenetration(palm.getPosition(), scaledPalmRadius, avatarPenetration)) { - totalPenetration = addPenetrations(totalPenetration, avatarPenetration); + if (avatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, collisions)) { + for (size_t j = 0; j < collisions.size(); ++j) { + totalPenetration = addPenetrations(totalPenetration, collisions[j]._penetration); + } // Check for collisions with the other avatar's leap palms } } @@ -234,18 +235,23 @@ void Hand::updateCollisions() { if (Menu::getInstance()->isOptionChecked(MenuOption::HandsCollideWithSelf)) { // and the current avatar (ignoring everything below the parent of the parent of the last free joint) - glm::vec3 owningPenetration; + collisions.clear(); const Model& skeletonModel = _owningAvatar->getSkeletonModel(); int skipIndex = skeletonModel.getParentJointIndex(skeletonModel.getParentJointIndex( skeletonModel.getLastFreeJointIndex((i == leftPalmIndex) ? skeletonModel.getLeftHandJointIndex() : (i == rightPalmIndex) ? skeletonModel.getRightHandJointIndex() : -1))); - if (_owningAvatar->findSpherePenetration(palm.getPosition(), scaledPalmRadius, owningPenetration, skipIndex)) { - totalPenetration = addPenetrations(totalPenetration, owningPenetration); + if (_owningAvatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, collisions, skipIndex)) { + for (size_t j = 0; j < collisions.size(); ++j) { + totalPenetration = addPenetrations(totalPenetration, collisions[j]._penetration); + } } } // un-penetrate palm.addToPosition(-totalPenetration); + + // we recycle the collisions container, so we clear it for the next loop + collisions.clear(); } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0742922533..e0a6dbd1aa 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -225,7 +225,8 @@ void MyAvatar::simulate(float deltaTime) { updateCollisionWithVoxels(deltaTime, radius); } if (_collisionFlags & COLLISION_GROUP_AVATARS) { - updateCollisionWithAvatars(deltaTime); + // TODO: Andrew to implement this + //updateCollisionWithAvatars(deltaTime); } } @@ -1017,8 +1018,9 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) { glm::vec3 pos = palmProxies[i]._position; // query against avatar if (avatar->findSphereCollisionWithSkeleton(pos, palmProxies[i]._radius, collisionInfo)) { + // TODO: Andrew to make this work // push hand out of penetration - palms[palmProxies[i]._palmIndex].addToPosition(0.5f * collisionInfo._penetration); + //palms[palmProxies[i]._palmIndex].addToPosition(0.5f * collisionInfo._penetration * float(TREE_SCALE)); // print results //distance = glm::length(collisionInfo._penetration); //printf("collision i = %d p = [%e, %e, %e] d = %e\n", i, pos.x, pos.y, pos.z, distance); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 6d61b2df68..9404e99cd5 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -437,11 +437,11 @@ bool Model::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct return false; } -bool Model::findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, - glm::vec3& penetration, float boneScale, int skipIndex) const { +bool Model::findSphereCollision(const glm::vec3& penetratorCenter, float penetratorRadius, + ModelCollisionInfo& collisionInfo, float boneScale, int skipIndex) const { + int jointIndex = -1; const glm::vec3 relativeCenter = penetratorCenter - _translation; const FBXGeometry& geometry = _geometry->getFBXGeometry(); - bool didPenetrate = false; glm::vec3 totalPenetration; float radiusScale = extractUniformScale(_scale) * boneScale; for (int i = 0; i < _jointStates.size(); i++) { @@ -468,12 +468,16 @@ bool Model::findSpherePenetration(const glm::vec3& penetratorCenter, float penet if (findSphereCapsuleConePenetration(relativeCenter, penetratorRadius, start, end, startRadius, endRadius, bonePenetration)) { totalPenetration = addPenetrations(totalPenetration, bonePenetration); - didPenetrate = true; + // TODO: Andrew to try to keep the joint furthest toward the root + jointIndex = i; } outerContinue: ; } - if (didPenetrate) { - penetration = totalPenetration; + if (jointIndex != -1) { + // TODO? Andrew to store contactPoint + // don't store collisionInfo._model at this stage, let the outer context do that + collisionInfo._penetration = totalPenetration; + collisionInfo._jointIndex = jointIndex; return true; } return false; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index a89c338e52..035dd689dc 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -17,6 +17,16 @@ #include "ProgramObject.h" #include "TextureCache.h" +class Model; + +// TODO: Andrew to move this into its own file +class ModelCollisionInfo : public CollisionInfo { +public: + ModelCollisionInfo() : CollisionInfo(), _model(NULL), _jointIndex(-1) {} + Model* _model; + int _jointIndex; +}; + /// A generic 3D model displaying geometry loaded from a URL. class Model : public QObject { Q_OBJECT @@ -149,8 +159,8 @@ public: bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; - bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, - glm::vec3& penetration, float boneScale = 1.0f, int skipIndex = -1) const; + bool findSphereCollision(const glm::vec3& penetratorCenter, float penetratorRadius, + ModelCollisionInfo& collision, float boneScale = 1.0f, int skipIndex = -1) const; void renderCollisionProxies(float alpha); diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index 4b3f1b7066..bb0260c2bf 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -186,8 +186,9 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { CollisionInfo collisionInfo; collisionInfo._damping = DAMPING; collisionInfo._elasticity = ELASTICITY; - if (avatar->findSphereCollisionWithHands(center, radius, collisionInfo) || - avatar->findSphereCollisionWithSkeleton(center, radius, collisionInfo)) { + if (avatar->findSphereCollisionWithHands(center, radius, collisionInfo)) { + // TODO: Andrew to resurrect particles-vs-avatar body collisions + //avatar->findSphereCollisionWithSkeleton(center, radius, collisionInfo)) { collisionInfo._addedVelocity /= (float)(TREE_SCALE); glm::vec3 relativeVelocity = collisionInfo._addedVelocity - particle->getVelocity(); if (glm::dot(relativeVelocity, collisionInfo._penetration) < 0.f) { From 10296577f4ef79da6ec8ee3bdeff81185dbfd978 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 10 Feb 2014 09:02:29 -0800 Subject: [PATCH 20/24] More info when colliding with meshes + stubbery for poking avatar. --- interface/src/avatar/Avatar.cpp | 14 ++++++++++++++ interface/src/avatar/Avatar.h | 2 ++ interface/src/avatar/Hand.cpp | 5 ++--- interface/src/renderer/Model.cpp | 2 +- libraries/shared/src/CollisionInfo.h | 5 +++-- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 4236e069d1..1ae6331a8a 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -437,6 +437,20 @@ float Avatar::getHeight() const { return extents.maximum.y - extents.minimum.y; } +void Avatar::poke(ModelCollisionInfo& collision) { + if (collision._model == &_skeletonModel + && collision._jointIndex != -1) { + // TODO: Andrew to make this work + printf("ADEBUG model = 0x%x joint = %d p = [%e, %e, %e]\n", + collision._model, + collision._jointIndex, + collision._contactPoint.x, + collision._contactPoint.y, + collision._contactPoint.z + ); + } +} + float Avatar::getPelvisFloatingHeight() const { return -_skeletonModel.getBindExtents().minimum.y; } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ca1b3cf49d..560680e2aa 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -126,6 +126,8 @@ public: float getHeight() const; + void poke(ModelCollisionInfo& collision); + public slots: void updateCollisionFlags(); diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 92eb5e5117..feff0a699d 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -219,16 +219,15 @@ void Hand::updateCollisions() { // add slapback here } } - - } } } if (avatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, collisions)) { for (size_t j = 0; j < collisions.size(); ++j) { totalPenetration = addPenetrations(totalPenetration, collisions[j]._penetration); + // TODO: Andrew to poke avatar using collision info + avatar->poke(collisions[i]); } - // Check for collisions with the other avatar's leap palms } } } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 9404e99cd5..d71732cbde 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -474,10 +474,10 @@ bool Model::findSphereCollision(const glm::vec3& penetratorCenter, float penetra outerContinue: ; } if (jointIndex != -1) { - // TODO? Andrew to store contactPoint // don't store collisionInfo._model at this stage, let the outer context do that collisionInfo._penetration = totalPenetration; collisionInfo._jointIndex = jointIndex; + collisionInfo._contactPoint = penetratorCenter + penetratorRadius * glm::normalize(totalPenetration); return true; } return false; diff --git a/libraries/shared/src/CollisionInfo.h b/libraries/shared/src/CollisionInfo.h index d48c22c876..1fa95cd83a 100644 --- a/libraries/shared/src/CollisionInfo.h +++ b/libraries/shared/src/CollisionInfo.h @@ -21,17 +21,18 @@ public: CollisionInfo() : _damping(0.f), _elasticity(1.f), + _contactPoint(0.f), _penetration(0.f), _addedVelocity(0.f) { } ~CollisionInfo() {} - //glm::vec3 _point; //glm::vec3 _normal; float _damping; float _elasticity; - glm::vec3 _penetration; // depth that bodyA is penetrates bodyB + glm::vec3 _contactPoint; // world-frame point on bodyA that is deepest into bodyB + glm::vec3 _penetration; // depth that bodyA penetrates into bodyB glm::vec3 _addedVelocity; }; From e5a700bf79e6783cf897e8f6ffbdf4440db61269 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 10 Feb 2014 09:59:22 -0800 Subject: [PATCH 21/24] Fix crash -- use correct index. --- interface/src/avatar/Hand.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index feff0a699d..a67aa788e3 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -226,7 +226,7 @@ void Hand::updateCollisions() { for (size_t j = 0; j < collisions.size(); ++j) { totalPenetration = addPenetrations(totalPenetration, collisions[j]._penetration); // TODO: Andrew to poke avatar using collision info - avatar->poke(collisions[i]); + avatar->poke(collisions[j]); } } } From e2e02fc85511462afdf0964578d3175419f6a46f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 10 Feb 2014 14:04:32 -0800 Subject: [PATCH 22/24] Removing bounding sphere measurement of hands -- not useful yet. --- interface/src/renderer/FBXReader.cpp | 72 ---------------------------- 1 file changed, 72 deletions(-) diff --git a/interface/src/renderer/FBXReader.cpp b/interface/src/renderer/FBXReader.cpp index af25dbf06d..b6c74c27cd 100644 --- a/interface/src/renderer/FBXReader.cpp +++ b/interface/src/renderer/FBXReader.cpp @@ -819,44 +819,6 @@ QString getTopModelID(const QMultiHash& parentMap, } } -// VBox = helper class that measures a bounding box around a collection of vertices -// This is a work in progress -- Andrew -class VBox { -public: - VBox() : _maxCorner(-FLT_MAX), _minCorner(FLT_MAX) {} - - void addVertex(const glm::vec3& vertex) { - if (vertex.x > _maxCorner.x) { - _maxCorner.x = vertex.x; - } - if (vertex.y > _maxCorner.y) { - _maxCorner.y = vertex.y; - } - if (vertex.z > _maxCorner.z) { - _maxCorner.z = vertex.z; - } - if (vertex.x < _minCorner.x) { - _minCorner.x = vertex.x; - } - if (vertex.y < _minCorner.y) { - _minCorner.y = vertex.y; - } - if (vertex.z < _minCorner.z) { - _minCorner.z = vertex.z; - } - } - - glm::vec3 getCenter() const { return 0.5f * (_minCorner + _maxCorner); } - - float getMaxDimension() const { - glm::vec3 dim = _maxCorner - _minCorner; - return glm::max(glm::max(dim.x, dim.y), dim.z); - } - - glm::vec3 _maxCorner; - glm::vec3 _minCorner; -}; - FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) { QHash meshes; QVector blendshapes; @@ -1283,17 +1245,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) geometry.leftFingertipJointIndices = getIndices(jointLeftFingertipIDs, modelIDs); geometry.rightFingertipJointIndices = getIndices(jointRightFingertipIDs, modelIDs); - bool hasBothHands = (geometry.rightHandJointIndex != -1 && geometry.leftHandJointIndex != -1); - // extract the translation component of the neck transform if (geometry.neckJointIndex != -1) { const glm::mat4& transform = geometry.joints.at(geometry.neckJointIndex).transform; geometry.neckPivot = glm::vec3(transform[3][0], transform[3][1], transform[3][2]); } - VBox rightHandBox; - VBox leftHandBox; - geometry.bindExtents.minimum = glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX); geometry.bindExtents.maximum = glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX); @@ -1422,24 +1379,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) const FBXCluster& fbxCluster = extracted.mesh.clusters.at(i); int jointIndex = fbxCluster.jointIndex; FBXJoint& joint = geometry.joints[jointIndex]; - - bool isRightHand = hasBothHands && jointIndex == geometry.rightHandJointIndex; - bool isLeftHand = hasBothHands && jointIndex == geometry.leftHandJointIndex; - if (hasBothHands && !isRightHand && !isLeftHand) { - // check to see if this - int parentIndex = joint.parentIndex; - while (parentIndex != -1) { - if (parentIndex == geometry.rightHandJointIndex) { - isRightHand = true; - break; - } else if (parentIndex == geometry.leftHandJointIndex) { - isLeftHand = true; - break; - } - parentIndex = geometry.joints[parentIndex].parentIndex; - } - } - glm::vec3 boneEnd = extractTranslation(inverseModelTransform * joint.bindTransform); glm::vec3 boneDirection; float boneLength; @@ -1463,12 +1402,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) const float EXPANSION_WEIGHT_THRESHOLD = 0.25f; if (weight > EXPANSION_WEIGHT_THRESHOLD) { const glm::vec3& vertex = extracted.mesh.vertices.at(it.value()); - // track vertex if it is on one of the hands - if (isRightHand) { - rightHandBox.addVertex(radiusScale * vertex); - } else if (isLeftHand) { - leftHandBox.addVertex(radiusScale * vertex); - } float proj = glm::dot(boneDirection, vertex - boneEnd); if (proj < 0.0f && proj > -boneLength) { joint.boneRadius = glm::max(joint.boneRadius, radiusScale * glm::distance( @@ -1591,11 +1524,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } geometry.attachments.append(attachment); } - if (hasBothHands) { - // use measured sizes of "hands" for bone radius of the joints - geometry.joints[geometry.rightHandJointIndex].boneRadius = 0.5f * rightHandBox.getMaxDimension(); - geometry.joints[geometry.leftHandJointIndex].boneRadius = 0.5f * leftHandBox.getMaxDimension(); - } return geometry; } From e73c9f70951d9ca08b36734022876e575a4000cc Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 10 Feb 2014 14:07:50 -0800 Subject: [PATCH 23/24] It is now possible to "poke" moveable parts of the avatar skeleton. --- interface/src/avatar/Avatar.cpp | 25 ++++++++--------------- interface/src/avatar/Avatar.h | 4 +++- interface/src/avatar/Hand.cpp | 6 +++--- interface/src/renderer/Model.cpp | 34 ++++++++++++++++++++++++++++++++ interface/src/renderer/Model.h | 4 ++++ 5 files changed, 52 insertions(+), 21 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ab815679a9..ab8fdbed60 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -276,16 +276,12 @@ bool Avatar::findSphereCollisions(const glm::vec3& penetratorCenter, float penet bool didPenetrate = false; glm::vec3 skeletonPenetration; ModelCollisionInfo collisionInfo; - int jointIndex = _skeletonModel.findSphereCollision(penetratorCenter, penetratorRadius, - collisionInfo, 1.0f, skeletonSkipIndex); - if (jointIndex != -1) { + if (_skeletonModel.findSphereCollision(penetratorCenter, penetratorRadius, collisionInfo, 1.0f, skeletonSkipIndex)) { collisionInfo._model = &_skeletonModel; collisions.push_back(collisionInfo); didPenetrate = true; } - glm::vec3 facePenetration; - jointIndex = _head.getFaceModel().findSphereCollision(penetratorCenter, penetratorRadius, collisionInfo); - if (jointIndex != -1) { + if (_head.getFaceModel().findSphereCollision(penetratorCenter, penetratorRadius, collisionInfo)) { collisionInfo._model = &(_head.getFaceModel()); collisions.push_back(collisionInfo); didPenetrate = true; @@ -447,18 +443,13 @@ float Avatar::getHeight() const { return extents.maximum.y - extents.minimum.y; } -void Avatar::poke(ModelCollisionInfo& collision) { - if (collision._model == &_skeletonModel - && collision._jointIndex != -1) { - // TODO: Andrew to make this work - printf("ADEBUG model = 0x%x joint = %d p = [%e, %e, %e]\n", - collision._model, - collision._jointIndex, - collision._contactPoint.x, - collision._contactPoint.y, - collision._contactPoint.z - ); +bool Avatar::poke(ModelCollisionInfo& collision) { + // ATM poke() can only affect the Skeleton (not the head) + // TODO: make poke affect head + if (collision._model == &_skeletonModel && collision._jointIndex != -1) { + return _skeletonModel.poke(collision); } + return false; } float Avatar::getPelvisFloatingHeight() const { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 4a076b1867..8290115240 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -128,7 +128,9 @@ public: float getHeight() const; - void poke(ModelCollisionInfo& collision); + /// \param collision a data structure for storing info about collisions against Models + /// \return true if the collision affects the Avatar models + bool poke(ModelCollisionInfo& collision); public slots: void updateCollisionFlags(); diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index a67aa788e3..c2ea3f8f31 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -224,9 +224,9 @@ void Hand::updateCollisions() { } if (avatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, collisions)) { for (size_t j = 0; j < collisions.size(); ++j) { - totalPenetration = addPenetrations(totalPenetration, collisions[j]._penetration); - // TODO: Andrew to poke avatar using collision info - avatar->poke(collisions[j]); + if (!avatar->poke(collisions[j])) { + totalPenetration = addPenetrations(totalPenetration, collisions[j]._penetration); + } } } } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index d71732cbde..e1652b1237 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -552,6 +552,9 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position, int last glm::vec3 relativePosition = position - _translation; const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& freeLineage = geometry.joints.at(jointIndex).freeLineage; + if (freeLineage.isEmpty()) { + return false; + } if (lastFreeIndex == -1) { lastFreeIndex = freeLineage.last(); } @@ -710,6 +713,37 @@ void Model::renderCollisionProxies(float alpha) { glPopMatrix(); } +bool Model::poke(ModelCollisionInfo& collision) { + // This needs work. At the moment it can wiggle joints that are free to move (such as arms) + // but unmovable joints (such as torso) cannot be influenced at all. + glm::vec3 jointPosition(0.f); + if (getJointPosition(collision._jointIndex, jointPosition)) { + int jointIndex = collision._jointIndex; + const FBXJoint& joint = _geometry->getFBXGeometry().joints[jointIndex]; + if (joint.parentIndex != -1) { + // compute the approximate distance (travel) that the joint needs to move + glm::vec3 start; + getJointPosition(joint.parentIndex, start); + glm::vec3 contactPoint = collision._contactPoint - start; + glm::vec3 penetrationEnd = contactPoint + collision._penetration; + glm::vec3 axis = glm::cross(contactPoint, penetrationEnd); + float travel = glm::length(axis); + const float MIN_TRAVEL = 1.0e-8f; + if (travel > MIN_TRAVEL) { + // compute the new position of the joint + float angle = asinf(travel / (glm::length(contactPoint) * glm::length(penetrationEnd))); + axis = glm::normalize(axis); + glm::vec3 end; + getJointPosition(jointIndex, end); + glm::vec3 newEnd = start + glm::angleAxis(glm::degrees(angle), axis) * (end - start); + // try to move it + return setJointPosition(jointIndex, newEnd, -1, true); + } + } + } + return false; +} + void Model::deleteGeometry() { foreach (Model* attachment, _attachments) { delete attachment; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 035dd689dc..f99e46c5f4 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -164,6 +164,10 @@ public: void renderCollisionProxies(float alpha); + /// \param collisionInfo info about the collision + /// \return true if collision affects the Model + bool poke(ModelCollisionInfo& collisionInfo); + protected: QSharedPointer _geometry; From 85298581343b59660475f57996a1544ec0a578c4 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 10 Feb 2014 17:12:25 -0800 Subject: [PATCH 24/24] Remove experimental joining of hand-avatar and avatar-avatar collision logic. --- interface/src/avatar/MyAvatar.cpp | 51 +++---------------------------- 1 file changed, 4 insertions(+), 47 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index abeb127e49..5628740770 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -225,8 +225,9 @@ void MyAvatar::simulate(float deltaTime) { updateCollisionWithVoxels(deltaTime, radius); } if (_collisionFlags & COLLISION_GROUP_AVATARS) { - // TODO: Andrew to implement this - //updateCollisionWithAvatars(deltaTime); + // Note, hand-vs-avatar collisions are done elsewhere + // This is where we avatar-vs-avatar bounding capsule + updateCollisionWithAvatars(deltaTime); } } @@ -973,19 +974,6 @@ void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTim } } -// this is a work in progress -class PalmCollisionProxy { -public: - PalmCollisionProxy() : _palmIndex(-1), _position(0.f), _radius(0.f) {} - - PalmCollisionProxy(int index, const glm::vec3& position, float radius) : - _palmIndex(index), _position(position), _radius(radius) {} - - int _palmIndex; - glm::vec3 _position; - float _radius; -}; - const float DEFAULT_HAND_RADIUS = 0.1f; void MyAvatar::updateCollisionWithAvatars(float deltaTime) { @@ -998,26 +986,6 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) { } float myRadius = getHeight(); - // precompute hand proxies before we start walking the avatarlist - QVector palmProxies; - std::vector& palms = getHand().getPalms(); - size_t numPalms = palms.size(); - glm::vec3 position; - for (int i = 0; i < numPalms; ++i) { - PalmData& palm = palms[i]; - if (palm.getSixenseID() == SIXENSE_CONTROLLER_ID_LEFT_HAND) { - if (_skeletonModel.getLeftHandPosition(position)) { - float radius = DEFAULT_HAND_RADIUS; - palmProxies.push_back(PalmCollisionProxy(i, position, radius)); - } - } else if (palm.getSixenseID() == SIXENSE_CONTROLLER_ID_RIGHT_HAND) { - if (_skeletonModel.getRightHandPosition(position)) { - float radius = DEFAULT_HAND_RADIUS; - palmProxies.push_back(PalmCollisionProxy(i, position, radius)); - } - } - } - CollisionInfo collisionInfo; foreach (const AvatarSharedPointer& avatarPointer, avatars) { Avatar* avatar = static_cast(avatarPointer.data()); @@ -1031,18 +999,7 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) { } float theirRadius = avatar->getHeight(); if (distance < myRadius + theirRadius) { - for (int i = 0; i < palmProxies.size(); ++i) { - glm::vec3 pos = palmProxies[i]._position; - // query against avatar - if (avatar->findSphereCollisionWithSkeleton(pos, palmProxies[i]._radius, collisionInfo)) { - // TODO: Andrew to make this work - // push hand out of penetration - //palms[palmProxies[i]._palmIndex].addToPosition(0.5f * collisionInfo._penetration * float(TREE_SCALE)); - // print results - //distance = glm::length(collisionInfo._penetration); - //printf("collision i = %d p = [%e, %e, %e] d = %e\n", i, pos.x, pos.y, pos.z, distance); - } - } + // TODO: Andrew to make avatar-avatar capsule collisions work here } } }