Debug options: Stop moving light, camera and cubes.

F1 to have free camera
This commit is contained in:
2026-02-23 22:05:46 -05:00
parent 3277624ec2
commit 581656568b
14 changed files with 263 additions and 56 deletions

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

@@ -9,16 +9,23 @@ struct PointLight
float Intensity; float Intensity;
}; };
struct TransformData
{
row_major float4x4 Model;
};
cbuffer RootConstants : register(b0, space0) cbuffer RootConstants : register(b0, space0)
{ {
row_major float4x4 ViewProjection; row_major float4x4 ViewProjection;
row_major float4x4 Model; uint MeshIndex;
uint TransformsBufferIndex;
uint BufferIndex; uint BufferIndex;
uint TextureIndex; uint TextureIndex;
uint VertexOffset; // Base vertex for indexed drawing with bindless buffers uint VertexOffset; // Base vertex for indexed drawing with bindless buffers
uint _Padding; // Padding for alignment uint _Padding; // Padding for alignment
float2 Scale; // 2D scale factor float2 Scale; // 2D scale factor
float2 Translate; // 2D translation float2 Translate; // 2D translation
float2 _Padding2; // Explicit padding to align LightDirection to 16 bytes
float3 LightDirection; // Normalized, world-space float3 LightDirection; // Normalized, world-space
float LightPad; float LightPad;

View File

@@ -21,6 +21,10 @@ Output main(uint vertexIndex : SV_VertexID)
float3 normal = asfloat(buffer.Load3(offset + 12)); float3 normal = asfloat(buffer.Load3(offset + 12));
float4 col = asfloat(buffer.Load4(offset + 24)); float4 col = asfloat(buffer.Load4(offset + 24));
// Fetch Model Matrix
StructuredBuffer<TransformData> transformsBuffer = ResourceDescriptorHeap[TransformsBufferIndex];
float4x4 Model = transformsBuffer[MeshIndex].Model;
float4 worldPos = mul(Model, float4(pos, 1.0f)); float4 worldPos = mul(Model, float4(pos, 1.0f));
output.Position = mul(ViewProjection, worldPos); output.Position = mul(ViewProjection, worldPos);
output.Color = col; output.Color = col;

View File

@@ -45,6 +45,15 @@ namespace Juliet
return result; return result;
} }
[[nodiscard]] inline Matrix MatrixScale(float x, float y, float z)
{
Matrix result = MatrixIdentity();
result.m[0][0] = x;
result.m[1][1] = y;
result.m[2][2] = z;
return result;
}
[[nodiscard]] inline Matrix MatrixRotationX(float radians) [[nodiscard]] inline Matrix MatrixRotationX(float radians)
{ {
float c = cosf(radians); float c = cosf(radians);

View File

@@ -9,13 +9,15 @@ namespace Juliet
struct PushData struct PushData
{ {
Matrix ViewProjection; Matrix ViewProjection;
Matrix Model; uint32 MeshIndex;
uint32 TransformsBufferIndex;
uint32 BufferIndex; uint32 BufferIndex;
uint32 TextureIndex; uint32 TextureIndex;
uint32 VertexOffset; uint32 VertexOffset;
uint32 Padding; uint32 Padding;
float Scale[2]; float Scale[2];
float Translate[2]; float Translate[2];
float Padding2[2];
Vector3 LightDirection; Vector3 LightDirection;
float LightPad; float LightPad;

View File

@@ -300,12 +300,11 @@ namespace Juliet
// Render depth-tested primitives (vertices at offset 0 in buffer) // Render depth-tested primitives (vertices at offset 0 in buffer)
if (g_DebugState.DepthTestedVertexCount > 0 && g_DebugState.DepthTestedPipeline && g_DebugState.VertexBuffer) if (g_DebugState.DepthTestedVertexCount > 0 && g_DebugState.DepthTestedPipeline && g_DebugState.VertexBuffer)
{ {
BindGraphicsPipeline(renderPass, g_DebugState.DepthTestedPipeline); // Pack VP matrix + buffer index into push constants
// Pack VP matrix + Model (identity for debug) + buffer index into push constants
PushData pushData = {}; PushData pushData = {};
pushData.ViewProjection = Camera_GetViewProjectionMatrix(camera); pushData.ViewProjection = Camera_GetViewProjectionMatrix(camera);
pushData.Model = MatrixIdentity(); pushData.MeshIndex = 0;
pushData.TransformsBufferIndex = 0; // Not used by debug shader but layout must match
pushData.BufferIndex = bufferIndex; pushData.BufferIndex = bufferIndex;
pushData.TextureIndex = 0; pushData.TextureIndex = 0;
pushData.VertexOffset = 0; // Depth-tested vertices start at 0 pushData.VertexOffset = 0; // Depth-tested vertices start at 0
@@ -329,10 +328,11 @@ namespace Juliet
{ {
BindGraphicsPipeline(renderPass, g_DebugState.OverlayPipeline); BindGraphicsPipeline(renderPass, g_DebugState.OverlayPipeline);
// Pack VP matrix + Model (identity for debug) + buffer index into push constants // Pack VP matrix + buffer index into push constants
PushData pushData = {}; PushData pushData = {};
pushData.ViewProjection = Camera_GetViewProjectionMatrix(camera); pushData.ViewProjection = Camera_GetViewProjectionMatrix(camera);
pushData.Model = MatrixIdentity(); pushData.MeshIndex = 0;
pushData.TransformsBufferIndex = 0;
pushData.BufferIndex = bufferIndex; pushData.BufferIndex = bufferIndex;
pushData.TextureIndex = 0; pushData.TextureIndex = 0;
pushData.VertexOffset = kMaxDebugVertices / 2; // Overlay vertices start at half pushData.VertexOffset = kMaxDebugVertices / 2; // Overlay vertices start at half

View File

@@ -12,7 +12,26 @@ namespace Juliet
{ {
namespace namespace
{ {
MeshRenderer g_MeshRenderer; struct MeshRendererState
{
GraphicsDevice* Device = nullptr;
GraphicsPipeline* Pipeline = nullptr;
GraphicsBuffer* VertexBuffer = nullptr;
GraphicsBuffer* IndexBuffer = nullptr;
GraphicsBuffer* LightsBuffer = nullptr;
GraphicsBuffer* TransformsBuffer = nullptr;
GraphicsTransferBuffer* LoadCopyBuffer = nullptr;
VectorArena<Mesh, kDefaultMeshNumber, false> Meshes;
VectorArena<Vertex, kDefaultVertexCount, false> Vertices;
VectorArena<Index, kDefaultIndexCount, false> Indices;
VectorArena<PointLight, kDefaultLightCount, false> PointLights;
PointLight* MappedLights = nullptr;
Matrix* MappedTransforms = nullptr;
};
MeshRendererState g_MeshRenderer;
} // namespace } // namespace
void InitializeMeshRenderer(NonNullPtr<Arena> arena) void InitializeMeshRenderer(NonNullPtr<Arena> arena)
@@ -92,6 +111,18 @@ namespace Juliet
g_MeshRenderer.MappedLights = static_cast<PointLight*>(MapGraphicsBuffer(graphicsDevice, g_MeshRenderer.LightsBuffer)); g_MeshRenderer.MappedLights = static_cast<PointLight*>(MapGraphicsBuffer(graphicsDevice, g_MeshRenderer.LightsBuffer));
Assert(g_MeshRenderer.MappedLights != nullptr); Assert(g_MeshRenderer.MappedLights != nullptr);
// Transforms Buffer
BufferCreateInfo transformsBufferCI = {};
transformsBufferCI.Size = 10000 * sizeof(Matrix); // Max 10000 meshes for now
transformsBufferCI.Stride = sizeof(Matrix);
transformsBufferCI.Usage = BufferUsage::StructuredBuffer;
transformsBufferCI.IsDynamic = true;
g_MeshRenderer.TransformsBuffer = CreateGraphicsBuffer(graphicsDevice, transformsBufferCI);
Assert(g_MeshRenderer.TransformsBuffer != nullptr);
g_MeshRenderer.MappedTransforms =
static_cast<Matrix*>(MapGraphicsBuffer(graphicsDevice, g_MeshRenderer.TransformsBuffer));
Assert(g_MeshRenderer.MappedTransforms != nullptr);
// Sync existing lights that might have been added before graphics initialization // Sync existing lights that might have been added before graphics initialization
for (index_t i = 0; i < g_MeshRenderer.PointLights.Count; ++i) for (index_t i = 0; i < g_MeshRenderer.PointLights.Count; ++i)
{ {
@@ -130,6 +161,14 @@ namespace Juliet
{ {
UnmapGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer); UnmapGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer);
DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer); DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer);
g_MeshRenderer.LightsBuffer = nullptr;
}
if (g_MeshRenderer.TransformsBuffer)
{
UnmapGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.TransformsBuffer);
DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.TransformsBuffer);
g_MeshRenderer.TransformsBuffer = nullptr;
} }
} }
@@ -214,15 +253,24 @@ namespace Juliet
uint32 vertexDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer); uint32 vertexDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer);
uint32 lightDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer); uint32 lightDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer);
uint32 transformsDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.TransformsBuffer);
pushData.BufferIndex = vertexDescriptorIndex; pushData.BufferIndex = vertexDescriptorIndex;
pushData.LightBufferIndex = lightDescriptorIndex; pushData.LightBufferIndex = lightDescriptorIndex;
pushData.TransformsBufferIndex = transformsDescriptorIndex;
pushData.ActiveLightCount = static_cast<uint32>(g_MeshRenderer.PointLights.Count); pushData.ActiveLightCount = static_cast<uint32>(g_MeshRenderer.PointLights.Count);
SetIndexBuffer(cmdList, g_MeshRenderer.IndexBuffer, IndexFormat::UInt16, g_MeshRenderer.Indices.Count, 0); SetIndexBuffer(cmdList, g_MeshRenderer.IndexBuffer, IndexFormat::UInt16, g_MeshRenderer.Indices.Count, 0);
uint32 meshIndex = 0;
for (Mesh& mesh : g_MeshRenderer.Meshes) for (Mesh& mesh : g_MeshRenderer.Meshes)
{ {
pushData.Model = mesh.Transform; if (g_MeshRenderer.MappedTransforms)
{
g_MeshRenderer.MappedTransforms[meshIndex] = mesh.Transform;
}
pushData.MeshIndex = meshIndex;
pushData.TextureIndex = 0; pushData.TextureIndex = 0;
pushData.VertexOffset = static_cast<uint32>(mesh.VertexOffset); pushData.VertexOffset = static_cast<uint32>(mesh.VertexOffset);
pushData.Padding = 0; pushData.Padding = 0;
@@ -233,6 +281,7 @@ namespace Juliet
SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData); SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
DrawIndexedPrimitives(pass, static_cast<uint32>(mesh.IndexCount), 1, static_cast<uint32>(mesh.IndexOffset), DrawIndexedPrimitives(pass, static_cast<uint32>(mesh.IndexCount), 1, static_cast<uint32>(mesh.IndexOffset),
static_cast<uint32>(mesh.VertexOffset), 0); static_cast<uint32>(mesh.VertexOffset), 0);
meshIndex++;
} }
} }
@@ -278,40 +327,40 @@ namespace Juliet
Mesh result = {}; Mesh result = {};
constexpr Vertex vertexData[] = { // Front Face (Z = -0.5f) — Red constexpr Vertex vertexData[] = { // Front Face (Z = -0.5f) — Red
{ { -0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 0.8f, 0.2f, 0.2f, 1.0f } }, { { -0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 0.8f, 0.2f, 0.2f, 1.0f } }, { { 0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 0.8f, 0.2f, 0.2f, 1.0f } }, { { 0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 0.8f, 0.2f, 0.2f, 1.0f } }, { { -0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
// Back Face (Z = 0.5f) — Green // Back Face (Z = 0.5f) — Green
{ { 0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.2f, 0.8f, 0.2f, 1.0f } }, { { 0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.2f, 0.8f, 0.2f, 1.0f } }, { { -0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.2f, 0.8f, 0.2f, 1.0f } }, { { -0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.2f, 0.8f, 0.2f, 1.0f } }, { { 0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
// Top Face (Y = 0.5f) — Blue // Top Face (Y = 0.5f) — Blue
{ { -0.5f, 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.2f, 0.2f, 0.8f, 1.0f } }, { { -0.5f, 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.2f, 0.2f, 0.8f, 1.0f } }, { { 0.5f, 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.2f, 0.2f, 0.8f, 1.0f } }, { { 0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.2f, 0.2f, 0.8f, 1.0f } }, { { -0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
// Bottom Face (Y = -0.5f) — Yellow // Bottom Face (Y = -0.5f) — Yellow
{ { -0.5f, -0.5f, -0.5f }, { 0.0f, -1.0f, 0.0f }, { 0.8f, 0.8f, 0.2f, 1.0f } }, { { -0.5f, -0.5f, -0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, -0.5f, -0.5f }, { 0.0f, -1.0f, 0.0f }, { 0.8f, 0.8f, 0.2f, 1.0f } }, { { 0.5f, -0.5f, -0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, -0.5f, 0.5f }, { 0.0f, -1.0f, 0.0f }, { 0.8f, 0.8f, 0.2f, 1.0f } }, { { 0.5f, -0.5f, 0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, -0.5f, 0.5f }, { 0.0f, -1.0f, 0.0f }, { 0.8f, 0.8f, 0.2f, 1.0f } }, { { -0.5f, -0.5f, 0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
// Right Face (X = 0.5f) — Cyan // Right Face (X = 0.5f) — Cyan
{ { 0.5f, 0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 0.2f, 0.8f, 0.8f, 1.0f } }, { { 0.5f, 0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f }, { 0.2f, 0.8f, 0.8f, 1.0f } }, { { 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, -0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f }, { 0.2f, 0.8f, 0.8f, 1.0f } }, { { 0.5f, -0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, -0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 0.2f, 0.8f, 0.8f, 1.0f } }, { { 0.5f, -0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
// Left Face (X = -0.5f) — Magenta // Left Face (X = -0.5f) — Magenta
{ { -0.5f, 0.5f, 0.5f }, { -1.0f, 0.0f, 0.0f }, { 0.8f, 0.2f, 0.8f, 1.0f } }, { { -0.5f, 0.5f, 0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, 0.5f, -0.5f }, { -1.0f, 0.0f, 0.0f }, { 0.8f, 0.2f, 0.8f, 1.0f } }, { { -0.5f, 0.5f, -0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, -0.5f, -0.5f }, { -1.0f, 0.0f, 0.0f }, { 0.8f, 0.2f, 0.8f, 1.0f } }, { { -0.5f, -0.5f, -0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, -0.5f, 0.5f }, { -1.0f, 0.0f, 0.0f }, { 0.8f, 0.2f, 0.8f, 1.0f } } { { -0.5f, -0.5f, 0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }
}; };
constexpr size_t cubeVertexCount = ArraySize(vertexData); constexpr size_t cubeVertexCount = ArraySize(vertexData);
result.VertexCount = cubeVertexCount; result.VertexCount = cubeVertexCount;

View File

@@ -84,7 +84,9 @@ namespace Juliet
PushData pushData = {}; PushData pushData = {};
pushData.ViewProjection = viewProjection; pushData.ViewProjection = viewProjection;
pushData.Model = MatrixIdentity(); pushData.MeshIndex = 0;
pushData.TransformsBufferIndex = 0;
pushData.BufferIndex = 0;
BindGraphicsPipeline(pass, g_SkyboxRenderer.Pipeline); BindGraphicsPipeline(pass, g_SkyboxRenderer.Pipeline);
SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData); SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);

View File

@@ -38,6 +38,18 @@
#endif #endif
static bool ShowMemoryDebugger = false; static bool ShowMemoryDebugger = false;
static bool animateCubes = true;
static bool animateLights = true;
static bool animateCamera = true;
static bool freeCameraMode = false;
static float camYaw = 0.0f;
static float camPitch = 0.0f;
static Juliet::Vector3 camPos = { 25.0f, 0.0f, 12.5f };
static float animateCubesTime = 0.0f;
static float animateLightsTime = 0.0f;
static float animateCameraTime = 0.0f;
// TODO : Replace with message box from framework + call main and not winmain + subsystem // TODO : Replace with message box from framework + call main and not winmain + subsystem
// TODO : Think how to do the draw pipeline. // TODO : Think how to do the draw pipeline.
@@ -226,6 +238,7 @@ void JulietApplication::Update()
bool reloadShaders = false; bool reloadShaders = false;
static bool reloadShadersDebounce = false; static bool reloadShadersDebounce = false;
static bool f1Debounce = false;
SystemEvent evt; SystemEvent evt;
while (GetEvent(evt)) while (GetEvent(evt))
@@ -249,18 +262,112 @@ void JulietApplication::Update()
{ {
reloadShadersDebounce = false; reloadShadersDebounce = false;
} }
if (evt.Type == EventType::Mouse_Move && freeCameraMode)
{
float sensitivity = 0.005f;
camYaw += evt.Data.MouseMovement.X_Displacement * sensitivity;
camPitch -= evt.Data.MouseMovement.Y_Displacement * sensitivity;
// Limit pitch to avoid flipping
if (camPitch > 1.5f) camPitch = 1.5f;
if (camPitch < -1.5f) camPitch = -1.5f;
} }
}
if (IsKeyDown(ScanCode::F1))
{
if (!f1Debounce)
{
freeCameraMode = !freeCameraMode;
f1Debounce = true;
}
}
else
{
f1Debounce = false;
}
if (freeCameraMode)
{
float speed = 10.0f * deltaTime;
if ((GetKeyModState() & KeyMod::Shift) != KeyMod::None)
{
speed *= 3.0f;
}
Vector3 forward = { cosf(camYaw) * cosf(camPitch), sinf(camYaw) * cosf(camPitch), sinf(camPitch) };
Vector3 right = { cosf(camYaw + 1.5708f), sinf(camYaw + 1.5708f), 0.0f };
Vector3 up = { 0.0f, 0.0f, 1.0f };
if (IsKeyDown(ScanCode::W)) camPos = camPos + forward * speed;
if (IsKeyDown(ScanCode::S)) camPos = camPos - forward * speed;
if (IsKeyDown(ScanCode::D)) camPos = camPos + right * speed;
if (IsKeyDown(ScanCode::A)) camPos = camPos - right * speed;
if (IsKeyDown(ScanCode::E)) camPos = camPos + up * speed;
if (IsKeyDown(ScanCode::Q)) camPos = camPos - up * speed;
}
if (animateCubes) animateCubesTime += deltaTime;
if (animateLights) animateLightsTime += deltaTime;
if (animateCamera) animateCameraTime += deltaTime;
#ifdef JULIET_ENABLE_IMGUI
ImGui::Begin("Debug Controls");
ImGui::Checkbox("Animate Cubes", &animateCubes);
ImGui::Checkbox("Animate Lights", &animateLights);
ImGui::Checkbox("Animate Camera", &animateCamera);
ImGui::End();
#endif
ArenaClear(GameScratchArena); ArenaClear(GameScratchArena);
Vector3 redLightPos{ cosf(CameraTime * 2.0f) * 5.0f, sinf(CameraTime * 2.0f) * 5.0f, 2.0f }; Vector3 redLightPos = { 5.0f, 5.0f, 2.0f };
Vector3 blueLightPos = { -5.0f, 0.0f, 2.0f };
if (animateLights || animateLightsTime > 0.0f)
{
redLightPos = { cosf(animateLightsTime * 2.0f) * 5.0f, sinf(animateLightsTime * 2.0f) * 5.0f, 2.0f };
blueLightPos = { -5.0f, cosf(animateLightsTime) * 3.0f, 2.0f };
}
SetPointLightPosition(RedLightID, redLightPos); SetPointLightPosition(RedLightID, redLightPos);
Vector3 blueLightPos{ -5.0f, cosf(CameraTime) * 3.0f, 2.0f };
SetPointLightPosition(BlueLightID, blueLightPos); SetPointLightPosition(BlueLightID, blueLightPos);
#ifdef JULIET_ENABLE_IMGUI // Animate the 100 cubes (10x10 grid)
ImGui::ShowDemoWindow(); constexpr int kGridSize = 10;
#endif constexpr float kSpacing = 2.5f;
constexpr float kOffset = (kGridSize - 1) * kSpacing * 0.5f;
for (int row = 0; row < kGridSize; ++row)
{
for (int col = 0; col < kGridSize; ++col)
{
MeshID cube = static_cast<MeshID>(row * kGridSize + col); // Assuming they were added first
float x = static_cast<float>(col) * kSpacing - kOffset;
float y = static_cast<float>(row) * kSpacing - kOffset;
float seed = static_cast<float>(cube);
float timeZ = animateCubesTime * 2.0f + seed * 0.5f;
float z = 0.0f;
float scaleF = 1.0f;
Matrix rotation = MatrixIdentity();
if (animateCubes || animateCubesTime > 0.0f)
{
z = sinf(timeZ) * 1.5f; // Oscillate up and down
scaleF = 1.0f + sinf(animateCubesTime * 1.5f + seed) * 0.3f; // Pulse scale
rotation = MatrixRotation(animateCubesTime * 1.2f + seed * 0.73f, animateCubesTime * 0.8f + seed * 1.17f,
animateCubesTime * 0.5f + seed * 0.53f);
}
Matrix scale = MatrixScale(scaleF, scaleF, scaleF);
SetMeshTransform(cube, MatrixTranslation(x, y, z) * rotation * scale);
}
}
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f }, false); DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f }, false);
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, true); DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, true);
@@ -358,20 +465,33 @@ DepthStencilTargetInfo* JulietApplication::GetDepthTargetInfo()
Camera JulietApplication::GetDebugCamera() Camera JulietApplication::GetDebugCamera()
{ {
float time = CameraTime; if (freeCameraMode)
{
float orbitSpeed = 0.5f; Camera cam = {};
float currentOrbitTime = time * orbitSpeed; cam.Position = camPos;
cam.Target = camPos + Vector3{ cosf(camYaw) * cosf(camPitch), sinf(camYaw) * cosf(camPitch), sinf(camPitch) };
cam.Up = { 0.0f, 0.0f, 1.0f };
cam.FOV = 1.047f;
cam.AspectRatio = 1200.0f / 800.0f;
cam.NearPlane = 0.1f;
cam.FarPlane = 1000.0f;
return cam;
}
// --- Adjusted for 1-Meter Scale --- // --- Adjusted for 1-Meter Scale ---
float baseRadius = 25.0f; // Increased to see 10x10 cube grid float baseRadius = 25.0f; // Increased to see 10x10 cube grid
float radius = baseRadius; float radius = baseRadius;
//* Uncomment for active zoom
if (animateCamera || animateCameraTime > 0.0f)
{
float orbitSpeed = 0.5f;
float currentOrbitTime = animateCameraTime * orbitSpeed;
float zoomAmplitude = 15.0f; float zoomAmplitude = 15.0f;
float zoomSpeed = 0.5f; float zoomSpeed = 0.5f;
radius = baseRadius + (sinf(time * zoomSpeed) * zoomAmplitude); radius = baseRadius + (sinf(animateCameraTime * zoomSpeed) * zoomAmplitude);
//*/
float zHeight = radius * 0.5f; // Keep a nice downward viewing angle float zHeight = radius * 0.5f; // Keep a nice downward viewing angle
Camera cam = {}; Camera cam = {};
@@ -386,6 +506,20 @@ Camera JulietApplication::GetDebugCamera()
return cam; return cam;
} }
float zHeight = radius * 0.5f; // Keep a nice downward viewing angle
Camera cam = {};
cam.Position = { radius, 0.0f, zHeight };
cam.Target = { 0.0f, 0.0f, 0.0f };
cam.Up = { 0.0f, 0.0f, 1.0f };
cam.FOV = 1.047f;
cam.AspectRatio = 1200.0f / 800.0f;
cam.NearPlane = 0.1f;
cam.FarPlane = 1000.0f;
return cam;
}
bool JulietApplication::IsRunning() bool JulietApplication::IsRunning()
{ {
return Running; return Running;