improved collision shapes for fingers

This commit is contained in:
Andrew Meadows 2014-07-17 14:31:16 -07:00
parent 53ee5f2340
commit 58e31abf60

View file

@ -967,17 +967,17 @@ QString getString(const QVariant& value) {
class JointShapeInfo { class JointShapeInfo {
public: public:
JointShapeInfo() : numVertices(0), numProjectedVertices(0), JointShapeInfo() : numVertices(0),
sumVertexWeights(0.0f), sumWeightedRadii(0.0f), sumVertexWeights(0.0f), sumWeightedRadii(0.0f), numVertexWeights(0),
averageVertex(0.f), boneBegin(0.f), averageRadius(0.f) { averageVertex(0.f), boneBegin(0.f), averageRadius(0.f) {
} }
// NOTE: the points here are in the "joint frame" which has the "jointEnd" at the origin // NOTE: the points here are in the "joint frame" which has the "jointEnd" at the origin
int numVertices; // num vertices from contributing meshes int numVertices; // num vertices from contributing meshes
int numProjectedVertices; // num vertices that successfully project onto bone axis float sumVertexWeights; // sum of all vertex weights
float sumVertexWeights; float sumWeightedRadii; // sum of weighted vertices
float sumWeightedRadii; int numVertexWeights; // num vertices that contributed to sums
glm::vec3 averageVertex; // average of all mesh vertices (in joint frame) glm::vec3 averageVertex;// average of all mesh vertices (in joint frame)
glm::vec3 boneBegin; // parent joint location (in joint frame) glm::vec3 boneBegin; // parent joint location (in joint frame)
float averageRadius; // average distance from mesh points to averageVertex float averageRadius; // average distance from mesh points to averageVertex
}; };
@ -1743,11 +1743,14 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
if (weight > EXPANSION_WEIGHT_THRESHOLD) { if (weight > EXPANSION_WEIGHT_THRESHOLD) {
const glm::vec3& vertex = extracted.mesh.vertices.at(it.value()); const glm::vec3& vertex = extracted.mesh.vertices.at(it.value());
float proj = glm::dot(boneDirection, boneEnd - vertex); float proj = glm::dot(boneDirection, boneEnd - vertex);
if (proj > 0.0f && proj < boneLength) { if (proj < 0.0f || proj > boneLength) {
joint.boneRadius = glm::max(joint.boneRadius, weight *= 0.5f;
radiusScale * glm::distance(vertex, boneEnd - boneDirection * proj));
++jointShapeInfo.numProjectedVertices;
} }
jointShapeInfo.sumVertexWeights += weight;
jointShapeInfo.sumWeightedRadii += weight * radiusScale * glm::distance(vertex, boneEnd - boneDirection * proj);
++jointShapeInfo.numVertexWeights;
glm::vec3 vertexInJointFrame = rotateMeshToJoint * (radiusScale * (vertex - boneEnd)); glm::vec3 vertexInJointFrame = rotateMeshToJoint * (radiusScale * (vertex - boneEnd));
jointShapeInfo.averageVertex += vertexInJointFrame; jointShapeInfo.averageVertex += vertexInJointFrame;
++jointShapeInfo.numVertices; ++jointShapeInfo.numVertices;
@ -1793,11 +1796,15 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
glm::vec3 averageVertex(0.f); glm::vec3 averageVertex(0.f);
foreach (const glm::vec3& vertex, extracted.mesh.vertices) { foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
float weight = 1.0f;
float proj = glm::dot(boneDirection, boneEnd - vertex); float proj = glm::dot(boneDirection, boneEnd - vertex);
if (proj > 0.0f && proj < boneLength) { if (proj < 0.0f || proj > boneLength) {
joint.boneRadius = glm::max(joint.boneRadius, radiusScale * glm::distance(vertex, boneEnd - boneDirection * proj)); weight *= 0.5f;
++jointShapeInfo.numProjectedVertices;
} }
jointShapeInfo.sumVertexWeights += weight;
jointShapeInfo.sumWeightedRadii += weight * radiusScale * glm::distance(vertex, boneEnd - boneDirection * proj);
++jointShapeInfo.numVertexWeights;
glm::vec3 vertexInJointFrame = rotateMeshToJoint * (radiusScale * (vertex - boneEnd)); glm::vec3 vertexInJointFrame = rotateMeshToJoint * (radiusScale * (vertex - boneEnd));
jointShapeInfo.averageVertex += vertexInJointFrame; jointShapeInfo.averageVertex += vertexInJointFrame;
averageVertex += vertex; averageVertex += vertex;
@ -1832,9 +1839,13 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
jointShapeInfo.boneBegin = inverseRotation * (extractTranslation(parentJoint.transform) - extractTranslation(joint.transform)); jointShapeInfo.boneBegin = inverseRotation * (extractTranslation(parentJoint.transform) - extractTranslation(joint.transform));
} }
// we use a capsule if the joint ANY mesh vertices successfully projected onto the bone if (jointShapeInfo.sumVertexWeights > 0.0f) {
joint.boneRadius = jointShapeInfo.sumWeightedRadii / jointShapeInfo.sumVertexWeights;
}
// we use a capsule if the joint had ANY mesh vertices successfully projected onto the bone
// AND its boneRadius is not too close to zero // AND its boneRadius is not too close to zero
bool collideLikeCapsule = jointShapeInfo.numProjectedVertices > 0 bool collideLikeCapsule = jointShapeInfo.numVertexWeights > 0
&& glm::length(jointShapeInfo.boneBegin) > EPSILON; && glm::length(jointShapeInfo.boneBegin) > EPSILON;
if (collideLikeCapsule) { if (collideLikeCapsule) {
@ -1850,7 +1861,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
} else { } else {
joint.shapePosition = glm::vec3(0.f); joint.shapePosition = glm::vec3(0.f);
} }
if (jointShapeInfo.numProjectedVertices == 0 if (jointShapeInfo.numVertexWeights == 0
&& jointShapeInfo.numVertices > 0) { && jointShapeInfo.numVertices > 0) {
// the bone projection algorithm was not able to compute the joint radius // the bone projection algorithm was not able to compute the joint radius
// so we use an alternative measure // so we use an alternative measure