Fix broken gltf exports and minor cleanup

This commit is contained in:
Yeicor
2025-04-20 12:47:23 +02:00
parent 9e4f571808
commit b629f07f5e
7 changed files with 40 additions and 34 deletions

View File

@@ -10,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_Shape
from build123d import Compound, Shape, Color
from build123d import Compound, Color
from yacv_server.gltf import GLTFMgr
@@ -78,7 +78,7 @@ def get_shape(obj: CADLike, error: bool = True) -> Optional[CADCoreLike]:
# Sorting is required to improve hashcode consistency
shapes_raw_filtered_sorted = sorted(shapes_raw_filtered, key=lambda x: _hashcode(x))
# Build a single compound shape
shapes_bd = [Shape(shape) for shape in shapes_raw_filtered_sorted if shape is not None]
shapes_bd = [Compound(shape) for shape in shapes_raw_filtered_sorted if shape is not None]
return get_shape(Compound(shapes_bd), error)
except TypeError:
pass
@@ -121,11 +121,11 @@ def image_to_gltf(source: str | bytes, center: any, width: Optional[float] = Non
hasher = hashlib.md5()
hasher.update(source)
name = 'image_' + hasher.hexdigest()
format: str
_format: str
if save_mime == 'image/jpeg':
format = 'JPEG'
_format = 'JPEG'
elif save_mime == 'image/png':
format = 'PNG'
_format = 'PNG'
else:
raise ValueError(f'Unsupported save MIME type (for GLTF files): {save_mime}')
@@ -154,7 +154,7 @@ def image_to_gltf(source: str | bytes, center: any, width: Optional[float] = Non
img = img.resize((new_width, new_height))
# Save the image to a buffer
img.save(img_buf, format=format)
img.save(img_buf, format=_format)
img_buf = img_buf.getvalue()
# Convert coordinates system as a last step (gltf is Y-up instead of Z-up)

View File

@@ -169,6 +169,7 @@ class GLTFMgr:
self.gltf.images = [Image(bufferView=len(buffers_list), mimeType=self.image[1])]
self.gltf.textures = [Texture(source=0, sampler=0)]
self.gltf.samplers = [Sampler(magFilter=NEAREST)]
# noinspection PyPep8Naming
self.gltf.materials[0].pbrMetallicRoughness.baseColorTexture = TextureInfo(index=0)
buffers_list.append((Accessor(), BufferView(), self.image[0]))

View File

@@ -138,3 +138,4 @@ class HTTPHandler(SimpleHTTPRequestHandler):
self.send_header('E-Tag', f'"{_hash}"')
self.end_headers()
self.wfile.write(exported_glb)
return None

View File

@@ -1,8 +1,6 @@
import queue
import queue
import threading
from typing import List, TypeVar, \
Generic, Generator
from typing import List, TypeVar, Generic, Generator
from yacv_server.mylogger import logger
@@ -58,7 +56,7 @@ class BufferedPubSub(Generic[T]):
def subscribe(self, include_buffered: bool = True, include_future: bool = True, yield_timeout: float = 0.0) -> \
Generator[T, None, None]:
"""Subscribes to events as an generator that yields events and automatically unsubscribes"""
"""Subscribes to events as a generator that yields events and automatically unsubscribes"""
q = self._subscribe(include_buffered, include_future)
try:
while True:

View File

@@ -5,7 +5,7 @@ from OCP.BRepAdaptor import BRepAdaptor_Curve
from OCP.GCPnts import GCPnts_TangentialDeflection
from OCP.TopLoc import TopLoc_Location
from OCP.TopoDS import TopoDS_Face, TopoDS_Edge, TopoDS_Shape, TopoDS_Vertex
from build123d import Shape, Vertex, Face, Location
from build123d import Vertex, Face, Location, Compound
from pygltflib import GLTF2
from yacv_server.cad import CADCoreLike, ColorTuple
@@ -33,7 +33,7 @@ def tessellate(
mgr.add_location(Location(cad_like))
elif isinstance(cad_like, TopoDS_Shape):
shape = Shape(cad_like)
shape = Compound(cad_like)
# Perform tessellation tasks
edge_to_faces: Dict[str, List[TopoDS_Face]] = {}
@@ -59,6 +59,9 @@ def tessellate(
for vertex in shape.vertices():
_tessellate_vertex(mgr, vertex.wrapped, vertex_to_faces.get(vertex.wrapped, []), obj_color)
else:
raise TypeError(f"Unsupported type: {type(cad_like)}: {cad_like}")
return mgr.build()
@@ -69,9 +72,10 @@ def _tessellate_face(
angular_tolerance: float = 0.1,
color: Optional[ColorTuple] = None,
):
face = Shape(ocp_face)
face = Compound(ocp_face)
# face.mesh(tolerance, angular_tolerance)
tri_mesh = face.tessellate(tolerance, angular_tolerance)
# noinspection PyArgumentList
poly = BRep_Tool.Triangulation_s(face.wrapped, TopLoc_Location())
if poly is None:
logger.warn("No triangulation found for face")
@@ -86,6 +90,7 @@ def _tessellate_face(
vertices = tri_mesh[0]
indices = tri_mesh[1]
mgr.add_face(vertices, indices, uv, color)
return None
def _push_point(v: Tuple[float, float, float], faces: List[TopoDS_Face]) -> Tuple[float, float, float]:

View File

@@ -9,18 +9,18 @@ import threading
import time
from dataclasses import dataclass
from http.server import ThreadingHTTPServer
from io import BytesIO
from threading import Thread
from typing import Optional, Dict, Union, Callable, List, Tuple
from OCP.TopLoc import TopLoc_Location
from OCP.TopoDS import TopoDS_Shape
# noinspection PyProtectedMember
from build123d import Shape, Axis, Location, Vector, Color
from dataclasses_json import dataclass_json
from PIL import Image
from io import BytesIO
# noinspection PyProtectedMember
from build123d import Shape, Axis, Location, Vector
from dataclasses_json import dataclass_json
from yacv_server.cad import _hashcode, ColorTuple, get_color
from yacv_server.cad import _hashcode, get_color
from yacv_server.cad import get_shape, grab_all_cad, CADCoreLike, CADLike
from yacv_server.gltf import get_version
from yacv_server.myhttp import HTTPHandler
@@ -95,7 +95,7 @@ class YACV:
"""Default texture to use for model faces, in (data, mimetype) format.
If left as None, a default checkerboard texture will be used.
It can be set with the YACV_BASE_TEXTURE=<uri> and overriden by `show(..., texture="<uri>")`.
It can be set with the YACV_BASE_TEXTURE=<uri> and overridden by `show(..., texture="<uri>")`.
The <uri> can be file:<path> or data:<mime>;base64,<data> where <mime> is the mime type and
<data> is the base64 encoded image."""
@@ -331,6 +331,7 @@ class YACV:
try:
return next(subscription), event.hash
finally:
# noinspection PyInconsistentReturns
subscription.close()
def export_all(self, folder: str,