libigl / libigl-python-bindings

libigl python bindings
https://libigl.github.io/libigl-python-bindings/
GNU General Public License v3.0
315 stars 62 forks source link

Ambient Occlusion - detecting outside faces #48

Closed Fliens closed 4 years ago

Fliens commented 4 years ago

So I've combined multiple stl files (10 by 10 by 10mm cubes) to one big mesh (20 by 20 by 20mm cube). Now I'm trying to detect the outside faces of this new mesh so that I can remove everything that is on the inside.

I thought it should work with the ambient occlusion function so that every face with a brightness below a certain threshold gets removed. I came up with this code:

import igl
import numpy as np
from meshplot import plot, subplot, interact
import os
import math

v, f = igl.read_triangle_mesh("cube.stl")
print("Vertices: ", len(v))
print("Faces: ", len(f))

n = igl.per_vertex_normals(v, f)
ao = igl.ambient_occlusion(v, f, v, n, 5)
newV = []
newF = []
z = 0.8 #brightness threshold
for x in range(3,len(v),3):
    if ao[x]<=z or ao[x]<=z or ao[x]<=z: #adds the faces with its verteces with brightness above z to 'newV' and 'newF'
        #each face has 3 verteces
        newV.append(v[x-3]) #verex1
        newV.append(v[x-2]) #verex2
        newV.append(v[x-1]) #verex3
        newF.append(f[int(x/3)-1]) #face
plot(np.array(newV),np.array(newF))

Unfortunately it also detects faces that are on the inside as bright, as you can see in this picture

The mesh I'm importing (my 20 by 20 by 20mm cube) looks like this

So what am I doing wrong? Because when calculating the brightness and then plotting the mesh it looks pretty good, but it somehow detects the inside faces as bright when running my code :/

skoch9 commented 4 years ago

If I understand you correctly, you basically want to filter out faces according to the summed ambient occlusion value? The ao value is 1.0 at a vertex if it is occluded, and 0.0 if it is visible. Your code has a few mistakes. Something like the following should work:

v, f = igl.read_triangle_mesh("my.obj")
n = igl.per_vertex_normals(v, f)
ao = igl.ambient_occlusion(v, f, v, n, 5)
face_ao = np.sum(ao[f], axis=1) / 3.0 # Summed AO per face
plot(v, f[face_ao < 0.8])