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
|
@dataclass
|
||||||
class PygfxRenderObject(RenderObject):
|
class PygfxRenderObject(RenderObject):
|
||||||
"""pygfx render object wrapper."""
|
"""pygfx render object wrapper."""
|
||||||
@@ -128,10 +158,9 @@ class PygfxRenderer(Renderer):
|
|||||||
vertices = np.asarray(vertices, dtype=np.float32)
|
vertices = np.asarray(vertices, dtype=np.float32)
|
||||||
faces = np.asarray(faces, dtype=np.int32)
|
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 = gfx.Geometry(positions=vertices, indices=faces, normals=normals)
|
||||||
geometry.normals = normals
|
|
||||||
|
|
||||||
material = gfx.MeshPhongMaterial(color=color, flat_shading=False)
|
material = gfx.MeshPhongMaterial(color=color, flat_shading=False)
|
||||||
|
|
||||||
@@ -252,8 +281,9 @@ class PygfxRenderer(Renderer):
|
|||||||
vertices = np.asarray(vertices, dtype=np.float32)
|
vertices = np.asarray(vertices, dtype=np.float32)
|
||||||
faces = np.asarray(faces, dtype=np.int32)
|
faces = np.asarray(faces, dtype=np.int32)
|
||||||
|
|
||||||
geometry = gfx.Geometry(positions=vertices, indices=faces)
|
normals = compute_normals(vertices, faces)
|
||||||
geometry.normals = gfx.compute_normals(geometry)
|
|
||||||
|
geometry = gfx.Geometry(positions=vertices, indices=faces, normals=normals)
|
||||||
|
|
||||||
obj.geometry = geometry
|
obj.geometry = geometry
|
||||||
if obj.scene_node is not None:
|
if obj.scene_node is not None:
|
||||||
|
|||||||
Reference in New Issue
Block a user