Notifications
Clear all

[Closed] Aligning objects local Bounding box to a facenormal?

Red-BAD Green-GOOD!!

How can i align the red objects bounding box to be minimal?

One solution i am thinking about is rotating the object so it’s facenormal points in the world Z+ axis and then apply a reset xfrom modifier and collapse the stack. Then rotate it back.

i really hope there is a more straight forward solution.

4 Replies
1 Reply
(@bobo)
Joined: 11 months ago

Posts: 0

Don’t think there is a better solution – when I had to do it, I did just that (but it was more complicated, as it involved growing crystals where I had to find out what the main direction of the crystal was based on edge lenghts and perform the orientation automatically).
Create a matrix from normal with position equal to the current position of the object, transform by the inverse of it to get the object aligned to the world origin, reset, then transform back.

Here is a simple example using the first normal:

fn AlignBBoxToFirstNormal theObject = 
  (
  theCurrentTM = theObject.transform --this is the current transformation
  theMesh = snapshotasmesh theObject --get the world space TriMesh
  theTM = matrixFromNormal (getFaceNormal theMesh 1) --build a matrix from normal
  delete theMesh --delete the TriMesh from memory
   theTM.row4 = theCurrentTM.row4 --set the position of the new matrix to the old pos
  theObject.transform *= inverse theTM --transform out of world space 
  resetXForm theObject --reset the XForm
  convertToMesh theObject --collapse the stack
  theObject.transform = theTM --transform back into world space
  )

To test this, I created a plane, moved and rotated it freely and reset the XForm myself to get a “bad” bbox. Then called the function and got a flat bbox.

This method does not give you the perfect orientation of the X and Y axes though, only the Z is aligned to make the bbox as flat as possible assuming all faces are coplanar to the first normal. In a better version, you could figure out the longest edge or something like that and use that direction as an X axis and build the Y as the cross-product of the normal and the X, then build your own matrix3 value out of the three vectors and the current position.
Also, if the normals are slightly different, you could average all normals of all faces and align the Z to the result instead of taking just one as I did above.
But the basics are the same…

In my test with the plane, I modified the function to use the first edge of the first face as the Y axis:

fn AlignBBoxToFirstNormal theObject = (
 theCurrentTM = theObject.transform
 theMesh = snapshotasmesh theObject
 theZ = normalize (getFaceNormal theMesh 1)
 theFace = getFace theMesh 1
 theY = normalize ((getVert theMesh theFace.y)-(getVert theMesh theFace.x))
 theX = normalize (cross theY theZ)
 theTM = matrix3 theX theY theZ theCurrentTM.row4
 theObject.transform *= inverse theTM
 resetXForm theObject
 convertToMesh theObject
 theObject.transform = theTM
  )

Even better, you could allow the user to SELECT the edge to be used as the Y axis and build the matrix out of that, but it would be only semi-automatic then as it would require a user for edge selection…

Thank you very much for the pointers. After revising the wonderful matrix explained dvd I got almost that far myself.

The problem i am facing now, is the nonaligned X,Y axes one.
Unfortunately this script needs to be fully automatic, and the pieces can be quite different (all planar, with same normals though). So selecting an axis or using longest edge won’t work :(.

I have a vague idea how to solve this problem , but i need some help with the mathematics behind the idea.

I know the Matrix-3 Z axis (the facenormal)
I know that the X axis must be parallel to worlds XY plane.
I know that the Y axis must point to the positive part of the world Z direction.

I know that the previous statements won’t give me a solution when the facenormal is [0,0,1], but let’s not worry about it yet

How would it be possible to calculate the missing axes for matrix generation?

Most edges in a typical mode tend to face in common directions.
At the same time, if an object is transformed out of world space to match the world origin, the .min and .max properties of the world bounding box become identical to the object bounding box for the current orientation (once you resetXform, the object bbox aligns to the world-aligned bbox of .min and .max).

So I would suggest to collect all possible edge directions and transform the object using a matrix based on the Z and each one of these edge directions without resetting the xform (to speed things up). After each transformation, collect the .min and .max and calculate the area of the XY world bounding box projection. Once you have tested them all, you will end up with the index of the edge that produced the minimum XY area for the world bbox and you can apply and resetXForm using that vector. This would work fully automaticlaly and shouldn’t take too long either, even with thousands of edges.

Most edges in a typical mode tend to face in common directions.

Wohhoo, that guided me to the right direction. If you don’t have the edges to base an axis on , make them! Slice worked out quite well.

Bobo saved the day again