Support for attaching models to joints.

This commit is contained in:
Andrzej Kapolka 2013-10-23 15:16:29 -07:00
parent 3f96343761
commit 41f73b5e9d
4 changed files with 96 additions and 2 deletions

View file

@ -9,6 +9,7 @@
#include <QBuffer>
#include <QDataStream>
#include <QIODevice>
#include <QStringList>
#include <QTextStream>
#include <QtDebug>
#include <QtEndian>
@ -397,6 +398,19 @@ glm::vec3 getVec3(const QVariantList& properties, int index) {
properties.at(index + 2).value<double>());
}
glm::vec3 parseVec3(const QString& string) {
QStringList elements = string.split(',');
if (elements.isEmpty()) {
return glm::vec3();
}
glm::vec3 value;
for (int i = 0; i < 3; i++) {
// duplicate last value if there aren't three elements
value[i] = elements.at(min(i, elements.size() - 1)).trimmed().toFloat();
}
return value;
}
const char* FACESHIFT_BLENDSHAPES[] = {
"EyeBlink_L",
"EyeBlink_R",
@ -1129,6 +1143,34 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
geometry.meshes.append(mesh);
}
// process attachments
QVariantHash attachments = mapping.value("attach").toHash();
for (QVariantHash::const_iterator it = attachments.constBegin(); it != attachments.constEnd(); it++) {
FBXAttachment attachment;
attachment.jointIndex = modelIDs.indexOf(it.key());
attachment.scale = glm::vec3(1.0f, 1.0f, 1.0f);
QVariantList properties = it->toList();
if (properties.isEmpty()) {
attachment.url = it->toUrl();
} else {
attachment.url = properties.at(0).toString();
if (properties.size() >= 2) {
attachment.translation = parseVec3(properties.at(1).toString());
if (properties.size() >= 3) {
attachment.rotation = glm::quat(glm::radians(parseVec3(properties.at(2).toString())));
if (properties.size() >= 4) {
attachment.scale = parseVec3(properties.at(3).toString());
}
}
}
}
geometry.attachments.append(attachment);
}
return geometry;
}

View file

@ -9,6 +9,7 @@
#ifndef __interface__FBXReader__
#define __interface__FBXReader__
#include <QUrl>
#include <QVarLengthArray>
#include <QVariant>
#include <QVector>
@ -98,6 +99,17 @@ public:
QVector<QVarLengthArray<QPair<int, int>, 4> > vertexConnections;
};
/// An attachment to an FBX document.
class FBXAttachment {
public:
int jointIndex;
QUrl url;
glm::vec3 translation;
glm::quat rotation;
glm::vec3 scale;
};
/// A set of meshes extracted from an FBX document.
class FBXGeometry {
public:
@ -117,6 +129,8 @@ public:
int headJointIndex;
glm::vec3 neckPivot;
QVector<FBXAttachment> attachments;
};
/// Reads FBX geometry from the supplied model and mapping data.

View file

@ -13,7 +13,8 @@
using namespace std;
Model::Model() :
Model::Model(QObject* parent) :
QObject(parent),
_pupilDilation(0.0f)
{
// we may have been created in the network thread, but we live in the main thread
@ -56,6 +57,10 @@ void Model::init() {
void Model::reset() {
_resetStates = true;
foreach (Model* attachment, _attachments) {
attachment->reset();
}
}
void Model::simulate(float deltaTime) {
@ -81,6 +86,13 @@ void Model::simulate(float deltaTime) {
}
_meshStates.append(state);
}
foreach (const FBXAttachment& attachment, geometry.attachments) {
Model* model = new Model(this);
model->init();
model->setURL(attachment.url);
model->setScale(attachment.scale);
_attachments.append(model);
}
_resetStates = true;
}
@ -89,6 +101,22 @@ void Model::simulate(float deltaTime) {
updateJointState(i);
}
// update the attachment transforms and simulate them
for (int i = 0; i < _attachments.size(); i++) {
const FBXAttachment& attachment = geometry.attachments.at(i);
Model* model = _attachments.at(i);
glm::vec3 jointTranslation = _translation;
glm::quat jointRotation = _rotation;
getJointPosition(attachment.jointIndex, jointTranslation);
getJointRotation(attachment.jointIndex, jointRotation);
model->setTranslation(jointTranslation + jointRotation * attachment.translation);
model->setRotation(jointRotation * attachment.rotation);
model->simulate(deltaTime);
}
for (int i = 0; i < _meshStates.size(); i++) {
MeshState& state = _meshStates[i];
const FBXMesh& mesh = geometry.meshes.at(i);
@ -175,6 +203,10 @@ void Model::simulate(float deltaTime) {
}
bool Model::render(float alpha) {
// render the attachments
foreach (Model* attachment, _attachments) {
attachment->render(alpha);
}
if (_meshStates.isEmpty()) {
return false;
}
@ -443,6 +475,10 @@ bool Model::getJointRotation(int jointIndex, glm::quat& rotation) const {
}
void Model::deleteGeometry() {
foreach (Model* attachment, _attachments) {
delete attachment;
}
_attachments.clear();
foreach (GLuint id, _blendedVertexBufferIDs) {
glDeleteBuffers(1, &id);
}

View file

@ -23,7 +23,7 @@ class Model : public QObject {
public:
Model();
Model(QObject* parent = NULL);
virtual ~Model();
void setTranslation(const glm::vec3& translation) { _translation = translation; }
@ -126,6 +126,8 @@ private:
QVector<glm::vec3> _blendedVertices;
QVector<glm::vec3> _blendedNormals;
QVector<Model*> _attachments;
static ProgramObject _program;
static ProgramObject _skinProgram;
static int _clusterMatricesLocation;