diff --git a/.gitignore b/.gitignore index e5babb84..58160bed 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,6 @@ OSP-MAGNUM.cbp CMakeSettings.json out/ .vs/ +.vscode/ build/ .vscode/ diff --git a/src/osp/util/logging.h b/src/osp/util/logging.h index 5109501d..44634269 100644 --- a/src/osp/util/logging.h +++ b/src/osp/util/logging.h @@ -24,7 +24,7 @@ */ #pragma once -#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO +#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG #include namespace osp diff --git a/src/testapp/main.cpp b/src/testapp/main.cpp index fd01a140..02fe9377 100644 --- a/src/testapp/main.cpp +++ b/src/testapp/main.cpp @@ -111,7 +111,7 @@ int main(int argc, char** argv) // Command line argument parsing Corrade::Utility::Arguments args; args.addSkippedPrefix("magnum", "Magnum options") - .addOption("scene", "none") .setHelp("scene", "Set the scene to launch") + .addOption("scene", "lander") .setHelp("scene", "Set the scene to launch") .addOption("config") .setHelp("config", "path to configuration file to use") .addBooleanOption("norepl") .setHelp("norepl", "don't enter read, evaluate, print, loop.") .addBooleanOption("log-exec") .setHelp("log-exec", "Log Task/Pipeline Execution (Extremely chatty!)") @@ -298,6 +298,7 @@ void start_magnum_async(int argc, char** argv) g_testApp.close_session(g_testApp.m_windowApp); OSP_LOG_INFO("Closed Magnum Application"); + std::exit(0); }); g_magnumThread.swap(t); } @@ -306,6 +307,7 @@ void load_a_bunch_of_stuff() { using namespace osp::restypes; using namespace Magnum; + using namespace testapp::scenes; using Primitives::ConeFlag; using Primitives::CylinderFlag; diff --git a/src/testapp/scenarios.cpp b/src/testapp/scenarios.cpp index 7797f433..d91a05cc 100644 --- a/src/testapp/scenarios.cpp +++ b/src/testapp/scenarios.cpp @@ -53,6 +53,8 @@ #include +#include "scenarios/lander.h" + using namespace adera; using namespace osp; using namespace osp::active; @@ -60,8 +62,6 @@ using namespace osp::active; namespace testapp { -static void setup_magnum_draw(TestApp& rTestApp, Session const& scene, Session const& sceneRenderer, Session const& magnumScene); - // MaterialIds hints which shaders should be used to draw a DrawEnt // DrawEnts can be assigned to multiple materials static constexpr auto sc_matVisualizer = draw::MaterialId(0); @@ -446,6 +446,10 @@ static ScenarioMap_t make_scenarios() return setup_renderer; }); + using lander::setup_lander_scenario; + + add_scenario("lander", "Lander simulation game", setup_lander_scenario); + return scenarioMap; } @@ -455,134 +459,6 @@ ScenarioMap_t const& scenarios() return s_scenarioMap; } - -//----------------------------------------------------------------------------- - - -struct MainLoopSignals -{ - PipelineId mainLoop; - PipelineId inputs; - PipelineId renderSync; - PipelineId renderResync; - PipelineId sceneUpdate; - PipelineId sceneRender; -}; - -/** - * @brief Runs Task/Pipeline main loop within MagnumApplication - */ -class CommonMagnumApp : public IOspApplication -{ -public: - CommonMagnumApp(TestApp &rTestApp, MainLoopControl &rMainLoopCtrl, MainLoopSignals signals) noexcept - : m_rTestApp { rTestApp } - , m_rMainLoopCtrl { rMainLoopCtrl } - , m_signals { signals } - { } - - void run(MagnumApplication& rApp) override - { - // Start the main loop - - PipelineId const mainLoop = m_rTestApp.m_application.get_pipelines().mainLoop; - m_rTestApp.m_pExecutor->run(m_rTestApp, mainLoop); - - // Resyncronize renderer - - m_rMainLoopCtrl = MainLoopControl{ - .doUpdate = false, - .doSync = true, - .doResync = true, - .doRender = false, - }; - - signal_all(); - - m_rTestApp.m_pExecutor->wait(m_rTestApp); - } - - void draw(MagnumApplication& rApp, float delta) override - { - // Magnum Application's main loop calls this - - m_rMainLoopCtrl = MainLoopControl{ - .doUpdate = true, - .doSync = true, - .doResync = false, - .doRender = true, - }; - - signal_all(); - - m_rTestApp.m_pExecutor->wait(m_rTestApp); - } - - void exit(MagnumApplication& rApp) override - { - m_rMainLoopCtrl = MainLoopControl{ - .doUpdate = false, - .doSync = false, - .doResync = false, - .doRender = false, - }; - - signal_all(); - - m_rTestApp.m_pExecutor->wait(m_rTestApp); - - if (m_rTestApp.m_pExecutor->is_running(m_rTestApp)) - { - // Main loop must have stopped, but didn't! - m_rTestApp.m_pExecutor->wait(m_rTestApp); - std::abort(); - } - } - -private: - - void signal_all() - { - m_rTestApp.m_pExecutor->signal(m_rTestApp, m_signals.mainLoop); - m_rTestApp.m_pExecutor->signal(m_rTestApp, m_signals.inputs); - m_rTestApp.m_pExecutor->signal(m_rTestApp, m_signals.renderSync); - m_rTestApp.m_pExecutor->signal(m_rTestApp, m_signals.renderResync); - m_rTestApp.m_pExecutor->signal(m_rTestApp, m_signals.sceneUpdate); - m_rTestApp.m_pExecutor->signal(m_rTestApp, m_signals.sceneRender); - } - - TestApp &m_rTestApp; - MainLoopControl &m_rMainLoopCtrl; - - MainLoopSignals m_signals; -}; - -void setup_magnum_draw(TestApp& rTestApp, Session const& scene, Session const& sceneRenderer, Session const& magnumScene) -{ - OSP_DECLARE_GET_DATA_IDS(rTestApp.m_application, TESTAPP_DATA_APPLICATION); - OSP_DECLARE_GET_DATA_IDS(sceneRenderer, TESTAPP_DATA_SCENE_RENDERER); - OSP_DECLARE_GET_DATA_IDS(rTestApp.m_magnum, TESTAPP_DATA_MAGNUM); - OSP_DECLARE_GET_DATA_IDS(magnumScene, TESTAPP_DATA_MAGNUM_SCENE); - - auto &rMainLoopCtrl = top_get (rTestApp.m_topData, idMainLoopCtrl); - auto &rActiveApp = top_get(rTestApp.m_topData, idActiveApp); - auto &rCamera = top_get (rTestApp.m_topData, idCamera); - - rCamera.set_aspect_ratio(Vector2{Magnum::GL::defaultFramebuffer.viewport().size()}); - - MainLoopSignals const signals - { - .mainLoop = rTestApp.m_application .get_pipelines() .mainLoop, - .inputs = rTestApp.m_windowApp .get_pipelines() .inputs, - .renderSync = rTestApp.m_windowApp .get_pipelines() .sync, - .renderResync = rTestApp.m_windowApp .get_pipelines() .resync, - .sceneUpdate = scene .get_pipelines() .update, - .sceneRender = sceneRenderer .get_pipelines() .render, - }; - - rActiveApp.set_osp_app( std::make_unique(rTestApp, rMainLoopCtrl, signals) ); -} - } // namespace testapp diff --git a/src/testapp/scenarios.h b/src/testapp/scenarios.h index 8beed14a..d35dfc3c 100644 --- a/src/testapp/scenarios.h +++ b/src/testapp/scenarios.h @@ -47,13 +47,6 @@ namespace scenes using enum EStgLink; } -struct MainLoopControl -{ - bool doUpdate; - bool doSync; - bool doResync; - bool doRender; -}; struct ScenarioOption { diff --git a/src/testapp/scenarios/lander.cpp b/src/testapp/scenarios/lander.cpp new file mode 100644 index 00000000..4177f623 --- /dev/null +++ b/src/testapp/scenarios/lander.cpp @@ -0,0 +1,129 @@ +#include "lander.h" +#include "../testapp.h" +#include "../identifiers.h" +#include "../sessions/common.h" +#include "../sessions/magnum.h" +#include "../sessions/misc.h" +#include "../sessions/newton.h" +#include "../sessions/physics.h" +#include "../sessions/shapes.h" +#include "../sessions/terrain.h" +#include "../sessions/universe.h" +#include "../sessions/vehicles.h" +#include "../sessions/vehicles_machines.h" +#include "../sessions/vehicles_prebuilt.h" +#include "../scenarios.h" + +#include + +#include + +namespace lander +{ + // MaterialIds hints which shaders should be used to draw a DrawEnt + // DrawEnts can be assigned to multiple materials + static constexpr auto sc_matVisualizer = osp::draw::MaterialId(0); + static constexpr auto sc_matFlat = osp::draw::MaterialId(1); + static constexpr auto sc_matPhong = osp::draw::MaterialId(2); + static constexpr int sc_materialCount = 4; + + RendererSetupFunc_t lander::setup_lander_scenario(TestApp &rTestApp) + { +#define SCENE_SESSIONS scene, commonScene, uniCore, uniScnFrame, uniPlanet, physics, \ + prefabs, parts, signalsFloat, vehicleSpawn, vehicleSpawnVB, vehicles, \ + newton, vehicleSpawnNwt, nwtRocketSet, rocketsNwt, \ + machRocket, machRcsDriver +#define SCENE_SESSIONS_COUNT 18 +#define RENDERER_SESSIONS sceneRenderer, magnumScene, planetDraw, \ + cameraCtrl, cameraFree, shVisual, shFlat, shPhong, \ + prefabDraw, vehicleDraw, vehicleCtrl, cameraVehicle +#define RENDERER_SESSIONS_COUNT 12 + + using namespace testapp::scenes; + using adera::ACtxVehicleSpawnVB; + using osp::top_get; + using osp::TopTaskBuilder; + using osp::active::ACtxVehicleSpawn; + using testapp::PlApplication; + // using osp::active::ad; + + auto const defaultPkg = rTestApp.m_defaultPkg; + auto const application = rTestApp.m_application; + auto &rTopData = rTestApp.m_topData; + + TopTaskBuilder builder{rTestApp.m_tasks, rTestApp.m_scene.m_edges, rTestApp.m_taskData}; + + auto &[SCENE_SESSIONS] = resize_then_unpack(rTestApp.m_scene.m_sessions); + + scene = setup_scene(builder, rTopData, application); + commonScene = setup_common_scene(builder, rTopData, scene, application, defaultPkg); + + auto const tgApp = application.get_pipelines(); + uniCore = setup_uni_core(builder, rTopData, tgApp.mainLoop); + uniScnFrame = setup_uni_sceneframe(builder, rTopData, uniCore); + uniPlanet = setup_uni_landerplanet(builder, rTopData, uniCore, uniScnFrame); + + physics = setup_physics(builder, rTopData, scene, commonScene); + prefabs = setup_prefabs(builder, rTopData, application, scene, commonScene, physics); + parts = setup_parts(builder, rTopData, application, scene); + signalsFloat = setup_signals_float(builder, rTopData, scene, parts); + vehicleSpawn = setup_vehicle_spawn(builder, rTopData, scene); + vehicleSpawnVB = setup_vehicle_spawn_vb(builder, rTopData, application, scene, commonScene, prefabs, parts, vehicleSpawn, signalsFloat); + vehicles = setup_prebuilt_vehicles(builder, rTopData, application, scene); + + machRocket = setup_mach_rocket(builder, rTopData, scene, parts, signalsFloat); + machRcsDriver = setup_mach_rcsdriver(builder, rTopData, scene, parts, signalsFloat); + + newton = setup_newton(builder, rTopData, scene, commonScene, physics); + vehicleSpawnNwt = setup_vehicle_spawn_newton(builder, rTopData, application, commonScene, physics, prefabs, parts, vehicleSpawn, newton); + nwtRocketSet = setup_newton_factors(builder, rTopData); + rocketsNwt = setup_rocket_thrust_newton(builder, rTopData, scene, commonScene, physics, prefabs, parts, signalsFloat, newton, nwtRocketSet); + + OSP_DECLARE_GET_DATA_IDS(vehicleSpawn, TESTAPP_DATA_VEHICLE_SPAWN); + OSP_DECLARE_GET_DATA_IDS(vehicleSpawnVB, TESTAPP_DATA_VEHICLE_SPAWN_VB); + OSP_DECLARE_GET_DATA_IDS(vehicles, TESTAPP_DATA_TEST_VEHICLES); + + auto &rVehicleSpawn = top_get(rTopData, idVehicleSpawn); + auto &rVehicleSpawnVB = top_get(rTopData, idVehicleSpawnVB); + auto &rPrebuiltVehicles = top_get(rTopData, idPrebuiltVehicles); + + rVehicleSpawn.spawnRequest.push_back( + {.position = {30.0f, 0.0f, 0.0f}, + .velocity = {0.0f, 0.0f, 0.0f}, + .rotation = {}}); + rVehicleSpawnVB.dataVB.push_back(rPrebuiltVehicles[gc_pbvSimpleCommandServiceModule].get()); + + RendererSetupFunc_t const setup_renderer = [](TestApp &rTestApp) -> void + { + auto const application = rTestApp.m_application; + auto const windowApp = rTestApp.m_windowApp; + auto const magnum = rTestApp.m_magnum; + auto &rTopData = rTestApp.m_topData; + + TopTaskBuilder builder{rTestApp.m_tasks, rTestApp.m_renderer.m_edges, rTestApp.m_taskData}; + + auto &[SCENE_SESSIONS] = unpack(rTestApp.m_scene.m_sessions); + auto &[RENDERER_SESSIONS] = resize_then_unpack(rTestApp.m_renderer.m_sessions); + + sceneRenderer = setup_scene_renderer(builder, rTopData, application, windowApp, commonScene); + create_materials(rTopData, sceneRenderer, sc_materialCount); + + magnumScene = setup_magnum_scene(builder, rTopData, application, rTestApp.m_windowApp, sceneRenderer, rTestApp.m_magnum, scene, commonScene); + cameraCtrl = setup_camera_ctrl(builder, rTopData, windowApp, sceneRenderer, magnumScene); + // cameraFree = setup_camera_free (builder, rTopData, windowApp, scene, cameraCtrl); + shVisual = setup_shader_visualizer(builder, rTopData, windowApp, sceneRenderer, magnum, magnumScene, sc_matVisualizer); + // shFlat = setup_shader_flat (builder, rTopData, windowApp, sceneRenderer, magnum, magnumScene, sc_matFlat); + shPhong = setup_shader_phong(builder, rTopData, windowApp, sceneRenderer, magnum, magnumScene, sc_matPhong); + planetDraw = setup_landerplanet_draw(builder, rTopData, windowApp, sceneRenderer, cameraCtrl, commonScene, uniCore, uniScnFrame, uniPlanet, sc_matVisualizer, sc_matFlat); + + prefabDraw = setup_prefab_draw(builder, rTopData, application, windowApp, sceneRenderer, commonScene, prefabs, sc_matPhong); + vehicleDraw = setup_vehicle_spawn_draw(builder, rTopData, sceneRenderer, vehicleSpawn); + vehicleCtrl = setup_vehicle_control(builder, rTopData, windowApp, scene, parts, signalsFloat); + cameraVehicle = setup_camera_vehicle(builder, rTopData, windowApp, scene, sceneRenderer, commonScene, physics, parts, cameraCtrl, vehicleCtrl); + + setup_magnum_draw(rTestApp, scene, sceneRenderer, magnumScene); + }; + return setup_renderer; + } + +} // namespace lander \ No newline at end of file diff --git a/src/testapp/scenarios/lander.h b/src/testapp/scenarios/lander.h new file mode 100644 index 00000000..b585ebca --- /dev/null +++ b/src/testapp/scenarios/lander.h @@ -0,0 +1,11 @@ +#include "../testapp.h" + +namespace lander +{ + using testapp::TestApp; + + using RendererSetupFunc_t = void (*)(TestApp &); + using MagnumDrawFunc_t = void (*)(TestApp &, osp::Session const &, osp::Session const &, osp::Session const &); + + RendererSetupFunc_t setup_lander_scenario(TestApp &rTestApp); +} // namespace lander \ No newline at end of file diff --git a/src/testapp/sessions/common.cpp b/src/testapp/sessions/common.cpp index cf752c7e..d9cc8040 100644 --- a/src/testapp/sessions/common.cpp +++ b/src/testapp/sessions/common.cpp @@ -24,6 +24,7 @@ */ #include "common.h" #include "../scenarios.h" +#include "magnum.h" #include #include diff --git a/src/testapp/sessions/magnum.cpp b/src/testapp/sessions/magnum.cpp index 01d1722f..426b9782 100644 --- a/src/testapp/sessions/magnum.cpp +++ b/src/testapp/sessions/magnum.cpp @@ -546,4 +546,125 @@ Session setup_shader_phong( } // setup_shader_phong +struct MainLoopSignals +{ + PipelineId mainLoop; + PipelineId inputs; + PipelineId renderSync; + PipelineId renderResync; + PipelineId sceneUpdate; + PipelineId sceneRender; +}; + +/** + * @brief Runs Task/Pipeline main loop within MagnumApplication + */ +class CommonMagnumApp : public IOspApplication +{ +public: + CommonMagnumApp(TestApp &rTestApp, MainLoopControl &rMainLoopCtrl, MainLoopSignals signals) noexcept + : m_rTestApp{rTestApp}, m_rMainLoopCtrl{rMainLoopCtrl}, m_signals{signals} + { + } + + void run(MagnumApplication &rApp) override + { + // Start the main loop + + PipelineId const mainLoop = m_rTestApp.m_application.get_pipelines().mainLoop; + m_rTestApp.m_pExecutor->run(m_rTestApp, mainLoop); + + // Resyncronize renderer + + m_rMainLoopCtrl = MainLoopControl{ + .doUpdate = false, + .doSync = true, + .doResync = true, + .doRender = false, + }; + + signal_all(); + + m_rTestApp.m_pExecutor->wait(m_rTestApp); + } + + void draw(MagnumApplication &rApp, float delta) override + { + // Magnum Application's main loop calls this + + m_rMainLoopCtrl = MainLoopControl{ + .doUpdate = true, + .doSync = true, + .doResync = false, + .doRender = true, + }; + + signal_all(); + + m_rTestApp.m_pExecutor->wait(m_rTestApp); + } + + void exit(MagnumApplication &rApp) override + { + m_rMainLoopCtrl = MainLoopControl{ + .doUpdate = false, + .doSync = false, + .doResync = false, + .doRender = false, + }; + + signal_all(); + + m_rTestApp.m_pExecutor->wait(m_rTestApp); + + if (m_rTestApp.m_pExecutor->is_running(m_rTestApp)) + { + // Main loop must have stopped, but didn't! + m_rTestApp.m_pExecutor->wait(m_rTestApp); + std::abort(); + } + } + +private: + void signal_all() + { + m_rTestApp.m_pExecutor->signal(m_rTestApp, m_signals.mainLoop); + m_rTestApp.m_pExecutor->signal(m_rTestApp, m_signals.inputs); + m_rTestApp.m_pExecutor->signal(m_rTestApp, m_signals.renderSync); + m_rTestApp.m_pExecutor->signal(m_rTestApp, m_signals.renderResync); + m_rTestApp.m_pExecutor->signal(m_rTestApp, m_signals.sceneUpdate); + m_rTestApp.m_pExecutor->signal(m_rTestApp, m_signals.sceneRender); + } + + TestApp &m_rTestApp; + MainLoopControl &m_rMainLoopCtrl; + + MainLoopSignals m_signals; +}; + +void setup_magnum_draw(TestApp &rTestApp, Session const &scene, Session const &sceneRenderer, Session const &magnumScene) +{ + OSP_DECLARE_GET_DATA_IDS(rTestApp.m_application, TESTAPP_DATA_APPLICATION); + OSP_DECLARE_GET_DATA_IDS(sceneRenderer, TESTAPP_DATA_SCENE_RENDERER); + OSP_DECLARE_GET_DATA_IDS(rTestApp.m_magnum, TESTAPP_DATA_MAGNUM); + OSP_DECLARE_GET_DATA_IDS(magnumScene, TESTAPP_DATA_MAGNUM_SCENE); + + auto &rMainLoopCtrl = top_get(rTestApp.m_topData, idMainLoopCtrl); + auto &rActiveApp = top_get(rTestApp.m_topData, idActiveApp); + auto &rCamera = top_get(rTestApp.m_topData, idCamera); + + rCamera.set_aspect_ratio(Vector2{Magnum::GL::defaultFramebuffer.viewport().size()}); + + MainLoopSignals const signals{ + .mainLoop = rTestApp.m_application.get_pipelines().mainLoop, + .inputs = rTestApp.m_windowApp.get_pipelines().inputs, + .renderSync = rTestApp.m_windowApp.get_pipelines().sync, + .renderResync = rTestApp.m_windowApp.get_pipelines().resync, + .sceneUpdate = scene.get_pipelines().update, + .sceneRender = sceneRenderer.get_pipelines().render, + }; + + rActiveApp.set_osp_app(std::make_unique(rTestApp, rMainLoopCtrl, signals)); +} // setup_magnum_draw + } // namespace testapp::scenes diff --git a/src/testapp/sessions/magnum.h b/src/testapp/sessions/magnum.h index 197cbfcd..d8e1c661 100644 --- a/src/testapp/sessions/magnum.h +++ b/src/testapp/sessions/magnum.h @@ -89,4 +89,18 @@ osp::Session setup_shader_phong( osp::Session const& magnumScene, osp::draw::MaterialId materialId = lgrn::id_null()); +void setup_magnum_draw( + TestApp& rTestApp, + osp::Session const& scene, + osp::Session const& sceneRenderer, + osp::Session const& magnumScene); + +struct MainLoopControl +{ + bool doUpdate; + bool doSync; + bool doResync; + bool doRender; +}; + } diff --git a/src/testapp/sessions/universe.cpp b/src/testapp/sessions/universe.cpp index 2537defd..7778f481 100644 --- a/src/testapp/sessions/universe.cpp +++ b/src/testapp/sessions/universe.cpp @@ -86,7 +86,103 @@ Session setup_uni_sceneframe( } // setup_uni_sceneframe +Session setup_uni_landerplanet( + TopTaskBuilder& rBuilder, + ArrayView topData, + Session const& uniCore, + Session const& uniScnFrame) +{ + using CoSpaceIdVec_t = std::vector; + using Corrade::Containers::Array; + + OSP_DECLARE_GET_DATA_IDS(uniCore, TESTAPP_DATA_UNI_CORE); + OSP_DECLARE_GET_DATA_IDS(uniScnFrame, TESTAPP_DATA_UNI_SCENEFRAME); + + auto const tgUCore = uniCore .get_pipelines(); + auto const tgUSFrm = uniScnFrame.get_pipelines(); + + auto &rUniverse = top_get< Universe >(topData, idUniverse); + + constexpr int precision = 10; + constexpr int planetCount = 1; + + // Create coordinate spaces + CoSpaceId const mainSpace = rUniverse.m_coordIds.create(); + std::vector satSurfaceSpaces(planetCount); + rUniverse.m_coordIds.create(satSurfaceSpaces.begin(), satSurfaceSpaces.end()); + rUniverse.m_coordCommon.resize(rUniverse.m_coordIds.capacity()); + + CoSpaceCommon &rMainSpaceCommon = rUniverse.m_coordCommon[mainSpace]; + rMainSpaceCommon.m_satCount = planetCount; + rMainSpaceCommon.m_satCapacity = planetCount; + + // Associate each planet satellite with their surface coordinate space + for (SatId satId = 0; satId < planetCount; ++satId) + { + CoSpaceId const surfaceSpaceId = satSurfaceSpaces[satId]; + CoSpaceCommon &rCommon = rUniverse.m_coordCommon[surfaceSpaceId]; + rCommon.m_parent = mainSpace; + rCommon.m_parentSat = satId; + } + + // Coordinate space data is a single allocation partitioned to hold positions, velocities, and + // rotations. + // TODO: Alignment is needed for SIMD (not yet implemented). see Corrade alignedAlloc + + std::size_t bytesUsed = 0; + + // Positions and velocities are arranged as XXXX... YYYY... ZZZZ... + partition(bytesUsed, planetCount, rMainSpaceCommon.m_satPositions[0]); + partition(bytesUsed, planetCount, rMainSpaceCommon.m_satPositions[1]); + partition(bytesUsed, planetCount, rMainSpaceCommon.m_satPositions[2]); + partition(bytesUsed, planetCount, rMainSpaceCommon.m_satVelocities[0]); + partition(bytesUsed, planetCount, rMainSpaceCommon.m_satVelocities[1]); + partition(bytesUsed, planetCount, rMainSpaceCommon.m_satVelocities[2]); + + // Rotations use XYZWXYZWXYZWXYZW... + partition(bytesUsed, planetCount, rMainSpaceCommon.m_satRotations[0], + rMainSpaceCommon.m_satRotations[1], + rMainSpaceCommon.m_satRotations[2], + rMainSpaceCommon.m_satRotations[3]); + + // Allocate data for all planets + rMainSpaceCommon.m_data = Array{Corrade::NoInit, bytesUsed}; + + // Create easily accessible array views for each component + auto const [x, y, z] = sat_views(rMainSpaceCommon.m_satPositions, rMainSpaceCommon.m_data, planetCount); + auto const [vx, vy, vz] = sat_views(rMainSpaceCommon.m_satVelocities, rMainSpaceCommon.m_data, planetCount); + auto const [qx, qy, qz, qw] = sat_views(rMainSpaceCommon.m_satRotations, rMainSpaceCommon.m_data, planetCount); + + for (std::size_t i = 0; i < planetCount; ++i) + { + // Assign each planet random positions and velocities + x[i] = 0; + y[i] = 0; + z[i] = 0; + vx[i] = 0; + vy[i] = 0; + vz[i] = 0; + + // No rotation + qx[i] = 0.0; + qy[i] = 0.0; + qz[i] = 0.0; + qw[i] = 1.0; + } + + auto &rScnFrame = top_get(topData, idScnFrame); + rScnFrame.m_parent = mainSpace; + rScnFrame.m_position = math::mul_2pow({400, 400, 400}, precision); + Session out; + OSP_DECLARE_CREATE_DATA_IDS(out, topData, TESTAPP_DATA_UNI_PLANETS); + + top_emplace< CoSpaceId > (topData, idPlanetMainSpace, mainSpace); + top_emplace< float > (topData, tgUniDeltaTimeIn, 1.0f / 60.0f); + top_emplace< CoSpaceIdVec_t > (topData, idSatSurfaceSpaces, std::move(satSurfaceSpaces)); + + return out; +} Session setup_uni_testplanets( TopTaskBuilder& rBuilder, @@ -318,6 +414,219 @@ struct PlanetDraw MaterialId matAxis; }; +Session setup_landerplanet_draw( + TopTaskBuilder& rBuilder, + ArrayView const topData, + Session const& windowApp, + Session const& sceneRenderer, + Session const& cameraCtrl, + Session const& commonScene, + Session const& uniCore, + Session const& uniScnFrame, + Session const& uniLanderPlanet, + MaterialId const matPlanets, + MaterialId const matAxis +) { + OSP_DECLARE_GET_DATA_IDS(commonScene, TESTAPP_DATA_COMMON_SCENE); + OSP_DECLARE_GET_DATA_IDS(sceneRenderer, TESTAPP_DATA_SCENE_RENDERER); + OSP_DECLARE_GET_DATA_IDS(cameraCtrl, TESTAPP_DATA_CAMERA_CTRL); + OSP_DECLARE_GET_DATA_IDS(uniCore, TESTAPP_DATA_UNI_CORE); + OSP_DECLARE_GET_DATA_IDS(uniScnFrame, TESTAPP_DATA_UNI_SCENEFRAME); + OSP_DECLARE_GET_DATA_IDS(uniLanderPlanet, TESTAPP_DATA_UNI_PLANETS); + + auto const tgWin = windowApp .get_pipelines(); + auto const tgScnRdr = sceneRenderer .get_pipelines(); + auto const tgCmCt = cameraCtrl .get_pipelines(); + auto const tgUSFrm = uniScnFrame .get_pipelines(); + + Session out; + + auto const [idPlanetDraw] = out.acquire_data<1>(topData); + auto &rPlanetDraw = top_emplace(topData, idPlanetDraw); + rPlanetDraw.matPlanets = matPlanets; + rPlanetDraw.matAxis = matAxis; + + rBuilder.task() + .name ("Position SceneFrame center to Camera Controller target") + .run_on ({tgWin.inputs(Run)}) + .sync_with ({tgCmCt.camCtrl(Ready), tgUSFrm.sceneFrame(Modify)}) + .push_to (out.m_tasks) + .args ({ idCamCtrl, idScnFrame }) + .func([] (ACtxCameraController& rCamCtrl, SceneFrame& rScnFrame) noexcept + { + if ( ! rCamCtrl.m_target.has_value()) + { + OSP_LOG_INFO("Camera Controller target not set"); + return; + } + Vector3 &rCamPl = rCamCtrl.m_target.value(); + + // check origin translation + // ADL used for Magnum::Math::sign/floor/abs + float const maxDist = 512.0f; + Vector3 const translate = sign(rCamPl) * floor(abs(rCamPl) / maxDist) * maxDist; + + if ( ! translate.isZero()) + { + // OSP_LOG_INFO("Translate Camera Controller target by {},{},{}", translate.x(), translate.y(), translate.z()); + // rCamCtrl.m_transform.translation() -= translate; + // rCamPl -= translate; + + // a bit janky to modify universe stuff directly here, but it works lol + // Vector3 const rotated = Quaternion(rScnFrame.m_rotation).transformVector(translate); + // OSP_LOG_INFO("Translate SceneFrame by {},{},{}", rotated.x(), rotated.y(), rotated.z()); + // rScnFrame.m_position += Vector3g(math::mul_2pow(rotated, rScnFrame.m_precision)); + } + + // OSP_LOG_INFO("SceneFrame position: {},{},{}", rScnFrame.m_position.x(), rScnFrame.m_position.y(), rScnFrame.m_position.z()); + rScnFrame.m_scenePosition = Vector3g(math::mul_2pow(rCamCtrl.m_target.value(), rScnFrame.m_precision)); + }); + + rBuilder.task() + .name ("Resync test planets, create DrawEnts") + .run_on ({tgWin.resync(Run)}) + .sync_with ({tgScnRdr.drawEntResized(ModifyOrSignal)}) + .push_to (out.m_tasks) + .args ({ idScnRender, idPlanetDraw, idUniverse, idPlanetMainSpace}) + .func([] (ACtxSceneRender& rScnRender, PlanetDraw& rPlanetDraw, Universe& rUniverse, CoSpaceId const planetMainSpace) noexcept + { + CoSpaceCommon &rMainSpace = rUniverse.m_coordCommon[planetMainSpace]; + + rPlanetDraw.drawEnts.resize(rMainSpace.m_satCount, lgrn::id_null()); + + rScnRender.m_drawIds.create(rPlanetDraw.drawEnts .begin(), rPlanetDraw.drawEnts .end()); + rScnRender.m_drawIds.create(rPlanetDraw.axis .begin(), rPlanetDraw.axis .end()); + rPlanetDraw.attractor = rScnRender.m_drawIds.create(); + }); + + rBuilder.task() + .name ("Resync test planets, add mesh and material") + .run_on ({tgWin.resync(Run)}) + .sync_with ({tgScnRdr.drawEntResized(Done), tgScnRdr.materialDirty(Modify_), tgScnRdr.entMeshDirty(Modify_)}) + .push_to (out.m_tasks) + .args ({ idDrawing, idScnRender, idNMesh, idPlanetDraw, idUniverse, idPlanetMainSpace}) + .func([] (ACtxDrawing& rDrawing, ACtxSceneRender& rScnRender, NamedMeshes& rNMesh, PlanetDraw& rPlanetDraw, Universe& rUniverse, CoSpaceId const planetMainSpace) noexcept + { + CoSpaceCommon &rMainSpace = rUniverse.m_coordCommon[planetMainSpace]; + + Material &rMatPlanet = rScnRender.m_materials[rPlanetDraw.matPlanets]; + Material &rMatAxis = rScnRender.m_materials[rPlanetDraw.matAxis]; + + MeshId const sphereMeshId = rNMesh.m_shapeToMesh.at(EShape::Sphere); + MeshId const cubeMeshId = rNMesh.m_shapeToMesh.at(EShape::Box); + + for (std::size_t i = 0; i < rMainSpace.m_satCount; ++i) + { + DrawEnt const drawEnt = rPlanetDraw.drawEnts[i]; + + rScnRender.m_mesh[drawEnt] = rDrawing.m_meshRefCounts.ref_add(sphereMeshId); + rScnRender.m_meshDirty.push_back(drawEnt); + rScnRender.m_visible.insert(drawEnt); + rScnRender.m_opaque.insert(drawEnt); + rMatPlanet.m_ents.insert(drawEnt); + rMatPlanet.m_dirty.push_back(drawEnt); + } + + rScnRender.m_mesh[rPlanetDraw.attractor] = rDrawing.m_meshRefCounts.ref_add(sphereMeshId); + rScnRender.m_meshDirty.push_back(rPlanetDraw.attractor); + rScnRender.m_visible.insert(rPlanetDraw.attractor); + rScnRender.m_opaque.insert(rPlanetDraw.attractor); + rMatPlanet.m_ents.insert(rPlanetDraw.attractor); + rMatPlanet.m_dirty.push_back(rPlanetDraw.attractor); + + for (DrawEnt const drawEnt : rPlanetDraw.axis) + { + rScnRender.m_mesh[drawEnt] = rDrawing.m_meshRefCounts.ref_add(cubeMeshId); + rScnRender.m_meshDirty.push_back(drawEnt); + rScnRender.m_visible.insert(drawEnt); + rScnRender.m_opaque.insert(drawEnt); + rMatAxis.m_ents.insert(drawEnt); + rMatAxis.m_dirty.push_back(drawEnt); + } + + rScnRender.m_color[rPlanetDraw.axis[0]] = {1.0f, 0.0f, 0.0f, 1.0f}; + rScnRender.m_color[rPlanetDraw.axis[1]] = {0.0f, 1.0f, 0.0f, 1.0f}; + rScnRender.m_color[rPlanetDraw.axis[2]] = {0.0f, 0.0f, 1.0f, 1.0f}; + }); + + rBuilder.task() + .name ("Reposition test planet DrawEnts") + .run_on ({tgScnRdr.render(Run)}) + .sync_with ({tgScnRdr.drawTransforms(Modify_), tgScnRdr.drawEntResized(Done), tgCmCt.camCtrl(Ready), tgUSFrm.sceneFrame(Modify)}) + .push_to (out.m_tasks) + .args ({ idDrawing, idScnRender, idPlanetDraw, idUniverse, idScnFrame, idPlanetMainSpace}) + .func([] (ACtxDrawing& rDrawing, ACtxSceneRender& rScnRender, PlanetDraw& rPlanetDraw, Universe& rUniverse, SceneFrame const& rScnFrame, CoSpaceId const planetMainSpace) noexcept + { + + CoSpaceCommon &rMainSpace = rUniverse.m_coordCommon[planetMainSpace]; + auto const [x, y, z] = sat_views(rMainSpace.m_satPositions, rMainSpace.m_data, rMainSpace.m_satCount); + auto const [qx, qy, qz, qw] = sat_views(rMainSpace.m_satRotations, rMainSpace.m_data, rMainSpace.m_satCount); + + // Calculate transform from universe to area/local-space for rendering. + // This can be generalized by finding a common ancestor within the tree + // of coordinate spaces. Since there's only two possibilities, an if + // statement works. + CoordTransformer mainToArea; + if (rScnFrame.m_parent == planetMainSpace) + { + mainToArea = coord_parent_to_child(rMainSpace, rScnFrame); + } + else + { + CoSpaceId const landedId = rScnFrame.m_parent; + CoSpaceCommon &rLanded = rUniverse.m_coordCommon[landedId]; + + CoSpaceTransform const landedTf = coord_get_transform(rLanded, rLanded, x, y, z, qx, qy, qz, qw); + CoordTransformer const mainToLanded = coord_parent_to_child(rMainSpace, landedTf); + CoordTransformer const landedToArea = coord_parent_to_child(landedTf, rScnFrame); + + mainToArea = coord_composite(landedToArea, mainToLanded); + } + Quaternion const mainToAreaRot{mainToArea.rotation()}; + + float const scale = math::mul_2pow(1.0f, -rMainSpace.m_precision); + + Vector3 const attractorPos = Vector3(mainToArea.transform_position({0, 0, 0})) * scale; + + // Attractor + rScnRender.m_drawTransform[rPlanetDraw.attractor] + = Matrix4::translation(attractorPos) + * Matrix4{mainToAreaRot.toMatrix()} + * Matrix4::scaling({500, 500, 500}); + + rScnRender.m_drawTransform[rPlanetDraw.axis[0]] + = Matrix4::translation(attractorPos) + * Matrix4{mainToAreaRot.toMatrix()} + * Matrix4::scaling({500000, 10, 10}); + rScnRender.m_drawTransform[rPlanetDraw.axis[1]] + = Matrix4::translation(attractorPos) + * Matrix4{mainToAreaRot.toMatrix()} + * Matrix4::scaling({10, 500000, 10}); + rScnRender.m_drawTransform[rPlanetDraw.axis[2]] + = Matrix4::translation(attractorPos) + * Matrix4{mainToAreaRot.toMatrix()} + * Matrix4::scaling({10, 10, 500000}); + + for (std::size_t i = 0; i < rMainSpace.m_satCount; ++i) + { + Vector3g const relative = mainToArea.transform_position({x[i], y[i], z[i]}); + Vector3 const relativeMeters = Vector3(relative) * scale; + + Quaterniond const rot{{qx[i], qy[i], qz[i]}, qw[i]}; + + DrawEnt const drawEnt = rPlanetDraw.drawEnts[i]; + + rScnRender.m_drawTransform[drawEnt] + = Matrix4::translation(relativeMeters) + * Matrix4::scaling({200, 200, 200}) + * Matrix4{(mainToAreaRot * Quaternion{rot}).toMatrix()}; + } + + }); + + return out; +} + Session setup_testplanets_draw( TopTaskBuilder& rBuilder, ArrayView const topData, diff --git a/src/testapp/sessions/universe.h b/src/testapp/sessions/universe.h index 94039d16..577cca0e 100644 --- a/src/testapp/sessions/universe.h +++ b/src/testapp/sessions/universe.h @@ -47,6 +47,15 @@ osp::Session setup_uni_sceneframe( osp::ArrayView topData, osp::Session const& uniCore); +/** + * @brief A single planet setup for landing on + */ +osp::Session setup_uni_landerplanet( + osp::TopTaskBuilder& rBuilder, + osp::ArrayView topData, + osp::Session const& uniCore, + osp::Session const& uniScnFrame); + /** * @brief Unrealistic planets test, allows SceneFrame to move around and get captured into planets */ @@ -56,6 +65,21 @@ osp::Session setup_uni_testplanets( osp::Session const& uniCore, osp::Session const& uniScnFrame); +/** + * @brief Draw universe, specifically designed for setup_uni_landerplanet + */ +osp::Session setup_landerplanet_draw( + osp::TopTaskBuilder& rBuilder, + osp::ArrayView topData, + osp::Session const& windowApp, + osp::Session const& sceneRenderer, + osp::Session const& cameraCtrl, + osp::Session const& commonScene, + osp::Session const& uniCore, + osp::Session const& uniScnFrame, + osp::Session const& uniTestPlanets, + osp::draw::MaterialId const matPlanets, + osp::draw::MaterialId const matAxis); /** * @brief Draw universe, specifically designed for setup_uni_test_planets