Merge pull request #15427 from SamGondelman/materialMap

Case 22079: Bake existing materialMap in FST
This commit is contained in:
Shannon Romano 2019-04-24 09:16:12 -07:00 committed by GitHub
commit 0768cd58dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 23 deletions

View file

@ -276,4 +276,8 @@ void MaterialBaker::setMaterials(const QHash<QString, hfm::Material>& materials,
addTexture(material.name, image::TextureUsage::SCATTERING_TEXTURE, material.scatteringTexture);
addTexture(material.name, image::TextureUsage::LIGHTMAP_TEXTURE, material.lightmapTexture);
}
}
void MaterialBaker::setMaterials(const NetworkMaterialResourcePointer& materialResource) {
_materialResource = materialResource;
}

View file

@ -31,6 +31,9 @@ public:
QString getBakedMaterialData() const { return _bakedMaterialData; }
void setMaterials(const QHash<QString, hfm::Material>& materials, const QString& baseURL);
void setMaterials(const NetworkMaterialResourcePointer& materialResource);
NetworkMaterialResourcePointer getNetworkMaterialResource() const { return _materialResource; }
static void setNextOvenWorkerThreadOperator(std::function<QThread*()> getNextOvenWorkerThreadOperator) { _getNextOvenWorkerThreadOperator = getNextOvenWorkerThreadOperator; }

View file

