I have a camera and a monkey (suzanne) in the scene. I'm attempting to manually cull the back faces from the monkey.
The problem is that certain faces get culled, despite its normal seen from the camera's view port.
- The monkey in object mode.
- The monkey after culling (using the function below).
I transform the monkey's vertices into world space, then transform the vertices to face the camera (camera's inverse matrix). This assumes the camera is at (0,0,0).
I'm using the internal renderer. Blender 2.78.
def cull_manual(camera_obj, object_obj):
matrix = camera_obj.matrix_local.inverted() * object_obj.matrix_local
delete_faces = []
mesh = object_obj.data
new_bmesh = bmesh.from_edit_mesh(mesh)
for face in new_bmesh.faces:
verts = [(matrix * bmvert.co) for bmvert in face.verts]
a = (verts[1] - verts[0])
b = (verts[2] - verts[0]) if (len(verts) == 3) else (verts[3] - verts[0])
normal = a.cross(b).normalized()
v = verts[0].normalized()
visibility = (-v).dot(normal)
if visibility <= 0.0:
delete_faces.append(face)
bmesh.ops.delete(new_bmesh, geom = delete_faces, context = 5)
bmesh.update_edit_mesh(mesh)
camera_obj = find_obj(scene, "Camera.05")
object_obj = find_obj(scene, "Suzanne")
cull_manual(camera_obj, object_obj)
I devised a way to do it the opposite way, where I move the object to the origin, and move the camera by applying the object's inverse transform:
def cull_from_camera(camera_obj, object_obj):
matrix = object_obj.matrix_world.inverted()
camera_matrix = matrix * camera_obj.matrix_world
location, _, _ = camera_matrix.decompose()
from_camera = location.normalized()
delete_faces = []
mesh = object_obj.data
new_bmesh = bmesh.new()
new_bmesh.from_mesh(mesh)
for face in new_bmesh.faces:
visibility = from_camera.dot(face.normal)
E = 1.0e-05
R = -0.5 # HERE
if visibility <= (R + E):
delete_faces.append(face)
bmesh.ops.delete(new_bmesh, geom = delete_faces, context = 5)
new_bmesh.to_mesh(mesh)
mesh.update()
It works, but there are still some aggressive culling happening, unless I change the visibility check from 0.0 to -0.5.
I can't think of a way to truly cull only the faces that are not visible to the camera.