[Closed] Calculate Object Render Region
I want to calculate the Render Region for a group of object, and it needs to be done without using ViewportTM as this is a pre-render script.
I always get confused when working in camera space. Needs to return a box2 value as with regionrender values.
Will attempt to solve it but if anyone has the code to hand or feels like a challenge, feel free to contribute.
Sorry, are you saying you want to know the coordinates of the object in the viewport’s coordinate space without knowing the viewport’s coordinate space?
I might be wrong but I don’t think this will work the way you want it to for two reasons:
- I don’t think you can change render settings with a pre-render script because Max takes a snapshot of the render settings before the script is run.
- As lo said, region render uses viewport coordinate space.
However, I tried to do something like this a while back but didn’t use it for anything in the end. Sorry it’s a bit messy but you’re welcome to use any of this if it helps:
try (destroyDialog BBautoRegion) catch ()
rollout BBautoRegion "AutoRegion"
(
fn bb2rect =
(
if $ != undefined then
(
renderSceneDialog.close()
vpSize = getViewSize()
gw.setTransform(Matrix3 1)
sel = getCurrentselection() as array
BBmask = sel[1]
gwMin = gw.wTransPoint BBmask.center
gwMax = gw.wTransPoint BBmask.center
for BBmask in sel do
(
objBB = nodeGetBoundingBox BBmask (Matrix3 1) --get selection BB in worldspace co-ordsys
for zi = 1 to 2 do
(
for yi = 1 to 2 do
(
for xi = 1 to 2 do
(
gw.setTransform(Matrix3 1)
wsPt = point3 obJBB[xi][1] objBB[yi][2] objBB[zi][3]
gwPnt = gw.wTransPoint wsPt
if (gwPnt.x < gwMin.x) then
(
if (gwPnt.x > 0) then (gwMin.x = gwPnt.x) else (gwMin.x = 0) --set gwMin.x
)
if (gwPnt.y < gwMin.y) then
(
if (gwPnt.y > 0) then (gwMin.y = gwPnt.y) else (gwMin.y = 0) --set gwMin.y
)
if (gwPnt.x > gwMax.x) then
(
if (gwPnt.x < vpSize.x) then (gwMax.x = gwPnt.x) else (gwMax.x = vpSize.x) --set gwMax.x
)
if (gwPnt.y > gwMax.y) then
(
if (gwPnt.y < vpSize.y) then (gwMax.y = gwPnt.y) else (gwMax.y = vpSize.y) --set gwMax.x
)
) --end x loop
) --end y loop
)--end z loop
)--end o loop
if getRendImageAspect() < (vpSize.x/vpSize.y) then
(
roScale = (renderHeight/vpSize.y)
roPad = ((vpSize.x*roScale)-(renderWidth))/2
roRegion = box2 (point2 ((gwMin.x*roScale)-roPad) (gwMin.y*roScale)) (point2 ((gwMax.x*roScale)-roPad) (gwMax.y*roScale))
)
else
(
roScale = (renderWidth/vpSize.x)
roPad = ((vpSize.y*roScale)-(renderHeight))/2
roRegion = box2 (point2 (gwMin.x*roScale) ((gwMin.y*roScale)-roPad)) (point2 (gwMax.x*roScale) ((gwMax.y*roScale)-roPad))
)
EditRenderRegion.IsEditable = true
if viewport.activeViewport != 0 then viewport.setRegionRect viewport.activeViewport roRegion
EditRenderRegion.UpdateRegion()
setRenderType #region
renderSceneDialog.open() --need test for previous state
displaySafeFrames = true --need test for previous state
)
)--end fn bb2rect
fn autobb2rect ev nd =
(
registerRedrawViewsCallback bb2rect
redrawViews()
unregisterRedrawViewsCallback bb2rect
redrawViews()
)
local sfState
on BBautoRegion open do
(
sfState = displaySafeFrames
displaySafeFrames = true
unregisterRedrawViewsCallback bb2rect
)
on BBautoRegion close do
(
displaySafeFrames = BBautoRegion.sfState
unregisterRedrawViewsCallback bb2rect
)
button setRegion "Set Region" pos:[5,10]
checkButton autoRegion "Auto Region" pos:[80,10]
on setRegion pressed do
(
if selection.count == 1 then
(
autobb2rect 1 1
)
)
on autoRegion changed state do
(
if state == true then
(
autobb2rect 1 1
selChanged = NodeEventCallback mouseUp:true selectionChanged:autobb2rect all:autobb2rect
)
else
(
selChanged = undefined
gc light:true
)
)
)--end rollout
createDialog BBautoRegion
Select a perspective or camera viewport and run the script and press the ‘auto region’ button. Select one or more objects and the region render box will automatically fit to anything your selection.
Dan
Thanks Dan, I’m going to pass these point2 value to Deadline so it’s not really a pre-render script, as it’ll be set before submission, but needs to be automatic.
I’ll test it in a bit and see how I get on… Cheers…
Dave
It works, but a) is really really slow and b) if the object goes off the edge of the Frame the region is rendering into negative space, which causes issues when rendering.
I’ll have a look at it and see what I can do, cheers for the base though
Yes it is slow. Like I said, it was never really finished or used for anything. I thought it did clip the region to the viewport if the object went off the frame though.
fn bb2rect =
(
if $ != undefined then
(
renderSceneDialog.close()
vpSize = getViewSize()
gw.setTransform(Matrix3 1)
sel = getCurrentselection() as array
BBmask = sel[1]
gwMin = gw.wTransPoint BBmask.center
gwMax = gw.wTransPoint BBmask.center
for BBmask in sel do
(
objBB = nodeGetBoundingBox BBmask (Matrix3 1) --get selection BB in worldspace co-ordsys
for zi = 1 to 2 do
(
for yi = 1 to 2 do
(
for xi = 1 to 2 do
(
gw.setTransform(Matrix3 1)
wsPt = point3 obJBB[xi][1] objBB[yi][2] objBB[zi][3]
gwPnt = gw.wTransPoint wsPt
if (gwPnt.x < gwMin.x) then
(
if (gwPnt.x > 0) then (gwMin.x = gwPnt.x) else (gwMin.x = 0) --set gwMin.x
)
if (gwPnt.y < gwMin.y) then
(
if (gwPnt.y > 0) then (gwMin.y = gwPnt.y) else (gwMin.y = 0) --set gwMin.y
)
if (gwPnt.x > gwMax.x) then
(
if (gwPnt.x < vpSize.x) then (gwMax.x = gwPnt.x) else (gwMax.x = vpSize.x) --set gwMax.x
)
if (gwPnt.y > gwMax.y) then
(
if (gwPnt.y < vpSize.y) then (gwMax.y = gwPnt.y) else (gwMax.y = vpSize.y) --set gwMax.x
)
) --end x loop
) --end y loop
)--end z loop
)--end o loop
global roRegion
if getRendImageAspect() < (vpSize.x/vpSize.y) then
(
roScale = (renderHeight/vpSize.y)
roPad = ((vpSize.x*roScale)-(renderWidth))/2
roRegion = box2 (point2 ((gwMin.x*roScale)-roPad) (gwMin.y*roScale)) (point2 ((gwMax.x*roScale)-roPad) (gwMax.y*roScale))
)
else
(
roScale = (renderWidth/vpSize.x)
roPad = ((vpSize.y*roScale)-(renderHeight))/2
roRegion = box2 (point2 (gwMin.x*roScale) ((gwMin.y*roScale)-roPad)) (point2 (gwMax.x*roScale) ((gwMax.y*roScale)-roPad))
)
if roRegion.x < 0 then (roRegion.w += roRegion.x; roRegion.x = 0)
if roRegion.y < 0 then (roRegion.h += roRegion.y; roRegion.y = 0)
if roRegion.w + roRegion.x > Renderwidth then roRegion.w = Renderwidth - roRegion.x
if roRegion.h + roRegion.y > RenderHeight then roRegion.h = RenderHeight - roRegion.y
EditRenderRegion.IsEditable = true
if viewport.activeViewport != 0 then viewport.setRegionRect viewport.activeViewport roRegion
EditRenderRegion.UpdateRegion()
setRenderType #region
renderSceneDialog.open() --need test for previous state
displaySafeFrames = true --need test for previous state
)
)--end fn bb2rect
Updated it to fix the values if they’re outside of the range.
I’ve got to have a re-think for how this is going to work… I thought I could pass the values to Deadline, but as the scene builds itself on the render slave I won’t know what the area will before I kick it off… hhmmmm…
You could always send the script to deadline as a postLoad script. That way it will set the region for the chosen objects before it starts rendering.
Postload scripts allow layers and objects to be hidden and unhidden, materials to be changed and a few other things. Prerender is very restrictive and won’t allow any of the previous things mentioned to be changed.