Compare commits

..

2 Commits

Author SHA1 Message Date
b2069e7b39 EDIT: remove bin/ from git tracking and LFS
- Add /bin to .gitignore
- Remove LFS tracking for bin/**
- Delete all bin/ files from git tracking

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 18:05:47 +09:00
719a5445ce ADD: planet camera fix 2025-12-30 17:56:16 +09:00
64 changed files with 184 additions and 173 deletions

1
.gitattributes vendored
View File

@@ -1 +0,0 @@
bin/** filter=lfs diff=lfs merge=lfs -text

1
.gitignore vendored
View File

@@ -5,3 +5,4 @@
/cmake-build-debug_win
/cmake-build-release_win
*.spv
/bin

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
bin/SDL2.dll LFS

Binary file not shown.

BIN
bin/SDL2.lib LFS

Binary file not shown.

BIN
bin/SDL2d.dll LFS

Binary file not shown.

BIN
bin/SDL2d.lib LFS

Binary file not shown.

BIN
bin/SDL2d.pdb LFS

Binary file not shown.

BIN
bin/dwd.rdc LFS

Binary file not shown.

BIN
bin/engine.exe LFS

Binary file not shown.

BIN
bin/engine.pdb LFS

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
bin/fmt.lib LFS

Binary file not shown.

BIN
bin/fmtd.lib LFS

Binary file not shown.

BIN
bin/imgui.ini LFS

Binary file not shown.

BIN
bin/imgui.lib LFS

Binary file not shown.

BIN
bin/ktx.dll LFS

Binary file not shown.

Binary file not shown.

View File

@@ -1 +0,0 @@
libSDL2-2.0d.so.0

View File

@@ -1 +0,0 @@
libSDL2-2.0d.so.0.3200.10

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
bin/libfmtd.a LFS

Binary file not shown.

BIN
bin/libimgui.a LFS

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -834,10 +834,40 @@ namespace
if (!pick.valid) return false;
if (pick.ownerType == RenderObject::OwnerType::MeshInstance)
{
// Many procedural objects (planets etc.) tag draws as "MeshInstance" for picking,
// but they don't exist in SceneManager::dynamicMeshInstances. Only use a
// MeshInstance camera target if it resolves.
WorldVec3 t{};
glm::quat r{};
glm::vec3 s{};
if (sceneMgr->getMeshInstanceTRSWorld(pick.ownerName, t, r, s))
{
target.type = CameraTargetType::MeshInstance;
target.name = pick.ownerName;
}
else if (PlanetSystem *planets = sceneMgr->get_planet_system())
{
if (PlanetSystem::PlanetBody *body = planets->find_body_by_name(pick.ownerName))
{
target.type = CameraTargetType::WorldPoint;
target.world_point = body->center_world;
target.name = body->name;
}
else
{
target.type = CameraTargetType::WorldPoint;
target.world_point = pick.worldPos;
target.name.clear();
}
}
else
{
target.type = CameraTargetType::WorldPoint;
target.world_point = pick.worldPos;
target.name.clear();
}
}
else if (pick.ownerType == RenderObject::OwnerType::GLTFInstance)
{
target.type = CameraTargetType::GLTFInstance;
@@ -920,7 +950,9 @@ namespace
target_from_last_pick(s.target);
}
ImGui::InputDouble("Distance", &s.distance, 0.1, 1.0, "%.3f");
s.distance = std::clamp(s.distance, 0.2, 100000.0);
s.distance = std::clamp(s.distance,
OrbitCameraSettings::kMinDistance,
OrbitCameraSettings::kMaxDistance);
float yawDeg = glm::degrees(s.yaw);
float pitchDeg = glm::degrees(s.pitch);
if (ImGui::SliderFloat("Yaw (deg)", &yawDeg, -180.0f, 180.0f))

View File

@@ -14,6 +14,7 @@
#include "scene/vk_scene.h"
#include "scene/camera.h"
#include "scene/camera/camera_rig.h"
#include "scene/planet/planet_system.h"
#include <glm/gtx/matrix_decompose.hpp>
#include <glm/gtx/quaternion.hpp>
@@ -1820,10 +1821,37 @@ bool Engine::set_camera_target_from_last_pick()
::CameraTarget t;
if (pick.ownerType == RenderObject::OwnerType::MeshInstance)
{
// RenderObject::OwnerType::MeshInstance is also used for some procedural objects
// (planets etc.) which don't exist in SceneManager::dynamicMeshInstances.
WorldVec3 inst_t{};
glm::quat inst_r{};
glm::vec3 inst_s{};
if (_engine->_sceneManager->getMeshInstanceTRSWorld(pick.ownerName, inst_t, inst_r, inst_s))
{
t.type = ::CameraTargetType::MeshInstance;
t.name = pick.ownerName;
}
else if (PlanetSystem *planets = _engine->_sceneManager->get_planet_system())
{
if (PlanetSystem::PlanetBody *body = planets->find_body_by_name(pick.ownerName))
{
t.type = ::CameraTargetType::WorldPoint;
t.name = body->name;
t.world_point = body->center_world;
}
else
{
t.type = ::CameraTargetType::WorldPoint;
t.world_point = pick.worldPos;
}
}
else
{
t.type = ::CameraTargetType::WorldPoint;
t.world_point = pick.worldPos;
}
}
else if (pick.ownerType == RenderObject::OwnerType::GLTFInstance)
{
t.type = ::CameraTargetType::GLTFInstance;

View File

@@ -5,6 +5,7 @@
#include "core/device/images.h"
#include "core/device/swapchain.h"
#include "render/graph/graph.h"
#include "scene/planet/planet_system.h"
#include "SDL2/SDL.h"
#include "SDL2/SDL_vulkan.h"
@@ -12,6 +13,91 @@
#include <algorithm>
#include <cmath>
namespace
{
bool try_orbit_camera_to_planet(EngineContext *context, const PickingSystem::PickInfo &pick)
{
if (!context || !context->scene)
{
return false;
}
if (pick.ownerType != RenderObject::OwnerType::MeshInstance)
{
return false;
}
SceneManager &scene = *context->scene;
// If this is a real dynamic MeshInstance, leave it alone (user might want
// to orbit other things separately).
{
WorldVec3 t{};
glm::quat r{};
glm::vec3 s{};
if (scene.getMeshInstanceTRSWorld(pick.ownerName, t, r, s))
{
return false;
}
}
PlanetSystem *planets = scene.get_planet_system();
if (!planets || !planets->enabled())
{
return false;
}
PlanetSystem::PlanetBody *body = planets->find_body_by_name(pick.ownerName);
if (!body || !body->visible)
{
return false;
}
CameraRig &rig = scene.getCameraRig();
Camera &cam = scene.getMainCamera();
CameraTarget target{};
target.type = CameraTargetType::WorldPoint;
target.name = body->name;
target.world_point = body->center_world;
rig.orbit_settings().target = target;
rig.follow_settings().target = target;
rig.chase_settings().target = target;
rig.set_mode(CameraMode::Orbit, scene, cam);
const WorldVec3 to_cam = cam.position_world - body->center_world;
double dist = glm::length(to_cam);
// If we're inside the planet (or very close), pop out to a sane viewing altitude.
// Clamp altitude to [10 km, 1000 km] and scale with body radius.
const double min_alt_m = std::clamp(body->radius_m * 0.05, 1.0e4, 1.0e6);
const double min_dist = body->radius_m + min_alt_m;
if (!std::isfinite(dist) || dist < min_dist)
{
dist = min_dist;
}
glm::dvec3 dir = glm::dvec3(to_cam);
if (glm::dot(dir, dir) < 1e-12)
{
dir = glm::dvec3(0.0, 0.0, 1.0);
}
else
{
dir = glm::normalize(dir);
}
OrbitCameraSettings &orbit = rig.orbit_settings();
orbit.distance = std::clamp(dist, OrbitCameraSettings::kMinDistance, OrbitCameraSettings::kMaxDistance);
orbit.yaw = static_cast<float>(std::atan2(dir.x, dir.z));
orbit.pitch = static_cast<float>(std::asin(std::clamp(-dir.y, -1.0, 1.0)));
return true;
}
} // namespace
void PickingSystem::init(EngineContext *context)
{
_context = context;
@@ -121,6 +207,7 @@ void PickingSystem::process_event(const SDL_Event &event, bool ui_want_capture_m
{
set_pick_from_hit(hit_object, hit_pos, _last_pick);
_last_pick_object_id = hit_object.objectID;
try_orbit_camera_to_planet(_context, _last_pick);
}
else
{
@@ -223,6 +310,7 @@ void PickingSystem::begin_frame()
glm::vec3 fallback_local = glm::vec3(picked.transform[3]);
WorldVec3 fallback_pos = local_to_world(fallback_local, _context->scene->get_world_origin());
set_pick_from_hit(picked, fallback_pos, _last_pick);
try_orbit_camera_to_planet(_context, _last_pick);
}
else
{

View File

@@ -45,6 +45,9 @@ struct FreeCameraSettings
struct OrbitCameraSettings
{
static constexpr double kMinDistance = 0.2;
static constexpr double kMaxDistance = 1.0e12;
CameraTarget target{};
double distance{10.0};
float yaw{0.0f}; // radians

View File

@@ -76,17 +76,18 @@ void FreeCameraMode::process_input(SceneManager & /*scene*/,
float dx = e.mouse_delta.x * _settings.look_sensitivity;
float dy = e.mouse_delta.y * _settings.look_sensitivity;
// Mouse right (xrel > 0) turns view right with -Z-forward: yaw around +Y.
glm::quat yaw_rotation = glm::angleAxis(dx, glm::vec3{0.f, 1.f, 0.f});
// Mouse right (xrel > 0) turns view right with -Z-forward: yaw around the
// camera's local +Y (up) axis, so yaw remains intuitive when rolled.
glm::vec3 up = glm::rotate(camera.orientation, glm::vec3{0.f, 1.f, 0.f});
glm::quat yaw_rotation = glm::angleAxis(dx, glm::normalize(up));
camera.orientation = glm::normalize(yaw_rotation * camera.orientation);
// Mouse up (yrel < 0) looks up with -Z-forward: negative dy.
float pitch_delta = -dy;
// Pitch around the camera's local X (right) axis in world space.
// Pitch around the camera's local +X (right) axis (after yaw is applied).
glm::vec3 right = glm::rotate(camera.orientation, glm::vec3{1.f, 0.f, 0.f});
glm::quat pitch_rotation = glm::angleAxis(pitch_delta, glm::vec3(right));
// Apply yaw, then pitch, to the current orientation.
camera.orientation = glm::normalize(pitch_rotation * yaw_rotation * camera.orientation);
glm::quat pitch_rotation = glm::angleAxis(pitch_delta, glm::normalize(right));
camera.orientation = glm::normalize(pitch_rotation * camera.orientation);
}
else if (e.type == InputEvent::Type::MouseWheel)
{

View File

@@ -102,7 +102,9 @@ void OrbitCameraMode::process_input(SceneManager & /*scene*/,
else
{
const double factor = std::pow(1.15, -static_cast<double>(steps));
_settings.distance = std::clamp(_settings.distance * factor, 0.2, 100000.0);
_settings.distance = std::clamp(_settings.distance * factor,
OrbitCameraSettings::kMinDistance,
OrbitCameraSettings::kMaxDistance);
}
}
}
@@ -137,7 +139,7 @@ void OrbitCameraMode::update(SceneManager &scene, Camera &camera, float /*dt*/)
glm::half_pi<float>() - 0.01f);
_settings.yaw = yaw;
_settings.pitch = pitch;
double dist = std::max(0.2, _settings.distance);
double dist = std::max(OrbitCameraSettings::kMinDistance, _settings.distance);
glm::quat yaw_q = glm::angleAxis(yaw, glm::vec3(0.0f, 1.0f, 0.0f));
glm::vec3 right = glm::rotate(yaw_q, glm::vec3(1.0f, 0.0f, 0.0f));

View File

@@ -182,6 +182,19 @@ PlanetSystem::PlanetBody *PlanetSystem::get_body(BodyID id)
return &_bodies[i];
}
PlanetSystem::PlanetBody *PlanetSystem::find_body_by_name(std::string_view name)
{
ensure_bodies_created();
for (PlanetBody &b : _bodies)
{
if (b.name == name)
{
return &b;
}
}
return nullptr;
}
void PlanetSystem::ensure_bodies_created()
{
if (!_bodies.empty())

View File

@@ -9,6 +9,7 @@
#include <list>
#include <memory>
#include <string>
#include <string_view>
#include <unordered_map>
#include <vector>
@@ -61,6 +62,7 @@ public:
const PlanetBody *get_body(BodyID id) const;
PlanetBody *get_body(BodyID id);
PlanetBody *find_body_by_name(std::string_view name);
const std::vector<PlanetBody> &bodies() const { return _bodies; }
const planet::PlanetQuadtree::Settings &earth_quadtree_settings() const { return _earth_quadtree_settings; }