diff --git a/CHANGELOG.md b/CHANGELOG.md index 64c486c9..e90812ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- multibody/RobotScene : move `invalid_enum()` back to cpp file - multibody/RobotScene : always render to G-buffer normal map - core: move header `LoadCoalGeometries.h` and its functions to library core - multibody/Visualizer : rename a data member in Config @@ -34,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed +- Remove deprecated header `candlewick/core/Renderer.h` - Remove deprecated header `candlewick/multibody/LoadCoalPrimitives.h` ## [0.9.0] - 2025-08-12 diff --git a/CMakeLists.txt b/CMakeLists.txt index 458418d0..ccabc4bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,13 +95,7 @@ ADD_PROJECT_DEPENDENCY(coal REQUIRED PKG_CONFIG_REQUIRES "coal >= 3.0.0") ADD_PROJECT_DEPENDENCY(nlohmann_json 3.11.3 REQUIRED) ADD_PROJECT_DEPENDENCY(EnTT REQUIRED) ADD_PROJECT_DEPENDENCY(magic_enum 0.9.7 CONFIG REQUIRED) -if(BUILD_PINOCCHIO_VISUALIZER) - ADD_PROJECT_DEPENDENCY( - pinocchio - REQUIRED - PKG_CONFIG_REQUIRES "pinocchio >= 3.7.0" - ) -endif() +ADD_PROJECT_DEPENDENCY(spdlog 1.10 REQUIRED) ADD_PROJECT_DEPENDENCY( FFmpeg 7.0.0 @@ -110,6 +104,14 @@ ADD_PROJECT_DEPENDENCY( avcodec swscale ) +if(BUILD_PINOCCHIO_VISUALIZER) + ADD_PROJECT_DEPENDENCY( + pinocchio + REQUIRED + PKG_CONFIG_REQUIRES "pinocchio >= 3.7.0" + ) +endif() + set(CANDLEWICK_ASSETS_DIR ${PROJECT_SOURCE_DIR}/assets) set(CANDLEWICK_SHADER_SRC_DIR ${PROJECT_SOURCE_DIR}/shaders) set( diff --git a/README.md b/README.md index d4c55b89..8c9e066c 100644 --- a/README.md +++ b/README.md @@ -96,10 +96,11 @@ Candlewick depends mainly on: * [Eigen](https://gitlab.com/libeigen/eigen/) - Linear algebra * [Coal](https://github.com/coal-library/coal) - Collision detection, geometry primitives * [magic_enum](https://github.com/Neargye/magic_enum) - Enum reflection utilities +* [spdlog](https://github.com/gabime/spdlog/) - Logging These dependencies can be installed from Conda as follows: ```bash -conda install -c conda-forge sdl3 eigen coal magic_enum assimp entt nlohmann_json +conda install -c conda-forge sdl3 eigen coal magic_enum assimp entt nlohmann_json spdlog ``` Additionally, candlewick depends on the following bundled dependencies: diff --git a/examples/Ur5WithSystems.cpp b/examples/Ur5WithSystems.cpp index 778e8c6d..05a7dceb 100644 --- a/examples/Ur5WithSystems.cpp +++ b/examples/Ur5WithSystems.cpp @@ -118,7 +118,7 @@ void eventLoop(const RenderContext &renderer) { ImGui_ImplSDL3_ProcessEvent(&event); ImGuiIO &io = ImGui::GetIO(); if (event.type == SDL_EVENT_QUIT) { - SDL_Log("Application exit requested."); + spdlog::info("Application exit requested."); quitRequested = true; break; } @@ -202,11 +202,11 @@ static void addTeapotGeometry(pin::GeometryModel &geom_model) { static void screenshotButtonCallback(const RenderContext &renderer, media::TransferBufferPool &pool, - const char *filename) { + std::string_view filename) { const auto &device = renderer.device; CommandBuffer command_buffer{device}; - SDL_Log("Saving screenshot at %s", filename); + spdlog::info("Saving screenshot at {:s}", filename); media::saveTextureToFile(command_buffer, device, pool, renderer.resolvedColorTarget(), renderer.colorFormat(), wWidth, wHeight, filename); @@ -319,7 +319,7 @@ int main(int argc, char **argv) { const size_t numRobotShapes = registry.view().size(); SDL_assert(numRobotShapes == geom_model.ngeoms); - SDL_Log("Registered %zu robot geometry objects.", numRobotShapes); + spdlog::info("Registered {:d} robot geometry objects.", numRobotShapes); // DEBUG SYSTEM @@ -539,7 +539,7 @@ int main(int argc, char **argv) { } gui_system.render(command_buffer); } else { - SDL_Log("Failed to acquire swapchain: %s", SDL_GetError()); + spdlog::info("Failed to acquire swapchain: {:s}", SDL_GetError()); continue; } diff --git a/examples/Visualizer.cpp b/examples/Visualizer.cpp index c4ecf6b0..3e83f6c0 100644 --- a/examples/Visualizer.cpp +++ b/examples/Visualizer.cpp @@ -9,6 +9,8 @@ #include #include +#include + using namespace candlewick::multibody; using candlewick::sdlSampleToValue; using pinocchio::visualizers::Vector3; @@ -40,7 +42,7 @@ static void addBall(pin::GeometryModel &geom_model) { geom_model.addGeometryObject(object); } -int main(int argc, char **argv) { +int main(int argc, char *argv[]) { CLI::App app{"Visualizer example"}; argv = app.ensure_utf8(argv); std::array window_dims{1920u, 1080u}; @@ -67,6 +69,9 @@ int main(int argc, char **argv) { CLI11_PARSE(app, argc, argv); + spdlog::cfg::load_env_levels(); + spdlog::set_pattern(">>> [%T] [%^%l%$] %v"); + spdlog::info("Robot spec:\n{}", ur_robot_spec); pin::Model model; pin::GeometryModel geom_model; loadModels(ur_robot_spec, model, &geom_model, NULL); diff --git a/examples/lib/Common.cpp b/examples/lib/Common.cpp index fbfd821c..da3d4d86 100644 --- a/examples/lib/Common.cpp +++ b/examples/lib/Common.cpp @@ -4,7 +4,6 @@ #include "Common.h" #include -#include using namespace candlewick; diff --git a/pixi.lock b/pixi.lock index a2d3d9bd..2fd570cb 100644 --- a/pixi.lock +++ b/pixi.lock @@ -26,6 +26,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-3.4.0-h00ab1b0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/eigenpy-3.11.0-np2py313h6b12d9a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/entt-3.15.0-h84d6215_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-11.2.0-h07f6e7f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.3.0-h76bdaa0_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-14.3.0-hd9e9e21_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-14.3.0-h1382650_11.conda @@ -124,6 +125,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.16.1-py313h3a520b0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl3-3.2.20-h68140b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.15.3-h6dc744f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda @@ -165,6 +167,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/eigen-3.4.0-h1c7c39f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/eigenpy-3.11.0-np2py313hdf23dc2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/entt-3.15.0-h9275861_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/fmt-11.2.0-hbf61d64_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-75.1-h120a0e1_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.3-h37d8d59_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-954.16-hc3792c1_1.conda @@ -224,6 +227,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.16.1-py313hada7951_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sdl3-3.2.20-hc0b302d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/spdlog-1.15.3-hcdbecca_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1300.6.5-h390ca13_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hf689a15_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda @@ -255,6 +259,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigen-3.4.0-h1995070_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigenpy-3.11.0-np2py313hfd44af5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/entt-3.15.0-h2c4a281_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-11.2.0-h440487c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-954.16-he86490a_1.conda @@ -314,6 +319,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.16.1-py313h74efe86_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sdl3-3.2.20-he22eeb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/spdlog-1.15.3-h217a1f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1300.6.5-h03f4b80_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda @@ -346,6 +352,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-3.4.0-h00ab1b0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/eigenpy-3.11.0-np2py313h6b12d9a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/entt-3.15.0-h84d6215_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-11.2.0-h07f6e7f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.3.0-h76bdaa0_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-14.3.0-hd9e9e21_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-14.3.0-h1382650_11.conda @@ -444,6 +451,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.16.1-py313h3a520b0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl3-3.2.20-h68140b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.15.3-h6dc744f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda @@ -486,6 +494,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/eigen-3.4.0-h1c7c39f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/eigenpy-3.11.0-np2py313hdf23dc2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/entt-3.15.0-h9275861_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/fmt-11.2.0-hbf61d64_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-75.1-h120a0e1_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.3-h37d8d59_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-954.16-hc3792c1_1.conda @@ -545,6 +554,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.16.1-py313hada7951_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sdl3-3.2.20-hc0b302d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/spdlog-1.15.3-hcdbecca_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1300.6.5-h390ca13_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hf689a15_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda @@ -577,6 +587,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigen-3.4.0-h1995070_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigenpy-3.11.0-np2py313hfd44af5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/entt-3.15.0-h2c4a281_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-11.2.0-h440487c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-954.16-he86490a_1.conda @@ -636,6 +647,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.16.1-py313h74efe86_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sdl3-3.2.20-he22eeb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/spdlog-1.15.3-h217a1f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1300.6.5-h03f4b80_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda @@ -679,6 +691,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/elfutils-0.193-h849f50c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/entt-3.15.0-h84d6215_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ffmpeg-7.1.1-gpl_hea4b676_907.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-11.2.0-h07f6e7f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 @@ -862,6 +875,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl2-2.32.54-h3f2d84a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl3-3.2.20-h68140b3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.15.3-h6dc744f_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/svt-av1-3.0.2-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-2022.1.0-h4ce085d_0.conda @@ -928,6 +942,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/eigenpy-3.11.0-np2py312h4e684d9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/entt-3.15.0-h9275861_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ffmpeg-7.1.1-gpl_h731c141_107.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/fmt-11.2.0-hbf61d64_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 @@ -1064,6 +1079,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/sdl3-3.2.20-hc0b302d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.2.2-h25c286d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/spdlog-1.15.3-hcdbecca_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/svt-av1-3.0.2-h240833e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1300.6.5-h390ca13_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tbb-2022.2.0-hc025b3e_0.conda @@ -1113,6 +1129,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigenpy-3.11.0-np2py313hfd44af5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/entt-3.15.0-h2c4a281_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ffmpeg-7.1.1-gpl_hf33b5e2_107.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-11.2.0-h440487c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 @@ -1249,6 +1266,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sdl3-3.2.20-he22eeb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.2-hd121638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/spdlog-1.15.3-h217a1f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/svt-av1-3.0.2-h8ab69cd_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1300.6.5-h03f4b80_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tbb-2022.2.0-h5b2e6d4_0.conda @@ -1289,6 +1307,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-3.4.0-h00ab1b0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/eigenpy-3.11.0-np2py313h6b12d9a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/entt-3.15.0-h84d6215_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-11.2.0-h07f6e7f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.3.0-h76bdaa0_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-14.3.0-hd9e9e21_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-14.3.0-h1382650_11.conda @@ -1388,6 +1407,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.16.1-py313h3a520b0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl3-3.2.20-h68140b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.15.3-h6dc744f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda @@ -1429,6 +1449,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/eigen-3.4.0-h1c7c39f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/eigenpy-3.11.0-np2py313hdf23dc2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/entt-3.15.0-h9275861_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/fmt-11.2.0-hbf61d64_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gtest-1.17.0-h9275861_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-75.1-h120a0e1_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.3-h37d8d59_0.conda @@ -1489,6 +1510,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.16.1-py313hada7951_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sdl3-3.2.20-hc0b302d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/spdlog-1.15.3-hcdbecca_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1300.6.5-h390ca13_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hf689a15_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda @@ -1520,6 +1542,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigen-3.4.0-h1995070_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigenpy-3.11.0-np2py313hfd44af5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/entt-3.15.0-h2c4a281_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-11.2.0-h440487c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gtest-1.17.0-ha393de7_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda @@ -1580,6 +1603,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.16.1-py313h74efe86_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sdl3-3.2.20-he22eeb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/spdlog-1.15.3-h217a1f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1300.6.5-h03f4b80_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda @@ -1623,6 +1647,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/elfutils-0.193-h849f50c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/entt-3.15.0-h84d6215_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ffmpeg-7.1.1-gpl_hea4b676_907.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-11.2.0-h07f6e7f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 @@ -1807,6 +1832,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl2-2.32.54-h3f2d84a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl3-3.2.20-h68140b3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.15.3-h6dc744f_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/svt-av1-3.0.2-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-2022.1.0-h4ce085d_0.conda @@ -1873,6 +1899,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/eigenpy-3.11.0-np2py312h4e684d9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/entt-3.15.0-h9275861_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ffmpeg-7.1.1-gpl_h731c141_107.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/fmt-11.2.0-hbf61d64_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 @@ -2010,6 +2037,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/sdl3-3.2.20-hc0b302d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.2.2-h25c286d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/spdlog-1.15.3-hcdbecca_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/svt-av1-3.0.2-h240833e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1300.6.5-h390ca13_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tbb-2022.2.0-hc025b3e_0.conda @@ -2059,6 +2087,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigenpy-3.11.0-np2py313hfd44af5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/entt-3.15.0-h2c4a281_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ffmpeg-7.1.1-gpl_hf33b5e2_107.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-11.2.0-h440487c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 @@ -2196,6 +2225,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sdl3-3.2.20-he22eeb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.2-hd121638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/spdlog-1.15.3-h217a1f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/svt-av1-3.0.2-h8ab69cd_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1300.6.5-h03f4b80_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tbb-2022.2.0-h5b2e6d4_0.conda @@ -2242,6 +2272,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/eigenpy-3.11.0-np2py313h6b12d9a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/elfutils-0.193-h849f50c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/entt-3.15.0-h84d6215_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-11.2.0-h07f6e7f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.3.0-h76bdaa0_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-14.3.0-hd9e9e21_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-14.3.0-h1382650_11.conda @@ -2374,6 +2405,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ruby-3.4.5-hd8161a3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.16.1-py313h3a520b0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl3-3.2.20-h68140b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.15.3-h6dc744f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tinyxml2-11.0.0-h3f2d84a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda @@ -2427,6 +2459,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/eigen-3.4.0-h1c7c39f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/eigenpy-3.11.0-np2py312h4e684d9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/entt-3.15.0-h9275861_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/fmt-11.2.0-hbf61d64_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gdbm-1.18-h8a0c380_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/gettext-0.25.1-he52a196_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gettext-tools-0.25.1-h3184127_1.conda @@ -2513,6 +2546,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.16.1-py312h594e5de_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sdl3-3.2.20-hc0b302d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/spdlog-1.15.3-hcdbecca_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1300.6.5-h390ca13_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tinyxml2-11.0.0-h92383a6_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hf689a15_2.conda @@ -2552,6 +2586,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigen-3.4.0-h1995070_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigenpy-3.11.0-np2py313hfd44af5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/entt-3.15.0-h2c4a281_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-11.2.0-h440487c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gettext-0.25.1-h3dcc1bd_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gettext-tools-0.25.1-h493aca8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gmp-6.3.0-h7bae524_2.conda @@ -2638,6 +2673,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.16.1-py313h74efe86_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sdl3-3.2.20-he22eeb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/spdlog-1.15.3-h217a1f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1300.6.5-h03f4b80_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tinyxml2-11.0.0-ha1acc90_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_2.conda @@ -4179,6 +4215,37 @@ packages: license_family: GPL size: 9176237 timestamp: 1753273202884 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-11.2.0-h07f6e7f_0.conda + sha256: e0f53b7801d0bcb5d61a1ddcb873479bfe8365e56fd3722a232fbcc372a9ac52 + md5: 0c2f855a88fab6afa92a7aa41217dc8e + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libstdcxx >=13 + license: MIT + license_family: MIT + size: 192721 + timestamp: 1751277120358 +- conda: https://conda.anaconda.org/conda-forge/osx-64/fmt-11.2.0-hbf61d64_0.conda + sha256: ba1b1187d6e6ed32a6da0ff4c46658168c16b7dfa1805768d3f347e0c306b804 + md5: 1883d88d80cb91497b7c2e4f69f2e5e3 + depends: + - __osx >=10.13 + - libcxx >=18 + license: MIT + license_family: MIT + size: 184106 + timestamp: 1751277237783 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-11.2.0-h440487c_0.conda + sha256: 1449ec46468860f6fb77edba87797ce22d4f6bfe8d5587c46fd5374c4f7383ee + md5: 24109723ac700cce5ff96ea3e63a83a3 + depends: + - __osx >=11.0 + - libcxx >=18 + license: MIT + license_family: MIT + size: 177090 + timestamp: 1751277262419 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b md5: 0c96522c6bdaed4b1566d11387caaf45 @@ -9716,6 +9783,40 @@ packages: license_family: BSD size: 38824 timestamp: 1753083462800 +- conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.15.3-h6dc744f_1.conda + sha256: e5ddcc73dac4c138b763aab4feace6101bdccf39ea4cf599705c9625c70beba0 + md5: ffeb70e2cedafa9243bf89a20ada4cfe + depends: + - __glibc >=2.17,<3.0.a0 + - fmt >=11.2.0,<11.3.0a0 + - libgcc >=13 + - libstdcxx >=13 + license: MIT + license_family: MIT + size: 195618 + timestamp: 1751348678073 +- conda: https://conda.anaconda.org/conda-forge/osx-64/spdlog-1.15.3-hcdbecca_1.conda + sha256: 9f06f687695cf119e85e0d68d337a94d4691fd58427a9fed764a97c1d87ccf69 + md5: 1bbfab208c5597f3f15e6bb0bb9381c2 + depends: + - __osx >=10.13 + - fmt >=11.2.0,<11.3.0a0 + - libcxx >=18 + license: MIT + license_family: MIT + size: 172909 + timestamp: 1751349142758 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/spdlog-1.15.3-h217a1f9_1.conda + sha256: 673e4475bc9ca8e321bc98c8f6e48bf0efd530b5978d6a675de03c77b0a41227 + md5: bd3f40ea227bed3b00b13a574a9dd9ee + depends: + - __osx >=11.0 + - fmt >=11.2.0,<11.3.0a0 + - libcxx >=18 + license: MIT + license_family: MIT + size: 166201 + timestamp: 1751348813679 - conda: https://conda.anaconda.org/conda-forge/linux-64/svt-av1-3.0.2-h5888daf_0.conda sha256: fb4b97a3fd259eff4849b2cfe5678ced0c5792b697eb1f7bcd93a4230e90e80e md5: 0096882bd623e6cc09e8bf920fc8fb47 diff --git a/pixi.toml b/pixi.toml index 53d96e0b..c4e8114a 100644 --- a/pixi.toml +++ b/pixi.toml @@ -23,6 +23,7 @@ coal = ">=3.0.1,<4" assimp = ">=5.4.3,<6" eigenpy = ">=3.10.3,<4" eigen = ">=3.4.0,<4" +spdlog = ">=1.15.3,<2" [activation] scripts = ["scripts/pixi/activation.sh"] diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 064bf289..ce179901 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -46,13 +46,8 @@ add_library( target_link_libraries( candlewick_core - PUBLIC - SDL3::SDL3-shared - assimp::assimp - coal::coal - magic_enum::magic_enum - EnTT::EnTT - PRIVATE imgui_headers nlohmann_json::nlohmann_json + PUBLIC SDL3::SDL3-shared assimp::assimp coal::coal EnTT::EnTT spdlog::spdlog + PRIVATE imgui_headers nlohmann_json::nlohmann_json magic_enum::magic_enum ) target_compile_definitions( candlewick_core @@ -102,7 +97,7 @@ if(BUILD_PINOCCHIO_VISUALIZER) candlewick_core pinocchio::pinocchio_default pinocchio::pinocchio_visualizers - PRIVATE imgui_headers + PRIVATE imgui_headers magic_enum::magic_enum ) target_link_libraries(${PROJECT_NAME} INTERFACE candlewick_multibody) diff --git a/src/candlewick/core/CommandBuffer.cpp b/src/candlewick/core/CommandBuffer.cpp index a121844f..13db8734 100644 --- a/src/candlewick/core/CommandBuffer.cpp +++ b/src/candlewick/core/CommandBuffer.cpp @@ -11,8 +11,7 @@ bool CommandBuffer::cancel() noexcept { bool ret = SDL_CancelGPUCommandBuffer(m_handle); m_handle = nullptr; if (!ret) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Failed to cancel command buffer: %s", SDL_GetError()); + spdlog::error("Failed to cancel command buffer: {:s}", SDL_GetError()); return false; } return true; diff --git a/src/candlewick/core/CommandBuffer.h b/src/candlewick/core/CommandBuffer.h index 13c8b1aa..83cd47cf 100644 --- a/src/candlewick/core/CommandBuffer.h +++ b/src/candlewick/core/CommandBuffer.h @@ -2,9 +2,8 @@ #include "Core.h" #include -#include -#include #include +#include namespace candlewick { @@ -69,9 +68,9 @@ class CommandBuffer { ~CommandBuffer() noexcept { if (active()) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "CommandBuffer object is being destroyed while still active. " - "It will be cancelled."); + spdlog::warn( + "CommandBuffer object is being destroyed while still active. " + "It will be cancelled."); [[maybe_unused]] bool ret = cancel(); CANDLEWICK_ASSERT(ret, "Failed to cancel command buffer on cleanup."); } diff --git a/src/candlewick/core/DepthAndShadowPass.cpp b/src/candlewick/core/DepthAndShadowPass.cpp index af105bfd..03377c18 100644 --- a/src/candlewick/core/DepthAndShadowPass.cpp +++ b/src/candlewick/core/DepthAndShadowPass.cpp @@ -4,8 +4,6 @@ #include "Collision.h" #include "Camera.h" -#include - namespace candlewick { static GraphicsPipeline @@ -112,18 +110,16 @@ void DepthPass::release() noexcept { } void ShadowMapPass::configureAtlasRegions(const Config &config) { - SDL_Log("Building shadow atlas.\n" - " > Dims: (%d, %d)\n" - " > %d regions:", - shadowMap.width(), shadowMap.height(), config.numLights); + spdlog::info("Building shadow atlas (dims: ({:d}, {:d}), regions: {:d}).", + shadowMap.width(), shadowMap.height(), config.numLights); // compute atlas regions for (Uint32 i = 0; i < config.numLights; i++) { regions[i] = AtlasRegion(i * config.width, 0, config.width, config.height); const auto ® = regions[i]; regions[i] = reg; - SDL_Log(" - %d: [%d, %d] x [%d, %d]", i, reg.x, reg.x + reg.w, reg.y, - reg.y + reg.h); + spdlog::info(" - {:d}: [{:d}, {:d}] x [{:d}, {:d}]", i, reg.x, + reg.x + reg.w, reg.y, reg.y + reg.h); } } diff --git a/src/candlewick/core/Device.cpp b/src/candlewick/core/Device.cpp index c7a0fd32..26c60959 100644 --- a/src/candlewick/core/Device.cpp +++ b/src/candlewick/core/Device.cpp @@ -1,7 +1,7 @@ #include "Device.h" #include "errors.h" -#include +#include namespace candlewick { @@ -25,8 +25,7 @@ void Device::create(SDL_GPUShaderFormat format_flags, bool debug_mode) { _device = SDL_CreateGPUDevice(format_flags, debug_mode, nullptr); if (!_device) throw RAIIException(SDL_GetError()); - const char *driver = SDL_GetGPUDeviceDriver(_device); - SDL_Log("Device driver: %s", driver); + spdlog::info("Device driver: {:s}", driverName()); } const char *Device::driverName() const noexcept { @@ -34,8 +33,10 @@ const char *Device::driverName() const noexcept { } void Device::destroy() noexcept { - if (_device) + if (_device) { + spdlog::debug("Destroying GPU device"); SDL_DestroyGPUDevice(_device); + } _device = nullptr; } diff --git a/src/candlewick/core/LoadCoalGeometries.cpp b/src/candlewick/core/LoadCoalGeometries.cpp index 223aad44..3fe68a15 100644 --- a/src/candlewick/core/LoadCoalGeometries.cpp +++ b/src/candlewick/core/LoadCoalGeometries.cpp @@ -10,7 +10,6 @@ #include #include #include -#include namespace candlewick { diff --git a/src/candlewick/core/RenderContext.cpp b/src/candlewick/core/RenderContext.cpp index 62de333f..9d536b38 100644 --- a/src/candlewick/core/RenderContext.cpp +++ b/src/candlewick/core/RenderContext.cpp @@ -1,10 +1,10 @@ -#include "Renderer.h" +#include "RenderContext.h" #include "errors.h" #include #include +#include #include -#include namespace candlewick { RenderContext::RenderContext(Device &&device_, Window &&window_, @@ -20,14 +20,43 @@ bool RenderContext::waitAndAcquireSwapchain(CommandBuffer &command_buffer) { CANDLEWICK_ASSERT(SDL_IsMainThread(), "Can only acquire swapchain from main thread."); return SDL_WaitAndAcquireGPUSwapchainTexture(command_buffer, window, - &swapchain, NULL, NULL); + &swapchain, nullptr, nullptr); } bool RenderContext::acquireSwapchain(CommandBuffer &command_buffer) { CANDLEWICK_ASSERT(SDL_IsMainThread(), "Can only acquire swapchain from main thread."); return SDL_AcquireGPUSwapchainTexture(command_buffer, window, &swapchain, - NULL, NULL); + nullptr, nullptr); +} + +std::string format_texture_usage(SDL_GPUTextureUsageFlags flags) { + std::vector elts; +#define _c(usage) \ + if ((flags & SDL_GPU_TEXTUREUSAGE_##usage) == SDL_GPU_TEXTUREUSAGE_##usage) \ + elts.push_back(#usage) + + _c(SAMPLER); + _c(COLOR_TARGET); + _c(DEPTH_STENCIL_TARGET); + _c(GRAPHICS_STORAGE_READ); + _c(COMPUTE_STORAGE_READ); + _c(COMPUTE_STORAGE_WRITE); + _c(COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE); + + return fmt::format("{}", fmt::join(elts, " | ")); +#undef _c +} + +static void log_texture_creation(const Texture &tex, + const char *nameOverride = nullptr) { + spdlog::debug("Created {:d} x {:d} texture \'{:s}\'", tex.width(), + tex.height(), + (nameOverride != nullptr) ? nameOverride : tex.name()); + spdlog::debug(" > format {:>45s}, samples {:d}, usage {:device, depthInfo, "Main depth target"); - SDL_Log("Created depth texture of format %s, size %d x %d\n", - magic_enum::enum_name(depthInfo.format).data(), width, height); + log_texture_creation(depthBuffer); } void RenderContext::createMsaaTargets(SDL_GPUSampleCount samples) { @@ -93,13 +122,15 @@ void RenderContext::createMsaaTargets(SDL_GPUSampleCount samples) { samples)) { terminate_with_message("Unsupported sample count for MSAA color target."); } - colorMsaa = Texture(device, msaaColorInfo, "MSAA color target"); + colorMsaa = Texture(device, msaaColorInfo, "Color target [MSAA]"); + log_texture_creation(colorMsaa); if (hasDepthTexture()) { // overwrite current depth texture to make it Msaa auto depthInfo = depthBuffer.description(); depthInfo.sample_count = samples; depthBuffer = Texture(device, depthInfo, "Main depth target [MSAA]"); + log_texture_creation(depthBuffer); } } diff --git a/src/candlewick/core/RenderContext.h b/src/candlewick/core/RenderContext.h index 85b1ce9f..e89e53f9 100644 --- a/src/candlewick/core/RenderContext.h +++ b/src/candlewick/core/RenderContext.h @@ -81,7 +81,7 @@ struct RenderContext { m_msaaEnabled = true; createMsaaTargets(samples); if (int sample_size = sdlSampleToValue(samples)) { - SDL_Log("MSAA enabled with %d samples", sample_size); + spdlog::info("MSAA enabled with {:d} samples", sample_size); } else { terminate_with_message("Unrecognized sample count {:d}", sample_size); } @@ -93,7 +93,7 @@ struct RenderContext { void disableMSAA() { m_msaaEnabled = false; colorMsaa.destroy(); - SDL_Log("MSAA disabled."); + spdlog::info("MSAA disabled"); } bool initialized() const { return bool(device); } diff --git a/src/candlewick/core/Renderer.h b/src/candlewick/core/Renderer.h deleted file mode 100644 index 8a09b65a..00000000 --- a/src/candlewick/core/Renderer.h +++ /dev/null @@ -1,5 +0,0 @@ -#include "candlewick/deprecated.h" -#include "RenderContext.h" - -CANDLEWICK_DEPRECATED_HEADER( - "Include \'\' instead.") diff --git a/src/candlewick/core/Texture.cpp b/src/candlewick/core/Texture.cpp index baa86850..ab9e0d90 100644 --- a/src/candlewick/core/Texture.cpp +++ b/src/candlewick/core/Texture.cpp @@ -12,15 +12,19 @@ Texture::Texture(const Device &device, SDL_GPUTextureCreateInfo texture_desc, : m_device(device) , m_texture(nullptr) , m_description(std::move(texture_desc)) { + if (!m_description.props) + m_description.props = SDL_CreateProperties(); + if (name != nullptr) { + SDL_SetStringProperty(m_description.props, + SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING, name); + } if (!(m_texture = SDL_CreateGPUTexture(m_device, &m_description))) { std::string msg = std::format("Failed to create texture with format (%s)", magic_enum::enum_name(m_description.format)); if (name) - msg += std::format(" (name %s)", name); + msg += std::format(" (name {:s})", name); throw RAIIException(std::move(msg)); } - if (name != nullptr) - SDL_SetGPUTextureName(m_device, m_texture, name); } Texture::Texture(Texture &&other) noexcept diff --git a/src/candlewick/core/Texture.h b/src/candlewick/core/Texture.h index 4721a155..fe554bc8 100644 --- a/src/candlewick/core/Texture.h +++ b/src/candlewick/core/Texture.h @@ -36,6 +36,10 @@ class Texture { Uint32 depth() const { return m_description.layer_count_or_depth; } Uint32 layerCount() const { return m_description.layer_count_or_depth; } SDL_GPUSampleCount sampleCount() const { return m_description.sample_count; } + std::string_view name() const { + return SDL_GetStringProperty( + m_description.props, SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING, "(null)"); + } SDL_GPUBlitRegion blitRegion(Uint32 offset_x, Uint32 y_offset, Uint32 layer_or_depth_plane = 0) const; diff --git a/src/candlewick/core/errors.cpp b/src/candlewick/core/errors.cpp index c28b158d..fd615257 100644 --- a/src/candlewick/core/errors.cpp +++ b/src/candlewick/core/errors.cpp @@ -1,5 +1,7 @@ #include "errors.h" #include +#include +#include namespace candlewick { RAIIException::RAIIException(std::string_view msg, @@ -15,4 +17,10 @@ namespace detail { return std::format("{:s} :: {:s}", fname, std::vformat(fmtstr, args)); } } // namespace detail + +void unreachable_with_message(std::string_view msg, + std::source_location location) { + spdlog::error("{} :: {:s}", location, msg); + ::candlewick::unreachable(); +} } // namespace candlewick diff --git a/src/candlewick/core/errors.h b/src/candlewick/core/errors.h index 1df43286..6abd83c9 100644 --- a/src/candlewick/core/errors.h +++ b/src/candlewick/core/errors.h @@ -4,8 +4,6 @@ #include #endif -#include -#include #include #include #include @@ -70,14 +68,8 @@ terminate_with_message(std::source_location, std::string_view, Ts &&...) -> terminate_with_message; [[noreturn]] -inline void unreachable_with_message( +void unreachable_with_message( std::string_view msg, - std::source_location location = std::source_location::current()) { - SDL_LogError( - SDL_LOG_CATEGORY_APPLICATION, "%s", - detail::error_message_format(location.function_name(), "{:s}", msg) - .c_str()); - ::candlewick::unreachable(); -} + std::source_location location = std::source_location::current()); } // namespace candlewick diff --git a/src/candlewick/core/file_dialog_gui.cpp b/src/candlewick/core/file_dialog_gui.cpp index d108d531..5865fbe8 100644 --- a/src/candlewick/core/file_dialog_gui.cpp +++ b/src/candlewick/core/file_dialog_gui.cpp @@ -1,13 +1,13 @@ #include "GuiSystem.h" #include -#include #include #include #include #include #include +#include namespace candlewick { @@ -31,11 +31,11 @@ static const std::pair g_file_filters[] = { static void fileCallbackImpl(void *userdata_, const char *const *filelist, int) { if (!filelist) { - SDL_Log("An error occured: %s", SDL_GetError()); + spdlog::error("An error occured: %s", SDL_GetError()); return; } else if (!*filelist) { - SDL_Log("The user did not select any file."); - SDL_Log("Most likely, the dialog was canceled."); + spdlog::info("The user did not select any file.\n" + "Most likely, the dialog was canceled."); return; } diff --git a/src/candlewick/multibody/RobotDebug.cpp b/src/candlewick/multibody/RobotDebug.cpp index f33d6365..04b9e8f4 100644 --- a/src/candlewick/multibody/RobotDebug.cpp +++ b/src/candlewick/multibody/RobotDebug.cpp @@ -94,10 +94,6 @@ void RobotDebugSystem::update() { auto view = reg.group(); for (auto [ent, arrow] : view.each()) { if (--arrow.lifetime <= 0) { -#ifndef NDEBUG - SDL_Log("Force arrow for frame %zu has expired... destroy.", - arrow.frame_id); -#endif reg.destroy(ent); } } diff --git a/src/candlewick/multibody/RobotLoader.h b/src/candlewick/multibody/RobotLoader.h index 1cf9cef8..a18d4587 100644 --- a/src/candlewick/multibody/RobotLoader.h +++ b/src/candlewick/multibody/RobotLoader.h @@ -1,3 +1,4 @@ +/// \copyright Copyright (c) 2025 INRIA #pragma once #include "candlewick/core/errors.h" @@ -9,6 +10,7 @@ #include #include #include +#include namespace candlewick::multibody { namespace pin = pinocchio; @@ -40,7 +42,31 @@ struct RobotSpec { return *this; } }; +} // namespace candlewick::multibody + +FMT_BEGIN_NAMESPACE +template <> struct formatter { + constexpr auto parse(format_parse_context &ctx) { return ctx.begin(); } + + template + auto format(const candlewick::multibody::RobotSpec &spec, + FormatContext &ctx) const { + return fmt::format_to(ctx.out(), + "RobotSpec{{\n" + " urdf_path: \"{}\"\n" + " srdf_path: \"{}\"\n" + " base_package_path: \"{}\"\n" + " relative_package_path: \"{}\"\n" + " has_free_flyer: {}\n" + "}}", + spec.urdf_path, spec.srdf_path, + spec.base_package_path, spec.relative_package_path, + spec.has_free_flyer); + } +}; +FMT_END_NAMESPACE +namespace candlewick::multibody { inline std::vector getPackageDirs(const RobotSpec &spec) { if (spec.relative_package_path.is_absolute()) { terminate_with_message( diff --git a/src/candlewick/multibody/RobotScene.cpp b/src/candlewick/multibody/RobotScene.cpp index b125013c..15f448e5 100644 --- a/src/candlewick/multibody/RobotScene.cpp +++ b/src/candlewick/multibody/RobotScene.cpp @@ -15,6 +15,18 @@ #include #include +namespace candlewick { +/// \brief Terminate the application after encountering an invalid enum value. +template + requires std::is_enum_v +[[noreturn]] void +invalid_enum(const char *msg, T type, + std::source_location location = std::source_location::current()) { + terminate_with_message(location, "Invalid enum: {:s} - {:s}", msg, + magic_enum::enum_name(type)); +} +} // namespace candlewick + namespace candlewick::multibody { struct alignas(16) LightArrayUbo { @@ -694,8 +706,8 @@ RobotScene::createRenderPipeline(const PipelineKey &key, auto [type, transparent, renderMode] = key; const auto sample_count = m_renderer.getMsaaSampleCount(); - SDL_Log("Building pipeline for type %s (%d MSAA)", - magic_enum::enum_name(type).data(), sdlSampleToValue(sample_count)); + spdlog::info("Building pipeline for type {:s} ({:d} MSAA)", + magic_enum::enum_name(type), sdlSampleToValue(sample_count)); PipelineConfig pipe_config = getPipelineConfig(m_config, type, transparent); auto vertexShader = @@ -785,11 +797,11 @@ RobotScene::createRenderPipeline(const PipelineKey &key, desc.depth_stencil_state.enable_depth_write = false; } - SDL_Log(" > transparency: %s", transparent ? "true" : "false"); - SDL_Log(" > render mode: %s", magic_enum::enum_name(renderMode).data()); - SDL_Log(" > depth compare op: %s", - magic_enum::enum_name(depth_compare_op).data()); - SDL_Log(" > prepass: %s", had_prepass ? "true" : "false"); + spdlog::info(" > transparency: {}", transparent); + spdlog::info(" > render mode: {:s}", magic_enum::enum_name(renderMode)); + spdlog::info(" > depth comp op: {:s}", + magic_enum::enum_name(depth_compare_op)); + spdlog::info(" > prepass: {}", had_prepass); } return GraphicsPipeline(device(), desc, nullptr); diff --git a/src/candlewick/multibody/RobotScene.h b/src/candlewick/multibody/RobotScene.h index 41cd24ae..9cf959a7 100644 --- a/src/candlewick/multibody/RobotScene.h +++ b/src/candlewick/multibody/RobotScene.h @@ -22,16 +22,6 @@ namespace candlewick { enum class RenderMode; -/// \brief Terminate the application after encountering an invalid enum value. -template - requires std::is_enum_v -[[noreturn]] void -invalid_enum(const char *msg, T type, - std::source_location location = std::source_location::current()) { - terminate_with_message(location, "Invalid enum: {:s} - {:s}", msg, - magic_enum::enum_name(type)); -} - namespace multibody { /// \brief A system for updating the transform components for robot geometry diff --git a/src/candlewick/multibody/Visualizer.cpp b/src/candlewick/multibody/Visualizer.cpp index 047194d0..ebe77704 100644 --- a/src/candlewick/multibody/Visualizer.cpp +++ b/src/candlewick/multibody/Visualizer.cpp @@ -36,7 +36,7 @@ static RenderContext _create_renderer(const Visualizer::Config &config, if (!SDL_Init(SDL_INIT_VIDEO)) { terminate_with_message("Failed to init video: {:s}", SDL_GetError()); } - SDL_Log("Video driver: %s", SDL_GetCurrentVideoDriver()); + spdlog::info("Video driver: {:s}", SDL_GetCurrentVideoDriver()); RenderContext r{Device{auto_detect_shader_format_subset()}, Window{"Candlewick Pinocchio visualizer", int(config.width), @@ -104,15 +104,15 @@ void Visualizer::initialize() { this->resetCamera(); this->loadViewerModel(); - SDL_Log("┌───────Controls────────"); - SDL_Log("│ Toggle GUI: [%s]", "H"); - SDL_Log("│ Move camera: [%s]", - sdlMouseButtonToString(cameraParams.mouseButtons.rotButton)); - SDL_Log("│ Pan camera: [%s]", - sdlMouseButtonToString(cameraParams.mouseButtons.panButton)); - SDL_Log("│ Y-rotate camera: [%s]", - sdlMouseButtonToString(cameraParams.mouseButtons.yRotButton)); - SDL_Log("└───────────────────────"); + spdlog::info("┌───────Controls──────────"); + spdlog::info("│ Toggle GUI: [{:s}] ", "H"); + spdlog::info("│ Move camera: [{:s}] ", + sdlMouseButtonToString(cameraParams.mouseButtons.rotButton)); + spdlog::info("│ Pan camera: [{:s}] ", + sdlMouseButtonToString(cameraParams.mouseButtons.panButton)); + spdlog::info("│ Y-rotate camera: [{:s}] ", + sdlMouseButtonToString(cameraParams.mouseButtons.yRotButton)); + spdlog::info("└─────────────────────────"); } void Visualizer::resetCamera() { @@ -220,7 +220,8 @@ void Visualizer::render() { void Visualizer::takeScreenshot(std::string_view filename) { CommandBuffer command_buffer{device()}; auto [width, height] = renderer.window.sizeInPixels(); - SDL_Log("Saving %dx%d screenshot at: '%s'", width, height, filename.data()); + spdlog::info("Saving {:d} x {:d} screenshot at: \'{:s}\'", width, height, + filename); media::saveTextureToFile(command_buffer, device(), m_transferBuffers, renderer.resolvedColorTarget(), renderer.colorFormat(), Uint16(width), @@ -237,10 +238,9 @@ void Visualizer::startRecording([[maybe_unused]] std::string_view filename) { m_videoSettings); m_currentVideoFilename = filename; #else - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Visualizer::%s() does nothing here, since Candlewick was " - "compiled without FFmpeg support.", - __FUNCTION__); + spdlog::warn("Visualizer::{:s}() does nothing here, since Candlewick was " + "compiled without FFmpeg support.", + __FUNCTION__); #endif } @@ -249,7 +249,6 @@ bool Visualizer::stopRecording() { if (!m_videoRecorder.isRecording()) return false; m_currentVideoFilename.clear(); - SDL_Log("Wrote %d frames.", m_videoRecorder.frameCounter()); m_videoRecorder.close(); return true; #else @@ -295,10 +294,6 @@ void Visualizer::setFrameExternalForce(pin::FrameIndex frame_id, } // otherwise, create the arrow -#ifndef NDEBUG - SDL_Log("Force arrow not found for frame %zu, adding arrow with lifetime %u", - frame_id, initial_lifetime); -#endif auto [ent, dmc] = debugScene.addArrow(); registry.emplace(ent, frame_id, force, initial_lifetime, dmc.colors[0]); diff --git a/src/candlewick/multibody/visualizer_gui.cpp b/src/candlewick/multibody/visualizer_gui.cpp index 38394fae..5504b516 100644 --- a/src/candlewick/multibody/visualizer_gui.cpp +++ b/src/candlewick/multibody/visualizer_gui.cpp @@ -2,7 +2,6 @@ #include "RobotDebug.h" #include -#include #include #include @@ -183,7 +182,7 @@ void Visualizer::processEvents() { ImGui_ImplSDL3_ProcessEvent(&event); if (event.type == SDL_EVENT_QUIT) { - SDL_Log("Exiting application..."); + spdlog::info("Exiting application..."); m_shouldExit = true; } diff --git a/src/candlewick/posteffects/ScreenSpaceShadows.cpp b/src/candlewick/posteffects/ScreenSpaceShadows.cpp index 78996a38..5ff7ae5e 100644 --- a/src/candlewick/posteffects/ScreenSpaceShadows.cpp +++ b/src/candlewick/posteffects/ScreenSpaceShadows.cpp @@ -6,8 +6,6 @@ #include "../core/Shader.h" #include "../core/Camera.h" -#include - namespace candlewick { namespace effects { ScreenSpaceShadowPass::ScreenSpaceShadowPass(const RenderContext &renderer, diff --git a/src/candlewick/runtime/main.cpp b/src/candlewick/runtime/main.cpp index e0a2c43e..410b8646 100644 --- a/src/candlewick/runtime/main.cpp +++ b/src/candlewick/runtime/main.cpp @@ -14,6 +14,8 @@ #include #include +#include + namespace cdw = candlewick; namespace pin = pinocchio; using namespace cdw::runtime; @@ -63,13 +65,14 @@ bool handle_first_message(ApplicationContext &app_ctx) { // send response only when models loaded. sock.send(zmq::str_buffer("ok")); - SDL_Log("Loaded model with %d joints", app_ctx.model.njoints); - SDL_Log("Loaded geometry model with %zd gobjs", - app_ctx.visual_model.ngeoms); + spdlog::info("Loaded model with {:d} joints", app_ctx.model.njoints); + spdlog::info("Loaded geometry model with {:d} gobjs", + app_ctx.visual_model.ngeoms); return true; } else { - SDL_Log("First message must have header \'%s\', got \'%s\'. Retry.", - CMD_send_models.data(), msg_header.data()); + spdlog::error( + "First message must have header \'{:s}\', got \'{:s}\'. Retry.", + CMD_send_models, msg_header); continue; } } @@ -150,7 +153,9 @@ void run_main_loop(Visualizer &viz, ApplicationContext &app_ctx) { } } -int main(int argc, char **argv) { +int main(int argc, char *argv[]) { + spdlog::cfg::load_env_levels(); + spdlog::set_pattern(">>> [%T] [%^%l%$] %v"); CLI::App app{"Candlewick visualizer runtime"}; argv = app.ensure_utf8(argv); @@ -175,9 +180,9 @@ int main(int argc, char **argv) { std::string endpoint; endpoint = sync_sock.get(zmq::sockopt::last_endpoint); - SDL_Log("ZMQ endpoint (setup): %s", endpoint.c_str()); + spdlog::info("ZMQ endpoint (setup): {:s}", endpoint); endpoint = state_sock.get(zmq::sockopt::last_endpoint); - SDL_Log("ZMQ endpoint (state): %s", endpoint.c_str()); + spdlog::info("ZMQ endpoint (state): {:s}", endpoint); // Handle first message bool loaded_models = handle_first_message(app_ctx); diff --git a/src/candlewick/utils/LoadMesh.cpp b/src/candlewick/utils/LoadMesh.cpp index 1ccc04a6..ccc9a4d0 100644 --- a/src/candlewick/utils/LoadMesh.cpp +++ b/src/candlewick/utils/LoadMesh.cpp @@ -5,7 +5,7 @@ #include "../core/DefaultVertex.h" #include -#include +#include #include #include #include @@ -55,7 +55,7 @@ MeshData loadAiMesh(const aiMesh *inMesh, const aiMatrix4x4 transform) { static void log_resource_failure( const char *err_message, std::source_location loc = std::source_location::current()) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "%s: Failed to load resource [%s]", + spdlog::log(spdlog::level::warn, "{}: Failed to load resource [{:s}]", loc.function_name(), err_message); } diff --git a/src/candlewick/utils/MeshData.cpp b/src/candlewick/utils/MeshData.cpp index b68a3cdc..922b0ab8 100644 --- a/src/candlewick/utils/MeshData.cpp +++ b/src/candlewick/utils/MeshData.cpp @@ -3,8 +3,6 @@ #include "../core/Mesh.h" #include "../core/CommandBuffer.h" -#include - namespace candlewick { MeshData::MeshData(NoInitT) {} @@ -160,10 +158,7 @@ void uploadMeshToDevice(const Device &device, const MeshView &meshView, SDL_ReleaseGPUTransferBuffer(device, transfer_buffer); SDL_EndGPUCopyPass(copy_pass); if (!upload_command_buffer.submit()) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "%s: Failed to submit command buffer: %s", __FILE__, - SDL_GetError()); - assert(false); + spdlog::error("Failed to submit command buffer: {:s}", SDL_GetError()); } } diff --git a/src/candlewick/utils/VideoRecorder.cpp b/src/candlewick/utils/VideoRecorder.cpp index 2d3ea168..f975420f 100644 --- a/src/candlewick/utils/VideoRecorder.cpp +++ b/src/candlewick/utils/VideoRecorder.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include extern "C" { #include @@ -279,7 +281,9 @@ namespace media { terminate_with_message("Recording stream already open."); } - SDL_Log("[VideoRecorder] Opening stream at %s", filename.data()); + spdlog::info( + "[{}] Opening video stream at {:s} (fps = {:d}, bitrate = {:d}Mbps)", + typeid(*this), filename, settings.fps, settings.bitRate / 1000); m_width = width; m_height = height; if (settings.outputWidth == 0) @@ -293,6 +297,8 @@ namespace media { Uint32 VideoRecorder::frameCounter() const { return m_impl->m_frameCounter; } void VideoRecorder::close() noexcept { + spdlog::info("[{}] Closing recording stream, wrote {:d} frames.", + typeid(*this), frameCounter()); if (m_impl) m_impl.reset(); } diff --git a/src/candlewick/utils/WriteTextureToImage.cpp b/src/candlewick/utils/WriteTextureToImage.cpp index 465c56ac..ff7efa5b 100644 --- a/src/candlewick/utils/WriteTextureToImage.cpp +++ b/src/candlewick/utils/WriteTextureToImage.cpp @@ -47,7 +47,7 @@ namespace media { // grow by 20% _currentBufSize = Uint32(1.2 * requiredSize); - SDL_Log("Reallocate transfer buffer of size %u", _currentBufSize); + spdlog::debug("Reallocate transfer buffer of size {:d}", _currentBufSize); _buffer = acquireBufferImpl(_device, _currentBufSize); } return _buffer;