# which facets are visible?

#1

hi all
i want to load an obj object, then position a camera somewhere in space .
then i want to know which facets of the object (numbered) are visible to the camera,
meaning that the normal is toward the camera and the facet is not behind any other facet.

i guess that this is done automatically all the time in 3dsmax but can i somehow get the info?

thanks in advance

p.s
this is my first post so i hope i managed to describe my problem correctly…

#2

this isn’t nearly as easy as you were hoping, I’m gonna guess

For faces facing towards/away from the camera it’s easy enough.

1. Get the camera’s direction (\$.dir) this is a vector.
2. Get the Normal of the face (getFaceNormal <mesh> i) this, too, is a vector.
3. Use ‘dot <vector1> <vector2>’ to test whether the face is facing away from (negative value) or towards (positive value) the camera.

For faces being occluded or not - welcome to a world of hurt that starts with this thread:
http://forums.cgsociety.org/showthread.php?f=98&t=295257
Basically, for each face you would have to check if any of its vertices are in front of all the other faces in the mesh; if a vertex is in front of another face, then some part of the face itself should be in front as well. The ‘in front of another face’ part is the annoying bit. If all the vertices of the other face are further away from the camera than the vertex you’re checking, then the vertex you’re checking is in front (similarly, if they’re all closer, then the vertex is behind). If one or two of the vertices of the other face are -closer-, however, you’ll need to do tricky math.

Dare we ask what you’re trying to do, just in case there’s a simpler solution?

#3

Hi Uri and welcome,
here is a function to just look for faces orientation, it doesn’t consider occlusion, but it’s a starting point. It works with Editable Poly and Editable Mesh.

``````-- getFrontFaces accepts Editable Poly and Editable Mesh objects and returns
-- a bitArray containing Camera-Facing faces index

function getFrontFaces obj =
(
-- general threshold
local fThresh = 1e-4

-- initialize face index storage
local baFrontFaces = #{}

-- initialize variables
local iNumFaces = 0

local p3FaceCenter = [0,0,0]
local p3FaceNormal = [0,0,0]

local p3CameraToFaceVect = [0,0,0]
local fDotViewAngle = 0.0

-- get current camera e viewport data
local p3CameraPos = (inverse(getViewTM())).row4
local p3CameraViewDir = -(inverse(getViewTM())).row3
local bIsPerspective = viewport.IsPerspView()

-- if object is an Editable Poly
if ((classOf obj) == Editable_Poly) then
(
-- get current number of faces in object
iNumFaces = polyOp.getNumFaces obj

-- cycle through faces
for i = 1 to iNumFaces do
(
-- get face center and normal vector
p3FaceCenter = polyOp.getFaceCenter obj i
p3FaceNormal = polyOp.getFaceNormal obj i

if (bIsPerspective == true) then -- view is perspective
(
-- get vector from camera to face center
p3CameraToFaceVect = p3FaceCenter - p3CameraPos
-- get dot between vector form camera and face normal
fDotViewAngle = dot p3CameraToFaceVect p3FaceNormal
)
else -- view is orthographic
(
-- get dot between camera view direction and face normal
fDotViewAngle = dot p3CameraViewDir p3FaceNormal
)

-- if face is not looking backward, collect it
if (fDotViewAngle < -fThresh) then ( baFrontFaces[i] = true )
)
)
else if ((classOf obj) == Editable_Mesh) then
(
iNumFaces = meshOp.getNumFaces obj

for i = 1 to iNumFaces do
(
p3FaceCenter = meshOp.getFaceCenter obj i
p3FaceNormal = getFaceNormal obj i

if (bIsPerspective == true) then
(
p3CameraToFaceVect = p3FaceCenter - p3CameraPos
fDotViewAngle = dot p3CameraToFaceVect p3FaceNormal
)
else
(
fDotViewAngle = dot p3CameraViewDir p3FaceNormal
)

if (fDotViewAngle < -fThresh) then ( baFrontFaces[i] = true )
)
)
else
(
throw "Wrong input in function getFrontFaces()"
)
return baFrontFaces
)
``````
• Enrico

#4

Dare we ask what you’re trying to do, just in case there’s a simpler solution?

basically i need to know which faces are visible at a specific camera/object orientation ,and then color the visible faces according to temperature (temperature calculations done in a different program), coloring everything and then viewing through a camera view is NOT sufficient

i dont really care if the occlusion is partial (i’ll just say it is occluded)

while reading some help files i saw “deselectHiddenFaces <mesh>”
can i somehow select all faces ,then remove from selection the hidden ones and get a list of the remaining selected faces?
Mesh Face Methods[left]
[/left]

thank you so much for your replies

#5

Hi Uri,
I just finished to write the whole function. It takes into account face direction and occlusion. It’s still a bit messy, not fast, and not commented, but seems to work well enough. I’ll try to refine it in the near future. It’s too long to post in this thread, you can find it here under “Snippets” -> “Get Front Faces”. Mind that you also need the function “getPolyFromMeshFace” under “Editable Poly data from underlying Mesh”. I hope it helps.

