Merge pull request from AndrewMeadows/avatar-capsule

fix bounding capusule calculations for new avatars
This commit is contained in:
Anthony Thibault 2015-11-18 13:02:48 -08:00
commit d3d3ddfaf1
4 changed files with 41 additions and 60 deletions

View file

@ -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")) {
@ -668,7 +664,7 @@ void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float alpha
// draw a blue sphere at the capsule top point
glm::vec3 topPoint = _translation + _boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * glm::vec3(0.0f, 1.0f, 0.0f);
deferredLighting->renderSolidSphereInstance(batch,
deferredLighting->renderSolidSphereInstance(batch,
Transform().setTranslation(topPoint).postScale(_boundingCapsuleRadius),
glm::vec4(0.6f, 0.6f, 0.8f, alpha));
@ -676,7 +672,7 @@ void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float alpha
glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, _boundingCapsuleHeight, 0.0f);
glm::vec3 axis = topPoint - bottomPoint;
deferredLighting->renderSolidSphereInstance(batch,
deferredLighting->renderSolidSphereInstance(batch,
Transform().setTranslation(bottomPoint).postScale(_boundingCapsuleRadius),
glm::vec4(0.8f, 0.8f, 0.6f, alpha));

View file

@ -82,7 +82,7 @@ public:
bool getNeckPosition(glm::vec3& neckPosition) const;
bool getLocalNeckPosition(glm::vec3& neckPosition) const;
/// Returns the rotation of the neck joint's parent from default orientation
/// \return whether or not the neck was found
bool getNeckParentRotationFromDefaultOrientation(glm::quat& neckParentRotation) const;

View file

@ -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,49 @@ 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
const float INV_SQRT_3 = 0.57735026918f;
ShapeVertices cardinalDirections = {
Vectors::UNIT_X,
Vectors::UNIT_Y,
Vectors::UNIT_Z,
glm::vec3(INV_SQRT_3, INV_SQRT_3, INV_SQRT_3),
glm::vec3(INV_SQRT_3, -INV_SQRT_3, INV_SQRT_3),
glm::vec3(INV_SQRT_3, INV_SQRT_3, -INV_SQRT_3),
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();
avgPoint /= (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;
// 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());

View file

@ -56,7 +56,6 @@ public:
struct FBXJointShapeInfo {
// same units and frame as FBXJoint.translation
QVector<glm::vec3> points;
float radius;
};
/// A single joint (transformation node) extracted from an FBX document.