Add SnapForm panels, preferences, properties, and runtime management

- Implemented RuntimeModelsPanel and DebugPanel for UI integration in Blender.
- Created SnapFormPreferences to manage user settings for storage and runtime configuration.
- Defined SnapFormSettings to hold various properties related to input, model selection, and export options.
- Developed runtime management functions for installation, model downloading, and reconstruction commands.
- Added status bar functionality to display job progress and status in the Blender UI.
- Implemented worker script for handling model downloads and depth reconstruction tasks.
- Introduced unit tests for download progress reporting and image depth extraction functionalities.
This commit is contained in:
2026-08-03 10:13:33 +08:00
parent 9586b35440
commit b02372c457
26 changed files with 1849 additions and 181 deletions

104
README.md
View File

@@ -1,15 +1,15 @@
# OmooLab DA3
# SnapForm
`OmooLab DA3` 是基于
`SnapForm` 是一套从图片快速构建空间结构的 Blender Extension。目前以
[Depth Anything 3](https://github.com/ByteDance-Seed/Depth-Anything-3)
的 Blender Extension。Extension 在独立 Runtime 中运行 DA3,将官方导出结果保存在
独立 job 目录,并在任务完成后使用系统文件管理器打开该目录。
作为首个 AI 能力,在独立 Runtime 中运行 DA3,可将官方导出结果保存在独立 job 目录,
也可把 Image Empty 转换成带几何与材质置换的立体面片。
## 当前功能
- 使用 Blender Extension manifest,可通过 `Install from Disk` 安装
- 在独立 Python Runtime 中运行 Torch 与 DA3,避免污染 Blender Python 进程
- Runtime、模型和任务结果默认保存在 `~/.omoo_da3`,可由多个 Blender 版本共享
- Runtime、模型和任务结果默认保存在 `~/.snapform`,可由多个 Blender 版本共享
- 支持 DA3 Small、Base、Large 1.1、Giant 1.1 和 Nested Giant Large 1.1
- 支持单张 JPG、JPEG、PNG、WEBP 图片或常见视频文件输入
- 视频均匀抽帧,可设置参与重建的最大帧数
@@ -22,12 +22,13 @@
- Debug 在模型选项同一行用勾选或警告图标表示下载状态,不显示状态文字、License 和
已完成任务的文件计数
- 分别调用 DA3 的 `glb`、`gs_ply`、`depth_vis` 和 `mini_npz` exporter
- 导出完成后只打开对应 job 文件夹,不向当前 Blender 文件添加任何数据
- Image Empty 右键菜单可直接运行 DA3,根据 `mini_npz` 深度生成面片
- 使用浮点深度贴图、Simple Subdivision、Displace Modifier 和原图 Bump
构建立体面片
- 转换对话框可选择推理模式、处理分辨率和面片网格细分
- Debug 导出完成后只打开对应 job 文件夹,不向当前 Blender 文件添加任何数据
- 完整保留每次任务生成的所有官方文件
- 安装、下载和推理均在后台子进程运行,状态栏显示阶段、百分比进度条与取消按钮
Blender 端不读取或转换导出文件,也不会重新反投影深度、构造网格、转换坐标、创建材质或
Geometry Nodes。
- 安装、模型下载和推理均在后台子进程运行,状态栏实时显示阶段、百分比进度条与取消按钮
## 使用
@@ -35,16 +36,84 @@ Geometry Nodes。
2. 在 Blender 的 `Preferences > Extensions` 中选择 `Install from Disk`。
3. 在 Extension Preferences 中确认 `uv` 路径和 Torch Backend。
4. 点击 `Install Runtime`。首次安装会下载 Python、PyTorch 和 DA3 依赖。
5. 在 3D View 按 `N`,打开 `Omoo DA3` 页签。
5. 在 3D View 按 `N`,打开 `SnapForm` 页签。
6. 在 `Setup` 中找到需要的模型并点击该行的 `Download`。
7. 展开默认收起的 `Debug`,选择 `Export Format` 和本次执行使用的模型。
8. 选择一张图片或一个视频文件。视频可设置均匀抽取的帧数,然后点击 `Export`。
## Image Empty 转深度面片
1. 在 3D View 选中 `Object Type = Empty`、`Display As = Image` 的对象。
2. 右键选择 `Convert to Depth Plane`,在对话框中选择 Model、Use Ray Pose、Process Resolution、Subdivision,
以及是否删除原 Image Empty。默认分辨率为 `1024`、Subdivision 为 `5`,并默认删除原对象。
Model 可选择 `DA3 Small`、`DA3 Base`、`DA3 Large 1.1`、`DA3 Giant 1.1` 或
`DA3 Nested Giant Large 1.1`,默认 `DA3 Base`;Use Ray Pose
默认开启。转换导出 `mini_npz`,使用前需要在 `Setup` 下载所选模型,并固定使用
`process_res_method="lower_bound_resize"`;设备和参考视图策略继续使用场景设置。
3. 推理完成后会自动创建面片。面片几何先由 `mini_npz` 的相机内参与深度确定,再通过对象
Transform 匹配原 Image Empty 的可见尺寸、位置、旋转和 Offset。XY 拟合得到的统一倍率
同时应用于 Z 轴,使面片厚度与宽高按同一比例变化。开启 `Delete Original` 时,成功生成后
删除源 Empty。生成面片 Object 使用源 Empty 的原名;关闭 `Delete Original` 时不处理
同名冲突,由 Blender 自动为生成面片追加编号。
4. 短边分段数为 `2^Subdivision`,长边分段数根据图像宽高比取最接近的整数。例如高:宽为
`2:3`、Subdivision 为 `1` 时,直接生成 `2×3` 个面;Subdivision 为 `3` 时生成
`8×12` 个面。随后的 Simple Subdivision 修改器使用原生名称,Viewport Levels 固定为
`1`,Render Levels 固定为 `2`,不再随 Process Resolution 或 Subdivision 动态变化。
所有任务使用统一的状态栏进度显示。变化中的阶段说明显示在右侧的紧凑进度条内部,取消按钮
位于进度条右侧。Image Depth 的阶段包括 Runtime 启动、输入准备、模型加载、深度估算、缓存
写出和面片构建。状态更新仅标记相关区域重绘,不强制执行窗口 Draw/Swap。
导入过程精确保留 NPZ 内深度值之间的差值。例如深度 `2.0` 和 `5.5` 在
`Displacement Strength = -1` 时,沿局部 Z 轴相差 `3.5 Blender Unit`。它不会把数值压缩到
`0..1`,也不再提供视觉归一化模式。
面片尺寸以有效深度的中位数 `Zref` 作为参考截面。先用 `mini_npz` 中的相机内参计算原始
投影面积,再恢复源图纵横比:
```text
RawWidth = depth_width × Zref × abs(Displacement Strength) / fx
RawHeight = depth_height × Zref × abs(Displacement Strength) / fy
Area = RawWidth × RawHeight
Aspect = source_image_width / source_image_height
Width = sqrt(Area × Aspect)
Height = sqrt(Area / Aspect)
```
这样即使 DA3 估计出的 `fx/fy` 不一致,也不会把正方形原图拉成长方形。主点 `cx/cy` 仍用于
确定原始相机面片,随后对象 XY Transform 将它匹配到源 Image Empty。生成对象会记录
`snapform_reference_depth`、`snapform_camera_plane_width` 和
`snapform_camera_plane_height`,便于检查实际采用的
参考深度和尺寸。
Displace Modifier 的深度贴图使用 `Extension = Extend`。材质不再使用生成的深度图执行
Displacement,其 `Strength` 固定为 `-1`、`Midlevel` 固定为 `1`;原始彩色贴图同时连接
Principled BSDF 的 `Base Color`,并通过
`Bump.Height → Bump.Normal → Principled.Normal` 提供表面细节。Bump 的基础 Distance 为
`0.001`,会乘以面片 Transform 的统一缩放倍率。原图 Color 还会经过 `Float Curve` 连接到
Principled BSDF 的 `Roughness`,曲线两端输出分别为 `0.5` 和 `0.1`;材质 IOR 默认为 `1.2`。
这里的“原始距离”是 DA3 模型输出的尺度。普通 Small、Base、Large 和 Giant 模型的深度不应
被解释为现实世界的米;需要现实尺度时应选择带 metric depth 的
`DA3 Nested Giant Large 1.1`。此外,当前结果仍是固定 XY 平面上的深度位移面,不是使用
相机内参逐像素反投影得到的完整 camera-space 网格;中位深度截面为现有 Displace Modifier
工作流提供正确的整体高宽尺度。
生成完成后会直接创建面片,不提供缓存重建入口或单独的导入参数。
重新选择 `Convert to Depth Plane` 会再次运行 DA3。
面片、深度 Image、Texture 与 Material 会在同一个 Blender Undo 步骤中创建;转换完成后执行
`Ctrl+Z` 会完整撤销本次转换,不会越过转换去回退更早的 Image Empty 操作。
当前转换入口要求 Image Empty 引用仍然存在的本地图像文件。DA3 的原始
`results.npz` 保留在对应 job 的 `exports/mini_npz/` 中,生成的浮点深度 Image 会 Pack 到
当前 `.blend`。源 Empty 名为 `img` 时,深度 Image 与 Displace Texture 都命名为
`img.depth`。Pack 使用 OpenEXR,因而不会把大于 `1.0` 的原始深度截断。
选择 PLY 后,模型菜单只会提供 `DA3 Giant 1.1` 和
`DA3 Nested Giant Large 1.1`。Small、Base 和 Large 没有 Gaussian head,无法由
DA3 生成 `gs_ply`。
每次任务会在 `~/.omoo_da3/jobs/<任务目录>/` 中保留 DA3 官方产物:
每次任务会在 `~/.snapform/jobs/<任务目录>/` 中保留 DA3 官方产物:
```text
<GLB 任务目录>/
@@ -75,8 +144,8 @@ CC BY-NC 4.0,仅限非商业用途。
界面使用 DA3 API 的参数名、选项和默认值。GLB 专属设置仅在选择 `GLB` 时显示,
`gs_views_interval` 仅在选择 `PLY (3DGS)` 时显示:
- `process_res=504`
- `process_res_method="upper_bound_resize"`
- `process_res=1024`
- `process_res_method="lower_bound_resize"`
- `use_ray_pose=False`
- `ref_view_strategy="saddle_balanced"`
- `conf_thresh_percentile=40.0`
@@ -107,10 +176,10 @@ Extension 本身不包含 Torch。`Install Runtime` 使用 `uv` 创建独立 Pyt
默认 CUDA Backend 为 CUDA 12.8,也可以选择 CPU。CPU 可以用于验证,但实际推理
通常很慢。
Runtime、模型和任务结果默认保存在用户主目录的 `~/.omoo_da3`:
Runtime、模型和任务结果默认保存在用户主目录的 `~/.snapform`:
```text
~/.omoo_da3/
~/.snapform/
├── runtime/
├── models/
└── jobs/
@@ -134,10 +203,11 @@ uv run python pack.py
.
├── pack.py
├── src/
│ └── omoo_da3/
│ └── snapform/
│ ├── blender_manifest.toml
│ ├── bootstrap_runtime.py
│ ├── models.py
│ ├── image_depth.py
│ ├── operators.py
│ ├── panel.py
│ ├── preferences.py