fix: implement custom compute_normals for pygfx
pygfx doesn't have a compute_normals function, so we implement our own vertex normal computation from positions and face indices.
This commit is contained in:
@@ -17,6 +17,36 @@ from fluency.rendering.base import (
|
||||
)
|
||||
|
||||
|
||||
def compute_normals(vertices: np.ndarray, faces: np.ndarray) -> np.ndarray:
|
||||
"""Compute vertex normals from positions and face indices."""
|
||||
vertices = np.asarray(vertices, dtype=np.float32)
|
||||
faces = np.asarray(faces, dtype=np.int32)
|
||||
|
||||
normals = np.zeros_like(vertices)
|
||||
|
||||
for face in faces:
|
||||
v0, v1, v2 = vertices[face[0]], vertices[face[1]], vertices[face[2]]
|
||||
|
||||
edge1 = v1 - v0
|
||||
edge2 = v2 - v0
|
||||
|
||||
face_normal = np.cross(edge1, edge2)
|
||||
|
||||
length = np.linalg.norm(face_normal)
|
||||
if length > 1e-10:
|
||||
face_normal = face_normal / length
|
||||
|
||||
normals[face[0]] += face_normal
|
||||
normals[face[1]] += face_normal
|
||||
normals[face[2]] += face_normal
|
||||
|
||||
lengths = np.linalg.norm(normals, axis=1, keepdims=True)
|
||||
lengths = np.where(lengths > 1e-10, lengths, 1)
|
||||
normals = normals / lengths
|
||||
|
||||
return normals.astype(np.float32)
|
||||
|
||||
|
||||
@dataclass
|
||||
class PygfxRenderObject(RenderObject):
|
||||
"""pygfx render object wrapper."""
|
||||
@@ -128,10 +158,9 @@ class PygfxRenderer(Renderer):
|
||||
vertices = np.asarray(vertices, dtype=np.float32)
|
||||
faces = np.asarray(faces, dtype=np.int32)
|
||||
|
||||
geometry = gfx.Geometry(positions=vertices, indices=faces)
|
||||
normals = compute_normals(vertices, faces)
|
||||
|
||||
normals = gfx.compute_normals(geometry)
|
||||
geometry.normals = normals
|
||||
geometry = gfx.Geometry(positions=vertices, indices=faces, normals=normals)
|
||||
|
||||
material = gfx.MeshPhongMaterial(color=color, flat_shading=False)
|
||||
|
||||
@@ -252,8 +281,9 @@ class PygfxRenderer(Renderer):
|
||||
vertices = np.asarray(vertices, dtype=np.float32)
|
||||
faces = np.asarray(faces, dtype=np.int32)
|
||||
|
||||
geometry = gfx.Geometry(positions=vertices, indices=faces)
|
||||
geometry.normals = gfx.compute_normals(geometry)
|
||||
normals = compute_normals(vertices, faces)
|
||||
|
||||
geometry = gfx.Geometry(positions=vertices, indices=faces, normals=normals)
|
||||
|
||||
obj.geometry = geometry
|
||||
if obj.scene_node is not None:
|
||||
|
||||
Reference in New Issue
Block a user