Notifications
Clear all

[Closed] OBB oriented bounding box

I have just programmed a function to find the OBB of a poly.
The OBB is an approximation. For example the angle step is 10° here.
If I decrease this value the function takes much time to calculate all the possibilities…

Would someone have an idea to improve this script?

struct OBBstruct
	(
	minPos=[0.0,0.0,0.0],
	maxPos=[0.0,0.0,0.0],
	size=[0.0,0.0,0.0],
	center=[0.0,0.0,0.0],
	angle=[0.0,0.0,0.0],
	angleQuat
	)

fn getSizeVerts theVertsPos theAngle = (
	local minCoord=[theVertsPos[1].x,theVertsPos[1].y,theVertsPos[1].z]
	local maxCoord=[theVertsPos[1].x,theVertsPos[1].y,theVertsPos[1].z]
	for thisPos in theVertsPos do (
		if thisPos.x<minCoord.x do minCoord.x=thisPos.x
		if thisPos.x>maxCoord.x do maxCoord.x=thisPos.x
		if thisPos.y<minCoord.y do minCoord.y=thisPos.y
		if thisPos.y>maxCoord.y do maxCoord.y=thisPos.y
		if thisPos.z<minCoord.z do minCoord.z=thisPos.z
		if thisPos.z>maxCoord.z do maxCoord.z=thisPos.z
		)
	local sizeCoord=maxCoord-minCoord
	local centerCoord=(minCoord+maxCoord)/2.0
	(OBBstruct minPos:minCoord maxPos:maxCoord size:sizeCoord center:centerCoord angle:theAngle)
	)

fn findOBB obj angleStep = (
	local lim=0.00001
	local objNumVerts=obj.numVerts
	local theVerts=#{1..objNumVerts}
	local polyOpGetVert=polyOp.getVert
	local theVertsPos=for v in theVerts collect (polyOpGetVert obj v)
	local firstOBB=getSizeVerts theVertsPos [0.0,0.0,0.0]
	local centerCoord=firstOBB.center
	for v in theVerts do theVertsPos[v]-=centerCoord
	local OBBarrayLev1=#()
	local OBBvolArrayLev1=#()
	local maxAngle=90.0
	for angleZ=-maxAngle to maxAngle by angleStep do (
		local OBBarrayLev2=#()
		local OBBvolArrayLev2=#()
		for angleY=-maxAngle to maxAngle by angleStep do (
			local OBBarrayLev3=#()
			local OBBvolArrayLev3=#()
			for angleX=-maxAngle to maxAngle by angleStep do (
				local q=inverse(eulerToQuat (eulerAngles angleX angleY angleZ))
				local theNewVertsPos=for v in theVerts collect ( theVertsPos[v]*q )
				local currentAngle=[angleX,angleY,angleZ]
				local currentOBB=getSizeVerts theNewVertsPos currentAngle
				append OBBarrayLev3 currentOBB
				if currentOBB.size.x<lim do currentOBB.size.x=lim
				if currentOBB.size.y<lim do currentOBB.size.y=lim
				if currentOBB.size.z<lim do currentOBB.size.z=lim
				append OBBvolArrayLev3 (currentOBB.size.x * currentOBB.size.y * currentOBB.size.z)
				)
			local idxLev3=findItem OBBvolArrayLev3 (amin OBBvolArrayLev3)
			append OBBarrayLev2 OBBarrayLev3[idxLev3]
			append OBBvolArrayLev2 OBBvolArrayLev3[idxLev3]
			)
		local idxLev2=findItem OBBvolArrayLev2 (amin OBBvolArrayLev2)
		append OBBarrayLev1 OBBarrayLev2[idxLev2]
		append OBBvolArrayLev1 OBBvolArrayLev2[idxLev2]
		)
	local idx=findItem OBBvolArrayLev1 (amin OBBvolArrayLev1)
	local thisOBB=OBBarrayLev1[idx]
	thisOBB.angleQuat=eulerToQuat (eulerAngles thisOBB.angle.x thisOBB.angle.y thisOBB.angle.z)
	thisOBB.minPos=(thisOBB.minPos*thisOBB.angleQuat)+firstOBB.center
	thisOBB.maxPos=(thisOBB.maxPos*thisOBB.angleQuat)+firstOBB.center
	thisOBB.center+=firstOBB.center
	thisOBB
	)

clearListener()
obj=selection[1]
if isValidNode obj do (
	local objName=obj.name
	
	local thisOBB=findOBB obj 10.0
	format "thisOBB=% 
" thisOBB
	
	point pos:thisOBB.center wireColor:red name:(objName+"_OBB_center")
	point pos:thisOBB.minPos wireColor:blue name:(objName+"_OBB_min")
	point pos:thisOBB.maxPos wireColor:blue name:(objName+"_OBB_max")

	local b=box length:thisOBB.size.y width:thisOBB.size.x height:thisOBB.size.z wireColor:green  name:(objName+"_OBB")
	b.pivot=[0,0,(thisOBB.size.z/2.0)]
	b.rotation.controller.x_rotation=thisOBB.angle.x
	b.rotation.controller.y_rotation=thisOBB.angle.y
	b.rotation.controller.z_rotation=thisOBB.angle.z
	b.pos=thisOBB.center
	b.xray=true
	select b
	
	max views redraw
	)

a test object:

b=box length:50.0 width:75.0 height:100.0 xray:true pos:[-10.0,20.0,-30.0]
rotate b (eulerAngles -10.0 -20.0 30.0)
b.pivot=[0,0,0]
convertToPoly b
1 Reply

using the addition instead of the multiplication seems to give better results.

in the code:

append OBBvolArrayLev3 (currentOBB.size.x + currentOBB.size.y + currentOBB.size.z) -- instead of (currentOBB.size.x * currentOBB.size.y * currentOBB.size.z)