[Closed] How to detect object's face is flip towards the camera ?
Hi all
I have a question, I have a camera view ,There are some boxs in the camera view, one of boxs face is flip,How to detect it ?
if face “flipped” to the view direction its normal points in direction of the view and dot product of face normal and view dir > then 0.
here is a function to collect all faces of Editable Mesh if their normals are pointing in the direction of view (it’s easy to change the code for Poly).
fn collectFlippedFaces node selectit:on = if iskindof node Editable_Mesh do
(
cam_dir = -(inverse (getViewTM())).row4
towards_faces = #{}
for f in (node.faces as bitarray) \
where dot (getfacenormal node f) cam_dir > 0 do append towards_faces f
if selectit do node.selectedfaces = towards_faces
towards_faces
)
you can loop through the faces of the object and for each face check the dot product of the normal of the face with the direction of the camera. this will give you the angle between the normal and the camera. if the angle is more then 90 degrees, then the face is flipped.
cheers,
Matan.
thanks TzMtN,
My maxscript is very poooooor,Can you give an example to illustrate it Mody ?
Hi,
This script will select faces that are facing a camera / viewport. Works on EMesh.
fn anglefrompointandnormal a b c= (acos(dot(normalize(b-a)) (normalize c)))
fn selectfacing obj=
(
FaceList=#{}
if gw.isperspview() then
( -- this method is for a perspective view
ViewTM=((Inverse(getViewTM())).row4) -- the viewTMposition of the camera or viewport
for i=1 to obj.numfaces do
(
FaceNormal=(getfacenormal obj i) -- get face normal of indexed face
FaceCenter=(meshop.getfacecenter obj i) -- get the face center
a=AngleFromPointAndNormal FaceCenter ViewTM FaceNormal -- get the angle using the face center, the viewTMposition, and the face normal vector
if a<90 then append FaceList i -- if this angle is greater than 90, then the face faces away from the camera
)
) else
( -- this method is for a orthoganol view (mostly from the MXS help, thanks Bobo)
for i=1 to obj.numfaces do
(
in coordsys (inverse (viewport.GetTM())) n=getFaceNormal obj i
if n.z > 0 then append FaceList i
)
)
return facelist
)
obj=selection[1]
setfaceselection obj (selectfacing selection[1])
update selection[1] -- update the object.
Josh.
The alternative is to get the face normal, transform into view space and check its Z value – if it is negative, then it is facing away. If it is not, it is pointing at the view (because the view’s -Z axis is pointing into the scene).
See “How Do I Get Faces With Normals Facing Away?” in the MAXScript Help (one has to wonder why I write these if nobody reads them ;))[color=white]
[/color]
lol true, I actually started with yours but had to modify it for some reason that escapes me now, you even got a credit in the code there Bobo.
J.
Thanks all,
Hi j-man, your script fn works vrey good,but only edit_mesh,Can it work edit_poly ?
Hi denisT, your script fn Does not work correctly, Easy to choose the wrong face.For example A sphere ,when the script works ,Select face’s Results is wrong.
my bad (made a slip):
fn collectFlippedFaces node:selection[1] selectit:on = if iskindof node Editable_Mesh do
(
cam_dir = -(inverse (getViewTM())).row3
flipped_faces = #{}
for f in (node.faces as bitarray) where dot (getfacenormal node f) cam_dir > 0 do append flipped_faces f
if selectit do node.selectedfaces = flipped_faces
flipped_faces
)
Thanks denisT !
I tried to make it work to edit_poly,But seem it does not work,why?
denisT,Can you help me thank you !
fn collectFlippedFaces node:selection[1] selectit:on = if iskindof node Editable_poly do
(
cam_dir = -(inverse (getViewTM())).row3
flipped_faces = #{}
for f in (node.faces as bitarray) where dot (getfacenormal node f) cam_dir > 0 do append flipped_faces f
if selectit do node.selectedfaces = flipped_faces
flipped_faces
)
here is my “poly” version
fn collectFlippedPolyFaces node:selection[1] selectit:on = if iskindof node Editable_Poly do
(
cam_dir = -(inverse (getViewTM())).row3
flipped_faces = #{}
getpolynormal = polyop.getfacenormal
for f in (node.faces as bitarray) \
where dot (getpolynormal node f) cam_dir > 0 do append flipped_faces f
if selectit do node.selectedfaces = flipped_faces
flipped_faces
)
Hi, I hope you don’t mind if I rewrite this a little more expanded to make it easier to read. You should use EditablePoly methods to get right values like Poly Normals.
function collectFlippedFaces theNode:selection[1] selectIt:true =
(
local baFlippedFaces = #{}
if (isKindOf theNode Editable_Poly) do
(
local p3ViewDir = -(inverse(getViewTM())).row3
local iNumFaces = polyOp.getNumFaces theNode
for iFace = 1 to iNumFaces where ( (dot (polyOp.getFaceNormal theNode iFace) p3ViewDir) > 0 ) do
baFlippedFaces[iFace] = true
if (selectIt == true) do
(
polyOp.setFaceSelection theNode baFlippedFaces
if (subObjectLevel != 4) do
subObjectLevel = 4
forceCompleteRedraw()
)
)
return baFlippedFaces
)
- Enrico