How to align an object to a normal vector of a face?

#1

Hi,
I want to use to normal direction which is returned by the intersectRay function to align an object. The object’s z-axis should point to the normal direction.

I tried to directly manipulate the object’s transform matrix but it failed:

``````p2 = intersectRay \$ p1
\$.transform = matrix3 (normalize -(cross p2.dir [0,1,0])) [0,1,0] (normalize p2.dir) p2.pos
``````

Thanks,
Christian

#2

[left]This might help (taken from maxscript help)[/left]

[left][/left]

[left]The following code implements the “Normal Align” feature of the UVW_Map modifier. The “Normal Align” button is not directly accessible to MAXScript. This function can be used as a replacement, and might help you understand the usefulness of the Vector Cross Product.[/left]

[left]Script:[/left]

[left]

`````` fn alignUVGizmo theObj theFace = [/left]

[left]([/left]

[left]--First get the face normal vector.[/left]

[left]--It is shown in BLUE on the image[/left]

[left]faceNormal = incoordsys theObj (getFaceNormal theObj theFace) [/left]

[left] [/left]

[left]--This is the desired up vector in world space [/left]

[left]--It is shown in YELLOW on the image[/left]

[left]worldUpVector = [0,0,1] [/left]

[left] [/left]

[left][/left]

[left]--Now get the cross-product of the face normal and the up vector.[/left]

[left]--This will give you a vector that is perpendicular to the plane defined[/left]

[left]--by the normal and the up vector. Normalize it to get a normal vector [/left]

[left]--pointing to the right.[/left]

[left]--It is shown in RED on the image[/left]

[left]rightVector = normalize (cross worldUpVector faceNormal) [/left]

[left] [/left]

[left]--Now using the face normal and the new vector,[/left]

[left]--get a vector that is perpendicular to the plane defined by the two.[/left]

[left]--This is the "local up vector", the vector that is the projection of[/left]

[left]--the world up vector on the face you selected. This one is perpendicular[/left]

[left]--to both the face normal and the right vector, and you have 3 normals now[/left]

[left]--that define the X, Y and Z of your new orthogonal coordinate system[/left]

[left]--for the UVW gizmo! [/left]

[left]--Note that this new vector can be seen as the SHADOW of the World Up vector [/left]

[left]--on the face of the object in the above image.[/left]

[left]-- It is now displayed in green in the image below:[/left]

[left]upVector = normalize ( cross rightVector faceNormal )[/left]

[left] [/left]

[left]--Using the 3 vectors, define a matrix3 value which represents the[/left]

[left]--coordinate system of the gizmo. The face normal is the Z axis,[/left]

[left]--the right vector is the X axis, and the local up vector is the Y axis:[/left]

[left]theMatrix = matrix3 rightVector upVector faceNormal [0,0,0] [/left]

[left] [/left]

[left]theMap = Uvwmap()[/left]

[left]theMap.gizmo.transform = theMatrix [/left]

[left])[/left]
[left]
``````

[/left]

#3

#4

Every Node in Max has a .DIR property which represent its Z axis. So in order to align an object to a normal, in the simplest case when you don’t care about the rest of the axes, you can just assign the vector to that property.

``````
(
s = sphere pos:[10,20,30]
theMesh = snapshotasmesh s
for f = 1 to theMesh.numfaces do
(
theClone = instance t
theClone.dir = getFaceNormal theMesh f
theClone.pos = meshop.getFaceCenter theMesh f
)
)

``````

The other way would be to use MatrixFromNormal, set the .row4 to the position of the object and assign to the .transform property.

``````
(
s = sphere pos:[10,20,30]
theMesh = snapshotasmesh s
for f = 1 to theMesh.numfaces do
(
theClone = instance t
theClone.transform = matrixFromNormal (getFaceNormal theMesh f)
theClone.pos = meshop.getFaceCenter theMesh f

--ALTERNATIVE:
-- theTM = matrixFromNormal (getFaceNormal theMesh f)
-- theTM.row4 = meshop.getFaceCenter theMesh f
-- theClone.transform = theTM
)
)
``````

Of course, the example from the Online Help takes the UP vector into account, so it is much more general and advanced.