mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 04:43:31 +02:00
use kDop volume of avatar mesh parts for capsule
This commit is contained in:
parent
9c29ba2ca3
commit
ee751ed1b9
3 changed files with 38 additions and 58 deletions
|
@ -625,19 +625,15 @@ void SkeletonModel::computeBoundingShape() {
|
||||||
totalExtents.addPoint(glm::vec3(0.0f));
|
totalExtents.addPoint(glm::vec3(0.0f));
|
||||||
int numStates = _rig->getJointStateCount();
|
int numStates = _rig->getJointStateCount();
|
||||||
for (int i = 0; i < numStates; i++) {
|
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.
|
// Each joint contributes a capsule defined by FBXJoint.shapeInfo.
|
||||||
// For totalExtents we use the capsule endpoints expanded by the radius.
|
// 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;
|
const FBXJointShapeInfo& shapeInfo = geometry.joints.at(i).shapeInfo;
|
||||||
for (int j = 0; j < shapeInfo.points.size(); ++j) {
|
if (shapeInfo.points.size() > 0) {
|
||||||
glm::vec3 transformedPoint = extractTranslation(jointTransform * glm::translate(shapeInfo.points[j]));
|
for (int j = 0; j < shapeInfo.points.size(); ++j) {
|
||||||
vec3 radius(scale * shapeInfo.radius);
|
totalExtents.addPoint(extractTranslation(jointTransform * glm::translate(shapeInfo.points[j])));
|
||||||
totalExtents.addPoint(transformedPoint + radius);
|
}
|
||||||
totalExtents.addPoint(transformedPoint - radius);
|
|
||||||
}
|
}
|
||||||
// HACK so that default legless robot doesn't knuckle-drag
|
// HACK so that default legless robot doesn't knuckle-drag
|
||||||
if (shapeInfo.points.size() == 0 && (state.getName() == "LeftFoot" || state.getName() == "RightFoot")) {
|
if (shapeInfo.points.size() == 0 && (state.getName() == "LeftFoot" || state.getName() == "RightFoot")) {
|
||||||
|
|
|
@ -1460,7 +1460,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
|
||||||
it != extracted.newIndices.end() && it.key() == oldIndex; it++) {
|
it != extracted.newIndices.end() && it.key() == oldIndex; it++) {
|
||||||
|
|
||||||
// remember vertices with at least 1/4 weight
|
// 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) {
|
if (weight > EXPANSION_WEIGHT_THRESHOLD) {
|
||||||
// transform to joint-frame and save for later
|
// transform to joint-frame and save for later
|
||||||
const glm::mat4 vertexTransform = meshToJoint * glm::translate(extracted.mesh.vertices.at(it.value()));
|
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);
|
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);
|
glm::vec3 defaultCapsuleAxis(0.0f, 1.0f, 0.0f);
|
||||||
for (int i = 0; i < geometry.joints.size(); ++i) {
|
for (int i = 0; i < geometry.joints.size(); ++i) {
|
||||||
FBXJoint& joint = geometry.joints[i];
|
FBXJoint& joint = geometry.joints[i];
|
||||||
|
|
||||||
// NOTE: points are in joint-frame
|
// NOTE: points are in joint-frame
|
||||||
// compute average point
|
|
||||||
ShapeVertices& points = shapeVertices[i];
|
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) {
|
if (points.size() > 0) {
|
||||||
float minProjection = FLT_MAX;
|
// compute average point
|
||||||
float maxProjection = -FLT_MIN;
|
glm::vec3 avgPoint = glm::vec3(0.0f);
|
||||||
for (uint32_t j = 0; j < points.size(); ++j) {
|
for (uint32_t j = 0; j < points.size(); ++j) {
|
||||||
glm::vec3 offset = points[j] - avgPoint;
|
avgPoint += points[j];
|
||||||
float projection = glm::dot(offset, axis);
|
|
||||||
maxProjection = glm::max(maxProjection, projection);
|
|
||||||
minProjection = glm::min(minProjection, projection);
|
|
||||||
avgRadius += glm::length(offset - projection * axis);
|
|
||||||
}
|
}
|
||||||
avgRadius /= (float)points.size();
|
avgPoint /= (float)points.size();
|
||||||
|
|
||||||
// compute endpoints of capsule in joint-frame
|
// compute a k-Dop bounding volume
|
||||||
glm::vec3 capsuleBegin = avgPoint;
|
for (uint32_t j = 0; j < cardinalDirections.size(); ++j) {
|
||||||
glm::vec3 capsuleEnd = avgPoint;
|
float maxDot = -FLT_MAX;
|
||||||
if (maxProjection - minProjection < 2.0f * avgRadius) {
|
float minDot = FLT_MIN;
|
||||||
// the mesh-as-cylinder approximation is too short to collide as a capsule
|
for (uint32_t k = 0; k < points.size(); ++k) {
|
||||||
// so we'll collapse it to a sphere (although that isn't a very good approximation)
|
float kDot = glm::dot(cardinalDirections[j], points[k] - avgPoint);
|
||||||
capsuleBegin = avgPoint + 0.5f * (maxProjection + minProjection) * axis;
|
if (kDot > maxDot) {
|
||||||
capsuleEnd = capsuleBegin;
|
maxDot = kDot;
|
||||||
} else {
|
}
|
||||||
capsuleBegin = avgPoint + (minProjection + avgRadius) * axis;
|
if (kDot < minDot) {
|
||||||
capsuleEnd = avgPoint + (maxProjection - avgRadius) * axis;
|
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());
|
geometry.palmDirection = parseVec3(mapping.value("palmDirection", "0, -1, 0").toString());
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,6 @@ public:
|
||||||
struct FBXJointShapeInfo {
|
struct FBXJointShapeInfo {
|
||||||
// same units and frame as FBXJoint.translation
|
// same units and frame as FBXJoint.translation
|
||||||
QVector<glm::vec3> points;
|
QVector<glm::vec3> points;
|
||||||
float radius;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A single joint (transformation node) extracted from an FBX document.
|
/// A single joint (transformation node) extracted from an FBX document.
|
||||||
|
|
Loading…
Reference in a new issue