981c250559
- What: `VIEW_SHOWS_3D` 加入 `replay`;`app_window` 新增 `_shows_3d()`(可见性与布局共用一个判据) 与 `_splitter_sizes_for()`(预设表里的 3D 槽是"二维布局"的描述,面板打开时从最宽的面板借 `DEFAULT_3D_PANE_WIDTH=340`);`ThreeDPanel` 新增第三个来源标签(实时采集 / 回放:录像不含三维场 / 重算通道:由录像重算,非记录值)与 `set_source_kind()`;`ThreeDCoordinator.show_rest()` 把参考模型 放回屏幕并停止主张测量值(重算停止时调用,否则最后一帧会留在屏幕上);`Mesh3dPanel` 转发这两者, 并新增"加载中"状态的修正:切换传感器再切回来时若该包已加载,直接显示已就绪的画面而不是一条永远 不会被替换的"正在加载"。 - Why: 录像里没有三维场(raw_*.mp4 是原始相机图像,`depth.stored=false`,CSV 只有力值),所以纯回放只能 显示参考模型;但「从视频重算力值」本来就把同一个运行路径指向录像的原始视频,而采集线程上的三维 sink 早已注册——因此重算一开始面板就会收到真实的形变帧。这两件事必须由界面区分:一个是"没有测量", 一个是"当前算法对这段录像会说什么",把后者当成记录值展示就是另一种 `display_illustrative`。 - Verification: apps/studio 全量通过(test_scene3d_view.py 32 项,含"回放里面板可见且标注正确""重算时 标注切换""停止重算后清回参考模型""实时视图标为实时";test_scene3d_coordinator.py 15 项,含 show_rest 与"停止时在飞的帧不会随后被显示");ui_check 570 项 0 失败(新增"已安装包必须被加载并标注来源"); locale_check 0 缺失;仓库内工程包经 validate_scene 全部 ok。 - Not in this change: 逐帧保存展开场/深度(记录格式变更,设计文档明确否掉);重算通道本身(已存在,本次 只是把它的帧接到面板上);示意位移(仍需 SDK lift + 已确认尺度)。
127 lines
5.9 KiB
Markdown
127 lines
5.9 KiB
Markdown
# Scene asset tools
|
||
|
||
Offline tools for the three-dimensional view. They never run in the application:
|
||
the app loads a **compiled** package (`.oryscene`) and nothing else.
|
||
|
||
| tool | what it is for |
|
||
|---|---|
|
||
| `compile_scene.py` | a Blender export (+ optional housing GLB) → one `.oryscene` package |
|
||
| `validate_scene.py` | the checks the loader and the compiler must agree on; the release gate |
|
||
| `probe_gl.py` | what this machine's OpenGL actually is (exit 0 GPU, 3 software, 4 no context) |
|
||
| `bench_scene.py` | per-stage p50/p95 of the running view (`--cpu-only` for the pure CPU cost) |
|
||
| `soak_scene.py` | long run: RSS trend and the queue bound |
|
||
|
||
Run them with the repository's own interpreter, from `orisys-app`:
|
||
|
||
```powershell
|
||
$py = '.venv-build\Scripts\python.exe'
|
||
```
|
||
|
||
## Compiling the shipped finger sensor
|
||
|
||
The **runtime** asset is `sensors/finger/assets/30fps-0703`: it is what
|
||
`sensors/finger/manifest.json` names (`assets_dir`), and its unroll map
|
||
(`unroll_map_uv_s0.4.npz`, out size 300×280, `source_scale` 0.4) matches
|
||
`camera.resolution_stitch` in `sensor.json`, which is the grid the live optical flow
|
||
is computed on.
|
||
|
||
Do **not** compile `assets/visualization/flatten_remap.npz`: it is a 1024×1024
|
||
domain, so every live frame would be refused with `field_domain_mismatch`
|
||
(300x280 vs 1024x1024). That map belongs to offline visualisation.
|
||
|
||
```powershell
|
||
$sdk = 'D:\orisys_ws\orisys-sdk\sensors\finger\assets\30fps-0703' # or the copy in apps/studio/config
|
||
|
||
# 1) state the unit (the importer never guesses it) and read what it measured
|
||
& $py tools\scene_assets\validate_scene.py --legacy-dir $sdk --map "$sdk\unroll_map_uv_s0.4.npz"
|
||
|
||
# 2) compile
|
||
& $py tools\scene_assets\compile_scene.py `
|
||
--legacy-dir $sdk `
|
||
--map "$sdk\unroll_map_uv_s0.4.npz" `
|
||
--meters-per-source-unit 0.001 `
|
||
--output apps\studio\config\sensors\finger\scene\finger-display-1.0.0.oryscene
|
||
|
||
# 3) verify
|
||
& $py tools\scene_assets\validate_scene.py apps\studio\config\sensors\finger\scene\finger-display-1.0.0.oryscene
|
||
```
|
||
|
||
**`--meters-per-source-unit` is a physical statement about the sensor, not a
|
||
formatting choice.** The measured mesh extent is 15.81 × 15.0 × 7.5 source units
|
||
(1032 vertices, 1974 triangles); the shipped finger surface is about 15.8 mm across,
|
||
so one source unit is one millimetre and the value is `0.001`. If the mechanical
|
||
drawing says otherwise, state that number instead — nothing downstream can tell the
|
||
difference, and a wrong factor looks plausible.
|
||
|
||
Expected result: `1032 vertices`, `1974 triangles`, `geometry_id` starting
|
||
`1a2e0e92…`, a 56 KB package, and `validate_scene.py` reporting every check `ok`.
|
||
|
||
## Where the application looks for a package
|
||
|
||
1. `preference.json` → `"scene3d_package": "<path>"` (an absolute path; also the way
|
||
to point a developer build at a freshly compiled package);
|
||
2. `<config>/sensors/<sensor>/scene/*.oryscene` — for the studio app that is
|
||
`apps/studio/config/sensors/finger/scene/`;
|
||
3. nothing: the pane reports the directory it searched and the compile command above,
|
||
and the two-dimensional views keep working.
|
||
|
||
The SDK's own `sensors/` tree is **not** searched (the app prefers its local
|
||
`config/sensors` bundles). Compile into the app's `scene/` directory, or set
|
||
`scene3d_package`.
|
||
|
||
## Release packages (signature, optional encryption, platform lock)
|
||
|
||
All three are optional and independent of the plain package above:
|
||
|
||
```powershell
|
||
& $py tools\scene_assets\compile_scene.py --legacy-dir $sdk --map "$sdk\unroll_map_uv_s0.4.npz" `
|
||
--meters-per-source-unit 0.001 `
|
||
--sign-key keys\build-ed25519.pem --sign-key-id build-2024 `
|
||
--write-verify-key keys\build-ed25519.pub.pem `
|
||
--encrypt-key-id finger-display --key-file keys\finger-display.key `
|
||
--lock-from-probe docs\architecture\gl-report-windows-dev.json `
|
||
--output apps\studio\config\sensors\finger\scene\finger-display-1.0.0.oryscene
|
||
```
|
||
|
||
- `--sign-key` signs the manifest (and therefore every entry hash, the compatibility
|
||
information and the platform lock). The private key stays on the build machine; the
|
||
client ships only `--write-verify-key`'s public half.
|
||
- `--encrypt-key-id` + `--key-file` additionally seal the content with AES-256-GCM.
|
||
Encryption never replaces signing. Reading a sealed package needs the
|
||
`protected-assets` extra (`cryptography`); a plain package does not.
|
||
- `--lock-from-probe` takes the platform lock (OS, architecture, GL profile, vendor,
|
||
renderer, minimum texture size, "no software rasteriser") from a `probe_gl.py`
|
||
report. A machine the lock excludes loses the 3D pane, with the reason, and keeps
|
||
everything else.
|
||
- `--encrypt-key-id` without `--key-file`, or with no crypto backend installed, is
|
||
**refused** rather than silently writing a plain package that looks protected.
|
||
|
||
Release gate:
|
||
|
||
```powershell
|
||
& $py tools\scene_assets\validate_scene.py <package> `
|
||
--key-file keys\finger-display.key --key-id finger-display `
|
||
--verify-key keys\build-ed25519.pub.pem --require-signature
|
||
```
|
||
|
||
## Performance and long runs
|
||
|
||
```powershell
|
||
# per-stage p50/p95 of the running view (needs a real window system)
|
||
$env:QT_QPA_PLATFORM = 'windows'
|
||
& $py tools\scene_assets\bench_scene.py --frames 600 --output perf.json
|
||
& $py tools\scene_assets\bench_scene.py --cpu-only --frames 500 --vertices 20000 --output perf-cpu.json
|
||
& $py tools\scene_assets\bench_scene.py --package <package> --key-file keys\finger-display.key `
|
||
--key-id finger-display --verify-key keys\build-ed25519.pub.pem --output perf-real.json
|
||
|
||
# long run: the release gate is two hours in the GUI mode (it is the stricter one)
|
||
& $py tools\scene_assets\soak_scene.py --minutes 120 --fps 30 --output soak.json
|
||
& $py tools\scene_assets\soak_scene.py --no-window --minutes 10 --fps 60 --output soak-cpu.json
|
||
```
|
||
|
||
The committed reports for the developer machine are
|
||
`docs/architecture/perf-report-windows-dev.json` and
|
||
`docs/architecture/soak-report-windows-dev.json`; the stage-by-stage acceptance, the
|
||
failure samples and the compatibility notes are in
|
||
`docs/architecture/studio-3d-stages.md`.
|