PDA

View Full Version : Aligning objects local Bounding box to a facenormal?


DaXiiD
04-06-2008, 11:08 AM
Red-BAD Green-GOOD!! :)
http://a3ia.com/ivar/kastid.JPG
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.

Bobo
04-06-2008, 03:04 PM
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.

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...

DaXiiD
04-06-2008, 04:35 PM
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?

Bobo
04-06-2008, 07:19 PM
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.

DaXiiD
04-06-2008, 08:50 PM
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 :)

CGTalk Moderation
04-06-2008, 08:50 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.