From 099738e54589d14cfaf9bc4d8dd094e38f0c8ea7 Mon Sep 17 00:00:00 2001 From: Philip Rideout Date: Thu, 23 Aug 2018 12:46:45 -0700 Subject: [PATCH] Try to clean up asset folders for sample apps. (#128) * Try to clean up asset folders for sample apps. This removes the build step where we copy a subset of assets, and makes it so that FilamentApp hands out a "root path" for assets. For now this is determined based on the location of the executable. This allows developers to launch samples from any CWD. Closes #11 * Restore asset copy to build. --- libs/filagui/include/filagui/ImGuiHelper.h | 4 +++- libs/filagui/src/ImGuiHelper.cpp | 11 +++++------ libs/utils/include/utils/Path.h | 6 ++++++ libs/utils/src/Path.cpp | 8 ++++++++ samples/CMakeLists.txt | 13 +++++++++++++ samples/app/FilamentApp.cpp | 3 ++- samples/app/FilamentApp.h | 9 +++++++++ samples/vk_hellopbr.cpp | 8 ++++---- samples/vk_shadowtest.cpp | 8 ++++---- samples/vk_texturedquad.cpp | 5 ++--- 10 files changed, 56 insertions(+), 19 deletions(-) diff --git a/libs/filagui/include/filagui/ImGuiHelper.h b/libs/filagui/include/filagui/ImGuiHelper.h index a0f47a72bc..022773822d 100644 --- a/libs/filagui/include/filagui/ImGuiHelper.h +++ b/libs/filagui/include/filagui/ImGuiHelper.h @@ -28,6 +28,8 @@ #include #include +#include + struct ImDrawData; namespace filagui { @@ -42,7 +44,7 @@ public: using Callback = std::function; // The constructor creates its own Scene and places it in the given View. - ImGuiHelper(filament::Engine* engine, filament::View* view); + ImGuiHelper(filament::Engine* engine, filament::View* view, const utils::Path& fontPath); ~ImGuiHelper(); // Informs ImGui of the current display size, as well as the pixel ratio for high DPI displays. diff --git a/libs/filagui/src/ImGuiHelper.cpp b/libs/filagui/src/ImGuiHelper.cpp index 86d75d3eb8..703a9a36ca 100644 --- a/libs/filagui/src/ImGuiHelper.cpp +++ b/libs/filagui/src/ImGuiHelper.cpp @@ -31,7 +31,6 @@ #include #include #include -#include using namespace math; using namespace filament; @@ -43,14 +42,14 @@ static const uint8_t UI_BLIT_PACKAGE[] = { #include "generated/material/uiBlit.inc" }; -ImGuiHelper::ImGuiHelper(Engine* engine, filament::View* view) : mEngine(engine), mView(view) { +ImGuiHelper::ImGuiHelper(Engine* engine, filament::View* view, const Path& fontPath) : + mEngine(engine), mView(view) { ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); - // Try loading Roboto from assets/fonts (relative to the executable). If this fails, ImGui - // will silently fall back to proggy. - std::string fpath = Path::getCurrentExecutable().getParent() + "assets/fonts/Roboto-Medium.ttf"; - io.Fonts->AddFontFromFileTTF(fpath.c_str(), 16.0f); + // If the given font path is invalid, ImGui will silently fall back to proggy, which is a + // tiny "pixel art" texture that is compiled into the library. + io.Fonts->AddFontFromFileTTF(fontPath.c_str(), 16.0f); // Create the grayscale texture that ImGui uses for its glyph atlas. static unsigned char* pixels; diff --git a/libs/utils/include/utils/Path.h b/libs/utils/include/utils/Path.h index 9fe5d68706..2107918272 100644 --- a/libs/utils/include/utils/Path.h +++ b/libs/utils/include/utils/Path.h @@ -108,6 +108,12 @@ public: */ Path getParent() const; + /** + * Returns ancestor path where "0" is the immediate parent. + * @return a new path containing the ancestor of this path + */ + Path getAncestor(int n) const; + /** * Returns the name of the file or directory represented by * this abstract pathname. diff --git a/libs/utils/src/Path.cpp b/libs/utils/src/Path.cpp index d8e5f3b343..07f53e7cc2 100644 --- a/libs/utils/src/Path.cpp +++ b/libs/utils/src/Path.cpp @@ -131,6 +131,14 @@ Path Path::getParent() const { return getCanonicalPath(result); } +Path Path::getAncestor(int n) const { + Path result = getParent(); + while (n--) { + result = result.getParent(); + } + return result; +} + std::string Path::getName() const { if (isEmpty()) return ""; diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 949c57b5b2..726cdf534c 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -191,6 +191,15 @@ endif() # ================================================================================================== # Copy Assets +# +# This creates a structure like: +# +# /lightbulb (etc) sample app executable +# /assets/fonts copied from REPO/assets +# /assets/models copied from REPO/assets +# /textures copied from REPO/third_party +# /envs copied from REPO/samples/envs +# # ================================================================================================== file(COPY ../third_party/textures DESTINATION ${PROJECT_BINARY_DIR}) @@ -202,3 +211,7 @@ file(COPY ../assets DESTINATION ${PROJECT_BINARY_DIR} PATTERN "environments" EXCLUDE) add_custom_target(assets ALL DEPENDS assets) add_dependencies(filament assets) + +file(COPY ../samples/envs DESTINATION ${PROJECT_BINARY_DIR}) +add_custom_target(envs ALL DEPENDS envs) +add_dependencies(filament envs) diff --git a/samples/app/FilamentApp.cpp b/samples/app/FilamentApp.cpp index 0d3a9d68fb..daaa2dcf20 100644 --- a/samples/app/FilamentApp.cpp +++ b/samples/app/FilamentApp.cpp @@ -155,7 +155,8 @@ void FilamentApp::run(const Config& config,SetupCallback setupCallback, setupCallback(mEngine, window->mMainView->getView(), mScene); if (imguiCallback) { - mImGuiHelper = std::make_unique(mEngine, window->mUiView->getView()); + mImGuiHelper = std::make_unique(mEngine, window->mUiView->getView(), + getRootPath() + "assets/fonts/Roboto-Medium.ttf"); ImGuiIO& io = ImGui::GetIO(); #ifdef WIN32 SDL_SysWMinfo wmInfo; diff --git a/samples/app/FilamentApp.h b/samples/app/FilamentApp.h index bd57a456f6..8db7c0acab 100644 --- a/samples/app/FilamentApp.h +++ b/samples/app/FilamentApp.h @@ -27,6 +27,8 @@ #include #include +#include + #include "CameraManipulator.h" #include "Config.h" #include "IBL.h" @@ -77,6 +79,13 @@ public: FilamentApp& operator=(const FilamentApp& rhs) = delete; FilamentApp& operator=(FilamentApp&& rhs) = delete; + // Returns the path to the Filament root for loading assets. This is determined from the + // executable folder, which allows users to launch samples from any folder. + static const utils::Path& getRootPath() { + static const utils::Path root = utils::Path::getCurrentExecutable().getParent(); + return root; + } + private: FilamentApp(); diff --git a/samples/vk_hellopbr.cpp b/samples/vk_hellopbr.cpp index 5fa93b88f5..66e3f23f75 100644 --- a/samples/vk_hellopbr.cpp +++ b/samples/vk_hellopbr.cpp @@ -36,14 +36,14 @@ struct App { mat4f transform; }; -static const char* MODEL_FILE = "samples/assets/models/monkey/monkey.obj"; -static const char* IBL_FOLDER = "../samples/envs/office"; +static const char* MODEL_FILE = "assets/models/monkey/monkey.obj"; +static const char* IBL_FOLDER = "envs/office"; int main(int argc, char** argv) { Config config; config.title = "hellopbr"; config.backend = Backend::VULKAN; - config.iblDirectory = IBL_FOLDER; + config.iblDirectory = FilamentApp::getRootPath() + IBL_FOLDER; App app; auto setup = [config, &app](Engine* engine, View* view, Scene* scene) { @@ -53,7 +53,7 @@ int main(int argc, char** argv) { // Add geometry into the scene. app.meshes = new MeshAssimp(*engine); - app.meshes->addFromFile(MODEL_FILE, app.materials); + app.meshes->addFromFile(FilamentApp::getRootPath() + MODEL_FILE, app.materials); auto ti = tcm.getInstance(app.meshes->getRenderables()[0]); app.transform = mat4f{ mat3f(1), float3(0, 0, -4) } * tcm.getWorldTransform(ti); for (auto renderable : app.meshes->getRenderables()) { diff --git a/samples/vk_shadowtest.cpp b/samples/vk_shadowtest.cpp index dfeb3dd922..c0de64fb7a 100644 --- a/samples/vk_shadowtest.cpp +++ b/samples/vk_shadowtest.cpp @@ -47,8 +47,8 @@ struct App { GroundPlane plane; }; -static const char* MODEL_FILE = "samples/assets/models/monkey/monkey.obj"; -static const char* IBL_FOLDER = "../samples/envs/office"; +static const char* MODEL_FILE = "assets/models/monkey/monkey.obj"; +static const char* IBL_FOLDER = "envs/office"; static constexpr bool ENABLE_SHADOWS = true; static constexpr uint8_t GROUND_SHADOW_PACKAGE[] = { @@ -59,7 +59,7 @@ static GroundPlane createGroundPlane(Engine* engine); static const Config config { .title = "shadowtest", - .iblDirectory = IBL_FOLDER, + .iblDirectory = FilamentApp::getRootPath() + IBL_FOLDER, .scale = 1, .splitView = false, .backend = Backend::VULKAN, @@ -75,7 +75,7 @@ int main(int argc, char** argv) { // Add geometry into the scene. app.meshes = new MeshAssimp(*engine); - app.meshes->addFromFile(MODEL_FILE, app.materials); + app.meshes->addFromFile(FilamentApp::getRootPath() + MODEL_FILE, app.materials); auto ti = tcm.getInstance(app.meshes->getRenderables()[0]); app.transform = mat4f{ mat3f(1), float3(0, 0, -4) } * tcm.getWorldTransform(ti); for (auto renderable : app.meshes->getRenderables()) { diff --git a/samples/vk_texturedquad.cpp b/samples/vk_texturedquad.cpp index 36e2785517..39820f4ff8 100644 --- a/samples/vk_texturedquad.cpp +++ b/samples/vk_texturedquad.cpp @@ -81,14 +81,13 @@ int main() { auto setup = [&app](Engine* engine, View* view, Scene* scene) { // Load texture - Path path = Path::getCurrentExecutable().getParent() + - "textures/Moss_01/Moss_01_Color.png"; + Path path = FilamentApp::getRootPath() + "third_party/textures/Moss_01/Moss_01_Color.png"; if (!path.exists()) { std::cerr << "The texture " << path << " does not exist" << std::endl; exit(1); } int w, h, n; - unsigned char* data = stbi_load(path.getAbsolutePath().c_str(), &w, &h, &n, 4); + unsigned char* data = stbi_load(path.c_str(), &w, &h, &n, 4); if (data == nullptr) { std::cerr << "The texture " << path << " could not be loaded" << std::endl; exit(1);