From 69b1da711e591794ab75eae04c1beed55b351cbe Mon Sep 17 00:00:00 2001 From: Yeicor <4929005+Yeicor@users.noreply.github.com> Date: Sat, 24 Feb 2024 10:56:18 +0100 Subject: [PATCH] make "inner" edges more visible --- yacv_server/plugin.py | 1 + yacv_server/tessellate.py | 39 +++++++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 yacv_server/plugin.py diff --git a/yacv_server/plugin.py b/yacv_server/plugin.py new file mode 100644 index 0000000..8e03648 --- /dev/null +++ b/yacv_server/plugin.py @@ -0,0 +1 @@ +# TODO: Plugins that can freely modify the GLTF file as it is being built diff --git a/yacv_server/tessellate.py b/yacv_server/tessellate.py index 1a3cacf..2a34633 100644 --- a/yacv_server/tessellate.py +++ b/yacv_server/tessellate.py @@ -1,6 +1,7 @@ import hashlib import io import re +from typing import List, Dict, Tuple from OCP.BRep import BRep_Tool from OCP.BRepAdaptor import BRepAdaptor_Curve @@ -9,7 +10,7 @@ from OCP.TopExp import TopExp from OCP.TopLoc import TopLoc_Location from OCP.TopTools import TopTools_IndexedMapOfShape from OCP.TopoDS import TopoDS_Face, TopoDS_Edge, TopoDS_Shape, TopoDS_Vertex -from build123d import Shape, Vertex +from build123d import Shape, Vertex, Face from pygltflib import GLTF2 import mylogger @@ -32,15 +33,23 @@ def tessellate( shape = Shape(ocp_shape) # Perform tessellation tasks + edge_to_faces: Dict[TopoDS_Edge, List[TopoDS_Face]] = {} + vertex_to_faces: Dict[TopoDS_Vertex, List[TopoDS_Face]] = {} if faces: for face in shape.faces(): _tessellate_face(mgr, face.wrapped, tolerance, angular_tolerance) + if edges: + for edge in face.edges(): + edge_to_faces[edge] = edge_to_faces.get(edge, []) + [face.wrapped] + if vertices: + for vertex in face.vertices(): + vertex_to_faces[vertex.wrapped] = vertex_to_faces.get(vertex.wrapped, []) + [face.wrapped] if edges: for edge in shape.edges(): - _tessellate_edge(mgr, edge.wrapped, angular_tolerance, angular_tolerance) + _tessellate_edge(mgr, edge.wrapped, edge_to_faces[edge], angular_tolerance, angular_tolerance) if vertices: for vertex in shape.vertices(): - _tessellate_vertex(mgr, vertex.wrapped) + _tessellate_vertex(mgr, vertex_to_faces[vertex], vertex.wrapped) return mgr.gltf @@ -70,19 +79,37 @@ def _tessellate_face( mgr.add_face(vertices, indices, uv) +def _push_point(v: Tuple[float, float, float], faces: List[TopoDS_Face]) -> Tuple[float, float, float]: + # Use the connected faces to push edges/vertices and make them always visible + push_dir = (0, 0, 0) + for ocp_face in faces: + normal = Face(ocp_face).normal_at(v) + push_dir = (push_dir[0] + normal.X, push_dir[1] + normal.Y, push_dir[2] + normal.Z) + if push_dir != (0, 0, 0): + # Normalize the push direction by the number of faces and a constant factor + # NOTE: Don't overdo it, or metrics will be wrong + n = len(faces) / 1e-3 + push_dir = (push_dir[0] / n, push_dir[1] / n, push_dir[2] / n) + # Push the vertex by the normal + v = (v[0] + push_dir[0], v[1] + push_dir[1], v[2] + push_dir[2]) + return v + + def _tessellate_edge( mgr: GLTFMgr, ocp_edge: TopoDS_Edge, + faces: List[TopoDS_Face], angular_deflection: float = 0.1, curvature_deflection: float = 0.1, ): + # Use a curve discretizer to get the vertices curve = BRepAdaptor_Curve(ocp_edge) discretizer = GCPnts_TangentialDeflection(curve, angular_deflection, curvature_deflection) assert discretizer.NbPoints() > 1, "Edge is too small??" # add vertices vertices = [ - (v.X(), v.Y(), v.Z()) + _push_point((v.X(), v.Y(), v.Z()), faces) for v in ( discretizer.Value(i) # .Transformed(transformation) for i in range(1, discretizer.NbPoints() + 1) @@ -91,9 +118,9 @@ def _tessellate_edge( mgr.add_edge(vertices) -def _tessellate_vertex(mgr: GLTFMgr, ocp_vertex: TopoDS_Vertex): +def _tessellate_vertex(mgr: GLTFMgr, ocp_vertex: TopoDS_Vertex, faces: List[TopoDS_Face]): c = Vertex(ocp_vertex).center() - mgr.add_vertex((c.X, c.Y, c.Z)) + mgr.add_vertex(_push_point((c.X, c.Y, c.Z), faces)) def _hashcode(obj: TopoDS_Shape) -> str: