Skip to content

Commit

Permalink
Merge pull request #207 from RagnarokResearchLab/camera-target-debugging
Browse files Browse the repository at this point in the history
Allow moving the camera target via SHIFT + arrow keys
  • Loading branch information
rdw-software authored Nov 23, 2023
2 parents a2b6cf8 + 5f0c05c commit 671354c
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 4 deletions.
16 changes: 15 additions & 1 deletion Core/NativeClient/C_Camera.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ local C_Camera = {
DEGREES_PER_ZOOM_LEVEL = 5,
MIN_ORBIT_DISTANCE = 45,
MAX_ORBIT_DISTANCE = 80,
targetWorldPosition = Vector3D(0, 0, 0),
TARGET_DEBUG_STEPSIZE_IN_WORLD_UNITS = 12,
}

function C_Camera.CreatePerspectiveProjection(verticalFieldOfViewInDegrees, aspectRatio, zNearDistance, zFarDistance)
Expand Down Expand Up @@ -155,11 +157,13 @@ function C_Camera.StopAdjustingView()
end

function C_Camera.GetWorldPosition()
return C_Camera.ComputeOrbitPositionInLocalSpace(
local orbitPositionRelativeToTarget = C_Camera.ComputeOrbitPositionInLocalSpace(
C_Camera.horizontalRotationAngleInDegrees,
C_Camera.verticalRotationAngleInDegrees,
C_Camera.orbitDistanceInWorldUnits
)

return orbitPositionRelativeToTarget:Add(C_Camera.targetWorldPosition)
end

function C_Camera.GetHorizontalRotationAngle()
Expand Down Expand Up @@ -209,4 +213,14 @@ function C_Camera.SetOrbitDistance(distance)
C_Camera.orbitDistanceInWorldUnits = distance
end

function C_Camera.GetTargetPosition()
return C_Camera.targetWorldPosition
end

function C_Camera.SetTargetPosition(newPosition)
C_Camera.targetWorldPosition.x = newPosition.x
C_Camera.targetWorldPosition.y = newPosition.y
C_Camera.targetWorldPosition.z = newPosition.z
end

return C_Camera
35 changes: 34 additions & 1 deletion Core/NativeClient/NativeClient.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
local bit = require("bit")
local ffi = require("ffi")
local glfw = require("glfw")
local interop = require("interop")
Expand All @@ -6,6 +7,7 @@ local uv = require("uv")
local C_Camera = require("Core.NativeClient.C_Camera")
local C_Cursor = require("Core.NativeClient.C_Cursor")
local Renderer = require("Core.NativeClient.Renderer")
local Vector3D = require("Core.VectorMath.Vector3D")

local Box = require("Core.NativeClient.DebugDraw.Box")
local Cone = require("Core.NativeClient.DebugDraw.Cone")
Expand Down Expand Up @@ -261,7 +263,38 @@ function NativeClient:SCROLL_STATUS_CHANGED(eventID, payload)
end

function NativeClient:KEYPRESS_STATUS_CHANGED(eventID, payload)
print("KEYPRESS_STATUS_CHANGED")
local GLFW_KEY_LEFT = glfw.bindings.glfw_find_constant("GLFW_KEY_LEFT")
local GLFW_KEY_RIGHT = glfw.bindings.glfw_find_constant("GLFW_KEY_RIGHT")
local GLFW_KEY_DOWN = glfw.bindings.glfw_find_constant("GLFW_KEY_DOWN")
local GLFW_KEY_UP = glfw.bindings.glfw_find_constant("GLFW_KEY_UP")
local GLFW_MOD_SHIFT = glfw.bindings.glfw_find_constant("GLFW_MOD_SHIFT")
local GLFW_PRESS = glfw.bindings.glfw_find_constant("GLFW_PRESS")
local wasKeyPressed = tonumber(payload.key_details.action) == GLFW_PRESS
if not wasKeyPressed then
return
end

local isModifiedBySHIFT = bit.band(payload.key_details.mods, GLFW_MOD_SHIFT) == 1
if not isModifiedBySHIFT then
return
end

local wasLeftKey = payload.key_details.key == GLFW_KEY_LEFT
local wasRightKey = payload.key_details.key == GLFW_KEY_RIGHT
local wasUpKey = payload.key_details.key == GLFW_KEY_UP
local wasDownKey = payload.key_details.key == GLFW_KEY_DOWN
local movementDirectionX = wasLeftKey and -1 or 0
movementDirectionX = wasRightKey and 1 or movementDirectionX
local movementDirectionZ = wasUpKey and 1 or 0
movementDirectionZ = wasDownKey and -1 or movementDirectionZ

local movementDistanceInWorldUnits = C_Camera.TARGET_DEBUG_STEPSIZE_IN_WORLD_UNITS
local translation = Vector3D(
movementDirectionX * movementDistanceInWorldUnits,
0,
movementDirectionZ * movementDistanceInWorldUnits
)
C_Camera.targetWorldPosition = C_Camera.targetWorldPosition:Add(translation)
end

function NativeClient:UNICODE_INPUT_RECEIVED(eventID, payload)
Expand Down
4 changes: 2 additions & 2 deletions Core/NativeClient/Renderer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,10 @@ function Renderer:UpdateUniformBuffer()
local perSceneUniformData = self.perSceneUniformData

local cameraWorldPosition = C_Camera.GetWorldPosition()
local targetWorldPosition = Vector3D(0, 0, 0)
local cameraTarget = C_Camera.GetTargetPosition()
local upVectorHint = Vector3D(0, 1, 0)
local perspective = C_Camera.GetPerspective()
perSceneUniformData.view = C_Camera.CreateOrbitalView(cameraWorldPosition, targetWorldPosition, upVectorHint)
perSceneUniformData.view = C_Camera.CreateOrbitalView(cameraWorldPosition, cameraTarget, upVectorHint)
perSceneUniformData.perspectiveProjection =
C_Camera.CreatePerspectiveProjection(perspective.fov, aspectRatio, perspective.nearZ, perspective.farZ)
perSceneUniformData.time = ffi.new("float", currentTime)
Expand Down
32 changes: 32 additions & 0 deletions Tests/NativeClient/C_Camera.spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,38 @@ describe("C_Camera", function()

C_Camera.ResetView()
end)

it("should take into account the camera's focus target", function()
local positionBefore = C_Camera.GetWorldPosition()
local targetPosition = Vector3D(1, 2, 3)
C_Camera.SetTargetPosition(targetPosition)

local defaultCameraPosition = C_Camera.ComputeOrbitPositionInLocalSpace(
C_Camera.DEFAULT_HORIZONTAL_ROTATION,
C_Camera.DEFAULT_VERTICAL_ROTATION,
C_Camera.DEFAULT_ORBIT_DISTANCE
)

assertEquals(positionBefore.x, defaultCameraPosition.x)
assertEquals(positionBefore.y, defaultCameraPosition.y)
assertEquals(positionBefore.z, defaultCameraPosition.z)

C_Camera.ApplyHorizontalRotation(90)
local newCameraPosition = C_Camera.ComputeOrbitPositionInLocalSpace(
C_Camera.DEFAULT_HORIZONTAL_ROTATION + 90,
C_Camera.DEFAULT_VERTICAL_ROTATION,
C_Camera.DEFAULT_ORBIT_DISTANCE
)
newCameraPosition = newCameraPosition:Add(targetPosition) -- Local to world space

local positionAfter = C_Camera.GetWorldPosition()
assertEquals(positionAfter.x, newCameraPosition.x)
assertEquals(positionAfter.y, newCameraPosition.y)
assertEquals(positionAfter.z, newCameraPosition.z)

C_Camera.ResetView()
C_Camera.SetTargetPosition(Vector3D(0, 0, 0))
end)
end)

