173 lines
4.9 KiB
Lua
173 lines
4.9 KiB
Lua
--[[
|
|
CameraUtils - Math utility functions shared by multiple camera scripts
|
|
2018 Camera Update - AllYourBlox
|
|
--]]
|
|
|
|
local CameraUtils = {}
|
|
|
|
local FFlagUserCameraToggle do
|
|
local success, result = pcall(function()
|
|
return UserSettings():IsUserFeatureEnabled("UserCameraToggle")
|
|
end)
|
|
FFlagUserCameraToggle = success and result
|
|
end
|
|
|
|
local function round(num)
|
|
return math.floor(num + 0.5)
|
|
end
|
|
|
|
-- Critically damped spring class for fluid motion effects
|
|
local Spring = {} do
|
|
Spring.__index = Spring
|
|
|
|
-- Initialize to a given undamped frequency and default position
|
|
function Spring.new(freq, pos)
|
|
return setmetatable({
|
|
freq = freq,
|
|
goal = pos,
|
|
pos = pos,
|
|
vel = 0,
|
|
}, Spring)
|
|
end
|
|
|
|
-- Advance the spring simulation by `dt` seconds
|
|
function Spring:step(dt)
|
|
local f = self.freq*2*math.pi
|
|
local g = self.goal
|
|
local p0 = self.pos
|
|
local v0 = self.vel
|
|
|
|
local offset = p0 - g
|
|
local decay = math.exp(-f*dt)
|
|
|
|
local p1 = (offset*(1 + f*dt) + v0*dt)*decay + g
|
|
local v1 = (v0*(1 - f*dt) - offset*(f*f*dt))*decay
|
|
|
|
self.pos = p1
|
|
self.vel = v1
|
|
|
|
return p1
|
|
end
|
|
end
|
|
|
|
CameraUtils.Spring = Spring
|
|
|
|
-- map a value from one range to another
|
|
function CameraUtils.map(x, inMin, inMax, outMin, outMax)
|
|
return (x - inMin)*(outMax - outMin)/(inMax - inMin) + outMin
|
|
end
|
|
|
|
-- From TransparencyController
|
|
function CameraUtils.Round(num, places)
|
|
local decimalPivot = 10^places
|
|
return math.floor(num * decimalPivot + 0.5) / decimalPivot
|
|
end
|
|
|
|
function CameraUtils.IsFinite(val)
|
|
return val == val and val ~= math.huge and val ~= -math.huge
|
|
end
|
|
|
|
function CameraUtils.IsFiniteVector3(vec3)
|
|
return CameraUtils.IsFinite(vec3.X) and CameraUtils.IsFinite(vec3.Y) and CameraUtils.IsFinite(vec3.Z)
|
|
end
|
|
|
|
-- Legacy implementation renamed
|
|
function CameraUtils.GetAngleBetweenXZVectors(v1, v2)
|
|
return math.atan2(v2.X*v1.Z-v2.Z*v1.X, v2.X*v1.X+v2.Z*v1.Z)
|
|
end
|
|
|
|
function CameraUtils.RotateVectorByAngleAndRound(camLook, rotateAngle, roundAmount)
|
|
if camLook.Magnitude > 0 then
|
|
camLook = camLook.unit
|
|
local currAngle = math.atan2(camLook.z, camLook.x)
|
|
local newAngle = round((math.atan2(camLook.z, camLook.x) + rotateAngle) / roundAmount) * roundAmount
|
|
return newAngle - currAngle
|
|
end
|
|
return 0
|
|
end
|
|
|
|
-- K is a tunable parameter that changes the shape of the S-curve
|
|
-- the larger K is the more straight/linear the curve gets
|
|
local k = 0.35
|
|
local lowerK = 0.8
|
|
local function SCurveTranform(t)
|
|
t = math.clamp(t, -1, 1)
|
|
if t >= 0 then
|
|
return (k*t) / (k - t + 1)
|
|
end
|
|
return -((lowerK*-t) / (lowerK + t + 1))
|
|
end
|
|
|
|
local DEADZONE = 0.1
|
|
local function toSCurveSpace(t)
|
|
return (1 + DEADZONE) * (2*math.abs(t) - 1) - DEADZONE
|
|
end
|
|
|
|
local function fromSCurveSpace(t)
|
|
return t/2 + 0.5
|
|
end
|
|
|
|
function CameraUtils.GamepadLinearToCurve(thumbstickPosition)
|
|
local function onAxis(axisValue)
|
|
local sign = 1
|
|
if axisValue < 0 then
|
|
sign = -1
|
|
end
|
|
local point = fromSCurveSpace(SCurveTranform(toSCurveSpace(math.abs(axisValue))))
|
|
point = point * sign
|
|
return math.clamp(point, -1, 1)
|
|
end
|
|
return Vector2.new(onAxis(thumbstickPosition.x), onAxis(thumbstickPosition.y))
|
|
end
|
|
|
|
-- This function converts 4 different, redundant enumeration types to one standard so the values can be compared
|
|
function CameraUtils.ConvertCameraModeEnumToStandard(enumValue)
|
|
if enumValue == Enum.TouchCameraMovementMode.Default then
|
|
return Enum.ComputerCameraMovementMode.Follow
|
|
end
|
|
|
|
if enumValue == Enum.ComputerCameraMovementMode.Default then
|
|
return Enum.ComputerCameraMovementMode.Classic
|
|
end
|
|
|
|
if enumValue == Enum.TouchCameraMovementMode.Classic or
|
|
enumValue == Enum.DevTouchCameraMovementMode.Classic or
|
|
enumValue == Enum.DevComputerCameraMovementMode.Classic or
|
|
enumValue == Enum.ComputerCameraMovementMode.Classic then
|
|
return Enum.ComputerCameraMovementMode.Classic
|
|
end
|
|
|
|
if enumValue == Enum.TouchCameraMovementMode.Follow or
|
|
enumValue == Enum.DevTouchCameraMovementMode.Follow or
|
|
enumValue == Enum.DevComputerCameraMovementMode.Follow or
|
|
enumValue == Enum.ComputerCameraMovementMode.Follow then
|
|
return Enum.ComputerCameraMovementMode.Follow
|
|
end
|
|
|
|
if enumValue == Enum.TouchCameraMovementMode.Orbital or
|
|
enumValue == Enum.DevTouchCameraMovementMode.Orbital or
|
|
enumValue == Enum.DevComputerCameraMovementMode.Orbital or
|
|
enumValue == Enum.ComputerCameraMovementMode.Orbital then
|
|
return Enum.ComputerCameraMovementMode.Orbital
|
|
end
|
|
|
|
if FFlagUserCameraToggle then
|
|
if enumValue == Enum.ComputerCameraMovementMode.CameraToggle or
|
|
enumValue == Enum.DevComputerCameraMovementMode.CameraToggle then
|
|
return Enum.ComputerCameraMovementMode.CameraToggle
|
|
end
|
|
end
|
|
|
|
-- Note: Only the Dev versions of the Enums have UserChoice as an option
|
|
if enumValue == Enum.DevTouchCameraMovementMode.UserChoice or
|
|
enumValue == Enum.DevComputerCameraMovementMode.UserChoice then
|
|
return Enum.DevComputerCameraMovementMode.UserChoice
|
|
end
|
|
|
|
-- For any unmapped options return Classic camera
|
|
return Enum.ComputerCameraMovementMode.Classic
|
|
end
|
|
|
|
return CameraUtils
|
|
|