Update baker library with many style improvements

This commit is contained in:
Ryan Huffman 2017-12-08 10:29:26 -08:00
parent 57b943ae98
commit 70c35f84b5
15 changed files with 84 additions and 113 deletions

View file

@ -223,11 +223,13 @@ void FBXBaker::rewriteAndBakeSceneModels() {
auto extractedMesh = FBXReader::extractMesh(objectChild, meshIndex, false); auto extractedMesh = FBXReader::extractMesh(objectChild, meshIndex, false);
// Callback to get MaterialID // Callback to get MaterialID
getMaterialIDCallback materialIDcallback = [=](int partIndex) {return extractedMesh.partMaterialTextures[partIndex].first;}; GetMaterialIDCallback materialIDcallback = [&extractedMesh](int partIndex) {
return extractedMesh.partMaterialTextures[partIndex].first;
};
// Compress mesh information and store in dracoMeshNode // Compress mesh information and store in dracoMeshNode
FBXNode dracoMeshNode; FBXNode dracoMeshNode;
bool success = this->compressMesh(extractedMesh.mesh, hasDeformers, dracoMeshNode, materialIDcallback); bool success = compressMesh(extractedMesh.mesh, hasDeformers, dracoMeshNode, materialIDcallback);
// if bake fails - return, if there were errors and continue, if there were warnings. // if bake fails - return, if there were errors and continue, if there were warnings.
if (!success) { if (!success) {
@ -314,23 +316,20 @@ void FBXBaker::rewriteAndBakeSceneTextures() {
for (FBXNode& textureChild : object->children) { for (FBXNode& textureChild : object->children) {
if (textureChild.name == "RelativeFilename") { if (textureChild.name == "RelativeFilename") {
QString fbxTextureFileName { textureChild.properties.at(0).toByteArray() }; QString fbxTextureFileName { textureChild.properties.at(0).toString() };
// Callback to get texture type // Callback to get texture type
getTextureTypeCallback textureTypeCallback = [=]() { // grab the ID for this texture so we can figure out the
// grab the ID for this texture so we can figure out the // texture type from the loaded materials
// texture type from the loaded materials auto textureID { object->properties[0].toString() };
auto textureID{ object->properties[0].toByteArray() }; auto textureType = textureTypes[textureID];
auto textureType = textureTypes[textureID];
return textureType;
};
// Compress the texture information and return the new filename to be added into the FBX scene // Compress the texture information and return the new filename to be added into the FBX scene
QByteArray* bakedTextureFile = this->compressTexture(fbxTextureFileName, textureTypeCallback); auto bakedTextureFile = compressTexture(fbxTextureFileName, textureType);
// If no errors or warnings have occurred during texture compression add the filename to the FBX scene // If no errors or warnings have occurred during texture compression add the filename to the FBX scene
if (bakedTextureFile) { if (!bakedTextureFile.isNull()) {
textureChild.properties[0] = *bakedTextureFile; textureChild.properties[0] = bakedTextureFile;
} else { } else {
// if bake fails - return, if there were errors and continue, if there were warnings. // if bake fails - return, if there were errors and continue, if there were warnings.
if (hasErrors()) { if (hasErrors()) {

View file

@ -35,9 +35,6 @@ class FBXBaker : public ModelBaker {
public: public:
using ModelBaker::ModelBaker; using ModelBaker::ModelBaker;
QUrl getFBXUrl() const { return _modelURL; }
QString getBakedFBXFilePath() const { return _bakedModelFilePath; }
public slots: public slots:
virtual void bake() override; virtual void bake() override;

View file

@ -71,7 +71,7 @@ void ModelBaker::abort() {
} }
} }
bool ModelBaker::compressMesh(FBXMesh& mesh, bool hasDeformers,FBXNode& dracoMeshNode, getMaterialIDCallback materialIDCallback) { bool ModelBaker::compressMesh(FBXMesh& mesh, bool hasDeformers, FBXNode& dracoMeshNode, GetMaterialIDCallback materialIDCallback) {
if (mesh.wasCompressed) { if (mesh.wasCompressed) {
handleError("Cannot re-bake a file that contains compressed mesh"); handleError("Cannot re-bake a file that contains compressed mesh");
return false; return false;
@ -106,12 +106,12 @@ bool ModelBaker::compressMesh(FBXMesh& mesh, bool hasDeformers,FBXNode& dracoMes
bool hasPerFaceMaterials = (materialIDCallback) ? (mesh.parts.size() > 1 || materialIDCallback(0) != 0 ) : true; bool hasPerFaceMaterials = (materialIDCallback) ? (mesh.parts.size() > 1 || materialIDCallback(0) != 0 ) : true;
bool needsOriginalIndices{ hasDeformers }; bool needsOriginalIndices{ hasDeformers };
int normalsAttributeID{ -1 }; int normalsAttributeID { -1 };
int colorsAttributeID{ -1 }; int colorsAttributeID { -1 };
int texCoordsAttributeID{ -1 }; int texCoordsAttributeID { -1 };
int texCoords1AttributeID{ -1 }; int texCoords1AttributeID { -1 };
int faceMaterialAttributeID{ -1 }; int faceMaterialAttributeID { -1 };
int originalIndexAttributeID{ -1 }; int originalIndexAttributeID { -1 };
const int positionAttributeID = meshBuilder.AddAttribute(draco::GeometryAttribute::POSITION, const int positionAttributeID = meshBuilder.AddAttribute(draco::GeometryAttribute::POSITION,
3, draco::DT_FLOAT32); 3, draco::DT_FLOAT32);
@ -244,14 +244,7 @@ bool ModelBaker::compressMesh(FBXMesh& mesh, bool hasDeformers,FBXNode& dracoMes
return true; return true;
} }
QByteArray* ModelBaker::compressTexture(QString modelTextureFileName, getTextureTypeCallback textureTypeCallback) { QString ModelBaker::compressTexture(QString modelTextureFileName, image::TextureUsage::Type textureType) {
static QByteArray textureChild;
QByteArray textureContent = "";
image::TextureUsage::Type textureType = image::TextureUsage::Type::DEFAULT_TEXTURE;
if (textureTypeCallback) {
textureType = textureTypeCallback();
}
QFileInfo modelTextureFileInfo{ modelTextureFileName.replace("\\", "/") }; QFileInfo modelTextureFileInfo{ modelTextureFileName.replace("\\", "/") };
@ -259,18 +252,20 @@ QByteArray* ModelBaker::compressTexture(QString modelTextureFileName, getTexture
// re-baking a model that already references baked textures // re-baking a model that already references baked textures
// this is an error - return from here // this is an error - return from here
handleError("Cannot re-bake a file that already references compressed textures"); handleError("Cannot re-bake a file that already references compressed textures");
return nullptr; return QString::null;
} }
if (!TextureBaker::getSupportedFormats().contains(modelTextureFileInfo.suffix())) { if (!TextureBaker::getSupportedFormats().contains(modelTextureFileInfo.suffix())) {
// this is a texture format we don't bake, skip it // this is a texture format we don't bake, skip it
handleWarning(modelTextureFileName + " is not a bakeable texture format"); handleWarning(modelTextureFileName + " is not a bakeable texture format");
return nullptr; return QString::null;
} }
// make sure this texture points to something and isn't one we've already re-mapped // make sure this texture points to something and isn't one we've already re-mapped
QString textureChild { QString::null };
if (!modelTextureFileInfo.filePath().isEmpty()) { if (!modelTextureFileInfo.filePath().isEmpty()) {
// check if this was an embedded texture that we already have in-memory content for // check if this was an embedded texture that we already have in-memory content for
QByteArray textureContent;
// figure out the URL to this texture, embedded or external // figure out the URL to this texture, embedded or external
if (!modelTextureFileInfo.filePath().isEmpty()) { if (!modelTextureFileInfo.filePath().isEmpty()) {
@ -296,7 +291,7 @@ QByteArray* ModelBaker::compressTexture(QString modelTextureFileName, getTexture
_bakedOutputDir + "/" + bakedTextureFileName _bakedOutputDir + "/" + bakedTextureFileName
}; };
textureChild = bakedTextureFileName.toLocal8Bit(); textureChild = bakedTextureFileName;
if (!_bakingTextures.contains(urlToTexture)) { if (!_bakingTextures.contains(urlToTexture)) {
_outputFiles.push_back(bakedTextureFilePath); _outputFiles.push_back(bakedTextureFilePath);
@ -306,11 +301,11 @@ QByteArray* ModelBaker::compressTexture(QString modelTextureFileName, getTexture
} }
} }
return &textureChild; return textureChild;
} }
void ModelBaker::bakeTexture(const QUrl& textureURL, image::TextureUsage::Type textureType, void ModelBaker::bakeTexture(const QUrl& textureURL, image::TextureUsage::Type textureType,
const QDir& outputDir, const QString& bakedFilename, const QByteArray& textureContent) { const QDir& outputDir, const QString& bakedFilename, const QByteArray& textureContent) {
// start a bake for this texture and add it to our list to keep track of // start a bake for this texture and add it to our list to keep track of
QSharedPointer<TextureBaker> bakingTexture{ QSharedPointer<TextureBaker> bakingTexture{

View file

@ -27,8 +27,7 @@
#include <FBX.h> #include <FBX.h>
using TextureBakerThreadGetter = std::function<QThread*()>; using TextureBakerThreadGetter = std::function<QThread*()>;
using getMaterialIDCallback = std::function <int(int)>; using GetMaterialIDCallback = std::function <int(int)>;
using getTextureTypeCallback = std::function<image::TextureUsage::Type()>;
class ModelBaker : public Baker { class ModelBaker : public Baker {
Q_OBJECT Q_OBJECT
@ -37,10 +36,13 @@ public:
ModelBaker(const QUrl& inputModelURL, TextureBakerThreadGetter inputTextureThreadGetter, ModelBaker(const QUrl& inputModelURL, TextureBakerThreadGetter inputTextureThreadGetter,
const QString& bakedOutputDirectory, const QString& originalOutputDirectory = ""); const QString& bakedOutputDirectory, const QString& originalOutputDirectory = "");
virtual ~ModelBaker(); virtual ~ModelBaker();
bool compressMesh(FBXMesh& mesh, bool hasDeformers, FBXNode& dracoMeshNode, getMaterialIDCallback materialIDCallback = NULL); bool compressMesh(FBXMesh& mesh, bool hasDeformers, FBXNode& dracoMeshNode, GetMaterialIDCallback materialIDCallback = nullptr);
QByteArray* compressTexture(QString textureFileName, getTextureTypeCallback textureTypeCallback = NULL); QString compressTexture(QString textureFileName, image::TextureUsage::Type = image::TextureUsage::Type::DEFAULT_TEXTURE);
virtual void setWasAborted(bool wasAborted) override; virtual void setWasAborted(bool wasAborted) override;
QUrl getModelURL() const { return _modelURL; }
QString getBakedModelFilePath() const { return _bakedModelFilePath; }
public slots: public slots:
virtual void abort() override; virtual void abort() override;

View file

@ -134,7 +134,7 @@ void OBJBaker::bakeOBJ() {
bool combineParts = true; // set true so that OBJReader reads material info from material library bool combineParts = true; // set true so that OBJReader reads material info from material library
OBJReader reader; OBJReader reader;
FBXGeometry* geometry = reader.readOBJ(objData, QVariantHash(), combineParts, _modelURL); auto geometry = reader.readOBJ(objData, QVariantHash(), combineParts, _modelURL);
// Write OBJ Data as FBX tree nodes // Write OBJ Data as FBX tree nodes
FBXNode rootNode; FBXNode rootNode;
@ -211,7 +211,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
// Compress the mesh information and store in dracoNode // Compress the mesh information and store in dracoNode
bool hasDeformers = false; // No concept of deformers for an OBJ bool hasDeformers = false; // No concept of deformers for an OBJ
FBXNode dracoNode; FBXNode dracoNode;
this->compressMesh(geometry.meshes[0], hasDeformers, dracoNode); compressMesh(geometry.meshes[0], hasDeformers, dracoNode);
geometryNode.children.append(dracoNode); geometryNode.children.append(dracoNode);
// Generating Object node's child - Model node // Generating Object node's child - Model node
@ -219,11 +219,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
modelNode.name = MODEL_NODE_NAME; modelNode.name = MODEL_NODE_NAME;
{ {
_modelID = _nodeID++; _modelID = _nodeID++;
modelNode.properties = { modelNode.properties = { _nodeID, MODEL_NODE_NAME, MESH };
_nodeID,
MODEL_NODE_NAME,
MESH
};
} }
_objectNode.children = { geometryNode, modelNode }; _objectNode.children = { geometryNode, modelNode };
@ -253,7 +249,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
FBXMaterial currentMaterial = geometry.materials[material]; FBXMaterial currentMaterial = geometry.materials[material];
if (!currentMaterial.albedoTexture.filename.isEmpty() || !currentMaterial.specularTexture.filename.isEmpty()) { if (!currentMaterial.albedoTexture.filename.isEmpty() || !currentMaterial.specularTexture.filename.isEmpty()) {
_textureID = _nodeID; _textureID = _nodeID;
_mapTextureMaterial.push_back(QPair<qlonglong, int>(_textureID, i)); _mapTextureMaterial.emplace_back(_textureID, i);
FBXNode textureNode; FBXNode textureNode;
{ {
@ -277,18 +273,15 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
QByteArray textureFileName = (!currentMaterial.albedoTexture.filename.isEmpty()) ? currentMaterial.albedoTexture.filename : currentMaterial.specularTexture.filename; QByteArray textureFileName = (!currentMaterial.albedoTexture.filename.isEmpty()) ? currentMaterial.albedoTexture.filename : currentMaterial.specularTexture.filename;
// Callback to get Texture content and type auto textureType = (!currentMaterial.albedoTexture.filename.isEmpty()) ? image::TextureUsage::Type::ALBEDO_TEXTURE : image::TextureUsage::Type::SPECULAR_TEXTURE;
getTextureTypeCallback textureContentTypeCallback = [=]() {
return (!currentMaterial.albedoTexture.filename.isEmpty()) ? image::TextureUsage::Type::ALBEDO_TEXTURE : image::TextureUsage::Type::SPECULAR_TEXTURE;
};
// Compress the texture using ModelBaker::compressTexture() and store compressed file's name in the node // Compress the texture using ModelBaker::compressTexture() and store compressed file's name in the node
QByteArray* textureFile = this->compressTexture(textureFileName, textureContentTypeCallback); auto textureFile = compressTexture(textureFileName, textureType);
if (!textureFile) { if (textureFile.isNull()) {
// Baking failed return // Baking failed return
return; return;
} }
relativeFilenameNode.properties = { *textureFile }; relativeFilenameNode.properties = { textureFile };
textureNode.children = { textureNameNode, relativeFilenameNode }; textureNode.children = { textureNameNode, relativeFilenameNode };
@ -303,27 +296,19 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
// connect Geometry to Model // connect Geometry to Model
FBXNode cNode; FBXNode cNode;
cNode.name = C_NODE_NAME; cNode.name = C_NODE_NAME;
cNode.properties = { cNode.properties = { CONNECTIONS_NODE_PROPERTY, _geometryID, _modelID };
CONNECTIONS_NODE_PROPERTY,
_geometryID,
_modelID
};
connectionsNode.children = { cNode }; connectionsNode.children = { cNode };
// connect all materials to model // connect all materials to model
for (auto& materialID : _materialIDs) { for (auto& materialID : _materialIDs) {
FBXNode cNode; FBXNode cNode;
cNode.name = C_NODE_NAME; cNode.name = C_NODE_NAME;
cNode.properties = { cNode.properties = { CONNECTIONS_NODE_PROPERTY, materialID, _modelID };
CONNECTIONS_NODE_PROPERTY,
materialID,
_modelID
};
connectionsNode.children.append(cNode); connectionsNode.children.append(cNode);
} }
// Connect textures to materials // Connect textures to materials
for (auto& texMat : _mapTextureMaterial) { for (const auto& texMat : _mapTextureMaterial) {
FBXNode cAmbientNode; FBXNode cAmbientNode;
cAmbientNode.name = C_NODE_NAME; cAmbientNode.name = C_NODE_NAME;
cAmbientNode.properties = { cAmbientNode.properties = {
@ -353,11 +338,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
void OBJBaker::setMaterialNodeProperties(FBXNode& materialNode, QString material, FBXGeometry& geometry) { void OBJBaker::setMaterialNodeProperties(FBXNode& materialNode, QString material, FBXGeometry& geometry) {
auto materialID = _nodeID++; auto materialID = _nodeID++;
_materialIDs.push_back(materialID); _materialIDs.push_back(materialID);
materialNode.properties = { materialNode.properties = { materialID, material, MESH };
materialID,
material,
MESH
};
FBXMaterial currentMaterial = geometry.materials[material]; FBXMaterial currentMaterial = geometry.materials[material];

View file

@ -20,6 +20,9 @@
using TextureBakerThreadGetter = std::function<QThread*()>; using TextureBakerThreadGetter = std::function<QThread*()>;
using TextureID = int64_t;
using MaterialID = int64_t;
class OBJBaker : public ModelBaker { class OBJBaker : public ModelBaker {
Q_OBJECT Q_OBJECT
public: public:
@ -43,9 +46,9 @@ private:
qlonglong _nodeID = 0; qlonglong _nodeID = 0;
qlonglong _geometryID; qlonglong _geometryID;
qlonglong _modelID; qlonglong _modelID;
std::vector<qlonglong> _materialIDs; std::vector<MaterialID> _materialIDs;
qlonglong _textureID; qlonglong _textureID;
std::vector<QPair<qlonglong, int>> _mapTextureMaterial; std::vector<std::pair<TextureID, int>> _mapTextureMaterial;
FBXNode _objectNode; FBXNode _objectNode;
}; };
#endif // hifi_OBJBaker_h #endif // hifi_OBJBaker_h

View file

@ -490,13 +490,13 @@ done:
} }
FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, bool combineParts, const QUrl& url) { FBXGeometry::Pointer OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, bool combineParts, const QUrl& url) {
PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xffff0000, nullptr); PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xffff0000, nullptr);
QBuffer buffer { &model }; QBuffer buffer { &model };
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);
FBXGeometry* geometryPtr = new FBXGeometry(); auto geometryPtr { std::make_shared<FBXGeometry>() };
FBXGeometry& geometry = *geometryPtr; FBXGeometry& geometry { *geometryPtr };
OBJTokenizer tokenizer { &buffer }; OBJTokenizer tokenizer { &buffer };
float scaleGuess = 1.0f; float scaleGuess = 1.0f;

View file

@ -75,7 +75,7 @@ public:
QString currentMaterialName; QString currentMaterialName;
QHash<QString, OBJMaterial> materials; QHash<QString, OBJMaterial> materials;
FBXGeometry* readOBJ(QByteArray& model, const QVariantHash& mapping, bool combineParts, const QUrl& url = QUrl()); FBXGeometry::Pointer readOBJ(QByteArray& model, const QVariantHash& mapping, bool combineParts, const QUrl& url = QUrl());
private: private:
QUrl _url; QUrl _url;

View file

@ -186,11 +186,11 @@ void GeometryReader::run() {
throw QString("empty geometry, possibly due to an unsupported FBX version"); throw QString("empty geometry, possibly due to an unsupported FBX version");
} }
} else if (_url.path().toLower().endsWith(".obj")) { } else if (_url.path().toLower().endsWith(".obj")) {
fbxGeometry.reset(OBJReader().readOBJ(_data, _mapping, _combineParts, _url)); fbxGeometry = OBJReader().readOBJ(_data, _mapping, _combineParts, _url);
} else if (_url.path().toLower().endsWith(".obj.gz")) { } else if (_url.path().toLower().endsWith(".obj.gz")) {
QByteArray uncompressedData; QByteArray uncompressedData;
if (gunzip(_data, uncompressedData)){ if (gunzip(_data, uncompressedData)){
fbxGeometry.reset(OBJReader().readOBJ(uncompressedData, _mapping, _combineParts, _url)); fbxGeometry = OBJReader().readOBJ(uncompressedData, _mapping, _combineParts, _url);
} else { } else {
throw QString("failed to decompress .obj.gz" ); throw QString("failed to decompress .obj.gz" );
} }

View file

@ -304,11 +304,11 @@ void DomainBaker::handleFinishedModelBaker() {
if (baker) { if (baker) {
if (!baker->hasErrors()) { if (!baker->hasErrors()) {
// this FBXBaker is done and everything went according to plan // this FBXBaker is done and everything went according to plan
qDebug() << "Re-writing entity references to" << baker->getFBXUrl(); qDebug() << "Re-writing entity references to" << baker->getModelURL();
// enumerate the QJsonRef values for the URL of this FBX from our multi hash of // enumerate the QJsonRef values for the URL of this FBX from our multi hash of
// entity objects needing a URL re-write // entity objects needing a URL re-write
for (QJsonValueRef entityValue : _entitiesNeedingRewrite.values(baker->getFBXUrl())) { for (QJsonValueRef entityValue : _entitiesNeedingRewrite.values(baker->getModelURL())) {
// convert the entity QJsonValueRef to a QJsonObject so we can modify its URL // convert the entity QJsonValueRef to a QJsonObject so we can modify its URL
auto entity = entityValue.toObject(); auto entity = entityValue.toObject();
@ -317,7 +317,7 @@ void DomainBaker::handleFinishedModelBaker() {
QUrl oldModelURL { entity[ENTITY_MODEL_URL_KEY].toString() }; QUrl oldModelURL { entity[ENTITY_MODEL_URL_KEY].toString() };
// setup a new URL using the prefix we were passed // setup a new URL using the prefix we were passed
auto relativeFBXFilePath = baker->getBakedFBXFilePath().remove(_contentOutputPath); auto relativeFBXFilePath = baker->getBakedModelFilePath().remove(_contentOutputPath);
if (relativeFBXFilePath.startsWith("/")) { if (relativeFBXFilePath.startsWith("/")) {
relativeFBXFilePath = relativeFBXFilePath.right(relativeFBXFilePath.length() - 1); relativeFBXFilePath = relativeFBXFilePath.right(relativeFBXFilePath.length() - 1);
} }
@ -370,10 +370,10 @@ void DomainBaker::handleFinishedModelBaker() {
} }
// remove the baked URL from the multi hash of entities needing a re-write // remove the baked URL from the multi hash of entities needing a re-write
_entitiesNeedingRewrite.remove(baker->getFBXUrl()); _entitiesNeedingRewrite.remove(baker->getModelURL());
// drop our shared pointer to this baker so that it gets cleaned up // drop our shared pointer to this baker so that it gets cleaned up
_modelBakers.remove(baker->getFBXUrl()); _modelBakers.remove(baker->getModelURL());
// emit progress to tell listeners how many models we have baked // emit progress to tell listeners how many models we have baked
emit bakeProgress(++_completedSubBakes, _totalNumberOfSubBakes); emit bakeProgress(++_completedSubBakes, _totalNumberOfSubBakes);

View file

@ -42,5 +42,5 @@ void BakeWidget::cancelButtonClicked() {
auto stackedWidget = qobject_cast<QStackedWidget*>(parentWidget()); auto stackedWidget = qobject_cast<QStackedWidget*>(parentWidget());
stackedWidget->removeWidget(this); stackedWidget->removeWidget(this);
this->deleteLater(); deleteLater();
} }

View file

@ -204,31 +204,30 @@ void ModelBakeWidget::bakeButtonClicked() {
bakedOutputDirectory.mkdir("."); bakedOutputDirectory.mkdir(".");
originalOutputDirectory.mkdir("."); originalOutputDirectory.mkdir(".");
std::unique_ptr<Baker> baker;
auto getWorkerThreadCallback = []() -> QThread* {
return qApp->getNextWorkerThread();
};
// everything seems to be in place, kick off a bake for this model now // everything seems to be in place, kick off a bake for this model now
if (modelToBakeURL.fileName().endsWith(".fbx")) { if (modelToBakeURL.fileName().endsWith(".fbx")) {
_baker = std::unique_ptr<FBXBaker>{ baker.reset(new FBXBaker(modelToBakeURL, getWorkerThreadCallback, bakedOutputDirectory.absolutePath(),
new FBXBaker(modelToBakeURL, []() -> QThread* { originalOutputDirectory.absolutePath()));
return qApp->getNextWorkerThread();
}, bakedOutputDirectory.absolutePath(), originalOutputDirectory.absolutePath())
};
_isFBX = true;
} else if (modelToBakeURL.fileName().endsWith(".obj")) { } else if (modelToBakeURL.fileName().endsWith(".obj")) {
_baker = std::unique_ptr<OBJBaker>{ baker.reset(new OBJBaker(modelToBakeURL, getWorkerThreadCallback, bakedOutputDirectory.absolutePath(),
new OBJBaker(modelToBakeURL, []() -> QThread* { originalOutputDirectory.absolutePath()));
return qApp->getNextWorkerThread(); } else {
}, bakedOutputDirectory.absolutePath(), originalOutputDirectory.absolutePath()) qWarning() << "Unknown model type: " << modelToBakeURL.fileName());
}; continue;
_isOBJ = true;
} }
// move the baker to the FBX/OBJ baker thread // move the baker to the FBX/OBJ baker thread
_baker->moveToThread(qApp->getNextWorkerThread()); baker->moveToThread(qApp->getNextWorkerThread());
// invoke the bake method on the baker thread // invoke the bake method on the baker thread
QMetaObject::invokeMethod(_baker.get(), "bake"); QMetaObject::invokeMethod(baker.get(), "bake");
// make sure we hear about the results of this baker when it is done // make sure we hear about the results of this baker when it is done
connect(_baker.get(), &Baker::finished, this, &ModelBakeWidget::handleFinishedBaker); connect(baker.get(), &Baker::finished, this, &ModelBakeWidget::handleFinishedBaker);
// add a pending row to the results window to show that this bake is in process // add a pending row to the results window to show that this bake is in process
auto resultsWindow = qApp->getMainWindow()->showResultsWindow(); auto resultsWindow = qApp->getMainWindow()->showResultsWindow();
@ -236,16 +235,15 @@ void ModelBakeWidget::bakeButtonClicked() {
// keep a unique_ptr to this baker // keep a unique_ptr to this baker
// and remember the row that represents it in the results table // and remember the row that represents it in the results table
_bakers.emplace_back(std::move(_baker), resultsRow); _bakers.emplace_back(std::move(baker), resultsRow);
} }
} }
void ModelBakeWidget::handleFinishedBaker() { void ModelBakeWidget::handleFinishedBaker() {
Baker* baker; Baker* baker = dynamic_cast<Baker*>(sender());
if (_isFBX) { if (!baker) {
baker = qobject_cast<FBXBaker*>(sender()); qWarning() << "Received signal from unexpected sender";
} else if (_isOBJ) { return;
baker = qobject_cast<OBJBaker*>(sender());
} }
// add the results of this bake to the results window // add the results of this bake to the results window

View file

@ -49,9 +49,6 @@ private:
Setting::Handle<QString> _modelStartDirectory; Setting::Handle<QString> _modelStartDirectory;
std::unique_ptr<Baker> _baker; std::unique_ptr<Baker> _baker;
bool _isOBJ = false;
bool _isFBX = false;
}; };
#endif // hifi_ModelBakeWidget_h #endif // hifi_ModelBakeWidget_h

View file

@ -46,7 +46,7 @@ ResultsWindow* OvenMainWindow::showResultsWindow(bool shouldRaise) {
_resultsWindow->show(); _resultsWindow->show();
// place the results window initially below our window // place the results window initially below our window
_resultsWindow->move(_resultsWindow->x(), this->frameGeometry().bottom()); _resultsWindow->move(_resultsWindow->x(), frameGeometry().bottom());
} }
// show the results window and make sure it is in front // show the results window and make sure it is in front

View file

@ -41,18 +41,17 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, FBXGeometry& result) {
} }
try { try {
QByteArray fbxContents = fbx.readAll(); QByteArray fbxContents = fbx.readAll();
FBXGeometry* geom; FBXGeometry::Pointer geom;
if (filename.toLower().endsWith(".obj")) { if (filename.toLower().endsWith(".obj")) {
bool combineParts = false; bool combineParts = false;
geom = OBJReader().readOBJ(fbxContents, QVariantHash(), combineParts); geom = OBJReader().readOBJ(fbxContents, QVariantHash(), combineParts);
} else if (filename.toLower().endsWith(".fbx")) { } else if (filename.toLower().endsWith(".fbx")) {
geom = readFBX(fbxContents, QVariantHash(), filename); geom.reset(readFBX(fbxContents, QVariantHash(), filename));
} else { } else {
qWarning() << "file has unknown extension" << filename; qWarning() << "file has unknown extension" << filename;
return false; return false;
} }
result = *geom; result = *geom;
delete geom;
reSortFBXGeometryMeshes(result); reSortFBXGeometryMeshes(result);
} catch (const QString& error) { } catch (const QString& error) {