ADD: planet prototype
This commit is contained in:
@@ -35,6 +35,26 @@ const float SHADOW_MIN_BIAS = 1e-5;
|
||||
const float SHADOW_RAY_TMIN = 0.02;// start a bit away from the surface
|
||||
const float SHADOW_RAY_ORIGIN_BIAS = 0.01;// world units
|
||||
|
||||
// Estimate the float ULP scale at this world position magnitude, used to keep
|
||||
// ray bias and tMin effective even when world coordinates are very large.
|
||||
float world_pos_ulp(vec3 p)
|
||||
{
|
||||
float m = max(max(abs(p.x), abs(p.y)), abs(p.z));
|
||||
// For IEEE-754 float, relative precision is ~2^-23 (~1.192e-7). Clamp to a
|
||||
// small baseline to avoid tiny values near the origin.
|
||||
return max(1e-4, m * 1.1920929e-7);
|
||||
}
|
||||
|
||||
float shadow_ray_origin_bias(vec3 p)
|
||||
{
|
||||
return max(SHADOW_RAY_ORIGIN_BIAS, world_pos_ulp(p) * 8.0);
|
||||
}
|
||||
|
||||
float shadow_ray_tmin(vec3 p)
|
||||
{
|
||||
return max(SHADOW_RAY_TMIN, world_pos_ulp(p) * 16.0);
|
||||
}
|
||||
|
||||
vec3 getCameraWorldPosition()
|
||||
{
|
||||
// view = [ R^T -R^T*C ]
|
||||
@@ -223,9 +243,11 @@ float calcShadowVisibility(vec3 worldPos, vec3 N, vec3 L)
|
||||
#ifdef GL_EXT_ray_query
|
||||
float farR = max(max(sceneData.cascadeSplitsView.x, sceneData.cascadeSplitsView.y),
|
||||
max(sceneData.cascadeSplitsView.z, sceneData.cascadeSplitsView.w));
|
||||
float originBias = shadow_ray_origin_bias(wp);
|
||||
float tmin = shadow_ray_tmin(wp);
|
||||
rayQueryEXT rq;
|
||||
rayQueryInitializeEXT(rq, topLevelAS, gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT,
|
||||
0xFF, wp + N * SHADOW_RAY_ORIGIN_BIAS, SHADOW_RAY_TMIN, L, farR);
|
||||
0xFF, wp + N * originBias, tmin, L, farR);
|
||||
while (rayQueryProceedEXT(rq)) { }
|
||||
bool hit = (rayQueryGetIntersectionTypeEXT(rq, true) != gl_RayQueryCommittedIntersectionNoneEXT);
|
||||
return hit ? 0.0 : 1.0;
|
||||
@@ -249,10 +271,12 @@ float calcShadowVisibility(vec3 worldPos, vec3 N, vec3 L)
|
||||
if (cascadeEnabled && NoL < sceneData.rtParams.x)
|
||||
{
|
||||
float maxT = sceneData.cascadeSplitsView[cm.i0];
|
||||
float originBias = shadow_ray_origin_bias(wp);
|
||||
float tmin = shadow_ray_tmin(wp);
|
||||
rayQueryEXT rq;
|
||||
// tmin: small offset to avoid self-hits
|
||||
rayQueryInitializeEXT(rq, topLevelAS, gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT,
|
||||
0xFF, wp + N * SHADOW_RAY_ORIGIN_BIAS, SHADOW_RAY_TMIN, L, maxT);
|
||||
0xFF, wp + N * originBias, tmin, L, maxT);
|
||||
bool hit = false;
|
||||
while (rayQueryProceedEXT(rq)) { }
|
||||
hit = (rayQueryGetIntersectionTypeEXT(rq, true) != gl_RayQueryCommittedIntersectionNoneEXT);
|
||||
@@ -278,9 +302,11 @@ float calcShadowVisibility(vec3 worldPos, vec3 N, vec3 L)
|
||||
float maxT0 = sceneData.cascadeSplitsView[cm.i0];
|
||||
float maxT1 = sceneData.cascadeSplitsView[cm.i1];
|
||||
float maxT = max(maxT0, maxT1);
|
||||
float originBias = shadow_ray_origin_bias(wp);
|
||||
float tmin = shadow_ray_tmin(wp);
|
||||
rayQueryEXT rq;
|
||||
rayQueryInitializeEXT(rq, topLevelAS, gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT,
|
||||
0xFF, wp + N * SHADOW_RAY_ORIGIN_BIAS, SHADOW_RAY_TMIN, L, maxT);
|
||||
0xFF, wp + N * originBias, tmin, L, maxT);
|
||||
while (rayQueryProceedEXT(rq)) { }
|
||||
bool hit = (rayQueryGetIntersectionTypeEXT(rq, true) != gl_RayQueryCommittedIntersectionNoneEXT);
|
||||
if (hit) vis = min(vis, 0.0);
|
||||
@@ -335,7 +361,9 @@ void main(){
|
||||
if (maxT > 0.01)
|
||||
{
|
||||
vec3 dir = toL / maxT;
|
||||
vec3 origin = pos + N * SHADOW_RAY_ORIGIN_BIAS;
|
||||
float originBias = shadow_ray_origin_bias(pos);
|
||||
float tmin = shadow_ray_tmin(pos);
|
||||
vec3 origin = pos + N * originBias;
|
||||
|
||||
rayQueryEXT rq;
|
||||
rayQueryInitializeEXT(
|
||||
@@ -344,7 +372,7 @@ void main(){
|
||||
gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT,
|
||||
0xFF,
|
||||
origin,
|
||||
SHADOW_RAY_TMIN,
|
||||
tmin,
|
||||
dir,
|
||||
maxT
|
||||
);
|
||||
@@ -380,7 +408,9 @@ void main(){
|
||||
float cosTheta = dot(-L, dir);
|
||||
if (cosTheta > sceneData.spotLights[i].direction_cos_outer.w)
|
||||
{
|
||||
vec3 origin = pos + N * SHADOW_RAY_ORIGIN_BIAS;
|
||||
float originBias = shadow_ray_origin_bias(pos);
|
||||
float tmin = shadow_ray_tmin(pos);
|
||||
vec3 origin = pos + N * originBias;
|
||||
|
||||
rayQueryEXT rq;
|
||||
rayQueryInitializeEXT(
|
||||
@@ -389,7 +419,7 @@ void main(){
|
||||
gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT,
|
||||
0xFF,
|
||||
origin,
|
||||
SHADOW_RAY_TMIN,
|
||||
tmin,
|
||||
L,
|
||||
maxT
|
||||
);
|
||||
|
||||
@@ -130,6 +130,8 @@ add_executable (vulkan_engine
|
||||
scene/camera/mode_chase.cpp
|
||||
scene/camera/mode_fixed.h
|
||||
scene/camera/mode_fixed.cpp
|
||||
scene/planet/planet_system.h
|
||||
scene/planet/planet_system.cpp
|
||||
# compute
|
||||
compute/vk_compute.h
|
||||
compute/vk_compute.cpp
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "mesh_bvh.h"
|
||||
#include "scene/planet/planet_system.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -2242,6 +2243,111 @@ namespace
|
||||
pick->worldPos = local_to_world(glm::vec3(targetTransform[3]), sceneMgr->get_world_origin());
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_planets(VulkanEngine *eng)
|
||||
{
|
||||
if (!eng || !eng->_sceneManager)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SceneManager *scene = eng->_sceneManager.get();
|
||||
PlanetSystem *planets = scene->get_planet_system();
|
||||
if (!planets)
|
||||
{
|
||||
ImGui::TextUnformatted("Planet system not available");
|
||||
return;
|
||||
}
|
||||
|
||||
bool enabled = planets->enabled();
|
||||
if (ImGui::Checkbox("Enable planet rendering", &enabled))
|
||||
{
|
||||
planets->set_enabled(enabled);
|
||||
}
|
||||
|
||||
const WorldVec3 origin_world = scene->get_world_origin();
|
||||
const WorldVec3 cam_world = scene->getMainCamera().position_world;
|
||||
const glm::vec3 cam_local = scene->get_camera_local_position();
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Camera world (m): %.3f, %.3f, %.3f", cam_world.x, cam_world.y, cam_world.z);
|
||||
ImGui::Text("Camera local (m): %.3f, %.3f, %.3f", cam_local.x, cam_local.y, cam_local.z);
|
||||
ImGui::Text("World origin (m): %.3f, %.3f, %.3f", origin_world.x, origin_world.y, origin_world.z);
|
||||
|
||||
auto look_at_world = [](Camera &cam, const WorldVec3 &target_world)
|
||||
{
|
||||
glm::dvec3 dirD = glm::normalize(target_world - cam.position_world);
|
||||
glm::vec3 dir = glm::normalize(glm::vec3(dirD));
|
||||
|
||||
glm::vec3 up(0.0f, 1.0f, 0.0f);
|
||||
if (glm::length2(glm::cross(dir, up)) < 1e-6f)
|
||||
{
|
||||
up = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
glm::vec3 f = dir;
|
||||
glm::vec3 r = glm::normalize(glm::cross(up, f));
|
||||
glm::vec3 u = glm::cross(f, r);
|
||||
|
||||
glm::mat3 rot;
|
||||
rot[0] = r;
|
||||
rot[1] = u;
|
||||
rot[2] = -f; // -Z forward
|
||||
cam.orientation = glm::quat_cast(rot);
|
||||
};
|
||||
|
||||
PlanetSystem::PlanetBody *earth = planets->get_body(PlanetSystem::BodyID::Earth);
|
||||
PlanetSystem::PlanetBody *moon = planets->get_body(PlanetSystem::BodyID::Moon);
|
||||
|
||||
if (earth)
|
||||
{
|
||||
ImGui::Separator();
|
||||
|
||||
bool vis = earth->visible;
|
||||
if (ImGui::Checkbox("Render Earth", &vis))
|
||||
{
|
||||
earth->visible = vis;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("(R=%.1f km)", earth->radius_m / 1000.0);
|
||||
|
||||
const double dist = glm::length(cam_world - earth->center_world);
|
||||
const double alt_m = dist - earth->radius_m;
|
||||
ImGui::Text("Altitude above Earth: %.3f km", alt_m / 1000.0);
|
||||
|
||||
if (ImGui::Button("Teleport: 10000 km above surface"))
|
||||
{
|
||||
scene->getMainCamera().position_world =
|
||||
earth->center_world + WorldVec3(0.0, 0.0, earth->radius_m + 1.0e7);
|
||||
look_at_world(scene->getMainCamera(), earth->center_world);
|
||||
}
|
||||
|
||||
if (ImGui::Button("Teleport: 1000 km orbit"))
|
||||
{
|
||||
scene->getMainCamera().position_world =
|
||||
earth->center_world + WorldVec3(0.0, 0.0, earth->radius_m + 1.0e6);
|
||||
look_at_world(scene->getMainCamera(), earth->center_world);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Teleport: 10 km above surface"))
|
||||
{
|
||||
scene->getMainCamera().position_world =
|
||||
earth->center_world + WorldVec3(0.0, 0.0, earth->radius_m + 1.0e4);
|
||||
look_at_world(scene->getMainCamera(), earth->center_world);
|
||||
}
|
||||
}
|
||||
|
||||
if (moon)
|
||||
{
|
||||
bool vis = moon->visible;
|
||||
if (ImGui::Checkbox("Render Moon", &vis))
|
||||
{
|
||||
moon->visible = vis;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("(R=%.1f km)", moon->radius_m / 1000.0);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Window visibility states for menu-bar toggles
|
||||
@@ -2260,6 +2366,7 @@ namespace
|
||||
bool show_postfx{false};
|
||||
bool show_scene{false};
|
||||
bool show_camera{false};
|
||||
bool show_planets{false};
|
||||
bool show_async_assets{false};
|
||||
bool show_textures{false};
|
||||
};
|
||||
@@ -2282,6 +2389,7 @@ void vk_engine_draw_debug_ui(VulkanEngine *eng)
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem("Scene", nullptr, &g_debug_windows.show_scene);
|
||||
ImGui::MenuItem("Camera", nullptr, &g_debug_windows.show_camera);
|
||||
ImGui::MenuItem("Planets", nullptr, &g_debug_windows.show_planets);
|
||||
ImGui::MenuItem("Render Graph", nullptr, &g_debug_windows.show_render_graph);
|
||||
ImGui::MenuItem("Pipelines", nullptr, &g_debug_windows.show_pipelines);
|
||||
ImGui::Separator();
|
||||
@@ -2406,6 +2514,15 @@ void vk_engine_draw_debug_ui(VulkanEngine *eng)
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (g_debug_windows.show_planets)
|
||||
{
|
||||
if (ImGui::Begin("Planets", &g_debug_windows.show_planets))
|
||||
{
|
||||
ui_planets(eng);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (g_debug_windows.show_async_assets)
|
||||
{
|
||||
if (ImGui::Begin("Async Assets", &g_debug_windows.show_async_assets))
|
||||
|
||||
10
src/main.cpp
10
src/main.cpp
@@ -33,6 +33,16 @@ public:
|
||||
api.load_global_ibl(ibl);
|
||||
}
|
||||
|
||||
// Planet demo defaults (Milestone A): start outside Earth and speed up the free camera.
|
||||
{
|
||||
constexpr double kEarthRadiusM = 6378137.0;
|
||||
GameAPI::FreeCameraSettings free = api.get_free_camera_settings();
|
||||
free.moveSpeed = 20000.0f;
|
||||
api.set_free_camera_settings(free);
|
||||
|
||||
api.set_camera_position(glm::dvec3(0.0, 0.0, kEarthRadiusM + 1.0e6));
|
||||
api.camera_look_at(glm::dvec3(0.0, 0.0, 0.0));
|
||||
}
|
||||
|
||||
// Load a glTF model asynchronously
|
||||
// api.add_gltf_instance_async("example_model", "models/example.gltf",
|
||||
|
||||
168
src/scene/planet/planet_system.cpp
Normal file
168
src/scene/planet/planet_system.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
#include "planet_system.h"
|
||||
|
||||
#include <core/context.h>
|
||||
#include <core/types.h>
|
||||
#include <core/assets/manager.h>
|
||||
#include <render/materials.h>
|
||||
#include <render/primitives.h>
|
||||
#include <scene/tangent_space.h>
|
||||
#include <scene/vk_scene.h>
|
||||
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr double kEarthRadiusM = 6378137.0; // WGS84 equatorial radius
|
||||
constexpr double kMoonRadiusM = 1737400.0; // mean radius
|
||||
constexpr double kMoonDistanceM = 384400000.0; // mean Earth-Moon distance
|
||||
|
||||
GLTFMetallic_Roughness::MaterialConstants make_planet_constants()
|
||||
{
|
||||
GLTFMetallic_Roughness::MaterialConstants c{};
|
||||
c.colorFactors = glm::vec4(1.0f);
|
||||
// metal_rough_factors.x = metallic, .y = roughness
|
||||
c.metal_rough_factors = glm::vec4(0.0f, 1.0f, 0.0f, 0.0f);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
void PlanetSystem::init(EngineContext *context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
const PlanetSystem::PlanetBody *PlanetSystem::get_body(BodyID id) const
|
||||
{
|
||||
size_t i = static_cast<size_t>(id);
|
||||
if (i >= _bodies.size())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return &_bodies[i];
|
||||
}
|
||||
|
||||
PlanetSystem::PlanetBody *PlanetSystem::get_body(BodyID id)
|
||||
{
|
||||
size_t i = static_cast<size_t>(id);
|
||||
if (i >= _bodies.size())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return &_bodies[i];
|
||||
}
|
||||
|
||||
void PlanetSystem::ensure_bodies_created()
|
||||
{
|
||||
if (!_bodies.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PlanetBody earth{};
|
||||
earth.name = "Earth";
|
||||
earth.center_world = WorldVec3(0.0, 0.0, 0.0);
|
||||
earth.radius_m = kEarthRadiusM;
|
||||
|
||||
PlanetBody moon{};
|
||||
moon.name = "Moon";
|
||||
moon.center_world = WorldVec3(kMoonDistanceM, 0.0, 0.0);
|
||||
moon.radius_m = kMoonRadiusM;
|
||||
|
||||
if (_context && _context->assets)
|
||||
{
|
||||
AssetManager *assets = _context->assets;
|
||||
|
||||
// Earth: textured sphere (albedo only for now).
|
||||
{
|
||||
AssetManager::MeshCreateInfo ci{};
|
||||
ci.name = "Planet_EarthSphere";
|
||||
ci.geometry.type = AssetManager::MeshGeometryDesc::Type::Sphere;
|
||||
ci.geometry.sectors = 64;
|
||||
ci.geometry.stacks = 32;
|
||||
|
||||
ci.material.kind = AssetManager::MeshMaterialDesc::Kind::Textured;
|
||||
ci.material.options.albedoPath = "earth/earth_8k.jpg";
|
||||
ci.material.options.albedoSRGB = true;
|
||||
ci.material.options.constants = make_planet_constants();
|
||||
ci.material.options.pass = MaterialPass::MainColor;
|
||||
|
||||
earth.mesh = assets->createMesh(ci);
|
||||
if (earth.mesh && !earth.mesh->surfaces.empty())
|
||||
{
|
||||
earth.material = earth.mesh->surfaces[0].material;
|
||||
}
|
||||
}
|
||||
|
||||
// Moon: constant albedo (no texture yet).
|
||||
{
|
||||
GLTFMetallic_Roughness::MaterialConstants mc = make_planet_constants();
|
||||
mc.colorFactors = glm::vec4(0.72f, 0.72f, 0.75f, 1.0f);
|
||||
|
||||
moon.material = assets->createMaterialFromConstants("Planet_MoonMaterial", mc, MaterialPass::MainColor);
|
||||
|
||||
std::vector<Vertex> verts;
|
||||
std::vector<uint32_t> inds;
|
||||
primitives::buildSphere(verts, inds, 48, 24);
|
||||
geom::generate_tangents(verts, inds);
|
||||
|
||||
moon.mesh = assets->createMesh("Planet_MoonSphere", verts, inds, moon.material);
|
||||
}
|
||||
}
|
||||
|
||||
_bodies.push_back(std::move(earth));
|
||||
_bodies.push_back(std::move(moon));
|
||||
}
|
||||
|
||||
void PlanetSystem::update_and_emit(const SceneManager &scene, DrawContext &draw_context)
|
||||
{
|
||||
if (!_enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ensure_bodies_created();
|
||||
|
||||
const WorldVec3 origin_world = scene.get_world_origin();
|
||||
|
||||
for (PlanetBody &b : _bodies)
|
||||
{
|
||||
if (!b.visible || !b.mesh || b.mesh->surfaces.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const glm::vec3 t_local = world_to_local(b.center_world, origin_world);
|
||||
const float r = static_cast<float>(b.radius_m);
|
||||
const glm::vec3 s = glm::vec3(r * 2.0f); // primitive sphere radius is 0.5
|
||||
const glm::quat q = glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
|
||||
const glm::mat4 transform = make_trs_matrix(t_local, q, s);
|
||||
|
||||
uint32_t surface_index = 0;
|
||||
for (const GeoSurface &surf : b.mesh->surfaces)
|
||||
{
|
||||
RenderObject obj{};
|
||||
obj.indexCount = surf.count;
|
||||
obj.firstIndex = surf.startIndex;
|
||||
obj.indexBuffer = b.mesh->meshBuffers.indexBuffer.buffer;
|
||||
obj.vertexBuffer = b.mesh->meshBuffers.vertexBuffer.buffer;
|
||||
obj.vertexBufferAddress = b.mesh->meshBuffers.vertexBufferAddress;
|
||||
obj.material = surf.material ? &surf.material->data : nullptr;
|
||||
obj.bounds = surf.bounds;
|
||||
obj.transform = transform;
|
||||
obj.sourceMesh = b.mesh.get();
|
||||
obj.surfaceIndex = surface_index++;
|
||||
obj.objectID = draw_context.nextID++;
|
||||
obj.ownerType = RenderObject::OwnerType::MeshInstance;
|
||||
obj.ownerName = b.name;
|
||||
|
||||
if (obj.material && obj.material->passType == MaterialPass::Transparent)
|
||||
{
|
||||
draw_context.TransparentSurfaces.push_back(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
draw_context.OpaqueSurfaces.push_back(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
54
src/scene/planet/planet_system.h
Normal file
54
src/scene/planet/planet_system.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include <core/world.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class EngineContext;
|
||||
class SceneManager;
|
||||
struct DrawContext;
|
||||
class MeshAsset;
|
||||
struct GLTFMaterial;
|
||||
|
||||
class PlanetSystem
|
||||
{
|
||||
public:
|
||||
enum class BodyID : uint8_t
|
||||
{
|
||||
Earth = 0,
|
||||
Moon = 1,
|
||||
};
|
||||
|
||||
struct PlanetBody
|
||||
{
|
||||
std::string name;
|
||||
WorldVec3 center_world{0.0, 0.0, 0.0};
|
||||
double radius_m = 1.0;
|
||||
bool visible = true;
|
||||
|
||||
std::shared_ptr<MeshAsset> mesh;
|
||||
std::shared_ptr<GLTFMaterial> material;
|
||||
};
|
||||
|
||||
void init(EngineContext *context);
|
||||
|
||||
void update_and_emit(const SceneManager &scene, DrawContext &draw_context);
|
||||
|
||||
bool enabled() const { return _enabled; }
|
||||
void set_enabled(bool enabled) { _enabled = enabled; }
|
||||
|
||||
const PlanetBody *get_body(BodyID id) const;
|
||||
PlanetBody *get_body(BodyID id);
|
||||
const std::vector<PlanetBody> &bodies() const { return _bodies; }
|
||||
|
||||
private:
|
||||
void ensure_bodies_created();
|
||||
|
||||
EngineContext *_context = nullptr;
|
||||
bool _enabled = true;
|
||||
std::vector<PlanetBody> _bodies;
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <unordered_set>
|
||||
#include <chrono>
|
||||
|
||||
#include "scene/planet/planet_system.h"
|
||||
#include "core/device/swapchain.h"
|
||||
#include "core/context.h"
|
||||
#include "core/config.h"
|
||||
@@ -19,6 +20,8 @@
|
||||
#include "core/config.h"
|
||||
#include <fmt/core.h>
|
||||
|
||||
SceneManager::SceneManager() = default;
|
||||
|
||||
SceneManager::~SceneManager()
|
||||
{
|
||||
fmt::println("[SceneManager] dtor: loadedScenes={} dynamicGLTFInstances={} pendingGLTFRelease={}",
|
||||
@@ -121,6 +124,9 @@ void SceneManager::init(EngineContext *context)
|
||||
cameraRig.init(*this, mainCamera);
|
||||
|
||||
_camera_position_local = world_to_local(mainCamera.position_world, _origin_world);
|
||||
|
||||
_planetSystem = std::make_unique<PlanetSystem>();
|
||||
_planetSystem->init(_context);
|
||||
}
|
||||
|
||||
void SceneManager::update_scene()
|
||||
@@ -306,6 +312,11 @@ void SceneManager::update_scene()
|
||||
}
|
||||
}
|
||||
|
||||
if (_planetSystem)
|
||||
{
|
||||
_planetSystem->update_and_emit(*this, mainDrawContext);
|
||||
}
|
||||
|
||||
glm::mat4 view = mainCamera.getViewMatrix(_camera_position_local);
|
||||
// Use reversed infinite-Z projection (right-handed, -Z forward) to avoid far-plane clipping
|
||||
// on very large scenes. Vulkan clip space is 0..1 (GLM_FORCE_DEPTH_ZERO_TO_ONE) and requires Y flip.
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "scene/vk_loader.h"
|
||||
class EngineContext;
|
||||
class PlanetSystem;
|
||||
|
||||
struct RenderObject
|
||||
{
|
||||
@@ -61,6 +62,7 @@ struct DrawContext
|
||||
class SceneManager
|
||||
{
|
||||
public:
|
||||
SceneManager();
|
||||
~SceneManager();
|
||||
void init(EngineContext *context);
|
||||
|
||||
@@ -223,6 +225,8 @@ public:
|
||||
|
||||
const PickingDebug &getPickingDebug() const { return pickingDebug; }
|
||||
|
||||
PlanetSystem *get_planet_system() const { return _planetSystem.get(); }
|
||||
|
||||
// Returns the LoadedGLTF scene for a named GLTF instance, or nullptr if not found.
|
||||
std::shared_ptr<LoadedGLTF> getGLTFInstanceScene(const std::string &instanceName) const;
|
||||
|
||||
@@ -252,5 +256,7 @@ private:
|
||||
// GPU resources that might still be in-flight.
|
||||
std::vector<std::shared_ptr<LoadedGLTF>> pendingGLTFRelease;
|
||||
|
||||
std::unique_ptr<PlanetSystem> _planetSystem;
|
||||
|
||||
PickingDebug pickingDebug{};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user