mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 11:50:39 +02:00
Merge pull request #971 from ey6es/blendface
Fix to allow models other than the pug.
This commit is contained in:
commit
8fa4a60d31
1 changed files with 41 additions and 16 deletions
|
@ -41,6 +41,7 @@ template<class T> QVariant readArray(QDataStream& in) {
|
||||||
QByteArray uncompressed = qUncompress(compressed);
|
QByteArray uncompressed = qUncompress(compressed);
|
||||||
QDataStream uncompressedIn(uncompressed);
|
QDataStream uncompressedIn(uncompressed);
|
||||||
uncompressedIn.setByteOrder(QDataStream::LittleEndian);
|
uncompressedIn.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
uncompressedIn.setVersion(QDataStream::Qt_4_5); // for single/double precision switch
|
||||||
for (int i = 0; i < arrayLength; i++) {
|
for (int i = 0; i < arrayLength; i++) {
|
||||||
T value;
|
T value;
|
||||||
uncompressedIn >> value;
|
uncompressedIn >> value;
|
||||||
|
@ -132,7 +133,7 @@ FBXNode parseFBXNode(QDataStream& in) {
|
||||||
if (endOffset < MIN_VALID_OFFSET || nameLength == 0) {
|
if (endOffset < MIN_VALID_OFFSET || nameLength == 0) {
|
||||||
// use a null name to indicate a null node
|
// use a null name to indicate a null node
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
node.name = in.device()->read(nameLength);
|
node.name = in.device()->read(nameLength);
|
||||||
|
|
||||||
for (int i = 0; i < propertyCount; i++) {
|
for (int i = 0; i < propertyCount; i++) {
|
||||||
|
@ -155,6 +156,7 @@ FBXNode parseFBXNode(QDataStream& in) {
|
||||||
FBXNode parseFBX(QIODevice* device) {
|
FBXNode parseFBX(QIODevice* device) {
|
||||||
QDataStream in(device);
|
QDataStream in(device);
|
||||||
in.setByteOrder(QDataStream::LittleEndian);
|
in.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
in.setVersion(QDataStream::Qt_4_5); // for single/double precision switch
|
||||||
|
|
||||||
// see http://code.blender.org/index.php/2013/08/fbx-binary-file-format-specification/ for an explanation
|
// see http://code.blender.org/index.php/2013/08/fbx-binary-file-format-specification/ for an explanation
|
||||||
// of the FBX format
|
// of the FBX format
|
||||||
|
@ -258,18 +260,23 @@ QHash<QByteArray, int> createBlendshapeMap() {
|
||||||
}
|
}
|
||||||
|
|
||||||
FBXGeometry extractFBXGeometry(const FBXNode& node) {
|
FBXGeometry extractFBXGeometry(const FBXNode& node) {
|
||||||
FBXGeometry geometry;
|
QVector<FBXBlendshape> blendshapes;
|
||||||
|
QHash<qint64, FBXGeometry> meshMap;
|
||||||
|
qint64 blendshapeId = 0;
|
||||||
|
QHash<qint64, qint64> parentMap;
|
||||||
|
|
||||||
foreach (const FBXNode& child, node.children) {
|
foreach (const FBXNode& child, node.children) {
|
||||||
if (child.name == "Objects") {
|
if (child.name == "Objects") {
|
||||||
foreach (const FBXNode& object, child.children) {
|
foreach (const FBXNode& object, child.children) {
|
||||||
if (object.name == "Geometry") {
|
if (object.name == "Geometry") {
|
||||||
if (object.properties.at(2) == "Mesh") {
|
if (object.properties.at(2) == "Mesh") {
|
||||||
|
FBXGeometry mesh;
|
||||||
|
|
||||||
QVector<glm::vec3> vertices;
|
QVector<glm::vec3> vertices;
|
||||||
QVector<int> polygonIndices;
|
QVector<int> polygonIndices;
|
||||||
foreach (const FBXNode& data, object.children) {
|
foreach (const FBXNode& data, object.children) {
|
||||||
if (data.name == "Vertices") {
|
if (data.name == "Vertices") {
|
||||||
geometry.vertices = createVec3Vector(data.properties.at(0).value<QVector<double> >());
|
mesh.vertices = createVec3Vector(data.properties.at(0).value<QVector<double> >());
|
||||||
|
|
||||||
} else if (data.name == "PolygonVertexIndex") {
|
} else if (data.name == "PolygonVertexIndex") {
|
||||||
polygonIndices = data.properties.at(0).value<QVector<int> >();
|
polygonIndices = data.properties.at(0).value<QVector<int> >();
|
||||||
|
@ -277,7 +284,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node) {
|
||||||
} else if (data.name == "LayerElementNormal") {
|
} else if (data.name == "LayerElementNormal") {
|
||||||
foreach (const FBXNode& subdata, data.children) {
|
foreach (const FBXNode& subdata, data.children) {
|
||||||
if (subdata.name == "Normals") {
|
if (subdata.name == "Normals") {
|
||||||
geometry.normals = createVec3Vector(
|
mesh.normals = createVec3Vector(
|
||||||
subdata.properties.at(0).value<QVector<double> >());
|
subdata.properties.at(0).value<QVector<double> >());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,25 +297,26 @@ FBXGeometry extractFBXGeometry(const FBXNode& node) {
|
||||||
while (*endIndex++ >= 0);
|
while (*endIndex++ >= 0);
|
||||||
|
|
||||||
if (endIndex - beginIndex == 4) {
|
if (endIndex - beginIndex == 4) {
|
||||||
geometry.quadIndices.append(*beginIndex++);
|
mesh.quadIndices.append(*beginIndex++);
|
||||||
geometry.quadIndices.append(*beginIndex++);
|
mesh.quadIndices.append(*beginIndex++);
|
||||||
geometry.quadIndices.append(*beginIndex++);
|
mesh.quadIndices.append(*beginIndex++);
|
||||||
geometry.quadIndices.append(-*beginIndex++ - 1);
|
mesh.quadIndices.append(-*beginIndex++ - 1);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
for (const int* nextIndex = beginIndex + 1;; ) {
|
for (const int* nextIndex = beginIndex + 1;; ) {
|
||||||
geometry.triangleIndices.append(*beginIndex);
|
mesh.triangleIndices.append(*beginIndex);
|
||||||
geometry.triangleIndices.append(*nextIndex++);
|
mesh.triangleIndices.append(*nextIndex++);
|
||||||
if (*nextIndex >= 0) {
|
if (*nextIndex >= 0) {
|
||||||
geometry.triangleIndices.append(*nextIndex);
|
mesh.triangleIndices.append(*nextIndex);
|
||||||
} else {
|
} else {
|
||||||
geometry.triangleIndices.append(-*nextIndex - 1);
|
mesh.triangleIndices.append(-*nextIndex - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
beginIndex = endIndex;
|
beginIndex = endIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
meshMap.insert(object.properties.at(0).value<qint64>(), mesh);
|
||||||
|
|
||||||
} else { // object.properties.at(2) == "Shape"
|
} else { // object.properties.at(2) == "Shape"
|
||||||
FBXBlendshape blendshape;
|
FBXBlendshape blendshape;
|
||||||
|
@ -328,14 +336,31 @@ FBXGeometry extractFBXGeometry(const FBXNode& node) {
|
||||||
QByteArray name = object.properties.at(1).toByteArray();
|
QByteArray name = object.properties.at(1).toByteArray();
|
||||||
static QHash<QByteArray, int> blendshapeMap = createBlendshapeMap();
|
static QHash<QByteArray, int> blendshapeMap = createBlendshapeMap();
|
||||||
int index = blendshapeMap.value(name.left(name.indexOf('\0')));
|
int index = blendshapeMap.value(name.left(name.indexOf('\0')));
|
||||||
geometry.blendshapes.resize(qMax(geometry.blendshapes.size(), index + 1));
|
blendshapes.resize(qMax(blendshapes.size(), index + 1));
|
||||||
geometry.blendshapes[index] = blendshape;
|
blendshapes[index] = blendshape;
|
||||||
}
|
}
|
||||||
}
|
} else if (object.name == "Deformer" && object.properties.at(2) == "BlendShape") {
|
||||||
|
blendshapeId = object.properties.at(0).value<qint64>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (child.name == "Connections") {
|
||||||
|
foreach (const FBXNode& connection, child.children) {
|
||||||
|
if (connection.name == "C") {
|
||||||
|
parentMap.insert(connection.properties.at(1).value<qint64>(), connection.properties.at(2).value<qint64>());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the mesh that owns the blendshape
|
||||||
|
FBXGeometry geometry;
|
||||||
|
if (meshMap.size() == 1) {
|
||||||
|
geometry = *meshMap.begin();
|
||||||
|
} else {
|
||||||
|
geometry = meshMap.take(parentMap.value(blendshapeId));
|
||||||
|
}
|
||||||
|
geometry.blendshapes = blendshapes;
|
||||||
|
|
||||||
return geometry;
|
return geometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue