mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 07:19:21 +02:00
fix collision shape of avatars
This commit is contained in:
parent
41daea7d92
commit
16dfc39f5f
2 changed files with 22 additions and 35 deletions
|
@ -547,14 +547,11 @@ void SkeletonModel::computeBoundingShape() {
|
||||||
// compute the default transform of this joint
|
// compute the default transform of this joint
|
||||||
const JointState& state = _rig->getJointState(i);
|
const JointState& state = _rig->getJointState(i);
|
||||||
|
|
||||||
// HACK WORKAROUND: ignore joints that may have bad translation (e.g. have been flagged as such with zero radius)
|
// Each joint contributes a sphere at its position
|
||||||
if (state.getBoneRadius() > 0.0f) {
|
glm::vec3 axis(state.getBoneRadius());
|
||||||
// Each joint contributes a sphere at its position
|
glm::vec3 jointPosition = state.getPosition();
|
||||||
glm::vec3 axis(state.getBoneRadius());
|
totalExtents.addPoint(jointPosition + axis);
|
||||||
glm::vec3 jointPosition = state.getPosition();
|
totalExtents.addPoint(jointPosition - axis);
|
||||||
totalExtents.addPoint(jointPosition + axis);
|
|
||||||
totalExtents.addPoint(jointPosition - axis);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute bounding shape parameters
|
// compute bounding shape parameters
|
||||||
|
|
|
@ -2557,6 +2557,7 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping
|
||||||
int maxJointIndex = firstFBXCluster.jointIndex;
|
int maxJointIndex = firstFBXCluster.jointIndex;
|
||||||
glm::mat4 inverseModelTransform = glm::inverse(modelTransform);
|
glm::mat4 inverseModelTransform = glm::inverse(modelTransform);
|
||||||
if (clusterIDs.size() > 1) {
|
if (clusterIDs.size() > 1) {
|
||||||
|
// this is a multi-mesh joint
|
||||||
extracted.mesh.clusterIndices.resize(extracted.mesh.vertices.size());
|
extracted.mesh.clusterIndices.resize(extracted.mesh.vertices.size());
|
||||||
extracted.mesh.clusterWeights.resize(extracted.mesh.vertices.size());
|
extracted.mesh.clusterWeights.resize(extracted.mesh.vertices.size());
|
||||||
float maxWeight = 0.0f;
|
float maxWeight = 0.0f;
|
||||||
|
@ -2640,6 +2641,7 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// this is a single-mesh joint
|
||||||
int jointIndex = maxJointIndex;
|
int jointIndex = maxJointIndex;
|
||||||
FBXJoint& joint = geometry.joints[jointIndex];
|
FBXJoint& joint = geometry.joints[jointIndex];
|
||||||
JointShapeInfo& jointShapeInfo = jointShapeInfos[jointIndex];
|
JointShapeInfo& jointShapeInfo = jointShapeInfos[jointIndex];
|
||||||
|
@ -2660,6 +2662,7 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping
|
||||||
}
|
}
|
||||||
float radiusScale = extractUniformScale(joint.transform * firstFBXCluster.inverseBindMatrix);
|
float radiusScale = extractUniformScale(joint.transform * firstFBXCluster.inverseBindMatrix);
|
||||||
|
|
||||||
|
// compute average vertex
|
||||||
glm::vec3 averageVertex(0.0f);
|
glm::vec3 averageVertex(0.0f);
|
||||||
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
|
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
|
||||||
float proj = glm::dot(boneDirection, boneEnd - vertex);
|
float proj = glm::dot(boneDirection, boneEnd - vertex);
|
||||||
|
@ -2669,29 +2672,26 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping
|
||||||
++jointShapeInfo.numVertexWeights;
|
++jointShapeInfo.numVertexWeights;
|
||||||
averageVertex += vertex;
|
averageVertex += vertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compute joint's radius
|
||||||
int numVertices = extracted.mesh.vertices.size();
|
int numVertices = extracted.mesh.vertices.size();
|
||||||
jointShapeInfo.numVertices = numVertices;
|
jointShapeInfo.numVertices = numVertices;
|
||||||
if (numVertices > 0) {
|
if (numVertices > 0) {
|
||||||
|
// compute average radius
|
||||||
averageVertex /= (float)jointShapeInfo.numVertices;
|
averageVertex /= (float)jointShapeInfo.numVertices;
|
||||||
float averageRadius = 0.0f;
|
float averageRadius = 0.0f;
|
||||||
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
|
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
|
||||||
averageRadius += glm::distance(vertex, averageVertex);
|
averageRadius += glm::distance(vertex, averageVertex);
|
||||||
}
|
}
|
||||||
jointShapeInfo.averageRadius = averageRadius * radiusScale / (float)jointShapeInfo.numVertices;
|
averageRadius *= radiusScale / (float)jointShapeInfo.numVertices;
|
||||||
|
|
||||||
|
// final radius is minimum of average and weighted
|
||||||
|
float weightedRadius = jointShapeInfo.sumWeightedRadii / jointShapeInfo.sumVertexWeights;
|
||||||
|
jointShapeInfo.averageRadius = glm::min(weightedRadius, averageRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BUG: the boneBegin and/or boneEnd are incorrect for meshes that are "connected
|
// clear sumVertexWeights (this flags it as a single-mesh joint for later)
|
||||||
// under the bone" without weights. Unfortunately we haven't been able to find it yet.
|
|
||||||
// Although the the mesh vertices are correct in the model-frame, the joint's transform
|
|
||||||
// in the same frame is just BAD.
|
|
||||||
//
|
|
||||||
// HACK WORKAROUND: prevent these shapes from contributing to the collision capsule by setting
|
|
||||||
// some key members of jointShapeInfo to zero:
|
|
||||||
jointShapeInfo.numVertices = 0;
|
|
||||||
jointShapeInfo.sumVertexWeights = 0.0f;
|
jointShapeInfo.sumVertexWeights = 0.0f;
|
||||||
jointShapeInfo.numVertexWeights = 0;
|
|
||||||
jointShapeInfo.boneBegin = glm::vec3(0.0f);
|
|
||||||
jointShapeInfo.averageRadius = 0.0f;
|
|
||||||
}
|
}
|
||||||
extracted.mesh.isEye = (maxJointIndex == geometry.leftEyeJointIndex || maxJointIndex == geometry.rightEyeJointIndex);
|
extracted.mesh.isEye = (maxJointIndex == geometry.leftEyeJointIndex || maxJointIndex == geometry.rightEyeJointIndex);
|
||||||
|
|
||||||
|
@ -2727,22 +2727,12 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jointShapeInfo.sumVertexWeights > 0.0f) {
|
if (jointShapeInfo.sumVertexWeights > 0.0f) {
|
||||||
|
// mutiple meshes contributed to the bone radius and now that all
|
||||||
|
// contributing meshes are done we can finally compute the boneRadius
|
||||||
joint.boneRadius = jointShapeInfo.sumWeightedRadii / jointShapeInfo.sumVertexWeights;
|
joint.boneRadius = jointShapeInfo.sumWeightedRadii / jointShapeInfo.sumVertexWeights;
|
||||||
}
|
} else {
|
||||||
|
// single-mesh joint
|
||||||
// the joint is "capsule-like" if it had ANY mesh vertices successfully projected onto the bone
|
joint.boneRadius = jointShapeInfo.averageRadius;
|
||||||
// AND its boneRadius is not too close to zero
|
|
||||||
bool collideLikeCapsule = jointShapeInfo.numVertexWeights > 0
|
|
||||||
&& glm::length(jointShapeInfo.boneBegin) > EPSILON;
|
|
||||||
|
|
||||||
if (!collideLikeCapsule) {
|
|
||||||
// this joint's mesh did not successfully project onto the bone axis
|
|
||||||
// so it isn't "capsule-like" and we need to estimate its radius a different way:
|
|
||||||
// the average radius to the average point.
|
|
||||||
if (jointShapeInfo.numVertexWeights == 0
|
|
||||||
&& jointShapeInfo.numVertices > 0) {
|
|
||||||
joint.boneRadius = jointShapeInfo.averageRadius;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
geometry.palmDirection = parseVec3(mapping.value("palmDirection", "0, -1, 0").toString());
|
geometry.palmDirection = parseVec3(mapping.value("palmDirection", "0, -1, 0").toString());
|
||||||
|
|
Loading…
Reference in a new issue