From 3d2b71bc7b015779187d743d8780a07a8e1c7de0 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 26 Mar 2019 17:16:13 -0700 Subject: [PATCH] remove all existing material parsing --- libraries/baking/src/FBXBaker.cpp | 111 +----- libraries/baking/src/FBXBaker.h | 8 +- libraries/baking/src/MaterialBaker.cpp | 8 + libraries/baking/src/MaterialBaker.h | 1 + libraries/baking/src/ModelBaker.cpp | 344 +------------------ libraries/baking/src/ModelBaker.h | 31 +- libraries/baking/src/OBJBaker.cpp | 72 ---- libraries/baking/src/OBJBaker.h | 2 - libraries/baking/src/baking/BakerLibrary.cpp | 12 +- libraries/baking/src/baking/BakerLibrary.h | 4 +- libraries/baking/src/baking/FSTBaker.cpp | 7 +- libraries/baking/src/baking/FSTBaker.h | 3 +- tools/oven/src/BakerCLI.cpp | 5 +- tools/oven/src/DomainBaker.cpp | 5 +- tools/oven/src/ui/ModelBakeWidget.cpp | 6 +- 15 files changed, 46 insertions(+), 573 deletions(-) diff --git a/libraries/baking/src/FBXBaker.cpp b/libraries/baking/src/FBXBaker.cpp index 2189e7bdc3..b7eb56c921 100644 --- a/libraries/baking/src/FBXBaker.cpp +++ b/libraries/baking/src/FBXBaker.cpp @@ -33,9 +33,8 @@ #include "ModelBakingLoggingCategory.h" #include "TextureBaker.h" -FBXBaker::FBXBaker(const QUrl& inputModelURL, TextureBakerThreadGetter inputTextureThreadGetter, - const QString& bakedOutputDirectory, const QString& originalOutputDirectory, bool hasBeenBaked) : - ModelBaker(inputModelURL, inputTextureThreadGetter, bakedOutputDirectory, originalOutputDirectory, hasBeenBaked) { +FBXBaker::FBXBaker(const QUrl& inputModelURL, const QString& bakedOutputDirectory, const QString& originalOutputDirectory, bool hasBeenBaked) : + ModelBaker(inputModelURL, bakedOutputDirectory, originalOutputDirectory, hasBeenBaked) { if (hasBeenBaked) { // Look for the original model file one directory higher. Perhaps this is an oven output directory. QUrl originalRelativePath = QUrl("../original/" + inputModelURL.fileName().replace(BAKED_FBX_EXTENSION, FBX_EXTENSION)); @@ -45,15 +44,6 @@ FBXBaker::FBXBaker(const QUrl& inputModelURL, TextureBakerThreadGetter inputText } void FBXBaker::bakeProcessedSource(const hfm::Model::Pointer& hfmModel, const std::vector& dracoMeshes, const std::vector>& dracoMaterialLists) { - _hfmModel = hfmModel; - - if (shouldStop()) { - return; - } - - // enumerate the models and textures found in the scene and start a bake for them - rewriteAndBakeSceneTextures(); - if (shouldStop()) { return; } @@ -114,15 +104,15 @@ void FBXBaker::rewriteAndBakeSceneModels(const QVector& meshes, const int meshIndex = 0; for (FBXNode& rootChild : _rootNode.children) { if (rootChild.name == "Objects") { - for (FBXNode& object : rootChild.children) { - if (object.name == "Geometry") { - if (object.properties.at(2) == "Mesh") { + for (auto object = rootChild.children.begin(); object != rootChild.children.end(); object++) { + if (object->name == "Geometry") { + if (object->properties.at(2) == "Mesh") { int meshNum = meshIndexToRuntimeOrder[meshIndex]; - replaceMeshNodeWithDraco(object, dracoMeshes[meshNum], dracoMaterialLists[meshNum]); + replaceMeshNodeWithDraco(*object, dracoMeshes[meshNum], dracoMaterialLists[meshNum]); meshIndex++; } - } else if (object.name == "Model") { - for (FBXNode& modelChild : object.children) { + } else if (object->name == "Model") { + for (FBXNode& modelChild : object->children) { if (modelChild.name == "Properties60" || modelChild.name == "Properties70") { // This is a properties node // Remove the geometric transform because that has been applied directly to the vertices in FBXSerializer @@ -142,10 +132,13 @@ void FBXBaker::rewriteAndBakeSceneModels(const QVector& meshes, const } else if (modelChild.name == "Vertices") { // This model is also a mesh int meshNum = meshIndexToRuntimeOrder[meshIndex]; - replaceMeshNodeWithDraco(object, dracoMeshes[meshNum], dracoMaterialLists[meshNum]); + replaceMeshNodeWithDraco(*object, dracoMeshes[meshNum], dracoMaterialLists[meshNum]); meshIndex++; } } + } else if (object->name == "Texture" || object->name == "Video") { + // this is an embedded texture, we need to remove it from the FBX + object = rootChild.children.erase(object); } if (hasErrors()) { @@ -154,82 +147,4 @@ void FBXBaker::rewriteAndBakeSceneModels(const QVector& meshes, const } } } -} - -void FBXBaker::rewriteAndBakeSceneTextures() { - using namespace image::TextureUsage; - QHash textureTypes; - - // enumerate the materials in the extracted geometry so we can determine the texture type for each texture ID - for (const auto& material : _hfmModel->materials) { - if (material.normalTexture.isBumpmap) { - textureTypes[material.normalTexture.id] = BUMP_TEXTURE; - } else { - textureTypes[material.normalTexture.id] = NORMAL_TEXTURE; - } - - textureTypes[material.albedoTexture.id] = ALBEDO_TEXTURE; - textureTypes[material.glossTexture.id] = GLOSS_TEXTURE; - textureTypes[material.roughnessTexture.id] = ROUGHNESS_TEXTURE; - textureTypes[material.specularTexture.id] = SPECULAR_TEXTURE; - textureTypes[material.metallicTexture.id] = METALLIC_TEXTURE; - textureTypes[material.emissiveTexture.id] = EMISSIVE_TEXTURE; - textureTypes[material.occlusionTexture.id] = OCCLUSION_TEXTURE; - textureTypes[material.lightmapTexture.id] = LIGHTMAP_TEXTURE; - } - - // enumerate the children of the root node - for (FBXNode& rootChild : _rootNode.children) { - - if (rootChild.name == "Objects") { - - // enumerate the objects - auto object = rootChild.children.begin(); - while (object != rootChild.children.end()) { - if (object->name == "Texture") { - - // double check that we didn't get an abort while baking the last texture - if (shouldStop()) { - return; - } - - // enumerate the texture children - for (FBXNode& textureChild : object->children) { - - if (textureChild.name == "RelativeFilename") { - QString hfmTextureFileName { textureChild.properties.at(0).toString() }; - - // grab the ID for this texture so we can figure out the - // texture type from the loaded materials - auto textureID { object->properties[0].toString() }; - auto textureType = textureTypes[textureID]; - - // Compress the texture information and return the new filename to be added into the FBX scene - auto bakedTextureFile = compressTexture(hfmTextureFileName, textureType); - - // If no errors or warnings have occurred during texture compression add the filename to the FBX scene - if (!bakedTextureFile.isNull()) { - textureChild.properties[0] = bakedTextureFile; - } else { - // if bake fails - return, if there were errors and continue, if there were warnings. - if (hasErrors()) { - return; - } else if (hasWarnings()) { - continue; - } - } - } - } - - ++object; - - } else if (object->name == "Video") { - // this is an embedded texture, we need to remove it from the FBX - object = rootChild.children.erase(object); - } else { - ++object; - } - } - } - } -} +} \ No newline at end of file diff --git a/libraries/baking/src/FBXBaker.h b/libraries/baking/src/FBXBaker.h index 59ef5e349d..5daf8a8adf 100644 --- a/libraries/baking/src/FBXBaker.h +++ b/libraries/baking/src/FBXBaker.h @@ -31,20 +31,14 @@ using TextureBakerThreadGetter = std::function; class FBXBaker : public ModelBaker { Q_OBJECT public: - FBXBaker(const QUrl& inputModelURL, TextureBakerThreadGetter inputTextureThreadGetter, - const QString& bakedOutputDirectory, const QString& originalOutputDirectory = "", bool hasBeenBaked = false); + FBXBaker(const QUrl& inputModelURL, const QString& bakedOutputDirectory, const QString& originalOutputDirectory = "", bool hasBeenBaked = false); protected: virtual void bakeProcessedSource(const hfm::Model::Pointer& hfmModel, const std::vector& dracoMeshes, const std::vector>& dracoMaterialLists) override; private: void rewriteAndBakeSceneModels(const QVector& meshes, const std::vector& dracoMeshes, const std::vector>& dracoMaterialLists); - void rewriteAndBakeSceneTextures(); void replaceMeshNodeWithDraco(FBXNode& meshNode, const QByteArray& dracoMeshBytes, const std::vector& dracoMaterialList); - - hfm::Model::Pointer _hfmModel; - - bool _pendingErrorEmission { false }; }; #endif // hifi_FBXBaker_h diff --git a/libraries/baking/src/MaterialBaker.cpp b/libraries/baking/src/MaterialBaker.cpp index dd1ba55e54..c35c16fc8a 100644 --- a/libraries/baking/src/MaterialBaker.cpp +++ b/libraries/baking/src/MaterialBaker.cpp @@ -64,6 +64,14 @@ void MaterialBaker::bake() { } } +void MaterialBaker::abort() { + Baker::abort(); + + for (auto& textureBaker : _textureBakers) { + textureBaker->abort(); + } +} + void MaterialBaker::loadMaterial() { if (!_isURL) { qCDebug(material_baking) << "Loading local material" << _materialData; diff --git a/libraries/baking/src/MaterialBaker.h b/libraries/baking/src/MaterialBaker.h index 41ce31380e..d89f16e57e 100644 --- a/libraries/baking/src/MaterialBaker.h +++ b/libraries/baking/src/MaterialBaker.h @@ -34,6 +34,7 @@ public: public slots: virtual void bake() override; + virtual void abort() override; signals: void originalMaterialLoaded(); diff --git a/libraries/baking/src/ModelBaker.cpp b/libraries/baking/src/ModelBaker.cpp index 9568a81578..56673398a7 100644 --- a/libraries/baking/src/ModelBaker.cpp +++ b/libraries/baking/src/ModelBaker.cpp @@ -42,12 +42,10 @@ #include "baking/BakerLibrary.h" -ModelBaker::ModelBaker(const QUrl& inputModelURL, TextureBakerThreadGetter inputTextureThreadGetter, - const QString& bakedOutputDirectory, const QString& originalOutputDirectory, bool hasBeenBaked) : +ModelBaker::ModelBaker(const QUrl& inputModelURL, const QString& bakedOutputDirectory, const QString& originalOutputDirectory, bool hasBeenBaked) : _modelURL(inputModelURL), _bakedOutputDir(bakedOutputDirectory), _originalOutputDir(originalOutputDirectory), - _textureThreadGetter(inputTextureThreadGetter), _hasBeenBaked(hasBeenBaked) { auto bakedFilename = _modelURL.fileName(); @@ -250,28 +248,6 @@ void ModelBaker::bakeSourceCopy() { dracoMaterialLists = baker.getDracoMaterialLists(); } - // Populate _textureContentMap with path to content mappings, for quick lookup by URL - for (auto materialIt = bakedModel->materials.cbegin(); materialIt != bakedModel->materials.cend(); materialIt++) { - static const auto addTexture = [](QHash& textureContentMap, const hfm::Texture& texture) { - if (!textureContentMap.contains(texture.filename)) { - // Content may be empty, unless the data is inlined - textureContentMap[texture.filename] = texture.content; - } - }; - const hfm::Material& material = *materialIt; - addTexture(_textureContentMap, material.normalTexture); - addTexture(_textureContentMap, material.albedoTexture); - addTexture(_textureContentMap, material.opacityTexture); - addTexture(_textureContentMap, material.glossTexture); - addTexture(_textureContentMap, material.roughnessTexture); - addTexture(_textureContentMap, material.specularTexture); - addTexture(_textureContentMap, material.metallicTexture); - addTexture(_textureContentMap, material.emissiveTexture); - addTexture(_textureContentMap, material.occlusionTexture); - addTexture(_textureContentMap, material.scatteringTexture); - addTexture(_textureContentMap, material.lightmapTexture); - } - // Do format-specific baking bakeProcessedSource(bakedModel, dracoMeshes, dracoMaterialLists); @@ -291,8 +267,6 @@ void ModelBaker::bakeSourceCopy() { auto outputMapping = _mapping; outputMapping[FST_VERSION_FIELD] = FST_VERSION; outputMapping[FILENAME_FIELD] = _bakedModelURL.fileName(); - // All textures will be found in the same directory as the model - outputMapping[TEXDIR_FIELD] = "."; hifi::ByteArray fstOut = FSTReader::writeMapping(outputMapping); QFile fstOutputFile { outputFSTURL }; @@ -307,18 +281,15 @@ void ModelBaker::bakeSourceCopy() { _outputFiles.push_back(outputFSTURL); _outputMappingURL = outputFSTURL; - // check if we're already done with textures (in case we had none to re-write) - checkIfTexturesFinished(); + exportScene(); + qCDebug(model_baking) << "Finished baking, emitting finished" << _modelURL; + emit finished(); } void ModelBaker::abort() { Baker::abort(); - // tell our underlying TextureBaker instances to abort - // the ModelBaker will wait until all are aborted before emitting its own abort signal - for (auto& textureBaker : _bakingTextures) { - textureBaker->abort(); - } + _materialBaker->abort(); } bool ModelBaker::buildDracoMeshNode(FBXNode& dracoMeshNode, const QByteArray& dracoMeshBytes, const std::vector& dracoMaterialList) { @@ -354,247 +325,6 @@ bool ModelBaker::buildDracoMeshNode(FBXNode& dracoMeshNode, const QByteArray& dr return true; } -QString ModelBaker::compressTexture(QString modelTextureFileName, image::TextureUsage::Type textureType) { - - QFileInfo modelTextureFileInfo { modelTextureFileName.replace("\\", "/") }; - - if (modelTextureFileInfo.suffix().toLower() == BAKED_TEXTURE_KTX_EXT.mid(1)) { - // re-baking a model that already references baked textures - // this is an error - return from here - handleError("Cannot re-bake a file that already references compressed textures"); - return QString::null; - } - - if (!image::getSupportedFormats().contains(modelTextureFileInfo.suffix())) { - // this is a texture format we don't bake, skip it - handleWarning(modelTextureFileName + " is not a bakeable texture format"); - return QString::null; - } - - // make sure this texture points to something and isn't one we've already re-mapped - QString textureChild { QString::null }; - if (!modelTextureFileInfo.filePath().isEmpty()) { - // 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 - if (!modelTextureFileInfo.filePath().isEmpty()) { - textureContent = _textureContentMap.value(modelTextureFileName.toLocal8Bit()); - } - auto urlToTexture = getTextureURL(modelTextureFileInfo, !textureContent.isNull()); - - TextureKey textureKey { urlToTexture, textureType }; - auto bakingTextureIt = _bakingTextures.find(textureKey); - if (bakingTextureIt == _bakingTextures.cend()) { - // construct the new baked texture file name and file path - // ensuring that the baked texture will have a unique name - // even if there was another texture with the same name at a different path - QString baseTextureFileName = _textureFileNamer.createBaseTextureFileName(modelTextureFileInfo, textureType); - - QString bakedTextureFilePath { - _bakedOutputDir + "/" + baseTextureFileName + BAKED_META_TEXTURE_SUFFIX - }; - - textureChild = baseTextureFileName + BAKED_META_TEXTURE_SUFFIX; - - _outputFiles.push_back(bakedTextureFilePath); - - // bake this texture asynchronously - bakeTexture(textureKey, _bakedOutputDir, baseTextureFileName, textureContent); - } else { - // Fetch existing texture meta name - textureChild = (*bakingTextureIt)->getBaseFilename() + BAKED_META_TEXTURE_SUFFIX; - } - } - - qCDebug(model_baking).noquote() << "Re-mapping" << modelTextureFileName - << "to" << textureChild; - - return textureChild; -} - -void ModelBaker::bakeTexture(const TextureKey& textureKey, 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 - QSharedPointer bakingTexture{ - new TextureBaker(textureKey.first, textureKey.second, outputDir, "../", bakedFilename, textureContent), - &TextureBaker::deleteLater - }; - - // make sure we hear when the baking texture is done or aborted - connect(bakingTexture.data(), &Baker::finished, this, &ModelBaker::handleBakedTexture); - connect(bakingTexture.data(), &TextureBaker::aborted, this, &ModelBaker::handleAbortedTexture); - - // keep a shared pointer to the baking texture - _bakingTextures.insert(textureKey, bakingTexture); - - // start baking the texture on one of our available worker threads - bakingTexture->moveToThread(_textureThreadGetter()); - QMetaObject::invokeMethod(bakingTexture.data(), "bake"); -} - -void ModelBaker::handleBakedTexture() { - TextureBaker* bakedTexture = qobject_cast(sender()); - qDebug() << "Handling baked texture" << bakedTexture->getTextureURL(); - - // make sure we haven't already run into errors, and that this is a valid texture - if (bakedTexture) { - if (!shouldStop()) { - if (!bakedTexture->hasErrors()) { - if (!_originalOutputDir.isEmpty()) { - // we've been asked to make copies of the originals, so we need to make copies of this if it is a linked texture - - // use the path to the texture being baked to determine if this was an embedded or a linked texture - - // it is embeddded if the texure being baked was inside a folder with the name of the model - // since that is the fake URL we provide when baking external textures - - if (!_modelURL.isParentOf(bakedTexture->getTextureURL())) { - // for linked textures we want to save a copy of original texture beside the original model - - qCDebug(model_baking) << "Saving original texture for" << bakedTexture->getTextureURL(); - - // check if we have a relative path to use for the texture - auto relativeTexturePath = texturePathRelativeToModel(_modelURL, bakedTexture->getTextureURL()); - - QFile originalTextureFile{ - _originalOutputDir + "/" + relativeTexturePath + bakedTexture->getTextureURL().fileName() - }; - - if (relativeTexturePath.length() > 0) { - // make the folders needed by the relative path - } - - if (originalTextureFile.open(QIODevice::WriteOnly) && originalTextureFile.write(bakedTexture->getOriginalTexture()) != -1) { - qCDebug(model_baking) << "Saved original texture file" << originalTextureFile.fileName() - << "for" << _modelURL; - } else { - handleError("Could not save original external texture " + originalTextureFile.fileName() - + " for " + _modelURL.toString()); - return; - } - } - } - - - // now that this texture has been baked and handled, we can remove that TextureBaker from our hash - _bakingTextures.remove({ bakedTexture->getTextureURL(), bakedTexture->getTextureType() }); - - checkIfTexturesFinished(); - } else { - // there was an error baking this texture - add it to our list of errors - _errorList.append(bakedTexture->getErrors()); - - // we don't emit finished yet so that the other textures can finish baking first - _pendingErrorEmission = true; - - // now that this texture has been baked, even though it failed, we can remove that TextureBaker from our list - _bakingTextures.remove({ bakedTexture->getTextureURL(), bakedTexture->getTextureType() }); - - // abort any other ongoing texture bakes since we know we'll end up failing - for (auto& bakingTexture : _bakingTextures) { - bakingTexture->abort(); - } - - checkIfTexturesFinished(); - } - } else { - // we have errors to attend to, so we don't do extra processing for this texture - // but we do need to remove that TextureBaker from our list - // and then check if we're done with all textures - _bakingTextures.remove({ bakedTexture->getTextureURL(), bakedTexture->getTextureType() }); - - checkIfTexturesFinished(); - } - } -} - -void ModelBaker::handleAbortedTexture() { - // grab the texture bake that was aborted and remove it from our hash since we don't need to track it anymore - TextureBaker* bakedTexture = qobject_cast(sender()); - - qDebug() << "Texture aborted: " << bakedTexture->getTextureURL(); - - if (bakedTexture) { - _bakingTextures.remove({ bakedTexture->getTextureURL(), bakedTexture->getTextureType() }); - } - - // since a texture we were baking aborted, our status is also aborted - _shouldAbort.store(true); - - // abort any other ongoing texture bakes since we know we'll end up failing - for (auto& bakingTexture : _bakingTextures) { - bakingTexture->abort(); - } - - checkIfTexturesFinished(); -} - -QUrl ModelBaker::getTextureURL(const QFileInfo& textureFileInfo, bool isEmbedded) { - QUrl urlToTexture; - - if (isEmbedded) { - urlToTexture = _modelURL.toString() + "/" + textureFileInfo.filePath(); - } else { - if (textureFileInfo.exists() && textureFileInfo.isFile()) { - // set the texture URL to the local texture that we have confirmed exists - urlToTexture = QUrl::fromLocalFile(textureFileInfo.absoluteFilePath()); - } else { - // external texture that we'll need to download or find - - // this is a relative file path which will require different handling - // depending on the location of the original model - if (_modelURL.isLocalFile() && textureFileInfo.exists() && textureFileInfo.isFile()) { - // the absolute path we ran into for the texture in the model exists on this machine - // so use that file - urlToTexture = QUrl::fromLocalFile(textureFileInfo.absoluteFilePath()); - } else { - // we didn't find the texture on this machine at the absolute path - // so assume that it is right beside the model to match the behaviour of interface - urlToTexture = _modelURL.resolved(textureFileInfo.fileName()); - } - } - } - - return urlToTexture; -} - -QString ModelBaker::texturePathRelativeToModel(QUrl modelURL, QUrl textureURL) { - auto modelPath = modelURL.toString(QUrl::RemoveFilename | QUrl::RemoveQuery | QUrl::RemoveFragment); - auto texturePath = textureURL.toString(QUrl::RemoveFilename | QUrl::RemoveQuery | QUrl::RemoveFragment); - - if (texturePath.startsWith(modelPath)) { - // texture path is a child of the model path, return the texture path without the model path - return texturePath.mid(modelPath.length()); - } else { - // the texture path was not a child of the model path, return the empty string - return ""; - } -} - -void ModelBaker::checkIfTexturesFinished() { - // check if we're done everything we need to do for this model - // and emit our finished signal if we're done - - if (_bakingTextures.isEmpty()) { - if (shouldStop()) { - // if we're checking for completion but we have errors - // that means one or more of our texture baking operations failed - - if (_pendingErrorEmission) { - setIsFinished(true); - } - - return; - } else { - qCDebug(model_baking) << "Finished baking, emitting finished" << _modelURL; - - texturesFinished(); - - setIsFinished(true); - } - } -} - void ModelBaker::setWasAborted(bool wasAborted) { if (wasAborted != _wasAborted.load()) { Baker::setWasAborted(wasAborted); @@ -605,70 +335,6 @@ void ModelBaker::setWasAborted(bool wasAborted) { } } -void ModelBaker::texturesFinished() { - embedTextureMetaData(); - exportScene(); -} - -void ModelBaker::embedTextureMetaData() { - std::vector embeddedTextureNodes; - - for (FBXNode& rootChild : _rootNode.children) { - if (rootChild.name == "Objects") { - qlonglong maxId = 0; - for (auto &child : rootChild.children) { - if (child.properties.length() == 3) { - maxId = std::max(maxId, child.properties[0].toLongLong()); - } - } - - for (auto& object : rootChild.children) { - if (object.name == "Texture") { - QVariant relativeFilename; - for (auto& child : object.children) { - if (child.name == "RelativeFilename") { - relativeFilename = child.properties[0]; - break; - } - } - - if (relativeFilename.isNull() - || !relativeFilename.toString().endsWith(BAKED_META_TEXTURE_SUFFIX)) { - continue; - } - if (object.properties.length() < 2) { - qWarning() << "Found texture with unexpected number of properties: " << object.name; - continue; - } - - FBXNode videoNode; - videoNode.name = "Video"; - videoNode.properties.append(++maxId); - videoNode.properties.append(object.properties[1]); - videoNode.properties.append("Clip"); - - QString bakedTextureFilePath { - _bakedOutputDir + "/" + relativeFilename.toString() - }; - - QFile textureFile { bakedTextureFilePath }; - if (!textureFile.open(QIODevice::ReadOnly)) { - qWarning() << "Failed to open: " << bakedTextureFilePath; - continue; - } - - videoNode.children.append({ "RelativeFilename", { relativeFilename }, { } }); - videoNode.children.append({ "Content", { textureFile.readAll() }, { } }); - - rootChild.children.append(videoNode); - - textureFile.close(); - } - } - } - } -} - void ModelBaker::exportScene() { auto fbxData = FBXWriter::encodeFBX(_rootNode); diff --git a/libraries/baking/src/ModelBaker.h b/libraries/baking/src/ModelBaker.h index d9a559392f..599ca2dbab 100644 --- a/libraries/baking/src/ModelBaker.h +++ b/libraries/baking/src/ModelBaker.h @@ -18,17 +18,13 @@ #include #include "Baker.h" -#include "TextureBaker.h" -#include "baking/TextureFileNamer.h" +#include "MaterialBaker.h" #include "ModelBakingLoggingCategory.h" -#include - #include #include -using TextureBakerThreadGetter = std::function; using GetMaterialIDCallback = std::function ; static const QString FST_EXTENSION { ".fst" }; @@ -42,10 +38,7 @@ class ModelBaker : public Baker { Q_OBJECT public: - using TextureKey = QPair; - - ModelBaker(const QUrl& inputModelURL, TextureBakerThreadGetter inputTextureThreadGetter, - const QString& bakedOutputDirectory, const QString& originalOutputDirectory = "", bool hasBeenBaked = false); + ModelBaker(const QUrl& inputModelURL, const QString& bakedOutputDirectory, const QString& originalOutputDirectory = "", bool hasBeenBaked = false); void setOutputURLSuffix(const QUrl& urlSuffix); void setMappingURL(const QUrl& mappingURL); @@ -54,7 +47,6 @@ public: void initializeOutputDirs(); bool buildDracoMeshNode(FBXNode& dracoMeshNode, const QByteArray& dracoMeshBytes, const std::vector& dracoMaterialList); - QString compressTexture(QString textureFileName, image::TextureUsage::Type = image::TextureUsage::Type::DEFAULT_TEXTURE); virtual void setWasAborted(bool wasAborted) override; QUrl getModelURL() const { return _modelURL; } @@ -71,20 +63,15 @@ public slots: protected: void saveSourceModel(); virtual void bakeProcessedSource(const hfm::Model::Pointer& hfmModel, const std::vector& dracoMeshes, const std::vector>& dracoMaterialLists) = 0; - void checkIfTexturesFinished(); - void texturesFinished(); - void embedTextureMetaData(); void exportScene(); FBXNode _rootNode; - QHash _textureContentMap; QUrl _modelURL; QUrl _outputURLSuffix; QUrl _mappingURL; hifi::VariantHash _mapping; QString _bakedOutputDir; QString _originalOutputDir; - TextureBakerThreadGetter _textureThreadGetter; QString _originalOutputModelPath; QString _outputMappingURL; QUrl _bakedModelURL; @@ -93,22 +80,10 @@ protected slots: void handleModelNetworkReply(); virtual void bakeSourceCopy(); -private slots: - void handleBakedTexture(); - void handleAbortedTexture(); - private: - QUrl getTextureURL(const QFileInfo& textureFileInfo, bool isEmbedded = false); - void bakeTexture(const TextureKey& textureKey, const QDir& outputDir, const QString& bakedFilename, const QByteArray& textureContent); - QString texturePathRelativeToModel(QUrl modelURL, QUrl textureURL); - - QMultiHash> _bakingTextures; - QHash _textureNameMatchCount; - bool _pendingErrorEmission { false }; - bool _hasBeenBaked { false }; - TextureFileNamer _textureFileNamer; + QSharedPointer _materialBaker; }; #endif // hifi_ModelBaker_h diff --git a/libraries/baking/src/OBJBaker.cpp b/libraries/baking/src/OBJBaker.cpp index 70bdeb2071..a2d0ab1094 100644 --- a/libraries/baking/src/OBJBaker.cpp +++ b/libraries/baking/src/OBJBaker.cpp @@ -132,55 +132,6 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, const hfm::Model::Pointer& h handleWarning("Baked mesh for OBJ model '" + _modelURL.toString() + "' is empty"); } - // Generating Texture Node - // iterate through mesh parts and process the associated textures - auto size = meshParts.size(); - for (int i = 0; i < size; i++) { - QString material = meshParts[i].materialID; - HFMMaterial currentMaterial = hfmModel->materials[material]; - if (!currentMaterial.albedoTexture.filename.isEmpty() || !currentMaterial.specularTexture.filename.isEmpty()) { - auto textureID = nextNodeID(); - _mapTextureMaterial.emplace_back(textureID, i); - - FBXNode textureNode; - { - textureNode.name = TEXTURE_NODE_NAME; - textureNode.properties = { textureID, "texture" + QString::number(textureID) }; - } - - // Texture node child - TextureName node - FBXNode textureNameNode; - { - textureNameNode.name = TEXTURENAME_NODE_NAME; - QByteArray propertyString = (!currentMaterial.albedoTexture.filename.isEmpty()) ? "Kd" : "Ka"; - textureNameNode.properties = { propertyString }; - } - - // Texture node child - Relative Filename node - FBXNode relativeFilenameNode; - { - relativeFilenameNode.name = RELATIVEFILENAME_NODE_NAME; - } - - QByteArray textureFileName = (!currentMaterial.albedoTexture.filename.isEmpty()) ? currentMaterial.albedoTexture.filename : currentMaterial.specularTexture.filename; - - auto textureType = (!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 - auto textureFile = compressTexture(textureFileName, textureType); - if (textureFile.isNull()) { - // Baking failed return - handleError("Failed to compress texture: " + textureFileName); - return; - } - relativeFilenameNode.properties = { textureFile }; - - textureNode.children = { textureNameNode, relativeFilenameNode }; - - objectNode.children.append(textureNode); - } - } - // Generating Connections node connectionsNode.name = CONNECTIONS_NODE_NAME; @@ -199,29 +150,6 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, const hfm::Model::Pointer& h cNode.properties = { CONNECTIONS_NODE_PROPERTY, materialID, modelID }; connectionsNode.children.append(cNode); } - - // Connect textures to materials - for (const auto& texMat : _mapTextureMaterial) { - FBXNode cAmbientNode; - cAmbientNode.name = C_NODE_NAME; - cAmbientNode.properties = { - CONNECTIONS_NODE_PROPERTY_1, - texMat.first, - _materialIDs[texMat.second], - "AmbientFactor" - }; - connectionsNode.children.append(cAmbientNode); - - FBXNode cDiffuseNode; - cDiffuseNode.name = C_NODE_NAME; - cDiffuseNode.properties = { - CONNECTIONS_NODE_PROPERTY_1, - texMat.first, - _materialIDs[texMat.second], - "DiffuseColor" - }; - connectionsNode.children.append(cDiffuseNode); - } } // Set properties for material nodes diff --git a/libraries/baking/src/OBJBaker.h b/libraries/baking/src/OBJBaker.h index d1eced5452..9bd1431d28 100644 --- a/libraries/baking/src/OBJBaker.h +++ b/libraries/baking/src/OBJBaker.h @@ -35,9 +35,7 @@ private: void setMaterialNodeProperties(FBXNode& materialNode, QString material, const hfm::Model::Pointer& hfmModel); NodeID nextNodeID() { return _nodeID++; } - NodeID _nodeID { 0 }; std::vector _materialIDs; - std::vector> _mapTextureMaterial; }; #endif // hifi_OBJBaker_h diff --git a/libraries/baking/src/baking/BakerLibrary.cpp b/libraries/baking/src/baking/BakerLibrary.cpp index 2afeef4800..356eb4cdb9 100644 --- a/libraries/baking/src/baking/BakerLibrary.cpp +++ b/libraries/baking/src/baking/BakerLibrary.cpp @@ -45,7 +45,7 @@ bool isModelBaked(const QUrl& bakeableModelURL) { return beforeModelExtension.endsWith(".baked"); } -std::unique_ptr getModelBaker(const QUrl& bakeableModelURL, TextureBakerThreadGetter inputTextureThreadGetter, const QString& contentOutputPath) { +std::unique_ptr getModelBaker(const QUrl& bakeableModelURL, const QString& contentOutputPath) { auto filename = bakeableModelURL.fileName(); // Output in a sub-folder with the name of the model, potentially suffixed by a number to make it unique @@ -59,20 +59,20 @@ std::unique_ptr getModelBaker(const QUrl& bakeableModelURL, TextureB QString bakedOutputDirectory = contentOutputPath + subDirName + "/baked"; QString originalOutputDirectory = contentOutputPath + subDirName + "/original"; - return getModelBakerWithOutputDirectories(bakeableModelURL, inputTextureThreadGetter, bakedOutputDirectory, originalOutputDirectory); + return getModelBakerWithOutputDirectories(bakeableModelURL, bakedOutputDirectory, originalOutputDirectory); } -std::unique_ptr getModelBakerWithOutputDirectories(const QUrl& bakeableModelURL, TextureBakerThreadGetter inputTextureThreadGetter, const QString& bakedOutputDirectory, const QString& originalOutputDirectory) { +std::unique_ptr getModelBakerWithOutputDirectories(const QUrl& bakeableModelURL, const QString& bakedOutputDirectory, const QString& originalOutputDirectory) { auto filename = bakeableModelURL.fileName(); std::unique_ptr baker; if (filename.endsWith(FST_EXTENSION, Qt::CaseInsensitive)) { - baker = std::make_unique(bakeableModelURL, inputTextureThreadGetter, bakedOutputDirectory, originalOutputDirectory, filename.endsWith(BAKED_FST_EXTENSION, Qt::CaseInsensitive)); + baker = std::make_unique(bakeableModelURL, bakedOutputDirectory, originalOutputDirectory, filename.endsWith(BAKED_FST_EXTENSION, Qt::CaseInsensitive)); } else if (filename.endsWith(FBX_EXTENSION, Qt::CaseInsensitive)) { - baker = std::make_unique(bakeableModelURL, inputTextureThreadGetter, bakedOutputDirectory, originalOutputDirectory, filename.endsWith(BAKED_FBX_EXTENSION, Qt::CaseInsensitive)); + baker = std::make_unique(bakeableModelURL, bakedOutputDirectory, originalOutputDirectory, filename.endsWith(BAKED_FBX_EXTENSION, Qt::CaseInsensitive)); } else if (filename.endsWith(OBJ_EXTENSION, Qt::CaseInsensitive)) { - baker = std::make_unique(bakeableModelURL, inputTextureThreadGetter, bakedOutputDirectory, originalOutputDirectory); + baker = std::make_unique(bakeableModelURL, bakedOutputDirectory, originalOutputDirectory); //} else if (filename.endsWith(GLTF_EXTENSION, Qt::CaseInsensitive)) { //baker = std::make_unique(bakeableModelURL, inputTextureThreadGetter, bakedOutputDirectory, originalOutputDirectory); } else { diff --git a/libraries/baking/src/baking/BakerLibrary.h b/libraries/baking/src/baking/BakerLibrary.h index a646c8d36a..8f82661b25 100644 --- a/libraries/baking/src/baking/BakerLibrary.h +++ b/libraries/baking/src/baking/BakerLibrary.h @@ -23,9 +23,9 @@ bool isModelBaked(const QUrl& bakeableModelURL); // Assuming the URL is valid, gets the appropriate baker for the given URL, and creates the base directory where the baker's output will later be stored // Returns an empty pointer if a baker could not be created -std::unique_ptr getModelBaker(const QUrl& bakeableModelURL, TextureBakerThreadGetter inputTextureThreadGetter, const QString& contentOutputPath); +std::unique_ptr getModelBaker(const QUrl& bakeableModelURL, const QString& contentOutputPath); // Similar to getModelBaker, but gives control over where the output folders will be -std::unique_ptr getModelBakerWithOutputDirectories(const QUrl& bakeableModelURL, TextureBakerThreadGetter inputTextureThreadGetter, const QString& bakedOutputDirectory, const QString& originalOutputDirectory); +std::unique_ptr getModelBakerWithOutputDirectories(const QUrl& bakeableModelURL, const QString& bakedOutputDirectory, const QString& originalOutputDirectory); #endif // hifi_BakerLibrary_h diff --git a/libraries/baking/src/baking/FSTBaker.cpp b/libraries/baking/src/baking/FSTBaker.cpp index acf3bfe1c7..176c35c059 100644 --- a/libraries/baking/src/baking/FSTBaker.cpp +++ b/libraries/baking/src/baking/FSTBaker.cpp @@ -18,9 +18,8 @@ #include -FSTBaker::FSTBaker(const QUrl& inputMappingURL, TextureBakerThreadGetter inputTextureThreadGetter, - const QString& bakedOutputDirectory, const QString& originalOutputDirectory, bool hasBeenBaked) : - ModelBaker(inputMappingURL, inputTextureThreadGetter, bakedOutputDirectory, originalOutputDirectory, hasBeenBaked) { +FSTBaker::FSTBaker(const QUrl& inputMappingURL, const QString& bakedOutputDirectory, const QString& originalOutputDirectory, bool hasBeenBaked) : + ModelBaker(inputMappingURL, bakedOutputDirectory, originalOutputDirectory, hasBeenBaked) { if (hasBeenBaked) { // Look for the original model file one directory higher. Perhaps this is an oven output directory. QUrl originalRelativePath = QUrl("../original/" + inputMappingURL.fileName().replace(BAKED_FST_EXTENSION, FST_EXTENSION)); @@ -70,7 +69,7 @@ void FSTBaker::bakeSourceCopy() { return; } - auto baker = getModelBakerWithOutputDirectories(bakeableModelURL, _textureThreadGetter, _bakedOutputDir, _originalOutputDir); + auto baker = getModelBakerWithOutputDirectories(bakeableModelURL, _bakedOutputDir, _originalOutputDir); _modelBaker = std::unique_ptr(dynamic_cast(baker.release())); if (!_modelBaker) { handleError("The model url '" + bakeableModelURL.toString() + "' from the FST file '" + _originalOutputModelPath + "' (property: '" + FILENAME_FIELD + "') could not be used to initialize a valid model baker"); diff --git a/libraries/baking/src/baking/FSTBaker.h b/libraries/baking/src/baking/FSTBaker.h index 85c7c93a37..32997680f5 100644 --- a/libraries/baking/src/baking/FSTBaker.h +++ b/libraries/baking/src/baking/FSTBaker.h @@ -18,8 +18,7 @@ class FSTBaker : public ModelBaker { Q_OBJECT public: - FSTBaker(const QUrl& inputMappingURL, TextureBakerThreadGetter inputTextureThreadGetter, - const QString& bakedOutputDirectory, const QString& originalOutputDirectory = "", bool hasBeenBaked = false); + FSTBaker(const QUrl& inputMappingURL, const QString& bakedOutputDirectory, const QString& originalOutputDirectory = "", bool hasBeenBaked = false); virtual QUrl getFullOutputMappingURL() const override; diff --git a/tools/oven/src/BakerCLI.cpp b/tools/oven/src/BakerCLI.cpp index 2946db650c..ff8acf060e 100644 --- a/tools/oven/src/BakerCLI.cpp +++ b/tools/oven/src/BakerCLI.cpp @@ -49,10 +49,7 @@ void BakerCLI::bakeFile(QUrl inputUrl, const QString& outputPath, const QString& if (type == MODEL_EXTENSION || type == FBX_EXTENSION) { QUrl bakeableModelURL = getBakeableModelURL(inputUrl); if (!bakeableModelURL.isEmpty()) { - auto getWorkerThreadCallback = []() -> QThread* { - return Oven::instance().getNextWorkerThread(); - }; - _baker = getModelBaker(bakeableModelURL, getWorkerThreadCallback, outputPath); + _baker = getModelBaker(bakeableModelURL, outputPath); if (_baker) { _baker->moveToThread(Oven::instance().getNextWorkerThread()); } diff --git a/tools/oven/src/DomainBaker.cpp b/tools/oven/src/DomainBaker.cpp index 05745aad24..80ad410053 100644 --- a/tools/oven/src/DomainBaker.cpp +++ b/tools/oven/src/DomainBaker.cpp @@ -152,10 +152,7 @@ void DomainBaker::addModelBaker(const QString& property, const QString& url, con // setup a ModelBaker for this URL, as long as we don't already have one bool haveBaker = _modelBakers.contains(bakeableModelURL); if (!haveBaker) { - auto getWorkerThreadCallback = []() -> QThread* { - return Oven::instance().getNextWorkerThread(); - }; - QSharedPointer baker = QSharedPointer(getModelBaker(bakeableModelURL, getWorkerThreadCallback, _contentOutputPath).release(), &Baker::deleteLater); + QSharedPointer baker = QSharedPointer(getModelBaker(bakeableModelURL, _contentOutputPath).release(), &Baker::deleteLater); if (baker) { // Hold on to the old url userinfo/query/fragment data so ModelBaker::getFullOutputMappingURL retains that data from the original model URL // Note: The ModelBaker currently doesn't store this in the FST because the equal signs mess up FST parsing. diff --git a/tools/oven/src/ui/ModelBakeWidget.cpp b/tools/oven/src/ui/ModelBakeWidget.cpp index 79ab733b0c..7561a8e009 100644 --- a/tools/oven/src/ui/ModelBakeWidget.cpp +++ b/tools/oven/src/ui/ModelBakeWidget.cpp @@ -180,11 +180,7 @@ void ModelBakeWidget::bakeButtonClicked() { QUrl bakeableModelURL = getBakeableModelURL(modelToBakeURL); if (!bakeableModelURL.isEmpty()) { - auto getWorkerThreadCallback = []() -> QThread* { - return Oven::instance().getNextWorkerThread(); - }; - - std::unique_ptr baker = getModelBaker(bakeableModelURL, getWorkerThreadCallback, outputDirectory.path()); + std::unique_ptr baker = getModelBaker(bakeableModelURL, outputDirectory.path()); if (baker) { // everything seems to be in place, kick off a bake for this model now