describe("ApplyHorizontalRotation", function()
Expand Down
76 changes: 76 additions & 0 deletions Tests/NativeClient/NativeClient.spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ local glfw = require("glfw")
local C_Camera = require("Core.NativeClient.C_Camera")
local C_Cursor = require("Core.NativeClient.C_Cursor")
local NativeClient = require("Core.NativeClient.NativeClient")
local Vector3D = require("Core.VectorMath.Vector3D")

describe("NativeClient", function()
describe("CURSOR_MOVED", function()
Expand Down Expand Up @@ -479,4 +480,79 @@ describe("NativeClient", function()
end
)
end)

describe("KEYPRESS_STATUS_CHANGED", function()
local originalCameraTarget = C_Camera.GetTargetPosition()
after(function()
C_Camera.SetTargetPosition(originalCameraTarget)
end)

it("should adjust the camera target if SHIFT + LEFT was pressed", function()
local event = ffi.new("deferred_event_t")
event.key_details.key = glfw.bindings.glfw_find_constant("GLFW_KEY_LEFT")
event.key_details.action = glfw.bindings.glfw_find_constant("GLFW_PRESS")
event.key_details.mods = glfw.bindings.glfw_find_constant("GLFW_MOD_SHIFT")

NativeClient:KEYPRESS_STATUS_CHANGED("KEYPRESS_STATUS_CHANGED", event)

local newCameraTarget = C_Camera.GetTargetPosition()
local expectedTranslation = Vector3D(-C_Camera.TARGET_DEBUG_STEPSIZE_IN_WORLD_UNITS, 0, 0)
local expectedCameraTarget = originalCameraTarget:Add(expectedTranslation)

assertEquals(newCameraTarget.x, expectedCameraTarget.x)
assertEquals(newCameraTarget.y, expectedCameraTarget.y)
assertEquals(newCameraTarget.z, expectedCameraTarget.z)
end)

it("should adjust the camera target if SHIFT + RIGHT was pressed", function()
local event = ffi.new("deferred_event_t")
event.key_details.key = glfw.bindings.glfw_find_constant("GLFW_KEY_RIGHT")
event.key_details.action = glfw.bindings.glfw_find_constant("GLFW_PRESS")
event.key_details.mods = glfw.bindings.glfw_find_constant("GLFW_MOD_SHIFT")

NativeClient:KEYPRESS_STATUS_CHANGED("KEYPRESS_STATUS_CHANGED", event)

local newCameraTarget = C_Camera.GetTargetPosition()
local expectedTranslation = Vector3D(C_Camera.TARGET_DEBUG_STEPSIZE_IN_WORLD_UNITS, 0, 0)
local expectedCameraTarget = originalCameraTarget:Add(expectedTranslation)

assertEquals(newCameraTarget.x, expectedCameraTarget.x)
assertEquals(newCameraTarget.y, expectedCameraTarget.y)
assertEquals(newCameraTarget.z, expectedCameraTarget.z)
end)

it("should adjust the camera target if SHIFT + UP was pressed", function()
local event = ffi.new("deferred_event_t")
event.key_details.key = glfw.bindings.glfw_find_constant("GLFW_KEY_UP")
event.key_details.action = glfw.bindings.glfw_find_constant("GLFW_PRESS")
event.key_details.mods = glfw.bindings.glfw_find_constant("GLFW_MOD_SHIFT")

NativeClient:KEYPRESS_STATUS_CHANGED("KEYPRESS_STATUS_CHANGED", event)

local newCameraTarget = C_Camera.GetTargetPosition()
local expectedTranslation = Vector3D(0, 0, C_Camera.TARGET_DEBUG_STEPSIZE_IN_WORLD_UNITS)
local expectedCameraTarget = originalCameraTarget:Add(expectedTranslation)

assertEquals(newCameraTarget.x, expectedCameraTarget.x)
assertEquals(newCameraTarget.y, expectedCameraTarget.y)
assertEquals(newCameraTarget.z, expectedCameraTarget.z)
end)

it("should adjust the camera target if SHIFT + DOWN was pressed", function()
local event = ffi.new("deferred_event_t")
event.key_details.key = glfw.bindings.glfw_find_constant("GLFW_KEY_DOWN")
event.key_details.action = glfw.bindings.glfw_find_constant("GLFW_PRESS")
event.key_details.mods = glfw.bindings.glfw_find_constant("GLFW_MOD_SHIFT")

NativeClient:KEYPRESS_STATUS_CHANGED("KEYPRESS_STATUS_CHANGED", event)

local newCameraTarget = C_Camera.GetTargetPosition()
local expectedTranslation = Vector3D(0, 0, -C_Camera.TARGET_DEBUG_STEPSIZE_IN_WORLD_UNITS)
local expectedCameraTarget = originalCameraTarget:Add(expectedTranslation)

assertEquals(newCameraTarget.x, expectedCameraTarget.x)
assertEquals(newCameraTarget.y, expectedCameraTarget.y)
assertEquals(newCameraTarget.z, expectedCameraTarget.z)
end)
end)
end)

0 comments on commit 671354c

Please sign in to comment.