mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-07 10:02:24 +02:00
Fix FBXBaker failing when an unbaked mesh is empty
Error early for all model bakers for draco errors
This commit is contained in:
parent
5171b660ae
commit
384b7fd629
7 changed files with 32 additions and 15 deletions
|
@ -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<hifi::ByteArray>& 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;
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -56,7 +56,7 @@ const int MAX_NUM_PIXELS_FOR_FBX_TEXTURE = 2048 * 2048;
|
|||
|
||||
using ShapeVertices = std::vector<glm::vec3>;
|
||||
// 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;
|
||||
|
|
|
@ -120,7 +120,7 @@ namespace baker {
|
|||
class BakerEngineBuilder {
|
||||
public:
|
||||
using Input = VaryingSet3<hfm::Model::Pointer, hifi::VariantHash, hifi::URL>;
|
||||
using Output = VaryingSet4<hfm::Model::Pointer, MaterialMapping, std::vector<hifi::ByteArray>, std::vector<std::vector<hifi::ByteArray>>>;
|
||||
using Output = VaryingSet5<hfm::Model::Pointer, MaterialMapping, std::vector<hifi::ByteArray>, std::vector<bool>, std::vector<std::vector<hifi::ByteArray>>>;
|
||||
using JobModel = Task::ModelIO<BakerEngineBuilder, Input, Output>;
|
||||
void build(JobModel& model, const Varying& input, Varying& output) {
|
||||
const auto& hfmModelIn = input.getN<Input>(0);
|
||||
|
@ -168,7 +168,8 @@ namespace baker {
|
|||
const auto buildDracoMeshInputs = BuildDracoMeshTask::Input(meshesIn, normalsPerMesh, tangentsPerMesh).asVarying();
|
||||
const auto buildDracoMeshOutputs = model.addJob<BuildDracoMeshTask>("BuildDracoMesh", buildDracoMeshInputs);
|
||||
const auto dracoMeshes = buildDracoMeshOutputs.getN<BuildDracoMeshTask::Output>(0);
|
||||
const auto materialList = buildDracoMeshOutputs.getN<BuildDracoMeshTask::Output>(1);
|
||||
const auto dracoErrors = buildDracoMeshOutputs.getN<BuildDracoMeshTask::Output>(1);
|
||||
const auto materialList = buildDracoMeshOutputs.getN<BuildDracoMeshTask::Output>(2);
|
||||
|
||||
// Parse flow data
|
||||
const auto flowData = model.addJob<ParseFlowDataTask>("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<BuildModelTask>("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<BakerEngineBuilder::Output>().get2();
|
||||
}
|
||||
|
||||
std::vector<std::vector<hifi::ByteArray>> Baker::getDracoMaterialLists() const {
|
||||
std::vector<bool> Baker::getDracoErrors() const {
|
||||
return _engine->getOutput().get<BakerEngineBuilder::Output>().get3();
|
||||
}
|
||||
|
||||
std::vector<std::vector<hifi::ByteArray>> Baker::getDracoMaterialLists() const {
|
||||
return _engine->getOutput().get<BakerEngineBuilder::Output>().get4();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace baker {
|
|||
hfm::Model::Pointer getHFMModel() const;
|
||||
MaterialMapping getMaterialMapping() const;
|
||||
const std::vector<hifi::ByteArray>& getDracoMeshes() const;
|
||||
std::vector<bool> 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<std::vector<hifi::ByteArray>> getDracoMaterialLists() const;
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ std::vector<hifi::ByteArray> createMaterialList(const hfm::Mesh& mesh) {
|
|||
return materialList;
|
||||
}
|
||||
|
||||
std::unique_ptr<draco::Mesh> createDracoMesh(const hfm::Mesh& mesh, const std::vector<glm::vec3>& normals, const std::vector<glm::vec3>& tangents, const std::vector<hifi::ByteArray>& 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) {
|
||||
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<draco::Mesh> createDracoMesh(const hfm::Mesh& mesh, const std::v
|
|||
}
|
||||
|
||||
if (numTriangles == 0) {
|
||||
return std::unique_ptr<draco::Mesh>();
|
||||
return std::make_tuple(std::unique_ptr<draco::Mesh>(), false);
|
||||
}
|
||||
|
||||
draco::TriangleSoupMeshBuilder meshBuilder;
|
||||
|
@ -184,7 +184,7 @@ std::unique_ptr<draco::Mesh> 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<draco::Mesh>();
|
||||
return std::make_tuple(std::unique_ptr<draco::Mesh>(), true);
|
||||
}
|
||||
|
||||
// we need to modify unique attribute IDs for custom attributes
|
||||
|
@ -201,7 +201,7 @@ std::unique_ptr<draco::Mesh> 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<draco::Mesh> dracoMesh;
|
||||
std::tie(dracoMesh, dracoError) = createDracoMesh(mesh, normals, tangents, materialList);
|
||||
|
||||
if (dracoMesh) {
|
||||
draco::Encoder encoder;
|
||||
|
|
|
@ -34,7 +34,7 @@ class BuildDracoMeshTask {
|
|||
public:
|
||||
using Config = BuildDracoMeshConfig;
|
||||
using Input = baker::VaryingSet3<std::vector<hfm::Mesh>, baker::NormalsPerMesh, baker::TangentsPerMesh>;
|
||||
using Output = baker::VaryingSet2<std::vector<hifi::ByteArray>, 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>;
|
||||
|
||||
void configure(const Config& config);
|
||||
|
|
Loading…
Reference in a new issue