sensor: finger revision: r01 status: experimental # Authoring unit in Blender (mm). Export converts using meters_per_source_unit. authoring_unit: mm meters_per_source_unit: 0.001 source_blend: source/geometry.blend # Expected sensing surface topology for r01 (from shipped 30fps-0703 runtime). # First exports from geometry.blend may differ until topology is locked. expected: sensing_vertices: 1032 sensing_triangles: 1974 frames: sensor: origin_sensor objects: sensing_surface: sensing_surface cam_sensor: cam_sensor origin_sensor: origin_sensor # Headless colored-patch texture generation (`orisys-design texture`). # UV unwrapping is still done in the Blender GUI: the headless run consumes the # UV maps already stored in source_blend and never creates or unwraps one. # One PNG/SVG/PDF set is written per UV map below. All maps and formats share # the settings and patch colours, so they differ only by UV layout. # These are the revision defaults; CLI flags override every value. texture_patch: mesh: sensing_surface camera: cam_sensor uv_outputs: produce: patch_texture_produce.png # hardware production layout compute: patch_texture_compute.png # compute/runtime layout width: 3280 # 1640*2 height: 3200 # 1600*2 nx: 80 ny: 45 color_r: 0.05 edge_sample_grid: 5 seed: 7 # fixed so PNG/SVG/PDF share one reproducible colour set vector: width_mm: 16.4 # editable SVG/PDF production page width height_mm: 16.0 # editable SVG/PDF production page height cross: enabled: true length_px: 40 thickness_px: 3 color: [1.0, 0.0, 0.0, 1.0] # red reference cross # Multi-view production textures (`orisys-design texture-views`). # # The PATTERN is grounded on the sensing camera, not on the production views. `uv_1` and # `uv_2` are two different *parameterisations* of the one surface pattern that # `texture_compute` carries, so the printed marker stays a single pattern across the whole # surface. `cam_uv_1` / `cam_uv_2` authored those layouts in Blender (Project from View # (Bounds)) and now serve as each pair's REGION camera: they decide which surface that pair # may own. Neither is a pattern source. # # OWNERSHIP closes the overlap. `uv_1` and `uv_2` are both full-surface layouts, so printing # both would double-ink essentially the whole part. Every loop triangle is assigned to # exactly one pair and each file emits only its own triangles, which makes zero double ink a # property of the partition rather than something to measure after printing. # # Rendering settings (page size, grid, palette, seed) come from `texture_patch` above, # because they are decisions about the printed page rather than about a particular layout. # `produce`/`compute` and `orisys-design texture` are untouched. texture_patch_views: enabled: true pattern_camera: cam_sensor # the pattern every layout carries, same source as `compute` # Per-view page sizing. A layout authored by Project from View (Bounds) maps [0,1]^2 to the # image-plane extent of the mesh through ITS camera, so the page is measurable and differs # per view: measured 17.5116 x 15.9772 mm for uv_1 (aspect 1.0960) and 17.5114 x 15.9820 mm # for uv_2 (aspect 1.0957). `vector:` above says 16.4 x 16.0 (aspect 1.0250), which stretched # the artwork by 6.9% along u. `auto` derives it and proves the layout really is a # bounds-projection from the named camera before using the result. # # `px_per_mm: 200` reproduces the existing density exactly (3280/16.4 = 3700/18.5 = 200.0), # and the page is set from the rounded raster so page and raster always share an aspect. # # `fixed` keeps `texture_patch.vector`. Unwrapped layouts (`produce`, `compute`) are not # projections and must use it — a camera-derived page would be meaningless there. # # To overlay a texture on a render from its camera: set the render resolution to the emitted # raster size and the background image to "Stretch to fill". At any other resolution the # scene aspect (1280x720 here) will distort the overlay regardless of the page. page: mode: auto px_per_mm: 200 pairs: - id: uv_1 # layout authored from cam_uv_1 camera: cam_uv_1 # REGION camera: what this pair may own uv_map: uv_1 - id: uv_2 camera: cam_uv_2 uv_map: uv_2 merge: # `authored` honours the seam marked on the mesh: 32 edges on y = 0, which cuts the # surface into 2 components of 177.882 / 177.885 mm^2 (50.0 / 50.0). Because the two # cameras are mirrored about XZ that plane is also where incidence_uv1 == incidence_uv2, # so the hand-drawn seam coincides with the metric-optimal boundary: measured coverage # differs from `computed` by 0.0014 at 60 deg and by nothing from 62 deg up. mode: authored # Calibrated on this mesh (355.767 mm^2, 1977 tris): 60 deg leaves 0.0218 holes and FAILS # max_hole_fraction, 62 deg leaves 0.0000. 65 deg was an earlier estimate from the # pre-edit mesh; 62 is the measured threshold. incidence_limit_deg: 62.0 min_footprint_mm2: 2.0e-3 # ~1 printer dot at 600 dpi, squared x 1.1 min_triangle_coverage: 0.60 max_hole_fraction: 0.02 component_policy: best_coverage # not `pinned`: both views qualify, so let the metric rank seam: boundary: use_seam # read mesh.edges[].use_seam as a hard graph cut pins: [] # {component, view, reason} to override a component's owner # Empty band along the seam, to absorb two-pass registration error. Without it the two # files butt exactly at the seam and any placement error makes them overlap there, which # is the delamination case. # # The width is derived, not guessed. Each pass is placed to within # `alignment_tolerance_mm`, so the two can close on each other by twice that; the band # must be at least that wide. Default total = 2 x tolerance = 0.2 mm, half per file, and # `total_mm` overrides the derivation if a different margin is wanted. gap: enabled: true # false = hard butt at the seam, no band at all apply: post_process # post_process = straight edge | geometry_trim = sawtooth treatment: no_print # the band carries nothing alignment_tolerance_mm: 0.1 # per-pass placement accuracy, mm # total_mm: 0.2 # default: 2 x alignment_tolerance_mm print: # Every artifact carries a full-page black ``. That background # is itself a print element, so it cannot be used as the "no print" marker: the split is # expressed by WHERE the white mesh layer is drawn and where the colour patches are. # # `owned` keeps the same white ground the `compute` texture carries, but clipped to the # triangles this view owns. So white is split by the seam exactly like the pattern is, # and neither file paints white over the other's territory. base_fill: owned # Post-generation printability inspection (`orisys-design inspect`). Advisory # only: it reports a verdict but never blocks generation or changes exit codes. # Millimetres are measured on the vector page declared above. printability: printer_dpi: 600 # target UV printer resolution min_dots: 2 # printer dots required across the smallest feature min_feature_mm: 0.10 # smallest acceptable feature width min_edge_mm: 0.05 # shortest acceptable polygon edge max_sliver_ratio: 4.0 # longest edge / minimum width min_patch_area_mm2: 1.0e-4 # area above which a polygon is a material feature collections: frames: FRAMES export_compute: EXPORT_COMPUTE assembly: ASSEMBLY design_sim: DESIGN_SIM exclude: EXCLUDE notes: | Canonical source is geometry.blend with named collections and objects. Compute export uses sensing_surface + cam_sensor relative to origin_sensor. Studio observation cameras are derived from mesh bounds; no cam_viz required.