• Enrico

#6

Thank you so much:applause:

#7

i got it to work almost perfectly (including UI ) but i see that the selection is not perfect,
there are a few faces that are definitely not occluded and their normals are exactly like their neighbors which dont get selected,
any possible reasons ?

i converted obj to mesh

thanks

#8

Hi Uri,
the function I posted is not perfect, it doesn’t take into account some cases. The problem you’re reporting seems to be tied to threshold accuracy. I’ve been working a bit on the whole function today and will post an update as soon as it is ready. Unfortunately it is still slow because heavily relies on the MaxScript IntersectRayEx function, proven to be quite slow.

Hang in there

• Enrico

#9

thanks,
this part:

`````` if (fDotViewAngle < fThresh) then
(
baFrontFaces[i] = true
)
``````

returns true for those faces , so i guess they are later made false,

i think that in those faces a vertex or more ARE occluded and it removes the hole face

is there a way to check the face center instead of its vertices (should also be faster no?)

#10

i did this:

``````		for i = 1 to iNumFaces do
(
p3FaceCenter = meshOp.getFaceCenter obj i
p3CameraToVertDir = normalize(p3FaceCenter - p3CameraPos)

rTest = ray p3CameraPos p3CameraToVertDir
aResult = intersectRayEx obj rTest

if (aResult != undefined) then
(
if ((posMatch p3FaceCenter aResult[1].pos fThresh) == false) then
(
if (distance p3CameraPos aResult[1].pos) < (distance p3CameraPos p3FaceCenter ) then
(
baFrontFaces[i] = false
)
)
)

p3RayPos = p3FaceCenter + p3CameraToVertDir * fThresh

aIterator = #(true)
for dummy in aIterator do
(
rTest = ray p3RayPos p3CameraToVertDir
aResult = intersectRayEx obj rTest

if (aResult != undefined) then
(
baFrontFaces -= #{aResult[2]}

p3RayPos = aResult[1].pos + p3CameraToVertDir * fThresh
append aIterator true
)
)

rTest = ray (p3FaceCenter - p3CameraToVertDir * fThresh) -p3CameraToVertDir
rResult = intersectRay obj rTest
if (rResult != undefined) then
(
baFrontFaces[i] = false

)
)
setFaceSelection obj baFrontFaces
)
``````

i think it does what i wanted…
are there errors in this code?
for instance i think this: baFrontFaces -= #{aResult[2]}
is probably an error i just have no idea what to put there

#11

Hey Uri,
are you in a hurry? I just uploaded a better version of the function, try it, works better and slightly faster. There’s an optional parameter to determine occlusion detection, but try first at 0, and increment by one if fails to deselect any occluded face. I’ll refine it and add comments in the next days.

Checking face center isn’t enough to determine whole face occlusion.

``````baFrontFaces -= #{aResult[2]}
``````

means: subtract a BitArray with the single bit number aResult[2] from the BitArray baFrontFaces and assign the result to baFrontFaces. This expression is equivalent to:

``````baFrontFaces[aResult[2]] = false
``````

means: set the bit number “aResult[2]” in the BitArray baFrontFaces equal to false.

• Enrico

#12

i’ll try
though i think the face center check is what i need (even though its not as correct)

thanks

#13

Hi Uri,
I just corrected a bug in the old function and added a new one that checks normals and face centers occlusion only, for Editable Poly and Mesh. You can find them here.

• Enrico

#14

Works Great!

thank you so much for all your help

#15

Hi Uri,
if you’re working with Editable Poly, face normals aren’t always obvious since polys are made of tri faces and the poly normal is the average of those normals. Maybe the unselected polys aren’t flat and the resulting normal points away from the camera for a very little angle, I’m just guessing. You can try the first function I posted here to see if it is a face orientation problem and not occlusion, you can try to adjust the threshold value too to see if selection changes. I cannot tell what’s going on without looking at the model.

• Enrico

#16

i corrected my previous post…

it works great

thanks

#17

Hi Uri,
my last function doesn’t work right in ortho views, I’m fixing it right now, but I’ve got strange results when I tried it on an Editable Poly modified by a noise. I’m trying to figure out what’s wrong.

EDIT: I found the issue. Current functions work only for flat polys. I’m going to modify the algorithm to make it work for the most general case.

• Enrico

#18

Here they are. I just uploaded a new version of both functions. They’ve been revised and should work in every situation with Polys and Meshes, in Persp and Ortho viewports. The logic in the function to get non occluded faces by centers for Editable Polys has changed a little, now a poly is considered not occluded only if the centers of all the underlying triangles constituting it are not occluded. I hope it suits your needs.

• Enrico

p.s.
Richard was right, this wasn’t so trivial

#19

well,
you sure met the challenge
:applause:

#20

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.