From 69c560dfe66bfc2ae78ddc44c32e7119b094055a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=27=C3=A9lectron=20rare?= <108685187+electron-rare@users.noreply.github.com> Date: Thu, 2 Jul 2026 18:57:36 +0200 Subject: [PATCH] feat(viz): bold body skeleton strokes Metal lines are 1px and the skeleton was barely visible in performance. Each ARKit bone is now drawn in concentric offset passes (SKEL_LINE_WIDTH, default 4 approx px; 1 restores the thin look). --- data_only_viz/config.py | 5 +++++ data_only_viz/renderer.py | 15 +++++++++++++-- data_only_viz/tests/test_config.py | 5 +++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/data_only_viz/config.py b/data_only_viz/config.py index af07416..3ae5237 100644 --- a/data_only_viz/config.py +++ b/data_only_viz/config.py @@ -45,6 +45,7 @@ VIZ_HUD "0" bool show debug HUD overlay VIZ_SOURCE_KEYS "0" bool wxcvbn + 0-9 source-bundle shortcuts (off: perf safety) VIZ_AUDIO_KEYS "0" bool qsdfghjkl audio-scene shortcuts (off: perf safety; m stays) VIZ_DEFAULT_MODE "auto" str fixed boot viz mode (e.g. voronoi); disables auto-openpos +SKEL_LINE_WIDTH "4" int body skeleton stroke width, approx px (1 = thin) IPHONE_OSC_PORT 57128 int UDP port for iPhone ARBodyTracker /body3d/kp CONCERT_MIRROR "1" bool mirror video horizontally (!=0 = True) ICP_FUSION "0" bool enable ICP LiDAR fusion (only "1" = True) @@ -147,6 +148,9 @@ class VizConfig: # appear). A fixed mode also DISABLES the auto-openpos timer so it is # truly always on (user request live 2026-07-02: t/voronoi permanent). viz_default_mode: str = "auto" + # Approximate body-skeleton stroke width in pixels (multi-pass offsets; + # Metal lines are 1px). 1 = thin historical look. + skel_line_width: int = 4 # ---- iPhone OSC ------------------------------------------------------ iphone_osc_port: int = 57128 @@ -297,6 +301,7 @@ class VizConfig: viz_source_keys=_bool_std("VIZ_SOURCE_KEYS", False), viz_audio_keys=_bool_std("VIZ_AUDIO_KEYS", False), viz_default_mode=_str("VIZ_DEFAULT_MODE", "auto"), + skel_line_width=_int("SKEL_LINE_WIDTH", 4), iphone_osc_port=_int("IPHONE_OSC_PORT", 57128), concert_mirror=_bool_ne0("CONCERT_MIRROR", True), # ICP_FUSION / MULTIHMR_AUTOCAST use strict "1" convention diff --git a/data_only_viz/renderer.py b/data_only_viz/renderer.py index 0f7373a..7989dd4 100644 --- a/data_only_viz/renderer.py +++ b/data_only_viz/renderer.py @@ -171,6 +171,7 @@ class MetalRenderer(NSObject): # future iPhone app build flips it. self._hand_swap_lr = _cfg.hand_swap_lr self._arkit_full = _cfg.arkit_full_skeleton + self._skel_width = max(1, int(_cfg.skel_line_width)) self._init_skel_cpu_buffer() self._init_mesh_cpu_buffer() self._build_pipelines() @@ -432,11 +433,21 @@ class MetalRenderer(NSObject): valid = ~fmask elif len(valid) == len(fmask): valid = valid & ~fmask + # Bold strokes: Metal lines are 1px, so each bone is drawn + # in concentric offset passes (SKEL_LINE_WIDTH approx px). + _w = getattr(self, "_skel_width", 1) + _o = 1.0 / max(1, s.height or 720) + _offsets = [(0.0, 0.0)] + for _r in range(1, _w): + _d = _r * _o + _offsets += [(_d, 0.0), (-_d, 0.0), (0.0, _d), (0.0, -_d)] for (ax, ay, bx, by) in arkit_segments( arr2d, valid, parents, max_len=self._arkit_bone_max ): - if not push_seg(ax, ay, bx, by, 1.0, pid): - break + for _dx, _dy in _offsets: + if not push_seg(ax + _dx, ay + _dy, + bx + _dx, by + _dy, 1.0, pid): + break if self._mp_bones is not None and ( s.persons_body or s.persons_face or s.persons_hands or diff --git a/data_only_viz/tests/test_config.py b/data_only_viz/tests/test_config.py index 73e59fe..6381bb0 100644 --- a/data_only_viz/tests/test_config.py +++ b/data_only_viz/tests/test_config.py @@ -425,3 +425,8 @@ def test_viz_default_mode(): assert VizConfig.from_env({}).viz_default_mode == "auto" assert VizConfig.from_env( {"VIZ_DEFAULT_MODE": "voronoi"}).viz_default_mode == "voronoi" + + +def test_skel_line_width_default(): + assert VizConfig.from_env({}).skel_line_width == 4 + assert VizConfig.from_env({"SKEL_LINE_WIDTH": "1"}).skel_line_width == 1