Workflow:
1. imported targetObj (cube, poly, *.obj)
2. on-scene sceneObj (cube, poly, later point helper)
3. sceneObj.rotation = targetObj.rotation (the two cubes need to overlap)
4. sceneObj.pos = targetObj.pos
Problem:
Can't set proper axis / rotation to sceneObj from face normal of targetObj. Transformation nooberism.
Details:
I'm working on a simple import plugin, that imports custom mesh from another app into 3ds Max. In the 3ds Max scene I have a helper (a cube for testing right now) and I need to fit the position and rotation to another one (same size, 6 polys) which is imported. This proves to be extremely difficult for me, and while the position is no problem at all (sceneObj.pos = targetObj.pos) I'm totally lost at matrix3, eulerangles and quat values. And (sceneObj.rotation = targetObj.rotation) is not an option, as the simple imported *.obj file has NO rotation at all.
So - I've thought that getting the matrix3 of the normal of face 3 (front face) of the targetObj. I managed to somehow translate the rotation to my scene object but I think the axis are all wrong - some of them keep the sceneObj aligned properly, while when targetObj orientation changes it rotates the sceneObj in the wrong direction / along wrong axis.
Code:
fn getAngleFromNormal targetObj sceneObj =
(
--RESET sceneObj ROTATION
oldTranslateMtx = transMatrix sceneObj.transform.pos
oldScaleMtx = scaleMatrix sceneObj.transform.scale
sceneObj.transform = oldScaleMtx * oldTranslateMtx
mtx = matrixFromNormal (polyOp.getFaceNormal targetObj 3)
sceneObj.transform *= mtx
eu = mtx as eulerangles
rx = eu.x
ry = eu.y
rz = eu.z
sceneObj.rotation *= inverse (eu as quat)
sceneObj.pos = targetObj.pos
)
Screenshots:
I'm really, really hopeless if it goes for things such as these, so I'd appreciate any and all help that can direct and teach me even a bit.
Thanks for your time, Michelle.
I think you're on the right track, however in order to get an orientation you need at least two vectors. From what I gather in the documentation, getting the matrixFromNormal uses the world axis as a tangent, which is why you're getting odd results.
I'm sure there are more streamlined approaches, but hopefully this gets you on the right track.
--Returns matrix based on the face of a mesh - aligns X axis with Normal
fn getMatrixFromFace targetObj faceId:10 =
(
-- here we get the normal and assume it's the first row of the resulting
-- matrix, hence the x-axis
local row1 = getFaceNormal targetObj faceId
-- here we are building a tangent from the vertex positions of the face
local verts = getFace targetObj faceId
local row2 = normalize (targetObj.verts[1].pos - targetObj.verts[2].pos)
-- to get the third axis we get the cross product of X-axis and Y-axis
local row3 = cross row1 row2
-- we zero out the position (row4), in case you need to multiply by this
-- matrix. Optionally, if you know you will always want the translation,
-- (matrix3 row1 row2 row3 targetObj.transform.row4)
(matrix3 row1 row2 row3 [0, 0, 0])
)
mtx = getMatrixFromFace targetObj faceId:10
mtx.row4 = targetObj.transform.row4
sourceObj.transform = mtx
Note that this aligns the normal of the face with the X-axis of the sourceObj, and the Y-axis is aligned to the tangent of the face. If you which to change this, simply change the rows around or change the orientation of the tangent.
If you need to align face to face, there's more work involved. I'm sure you can figure it out from the information given.
Also note that I assume that the targetObj has a world orientation, but has a position that relates to its geometry (offset from origin). If not you can modify row4 in the function above by averaging the position of the verts of the faces, and then offsetting by the vector between the aforementioned average pos, and the bounding volume of the targetObj.