Fix coding guideline violations in *Baker classes

This commit is contained in:
Ryan Huffman 2017-11-16 16:32:11 -08:00
parent 730202b7fc
commit dd2d3d97b4
6 changed files with 165 additions and 192 deletions

View file

@ -40,32 +40,8 @@ FBXBaker::FBXBaker(const QUrl& fbxURL, TextureBakerThreadGetter textureThreadGet
}
FBXBaker::~FBXBaker() {
if (modelTempDir.exists()) {
if (!modelTempDir.remove(originalModelFilePath)) {
qCWarning(model_baking) << "Failed to remove temporary copy of fbx file:" << originalModelFilePath;
}
if (!modelTempDir.rmdir(".")) {
qCWarning(model_baking) << "Failed to remove temporary directory:" << modelTempDir;
}
}
}
void FBXBaker::bake() {
qDebug() << "FBXBaker" << modelURL << "bake starting";
auto tempDir = PathUtils::generateTemporaryDir();
if (tempDir.isEmpty()) {
handleError("Failed to create a temporary directory.");
return;
}
modelTempDir = tempDir;
originalModelFilePath = modelTempDir.filePath(modelURL.fileName());
qDebug() << "Made temporary dir " << modelTempDir;
qDebug() << "Origin file path: " << originalModelFilePath;
qDebug() << "FBXBaker" << _modelURL << "bake starting";
// setup the output folder for the results of this bake
setupOutputFolder();
@ -114,19 +90,19 @@ void FBXBaker::bakeSourceCopy() {
void FBXBaker::setupOutputFolder() {
// make sure there isn't already an output directory using the same name
if (QDir(bakedOutputDir).exists()) {
qWarning() << "Output path" << bakedOutputDir << "already exists. Continuing.";
if (QDir(_bakedOutputDir).exists()) {
qWarning() << "Output path" << _bakedOutputDir << "already exists. Continuing.";
} else {
qCDebug(model_baking) << "Creating FBX output folder" << bakedOutputDir;
qCDebug(model_baking) << "Creating FBX output folder" << _bakedOutputDir;
// attempt to make the output folder
if (!QDir().mkpath(bakedOutputDir)) {
handleError("Failed to create FBX output folder " + bakedOutputDir);
if (!QDir().mkpath(_bakedOutputDir)) {
handleError("Failed to create FBX output folder " + _bakedOutputDir);
return;
}
// attempt to make the output folder
if (!QDir().mkpath(originalOutputDir)) {
handleError("Failed to create FBX output folder " + bakedOutputDir);
if (!QDir().mkpath(_originalOutputDir)) {
handleError("Failed to create FBX output folder " + _bakedOutputDir);
return;
}
}
@ -134,25 +110,25 @@ void FBXBaker::setupOutputFolder() {
void FBXBaker::loadSourceFBX() {
// check if the FBX is local or first needs to be downloaded
if (modelURL.isLocalFile()) {
if (_modelURL.isLocalFile()) {
// load up the local file
QFile localFBX { modelURL.toLocalFile() };
QFile localFBX { _modelURL.toLocalFile() };
qDebug() << "Local file url: " << modelURL << modelURL.toString() << modelURL.toLocalFile() << ", copying to: " << originalModelFilePath;
qDebug() << "Local file url: " << _modelURL << _modelURL.toString() << _modelURL.toLocalFile() << ", copying to: " << _originalModelFilePath;
if (!localFBX.exists()) {
//QMessageBox::warning(this, "Could not find " + _fbxURL.toString(), "");
handleError("Could not find " + modelURL.toString());
handleError("Could not find " + _modelURL.toString());
return;
}
// make a copy in the output folder
if (!originalOutputDir.isEmpty()) {
qDebug() << "Copying to: " << originalOutputDir << "/" << modelURL.fileName();
localFBX.copy(originalOutputDir + "/" + modelURL.fileName());
if (!_originalOutputDir.isEmpty()) {
qDebug() << "Copying to: " << _originalOutputDir << "/" << _modelURL.fileName();
localFBX.copy(_originalOutputDir + "/" + _modelURL.fileName());
}
localFBX.copy(originalModelFilePath);
localFBX.copy(_originalModelFilePath);
// emit our signal to start the import of the FBX source copy
emit sourceCopyReadyToLoad();
@ -167,9 +143,9 @@ void FBXBaker::loadSourceFBX() {
networkRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
networkRequest.setUrl(modelURL);
networkRequest.setUrl(_modelURL);
qCDebug(model_baking) << "Downloading" << modelURL;
qCDebug(model_baking) << "Downloading" << _modelURL;
auto networkReply = networkAccessManager.get(networkRequest);
connect(networkReply, &QNetworkReply::finished, this, &FBXBaker::handleFBXNetworkReply);
@ -180,53 +156,53 @@ void FBXBaker::handleFBXNetworkReply() {
auto requestReply = qobject_cast<QNetworkReply*>(sender());
if (requestReply->error() == QNetworkReply::NoError) {
qCDebug(model_baking) << "Downloaded" << modelURL;
qCDebug(model_baking) << "Downloaded" << _modelURL;
// grab the contents of the reply and make a copy in the output folder
QFile copyOfOriginal(originalModelFilePath);
QFile copyOfOriginal(_originalModelFilePath);
qDebug(model_baking) << "Writing copy of original FBX to" << originalModelFilePath << copyOfOriginal.fileName();
qDebug(model_baking) << "Writing copy of original FBX to" << _originalModelFilePath << copyOfOriginal.fileName();
if (!copyOfOriginal.open(QIODevice::WriteOnly)) {
// add an error to the error list for this FBX stating that a duplicate of the original FBX could not be made
handleError("Could not create copy of " + modelURL.toString() + " (Failed to open " + originalModelFilePath + ")");
handleError("Could not create copy of " + _modelURL.toString() + " (Failed to open " + _originalModelFilePath + ")");
return;
}
if (copyOfOriginal.write(requestReply->readAll()) == -1) {
handleError("Could not create copy of " + modelURL.toString() + " (Failed to write)");
handleError("Could not create copy of " + _modelURL.toString() + " (Failed to write)");
return;
}
// close that file now that we are done writing to it
copyOfOriginal.close();
if (!originalOutputDir.isEmpty()) {
copyOfOriginal.copy(originalOutputDir + "/" + modelURL.fileName());
if (!_originalOutputDir.isEmpty()) {
copyOfOriginal.copy(_originalOutputDir + "/" + _modelURL.fileName());
}
// emit our signal to start the import of the FBX source copy
emit sourceCopyReadyToLoad();
} else {
// add an error to our list stating that the FBX could not be downloaded
handleError("Failed to download " + modelURL.toString());
handleError("Failed to download " + _modelURL.toString());
}
}
void FBXBaker::importScene() {
qDebug() << "file path: " << originalModelFilePath.toLocal8Bit().data() << QDir(originalModelFilePath).exists();
qDebug() << "file path: " << _originalModelFilePath.toLocal8Bit().data() << QDir(_originalModelFilePath).exists();
QFile fbxFile(originalModelFilePath);
QFile fbxFile(_originalModelFilePath);
if (!fbxFile.open(QIODevice::ReadOnly)) {
handleError("Error opening " + originalModelFilePath + " for reading");
handleError("Error opening " + _originalModelFilePath + " for reading");
return;
}
FBXReader reader;
qCDebug(model_baking) << "Parsing" << modelURL;
qCDebug(model_baking) << "Parsing" << _modelURL;
_rootNode = reader._rootNode = reader.parseFBX(&fbxFile);
_geometry = reader.extractFBXGeometry({}, modelURL.toString());
textureContentMap = reader._textureContent;
_geometry = reader.extractFBXGeometry({}, _modelURL.toString());
_textureContentMap = reader._textureContent;
}
void FBXBaker::rewriteAndBakeSceneModels() {
@ -388,24 +364,24 @@ void FBXBaker::rewriteAndBakeSceneTextures() {
void FBXBaker::exportScene() {
// save the relative path to this FBX inside our passed output folder
auto fileName = modelURL.fileName();
auto fileName = _modelURL.fileName();
auto baseName = fileName.left(fileName.lastIndexOf('.'));
auto bakedFilename = baseName + BAKED_FBX_EXTENSION;
bakedModelFilePath = bakedOutputDir + "/" + bakedFilename;
_bakedModelFilePath = _bakedOutputDir + "/" + bakedFilename;
auto fbxData = FBXWriter::encodeFBX(_rootNode);
QFile bakedFile(bakedModelFilePath);
QFile bakedFile(_bakedModelFilePath);
if (!bakedFile.open(QIODevice::WriteOnly)) {
handleError("Error opening " + bakedModelFilePath + " for writing");
handleError("Error opening " + _bakedModelFilePath + " for writing");
return;
}
bakedFile.write(fbxData);
_outputFiles.push_back(bakedModelFilePath);
_outputFiles.push_back(_bakedModelFilePath);
qCDebug(model_baking) << "Exported" << modelURL << "with re-written paths to" << bakedModelFilePath;
qCDebug(model_baking) << "Exported" << _modelURL << "with re-written paths to" << _bakedModelFilePath;
}

View file

@ -35,10 +35,9 @@ class FBXBaker : public ModelBaker {
public:
FBXBaker(const QUrl& fbxURL, TextureBakerThreadGetter textureThreadGetter,
const QString& bakedOutputDir, const QString& originalOutputDir = "");
~FBXBaker() override;
QUrl getFBXUrl() const { return modelURL; }
QString getBakedFBXFilePath() const { return bakedModelFilePath; }
QUrl getFBXUrl() const { return _modelURL; }
QString getBakedFBXFilePath() const { return _bakedModelFilePath; }
public slots:
virtual void bake() override;

View file

@ -30,12 +30,35 @@
ModelBaker::ModelBaker(const QUrl& inputModelURL, TextureBakerThreadGetter inputTextureThreadGetter,
const QString& bakedOutputDirectory, const QString& originalOutputDirectory) :
modelURL(inputModelURL),
textureThreadGetter(inputTextureThreadGetter),
bakedOutputDir(bakedOutputDirectory),
originalOutputDir(originalOutputDirectory)
_modelURL(inputModelURL),
_textureThreadGetter(inputTextureThreadGetter),
_bakedOutputDir(bakedOutputDirectory),
_originalOutputDir(originalOutputDirectory)
{
auto tempDir = PathUtils::generateTemporaryDir();
if (tempDir.isEmpty()) {
handleError("Failed to create a temporary directory.");
return;
}
_modelTempDir = tempDir;
_originalModelFilePath = _modelTempDir.filePath(_modelURL.fileName());
qDebug() << "Made temporary dir " << _modelTempDir;
qDebug() << "Origin file path: " << _originalModelFilePath;
}
ModelBaker::~ModelBaker() {
if (_modelTempDir.exists()) {
if (!_modelTempDir.remove(_originalModelFilePath)) {
qCWarning(model_baking) << "Failed to remove temporary copy of fbx file:" << _originalModelFilePath;
}
if (!_modelTempDir.rmdir(".")) {
qCWarning(model_baking) << "Failed to remove temporary directory:" << _modelTempDir;
}
}
}
void ModelBaker::abort() {
@ -43,7 +66,7 @@ void ModelBaker::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) {
for (auto& textureBaker : _bakingTextures) {
textureBaker->abort();
}
}
@ -251,7 +274,7 @@ QByteArray* ModelBaker::compressTexture(QString modelTextureFileName, getTexture
// figure out the URL to this texture, embedded or external
if (!modelTextureFileInfo.filePath().isEmpty()) {
textureContent = textureContentMap.value(modelTextureFileName.toLocal8Bit());
textureContent = _textureContentMap.value(modelTextureFileName.toLocal8Bit());
}
auto urlToTexture = getTextureURL(modelTextureFileInfo, modelTextureFileName, !textureContent.isNull());
@ -270,16 +293,16 @@ QByteArray* ModelBaker::compressTexture(QString modelTextureFileName, getTexture
<< "to" << bakedTextureFileName;
QString bakedTextureFilePath{
bakedOutputDir + "/" + bakedTextureFileName
_bakedOutputDir + "/" + bakedTextureFileName
};
textureChild = bakedTextureFileName.toLocal8Bit();
if (!bakingTextures.contains(urlToTexture)) {
if (!_bakingTextures.contains(urlToTexture)) {
_outputFiles.push_back(bakedTextureFilePath);
// bake this texture asynchronously
bakeTexture(urlToTexture, textureType, bakedOutputDir, bakedTextureFileName, textureContent);
bakeTexture(urlToTexture, textureType, _bakedOutputDir, bakedTextureFileName, textureContent);
}
}
@ -300,10 +323,10 @@ void ModelBaker::bakeTexture(const QUrl& textureURL, image::TextureUsage::Type t
connect(bakingTexture.data(), &TextureBaker::aborted, this, &ModelBaker::handleAbortedTexture);
// keep a shared pointer to the baking texture
bakingTextures.insert(textureURL, bakingTexture);
_bakingTextures.insert(textureURL, bakingTexture);
// start baking the texture on one of our available worker threads
bakingTexture->moveToThread(textureThreadGetter());
bakingTexture->moveToThread(_textureThreadGetter());
QMetaObject::invokeMethod(bakingTexture.data(), "bake");
}
@ -314,7 +337,7 @@ void ModelBaker::handleBakedTexture() {
if (bakedTexture) {
if (!shouldStop()) {
if (!bakedTexture->hasErrors()) {
if (!originalOutputDir.isEmpty()) {
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
@ -322,16 +345,16 @@ void ModelBaker::handleBakedTexture() {
// 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())) {
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());
auto relativeTexturePath = texturePathRelativeToModel(_modelURL, bakedTexture->getTextureURL());
QFile originalTextureFile{
originalOutputDir + "/" + relativeTexturePath + bakedTexture->getTextureURL().fileName()
_originalOutputDir + "/" + relativeTexturePath + bakedTexture->getTextureURL().fileName()
};
if (relativeTexturePath.length() > 0) {
@ -340,10 +363,10 @@ void ModelBaker::handleBakedTexture() {
if (originalTextureFile.open(QIODevice::WriteOnly) && originalTextureFile.write(bakedTexture->getOriginalTexture()) != -1) {
qCDebug(model_baking) << "Saved original texture file" << originalTextureFile.fileName()
<< "for" << modelURL;
<< "for" << _modelURL;
} else {
handleError("Could not save original external texture " + originalTextureFile.fileName()
+ " for " + modelURL.toString());
+ " for " + _modelURL.toString());
return;
}
}
@ -351,7 +374,7 @@ void ModelBaker::handleBakedTexture() {
// now that this texture has been baked and handled, we can remove that TextureBaker from our hash
bakingTextures.remove(bakedTexture->getTextureURL());
_bakingTextures.remove(bakedTexture->getTextureURL());
checkIfTexturesFinished();
} else {
@ -362,10 +385,10 @@ void ModelBaker::handleBakedTexture() {
_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());
_bakingTextures.remove(bakedTexture->getTextureURL());
// abort any other ongoing texture bakes since we know we'll end up failing
for (auto& bakingTexture : bakingTextures) {
for (auto& bakingTexture : _bakingTextures) {
bakingTexture->abort();
}
@ -375,7 +398,7 @@ void ModelBaker::handleBakedTexture() {
// 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());
_bakingTextures.remove(bakedTexture->getTextureURL());
checkIfTexturesFinished();
}
@ -387,14 +410,14 @@ void ModelBaker::handleAbortedTexture() {
TextureBaker* bakedTexture = qobject_cast<TextureBaker*>(sender());
if (bakedTexture) {
bakingTextures.remove(bakedTexture->getTextureURL());
_bakingTextures.remove(bakedTexture->getTextureURL());
}
// 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) {
for (auto& bakingTexture : _bakingTextures) {
bakingTexture->abort();
}
@ -408,7 +431,7 @@ QUrl ModelBaker::getTextureURL(const QFileInfo& textureFileInfo, QString relativ
auto apparentRelativePath = QFileInfo(relativeFileName.replace("\\", "/"));
if (isEmbedded) {
urlToTexture = modelURL.toString() + "/" + apparentRelativePath.filePath();
urlToTexture = _modelURL.toString() + "/" + apparentRelativePath.filePath();
} else {
if (textureFileInfo.exists() && textureFileInfo.isFile()) {
// set the texture URL to the local texture that we have confirmed exists
@ -418,14 +441,14 @@ QUrl ModelBaker::getTextureURL(const QFileInfo& textureFileInfo, QString relativ
// this is a relative file path which will require different handling
// depending on the location of the original model
if (modelURL.isLocalFile() && apparentRelativePath.exists() && apparentRelativePath.isFile()) {
if (_modelURL.isLocalFile() && apparentRelativePath.exists() && apparentRelativePath.isFile()) {
// the absolute path we ran into for the texture in the model exists on this machine
// so use that file
urlToTexture = QUrl::fromLocalFile(apparentRelativePath.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(apparentRelativePath.fileName());
urlToTexture = _modelURL.resolved(apparentRelativePath.fileName());
}
}
}
@ -450,7 +473,7 @@ 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 (_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
@ -461,7 +484,7 @@ void ModelBaker::checkIfTexturesFinished() {
return;
} else {
qCDebug(model_baking) << "Finished baking, emitting finished" << modelURL;
qCDebug(model_baking) << "Finished baking, emitting finished" << _modelURL;
setIsFinished(true);
}
@ -494,7 +517,7 @@ void ModelBaker::setWasAborted(bool wasAborted) {
Baker::setWasAborted(wasAborted);
if (wasAborted) {
qCDebug(model_baking) << "Aborted baking" << modelURL;
qCDebug(model_baking) << "Aborted baking" << _modelURL;
}
}
}

View file

@ -30,12 +30,13 @@ using TextureBakerThreadGetter = std::function<QThread*()>;
using getMaterialIDCallback = std::function <int(int)>;
using getTextureTypeCallback = std::function<image::TextureUsage::Type()>;
class ModelBaker : public Baker{
class ModelBaker : public Baker {
Q_OBJECT
public:
ModelBaker(const QUrl& inputModelURL, TextureBakerThreadGetter inputTextureThreadGetter,
const QString& bakedOutputDirectory, const QString& originalOutputDirectory);
virtual ~ModelBaker();
bool compressMesh(FBXMesh& mesh, bool hasDeformers, FBXNode& dracoMeshNode, getMaterialIDCallback materialIDCallback = NULL);
QByteArray* compressTexture(QString textureFileName, getTextureTypeCallback textureTypeCallback = NULL);
virtual void setWasAborted(bool wasAborted) override;
@ -43,15 +44,13 @@ public:
protected:
void checkIfTexturesFinished();
QHash<QByteArray, QByteArray> textureContentMap;
QUrl modelURL;
TextureBakerThreadGetter textureThreadGetter;
QString bakedOutputDir;
QString originalOutputDir;
QString bakedModelFilePath;
QDir modelTempDir;
QString originalModelFilePath;
QMultiHash<QUrl, QSharedPointer<TextureBaker>> bakingTextures;
QHash<QByteArray, QByteArray> _textureContentMap;
QUrl _modelURL;
QString _bakedOutputDir;
QString _originalOutputDir;
QString _bakedModelFilePath;
QDir _modelTempDir;
QString _originalModelFilePath;
public slots:
virtual void abort() override;
@ -67,7 +66,8 @@ private:
const QString & bakedFilename, const QByteArray & textureContent);
QString texturePathRelativeToModel(QUrl modelURL, QUrl textureURL);
TextureBakerThreadGetter _textureThreadGetter;
QMultiHash<QUrl, QSharedPointer<TextureBaker>> _bakingTextures;
QHash<QString, int> _textureNameMatchCount;
QHash<QUrl, QString> _remappedTexturePaths;
bool _pendingErrorEmission{ false };

View file

@ -16,7 +16,7 @@
#include "OBJReader.h"
#include "FBXWriter.h"
const double UNIT_SCALE_FACTOR = 100;
const double UNIT_SCALE_FACTOR = 100.0;
const QByteArray PROPERTIES70_NODE_NAME = "Properties70";
const QByteArray P_NODE_NAME = "P";
const QByteArray C_NODE_NAME = "C";
@ -41,33 +41,9 @@ OBJBaker::OBJBaker(const QUrl& objURL, TextureBakerThreadGetter textureThreadGet
}
OBJBaker::~OBJBaker() {
if (modelTempDir.exists()) {
if (!modelTempDir.remove(originalModelFilePath)) {
qCWarning(model_baking) << "Failed to remove temporary copy of OBJ file:" << originalModelFilePath;
}
if (!modelTempDir.rmdir(".")) {
qCWarning(model_baking) << "Failed to remove temporary directory:" << modelTempDir;
}
}
}
void OBJBaker::bake() {
qDebug() << "OBJBaker" << modelURL << "bake starting";
qDebug() << "OBJBaker" << _modelURL << "bake starting";
auto tempDir = PathUtils::generateTemporaryDir();
if (tempDir.isEmpty()) {
handleError("Failed to create a temporary directory.");
return;
}
modelTempDir = tempDir;
originalModelFilePath = modelTempDir.filePath(modelURL.fileName());
qDebug() << "Made temporary dir " << modelTempDir;
qDebug() << "Origin file path: " << originalModelFilePath;
// trigger bakeOBJ once OBJ is loaded
connect(this, &OBJBaker::OBJLoaded, this, &OBJBaker::bakeOBJ);
@ -77,24 +53,24 @@ void OBJBaker::bake() {
void OBJBaker::loadOBJ() {
// check if the OBJ is local or it needs to be downloaded
if (modelURL.isLocalFile()) {
if (_modelURL.isLocalFile()) {
// loading the local OBJ
QFile localOBJ{ modelURL.toLocalFile() };
QFile localOBJ { _modelURL.toLocalFile() };
qDebug() << "Local file url: " << modelURL << modelURL.toString() << modelURL.toLocalFile() << ", copying to: " << originalModelFilePath;
qDebug() << "Local file url: " << _modelURL << _modelURL.toString() << _modelURL.toLocalFile() << ", copying to: " << _originalModelFilePath;
if (!localOBJ.exists()) {
handleError("Could not find " + modelURL.toString());
handleError("Could not find " + _modelURL.toString());
return;
}
// make a copy in the output folder
if (!originalOutputDir.isEmpty()) {
qDebug() << "Copying to: " << originalOutputDir << "/" << modelURL.fileName();
localOBJ.copy(originalOutputDir + "/" + modelURL.fileName());
if (!_originalOutputDir.isEmpty()) {
qDebug() << "Copying to: " << _originalOutputDir << "/" << _modelURL.fileName();
localOBJ.copy(_originalOutputDir + "/" + _modelURL.fileName());
}
localOBJ.copy(originalModelFilePath);
localOBJ.copy(_originalModelFilePath);
// local OBJ is loaded emit signal to trigger its baking
emit OBJLoaded();
@ -108,11 +84,11 @@ void OBJBaker::loadOBJ() {
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
networkRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
networkRequest.setUrl(modelURL);
qCDebug(model_baking) << "Downloading" << modelURL;
networkRequest.setUrl(_modelURL);
qCDebug(model_baking) << "Downloading" << _modelURL;
auto networkReply = networkAccessManager.get(networkRequest);
connect(networkReply, &QNetworkReply::finished, this, &OBJBaker::handleOBJNetworkReply);
}
}
@ -121,44 +97,44 @@ void OBJBaker::handleOBJNetworkReply() {
auto requestReply = qobject_cast<QNetworkReply*>(sender());
if (requestReply->error() == QNetworkReply::NoError) {
qCDebug(model_baking) << "Downloaded" << modelURL;
qCDebug(model_baking) << "Downloaded" << _modelURL;
// grab the contents of the reply and make a copy in the output folder
QFile copyOfOriginal(originalModelFilePath);
QFile copyOfOriginal(_originalModelFilePath);
qDebug(model_baking) << "Writing copy of original obj to" << originalModelFilePath << copyOfOriginal.fileName();
qDebug(model_baking) << "Writing copy of original obj to" << _originalModelFilePath << copyOfOriginal.fileName();
if (!copyOfOriginal.open(QIODevice::WriteOnly)) {
// add an error to the error list for this obj stating that a duplicate of the original obj could not be made
handleError("Could not create copy of " + modelURL.toString() + " (Failed to open " + originalModelFilePath + ")");
handleError("Could not create copy of " + _modelURL.toString() + " (Failed to open " + _originalModelFilePath + ")");
return;
}
if (copyOfOriginal.write(requestReply->readAll()) == -1) {
handleError("Could not create copy of " + modelURL.toString() + " (Failed to write)");
handleError("Could not create copy of " + _modelURL.toString() + " (Failed to write)");
return;
}
// close that file now that we are done writing to it
copyOfOriginal.close();
if (!originalOutputDir.isEmpty()) {
copyOfOriginal.copy(originalOutputDir + "/" + modelURL.fileName());
if (!_originalOutputDir.isEmpty()) {
copyOfOriginal.copy(_originalOutputDir + "/" + _modelURL.fileName());
}
// remote OBJ is loaded emit signal to trigger its baking
emit OBJLoaded();
} else {
// add an error to our list stating that the OBJ could not be downloaded
handleError("Failed to download " + modelURL.toString());
handleError("Failed to download " + _modelURL.toString());
}
}
void OBJBaker::bakeOBJ() {
// Read the OBJ file
QFile objFile(originalModelFilePath);
QFile objFile(_originalModelFilePath);
if (!objFile.open(QIODevice::ReadOnly)) {
handleError("Error opening " + originalModelFilePath + " for reading");
handleError("Error opening " + _originalModelFilePath + " for reading");
return;
}
@ -166,8 +142,8 @@ void OBJBaker::bakeOBJ() {
bool combineParts = true; // set true so that OBJReader reads material info from material library
OBJReader reader;
FBXGeometry* geometry = reader.readOBJ(objData, QVariantHash(), combineParts, modelURL);
FBXGeometry* geometry = reader.readOBJ(objData, QVariantHash(), combineParts, _modelURL);
// Write OBJ Data as FBX tree nodes
FBXNode rootNode;
createFBXNodeTree(rootNode, *geometry);
@ -176,25 +152,25 @@ void OBJBaker::bakeOBJ() {
auto encodedFBX = FBXWriter::encodeFBX(rootNode);
// Export as baked FBX
auto fileName = modelURL.fileName();
auto fileName = _modelURL.fileName();
auto baseName = fileName.left(fileName.lastIndexOf('.'));
auto bakedFilename = baseName + ".baked.fbx";
bakedModelFilePath = bakedOutputDir + "/" + bakedFilename;
_bakedModelFilePath = _bakedOutputDir + "/" + bakedFilename;
QFile bakedFile;
bakedFile.setFileName(bakedModelFilePath);
bakedFile.setFileName(_bakedModelFilePath);
if (!bakedFile.open(QIODevice::WriteOnly)) {
handleError("Error opening " + bakedModelFilePath + " for writing");
handleError("Error opening " + _bakedModelFilePath + " for writing");
return;
}
bakedFile.write(encodedFBX);
// Export successful
_outputFiles.push_back(bakedModelFilePath);
qCDebug(model_baking) << "Exported" << modelURL << "to" << bakedModelFilePath;
_outputFiles.push_back(_bakedModelFilePath);
qCDebug(model_baking) << "Exported" << _modelURL << "to" << _bakedModelFilePath;
// Export done emit finished
emit finished();
}
@ -208,7 +184,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
// Required for Unit Scale Factor
FBXNode globalSettingsNode;
globalSettingsNode.name = GLOBAL_SETTINGS_NODE_NAME;
// Setting the tree hierarchy: GlobalSettings -> Properties70 -> P -> Properties
FBXNode properties70Node;
properties70Node.name = PROPERTIES70_NODE_NAME;
@ -225,10 +201,10 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
FBXNode geometryNode;
geometryNode.name = GEOMETRY_NODE_NAME;
setNodeProperties(geometryNode);
// Compress the mesh information and store in dracoNode
bool hasDeformers = false; // No concept of deformers for an OBJ
FBXNode dracoNode;
FBXNode dracoNode;
this->compressMesh(geometry.meshes[0], hasDeformers, dracoNode);
geometryNode.children.append(dracoNode);
@ -236,12 +212,12 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
FBXNode modelNode;
modelNode.name = MODEL_NODE_NAME;
setNodeProperties(modelNode);
_objectNode.children = { geometryNode, modelNode };
// Generating Objects node's child - Material node
auto meshParts = geometry.meshes[0].parts;
for (auto meshPart : meshParts) {
auto& meshParts = geometry.meshes[0].parts;
for (auto& meshPart : meshParts) {
FBXNode materialNode;
materialNode.name = MATERIAL_NODE_NAME;
if (geometry.materials.size() == 1) {
@ -252,24 +228,24 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
} else {
setMaterialNodeProperties(materialNode, meshPart.materialID, geometry);
}
_objectNode.children.append(materialNode);
}
// Generating Texture Node
// iterate through mesh parts and process the associated textures
for (int i = 0;i < meshParts.size();i++) {
for (int i = 0; i < meshParts.size(); i++) {
QString material = meshParts[i].materialID;
FBXMaterial currentMaterial = geometry.materials[material];
if (!currentMaterial.albedoTexture.filename.isEmpty() || !currentMaterial.specularTexture.filename.isEmpty()) {
_textureID = _nodeID;
_mapTextureMaterial.push_back(QPair<qlonglong, int>(_textureID, i));
FBXNode textureNode;
textureNode.name = TEXTURE_NODE_NAME;
QVariant textureProperty(_nodeID++);
textureNode.properties = { textureProperty };
// Texture node child - TextureName node
FBXNode textureNameNode;
textureNameNode.name = TEXTURENAME_NODE_NAME;
@ -280,14 +256,14 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
// 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;
// Callback to get Texture content and type
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
QByteArray* textureFile = this->compressTexture(textureFileName, textureContentTypeCallback);
if (textureFile) {
@ -297,17 +273,17 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
return;
}
relativeFilenameNode.properties = { textureProperty };
textureNode.children = { textureNameNode, relativeFilenameNode };
_objectNode.children.append(textureNode);
}
}
// Generating Connections node
FBXNode connectionsNode;
connectionsNode.name = CONNECTIONS_NODE_NAME;
// connect Geometry to Model
FBXNode cNode;
cNode.name = C_NODE_NAME;
@ -321,7 +297,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
connectionsNode.children = { cNode };
// connect all materials to model
for (int i = 0;i < geometry.materials.size();i++) {
for (int i = 0; i < geometry.materials.size(); i++) {
FBXNode cNode1;
cNode1.name = C_NODE_NAME;
property0 = QVariant::fromValue(QByteArray(propertyString.data(), (int)propertyString.size()));
@ -330,10 +306,10 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
cNode1.properties = { property0, property1, property2 };
connectionsNode.children.append(cNode1);
}
// Connect textures to materials
auto mapSize = _mapTextureMaterial.size();
for (size_t i = 0;i < mapSize;i++) {
for (size_t i = 0; i < mapSize; i++) {
FBXNode cNode2;
cNode2.name = C_NODE_NAME;
propertyString = CONNECTIONS_NODE_PROPERTY_1;
@ -357,7 +333,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
cNode3.properties = { property0, property1, property2, property3 };
connectionsNode.children.append(cNode3);
}
// Make all generated nodes children of rootNode
rootNode.children = { globalSettingsNode, _objectNode, connectionsNode };
}
@ -365,8 +341,8 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
// Set properties for P Node and Sub-Object nodes
void OBJBaker::setNodeProperties(FBXNode& parentNode) {
if (parentNode.name == P_NODE_NAME) {
std::vector<QByteArray> stringProperties{ "UnitScaleFactor", "double", "Number", "" };
std::vector<double> numericProperties{ UNIT_SCALE_FACTOR };
std::vector<QByteArray> stringProperties { "UnitScaleFactor", "double", "Number", "" };
std::vector<double> numericProperties { UNIT_SCALE_FACTOR };
setPropertiesList(stringProperties, numericProperties, parentNode.properties);
} else if (parentNode.name == GEOMETRY_NODE_NAME) {
@ -400,9 +376,9 @@ void OBJBaker::setMaterialNodeProperties(FBXNode& materialNode, QString material
QVariant property2 = QVariant::fromValue(QByteArray(propertyString.data(), (int)propertyString.size()));
materialNode.properties = { property0, property1, property2 };
FBXMaterial currentMaterial = geometry.materials[material];
// Setting the hierarchy: Material -> Properties70 -> P -> Properties
FBXNode properties70Node;
properties70Node.name = PROPERTIES70_NODE_NAME;
@ -411,8 +387,8 @@ void OBJBaker::setMaterialNodeProperties(FBXNode& materialNode, QString material
FBXNode pNodeDiffuseColor;
pNodeDiffuseColor.name = P_NODE_NAME;
std::vector<QByteArray> stringProperties{ "DiffuseColor", "Color", "", "A" };
std::vector<double> numericProperties{ currentMaterial.diffuseColor[0], currentMaterial.diffuseColor[1], currentMaterial.diffuseColor[2] };
std::vector<QByteArray> stringProperties { "DiffuseColor", "Color", "", "A" };
std::vector<double> numericProperties { currentMaterial.diffuseColor[0], currentMaterial.diffuseColor[1], currentMaterial.diffuseColor[2] };
setPropertiesList(stringProperties, numericProperties, pNodeDiffuseColor.properties);
properties70Node.children.append(pNodeDiffuseColor);
@ -434,7 +410,7 @@ void OBJBaker::setMaterialNodeProperties(FBXNode& materialNode, QString material
stringProperties = { "Shininess", "Number", "", "A" };
numericProperties = { currentMaterial.shininess };
setPropertiesList(stringProperties, numericProperties, pNodeShininess.properties);
properties70Node.children.append(pNodeShininess);
// Set Opacity

View file

@ -25,7 +25,6 @@ class OBJBaker : public ModelBaker {
public:
OBJBaker(const QUrl& objURL, TextureBakerThreadGetter textureThreadGetter,
const QString& bakedOutputDir, const QString& originalOutputDir = "");
~OBJBaker() override;
void loadOBJ();
void createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry);
void setNodeProperties(FBXNode& parentNode);