From 2158e084d43821613ec1025674ea55c63d74b905 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 17 Jan 2019 14:00:54 -0700 Subject: [PATCH] Add avatar joints filter to intersection calculation --- interface/src/avatar/AvatarManager.cpp | 121 +++++++++++------- interface/src/avatar/AvatarManager.h | 8 +- interface/src/avatar/DetailedMotionState.cpp | 2 +- .../src/avatar/MyCharacterController.cpp | 3 + interface/src/avatar/OtherAvatar.cpp | 9 +- interface/src/raypick/RayPick.cpp | 2 +- 6 files changed, 94 insertions(+), 51 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 53f8a0bc7f..f24e1e72eb 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -640,23 +640,27 @@ AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID) RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay& ray, const QScriptValue& avatarIdsToInclude, - const QScriptValue& avatarIdsToDiscard) { + const QScriptValue& avatarIdsToDiscard, + const QScriptValue& jointIndicesToFilter) { QVector avatarsToInclude = qVectorEntityItemIDFromScriptValue(avatarIdsToInclude); QVector avatarsToDiscard = qVectorEntityItemIDFromScriptValue(avatarIdsToDiscard); - - return findRayIntersectionVector(ray, avatarsToInclude, avatarsToDiscard); + QVector jointsToFilter; + qVectorIntFromScriptValue(jointIndicesToFilter, jointsToFilter); + return findRayIntersectionVector(ray, avatarsToInclude, avatarsToDiscard, jointsToFilter); } RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const PickRay& ray, const QVector& avatarsToInclude, - const QVector& avatarsToDiscard) { + const QVector& avatarsToDiscard, + const QVector& jointIndicesToFilter) { RayToAvatarIntersectionResult result; if (QThread::currentThread() != thread()) { BLOCKING_INVOKE_METHOD(const_cast(this), "findRayIntersectionVector", Q_RETURN_ARG(RayToAvatarIntersectionResult, result), Q_ARG(const PickRay&, ray), Q_ARG(const QVector&, avatarsToInclude), - Q_ARG(const QVector&, avatarsToDiscard)); + Q_ARG(const QVector&, avatarsToDiscard), + Q_ARG(const QVector&, jointIndicesToFilter)); return result; } @@ -672,55 +676,80 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic if (physicsResults.size() > 0) { MyCharacterController::RayAvatarResult rayAvatarResult; + AvatarPointer avatar = nullptr; for (auto &hit : physicsResults) { - if ((avatarsToInclude.size() > 0 && !avatarsToInclude.contains(hit._intersectWithAvatar)) || - (avatarsToDiscard.size() > 0 && avatarsToDiscard.contains(hit._intersectWithAvatar))) { + auto avatarID = hit._intersectWithAvatar; + bool skipThisAvatar = (avatarsToInclude.size() > 0 && !avatarsToInclude.contains(avatarID)) || + (avatarsToDiscard.size() > 0 && avatarsToDiscard.contains(avatarID)) && jointIndicesToFilter.size() == 0; + if (skipThisAvatar) { continue; } - if (!hit._isBound) { - rayAvatarResult = hit; - break; - } else { + if (!(_myAvatar->getSessionUUID() == avatarID)) { auto avatarMap = getHashCopy(); - auto avatarID = hit._intersectWithAvatar; AvatarHash::iterator itr = avatarMap.find(avatarID); if (itr != avatarMap.end()) { - const auto& avatar = std::static_pointer_cast(*itr); - auto &multiSpheres = avatar->getMultiSphereShapes(); - if (multiSpheres.size() > 0) { - std::vector boxHits; - for (size_t i = 0; i < hit._boundJoints.size(); i++) { - assert(hit._boundJoints[i] < multiSpheres.size()); - auto &mSphere = multiSpheres[hit._boundJoints[i]]; - if (mSphere.isValid()) { - float boundDistance = FLT_MAX; - BoxFace face; - glm::vec3 surfaceNormal; - auto &bbox = mSphere.getBoundingBox(); - if (bbox.findRayIntersection(ray.origin, ray.direction, rayDirectionInv, boundDistance, face, surfaceNormal)) { - MyCharacterController::RayAvatarResult boxHit; - boxHit._distance = boundDistance; - boxHit._intersect = true; - boxHit._intersectionNormal = surfaceNormal; - boxHit._intersectionPoint = ray.origin + boundDistance * glm::normalize(ray.direction); - boxHit._intersectWithAvatar = avatarID; - boxHit._intersectWithJoint = mSphere.getJointIndex(); - boxHits.push_back(boxHit); - } - } - } - if (boxHits.size() > 0) { - if (boxHits.size() > 1) { - std::sort(boxHits.begin(), boxHits.end(), [](const MyCharacterController::RayAvatarResult& hitA, - const MyCharacterController::RayAvatarResult& hitB) { - return hitA._distance < hitB._distance; - }); - } - rayAvatarResult = boxHits[0]; - break; + avatar = std::static_pointer_cast(*itr); + } + } else { + avatar = _myAvatar; + } + QVector jointsToDiscard; + if (avatar && jointIndicesToFilter.size() > 0) { + int jointCount = avatar->getJointCount(); + if (avatarsToInclude.size() > 0 && avatarsToInclude.contains(avatarID)) { + for (int i = 0; i < jointCount; i++) { + if (!jointIndicesToFilter.contains(i)) { + jointsToDiscard.push_back(i); } } - } + } else if (avatarsToDiscard.size() > 0 && avatarsToDiscard.contains(avatarID)) { + for (int i = 0; i < jointCount; i++) { + if (jointIndicesToFilter.contains(i)) { + jointsToDiscard.push_back(i); + } + } + } + } + if (!hit._isBound) { + if (!jointsToDiscard.contains(hit._intersectWithJoint)) { + rayAvatarResult = hit; + break; + } + } else if (avatar) { + auto &multiSpheres = avatar->getMultiSphereShapes(); + if (multiSpheres.size() > 0) { + std::vector boxHits; + for (size_t i = 0; i < hit._boundJoints.size(); i++) { + assert(hit._boundJoints[i] < multiSpheres.size()); + auto &mSphere = multiSpheres[hit._boundJoints[i]]; + if (mSphere.isValid() && !jointsToDiscard.contains(hit._boundJoints[i])) { + float boundDistance = FLT_MAX; + BoxFace face; + glm::vec3 surfaceNormal; + auto &bbox = mSphere.getBoundingBox(); + if (bbox.findRayIntersection(ray.origin, ray.direction, rayDirectionInv, boundDistance, face, surfaceNormal)) { + MyCharacterController::RayAvatarResult boxHit; + boxHit._distance = boundDistance; + boxHit._intersect = true; + boxHit._intersectionNormal = surfaceNormal; + boxHit._intersectionPoint = ray.origin + boundDistance * glm::normalize(ray.direction); + boxHit._intersectWithAvatar = avatarID; + boxHit._intersectWithJoint = hit._intersectWithJoint; + boxHits.push_back(boxHit); + } + } + } + if (boxHits.size() > 0) { + if (boxHits.size() > 1) { + std::sort(boxHits.begin(), boxHits.end(), [](const MyCharacterController::RayAvatarResult& hitA, + const MyCharacterController::RayAvatarResult& hitB) { + return hitA._distance < hitB._distance; + }); + } + rayAvatarResult = boxHits[0]; + break; + } + } } } if (rayAvatarResult._intersect) { diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 6717c301af..93be716087 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -138,21 +138,25 @@ public: * @param {PickRay} ray * @param {Uuid[]} [avatarsToInclude=[]] * @param {Uuid[]} [avatarsToDiscard=[]] + * @param {uint[]} [jointIndicesToFilter=[] - If included/discarded avatars are provided only this joints corresponding to those avatars would be included/discarded. ] * @returns {RayToAvatarIntersectionResult} */ Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray, const QScriptValue& avatarIdsToInclude = QScriptValue(), - const QScriptValue& avatarIdsToDiscard = QScriptValue()); + const QScriptValue& avatarIdsToDiscard = QScriptValue(), + const QScriptValue& jointIndicesToFilter = QScriptValue()); /**jsdoc * @function AvatarManager.findRayIntersectionVector * @param {PickRay} ray * @param {Uuid[]} avatarsToInclude * @param {Uuid[]} avatarsToDiscard + * @param {uint[]} [jointIndicesToFilter=[] - If included/discarded avatars are provided only this joints corresponding to those avatars would be included/discarded. ] * @returns {RayToAvatarIntersectionResult} */ Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersectionVector(const PickRay& ray, const QVector& avatarsToInclude, - const QVector& avatarsToDiscard); + const QVector& avatarsToDiscard, + const QVector& jointIndicesToFilter); /**jsdoc * @function AvatarManager.findParabolaIntersectionVector diff --git a/interface/src/avatar/DetailedMotionState.cpp b/interface/src/avatar/DetailedMotionState.cpp index 4d8e3d5ec7..cec27108ca 100644 --- a/interface/src/avatar/DetailedMotionState.cpp +++ b/interface/src/avatar/DetailedMotionState.cpp @@ -182,7 +182,7 @@ void DetailedMotionState::setShape(const btCollisionShape* shape) { } void DetailedMotionState::forceActive() { - if (_body) { + if (_body && !_body->isActive()) { _body->setActivationState(ACTIVE_TAG); } } \ No newline at end of file diff --git a/interface/src/avatar/MyCharacterController.cpp b/interface/src/avatar/MyCharacterController.cpp index 0141154f10..f1eb59d808 100755 --- a/interface/src/avatar/MyCharacterController.cpp +++ b/interface/src/avatar/MyCharacterController.cpp @@ -360,6 +360,9 @@ btCollisionShape* MyCharacterController::createDetailedCollisionShapeForJoint(in _avatar->computeDetailedShapeInfo(shapeInfo, jointIndex); if (shapeInfo.getType() != SHAPE_TYPE_NONE) { btCollisionShape* shape = const_cast(ObjectMotionState::getShapeManager()->getShape(shapeInfo)); + if (shape) { + shape->setMargin(0.001f); + } return shape; } return nullptr; diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index 53fc826fb0..6447d8d8b5 100644 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -114,6 +114,9 @@ void OtherAvatar::updateSpaceProxy(workload::Transaction& transaction) const { int OtherAvatar::parseDataFromBuffer(const QByteArray& buffer) { int32_t bytesRead = Avatar::parseDataFromBuffer(buffer); + for (size_t i = 0; i < _detailedMotionStates.size(); i++) { + _detailedMotionStates[i]->forceActive(); + } if (_moving && _motionState) { _motionState->addDirtyFlags(Simulation::DIRTY_POSITION); } @@ -166,7 +169,11 @@ btCollisionShape* OtherAvatar::createCollisionShape(int jointIndex, bool& isBoun break; } if (shapeInfo.getType() != SHAPE_TYPE_NONE) { - return const_cast(ObjectMotionState::getShapeManager()->getShape(shapeInfo)); + auto shape = const_cast(ObjectMotionState::getShapeManager()->getShape(shapeInfo)); + if (shape) { + shape->setMargin(0.001f); + } + return shape; } return nullptr; } diff --git a/interface/src/raypick/RayPick.cpp b/interface/src/raypick/RayPick.cpp index 507e45b470..85ffc97450 100644 --- a/interface/src/raypick/RayPick.cpp +++ b/interface/src/raypick/RayPick.cpp @@ -56,7 +56,7 @@ PickResultPointer RayPick::getOverlayIntersection(const PickRay& pick) { } PickResultPointer RayPick::getAvatarIntersection(const PickRay& pick) { - RayToAvatarIntersectionResult avatarRes = DependencyManager::get()->findRayIntersectionVector(pick, getIncludeItemsAs(), getIgnoreItemsAs()); + RayToAvatarIntersectionResult avatarRes = DependencyManager::get()->findRayIntersectionVector(pick, getIncludeItemsAs(), getIgnoreItemsAs(), QVector()); if (avatarRes.intersects) { return std::make_shared(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, pick, avatarRes.surfaceNormal, avatarRes.extraInfo); } else {