[Closed] turn 3d tracked camera data into 2d retiming curve?
hi everyone,
this might be a little off-topic, but since i am using maxscript to solve it, i just ask.
i am having a problem i can’t quite solve:
i have two filmed dollyshots that i want to retime to perfectly match.
the dolly is a 180 degrees arc on the floor. the foreground plate was filmed in a studio (actors in front of greenscreen), the other was filmed outside on the exact same dolly with a slower moving camera (so there are enough in-between frames)
i 3d tracked both plates and brought them to max to extract data that i can use in a retime curve in my compositing software.
so far, so good.
now i am trying to write a script, that calculates a retime curve based on the two different camera speeds.
for the 2d retimer to work, it needs to know what frame the background camera would have to be at to match the position of the foreground camera at any given frame.
so ideally, the output of the script would be a list from frame 1 to x likt this
(current frame) (frame where the bg_cam would match the position of the fg_cam)
whati tried is a script that outputs the speed of the camera at the current frame and had hoped, i could somehow calculate the retime frame from that, but i don’t know how to do that. it might also work with calculating the percent along the path based on the distance from every frames cam_position to the next- but how?
maybe someone has an idea?
thanks
Hi,
Try this code. you’ll need to edit the 2 lines defining the camera objects by their names. This script works by comparing distances, so make sure the 2 cameras are aligned.
(
-- Change the names to the camera names used in your scene.
local fg = $FG_Cam
local bg = $BG_Cam
-- This function finds a target frame in which the camera is closest to
-- the given position
fn findTimeByPos cam pos =
(
local outTime = animationRange.start
local dist = 1e30
for f = animationRange.start to animationRange.end do at time f (
local d = distance cam.pos pos
if d < dist then (
dist = d
outTime = f
)
)
outTime
)
-- This functin outputs the time ramapping and creates an ease curve
-- to apply to the copy camera, to test that the retiming matches the FG camera.
fn getEaseCurve fgCam bgCam =
(
local curve = Linear_Float()
local win = newScript()
for f = animationRange.start to animationRange.end do at time f (
local targetTime = findTimeByPos bgCam fgCam.pos
format "% -> %
" f targetTime to:win
animate on curve.value = targetTime * ticksPerFrame
)
curve
)
-- get the bg_cam copy (or create one if one doesn't exist)
-- and apply the ease curve to it for testing.
local bg_copy_name = bg.name + "_copy"
local bg_copy = getNodeByName bg_copy_name
if not isValidNode bg_copy then (
bg_copy = copy bg
bg_copy.name = bg_copy_name
)
local cont = bg_copy.pos.controller.percent.controller
for i = 1 to numEaseCurves cont do
deleteEaseCurve cont i
addEaseCurve cont (getEaseCurve fg bg)
)
hOpe this helps,
o
wow, very nice
that works really well. thank you very much!
do you think it is possible to output frames as a floating number so they can represent not only full frames but also eg. 1/10 frame, so frame 32 of the fg_cam could be frame 32.3 of the bg_cam?
this would be very handy if the background plate is not (like in my case) slower and does not provide enough inbetween frame.
many retimers do a great job of creating interpolated (morph)-frames. that could stand in for those non-existing frames that are somewhere between two full frames.
-in fact, since the camera move is already 3d, it could easily be used to produce motion vectors that assist the retimer in creating those extra frames, just like in a 2d motion blur.
the ability to convert the foreground cameras rotation to xy position data to be used on the bg_plate would also allow for easy adaption of camera pans and tilts without aditional 2d tracking in comp.
again: thanks alot
Check out this version, it has frame accuracy. Note that the smaller the value, the more accurate the match will be, but at the cost of more time to calculate.
(
-- Change the names to the camera names used in your scene.
local fg = $FG_Cam
local bg = $BG_Cam
local frame_accuracy = 0.1
-- This function finds a target frame in which the camera is closest to
-- the given position
fn findTimeByPos cam pos frame_accuracy:1.0 =
(
local outTime = animationRange.start
local dist = 1e30
for f = animationRange.start to animationRange.end by frame_accuracy do at time f (
local d = distance cam.pos pos
if d < dist then (
dist = d
outTime = f
)
)
outTime
)
-- This functin outputs the time ramapping and creates an ease curve
-- to apply to the copy camera, to test that the retiming matches the FG camera.
fn getEaseCurve fgCam bgCam =
(
local curve = Linear_Float()
local win = newScript()
for f = animationRange.start to animationRange.end do at time f (
local targetTime = findTimeByPos bgCam fgCam.pos frame_accuracy:frame_accuracy
format "% -> %
" f targetTime to:win
animate on curve.value = targetTime * ticksPerFrame
)
curve
)
-- get the bg_cam copy (or create one if one doesn't exist)
-- and apply the ease curve to it for testing.
local bg_copy_name = bg.name + "_copy"
local bg_copy = getNodeByName bg_copy_name
if not isValidNode bg_copy then (
at time animationRange.start
bg_copy = copy bg
)
bg_copy.transform.controller = copy bg.transform.controller
bg_copy.name = bg_copy_name
local cont = bg_copy.pos.controller --.percent.controller
for i = numEaseCurves cont to 1 by -1 do
deleteEaseCurve cont i
addEaseCurve cont (getEaseCurve fg bg)
)
hOpe this helps,
o