mirror of
https://github.com/lubosz/overte.git
synced 2025-08-12 20:03:58 +02:00
Merge pull request #16484 from sabrina-shanman/instancing_oven
(DEV-2593) Instancing: Fix model baking to work with new hfm::Shape material definition
This commit is contained in:
commit
5f99c36bb1
9 changed files with 70 additions and 58 deletions
|
@ -37,10 +37,10 @@ const QByteArray MESH = "Mesh";
|
||||||
|
|
||||||
void OBJBaker::bakeProcessedSource(const hfm::Model::Pointer& hfmModel, const std::vector<hifi::ByteArray>& dracoMeshes, const std::vector<std::vector<hifi::ByteArray>>& dracoMaterialLists) {
|
void OBJBaker::bakeProcessedSource(const hfm::Model::Pointer& hfmModel, const std::vector<hifi::ByteArray>& dracoMeshes, const std::vector<std::vector<hifi::ByteArray>>& dracoMaterialLists) {
|
||||||
// Write OBJ Data as FBX tree nodes
|
// Write OBJ Data as FBX tree nodes
|
||||||
createFBXNodeTree(_rootNode, hfmModel, dracoMeshes[0]);
|
createFBXNodeTree(_rootNode, hfmModel, dracoMeshes[0], dracoMaterialLists[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OBJBaker::createFBXNodeTree(FBXNode& rootNode, const hfm::Model::Pointer& hfmModel, const hifi::ByteArray& dracoMesh) {
|
void OBJBaker::createFBXNodeTree(FBXNode& rootNode, const hfm::Model::Pointer& hfmModel, const hifi::ByteArray& dracoMesh, const std::vector<hifi::ByteArray>& dracoMaterialList) {
|
||||||
// Make all generated nodes children of rootNode
|
// Make all generated nodes children of rootNode
|
||||||
rootNode.children = { FBXNode(), FBXNode(), FBXNode() };
|
rootNode.children = { FBXNode(), FBXNode(), FBXNode() };
|
||||||
FBXNode& globalSettingsNode = rootNode.children[0];
|
FBXNode& globalSettingsNode = rootNode.children[0];
|
||||||
|
@ -100,24 +100,22 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, const hfm::Model::Pointer& h
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generating Objects node's child - Material node
|
// Generating Objects node's child - Material node
|
||||||
auto& meshParts = hfmModel->meshes[0].parts;
|
|
||||||
for (auto& meshPart : meshParts) {
|
// Each material ID should only appear once thanks to deduplication in BuildDracoMeshTask, but we want to make sure they are created in the right order
|
||||||
|
std::unordered_map<QString, uint32_t> materialIDToIndex;
|
||||||
|
for (uint32_t materialIndex = 0; materialIndex < hfmModel->materials.size(); ++materialIndex) {
|
||||||
|
const auto& material = hfmModel->materials[materialIndex];
|
||||||
|
materialIDToIndex[material.materialID] = materialIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create nodes for each material in the material list
|
||||||
|
for (const auto& dracoMaterial : dracoMaterialList) {
|
||||||
|
const QString materialID = QString(dracoMaterial);
|
||||||
|
const uint32_t materialIndex = materialIDToIndex[materialID];
|
||||||
|
const auto& material = hfmModel->materials[materialIndex];
|
||||||
FBXNode materialNode;
|
FBXNode materialNode;
|
||||||
materialNode.name = MATERIAL_NODE_NAME;
|
materialNode.name = MATERIAL_NODE_NAME;
|
||||||
if (hfmModel->materials.size() == 1) {
|
setMaterialNodeProperties(materialNode, material.materialID, material, hfmModel);
|
||||||
// case when no material information is provided, OBJSerializer considers it as a single default material
|
|
||||||
for (auto& material : hfmModel->materials) {
|
|
||||||
setMaterialNodeProperties(materialNode, material.name, material, hfmModel);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (auto& material : hfmModel->materials) {
|
|
||||||
if (material.name == meshPart.materialID) {
|
|
||||||
setMaterialNodeProperties(materialNode, meshPart.materialID, material, hfmModel);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
objectNode.children.append(materialNode);
|
objectNode.children.append(materialNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ protected:
|
||||||
virtual void bakeProcessedSource(const hfm::Model::Pointer& hfmModel, const std::vector<hifi::ByteArray>& dracoMeshes, const std::vector<std::vector<hifi::ByteArray>>& dracoMaterialLists) override;
|
virtual void bakeProcessedSource(const hfm::Model::Pointer& hfmModel, const std::vector<hifi::ByteArray>& dracoMeshes, const std::vector<std::vector<hifi::ByteArray>>& dracoMaterialLists) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createFBXNodeTree(FBXNode& rootNode, const hfm::Model::Pointer& hfmModel, const hifi::ByteArray& dracoMesh);
|
void createFBXNodeTree(FBXNode& rootNode, const hfm::Model::Pointer& hfmModel, const hifi::ByteArray& dracoMesh, const std::vector<hifi::ByteArray>& dracoMaterialList);
|
||||||
void setMaterialNodeProperties(FBXNode& materialNode, const QString& materialName, const hfm::Material& material, const hfm::Model::Pointer& hfmModel);
|
void setMaterialNodeProperties(FBXNode& materialNode, const QString& materialName, const hfm::Material& material, const hfm::Model::Pointer& hfmModel);
|
||||||
NodeID nextNodeID() { return _nodeID++; }
|
NodeID nextNodeID() { return _nodeID++; }
|
||||||
|
|
||||||
|
|
|
@ -1485,12 +1485,6 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const
|
||||||
shape.mesh = meshIndex;
|
shape.mesh = meshIndex;
|
||||||
shape.meshPart = i;
|
shape.meshPart = i;
|
||||||
shape.joint = transformIndex;
|
shape.joint = transformIndex;
|
||||||
|
|
||||||
auto matName = mesh.parts[i].materialID;
|
|
||||||
auto materialIt = materialNameToID.find(matName.toStdString());
|
|
||||||
if (materialIt != materialNameToID.end()) {
|
|
||||||
shape.material = materialIt->second;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For FBX_DRACO_MESH_VERSION < 2, or unbaked models, get materials from the partMaterialTextures
|
// For FBX_DRACO_MESH_VERSION < 2, or unbaked models, get materials from the partMaterialTextures
|
||||||
|
|
|
@ -174,11 +174,6 @@ glm::vec2 OBJTokenizer::getVec2() {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setMeshPartDefaults(HFMMeshPart& meshPart, QString materialID) {
|
|
||||||
meshPart.materialID = materialID;
|
|
||||||
}
|
|
||||||
|
|
||||||
// OBJFace
|
// OBJFace
|
||||||
// NOTE (trent, 7/20/17): The vertexColors vector being passed-in isn't necessary here, but I'm just
|
// NOTE (trent, 7/20/17): The vertexColors vector being passed-in isn't necessary here, but I'm just
|
||||||
// pairing it with the vertices vector for consistency.
|
// pairing it with the vertices vector for consistency.
|
||||||
|
@ -493,7 +488,6 @@ bool OBJSerializer::parseOBJGroup(OBJTokenizer& tokenizer, const hifi::VariantHa
|
||||||
FaceGroup faces;
|
FaceGroup faces;
|
||||||
HFMMesh& mesh = hfmModel.meshes[0];
|
HFMMesh& mesh = hfmModel.meshes[0];
|
||||||
mesh.parts.push_back(HFMMeshPart());
|
mesh.parts.push_back(HFMMeshPart());
|
||||||
HFMMeshPart& meshPart = mesh.parts.back();
|
|
||||||
bool sawG = false;
|
bool sawG = false;
|
||||||
bool result = true;
|
bool result = true;
|
||||||
int originalFaceCountForDebugging = 0;
|
int originalFaceCountForDebugging = 0;
|
||||||
|
@ -501,8 +495,6 @@ bool OBJSerializer::parseOBJGroup(OBJTokenizer& tokenizer, const hifi::VariantHa
|
||||||
bool anyVertexColor { false };
|
bool anyVertexColor { false };
|
||||||
int vertexCount { 0 };
|
int vertexCount { 0 };
|
||||||
|
|
||||||
setMeshPartDefaults(meshPart, QString("dontknow") + QString::number(mesh.parts.size()));
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
int tokenType = tokenizer.nextToken();
|
int tokenType = tokenizer.nextToken();
|
||||||
if (tokenType == OBJTokenizer::COMMENT_TOKEN) {
|
if (tokenType == OBJTokenizer::COMMENT_TOKEN) {
|
||||||
|
|
|
@ -160,8 +160,6 @@ public:
|
||||||
QVector<int> quadIndices; // original indices from the FBX mesh
|
QVector<int> quadIndices; // original indices from the FBX mesh
|
||||||
QVector<int> quadTrianglesIndices; // original indices from the FBX mesh of the quad converted as triangles
|
QVector<int> quadTrianglesIndices; // original indices from the FBX mesh of the quad converted as triangles
|
||||||
QVector<int> triangleIndices; // original indices from the FBX mesh
|
QVector<int> triangleIndices; // original indices from the FBX mesh
|
||||||
|
|
||||||
QString materialID; // DEPRECATED
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Material {
|
class Material {
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace baker {
|
||||||
class GetModelPartsTask {
|
class GetModelPartsTask {
|
||||||
public:
|
public:
|
||||||
using Input = hfm::Model::Pointer;
|
using Input = hfm::Model::Pointer;
|
||||||
using Output = VaryingSet8<std::vector<hfm::Mesh>, hifi::URL, baker::MeshIndicesToModelNames, baker::BlendshapesPerMesh, std::vector<hfm::Joint>, std::vector<hfm::Shape>, std::vector<hfm::SkinDeformer>, Extents>;
|
using Output = VaryingSet9<std::vector<hfm::Mesh>, hifi::URL, baker::MeshIndicesToModelNames, baker::BlendshapesPerMesh, std::vector<hfm::Joint>, std::vector<hfm::Shape>, std::vector<hfm::SkinDeformer>, Extents, std::vector<hfm::Material>>;
|
||||||
using JobModel = Job::ModelIO<GetModelPartsTask, Input, Output>;
|
using JobModel = Job::ModelIO<GetModelPartsTask, Input, Output>;
|
||||||
|
|
||||||
void run(const BakeContextPointer& context, const Input& input, Output& output) {
|
void run(const BakeContextPointer& context, const Input& input, Output& output) {
|
||||||
|
@ -47,6 +47,7 @@ namespace baker {
|
||||||
output.edit5() = hfmModelIn->shapes;
|
output.edit5() = hfmModelIn->shapes;
|
||||||
output.edit6() = hfmModelIn->skinDeformers;
|
output.edit6() = hfmModelIn->skinDeformers;
|
||||||
output.edit7() = hfmModelIn->meshExtents;
|
output.edit7() = hfmModelIn->meshExtents;
|
||||||
|
output.edit8() = hfmModelIn->materials;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -170,6 +171,7 @@ namespace baker {
|
||||||
const auto shapesIn = modelPartsIn.getN<GetModelPartsTask::Output>(5);
|
const auto shapesIn = modelPartsIn.getN<GetModelPartsTask::Output>(5);
|
||||||
const auto skinDeformersIn = modelPartsIn.getN<GetModelPartsTask::Output>(6);
|
const auto skinDeformersIn = modelPartsIn.getN<GetModelPartsTask::Output>(6);
|
||||||
const auto modelExtentsIn = modelPartsIn.getN<GetModelPartsTask::Output>(7);
|
const auto modelExtentsIn = modelPartsIn.getN<GetModelPartsTask::Output>(7);
|
||||||
|
const auto materialsIn = modelPartsIn.getN<GetModelPartsTask::Output>(8);
|
||||||
|
|
||||||
// Calculate normals and tangents for meshes and blendshapes if they do not exist
|
// Calculate normals and tangents for meshes and blendshapes if they do not exist
|
||||||
// Note: Normals are never calculated here for OBJ models. OBJ files optionally define normals on a per-face basis, so for consistency normals are calculated beforehand in OBJSerializer.
|
// Note: Normals are never calculated here for OBJ models. OBJ files optionally define normals on a per-face basis, so for consistency normals are calculated beforehand in OBJSerializer.
|
||||||
|
@ -214,7 +216,7 @@ namespace baker {
|
||||||
// TODO: Tangent support (Needs changes to FBXSerializer_Mesh as well)
|
// TODO: Tangent support (Needs changes to FBXSerializer_Mesh as well)
|
||||||
// NOTE: Due to an unresolved linker error, BuildDracoMeshTask is not functional on Android
|
// NOTE: Due to an unresolved linker error, BuildDracoMeshTask is not functional on Android
|
||||||
// TODO: Figure out why BuildDracoMeshTask.cpp won't link with draco on Android
|
// TODO: Figure out why BuildDracoMeshTask.cpp won't link with draco on Android
|
||||||
const auto buildDracoMeshInputs = BuildDracoMeshTask::Input(meshesIn, normalsPerMesh, tangentsPerMesh).asVarying();
|
const auto buildDracoMeshInputs = BuildDracoMeshTask::Input(shapesOut, meshesIn, materialsIn, normalsPerMesh, tangentsPerMesh).asVarying();
|
||||||
const auto buildDracoMeshOutputs = model.addJob<BuildDracoMeshTask>("BuildDracoMesh", buildDracoMeshInputs);
|
const auto buildDracoMeshOutputs = model.addJob<BuildDracoMeshTask>("BuildDracoMesh", buildDracoMeshInputs);
|
||||||
const auto dracoMeshes = buildDracoMeshOutputs.getN<BuildDracoMeshTask::Output>(0);
|
const auto dracoMeshes = buildDracoMeshOutputs.getN<BuildDracoMeshTask::Output>(0);
|
||||||
const auto dracoErrors = buildDracoMeshOutputs.getN<BuildDracoMeshTask::Output>(1);
|
const auto dracoErrors = buildDracoMeshOutputs.getN<BuildDracoMeshTask::Output>(1);
|
||||||
|
|
|
@ -39,19 +39,47 @@
|
||||||
#include "ModelMath.h"
|
#include "ModelMath.h"
|
||||||
|
|
||||||
#ifndef Q_OS_ANDROID
|
#ifndef Q_OS_ANDROID
|
||||||
std::vector<hifi::ByteArray> createMaterialList(const hfm::Mesh& mesh) {
|
|
||||||
std::vector<hifi::ByteArray> materialList;
|
void reindexMaterials(const std::vector<uint32_t>& originalMaterialIndices, std::vector<uint32_t>& materials, std::vector<uint16_t>& materialIndices) {
|
||||||
for (const auto& meshPart : mesh.parts) {
|
materialIndices.resize(originalMaterialIndices.size());
|
||||||
auto materialID = QVariant(meshPart.materialID).toByteArray();
|
for (size_t i = 0; i < originalMaterialIndices.size(); ++i) {
|
||||||
const auto materialIt = std::find(materialList.cbegin(), materialList.cend(), materialID);
|
uint32_t material = originalMaterialIndices[i];
|
||||||
if (materialIt == materialList.cend()) {
|
auto foundMaterial = std::find(materials.cbegin(), materials.cend(), material);
|
||||||
materialList.push_back(materialID);
|
if (foundMaterial == materials.cend()) {
|
||||||
|
materials.push_back(material);
|
||||||
|
materialIndices[i] = (uint16_t)(materials.size() - 1);
|
||||||
|
} else {
|
||||||
|
materialIndices[i] = (uint16_t)(foundMaterial - materials.cbegin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return materialList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<std::unique_ptr<draco::Mesh>, bool> createDracoMesh(const hfm::Mesh& mesh, const std::vector<glm::vec3>& normals, const std::vector<glm::vec3>& tangents, const std::vector<hifi::ByteArray>& materialList) {
|
void createMaterialLists(const std::vector<hfm::Shape>& shapes, const std::vector<hfm::Mesh>& meshes, const std::vector<hfm::Material>& hfmMaterials, std::vector<std::vector<hifi::ByteArray>>& materialIndexLists, std::vector<std::vector<uint16_t>>& partMaterialIndicesPerMesh) {
|
||||||
|
std::vector<std::vector<uint32_t>> materialsPerMesh;
|
||||||
|
for (const auto& mesh : meshes) {
|
||||||
|
materialsPerMesh.emplace_back(mesh.parts.size(), hfm::UNDEFINED_KEY);
|
||||||
|
}
|
||||||
|
for (const auto& shape : shapes) {
|
||||||
|
materialsPerMesh[shape.mesh][shape.meshPart] = shape.material;
|
||||||
|
}
|
||||||
|
|
||||||
|
materialIndexLists.resize(materialsPerMesh.size());
|
||||||
|
partMaterialIndicesPerMesh.resize(materialsPerMesh.size());
|
||||||
|
for (size_t i = 0; i < materialsPerMesh.size(); ++i) {
|
||||||
|
const std::vector<uint32_t>& materials = materialsPerMesh[i];
|
||||||
|
std::vector<uint32_t> uniqueMaterials;
|
||||||
|
|
||||||
|
reindexMaterials(materials, uniqueMaterials, partMaterialIndicesPerMesh[i]);
|
||||||
|
|
||||||
|
materialIndexLists[i].reserve(uniqueMaterials.size());
|
||||||
|
for (const uint32_t material : uniqueMaterials) {
|
||||||
|
const auto& hfmMaterial = hfmMaterials[material];
|
||||||
|
materialIndexLists[i].push_back(QVariant(hfmMaterial.materialID).toByteArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<std::unique_ptr<draco::Mesh>, bool> createDracoMesh(const hfm::Mesh& mesh, const std::vector<glm::vec3>& normals, const std::vector<glm::vec3>& tangents, const std::vector<uint16_t>& partMaterialIndices) {
|
||||||
Q_ASSERT(normals.size() == 0 || (int)normals.size() == mesh.vertices.size());
|
Q_ASSERT(normals.size() == 0 || (int)normals.size() == mesh.vertices.size());
|
||||||
Q_ASSERT(mesh.colors.size() == 0 || mesh.colors.size() == mesh.vertices.size());
|
Q_ASSERT(mesh.colors.size() == 0 || mesh.colors.size() == mesh.vertices.size());
|
||||||
Q_ASSERT(mesh.texCoords.size() == 0 || mesh.texCoords.size() == mesh.vertices.size());
|
Q_ASSERT(mesh.texCoords.size() == 0 || mesh.texCoords.size() == mesh.vertices.size());
|
||||||
|
@ -122,11 +150,9 @@ std::tuple<std::unique_ptr<draco::Mesh>, bool> createDracoMesh(const hfm::Mesh&
|
||||||
|
|
||||||
auto partIndex = 0;
|
auto partIndex = 0;
|
||||||
draco::FaceIndex face;
|
draco::FaceIndex face;
|
||||||
uint16_t materialID;
|
|
||||||
|
|
||||||
for (auto& part : mesh.parts) {
|
for (auto& part : mesh.parts) {
|
||||||
auto materialIt = std::find(materialList.cbegin(), materialList.cend(), QVariant(part.materialID).toByteArray());
|
uint16_t materialID = partMaterialIndices[partIndex];
|
||||||
materialID = (uint16_t)(materialIt - materialList.cbegin());
|
|
||||||
|
|
||||||
auto addFace = [&](const QVector<int>& indices, int index, draco::FaceIndex face) {
|
auto addFace = [&](const QVector<int>& indices, int index, draco::FaceIndex face) {
|
||||||
int32_t idx0 = indices[index];
|
int32_t idx0 = indices[index];
|
||||||
|
@ -214,30 +240,33 @@ void BuildDracoMeshTask::run(const baker::BakeContextPointer& context, const Inp
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
qCWarning(model_baker) << "BuildDracoMesh is disabled on Android. Output meshes will be empty.";
|
qCWarning(model_baker) << "BuildDracoMesh is disabled on Android. Output meshes will be empty.";
|
||||||
#else
|
#else
|
||||||
const auto& meshes = input.get0();
|
const auto& shapes = input.get0();
|
||||||
const auto& normalsPerMesh = input.get1();
|
const auto& meshes = input.get1();
|
||||||
const auto& tangentsPerMesh = input.get2();
|
const auto& materials = input.get2();
|
||||||
|
const auto& normalsPerMesh = input.get3();
|
||||||
|
const auto& tangentsPerMesh = input.get4();
|
||||||
auto& dracoBytesPerMesh = output.edit0();
|
auto& dracoBytesPerMesh = output.edit0();
|
||||||
auto& dracoErrorsPerMesh = output.edit1();
|
auto& dracoErrorsPerMesh = output.edit1();
|
||||||
|
|
||||||
auto& materialLists = output.edit2();
|
auto& materialLists = output.edit2();
|
||||||
|
std::vector<std::vector<uint16_t>> partMaterialIndicesPerMesh;
|
||||||
|
createMaterialLists(shapes, meshes, materials, materialLists, partMaterialIndicesPerMesh);
|
||||||
|
|
||||||
dracoBytesPerMesh.reserve(meshes.size());
|
dracoBytesPerMesh.reserve(meshes.size());
|
||||||
// vector<bool> is an exception to the std::vector conventions as it is a bit field
|
// vector<bool> is an exception to the std::vector conventions as it is a bit field
|
||||||
// So a bool reference to an element doesn't work
|
// So a bool reference to an element doesn't work
|
||||||
dracoErrorsPerMesh.resize(meshes.size());
|
dracoErrorsPerMesh.resize(meshes.size());
|
||||||
materialLists.reserve(meshes.size());
|
|
||||||
for (size_t i = 0; i < meshes.size(); i++) {
|
for (size_t i = 0; i < meshes.size(); i++) {
|
||||||
const auto& mesh = meshes[i];
|
const auto& mesh = meshes[i];
|
||||||
const auto& normals = baker::safeGet(normalsPerMesh, i);
|
const auto& normals = baker::safeGet(normalsPerMesh, i);
|
||||||
const auto& tangents = baker::safeGet(tangentsPerMesh, i);
|
const auto& tangents = baker::safeGet(tangentsPerMesh, i);
|
||||||
dracoBytesPerMesh.emplace_back();
|
dracoBytesPerMesh.emplace_back();
|
||||||
auto& dracoBytes = dracoBytesPerMesh.back();
|
auto& dracoBytes = dracoBytesPerMesh.back();
|
||||||
materialLists.push_back(createMaterialList(mesh));
|
const auto& partMaterialIndices = partMaterialIndicesPerMesh[i];
|
||||||
const auto& materialList = materialLists.back();
|
|
||||||
|
|
||||||
bool dracoError;
|
bool dracoError;
|
||||||
std::unique_ptr<draco::Mesh> dracoMesh;
|
std::unique_ptr<draco::Mesh> dracoMesh;
|
||||||
std::tie(dracoMesh, dracoError) = createDracoMesh(mesh, normals, tangents, materialList);
|
std::tie(dracoMesh, dracoError) = createDracoMesh(mesh, normals, tangents, partMaterialIndices);
|
||||||
dracoErrorsPerMesh[i] = dracoError;
|
dracoErrorsPerMesh[i] = dracoError;
|
||||||
|
|
||||||
if (dracoMesh) {
|
if (dracoMesh) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
class BuildDracoMeshTask {
|
class BuildDracoMeshTask {
|
||||||
public:
|
public:
|
||||||
using Config = BuildDracoMeshConfig;
|
using Config = BuildDracoMeshConfig;
|
||||||
using Input = baker::VaryingSet3<std::vector<hfm::Mesh>, baker::NormalsPerMesh, baker::TangentsPerMesh>;
|
using Input = baker::VaryingSet5<std::vector<hfm::Shape>, std::vector<hfm::Mesh>, std::vector<hfm::Material>, baker::NormalsPerMesh, baker::TangentsPerMesh>;
|
||||||
using Output = baker::VaryingSet3<std::vector<hifi::ByteArray>, std::vector<bool>, std::vector<std::vector<hifi::ByteArray>>>;
|
using Output = baker::VaryingSet3<std::vector<hifi::ByteArray>, std::vector<bool>, std::vector<std::vector<hifi::ByteArray>>>;
|
||||||
using JobModel = baker::Job::ModelIO<BuildDracoMeshTask, Input, Output, Config>;
|
using JobModel = baker::Job::ModelIO<BuildDracoMeshTask, Input, Output, Config>;
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,6 @@ void vhacd::VHACDUtil::fattenMesh(const HFMMesh& mesh, const glm::mat4& modelOff
|
||||||
result.vertices << p3; // add the new point to the result mesh
|
result.vertices << p3; // add the new point to the result mesh
|
||||||
|
|
||||||
HFMMeshPart newMeshPart;
|
HFMMeshPart newMeshPart;
|
||||||
setMeshPartDefaults(newMeshPart, "unknown");
|
|
||||||
newMeshPart.triangleIndices << index0 << index1 << index2;
|
newMeshPart.triangleIndices << index0 << index1 << index2;
|
||||||
newMeshPart.triangleIndices << index0 << index3 << index1;
|
newMeshPart.triangleIndices << index0 << index3 << index1;
|
||||||
newMeshPart.triangleIndices << index1 << index3 << index2;
|
newMeshPart.triangleIndices << index1 << index3 << index2;
|
||||||
|
|
Loading…
Reference in a new issue