MODEL LOADING BABY WORKS
This commit is contained in:
@@ -153,4 +153,5 @@ void App::run() {
|
||||
}
|
||||
|
||||
void App::cleanup() {
|
||||
customCleanup();
|
||||
}
|
||||
|
||||
69
destrum/src/Components/OrbitAndSpin.cpp
Normal file
69
destrum/src/Components/OrbitAndSpin.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include <destrum/Components/OrbitAndSpin.h>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtx/norm.hpp>
|
||||
#include <random>
|
||||
#include <cmath>
|
||||
|
||||
#include "destrum/ObjectModel/Transform.h"
|
||||
|
||||
static glm::vec3 RandomUnitVector(std::mt19937& rng)
|
||||
{
|
||||
// uniform on sphere
|
||||
std::uniform_real_distribution<float> dist(0.0f, 1.0f);
|
||||
float z = dist(rng) * 2.0f - 1.0f; // -1..1
|
||||
float a = dist(rng) * 6.28318530718f; // 0..2pi
|
||||
float r = std::sqrt(std::max(0.0f, 1.0f - z*z));
|
||||
return glm::normalize(glm::vec3(r*std::cos(a), z, r*std::sin(a)));
|
||||
}
|
||||
|
||||
void OrbitAndSpin::Randomize(uint32_t seed)
|
||||
{
|
||||
std::mt19937 rng(seed);
|
||||
|
||||
// speeds + phase
|
||||
std::uniform_real_distribution<float> orbitSpeedDist(0.2f, 1.5f);
|
||||
std::uniform_real_distribution<float> spinSpeedDist(0.5f, 6.0f);
|
||||
std::uniform_real_distribution<float> phaseDist(0.0f, 6.28318530718f);
|
||||
|
||||
m_OrbitAxis = RandomUnitVector(rng);
|
||||
m_SpinAxis = RandomUnitVector(rng);
|
||||
|
||||
m_OrbitSpeed = orbitSpeedDist(rng);
|
||||
m_SpinSpeed = spinSpeedDist(rng);
|
||||
m_OrbitPhase = phaseDist(rng);
|
||||
|
||||
BuildOrbitBasis();
|
||||
}
|
||||
|
||||
void OrbitAndSpin::BuildOrbitBasis()
|
||||
{
|
||||
m_OrbitAxis = glm::normalize(m_OrbitAxis);
|
||||
|
||||
// pick any vector not parallel to axis
|
||||
glm::vec3 any = (std::abs(m_OrbitAxis.y) < 0.99f) ? glm::vec3(0,1,0) : glm::vec3(1,0,0);
|
||||
|
||||
m_U = glm::normalize(glm::cross(any, m_OrbitAxis));
|
||||
m_V = glm::normalize(glm::cross(m_OrbitAxis, m_U));
|
||||
}
|
||||
|
||||
void OrbitAndSpin::Update()
|
||||
{
|
||||
// If your engine provides dt via a global/time service, use that instead.
|
||||
// Since your Spinner takes dt indirectly, I'm assuming Component::Update()
|
||||
// is called once per frame and you can access dt somewhere globally.
|
||||
//
|
||||
// If you CAN pass dt into Update, change signature to Update(float dt).
|
||||
float dt = 1.0f / 60.0f;
|
||||
|
||||
// orbit
|
||||
m_OrbitAngle += m_OrbitSpeed * dt;
|
||||
float a = m_OrbitAngle + m_OrbitPhase;
|
||||
|
||||
glm::vec3 offset = (m_U * std::cos(a) + m_V * std::sin(a)) * m_Radius;
|
||||
GetTransform().SetWorldPosition(m_Center + offset);
|
||||
|
||||
// self spin (local rotation)
|
||||
glm::quat dq = glm::angleAxis(m_SpinSpeed * dt, glm::normalize(m_SpinAxis));
|
||||
auto current = GetTransform().GetLocalRotation(); // adapt to your API
|
||||
GetTransform().SetLocalRotation(glm::normalize(dq * current));
|
||||
}
|
||||
@@ -1,17 +1,95 @@
|
||||
#include <destrum/Components/Rotator.h>
|
||||
|
||||
Rotator::Rotator(GameObject& parent, float distance, float speed):
|
||||
Component(parent, "Rotator"),
|
||||
m_Distance(distance),
|
||||
m_Speed(speed),
|
||||
m_CurrentAngle(0),
|
||||
m_OriginalPosition(GetTransform().GetWorldPosition())
|
||||
{}
|
||||
#include <glm/gtx/rotate_vector.hpp> // glm::rotate(vec3, angle, axis)
|
||||
#include <glm/gtc/epsilon.hpp>
|
||||
#include <cmath>
|
||||
#include <glm/gtc/quaternion.hpp> // glm::quat, glm::angleAxis
|
||||
#include <glm/gtx/quaternion.hpp> // operator*(quat, vec3)
|
||||
|
||||
void Rotator::Update() {
|
||||
m_CurrentAngle += m_Speed * static_cast<float>(0.001);
|
||||
const float x = cos(m_CurrentAngle) * m_Distance;
|
||||
const float y = sin(m_CurrentAngle) * m_Distance;
|
||||
GetTransform().SetLocalPosition(m_OriginalPosition + glm::vec3(x, y, 0));
|
||||
glm::vec3 Rotator::MakePerpendicularUnitVector(const glm::vec3& axis)
|
||||
{
|
||||
// Pick any vector that is not parallel to axis, then cross to get perpendicular.
|
||||
const glm::vec3 a = glm::normalize(axis);
|
||||
const glm::vec3 ref = (std::abs(a.y) < 0.99f) ? glm::vec3(0, 1, 0) : glm::vec3(1, 0, 0);
|
||||
glm::vec3 perp = glm::cross(a, ref);
|
||||
|
||||
const float len2 = glm::dot(perp, perp);
|
||||
if (len2 < 1e-8f)
|
||||
return glm::vec3(1, 0, 0); // fallback
|
||||
|
||||
return perp / std::sqrt(len2);
|
||||
}
|
||||
|
||||
Rotator::Rotator(GameObject& parent, float distance, float speed)
|
||||
: Component(parent, "Rotator")
|
||||
, m_Distance(distance)
|
||||
, m_Speed(speed)
|
||||
, m_CurrentAngle(0.0f)
|
||||
{
|
||||
// Orbit around where we started (LOCAL), similar to your old behavior.
|
||||
m_Pivot = GetTransform().GetLocalPosition();
|
||||
|
||||
// Default axis is Z (so this behaves like your old XY circle by default).
|
||||
m_Axis = glm::vec3(0, 0, 1);
|
||||
|
||||
// Choose an initial offset that is perpendicular to the axis, with the requested radius.
|
||||
const glm::vec3 perp = MakePerpendicularUnitVector(m_Axis);
|
||||
m_InitialOffset = perp * m_Distance;
|
||||
|
||||
// Optional: if you'd rather keep the *current* position as the starting point on the orbit:
|
||||
// m_InitialOffset = GetTransform().GetLocalPosition() - m_Pivot;
|
||||
// m_Distance = glm::length(m_InitialOffset);
|
||||
}
|
||||
|
||||
void Rotator::SetPivotPosition(const glm::vec3& pivot)
|
||||
{
|
||||
m_Pivot = pivot;
|
||||
|
||||
// Recompute offset based on current position so it doesn't “jump”.
|
||||
m_InitialOffset = GetTransform().GetLocalPosition() - m_Pivot;
|
||||
const float len = glm::length(m_InitialOffset);
|
||||
|
||||
if (len > 1e-6f)
|
||||
m_Distance = len;
|
||||
else
|
||||
m_InitialOffset = MakePerpendicularUnitVector(m_Axis) * m_Distance;
|
||||
}
|
||||
|
||||
void Rotator::SetAxis(const glm::vec3& axis)
|
||||
{
|
||||
const float len2 = glm::dot(axis, axis);
|
||||
if (len2 < 1e-8f)
|
||||
return; // ignore invalid axis
|
||||
|
||||
m_Axis = glm::normalize(axis);
|
||||
|
||||
// Ensure the offset is perpendicular to the axis (remove any parallel component).
|
||||
m_InitialOffset -= m_Axis * glm::dot(m_Axis, m_InitialOffset);
|
||||
|
||||
const float offLen = glm::length(m_InitialOffset);
|
||||
if (offLen > 1e-6f)
|
||||
m_InitialOffset = (m_InitialOffset / offLen) * m_Distance;
|
||||
else
|
||||
m_InitialOffset = MakePerpendicularUnitVector(m_Axis) * m_Distance;
|
||||
}
|
||||
|
||||
void Rotator::SetDistance(float distance)
|
||||
{
|
||||
m_Distance = distance;
|
||||
|
||||
const float offLen = glm::length(m_InitialOffset);
|
||||
if (offLen > 1e-6f)
|
||||
m_InitialOffset = (m_InitialOffset / offLen) * m_Distance;
|
||||
else
|
||||
m_InitialOffset = MakePerpendicularUnitVector(m_Axis) * m_Distance;
|
||||
}
|
||||
|
||||
void Rotator::Update()
|
||||
{
|
||||
// Replace 0.001f with your engine delta time if you have one.
|
||||
m_CurrentAngle += m_Speed * 0.001f;
|
||||
|
||||
const glm::quat q = glm::angleAxis(m_CurrentAngle, glm::normalize(m_Axis));
|
||||
const glm::vec3 rotatedOffset = q * m_InitialOffset;
|
||||
GetTransform().SetLocalPosition(m_Pivot + rotatedOffset);
|
||||
}
|
||||
|
||||
26
destrum/src/Components/Spinner.cpp
Normal file
26
destrum/src/Components/Spinner.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <destrum/Components/Spinner.h>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include "destrum/ObjectModel/Transform.h"
|
||||
|
||||
void Spinner::Update()
|
||||
{
|
||||
// Replace with your engine dt if you have it available in Component.
|
||||
const float dt = 1.0f / 60.0f;
|
||||
|
||||
|
||||
m_Angle += m_Speed * dt;
|
||||
|
||||
// If you already have SetLocalRotation / SetWorldRotation, use that.
|
||||
// Here I'm assuming you can set rotation as a quaternion or Euler somewhere.
|
||||
// If not, tell me your Transform rotation API and I’ll adjust.
|
||||
|
||||
const glm::quat q = glm::angleAxis(m_Angle, m_Axis);
|
||||
|
||||
// Example APIs you might have:
|
||||
// GetTransform().SetLocalRotation(q);
|
||||
// or GetTransform().SetWorldRotation(q);
|
||||
|
||||
GetTransform().SetLocalRotation(q);
|
||||
}
|
||||
@@ -12,7 +12,17 @@ void AssetFS::Init(std::filesystem::path exeDir) {
|
||||
|
||||
void AssetFS::Mount(std::string scheme, std::filesystem::path root) {
|
||||
spdlog::debug("Mounting assetfs scheme '{}' to root '{}'", scheme, root.string());
|
||||
mounts.push_back({std::move(scheme), std::move(root)});
|
||||
|
||||
FSMount m;
|
||||
m.scheme = std::move(scheme);
|
||||
m.root = std::move(root);
|
||||
|
||||
const auto manifestPath = m.root / "manifest.json";
|
||||
if (std::filesystem::exists(manifestPath)) {
|
||||
m.manifest = FS::LoadAssetManifest(manifestPath);
|
||||
}
|
||||
|
||||
mounts.push_back(std::move(m));
|
||||
}
|
||||
|
||||
std::vector<uint8_t> AssetFS::ReadBytes(std::string_view vpath) {
|
||||
@@ -51,6 +61,37 @@ std::filesystem::path AssetFS::GetFullPath(std::string_view vpath) const {
|
||||
throw std::runtime_error("mount not found");
|
||||
}
|
||||
|
||||
std::filesystem::path AssetFS::GetCookedPathForFile(std::string_view vpath) const {
|
||||
assert(initialized && "AssetFS not initialized");
|
||||
|
||||
const auto pos = vpath.find("://");
|
||||
if (pos == std::string_view::npos)
|
||||
throw std::runtime_error("bad vpath");
|
||||
|
||||
const std::string scheme(vpath.substr(0, pos));
|
||||
const std::filesystem::path rel(std::string(vpath.substr(pos + 3)));
|
||||
const std::string relStr = rel.generic_string();
|
||||
|
||||
for (const auto& m : mounts) {
|
||||
if (m.scheme != scheme) continue;
|
||||
|
||||
// If we have a manifest, consult it
|
||||
if (m.manifest) {
|
||||
if (const ManifestAsset* asset = m.manifest->FindBySrc(relStr)) {
|
||||
if (asset->out) {
|
||||
return m.root / *asset->out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to raw file
|
||||
return m.root / rel;
|
||||
}
|
||||
|
||||
throw std::runtime_error("mount not found");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> AssetFS::ReadFile(const std::filesystem::path& fullPath) {
|
||||
std::ifstream file(fullPath, std::ios::binary);
|
||||
if (!file) {
|
||||
|
||||
43
destrum/src/FS/Manifest.cpp
Normal file
43
destrum/src/FS/Manifest.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#include <filesystem>
|
||||
#include <destrum/FS/Manifest.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
|
||||
AssetManifest FS::LoadAssetManifest(const std::filesystem::path& manifestPath) {
|
||||
std::ifstream f(manifestPath);
|
||||
if (!f) {
|
||||
throw std::runtime_error("Failed to open manifest: " + manifestPath.string());
|
||||
}
|
||||
|
||||
nlohmann::json j;
|
||||
f >> j;
|
||||
|
||||
AssetManifest manifest;
|
||||
manifest.version = j.value("version", 0);
|
||||
|
||||
if (!j.contains("assets") || !j["assets"].is_array()) {
|
||||
throw std::runtime_error("Invalid manifest format: missing assets array");
|
||||
}
|
||||
|
||||
for (const auto& a : j["assets"]) {
|
||||
ManifestAsset asset;
|
||||
asset.src = a.at("src").get<std::string>();
|
||||
asset.type = a.at("type").get<std::string>();
|
||||
asset.mtime_epoch_ns = a.value("mtime_epoch_ns", 0);
|
||||
asset.size_bytes = a.value("size_bytes", 0);
|
||||
|
||||
if (a.contains("out") && !a["out"].is_null()) {
|
||||
asset.out = a["out"].get<std::string>();
|
||||
}
|
||||
|
||||
// Normalize to forward slashes for cross-platform matching
|
||||
std::filesystem::path p(asset.src);
|
||||
asset.src = p.generic_string();
|
||||
|
||||
manifest.assetsBySrc.emplace(asset.src, std::move(asset));
|
||||
}
|
||||
|
||||
return manifest;
|
||||
}
|
||||
@@ -6,11 +6,13 @@
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
#include <glm/gtx/norm.hpp>
|
||||
|
||||
#include "glm/gtx/norm.hpp"
|
||||
|
||||
|
||||
Camera::Camera(const glm::vec3& position, const glm::vec3& up): m_position{position}, m_up{up} {
|
||||
Camera::Camera(const glm::vec3& position, const glm::vec3& up)
|
||||
: m_position{position}, m_up{up} {
|
||||
// Initialize yaw to -90 degrees so the camera faces -Z by default
|
||||
m_yaw = -glm::half_pi<float>();
|
||||
m_pitch = 0.0f;
|
||||
}
|
||||
|
||||
void Camera::Update(float deltaTime) {
|
||||
@@ -22,166 +24,126 @@ void Camera::Update(float deltaTime) {
|
||||
moveSpeed *= 2.0f;
|
||||
}
|
||||
|
||||
// Controller speed boost (pad0 LB)
|
||||
const SDL_JoystickID pad0 = input.GetPadInstanceId(0);
|
||||
if (pad0 >= 0 && input.IsPadButtonDown(pad0, SDL_CONTROLLER_BUTTON_LEFTSHOULDER)) {
|
||||
moveSpeed *= 3.0f;
|
||||
}
|
||||
|
||||
// Clamp pitch like your old code
|
||||
m_pitch = glm::clamp(m_pitch, -glm::half_pi<float>() + 0.01f, glm::half_pi<float>() - 0.01f);
|
||||
|
||||
// =========================
|
||||
// Movement (Keyboard)
|
||||
// Look Input (Keyboard & Controller)
|
||||
// =========================
|
||||
glm::vec3 move(0.0f);
|
||||
|
||||
if (input.IsKeyDown(SDL_SCANCODE_W)) move += m_forward;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_S)) move -= m_forward;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_D)) move += m_right;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_A)) move -= m_right;
|
||||
|
||||
if (input.IsKeyDown(SDL_SCANCODE_Q)) move += m_up;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_E)) move -= m_up;
|
||||
|
||||
if (glm::length2(move) > 0.0f) {
|
||||
move = glm::normalize(move);
|
||||
m_position += move * (moveSpeed * deltaTime);
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Movement (Controller)
|
||||
// =========================
|
||||
if (pad0 >= 0) {
|
||||
const float lx = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_LEFTX); // [-1..1]
|
||||
const float ly = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_LEFTY); // [-1..1]
|
||||
|
||||
// SDL Y is typically +down, so invert for "forward"
|
||||
glm::vec3 padMove(0.0f);
|
||||
padMove += m_forward * (-ly);
|
||||
padMove += m_right * ( lx);
|
||||
|
||||
// Triggers for vertical movement (optional)
|
||||
// SDL controller triggers are axes too: 0..1-ish after normalization in our helper, but signless.
|
||||
// With our NormalizeAxis, triggers will sit near 0 until pressed (depending on mapping).
|
||||
// If your NormalizeAxis maps triggers weirdly, swap to raw event value approach.
|
||||
const float lt = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
|
||||
const float rt = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_TRIGGERLEFT);
|
||||
const float vertical = (rt - lt);
|
||||
padMove += m_up * vertical;
|
||||
|
||||
if (glm::length2(padMove) > 0.0001f) {
|
||||
// do NOT normalize: preserve analog magnitude for smooth movement
|
||||
m_position += padMove * (moveSpeed * deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Look (Keyboard arrows only)
|
||||
// =========================
|
||||
// Use radians/sec so framerate-independent
|
||||
const float keyLookSpeed = glm::radians(120.0f); // degrees per second
|
||||
|
||||
const float keyLookSpeed = glm::radians(120.0f);
|
||||
if (input.IsKeyDown(SDL_SCANCODE_UP)) m_pitch += keyLookSpeed * deltaTime;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_DOWN)) m_pitch -= keyLookSpeed * deltaTime;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_LEFT)) m_yaw -= keyLookSpeed * deltaTime;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_RIGHT)) m_yaw += keyLookSpeed * deltaTime;
|
||||
|
||||
// =========================
|
||||
// Look (Controller right stick)
|
||||
// =========================
|
||||
if (pad0 >= 0) {
|
||||
const float rx = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_RIGHTX);
|
||||
const float ry = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_RIGHTY);
|
||||
|
||||
const float padLookSpeed = 2.2f; // radians/sec at full deflection
|
||||
const float padLookSpeed = 2.2f;
|
||||
m_yaw += rx * padLookSpeed * deltaTime;
|
||||
m_pitch += ry * padLookSpeed * deltaTime;
|
||||
m_pitch -= ry * padLookSpeed * deltaTime; // Inverted to match stick convention
|
||||
}
|
||||
|
||||
// Clamp pitch again after modifications
|
||||
// Clamp pitch to prevent flipping over the top
|
||||
m_pitch = glm::clamp(m_pitch, -glm::half_pi<float>() + 0.01f, glm::half_pi<float>() - 0.01f);
|
||||
|
||||
// Recompute basis from yaw/pitch (same convention you used)
|
||||
const glm::mat4 yawMatrix = glm::rotate(glm::mat4(1.0f), -m_yaw, glm::vec3(0, 1, 0));
|
||||
const glm::mat4 pitchMatrix = glm::rotate(glm::mat4(1.0f), m_pitch, glm::vec3(0, 0, 1));
|
||||
const glm::mat4 rotation = yawMatrix * pitchMatrix;
|
||||
// =========================
|
||||
// Update Basis Vectors
|
||||
// =========================
|
||||
// Standard Spherical to Cartesian coordinates (Y-Up, Right-Handed)
|
||||
glm::vec3 front;
|
||||
front.x = cos(m_yaw) * cos(m_pitch);
|
||||
front.y = sin(m_pitch);
|
||||
front.z = sin(m_yaw) * cos(m_pitch);
|
||||
|
||||
m_forward = glm::normalize(glm::vec3(rotation * glm::vec4(1, 0, 0, 0))); // +X forward
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
m_forward = glm::normalize(front);
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0))); // World Up
|
||||
m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
|
||||
// keep target mode off when manually controlled
|
||||
m_useTarget = false;
|
||||
// =========================
|
||||
// Movement Input
|
||||
// =========================
|
||||
glm::vec3 move(0.0f);
|
||||
if (input.IsKeyDown(SDL_SCANCODE_W)) move += m_forward;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_S)) move -= m_forward;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_D)) move += m_right;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_A)) move -= m_right;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_Q)) move += glm::vec3(0, 1, 0); // Absolute Up
|
||||
if (input.IsKeyDown(SDL_SCANCODE_E)) move -= glm::vec3(0, 1, 0); // Absolute Down
|
||||
|
||||
if (glm::length2(move) > 0.0f) {
|
||||
m_position += glm::normalize(move) * (moveSpeed * deltaTime);
|
||||
}
|
||||
|
||||
// Controller Movement
|
||||
if (pad0 >= 0) {
|
||||
const float lx = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_LEFTX);
|
||||
const float ly = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_LEFTY);
|
||||
const float lt = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
|
||||
const float rt = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_TRIGGERLEFT);
|
||||
|
||||
glm::vec3 padMove = (m_forward * -ly) + (m_right * lx) + (glm::vec3(0, 1, 0) * (lt - rt));
|
||||
if (glm::length2(padMove) > 0.0001f) {
|
||||
m_position += padMove * (moveSpeed * deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
m_useTarget = false;
|
||||
CalculateProjectionMatrix();
|
||||
CalculateViewMatrix();
|
||||
}
|
||||
|
||||
void Camera::CalculateViewMatrix() {
|
||||
if (m_useTarget) {
|
||||
m_forward = glm::normalize(m_target - m_position);
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
m_viewMatrix = glm::lookAt(m_position, m_target, m_up);
|
||||
m_viewMatrix = glm::lookAt(m_position, m_target, glm::vec3(0, 1, 0));
|
||||
} else {
|
||||
m_viewMatrix = glm::lookAt(m_position, m_position + m_forward, m_up);
|
||||
}
|
||||
|
||||
m_invMatrix = glm::inverse(m_viewMatrix);
|
||||
}
|
||||
|
||||
void Camera::CalculateProjectionMatrix() {
|
||||
// RH_ZO: Right-Handed, Zero-to-One depth (Vulkan/D3D standard)
|
||||
m_projectionMatrix = glm::perspectiveRH_ZO(glm::radians(fovAngle), m_aspectRatio, m_zNear, m_zFar);
|
||||
|
||||
// CRITICAL VULKAN FIX: Flip Y-axis
|
||||
// This keeps the world upright and fixes winding order issues
|
||||
m_projectionMatrix[1][1] *= -1;
|
||||
}
|
||||
|
||||
void Camera::ClearTarget() {
|
||||
m_useTarget = false;
|
||||
m_forward = glm::normalize(m_target - m_position);
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
}
|
||||
|
||||
void Camera::SetTarget(const glm::vec3& target) {
|
||||
m_target = target;
|
||||
m_useTarget = true;
|
||||
// m_forward = glm::normalize(m_target - m_position);
|
||||
// m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
// m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
}
|
||||
|
||||
void Camera::Target(const glm::vec3& target) {
|
||||
glm::vec3 directionToTarget = glm::normalize(target - m_position);
|
||||
|
||||
m_forward = glm::normalize(target - m_position);
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
|
||||
m_viewMatrix = glm::lookAt(m_position, m_position + m_forward, m_up);
|
||||
m_invMatrix = glm::inverse(m_viewMatrix);
|
||||
}
|
||||
// ---------------------------------------------------------
|
||||
// Helpers to keep orientation consistent
|
||||
// ---------------------------------------------------------
|
||||
|
||||
void Camera::SetRotation(float yawRadians, float pitchRadians) {
|
||||
m_yaw = yawRadians;
|
||||
m_pitch = glm::clamp(
|
||||
pitchRadians,
|
||||
-glm::half_pi<float>() + 0.001f,
|
||||
glm::half_pi<float>() - 0.001f
|
||||
);
|
||||
m_pitch = glm::clamp(pitchRadians, -glm::half_pi<float>() + 0.001f, glm::half_pi<float>() - 0.001f);
|
||||
|
||||
// Yaw around world Y, pitch around local Z (same convention you used)
|
||||
const glm::mat4 yawMatrix = glm::rotate(glm::mat4(1.0f), -m_yaw, glm::vec3(0, 1, 0));
|
||||
const glm::mat4 pitchMatrix = glm::rotate(glm::mat4(1.0f), m_pitch, glm::vec3(0, 0, 1));
|
||||
const glm::mat4 rotation = yawMatrix * pitchMatrix;
|
||||
|
||||
// Forward is +X in your camera space
|
||||
m_forward = glm::normalize(glm::vec3(rotation * glm::vec4(1, 0, 0, 0)));
|
||||
glm::vec3 front;
|
||||
front.x = cos(m_yaw) * cos(m_pitch);
|
||||
front.y = sin(m_pitch);
|
||||
front.z = sin(m_yaw) * cos(m_pitch);
|
||||
m_forward = glm::normalize(front);
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
|
||||
m_useTarget = false; // rotation overrides target mode
|
||||
}
|
||||
|
||||
void Camera::SetRotation(const glm::vec2& yawPitchRadians) {
|
||||
SetRotation(yawPitchRadians.x, yawPitchRadians.y);
|
||||
}
|
||||
|
||||
void Camera::SetTarget(const glm::vec3& target) {
|
||||
}
|
||||
|
||||
void Camera::ClearTarget() {
|
||||
}
|
||||
|
||||
void Camera::Target(const glm::vec3& target) {
|
||||
m_target = target;
|
||||
m_useTarget = true;
|
||||
m_forward = glm::normalize(target - m_position);
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ void GfxDevice::init(SDL_Window* window, const std::string& appName, bool vSync)
|
||||
void GfxDevice::recreateSwapchain(int width, int height) {
|
||||
assert(width != 0 && height != 0);
|
||||
waitIdle();
|
||||
swapchain.recreateSwapchain(*this, swapchainFormat, width, height, false);
|
||||
swapchain.recreateSwapchain(*this, swapchainFormat, width, height, true);
|
||||
}
|
||||
|
||||
VkCommandBuffer GfxDevice::beginFrame() {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
#include <tiny_gltf.h>
|
||||
|
||||
ImageData::~ImageData()
|
||||
{
|
||||
|
||||
@@ -134,6 +134,12 @@ void Pipeline::CreateGraphicsPipeline(const std::string& vertPath, const std::st
|
||||
|
||||
CreateShaderModule(vertCode, &m_vertShaderModule);
|
||||
|
||||
// vkutil::addDebugLabel(
|
||||
// m_device.getDevice(),
|
||||
// m_fragShaderModule,
|
||||
// VertFileName.c_str()
|
||||
// );
|
||||
|
||||
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
|
||||
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
@@ -155,6 +161,13 @@ void Pipeline::CreateGraphicsPipeline(const std::string& vertPath, const std::st
|
||||
|
||||
CreateShaderModule(fragCode, &m_fragShaderModule);
|
||||
|
||||
// vkutil::addDebugLabel(
|
||||
// m_device.getDevice(),
|
||||
// m_fragShaderModule,
|
||||
// FragFileName.c_str()
|
||||
// );
|
||||
|
||||
|
||||
VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
|
||||
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
|
||||
@@ -10,17 +10,10 @@ MeshPipeline::~MeshPipeline() {
|
||||
void MeshPipeline::init(GfxDevice& gfxDevice, VkFormat drawImageFormat, VkFormat depthImageFormat) {
|
||||
const auto& device = gfxDevice.getDevice();
|
||||
|
||||
// const auto vertexShader = vkutil::loadShaderModule(AssetFS::GetInstance().GetFullPath("engine://shaders/mesh.vert.spv"), device);
|
||||
// const auto fragShader = vkutil::loadShaderModule(AssetFS::GetInstance().GetFullPath("engine://shaders/mesh.frag.spv"), device);
|
||||
const auto vertexShader = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/mesh.vert");
|
||||
const auto fragShader = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/mesh.frag");
|
||||
|
||||
|
||||
const auto vertexShader = AssetFS::GetInstance().GetFullPath("engine://shaders/mesh.vert.spv");
|
||||
const auto fragShader = AssetFS::GetInstance().GetFullPath("engine://shaders/mesh.frag.spv");
|
||||
|
||||
|
||||
// vkutil::addDebugLabel(device, vertexShader, "mesh.vert");
|
||||
// vkutil::addDebugLabel(device, vertexShader, "mesh.frag");
|
||||
|
||||
const auto bufferRange = VkPushConstantRange{
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
.offset = 0,
|
||||
|
||||
@@ -91,6 +91,16 @@ void vkutil::addDebugLabel(VkDevice device, VkImage image, const char* label) {
|
||||
vkSetDebugUtilsObjectNameEXT(device, &nameInfo);
|
||||
}
|
||||
|
||||
void vkutil::addDebugLabel(VkDevice device, VkShaderModule shaderModule, const char* label) {
|
||||
const auto nameInfo = VkDebugUtilsObjectNameInfoEXT{
|
||||
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
|
||||
.objectType = VK_OBJECT_TYPE_SHADER_MODULE,
|
||||
.objectHandle = (std::uint64_t)shaderModule,
|
||||
.pObjectName = label,
|
||||
};
|
||||
vkSetDebugUtilsObjectNameEXT(device, &nameInfo);
|
||||
}
|
||||
|
||||
void vkutil::addDebugLabel(VkDevice device, VkBuffer buffer, const char* label) {
|
||||
const auto nameInfo = VkDebugUtilsObjectNameInfoEXT{
|
||||
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
// #include "Managers/ResourceManager.h"
|
||||
|
||||
GameObject::~GameObject() {
|
||||
spdlog::debug("GameObject destroyed: {}", GetName());
|
||||
// spdlog::debug("GameObject destroyed: {}", GetName());
|
||||
}
|
||||
|
||||
void GameObject::SetActiveDirty() {
|
||||
|
||||
@@ -9,12 +9,11 @@ Object::~Object() {
|
||||
if (!m_BeingDestroyed) {
|
||||
assert(false && "Objects destructor called before destroy");
|
||||
}
|
||||
spdlog::debug("Object Destroyed: {}", m_Name);
|
||||
// spdlog::debug("Object Destroyed: {}", m_Name);
|
||||
}
|
||||
|
||||
void Object::Destroy() {
|
||||
std::cout << "Marked Object for destruction: " << m_Name << std::endl;
|
||||
spdlog::debug("Object Destroyed: {}", m_Name);
|
||||
// spdlog::debug("Object marked for destruction: {}", m_Name);
|
||||
m_BeingDestroyed = true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user