@ -241,14 +241,12 @@ void ModelBaker::bakeSourceCopy() {
config->getJobConfig("BuildDracoMesh")->setEnabled(true);
// Do not permit potentially lossy modification of joint data meant for runtime
((PrepareJointsConfig*)config->getJobConfig("PrepareJoints"))->passthrough = true;
// The resources parsed from this job will not be used for now
// TODO: Proper full baking of all materials for a model
config->getJobConfig("ParseMaterialMapping")->setEnabled(false);
// Begin hfm baking
baker.run();
_hfmModel = baker.getHFMModel();
_materialMapping = baker.getMaterialMapping();
dracoMeshes = baker.getDracoMeshes();
dracoMaterialLists = baker.getDracoMaterialLists();
}
@ -260,7 +258,7 @@ void ModelBaker::bakeSourceCopy() {
return;
}
if (_hfmModel->materials.size() > 0) {
if (!_hfmModel->materials.isEmpty()) {
_materialBaker = QSharedPointer<MaterialBaker>(
new MaterialBaker(_modelURL.fileName(), true, _bakedOutputDir),
&MaterialBaker::deleteLater
@ -269,7 +267,7 @@ void ModelBaker::bakeSourceCopy() {
connect(_materialBaker.data(), &MaterialBaker::finished, this, &ModelBaker::handleFinishedMaterialBaker);
_materialBaker->bake();
} else {
outputBakedFST();
bakeMaterialMap();
}
}
@ -285,26 +283,14 @@ void ModelBaker::handleFinishedMaterialBaker() {
auto baseName = relativeBakedMaterialURL.left(relativeBakedMaterialURL.lastIndexOf('.'));
relativeBakedMaterialURL = baseName + BAKED_MATERIAL_EXTENSION;
// First we add the materials in the model
QJsonArray materialMapping;
for (auto material : _hfmModel->materials) {
QJsonObject json;
json["mat::" + material.name] = relativeBakedMaterialURL + "#" + material.name;
materialMapping.push_back(json);
}
// The we add any existing mappings from the mapping
if (_mapping.contains(MATERIAL_MAPPING_FIELD)) {
QByteArray materialMapValue = _mapping[MATERIAL_MAPPING_FIELD].toByteArray();
QJsonObject oldMaterialMapping = QJsonDocument::fromJson(materialMapValue).object();
for (auto key : oldMaterialMapping.keys()) {
auto materialResource = baker->getNetworkMaterialResource();
if (materialResource) {
for (auto materialName : materialResource->parsedMaterials.names) {
QJsonObject json;
json[key] = oldMaterialMapping[key];
materialMapping.push_back(json);
json[QString("mat::" + QString(materialName.c_str()))] = relativeBakedMaterialURL + "#" + materialName.c_str();
_materialMappingJSON.push_back(json);
}
}
_mapping[MATERIAL_MAPPING_FIELD] = QJsonDocument(materialMapping).toJson(QJsonDocument::Compact);
} else {
// this material failed to bake - this doesn't fail the entire bake but we need to add the errors from
// the material to our warnings
@ -314,7 +300,62 @@ void ModelBaker::handleFinishedMaterialBaker() {
handleWarning("Failed to bake the materials for model with URL " + _modelURL.toString());
}
outputBakedFST();
bakeMaterialMap();
}
void ModelBaker::bakeMaterialMap() {
if (!_materialMapping.empty()) {
// TODO: The existing material map must be baked in order, so we do it all on this thread to preserve the order.
// It could be spread over multiple threads if we had a good way of preserving the order once all of the bakers are done
_materialBaker = QSharedPointer<MaterialBaker>(
new MaterialBaker("materialMap" + QString::number(_materialMapIndex++), true, _bakedOutputDir),
&MaterialBaker::deleteLater
);
_materialBaker->setMaterials(_materialMapping.front().second);
connect(_materialBaker.data(), &MaterialBaker::finished, this, &ModelBaker::handleFinishedMaterialMapBaker);
_materialBaker->bake();
} else {
outputBakedFST();
}
}
void ModelBaker::handleFinishedMaterialMapBaker() {
auto baker = qobject_cast<MaterialBaker*>(sender());
if (baker) {
if (!baker->hasErrors()) {
// this MaterialBaker is done and everything went according to plan
qCDebug(model_baking) << "Adding baked material to FST mapping " << baker->getBakedMaterialData();
QString materialName;
{
auto materialResource = baker->getNetworkMaterialResource();
if (materialResource) {
auto url = materialResource->getURL();
if (!url.isEmpty()) {
QString urlString = url.toDisplayString();
auto index = urlString.lastIndexOf("#");
if (index != -1) {
materialName = urlString.right(urlString.length() - index);
}
}
}
}
QJsonObject json;
json[QString(_materialMapping.front().first.c_str())] = baker->getMaterialData() + BAKED_MATERIAL_EXTENSION + materialName;
_materialMappingJSON.push_back(json);
} else {
// this material failed to bake - this doesn't fail the entire bake but we need to add the errors from
// the material to our warnings
_warningList << baker->getWarnings();
}
} else {
handleWarning("Failed to bake the materialMap for model with URL " + _modelURL.toString() + " and mapping target " + _materialMapping.front().first.c_str());
}
_materialMapping.erase(_materialMapping.begin());
bakeMaterialMap();
}
void ModelBaker::outputUnbakedFST() {
@ -363,6 +404,9 @@ void ModelBaker::outputBakedFST() {
outputMapping[FILENAME_FIELD] = _bakedModelURL.fileName();
outputMapping.remove(TEXDIR_FIELD);
outputMapping.remove(COMMENT_FIELD);
if (!_materialMappingJSON.isEmpty()) {
outputMapping[MATERIAL_MAPPING_FIELD] = QJsonDocument(_materialMappingJSON).toJson(QJsonDocument::Compact);
}
hifi::ByteArray fstOut = FSTReader::writeMapping(outputMapping);
QFile fstOutputFile { outputFSTURL };

View file

@ -16,6 +16,7 @@
#include <QtCore/QDir>
#include <QtCore/QUrl>
#include <QtNetwork/QNetworkReply>
#include <QJsonArray>
#include "Baker.h"
#include "MaterialBaker.h"
@ -80,14 +81,19 @@ protected slots:
void handleModelNetworkReply();
virtual void bakeSourceCopy();
void handleFinishedMaterialBaker();
void handleFinishedMaterialMapBaker();
private:
void outputUnbakedFST();
void outputBakedFST();
void bakeMaterialMap();
bool _hasBeenBaked { false };
hfm::Model::Pointer _hfmModel;
MaterialMapping _materialMapping;
int _materialMapIndex { 0 };
QJsonArray _materialMappingJSON;
QSharedPointer<MaterialBaker> _materialBaker;
};