Notifications
Clear all

[Closed] create an accurate bounding box

I’m looking for a script than can create an accurate optimum bounding box from a selection of vertexes. A selection of objects or faces is also ok.

The bounding box I’m looking for must be rotated/scaled to fit the selection as close as possible.

If you have any script tutorial or tips to help, it will be greatly appreciated.

Thx

15 Replies

This link could be useful for you:
http://forums.cgsociety.org/showthread.php?t=300121

This script would be a good start to solve your problem.
Nevertheless the script should be adapted for all objects type (snapshotasmesh and using mesh functions instead of polys).

That will be slow with hires objects because the method is an approximation.
I don’t know the solution to optimize that but i’m still interested to learn a bit about this subject…

I think if you did these operations you would find the solution:

Loop through the vertices, and store the verts with the highest x, lowest x, highest y, lowest y, highest z, and lowest z values. From these “extreme” verts you can use distance to grab the dimensions of your box. The center of your box isn’t a mere average of all vertex positions, but an average between the extremes of each dimension, so calculate that, set your box to that position, and you have a box that perfectly fits your selected vertices.

Like this:


 (
 	if selection.count == 1 and classof $ == Editable_Poly do
 	(
 		theObj = $
 		theVerts = polyop.getvertselection theObj as array
 		xVals = #()
 		yVals = #()
 		zVals = #()
 			   
 		for v in theVerts do
 		(
 			vertPos = polyop.getvert theObj v
 			append xVals vertPos.x
 			append yVals vertPos.y
 			append zVals vertPos.z
 		)
 		
 		theWidth = (amax xVals) - (amin xVals)
 		theLength = (amax yVals) - (amin yVals)
 		theHeight = (amax zVals) - (amin zVals)
 		
 		avgPos = [(((amax xVals) + (amin xVals)) / 2.),(((amax yVals) + (amin yVals)) / 2.),(((amax zVals) + (amin zVals)) / 2.)]
 		theBox = box length:theLength width:theWidth height:theHeight xray:true
 		theBox.pivot = theBox.center
 		theBox.pos = avgPos
 	)
 )
 

I think he wanted an oriented bounding box.
A standard bounding box is oriented with the world axis. But the chalenge with an obb (oriented bounding box) is to find the best orientation for the smallest bb.
At present I know only this uneffiicient method of calculation: to evaluate all bounding boxes for all rotations…

1 Reply
(@dinmatin)
Joined: 11 months ago

Posts: 0

think in 2d (for instance XY):

take the world boundingbox
get the “outest” points

create a coordinatesystem in your 2dthinking from those 2 points
[the new coordinate system sticking out in Z-axis]

do the same for that new coordinatesystem
and you’ll have your “box”.

you may iterate this progress according to the coordinatesystem of you box.

hope it helps (couldn’t do it on my own, but THEORY!)

greets, /matin.

Hey Mr Matin, Your explanations are really very interesting!
I will try to program this routine in my free time

Thank you very much

I thought about your method.
If the form is a rectangle, it will find the diagonals of the rectangle.
It is not directly what we want but that could be a valid approach…
A diagonal is actually the longest line between two ends of a form.
If the program collects all the diagonals of a volume, it could be possible to use this information to create an OBB.

I still hesitate about the method.
If somebody sees further…

I’m not sure DINmatins theory works… what if you placed a diamond in the square? (a box rotated 45 degrees) the bounding box would be the same as the world space one no?

What a great exercise in trig this has been, haha. Using the two most extreme verts, it is possible to construct a matrix and determine the most accurate oriented bounding box, as DINmaten suggested. I have no idea what the OP would use this script for, but it has been a fun obsession during my free time. Its written for editable polys, but isn’t impossible to convert. Here is the code:


  (
  	if selection.count == 1 and classof $ == Editable_Poly do
  	(
  		theObj = $
  		theVerts = polyop.getvertselection theObj as array
  		vertLocs = for v in theVerts collect polyop.getvert theObj v
  		vertAmount = theVerts.count
  		avgPos = [0,0,0]
  		zComp = #()
  		xComp = #()
  		yComp = #()
  		zComp[vertAmount] = xComp[vertAmount] = yComp[vertAmount] = undefined
  		local zMax, zMin, xMax, xMin, yMax, yMin, xVect, yVect, zVect, theMatrix,
  			  theLength, theWidth, theHeight, xAmt, yAmt, zAmt, zMaxHold, zMinHold
  		
  		--Get average position
  		for v in vertLocs do avgPos += v
  		avgPos /= vertAmount
  		
  		--Get farthest vert
  		for x = 1 to vertAmount do
  			zComp[x] = distance avgPos vertLocs[x]
  		
  		zMaxHold = theVerts[(finditem zComp (amax zComp))]
  		zMax = polyop.getvert theObj zMaxHold
  		
  		--Get farthest vert from farthest vert (the 2 extremes)
  		for x = 1 to vertAmount do
  			zComp[x] = distance zMax vertLocs[x]
  		
  		zMinHold = theVerts[(finditem zComp (amax zComp))]
  		zMin = polyop.getvert theObj zMinHold
  		
  		--Construct matrix from vectors
  		zVect = normalize (zMax - zMin)
  		xVect = normalize (cross [0,0,1] zVect)
  		yVect = normalize (cross xVect zVect)
  		theMatrix = matrix3 xVect yVect zVect [0,0,0]
  		
  		--Determine dimensions and construct box
  		in coordsys theMatrix
  		(		
  			for x = 1 to vertAmount do
  			(
  				thePos = polyop.getvert theObj theVerts[x]
  				xComp[x] = thePos.x
  				yComp[x] = thePos.y
  			)
  			
  			xMax = polyop.getvert theObj theVerts[(finditem xComp (amax xComp))]
  			xMin = polyop.getvert theObj theVerts[(finditem xComp (amin xComp))]
  			yMax = polyop.getvert theObj theVerts[(finditem yComp (amax yComp))]
  			yMin = polyop.getvert theObj theVerts[(finditem yComp (amin yComp))]
  			zMax = polyop.getvert theObj zMaxHold
  			zMin = polyop.getvert theObj zMinHold
  			
  			xAmt = ((xMax + xMin) / 2.).x
  			yAmt = ((yMax + yMin) / 2.).y
  			zAmt = ((zMax + zMin) / 2.).z
  			
  			theWidth = xMax.x - xMin.x
  			theLength = yMax.y - yMin.y
  			theHeight = distance zMax zMin
  		)
  		
  		theBox = box width:theWidth length:theLength height:theHeight xray:true
  		theBox.pivot = theBox.center
  		theBox.transform = theMatrix
  		
  		in coordsys theMatrix(move theBox [xAmt, yAmt, zAmt])
  		completeredraw()
  	)
  )
  

You can construct spheres at each xMax, xMin, yMax, etc. location with corresponding red, green, and blue colors to visually verify that the script is detecting the correct dimensions.

Nice function you got there. The problem with it is that in cases like a box, it will fail to calculate the best OBB because it will take one of the diagonals as main axis. But I think that for an arbitrary disposition of vertices, should work fine.

Greets.

Doh, just when I thought I had it. The plot thickens

Page 1 / 2