mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-08 08:22:09 +02:00
add basic Oven QCoreApplication, start to output results
This commit is contained in:
parent
711938fb3d
commit
1b30afa03e
6 changed files with 182 additions and 28 deletions
|
@ -2,6 +2,8 @@ set(TARGET_NAME model-baking)
|
|||
|
||||
setup_hifi_library()
|
||||
|
||||
link_hifi_libraries(networking)
|
||||
|
||||
find_package(FBXSDK REQUIRED)
|
||||
target_link_libraries(${TARGET_NAME} ${FBX_LIBRARIES})
|
||||
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${FBX_INCLUDE_DIR})
|
||||
|
|
|
@ -10,33 +10,117 @@
|
|||
//
|
||||
|
||||
#include <fbxsdk.h>
|
||||
#include <fbxsdk/scene/shading/fbxlayeredtexture.h>
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QThread>
|
||||
|
||||
#include <NetworkAccessManager.h>
|
||||
|
||||
#include "FBXBaker.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(model_baking, "hifi.model-baking");
|
||||
|
||||
FBXBaker::FBXBaker(QUrl fbxPath) :
|
||||
_fbxPath(fbxPath)
|
||||
FBXBaker::FBXBaker(QUrl fbxURL, QString baseOutputPath) :
|
||||
_fbxURL(fbxURL),
|
||||
_baseOutputPath(baseOutputPath)
|
||||
{
|
||||
// create an FBX SDK manager
|
||||
_sdkManager = FbxManager::Create();
|
||||
|
||||
// grab the name of the FBX from the URL, this is used for folder output names
|
||||
auto fileName = fbxURL.fileName();
|
||||
_fbxName = fileName.left(fileName.indexOf('.'));
|
||||
}
|
||||
|
||||
FBXBaker::~FBXBaker() {
|
||||
_sdkManager->Destroy();
|
||||
}
|
||||
|
||||
|
||||
void FBXBaker::start() {
|
||||
// setup the output folder for the results of this bake
|
||||
if (!setupOutputFolder()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check if the FBX is local or first needs to be downloaded
|
||||
if (_fbxPath.isLocalFile()) {
|
||||
// local file, bake now
|
||||
if (_fbxURL.isLocalFile()) {
|
||||
// load up the local file
|
||||
QFile localFBX { _fbxURL.toLocalFile() };
|
||||
|
||||
// make a copy in the output folder
|
||||
localFBX.copy(_uniqueOutputPath + _fbxURL.fileName());
|
||||
|
||||
// start the bake now that we have everything in place
|
||||
bake();
|
||||
} else {
|
||||
// remote file, kick off a download
|
||||
auto& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
|
||||
QNetworkRequest networkRequest;
|
||||
|
||||
// setup the request to follow re-directs and always hit the network
|
||||
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
networkRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
|
||||
|
||||
networkRequest.setUrl(_fbxURL);
|
||||
|
||||
qCDebug(model_baking) << "Downloading" << _fbxURL;
|
||||
|
||||
auto networkReply = networkAccessManager.get(networkRequest);
|
||||
connect(networkReply, &QNetworkReply::finished, this, &FBXBaker::handleFBXNetworkReply);
|
||||
}
|
||||
}
|
||||
|
||||
bool FBXBaker::setupOutputFolder() {
|
||||
// construct the output path using the name of the fbx and the base output path
|
||||
_uniqueOutputPath = _baseOutputPath + "/" + _fbxName + "/";
|
||||
|
||||
// make sure there isn't already an output directory using the same name
|
||||
int iteration = 0;
|
||||
|
||||
while (QDir(_uniqueOutputPath).exists()) {
|
||||
_uniqueOutputPath = _baseOutputPath + "/" + _fbxName + "-" + QString::number(++iteration) + "/";
|
||||
}
|
||||
|
||||
qCDebug(model_baking) << "Creating FBX output folder" << _uniqueOutputPath;
|
||||
|
||||
// attempt to make the output folder
|
||||
if (!QDir().mkdir(_uniqueOutputPath)) {
|
||||
qCWarning(model_baking) << "Failed to created FBX output folder" << _uniqueOutputPath;
|
||||
|
||||
emit finished();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FBXBaker::handleFBXNetworkReply() {
|
||||
QNetworkReply* requestReply = qobject_cast<QNetworkReply*>(sender());
|
||||
|
||||
if (requestReply->error() == QNetworkReply::NoError) {
|
||||
qCDebug(model_baking) << "Downloaded" << _fbxURL;
|
||||
|
||||
// grab the contents of the reply and make a copy in the output folder
|
||||
QFile copyOfOriginal(_uniqueOutputPath + _fbxURL.fileName());
|
||||
|
||||
qDebug(model_baking) << "Writing copy of original FBX to" << copyOfOriginal.fileName();
|
||||
|
||||
if (!copyOfOriginal.open(QIODevice::WriteOnly) || (copyOfOriginal.write(requestReply->readAll()) == -1)) {
|
||||
|
||||
// add an error to the error list for this FBX stating that a duplicate of the original could not be made
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
|
||||
// close that file now that we are done writing to it
|
||||
copyOfOriginal.close();
|
||||
|
||||
// kick off the bake process now that everything is ready to go
|
||||
bake();
|
||||
} else {
|
||||
qDebug() << "ERROR DOWNLOADING FBX" << requestReply->errorString();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,25 +130,31 @@ void FBXBaker::bake() {
|
|||
// (3) export the FBX with re-written texture references
|
||||
// (4) enumerate the collected texture paths and bake the textures
|
||||
|
||||
qCDebug(model_baking) << "Baking" << _fbxURL;
|
||||
|
||||
// a failure at any step along the way stops the chain
|
||||
importScene() && rewriteAndCollectSceneTextures() && exportScene() && bakeTextures();
|
||||
|
||||
// emit a signal saying that we are done, with whatever errors were produced
|
||||
emit finished(_errorList);
|
||||
emit finished();
|
||||
}
|
||||
|
||||
bool FBXBaker::importScene() {
|
||||
// create an FBX SDK importer
|
||||
FbxImporter* importer = FbxImporter::Create(_sdkManager, "");
|
||||
|
||||
// import the FBX file at the given path
|
||||
bool importStatus = importer->Initialize(_fbxPath.toLocalFile().toLocal8Bit().data());
|
||||
// import the copy of the original FBX file
|
||||
QString originalCopyPath = _uniqueOutputPath + _fbxURL.fileName();
|
||||
bool importStatus = importer->Initialize(originalCopyPath.toLocal8Bit().data());
|
||||
|
||||
if (!importStatus) {
|
||||
// failed to initialize importer, print an error and return
|
||||
qCDebug(model_baking) << "Failed to import FBX file at" << _fbxPath << "- error:" << importer->GetStatus().GetErrorString();
|
||||
qCCritical(model_baking) << "Failed to import FBX file at" << _fbxURL
|
||||
<< "- error:" << importer->GetStatus().GetErrorString();
|
||||
|
||||
return false;
|
||||
} else {
|
||||
qCDebug(model_baking) << "Imported" << _fbxURL << "to FbxScene";
|
||||
}
|
||||
|
||||
// setup a new scene to hold the imported file
|
||||
|
@ -82,8 +172,6 @@ bool FBXBaker::importScene() {
|
|||
static const QString BAKED_TEXTURE_DIRECTORY = "textures";
|
||||
static const QString BAKED_TEXTURE_EXT = ".ktx";
|
||||
|
||||
static const QString EXPORT_PATH { "/Users/birarda/code/hifi/lod/test-oven/export/DiscGolfBasket.ktx.fbx" };
|
||||
|
||||
bool FBXBaker::rewriteAndCollectSceneTextures() {
|
||||
// get a count of the textures used in the scene
|
||||
int numTextures = _scene->GetTextureCount();
|
||||
|
@ -102,7 +190,7 @@ bool FBXBaker::rewriteAndCollectSceneTextures() {
|
|||
|
||||
// construct the new baked texture file name and file path
|
||||
QString bakedTextureFileName { textureFileInfo.baseName() + BAKED_TEXTURE_EXT };
|
||||
QString bakedTextureFilePath { QFileInfo(EXPORT_PATH).absolutePath() + "/textures/" + bakedTextureFileName };
|
||||
QString bakedTextureFilePath { _uniqueOutputPath + "ktx/" + bakedTextureFileName };
|
||||
|
||||
qCDebug(model_baking).noquote() << "Re-mapping" << fileTexture->GetFileName() << "to" << bakedTextureFilePath;
|
||||
|
||||
|
@ -127,12 +215,13 @@ bool FBXBaker::exportScene() {
|
|||
// setup the exporter
|
||||
FbxExporter* exporter = FbxExporter::Create(_sdkManager, "");
|
||||
|
||||
bool exportStatus = exporter->Initialize(EXPORT_PATH.toLocal8Bit().data());
|
||||
auto rewrittenFBXPath = _uniqueOutputPath + _fbxName + ".ktx.fbx";
|
||||
bool exportStatus = exporter->Initialize(rewrittenFBXPath.toLocal8Bit().data());
|
||||
|
||||
if (!exportStatus) {
|
||||
// failed to initialize exporter, print an error and return
|
||||
qCDebug(model_baking) << "Failed to export FBX file at" << _fbxPath
|
||||
<< "to" << EXPORT_PATH << "- error:" << exporter->GetStatus().GetErrorString();
|
||||
qCCritical(model_baking) << "Failed to export FBX file at" << _fbxURL
|
||||
<< "to" << rewrittenFBXPath << "- error:" << exporter->GetStatus().GetErrorString();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -140,6 +229,8 @@ bool FBXBaker::exportScene() {
|
|||
// export the scene
|
||||
exporter->Export(_scene);
|
||||
|
||||
qCDebug(model_baking) << "Exported" << _fbxURL << "with re-written paths to" << rewrittenFBXPath;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
#ifndef hifi_FBXBaker_h
|
||||
#define hifi_FBXBaker_h
|
||||
|
||||
#include <QLoggingCategory>
|
||||
#include <QUrl>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(model_baking)
|
||||
|
||||
|
@ -27,23 +29,33 @@ namespace fbxsdk {
|
|||
class FBXBaker : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
FBXBaker(QUrl fbxPath);
|
||||
FBXBaker(QUrl fbxURL, QString baseOutputPath);
|
||||
~FBXBaker();
|
||||
|
||||
void start();
|
||||
|
||||
signals:
|
||||
void finished(QStringList errorList);
|
||||
void finished();
|
||||
|
||||
private slots:
|
||||
void handleFBXNetworkReply();
|
||||
|
||||
private:
|
||||
void bake();
|
||||
|
||||
bool setupOutputFolder();
|
||||
bool importScene();
|
||||
bool rewriteAndCollectSceneTextures();
|
||||
bool exportScene();
|
||||
bool bakeTextures();
|
||||
bool bakeTexture();
|
||||
|
||||
QUrl _fbxPath;
|
||||
QUrl _fbxURL;
|
||||
QString _fbxName;
|
||||
|
||||
QString _baseOutputPath;
|
||||
QString _uniqueOutputPath;
|
||||
|
||||
fbxsdk::FbxManager* _sdkManager;
|
||||
fbxsdk::FbxScene* _scene { nullptr };
|
||||
|
||||
|
|
23
tools/oven/src/Oven.cpp
Normal file
23
tools/oven/src/Oven.cpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// Oven.cpp
|
||||
// tools/oven/src
|
||||
//
|
||||
// Created by Stephen Birarda on 4/5/17.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#include "Oven.h"
|
||||
|
||||
static const QString OUTPUT_FOLDER = "/Users/birarda/code/hifi/lod/test-oven/export";
|
||||
|
||||
Oven::Oven(int argc, char* argv[]) :
|
||||
QCoreApplication(argc, argv),
|
||||
_testBake(QUrl("file:///Users/birarda/code/hifi/lod/test-oven/DiscGolfBasket.fbx"), OUTPUT_FOLDER)
|
||||
{
|
||||
_testBake.start();
|
||||
}
|
30
tools/oven/src/Oven.h
Normal file
30
tools/oven/src/Oven.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// Oven.h
|
||||
// tools/oven/src
|
||||
//
|
||||
// Created by Stephen Birarda on 4/5/17.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_Oven_h
|
||||
#define hifi_Oven_h
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
|
||||
#include <FBXBaker.h>
|
||||
|
||||
class Oven : public QCoreApplication {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Oven(int argc, char* argv[]);
|
||||
|
||||
private:
|
||||
FBXBaker _testBake;
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Oven_h
|
|
@ -8,13 +8,9 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
#include <FBXBaker.h>
|
||||
|
||||
#include "Oven.h"
|
||||
|
||||
int main (int argc, char** argv) {
|
||||
|
||||
FBXBaker baker(QUrl("file:///Users/birarda/code/hifi/lod/test-oven/DiscGolfBasket.fbx"));
|
||||
baker.start();
|
||||
|
||||
return 0;
|
||||
Oven app(argc, argv);
|
||||
return app.exec();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue