mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 08:21:24 +02:00
very basic bounding info for joint meshes
This commit is contained in:
parent
b8c1bab4ae
commit
702612506b
2 changed files with 85 additions and 25 deletions
|
@ -6,6 +6,7 @@
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QIODevice>
|
#include <QIODevice>
|
||||||
|
@ -26,6 +27,11 @@
|
||||||
#include "FBXReader.h"
|
#include "FBXReader.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& s, const glm::vec3& v) {
|
||||||
|
s << "<" << v.x << "," << v.y << "," << v.z << ">";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
template<class T> QVariant readBinaryArray(QDataStream& in) {
|
template<class T> QVariant readBinaryArray(QDataStream& in) {
|
||||||
|
@ -536,8 +542,9 @@ public:
|
||||||
FBXBlendshape blendshape;
|
FBXBlendshape blendshape;
|
||||||
};
|
};
|
||||||
|
|
||||||
void printNode(const FBXNode& node, int indent) {
|
void printNode(const FBXNode& node, int indentLevel) {
|
||||||
QByteArray spaces(indent, ' ');
|
int indentLength = 2;
|
||||||
|
QByteArray spaces(indentLevel * indentLength, ' ');
|
||||||
QDebug nodeDebug = qDebug();
|
QDebug nodeDebug = qDebug();
|
||||||
|
|
||||||
nodeDebug.nospace() << spaces.data() << node.name.data() << ": ";
|
nodeDebug.nospace() << spaces.data() << node.name.data() << ": ";
|
||||||
|
@ -546,7 +553,7 @@ void printNode(const FBXNode& node, int indent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (const FBXNode& child, node.children) {
|
foreach (const FBXNode& child, node.children) {
|
||||||
printNode(child, indent + 1);
|
printNode(child, indentLevel + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -841,6 +848,9 @@ QString getString(const QVariant& value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) {
|
FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) {
|
||||||
|
// std::cout << "adebug beginPrintNode " << std::endl; // adebug
|
||||||
|
// printNode(node, 0); // adebug
|
||||||
|
// std::cout << "adebug endPrintNode " << std::endl; // adebug
|
||||||
QHash<QString, ExtractedMesh> meshes;
|
QHash<QString, ExtractedMesh> meshes;
|
||||||
QVector<ExtractedBlendshape> blendshapes;
|
QVector<ExtractedBlendshape> blendshapes;
|
||||||
QMultiHash<QString, QString> parentMap;
|
QMultiHash<QString, QString> parentMap;
|
||||||
|
@ -1248,6 +1258,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
}
|
}
|
||||||
joint.boneRadius = 0.0f;
|
joint.boneRadius = 0.0f;
|
||||||
joint.inverseBindRotation = joint.inverseDefaultRotation;
|
joint.inverseBindRotation = joint.inverseDefaultRotation;
|
||||||
|
joint.name = model.name;
|
||||||
|
joint.extents.minimum = glm::vec3(FLT_MAX);
|
||||||
|
joint.extents.maximum = glm::vec3(-FLT_MAX);
|
||||||
|
joint.averageVertex = glm::vec3(0.f);
|
||||||
|
joint.numVertices = 0;
|
||||||
|
joint.averageRadius = 0.f;
|
||||||
geometry.joints.append(joint);
|
geometry.joints.append(joint);
|
||||||
geometry.jointIndices.insert(model.name, geometry.joints.size() - 1);
|
geometry.jointIndices.insert(model.name, geometry.joints.size() - 1);
|
||||||
}
|
}
|
||||||
|
@ -1272,10 +1288,10 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
geometry.neckPivot = glm::vec3(transform[3][0], transform[3][1], transform[3][2]);
|
geometry.neckPivot = glm::vec3(transform[3][0], transform[3][1], transform[3][2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
geometry.bindExtents.minimum = glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX);
|
geometry.bindExtents.minimum = glm::vec3(FLT_MAX);
|
||||||
geometry.bindExtents.maximum = glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
geometry.bindExtents.maximum = glm::vec3(-FLT_MAX);
|
||||||
geometry.staticExtents.minimum = glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX);
|
geometry.staticExtents.minimum = glm::vec3(FLT_MAX);
|
||||||
geometry.staticExtents.maximum = glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
geometry.staticExtents.maximum = glm::vec3(-FLT_MAX);
|
||||||
|
|
||||||
QVariantHash springs = mapping.value("spring").toHash();
|
QVariantHash springs = mapping.value("spring").toHash();
|
||||||
QVariant defaultSpring = springs.value("default");
|
QVariant defaultSpring = springs.value("default");
|
||||||
|
@ -1405,11 +1421,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
cluster.jointIndex = 0;
|
cluster.jointIndex = 0;
|
||||||
}
|
}
|
||||||
extracted.mesh.clusters.append(cluster);
|
extracted.mesh.clusters.append(cluster);
|
||||||
// BUG: joints that fall into this context do not get their bindTransform and
|
|
||||||
// inverseBindRotation data members properly set. This causes bad boneRadius
|
|
||||||
// and boneLength calculations for collision proxies. Affected joints are usually:
|
|
||||||
// hair, teeth, tongue. I tried to figure out how to fix this but was going
|
|
||||||
// crosseyed trying to understand FBX so I gave up for the time being -- Andrew.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// whether we're skinned depends on how many clusters are attached
|
// whether we're skinned depends on how many clusters are attached
|
||||||
|
@ -1426,12 +1437,15 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
const FBXCluster& fbxCluster = extracted.mesh.clusters.at(i);
|
const FBXCluster& fbxCluster = extracted.mesh.clusters.at(i);
|
||||||
int jointIndex = fbxCluster.jointIndex;
|
int jointIndex = fbxCluster.jointIndex;
|
||||||
FBXJoint& joint = geometry.joints[jointIndex];
|
FBXJoint& joint = geometry.joints[jointIndex];
|
||||||
glm::vec3 boneEnd = extractTranslation(inverseModelTransform * joint.bindTransform);
|
glm::mat4 transformJointToMesh = inverseModelTransform * joint.bindTransform;
|
||||||
|
glm::quat rotateMeshToJoint = glm::inverse(extractRotation(transformJointToMesh));
|
||||||
|
glm::vec3 boneEnd = extractTranslation(transformJointToMesh);
|
||||||
|
glm::vec3 boneBegin = boneEnd;
|
||||||
glm::vec3 boneDirection;
|
glm::vec3 boneDirection;
|
||||||
float boneLength;
|
float boneLength;
|
||||||
if (joint.parentIndex != -1) {
|
if (joint.parentIndex != -1) {
|
||||||
boneDirection = boneEnd - extractTranslation(inverseModelTransform *
|
boneBegin = extractTranslation(inverseModelTransform * geometry.joints[joint.parentIndex].bindTransform);
|
||||||
geometry.joints[joint.parentIndex].bindTransform);
|
boneDirection = boneEnd - boneBegin;
|
||||||
boneLength = glm::length(boneDirection);
|
boneLength = glm::length(boneDirection);
|
||||||
if (boneLength > EPSILON) {
|
if (boneLength > EPSILON) {
|
||||||
boneDirection /= boneLength;
|
boneDirection /= boneLength;
|
||||||
|
@ -1453,9 +1467,13 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
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, vertex - boneEnd);
|
float proj = glm::dot(boneDirection, vertex - boneEnd);
|
||||||
if (proj < 0.0f && proj > -boneLength) {
|
if (proj < 0.0f && proj > -boneLength) {
|
||||||
joint.boneRadius = glm::max(joint.boneRadius, radiusScale * glm::distance(
|
joint.boneRadius = glm::max(joint.boneRadius, radiusScale * glm::distance(vertex, boneEnd + boneDirection * proj));
|
||||||
vertex, boneEnd + boneDirection * proj));
|
|
||||||
}
|
}
|
||||||
|
glm::vec3 vertexInJointFrame = rotateMeshToJoint * (radiusScale * (vertex - boneEnd));
|
||||||
|
joint.extents.minimum = glm::min(joint.extents.minimum, vertexInJointFrame);
|
||||||
|
joint.extents.maximum = glm::max(joint.extents.maximum, vertexInJointFrame);
|
||||||
|
joint.averageVertex += vertexInJointFrame;
|
||||||
|
++joint.numVertices;
|
||||||
if (jointIsStatic) {
|
if (jointIsStatic) {
|
||||||
// expand the extents of static (nonmovable) joints
|
// expand the extents of static (nonmovable) joints
|
||||||
geometry.staticExtents.minimum = glm::min(geometry.staticExtents.minimum, vertex + jointTranslation);
|
geometry.staticExtents.minimum = glm::min(geometry.staticExtents.minimum, vertex + jointTranslation);
|
||||||
|
@ -1482,7 +1500,11 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
} else {
|
} else {
|
||||||
int jointIndex = maxJointIndex;
|
int jointIndex = maxJointIndex;
|
||||||
FBXJoint& joint = geometry.joints[jointIndex];
|
FBXJoint& joint = geometry.joints[jointIndex];
|
||||||
glm::vec3 boneEnd = extractTranslation(inverseModelTransform * joint.bindTransform);
|
|
||||||
|
glm::mat4 transformJointToMesh = inverseModelTransform * joint.bindTransform;
|
||||||
|
glm::quat rotateMeshToJoint = glm::inverse(extractRotation(transformJointToMesh));
|
||||||
|
glm::vec3 boneEnd = extractTranslation(transformJointToMesh);
|
||||||
|
|
||||||
glm::vec3 boneDirection;
|
glm::vec3 boneDirection;
|
||||||
float boneLength;
|
float boneLength;
|
||||||
if (joint.parentIndex != -1) {
|
if (joint.parentIndex != -1) {
|
||||||
|
@ -1493,6 +1515,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
boneDirection /= boneLength;
|
boneDirection /= boneLength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float radiusScale = extractUniformScale(joint.transform * firstFBXCluster.inverseBindMatrix);
|
float radiusScale = extractUniformScale(joint.transform * firstFBXCluster.inverseBindMatrix);
|
||||||
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
|
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
|
||||||
float proj = glm::dot(boneDirection, vertex - boneEnd);
|
float proj = glm::dot(boneDirection, vertex - boneEnd);
|
||||||
|
@ -1500,6 +1523,22 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
joint.boneRadius = glm::max(joint.boneRadius, radiusScale * glm::distance(
|
joint.boneRadius = glm::max(joint.boneRadius, radiusScale * glm::distance(
|
||||||
vertex, boneEnd + boneDirection * proj));
|
vertex, boneEnd + boneDirection * proj));
|
||||||
}
|
}
|
||||||
|
glm::vec3 vertexInJointFrame = rotateMeshToJoint * (radiusScale * (vertex - boneEnd));
|
||||||
|
joint.extents.minimum = glm::min(joint.extents.minimum, vertexInJointFrame);
|
||||||
|
joint.extents.maximum = glm::max(joint.extents.maximum, vertexInJointFrame);
|
||||||
|
joint.averageVertex += vertex;
|
||||||
|
++joint.numVertices;
|
||||||
|
}
|
||||||
|
if (joint.numVertices > 0) {
|
||||||
|
joint.averageVertex /= float(joint.numVertices);
|
||||||
|
float averageRadius = 0.f;
|
||||||
|
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
|
||||||
|
averageRadius += glm::distance(vertex, joint.averageVertex);
|
||||||
|
}
|
||||||
|
joint.boneRadius = averageRadius * (radiusScale / float(joint.numVertices));
|
||||||
|
//joint.averageVertex /= float(joint.numVertices);
|
||||||
|
joint.averageVertex = rotateMeshToJoint * (radiusScale * (joint.averageVertex - boneEnd));
|
||||||
|
joint.numVertices = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extracted.mesh.isEye = (maxJointIndex == geometry.leftEyeJointIndex || maxJointIndex == geometry.rightEyeJointIndex);
|
extracted.mesh.isEye = (maxJointIndex == geometry.leftEyeJointIndex || maxJointIndex == geometry.rightEyeJointIndex);
|
||||||
|
@ -1579,6 +1618,22 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
geometry.attachments.append(attachment);
|
geometry.attachments.append(attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < geometry.joints.size(); ++i) {
|
||||||
|
FBXJoint& joint = geometry.joints[i];
|
||||||
|
if (joint.numVertices > 0) {
|
||||||
|
//joint.averageVertex /= 1.f;
|
||||||
|
joint.averageVertex /= float(joint.numVertices);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
std::cout << joint.name.toStdString().c_str()
|
||||||
|
<< " bR = " << joint.boneRadius
|
||||||
|
<< " extents = " << (joint.extents.maximum - joint.extents.minimum)
|
||||||
|
<< " avgV = " << joint.averageVertex
|
||||||
|
<< " numV = " << joint.numVertices
|
||||||
|
<< std::endl; // adebug
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
return geometry;
|
return geometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,13 @@ typedef QList<FBXNode> FBXNodeList;
|
||||||
/// The names of the blendshapes expected by Faceshift, terminated with an empty string.
|
/// The names of the blendshapes expected by Faceshift, terminated with an empty string.
|
||||||
extern const char* FACESHIFT_BLENDSHAPES[];
|
extern const char* FACESHIFT_BLENDSHAPES[];
|
||||||
|
|
||||||
|
class Extents {
|
||||||
|
public:
|
||||||
|
|
||||||
|
glm::vec3 minimum;
|
||||||
|
glm::vec3 maximum;
|
||||||
|
};
|
||||||
|
|
||||||
/// A node within an FBX document.
|
/// A node within an FBX document.
|
||||||
class FBXNode {
|
class FBXNode {
|
||||||
public:
|
public:
|
||||||
|
@ -63,6 +70,11 @@ public:
|
||||||
glm::quat inverseDefaultRotation;
|
glm::quat inverseDefaultRotation;
|
||||||
glm::quat inverseBindRotation;
|
glm::quat inverseBindRotation;
|
||||||
glm::mat4 bindTransform;
|
glm::mat4 bindTransform;
|
||||||
|
QString name;
|
||||||
|
Extents extents;
|
||||||
|
int numVertices;
|
||||||
|
glm::vec3 averageVertex;
|
||||||
|
float averageRadius;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A single binding to a joint in an FBX document.
|
/// A single binding to a joint in an FBX document.
|
||||||
|
@ -124,13 +136,6 @@ public:
|
||||||
glm::vec3 scale;
|
glm::vec3 scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Extents {
|
|
||||||
public:
|
|
||||||
|
|
||||||
glm::vec3 minimum;
|
|
||||||
glm::vec3 maximum;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A set of meshes extracted from an FBX document.
|
/// A set of meshes extracted from an FBX document.
|
||||||
class FBXGeometry {
|
class FBXGeometry {
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in a new issue