Notifications
Clear all

[Closed] camera zoom extents to fit

Hi.all
I have search internet about camera zoom extents. but no good answer. so put it here for talk about…

what I want it’s make one object in the center of the camera . then change the camera Fov to zoom extents . this is not different from the max default zoom select oject extents. becuase default way aways have more space around.

so. I just think whether can do it like the follow piont.

  1. make the camera pos.x= objec.x . camera pos.z= object.z. later make camera.z have a litte raise.
  2. use lookat . object.lookat=camera.—this just let object can in center of the camera view.
  3. this setp calculate the camera fov. —this is the main problem that I meet.

here is my simple start maxscript


rollout zoomcamera "zoomcamera" width:195 height:87
(
	button btn1 "zoom extents camera" pos:[26,27] width:143 height:27
	on btn1 pressed  do
(
	obj=Teapot()
	obj.radius=200
	CenterPivot obj
	cam=freecamera()
	rotate cam (angleaxis 90 [1,0,0])
	cam.pos=[0,-1350,150]
	cam.baseObject.targetDistance=1350
	obj.lookat=cam
	cam.pos.z=cam.pos.z+350
	--then the blow step is main problem. 
	
	)
)
createdialog  zoomcamera style:#(#style_minimizebox, #style_titlebar, #style_sysmenu)

12 Replies

there have some info that I find out in internet.

1. http://buchhofer.com/2008/08/maxscript-zoom-extents/

[B]2. http://forums.cgsociety.org/archive/index.php/t-860305.html

there have a goodidea about how to get the camera fov.
this is harefort’s code. but for me a litte hard to deal detail.[/B]


fMaxAngleX = 0.0
fMaxAngleY = 0.0
for i = 1 to $.verts.count do
(
p3ViewVector = $.verts[i].pos - nCamera.pos
p3ViewVectorProjX = p3CameraRightVector * (dot p3ViewVector p3CameraRightVector)
p3ViewVectorProjY = p3CameraUpVector * (dot p3ViewVector p3CameraUpVector)
fAngleX = acos (dot (normalize p3ViewVectorProjX) p3CameraForwardVector)
fAngleY = acos (dot (normalize p3ViewVectorProjY) p3CameraForwardVector)
fMaxAngleX = aMax #(fMaxAngleX , fAngleX)
fMaxAngleY = aMax #(fMaxAngleY , fAngleY)
)
nCamera.fov.x = fMaxAngleX * 2
nCamera.fov.y = fMaxAngleY * 2

3. the maxscript help also have a maxscipt. but I have test that. no so good.


fn ZE_Cam cam objs =

(

local max2, fov, asp, v -- declare local variables

-- define a function that returns the maximum value 

-- of a set of values in an array

fn maxof vals = (local v=vals[1]; for v1 in vals do (if v1 > v do v=v1);v)

fov=0 -- initialize the fov value

asp=(renderWidth as float)/renderHeight -- calculate the renderer's image aspect ratio

in coordsys cam -- work in coordinate system of the camera

(

for obj in objs where obj != cam do -- loop across all objects except the camera

(

if obj.min.z >=0 do continue -- if object is behind camera, skip it

-- get max value of the object's bounding box, correcting for the image aspect ratio

-- in the y values

v = maxof #((abs obj.max.x),(abs obj.min.x),(abs (obj.max.y*asp)),(abs (obj.min.y*asp)))

fov = maxof #(fov,(2*atan(-v/obj.min.z))) -- increase fov if needed

)

)

cam.fov=fov -- set the camera's fov to the new fov value

)

-- test bed --

cam=$camera01 -- specify the camera to "zoom extent all" on

ZE_Cam cam $* -- call the function, passing the camera and an object set containing all objects


and the camera fov should need this
camera.fov=acos( (a^2+b^2-c^2)/(2ab))
about . a.b.c please see the attached file.

Nobody want to talk? any goodidea ? :hmm:

