PDA

View Full Version : Calculate Object Render Region


DaveWortley
02-16-2012, 05:44 PM
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.

lo
02-16-2012, 06:28 PM
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?

Raytracer05
02-17-2012, 08:53 AM
I might be wrong but I don't think this will work the way you want it to for two reasons:
1. 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.
2. 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

DaveWortley
02-17-2012, 10:53 AM
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

DaveWortley
02-17-2012, 11:30 AM
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 :)

Raytracer05
02-17-2012, 12:19 PM
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.

DaveWortley
02-17-2012, 02:05 PM
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....

TimHawker
02-17-2012, 07:49 PM
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.

MikeOwen
10-05-2012, 03:20 PM
Hmmm...I wonder where you got that idea from Tim! :-)

CGTalk Moderation
10-05-2012, 03:20 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.