diff --git a/libraries/baking/src/ModelBaker.cpp b/libraries/baking/src/ModelBaker.cpp index 46da29cf00..adf6deeb56 100644 --- a/libraries/baking/src/ModelBaker.cpp +++ b/libraries/baking/src/ModelBaker.cpp @@ -246,6 +246,13 @@ void ModelBaker::bakeSourceCopy() { // Begin hfm baking baker.run(); + for (auto error : baker.getDracoErrors()) { + if (error) { + handleError("Failed to finalize the baking of a draco Geometry node from model " + _modelURL.toString()); + return; + } + } + _hfmModel = baker.getHFMModel(); _materialMapping = baker.getMaterialMapping(); dracoMeshes = baker.getDracoMeshes(); @@ -437,8 +444,7 @@ void ModelBaker::abort() { bool ModelBaker::buildDracoMeshNode(FBXNode& dracoMeshNode, const QByteArray& dracoMeshBytes, const std::vector& dracoMaterialList) { if (dracoMeshBytes.isEmpty()) { - handleError("Failed to finalize the baking of a draco Geometry node from model " + _modelURL.toString()); - return false; + handleWarning("Empty mesh detected in model: '" + _modelURL.toString() + "'. It will be included in the baked output."); } FBXNode dracoNode; diff --git a/libraries/baking/src/OBJBaker.h b/libraries/baking/src/OBJBaker.h index 9d0fe53e3c..55adec5786 100644 --- a/libraries/baking/src/OBJBaker.h +++ b/libraries/baking/src/OBJBaker.h @@ -28,7 +28,7 @@ protected: private: void createFBXNodeTree(FBXNode& rootNode, const hfm::Model::Pointer& hfmModel, const hifi::ByteArray& dracoMesh); - void setMaterialNodeProperties(FBXNode& materialNode, QString material, const hfm::Model::Pointer& hfmModel); + void setMaterialNodeProperties(FBXNode& materialNode, QString material, const hfm::Model::Pointer& hfmModel); NodeID nextNodeID() { return _nodeID++; } NodeID _nodeID { 0 }; diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index 484a10aa3b..888e562bca 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -56,7 +56,7 @@ const int MAX_NUM_PIXELS_FOR_FBX_TEXTURE = 2048 * 2048; using ShapeVertices = std::vector; // The version of the Draco mesh binary data itself. See also: FBX_DRACO_MESH_VERSION in FBX.h -static const int DRACO_MESH_VERSION = 2; +static const int DRACO_MESH_VERSION = 3; static const int DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES = 1000; static const int DRACO_ATTRIBUTE_MATERIAL_ID = DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES; diff --git a/libraries/model-baker/src/model-baker/Baker.cpp b/libraries/model-baker/src/model-baker/Baker.cpp index c896613df5..47a8db82b8 100644 --- a/libraries/model-baker/src/model-baker/Baker.cpp +++ b/libraries/model-baker/src/model-baker/Baker.cpp @@ -120,7 +120,7 @@ namespace baker { class BakerEngineBuilder { public: using Input = VaryingSet3; - using Output = VaryingSet4, std::vector>>; + using Output = VaryingSet5, std::vector, std::vector>>; using JobModel = Task::ModelIO; void build(JobModel& model, const Varying& input, Varying& output) { const auto& hfmModelIn = input.getN(0); @@ -168,7 +168,8 @@ namespace baker { const auto buildDracoMeshInputs = BuildDracoMeshTask::Input(meshesIn, normalsPerMesh, tangentsPerMesh).asVarying(); const auto buildDracoMeshOutputs = model.addJob("BuildDracoMesh", buildDracoMeshInputs); const auto dracoMeshes = buildDracoMeshOutputs.getN(0); - const auto materialList = buildDracoMeshOutputs.getN(1); + const auto dracoErrors = buildDracoMeshOutputs.getN(1); + const auto materialList = buildDracoMeshOutputs.getN(2); // Parse flow data const auto flowData = model.addJob("ParseFlowData", mapping); @@ -181,7 +182,7 @@ namespace baker { const auto buildModelInputs = BuildModelTask::Input(hfmModelIn, meshesOut, jointsOut, jointRotationOffsets, jointIndices, flowData).asVarying(); const auto hfmModelOut = model.addJob("BuildModel", buildModelInputs); - output = Output(hfmModelOut, materialMapping, dracoMeshes, materialList); + output = Output(hfmModelOut, materialMapping, dracoMeshes, dracoErrors, materialList); } }; @@ -212,7 +213,11 @@ namespace baker { return _engine->getOutput().get().get2(); } - std::vector> Baker::getDracoMaterialLists() const { + std::vector Baker::getDracoErrors() const { return _engine->getOutput().get().get3(); } + + std::vector> Baker::getDracoMaterialLists() const { + return _engine->getOutput().get().get4(); + } }; diff --git a/libraries/model-baker/src/model-baker/Baker.h b/libraries/model-baker/src/model-baker/Baker.h index 6f74cb646e..9780484fa4 100644 --- a/libraries/model-baker/src/model-baker/Baker.h +++ b/libraries/model-baker/src/model-baker/Baker.h @@ -33,6 +33,7 @@ namespace baker { hfm::Model::Pointer getHFMModel() const; MaterialMapping getMaterialMapping() const; const std::vector& getDracoMeshes() const; + std::vector getDracoErrors() const; // This is a ByteArray and not a std::string because the character sequence can contain the null character (particularly for FBX materials) std::vector> getDracoMaterialLists() const; diff --git a/libraries/model-baker/src/model-baker/BuildDracoMeshTask.cpp b/libraries/model-baker/src/model-baker/BuildDracoMeshTask.cpp index 25a45cefe5..180664a52a 100644 --- a/libraries/model-baker/src/model-baker/BuildDracoMeshTask.cpp +++ b/libraries/model-baker/src/model-baker/BuildDracoMeshTask.cpp @@ -51,7 +51,7 @@ std::vector createMaterialList(const hfm::Mesh& mesh) { return materialList; } -std::unique_ptr createDracoMesh(const hfm::Mesh& mesh, const std::vector& normals, const std::vector& tangents, const std::vector& materialList) { +std::tuple, bool> createDracoMesh(const hfm::Mesh& mesh, const std::vector& normals, const std::vector& tangents, const std::vector& materialList) { 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.texCoords.size() == 0 || mesh.texCoords.size() == mesh.vertices.size()); @@ -68,7 +68,7 @@ std::unique_ptr createDracoMesh(const hfm::Mesh& mesh, const std::v } if (numTriangles == 0) { - return std::unique_ptr(); + return std::make_tuple(std::unique_ptr(), false); } draco::TriangleSoupMeshBuilder meshBuilder; @@ -184,7 +184,7 @@ std::unique_ptr createDracoMesh(const hfm::Mesh& mesh, const std::v if (!dracoMesh) { qCWarning(model_baker) << "Failed to finalize the baking of a draco Geometry node"; - return std::unique_ptr(); + return std::make_tuple(std::unique_ptr(), true); } // we need to modify unique attribute IDs for custom attributes @@ -201,7 +201,7 @@ std::unique_ptr createDracoMesh(const hfm::Mesh& mesh, const std::v dracoMesh->attribute(originalIndexAttributeID)->set_unique_id(DRACO_ATTRIBUTE_ORIGINAL_INDEX); } - return dracoMesh; + return std::make_tuple(std::move(dracoMesh), false); } #endif // not Q_OS_ANDROID @@ -218,20 +218,25 @@ void BuildDracoMeshTask::run(const baker::BakeContextPointer& context, const Inp const auto& normalsPerMesh = input.get1(); const auto& tangentsPerMesh = input.get2(); auto& dracoBytesPerMesh = output.edit0(); - auto& materialLists = output.edit1(); + auto& dracoErrorsPerMesh = output.edit1(); + auto& materialLists = output.edit2(); dracoBytesPerMesh.reserve(meshes.size()); + dracoErrorsPerMesh.reserve(meshes.size()); materialLists.reserve(meshes.size()); for (size_t i = 0; i < meshes.size(); i++) { const auto& mesh = meshes[i]; const auto& normals = baker::safeGet(normalsPerMesh, i); const auto& tangents = baker::safeGet(tangentsPerMesh, i); dracoBytesPerMesh.emplace_back(); + dracoErrorsPerMesh.emplace_back(); auto& dracoBytes = dracoBytesPerMesh.back(); + auto& dracoError = dracoErrorsPerMesh.back(); materialLists.push_back(createMaterialList(mesh)); const auto& materialList = materialLists.back(); - auto dracoMesh = createDracoMesh(mesh, normals, tangents, materialList); + std::unique_ptr dracoMesh; + std::tie(dracoMesh, dracoError) = createDracoMesh(mesh, normals, tangents, materialList); if (dracoMesh) { draco::Encoder encoder; diff --git a/libraries/model-baker/src/model-baker/BuildDracoMeshTask.h b/libraries/model-baker/src/model-baker/BuildDracoMeshTask.h index 0e33be3c41..ac9ad648ab 100644 --- a/libraries/model-baker/src/model-baker/BuildDracoMeshTask.h +++ b/libraries/model-baker/src/model-baker/BuildDracoMeshTask.h @@ -34,7 +34,7 @@ class BuildDracoMeshTask { public: using Config = BuildDracoMeshConfig; using Input = baker::VaryingSet3, baker::NormalsPerMesh, baker::TangentsPerMesh>; - using Output = baker::VaryingSet2, std::vector>>; + using Output = baker::VaryingSet3, std::vector, std::vector>>; using JobModel = baker::Job::ModelIO; void configure(const Config& config);