I use the viewport controls for this, not a real camera. It’s mostly a hack of zoomextents and then zoom 0.7x to close in a bit. It’s not the greatest but it works well enough with most of our assets.

I would like to use IntersectRay or IntersectRayEx something like this:
[ul]
[li]zoom extents[/li][li]trace rays to hit test for geometry in a 20×20 grid[/li][li]collect all the points that hit geometry[/li][li]convert the returned point to the viewport transform matrix[/li][li]check for min and max of all the points[/li][li]adjust the FOV of the viewport to get a tighter fit.[/li][/ul]I haven’t had time to look into this though.

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

the method is absolutely correct. to make it more accurate you can start zooming the view always from the same default initial state: position, orientation, fov.

I would like to use IntersectRay or IntersectRayEx something like this …

It’s not necessary. You can project all world verts positions to view and find the bbox in view coordinates for all verts. You don’t need “intersection” methods to get it.

thank you for Jonah Hawk and denisT.

Originally Posted by jonahhawk
I use the viewport controls for this, not a real camera. It’s mostly a hack of zoomextents and then zoom 0.7x to close in a bit. It’s not the greatest but it works well enough with most of our assets.

Yes, this way in generally .it’s Ok. but for me. I want exact way. so. I must choose the “IntersectRay ” or “bbox” way,

But, A litte hard for me for this.I dont know this before. I need take some time to study this… if somebady can help me write a litte maxscript. just simple maxscirpt. it’s good. Thank you very much…

here is how to get Veiw BBox for selected geometry nodes:


      global easyViewSelectionBBox
      unRegisterRedrawViewsCallback easyViewSelectionBBox
      
      fn easyViewSelectionBBox =
      (
      	nodes = for node in selection where iskindof node GeometryClass collect node
      	if nodes.count > 0 do
      	(
      		view = viewport.activeViewport
      		local bmin = [1e9,1e9,0], bmax = [-1e9,-1e9,0]
      
      		gw.setTransform (matrix3 1)
      		transPoint = gw.hTransPoint
      		for node in nodes do
      		(
      			mesh = snapshotasmesh node
      			for v=1 to mesh.numverts do
      			(
      				vp = transPoint (GetVert mesh v)
      				if vp.x < bmin.x do bmin.x = vp.x
      				if vp.x > bmax.x do bmax.x = vp.x
      				if vp.y < bmin.y do bmin.y = vp.y
      				if vp.y > bmax.y do bmax.y = vp.y
      			)
      			free mesh
      		)
      		w = (bmax.x - bmin.x) as integer
      		h = (bmax.y - bmin.y) as integer
      		rect = box2 bmin.x bmin.y w h
      		gw.hPolyline #(bmin, point3 bmax.x bmin.y 0, bmax, point3 bmin.x bmax.y 0) on rgb:#(orange,orange,orange,orange)
      		gw.hText (bmin + [5,h-20,0]) ("Size: [" + (w as string) + ", " + (h as string) + "]") color:orange
      		gw.enlargeUpdateRect rect
      		gw.updateScreen()
      	)
      )
      registerRedrawViewsCallback easyViewSelectionBBox
      completeRedraw()
      
 I hope this sample will be helpful for some rookie max scripter

Hi, denisT

The script running cool… it’s you . DenisT. you make my working easy…

I must need say thank you very much ! Thank you in advanced !!

Joe

I’ve made small (but essential) correction in my code of easyViewSelectionBBox to make it faster for Geometry Primitives.

1 Reply
(@system)
Joined: 11 months ago

Posts: 0

Thank you very much. now , it’s very faster… thank you in advanced !!

I’ve thought a little more and made the function about two times faster… check the difference.
actually it’s three times faster

1 Reply
(@system)
Joined: 11 months ago

Posts: 0

wow.thank you agian… I have no words to say… just say thank you (in advanced) * (in advanced)