Compute the bone radii from the vertices. It's more error-prone than I

expected, but it more or less works.
This commit is contained in:
Andrzej Kapolka 2013-12-02 18:07:29 -08:00
parent 44f92fb47c
commit 2633223f4e
4 changed files with 60 additions and 4 deletions

View file

@ -224,6 +224,15 @@ glm::quat extractRotation(const glm::mat4& matrix, bool assumeOrthogonal) {
0.5f * sqrtf(z2) * (upper[0][1] >= upper[1][0] ? 1.0f : -1.0f)));
}
glm::vec3 extractScale(const glm::mat4& matrix) {
return glm::vec3(glm::length(matrix[0]), glm::length(matrix[1]), glm::length(matrix[2]));
}
float extractUniformScale(const glm::mat4& matrix) {
glm::vec3 scale = extractScale(matrix);
return (scale.x + scale.y + scale.z) / 3.0f;
}
// Draw a 3D vector floating in space
void drawVector(glm::vec3 * vector) {
glDisable(GL_LIGHTING);

View file

@ -61,6 +61,10 @@ void setTranslation(glm::mat4& matrix, const glm::vec3& translation);
glm::quat extractRotation(const glm::mat4& matrix, bool assumeOrthogonal = false);
glm::vec3 extractScale(const glm::mat4& matrix);
float extractUniformScale(const glm::mat4& matrix);
double diffclock(timeval *clock1,timeval *clock2);
void renderMouseVoxelGrid(const float& mouseVoxelX, const float& mouseVoxelY, const float& mouseVoxelZ, const float& mouseVoxelS);

View file

@ -20,6 +20,7 @@
#include <OctalCode.h>
#include <GeometryUtil.h>
#include <VoxelTree.h>
#include "FBXReader.h"
@ -1142,6 +1143,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
joint.distanceToParent = glm::distance(extractTranslation(parentJoint.transform),
extractTranslation(joint.transform));
}
joint.boneRadius = 0.0f;
joint.inverseBindRotation = joint.inverseDefaultRotation;
geometry.joints.append(joint);
geometry.jointIndices.insert(model.name, geometry.joints.size() - 1);
@ -1274,7 +1276,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
}
// whether we're skinned depends on how many clusters are attached
int maxJointIndex = extracted.mesh.clusters.at(0).jointIndex;
const FBXCluster& firstFBXCluster = extracted.mesh.clusters.at(0);
int maxJointIndex = firstFBXCluster.jointIndex;
glm::mat4 inverseModelTransform = glm::inverse(modelTransform);
if (clusterIDs.size() > 1) {
extracted.mesh.clusterIndices.resize(extracted.mesh.vertices.size());
extracted.mesh.clusterWeights.resize(extracted.mesh.vertices.size());
@ -1282,6 +1286,21 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
for (int i = 0; i < clusterIDs.size(); i++) {
QString clusterID = clusterIDs.at(i);
const Cluster& cluster = clusters[clusterID];
const FBXCluster& fbxCluster = extracted.mesh.clusters.at(i);
int jointIndex = fbxCluster.jointIndex;
FBXJoint& joint = geometry.joints[jointIndex];
glm::vec3 boneEnd = extractTranslation(inverseModelTransform * joint.bindTransform);
glm::vec3 boneDirection;
float boneLength;
if (joint.parentIndex != -1) {
boneDirection = boneEnd - extractTranslation(inverseModelTransform *
geometry.joints[joint.parentIndex].bindTransform);
boneLength = glm::length(boneDirection);
if (boneLength > EPSILON) {
boneDirection /= boneLength;
}
}
float radiusScale = extractUniformScale(joint.transform * fbxCluster.inverseBindMatrix);
float totalWeight = 0.0f;
for (int j = 0; j < cluster.indices.size(); j++) {
int oldIndex = cluster.indices.at(j);
@ -1289,9 +1308,18 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
totalWeight += weight;
for (QMultiHash<int, int>::const_iterator it = extracted.newIndices.constFind(oldIndex);
it != extracted.newIndices.end() && it.key() == oldIndex; it++) {
glm::vec4& weights = extracted.mesh.clusterWeights[it.value()];
// expand the bone radius
if (weight > 0.25f) {
const glm::vec3& vertex = extracted.mesh.vertices.at(it.value());
float proj = glm::dot(boneDirection, vertex - boneEnd);
if (proj < 0.0f && proj > -boneLength) {
joint.boneRadius = glm::max(joint.boneRadius, radiusScale * glm::distance(
vertex, boneEnd + boneDirection * proj));
} }
// look for an unused slot in the weights vector
glm::vec4& weights = extracted.mesh.clusterWeights[it.value()];
for (int k = 0; k < 4; k++) {
if (weights[k] == 0.0f) {
extracted.mesh.clusterIndices[it.value()][k] = i;
@ -1303,9 +1331,23 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
}
if (totalWeight > maxWeight) {
maxWeight = totalWeight;
maxJointIndex = extracted.mesh.clusters.at(i).jointIndex;
maxJointIndex = jointIndex;
}
}
} else {
int jointIndex = maxJointIndex;
FBXJoint& joint = geometry.joints[jointIndex];
glm::vec3 boneEnd = extractTranslation(inverseModelTransform * joint.bindTransform);
glm::vec3 boneStart = boneEnd;
if (joint.parentIndex != -1) {
boneStart = extractTranslation(inverseModelTransform * geometry.joints[joint.parentIndex].bindTransform);
}
float radiusScale = extractUniformScale(joint.transform * firstFBXCluster.inverseBindMatrix);
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
// expand the bone radius
joint.boneRadius = glm::max(joint.boneRadius, radiusScale * glm::length(
computeVectorFromPointToSegment(vertex, boneStart, boneEnd)));
}
}
extracted.mesh.isEye = (maxJointIndex == geometry.leftEyeJointIndex || maxJointIndex == geometry.rightEyeJointIndex);

View file

@ -47,6 +47,7 @@ public:
QVector<int> freeLineage;
int parentIndex;
float distanceToParent;
float boneRadius;
glm::mat4 preTransform;
glm::quat preRotation;
glm::quat rotation;