From ee751ed1b9da0aefda68cb7018303d601b4896bc Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 18 Nov 2015 09:21:04 -0800 Subject: [PATCH] use kDop volume of avatar mesh parts for capsule --- interface/src/avatar/SkeletonModel.cpp | 16 ++---- libraries/fbx/src/FBXReader.cpp | 79 +++++++++++--------------- libraries/fbx/src/FBXReader.h | 1 - 3 files changed, 38 insertions(+), 58 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 87f0e631f2..c6c1ead8c1 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -625,19 +625,15 @@ void SkeletonModel::computeBoundingShape() { totalExtents.addPoint(glm::vec3(0.0f)); int numStates = _rig->getJointStateCount(); for (int i = 0; i < numStates; i++) { - const JointState& state = _rig->getJointState(i); - - const glm::mat4& jointTransform = state.getTransform(); - float scale = extractUniformScale(jointTransform); - // Each joint contributes a capsule defined by FBXJoint.shapeInfo. // For totalExtents we use the capsule endpoints expanded by the radius. + const JointState& state = _rig->getJointState(i); + const glm::mat4& jointTransform = state.getTransform(); const FBXJointShapeInfo& shapeInfo = geometry.joints.at(i).shapeInfo; - for (int j = 0; j < shapeInfo.points.size(); ++j) { - glm::vec3 transformedPoint = extractTranslation(jointTransform * glm::translate(shapeInfo.points[j])); - vec3 radius(scale * shapeInfo.radius); - totalExtents.addPoint(transformedPoint + radius); - totalExtents.addPoint(transformedPoint - radius); + if (shapeInfo.points.size() > 0) { + for (int j = 0; j < shapeInfo.points.size(); ++j) { + totalExtents.addPoint(extractTranslation(jointTransform * glm::translate(shapeInfo.points[j]))); + } } // HACK so that default legless robot doesn't knuckle-drag if (shapeInfo.points.size() == 0 && (state.getName() == "LeftFoot" || state.getName() == "RightFoot")) { diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index f9bb089a9c..3251b5b35d 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1460,7 +1460,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS it != extracted.newIndices.end() && it.key() == oldIndex; it++) { // remember vertices with at least 1/4 weight - const float EXPANSION_WEIGHT_THRESHOLD = 0.25f; + const float EXPANSION_WEIGHT_THRESHOLD = 0.99f; if (weight > EXPANSION_WEIGHT_THRESHOLD) { // transform to joint-frame and save for later const glm::mat4 vertexTransform = meshToJoint * glm::translate(extracted.mesh.vertices.at(it.value())); @@ -1535,63 +1535,48 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS meshIDsToMeshIndices.insert(it.key(), meshIndex); } - // now that all joints have been scanned, compute a radius for each bone + ShapeVertices cardinalDirections; + cardinalDirections.push_back(Vectors::UNIT_X); + cardinalDirections.push_back(Vectors::UNIT_Y); + cardinalDirections.push_back(Vectors::UNIT_Z); + const float INV_SQRT_3 = 0.57735026918f; + cardinalDirections.push_back(glm::vec3(INV_SQRT_3, INV_SQRT_3, INV_SQRT_3)); + cardinalDirections.push_back(glm::vec3(INV_SQRT_3, -INV_SQRT_3, INV_SQRT_3)); + cardinalDirections.push_back(glm::vec3(INV_SQRT_3, INV_SQRT_3, -INV_SQRT_3)); + cardinalDirections.push_back(glm::vec3(INV_SQRT_3, -INV_SQRT_3, -INV_SQRT_3)); + + // now that all joints have been scanned compute a k-Dop bounding volume of mesh glm::vec3 defaultCapsuleAxis(0.0f, 1.0f, 0.0f); for (int i = 0; i < geometry.joints.size(); ++i) { FBXJoint& joint = geometry.joints[i]; // NOTE: points are in joint-frame - // compute average point ShapeVertices& points = shapeVertices[i]; - glm::vec3 avgPoint = glm::vec3(0.0f); - for (uint32_t j = 0; j < points.size(); ++j) { - avgPoint += points[j]; - } - avgPoint /= (float)points.size(); - - // compute axis from begin to avgPoint - glm::vec3 begin(0.0f); - glm::vec3 end = avgPoint; - glm::vec3 axis = end - begin; - float axisLength = glm::length(axis); - if (axisLength > EPSILON) { - axis /= axisLength; - } else { - axis = glm::vec3(0.0f); - } - - // measure average cylindrical radius - float avgRadius = 0.0f; if (points.size() > 0) { - float minProjection = FLT_MAX; - float maxProjection = -FLT_MIN; + // compute average point + glm::vec3 avgPoint = glm::vec3(0.0f); for (uint32_t j = 0; j < points.size(); ++j) { - glm::vec3 offset = points[j] - avgPoint; - float projection = glm::dot(offset, axis); - maxProjection = glm::max(maxProjection, projection); - minProjection = glm::min(minProjection, projection); - avgRadius += glm::length(offset - projection * axis); + avgPoint += points[j]; } - avgRadius /= (float)points.size(); - - // compute endpoints of capsule in joint-frame - glm::vec3 capsuleBegin = avgPoint; - glm::vec3 capsuleEnd = avgPoint; - if (maxProjection - minProjection < 2.0f * avgRadius) { - // the mesh-as-cylinder approximation is too short to collide as a capsule - // so we'll collapse it to a sphere (although that isn't a very good approximation) - capsuleBegin = avgPoint + 0.5f * (maxProjection + minProjection) * axis; - capsuleEnd = capsuleBegin; - } else { - capsuleBegin = avgPoint + (minProjection + avgRadius) * axis; - capsuleEnd = avgPoint + (maxProjection - avgRadius) * axis; + avgPoint /= (float)points.size(); + + // compute a k-Dop bounding volume + for (uint32_t j = 0; j < cardinalDirections.size(); ++j) { + float maxDot = -FLT_MAX; + float minDot = FLT_MIN; + for (uint32_t k = 0; k < points.size(); ++k) { + float kDot = glm::dot(cardinalDirections[j], points[k] - avgPoint); + if (kDot > maxDot) { + maxDot = kDot; + } + if (kDot < minDot) { + minDot = kDot; + } + } + joint.shapeInfo.points.push_back(avgPoint + maxDot * cardinalDirections[j]); + joint.shapeInfo.points.push_back(avgPoint + minDot * cardinalDirections[j]); } - - // save points for later - joint.shapeInfo.points.push_back(capsuleBegin); - joint.shapeInfo.points.push_back(capsuleEnd); } - joint.shapeInfo.radius = avgRadius; } geometry.palmDirection = parseVec3(mapping.value("palmDirection", "0, -1, 0").toString()); diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 8014718815..0ddbc11bda 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -56,7 +56,6 @@ public: struct FBXJointShapeInfo { // same units and frame as FBXJoint.translation QVector points; - float radius; }; /// A single joint (transformation node) extracted from an FBX document.