Notifications
Clear all

[Closed] zoom extends selected to fit object's width and height-capture viewport

Hi all,
I have a project need to capture viewport,the question is not how to capture the viewport,the question is how can I let the object in viewport to fit itself width and length,the output aspect size has already adjusted to object ‘s width and height in viewport manually,but how can I do that via maxscript?like below(In safe Frames mode):

The default zoom extends selected is to much empty area that what I don’t want,any help would be appreciate,thanks!

7 Replies

Are these orthographic views or can you set them to orthographic?

2 Replies
(@momo2012)
Joined: 11 months ago

Posts: 0
(@momo2012)
Joined: 11 months ago

Posts: 0

After tested,it’s not work for orthographic views(my project need to capture orthographic views),I still need to find a solution…
:shrug:

Not perfect and barely tested with default settings. The ‘border’ parameter was supposed to be in pixels, but I can’t make it fit perfectly.

If objects are too far away, you may need to do a “max zoomext sel” to get better results before running it.

Hopefully it should do well for what you need.

(
	
	fn FitNodesToViewport border:0 useSafeFrame:false passes:1 =
	(
		if viewport.gettype() != #view_iso_user do return ()
		
		nodes = for j in selection where iskindof j geometryclass collect j
		if nodes.count == 0 do return ()
		
		for k = 1 to passes do
		(
			minx = miny =  1E9
			maxx = maxy = -1E9
			
			gw.settransform (matrix3 1)
			hTransPoint = gw.htranspoint

			for node in nodes do
			(
				mesh = snapshotasmesh node
				for j = 1 to mesh.numverts do
				(
					pos = hTransPoint (getvert mesh j)
					minx = amin minx pos.x
					maxx = amax maxx pos.x
					miny = amin miny pos.y
					maxy = amax maxy pos.y
				)
				free mesh
			)

			brWidth  = amax 1 (maxx-minx)
			brHeight = amax 1 (maxy-miny)
			
			viewSize   = getviewsize()
			viewWidth  = viewSize[1] as float
			viewHeight = viewSize[2] as float
			
			if useSafeFrame do viewWidth = viewHeight*renderwidth/renderheight
			
			deltax = viewWidth  / brWidth
			deltay = viewHeight / brHeight
			
			fov = viewport.getfov()
			
			if deltay < deltax then factor = ((brHeight+(border*2)) * fov / viewHeight) / fov
			else factor = ((brWidth+(border*2)) * fov / viewWidth) / fov

			pt1 = gw.getpointoncp [minx+brWidth/2.0, viewSize.y-(maxy-brHeight/2.0)]
			pt2 = gw.getpointoncp (viewSize/2.0)

			tm = getviewtm()
			pretranslate tm (pt2-pt1)
			
			viewport.settm tm
			
			if abs (1-factor) > 0.005 do viewport.zoom factor
		)
		
		completeredraw()
		
	)
	
	FitNodesToViewport border:10 passes:3
	
)

Hi!
The script FitNodesToViewport by @PolyTools3D is great and works almost as I want it. But in the front view, the script doesn’t work, the model has zoomed out far away. This is the case for all views where the angle is almost tangent to the grid. In the top view, it works perfectly, so I started to wonder if the reason for the behavior in the front view is because gw.getPointOnCP. So I added at the beginning of the script a grid helper which is facing the view in the viewport. I make this grid active and this solves the problem. I now thought that the problem was solved but now it acts very strange from other angles. Any suggestion why this happens?

Thanks!
Sebastian

Hello Sebastian,
The reason the script doesn’t work on orthographic views is that it is meant to work only in isometric views.

I’ve modified it to work on both views now. Please note that while the algorithm works (at least as far as I could test), the implementation is sub-optimal as it snapshots the objects in each loop and parse all the vertices positions.

Ideally you would do this only once, outside the loop, and then just update the values. For many objects with many vertices the increment in performance should be very noticeable. Also, the code needs to be cleaned up.

Tested on Max 2016 only.

(
	
	fn FitNodesToViewport border:0 passes:2 =
	(
		case viewport.gettype() of
		(
			       #view_top: ()
			    #view_bottom: ()
			     #view_right: ()
			      #view_left: ()
			     #view_front: ()
			      #view_back: ()
			  #view_iso_user: ()
			     #view_shape: ()
			#view_persp_user: return false -- doesn't work
			    #view_camera: return false -- doesn't work
			      #view_spot: return false -- doesn't work
			      #view_grid: return false -- doesn't work
		)
		
		nodes = for j in selection where canconvertto j editable_mesh collect j
		if nodes.count == 0 do return false
		
		viewSize    = getviewsize()
		hTransPoint = gw.htranspoint
		FOV         = viewport.getfov()
		
		viewport.zoom 1E-9
		max zoomext sel
		
		gw.settransform (matrix3 1)
		
		done = false
		
		for k = 1 to passes while not done do
		(
			minx = miny =  1E9
			maxx = maxy = -1E9
			
			for node in nodes do
			(
				mesh = snapshotasmesh node
				for j = 1 to mesh.numverts do
				(
					pos = hTransPoint (getvert mesh j)
					minx = amin minx pos.x
					maxx = amax maxx pos.x
					miny = amin miny pos.y
					maxy = amax maxy pos.y
				)
				free mesh
			)
			
			viewWidth  = viewSize[1] as float
			viewHeight = viewSize[2] as float
			
			brWidth  = amax 1 (maxx-minx)
			brHeight = amax 1 (maxy-miny)
			
			offset_x = minx + ((brWidth  - viewWidth ) * 0.5)
			offset_y = miny + ((brHeight - viewHeight) * 0.5)
			
			if displaySafeFrames do
			(
				viewAspect   = viewWidth / viewHeight
				renderAspect = getrendimageaspect()
				
				if viewAspect > renderAspect then viewWidth = viewHeight*renderwidth/renderheight
				else viewHeight = viewWidth*renderheight/renderwidth
			)
			
			deltax = viewWidth  / brWidth
			deltay = viewHeight / brHeight
			
			if deltay < deltax then factor = ((brHeight+(border*2)) * FOV / viewHeight) / FOV
			else factor = ((brWidth+(border*2)) * FOV / viewWidth) / FOV
			
			viewport.pan -offset_x offset_y
			viewport.zoom factor
			
			if abs (1-factor) < 0.01 do done = true
		)
		
		completeredraw()
		
		return true
	)
	
	FitNodesToViewport border:20 passes:10
	
)

Thank you so much! It works perfectly. I will use it in the perspective view so I replaced “return false” with (). The script will be used for batch rendering a lot of products where they all have the same camera angles. The products are in different shapes and sizes, and we want them all to have the same amount of border space. 3ds Max zoom extents aren’t precise, but your script works as it should.

Again, thank you for your help!