mirror of
https://github.com/lubosz/overte.git
synced 2025-04-16 01:13:40 +02:00
Add support for baked skinned meshes
This commit is contained in:
parent
3793062045
commit
7db8d1dcbc
5 changed files with 48 additions and 20 deletions
|
@ -298,7 +298,7 @@ void FBXBaker::rewriteAndBakeSceneModels() {
|
|||
if (objectChild.name == "Geometry") {
|
||||
|
||||
// TODO Pull this out of _geometry instead so we don't have to reprocess it
|
||||
auto extractedMesh = FBXReader::extractMesh(objectChild, meshIndex);
|
||||
auto extractedMesh = FBXReader::extractMesh(objectChild, meshIndex, false);
|
||||
auto& mesh = extractedMesh.mesh;
|
||||
|
||||
Q_ASSERT(mesh.normals.size() == 0 || mesh.normals.size() == mesh.vertices.size());
|
||||
|
@ -338,6 +338,9 @@ void FBXBaker::rewriteAndBakeSceneModels() {
|
|||
|
||||
const int positionAttributeID = meshBuilder.AddAttribute(draco::GeometryAttribute::POSITION,
|
||||
3, draco::DT_FLOAT32);
|
||||
const int originalIndexAttributeID = meshBuilder.AddAttribute(
|
||||
(draco::GeometryAttribute::Type)DRACO_ATTRIBUTE_ORIGINAL_INDEX,
|
||||
1, draco::DT_INT32);
|
||||
|
||||
if (hasNormals) {
|
||||
normalsAttributeID = meshBuilder.AddAttribute(draco::GeometryAttribute::NORMAL,
|
||||
|
@ -367,14 +370,14 @@ void FBXBaker::rewriteAndBakeSceneModels() {
|
|||
draco::FaceIndex face;
|
||||
for (auto& part : mesh.parts) {
|
||||
const auto& matTex = extractedMesh.partMaterialTextures[partIndex];
|
||||
uint16_t materialID = matTex.first;
|
||||
|
||||
auto addFace = [&](QVector<int>& indices, int index, draco::FaceIndex face) {
|
||||
auto idx0 = indices[index];
|
||||
auto idx1 = indices[index + 1];
|
||||
auto idx2 = indices[index + 2];
|
||||
int32_t idx0 = indices[index];
|
||||
int32_t idx1 = indices[index + 1];
|
||||
int32_t idx2 = indices[index + 2];
|
||||
|
||||
if (hasPerFaceMaterials) {
|
||||
uint16_t materialID = matTex.first;
|
||||
meshBuilder.SetPerFaceAttributeValueForFace(faceMaterialAttributeID, face, &materialID);
|
||||
}
|
||||
|
||||
|
@ -382,6 +385,12 @@ void FBXBaker::rewriteAndBakeSceneModels() {
|
|||
&mesh.vertices[idx0], &mesh.vertices[idx1],
|
||||
&mesh.vertices[idx2]);
|
||||
|
||||
if (originalIndexAttributeID) {
|
||||
meshBuilder.SetAttributeValuesForFace(originalIndexAttributeID, face,
|
||||
&mesh.originalIndex[idx0],
|
||||
&mesh.originalIndex[idx1],
|
||||
&mesh.originalIndex[idx2]);
|
||||
}
|
||||
if (hasNormals) {
|
||||
meshBuilder.SetAttributeValuesForFace(normalsAttributeID, face,
|
||||
&mesh.normals[idx0], &mesh.normals[idx1],
|
||||
|
@ -432,6 +441,8 @@ void FBXBaker::rewriteAndBakeSceneModels() {
|
|||
dracoMesh->attribute(texCoords1AttributeID)->set_unique_id(DRACO_ATTRIBUTE_TEX_COORD_1);
|
||||
}
|
||||
|
||||
dracoMesh->attribute(originalIndexAttributeID)->set_unique_id(DRACO_ATTRIBUTE_ORIGINAL_INDEX);
|
||||
|
||||
draco::Encoder encoder;
|
||||
|
||||
encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, 14);
|
||||
|
|
|
@ -38,6 +38,7 @@ static const quint32 FBX_VERSION_2016 = 7500;
|
|||
static const int DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES = 1000;
|
||||
static const int DRACO_ATTRIBUTE_MATERIAL_ID = DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES;
|
||||
static const int DRACO_ATTRIBUTE_TEX_COORD_1 = DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES + 1;
|
||||
static const int DRACO_ATTRIBUTE_ORIGINAL_INDEX = DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES + 2;
|
||||
|
||||
|
||||
class FBXNode;
|
||||
|
@ -217,6 +218,7 @@ public:
|
|||
QVector<FBXMeshPart> parts;
|
||||
|
||||
QVector<glm::vec3> vertices;
|
||||
QVector<int32_t> originalIndex;
|
||||
QVector<glm::vec3> normals;
|
||||
QVector<glm::vec3> tangents;
|
||||
QVector<glm::vec3> colors;
|
||||
|
|
|
@ -110,7 +110,7 @@ public:
|
|||
|
||||
FBXGeometry* extractFBXGeometry(const QVariantHash& mapping, const QString& url);
|
||||
|
||||
static ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex);
|
||||
static ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex, bool deduplicate = true);
|
||||
QHash<QString, ExtractedMesh> meshes;
|
||||
static void buildModelMesh(FBXMesh& extractedMesh, const QString& url);
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ public:
|
|||
};
|
||||
|
||||
|
||||
void appendIndex(MeshData& data, QVector<int>& indices, int index) {
|
||||
void appendIndex(MeshData& data, QVector<int>& indices, int index, bool deduplicate) {
|
||||
if (index >= data.polygonIndices.size()) {
|
||||
return;
|
||||
}
|
||||
|
@ -156,12 +156,13 @@ void appendIndex(MeshData& data, QVector<int>& indices, int index) {
|
|||
}
|
||||
|
||||
QHash<Vertex, int>::const_iterator it = data.indices.find(vertex);
|
||||
if (it == data.indices.constEnd()) {
|
||||
if (!deduplicate || it == data.indices.constEnd()) {
|
||||
int newIndex = data.extracted.mesh.vertices.size();
|
||||
indices.append(newIndex);
|
||||
data.indices.insert(vertex, newIndex);
|
||||
data.extracted.newIndices.insert(vertexIndex, newIndex);
|
||||
data.extracted.mesh.vertices.append(position);
|
||||
data.extracted.mesh.originalIndices.append(vertexIndex);
|
||||
data.extracted.mesh.normals.append(normal);
|
||||
data.extracted.mesh.texCoords.append(vertex.texCoord);
|
||||
if (hasColors) {
|
||||
|
@ -176,7 +177,7 @@ void appendIndex(MeshData& data, QVector<int>& indices, int index) {
|
|||
}
|
||||
}
|
||||
|
||||
ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIndex) {
|
||||
ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIndex, bool deduplicate) {
|
||||
MeshData data;
|
||||
data.extracted.mesh.meshIndex = meshIndex++;
|
||||
|
||||
|
@ -355,6 +356,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
|
|||
auto extraTexCoordAttribute = dracoMesh->GetAttributeByUniqueId(DRACO_ATTRIBUTE_TEX_COORD_1);
|
||||
auto colorAttribute = dracoMesh->GetNamedAttribute(draco::GeometryAttribute::COLOR);
|
||||
auto matTexAttribute = dracoMesh->GetAttributeByUniqueId(DRACO_ATTRIBUTE_MATERIAL_ID);
|
||||
auto originalIndexAttribute = dracoMesh->GetAttributeByUniqueId(DRACO_ATTRIBUTE_ORIGINAL_INDEX);
|
||||
|
||||
// setup extracted mesh data structures given number of points
|
||||
auto numVertices = dracoMesh->num_points();
|
||||
|
@ -423,7 +425,17 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
|
|||
reinterpret_cast<float*>(&data.extracted.mesh.colors[i]));
|
||||
}
|
||||
|
||||
data.extracted.newIndices.insert(i, i);
|
||||
if (originalIndexAttribute) {
|
||||
auto mappedIndex = originalIndexAttribute->mapped_index(vertexIndex);
|
||||
|
||||
int32_t originalIndex;
|
||||
|
||||
originalIndexAttribute->ConvertValue<int32_t, 1>(mappedIndex, &originalIndex);
|
||||
|
||||
data.extracted.newIndices.insert(originalIndex, i);
|
||||
} else {
|
||||
data.extracted.newIndices.insert(i, i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < dracoMesh->num_faces(); ++i) {
|
||||
|
@ -487,10 +499,10 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
|
|||
FBXMeshPart& part = data.extracted.mesh.parts[partIndex - 1];
|
||||
|
||||
if (endIndex - beginIndex == 4) {
|
||||
appendIndex(data, part.quadIndices, beginIndex++);
|
||||
appendIndex(data, part.quadIndices, beginIndex++);
|
||||
appendIndex(data, part.quadIndices, beginIndex++);
|
||||
appendIndex(data, part.quadIndices, beginIndex++);
|
||||
appendIndex(data, part.quadIndices, beginIndex++, deduplicate);
|
||||
appendIndex(data, part.quadIndices, beginIndex++, deduplicate);
|
||||
appendIndex(data, part.quadIndices, beginIndex++, deduplicate);
|
||||
appendIndex(data, part.quadIndices, beginIndex++, deduplicate);
|
||||
|
||||
int quadStartIndex = part.quadIndices.size() - 4;
|
||||
int i0 = part.quadIndices[quadStartIndex + 0];
|
||||
|
@ -515,9 +527,9 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
|
|||
|
||||
} else {
|
||||
for (int nextIndex = beginIndex + 1;; ) {
|
||||
appendIndex(data, part.triangleIndices, beginIndex);
|
||||
appendIndex(data, part.triangleIndices, nextIndex++);
|
||||
appendIndex(data, part.triangleIndices, nextIndex);
|
||||
appendIndex(data, part.triangleIndices, beginIndex, deduplicate);
|
||||
appendIndex(data, part.triangleIndices, nextIndex++, deduplicate);
|
||||
appendIndex(data, part.triangleIndices, nextIndex, deduplicate);
|
||||
if (nextIndex >= data.polygonIndices.size() || data.polygonIndices.at(nextIndex) < 0) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -59,8 +59,6 @@ QByteArray FBXWriter::encodeFBX(const FBXNode& root) {
|
|||
}
|
||||
|
||||
void FBXWriter::encodeNode(QDataStream& out, const FBXNode& node) {
|
||||
qDebug() << "Encoding " << node.name;
|
||||
|
||||
auto device = out.device();
|
||||
auto nodeStartPos = device->pos();
|
||||
|
||||
|
@ -108,8 +106,12 @@ void FBXWriter::encodeNode(QDataStream& out, const FBXNode& node) {
|
|||
void FBXWriter::encodeFBXProperty(QDataStream& out, const QVariant& prop) {
|
||||
auto type = prop.userType();
|
||||
switch (type) {
|
||||
case QVariant::Type::Bool:
|
||||
case QMetaType::Short:
|
||||
out.device()->write("Y", 1);
|
||||
out << prop.value<int16_t>();
|
||||
break;
|
||||
|
||||
case QVariant::Type::Bool:
|
||||
out.device()->write("C", 1);
|
||||
out << prop.toBool();
|
||||
break;
|
||||
|
@ -229,6 +231,7 @@ void FBXWriter::encodeFBXProperty(QDataStream& out, const QVariant& prop) {
|
|||
writeVector(out, 'b', prop.value<QVector<bool>>());
|
||||
} else {
|
||||
qDebug() << "Unsupported property type in FBXWriter::encodeNode: " << type << prop;
|
||||
throw("Unsupported property type in FBXWriter::encodeNode: " + QString::number(type) + " " + prop.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue