Merge pull request #16171 from sabrina-shanman/bug_oven_draco

(BUGZ-1446) Fix oven error when baking FBX mesh with no indices
This commit is contained in:
Maia Hansen 2019-09-12 12:37:49 -07:00 committed by GitHub
commit 53aed1e6bf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 33 additions and 15 deletions

View file

@ -246,6 +246,12 @@ void ModelBaker::bakeSourceCopy() {
// Begin hfm baking
baker.run();
const auto& errors = baker.getDracoErrors();
if (std::find(errors.cbegin(), errors.cend(), true) != errors.cend()) {
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 +443,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");
return false;
handleWarning("Empty mesh detected in model: '" + _modelURL.toString() + "'. It will be included in the baked output.");
}
FBXNode dracoNode;

View file

@ -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 };

View file

@ -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;

View file

@ -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();
}
};

View file

@ -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;

View file

@ -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,9 +218,13 @@ 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());
// 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
dracoErrorsPerMesh.resize(meshes.size());
materialLists.reserve(meshes.size());
for (size_t i = 0; i < meshes.size(); i++) {
const auto& mesh = meshes[i];
@ -231,7 +235,10 @@ void BuildDracoMeshTask::run(const baker::BakeContextPointer& context, const Inp
materialLists.push_back(createMaterialList(mesh));
const auto& materialList = materialLists.back();
auto dracoMesh = createDracoMesh(mesh, normals, tangents, materialList);
bool dracoError;
std::unique_ptr<draco::Mesh> dracoMesh;
std::tie(dracoMesh, dracoError) = createDracoMesh(mesh, normals, tangents, materialList);
dracoErrorsPerMesh[i] = dracoError;
if (dracoMesh) {
draco::Encoder encoder;

View file

@ -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);