111 lines
2.9 KiB
Lua
111 lines
2.9 KiB
Lua
--[[
|
|
Poppercam - Occlusion module that brings the camera closer to the subject when objects are blocking the view.
|
|
--]]
|
|
|
|
local ZoomController = require(script.Parent:WaitForChild("ZoomController"))
|
|
|
|
local TransformExtrapolator = {} do
|
|
TransformExtrapolator.__index = TransformExtrapolator
|
|
|
|
local CF_IDENTITY = CFrame.new()
|
|
|
|
local function cframeToAxis(cframe)
|
|
local axis, angle = cframe:toAxisAngle()
|
|
return axis*angle
|
|
end
|
|
|
|
local function axisToCFrame(axis)
|
|
local angle = axis.magnitude
|
|
if angle > 1e-5 then
|
|
return CFrame.fromAxisAngle(axis, angle)
|
|
end
|
|
return CF_IDENTITY
|
|
end
|
|
|
|
local function extractRotation(cf)
|
|
local _, _, _, xx, yx, zx, xy, yy, zy, xz, yz, zz = cf:components()
|
|
return CFrame.new(0, 0, 0, xx, yx, zx, xy, yy, zy, xz, yz, zz)
|
|
end
|
|
|
|
function TransformExtrapolator.new()
|
|
return setmetatable({
|
|
lastCFrame = nil,
|
|
}, TransformExtrapolator)
|
|
end
|
|
|
|
function TransformExtrapolator:Step(dt, currentCFrame)
|
|
local lastCFrame = self.lastCFrame or currentCFrame
|
|
self.lastCFrame = currentCFrame
|
|
|
|
local currentPos = currentCFrame.p
|
|
local currentRot = extractRotation(currentCFrame)
|
|
|
|
local lastPos = lastCFrame.p
|
|
local lastRot = extractRotation(lastCFrame)
|
|
|
|
-- Estimate velocities from the delta between now and the last frame
|
|
-- This estimation can be a little noisy.
|
|
local dp = (currentPos - lastPos)/dt
|
|
local dr = cframeToAxis(currentRot*lastRot:inverse())/dt
|
|
|
|
local function extrapolate(t)
|
|
local p = dp*t + currentPos
|
|
local r = axisToCFrame(dr*t)*currentRot
|
|
return r + p
|
|
end
|
|
|
|
return {
|
|
extrapolate = extrapolate,
|
|
posVelocity = dp,
|
|
rotVelocity = dr,
|
|
}
|
|
end
|
|
|
|
function TransformExtrapolator:Reset()
|
|
self.lastCFrame = nil
|
|
end
|
|
end
|
|
|
|
--[[ The Module ]]--
|
|
local BaseOcclusion = require(script.Parent:WaitForChild("BaseOcclusion"))
|
|
local Poppercam = setmetatable({}, BaseOcclusion)
|
|
Poppercam.__index = Poppercam
|
|
|
|
function Poppercam.new()
|
|
local self = setmetatable(BaseOcclusion.new(), Poppercam)
|
|
self.focusExtrapolator = TransformExtrapolator.new()
|
|
return self
|
|
end
|
|
|
|
function Poppercam:GetOcclusionMode()
|
|
return Enum.DevCameraOcclusionMode.Zoom
|
|
end
|
|
|
|
function Poppercam:Enable(enable)
|
|
self.focusExtrapolator:Reset()
|
|
end
|
|
|
|
function Poppercam:Update(renderDt, desiredCameraCFrame, desiredCameraFocus, cameraController)
|
|
local rotatedFocus = CFrame.new(desiredCameraFocus.p, desiredCameraCFrame.p)*CFrame.new(
|
|
0, 0, 0,
|
|
-1, 0, 0,
|
|
0, 1, 0,
|
|
0, 0, -1
|
|
)
|
|
local extrapolation = self.focusExtrapolator:Step(renderDt, rotatedFocus)
|
|
local zoom = ZoomController.Update(renderDt, rotatedFocus, extrapolation)
|
|
return rotatedFocus*CFrame.new(0, 0, zoom), desiredCameraFocus
|
|
end
|
|
|
|
-- Called when character is added
|
|
function Poppercam:CharacterAdded(character, player)
|
|
end
|
|
|
|
-- Called when character is about to be removed
|
|
function Poppercam:CharacterRemoving(character, player)
|
|
end
|
|
|
|
function Poppercam:OnCameraSubjectChanged(newSubject)
|
|
end
|
|
|
|
return Poppercam |