Merge pull request #14816 from SamGondelman/avatar

Case 20924: Cleaning up Avatar findRayIntersection
This commit is contained in:
John Conklin II 2019-02-08 14:40:45 -08:00 committed by GitHub
commit f9b86725fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 52 deletions

View file

@ -652,21 +652,14 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic
PROFILE_RANGE(simulation_physics, __FUNCTION__); PROFILE_RANGE(simulation_physics, __FUNCTION__);
float distance = (float)INT_MAX; // with FLT_MAX bullet rayTest does not return results float bulletDistance = (float)INT_MAX; // with FLT_MAX bullet rayTest does not return results
glm::vec3 rayDirection = glm::normalize(ray.direction); glm::vec3 rayDirection = glm::normalize(ray.direction);
std::vector<MyCharacterController::RayAvatarResult> physicsResults = _myAvatar->getCharacterController()->rayTest(glmToBullet(ray.origin), glmToBullet(rayDirection), distance, QVector<uint>()); std::vector<MyCharacterController::RayAvatarResult> physicsResults = _myAvatar->getCharacterController()->rayTest(glmToBullet(ray.origin), glmToBullet(rayDirection), bulletDistance, QVector<uint>());
if (physicsResults.size() > 0) { if (physicsResults.size() > 0) {
glm::vec3 rayDirectionInv = { rayDirection.x != 0.0f ? 1.0f / rayDirection.x : INFINITY, glm::vec3 rayDirectionInv = { rayDirection.x != 0.0f ? 1.0f / rayDirection.x : INFINITY,
rayDirection.y != 0.0f ? 1.0f / rayDirection.y : INFINITY, rayDirection.y != 0.0f ? 1.0f / rayDirection.y : INFINITY,
rayDirection.z != 0.0f ? 1.0f / rayDirection.z : INFINITY }; rayDirection.z != 0.0f ? 1.0f / rayDirection.z : INFINITY };
MyCharacterController::RayAvatarResult rayAvatarResult;
AvatarPointer avatar = nullptr;
BoxFace face = BoxFace::UNKNOWN_FACE;
glm::vec3 surfaceNormal;
QVariantMap extraInfo;
for (auto &hit : physicsResults) { for (auto &hit : physicsResults) {
auto avatarID = hit._intersectWithAvatar; auto avatarID = hit._intersectWithAvatar;
if ((avatarsToInclude.size() > 0 && !avatarsToInclude.contains(avatarID)) || if ((avatarsToInclude.size() > 0 && !avatarsToInclude.contains(avatarID)) ||
@ -674,6 +667,10 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic
continue; continue;
} }
MyCharacterController::RayAvatarResult rayAvatarResult;
BoxFace face = BoxFace::UNKNOWN_FACE;
QVariantMap extraInfo;
AvatarPointer avatar = nullptr;
if (_myAvatar->getSessionUUID() != avatarID) { if (_myAvatar->getSessionUUID() != avatarID) {
auto avatarMap = getHashCopy(); auto avatarMap = getHashCopy();
AvatarHash::iterator itr = avatarMap.find(avatarID); AvatarHash::iterator itr = avatarMap.find(avatarID);
@ -683,46 +680,45 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic
} else { } else {
avatar = _myAvatar; avatar = _myAvatar;
} }
if (!hit._isBound) { if (!hit._isBound) {
rayAvatarResult = hit; rayAvatarResult = hit;
} else if (avatar) { } else if (avatar) {
auto &multiSpheres = avatar->getMultiSphereShapes(); auto &multiSpheres = avatar->getMultiSphereShapes();
if (multiSpheres.size() > 0) { if (multiSpheres.size() > 0) {
std::vector<MyCharacterController::RayAvatarResult> boxHits; MyCharacterController::RayAvatarResult boxHit;
boxHit._distance = FLT_MAX;
for (size_t i = 0; i < hit._boundJoints.size(); i++) { for (size_t i = 0; i < hit._boundJoints.size(); i++) {
assert(hit._boundJoints[i] < multiSpheres.size()); assert(hit._boundJoints[i] < multiSpheres.size());
auto &mSphere = multiSpheres[hit._boundJoints[i]]; auto &mSphere = multiSpheres[hit._boundJoints[i]];
if (mSphere.isValid()) { if (mSphere.isValid()) {
float boundDistance = FLT_MAX; float boundDistance = FLT_MAX;
BoxFace face; BoxFace boundFace = BoxFace::UNKNOWN_FACE;
glm::vec3 surfaceNormal; glm::vec3 boundSurfaceNormal;
auto &bbox = mSphere.getBoundingBox(); auto &bbox = mSphere.getBoundingBox();
if (bbox.findRayIntersection(ray.origin, rayDirection, rayDirectionInv, boundDistance, face, surfaceNormal)) { if (bbox.findRayIntersection(ray.origin, rayDirection, rayDirectionInv, boundDistance, boundFace, boundSurfaceNormal)) {
MyCharacterController::RayAvatarResult boxHit; if (boundDistance < boxHit._distance) {
boxHit._distance = boundDistance; boxHit._intersect = true;
boxHit._intersect = true; boxHit._intersectWithAvatar = avatarID;
boxHit._intersectionNormal = surfaceNormal; boxHit._intersectWithJoint = mSphere.getJointIndex();
boxHit._intersectionPoint = ray.origin + boundDistance * rayDirection; boxHit._distance = boundDistance;
boxHit._intersectWithAvatar = avatarID; boxHit._intersectionPoint = ray.origin + boundDistance * rayDirection;
boxHit._intersectWithJoint = mSphere.getJointIndex(); boxHit._intersectionNormal = boundSurfaceNormal;
boxHits.push_back(boxHit); face = boundFace;
}
} }
} }
} }
if (boxHits.size() > 0) { if (boxHit._distance < FLT_MAX) {
if (boxHits.size() > 1) { rayAvatarResult = boxHit;
std::sort(boxHits.begin(), boxHits.end(), [](const MyCharacterController::RayAvatarResult& hitA,
const MyCharacterController::RayAvatarResult& hitB) {
return hitA._distance < hitB._distance;
});
}
rayAvatarResult = boxHits[0];
} }
} }
} }
if (pickAgainstMesh) {
if (rayAvatarResult._intersect && pickAgainstMesh) {
glm::vec3 localRayOrigin = avatar->worldToJointPoint(ray.origin, rayAvatarResult._intersectWithJoint); glm::vec3 localRayOrigin = avatar->worldToJointPoint(ray.origin, rayAvatarResult._intersectWithJoint);
glm::vec3 localRayPoint = avatar->worldToJointPoint(ray.origin + rayDirection, rayAvatarResult._intersectWithJoint); glm::vec3 localRayPoint = avatar->worldToJointPoint(ray.origin + rayAvatarResult._distance * rayDirection, rayAvatarResult._intersectWithJoint);
auto avatarOrientation = avatar->getWorldOrientation(); auto avatarOrientation = avatar->getWorldOrientation();
auto avatarPosition = avatar->getWorldPosition(); auto avatarPosition = avatar->getWorldPosition();
@ -732,31 +728,37 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic
auto defaultFrameRayOrigin = jointPosition + jointOrientation * localRayOrigin; auto defaultFrameRayOrigin = jointPosition + jointOrientation * localRayOrigin;
auto defaultFrameRayPoint = jointPosition + jointOrientation * localRayPoint; auto defaultFrameRayPoint = jointPosition + jointOrientation * localRayPoint;
auto defaultFrameRayDirection = defaultFrameRayPoint - defaultFrameRayOrigin; auto defaultFrameRayDirection = glm::normalize(defaultFrameRayPoint - defaultFrameRayOrigin);
if (avatar->getSkeletonModel()->findRayIntersectionAgainstSubMeshes(defaultFrameRayOrigin, defaultFrameRayDirection, distance, face, surfaceNormal, extraInfo, true, false)) { float subMeshDistance = FLT_MAX;
auto newDistance = glm::length(vec3FromVariant(extraInfo["worldIntersectionPoint"]) - defaultFrameRayOrigin); BoxFace subMeshFace = BoxFace::UNKNOWN_FACE;
rayAvatarResult._distance = newDistance; glm::vec3 subMeshSurfaceNormal;
rayAvatarResult._intersectionPoint = ray.origin + newDistance * rayDirection; QVariantMap subMeshExtraInfo;
rayAvatarResult._intersectionNormal = surfaceNormal; if (avatar->getSkeletonModel()->findRayIntersectionAgainstSubMeshes(defaultFrameRayOrigin, defaultFrameRayDirection, subMeshDistance, subMeshFace, subMeshSurfaceNormal, subMeshExtraInfo, true, false)) {
extraInfo["worldIntersectionPoint"] = vec3toVariant(rayAvatarResult._intersectionPoint); rayAvatarResult._distance = subMeshDistance;
break; rayAvatarResult._intersectionPoint = ray.origin + subMeshDistance * rayDirection;
rayAvatarResult._intersectionNormal = subMeshSurfaceNormal;
face = subMeshFace;
extraInfo = subMeshExtraInfo;
} else {
rayAvatarResult._intersect = false;
} }
} else if (rayAvatarResult._intersect){ }
if (rayAvatarResult._intersect) {
result.intersects = true;
result.avatarID = rayAvatarResult._intersectWithAvatar;
result.distance = rayAvatarResult._distance;
result.face = face;
result.intersection = ray.origin + rayAvatarResult._distance * rayDirection;
result.surfaceNormal = rayAvatarResult._intersectionNormal;
result.jointIndex = rayAvatarResult._intersectWithJoint;
result.extraInfo = extraInfo;
break; break;
} }
} }
if (rayAvatarResult._intersect) {
result.intersects = true;
result.avatarID = rayAvatarResult._intersectWithAvatar;
result.distance = rayAvatarResult._distance;
result.surfaceNormal = rayAvatarResult._intersectionNormal;
result.jointIndex = rayAvatarResult._intersectWithJoint;
result.intersection = ray.origin + rayAvatarResult._distance * rayDirection;
result.extraInfo = extraInfo;
result.face = face;
}
} }
return result; return result;
} }

View file

@ -56,7 +56,8 @@ PickResultPointer RayPick::getOverlayIntersection(const PickRay& pick) {
} }
PickResultPointer RayPick::getAvatarIntersection(const PickRay& pick) { PickResultPointer RayPick::getAvatarIntersection(const PickRay& pick) {
RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersectionVector(pick, getIncludeItemsAs<EntityItemID>(), getIgnoreItemsAs<EntityItemID>(), true); bool precisionPicking = !(getFilter().isCoarse() || DependencyManager::get<PickManager>()->getForceCoarsePicking());
RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersectionVector(pick, getIncludeItemsAs<EntityItemID>(), getIgnoreItemsAs<EntityItemID>(), precisionPicking);
if (avatarRes.intersects) { if (avatarRes.intersects) {
return std::make_shared<RayPickResult>(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, pick, avatarRes.surfaceNormal, avatarRes.extraInfo); return std::make_shared<RayPickResult>(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, pick, avatarRes.surfaceNormal, avatarRes.extraInfo);
} else { } else {