23 KiB
Mesh-Pipeline 视角变换 · 跨会话实施计划
状态:SPEC / 尚未开工 最后更新:2026-04-20 15:30 负责人:Agent + 用户 @shine 适用对象:任意新会话的 Agent,本文档自包含,无需额外上下文即可开工
0 · 上下文(Why)
0.1 起因
当前项目 art-agent 已经集成了 Zero123++(jd7h/zero123plusplus)做单图→多视角变换,但存在固有缺陷:
- 只输出 6 个固定视角,
azimuth/elevation写死在config.py,用户无法指定任意相机位姿 - 大角度一致性差,Zero123++ 主要训练于小物体,对建筑类规整几何 + 大角度偏转常出现立面错位
- 无几何中间产物,纯图对图黑盒映射,无法二次利用
0.2 目标
新增一条"Mesh Pipeline"视角变换路径,与现有 zero123plus 并列保留,让用户可以:
- 输入 1 张 2D 图(典型场景:带描边卡通风的建筑,如教堂/房屋/塔楼)
- 输出 N 张保留原画风、几何一致的新视角 2D 图
- 可指定任意
azimuth/elevation(至少阶段性支持 Trellis 360° 中的任意角度)
非目标:输出 3D mesh 给用户下载(mesh 只是中间产物);替代 Zero123++(它作为"轻量路径"继续保留)。
0.3 相关历史上下文
| 记录 | 说明 |
|---|---|
CL-20260416-1000 |
Zero123++ 首次集成 |
CL-20260420-1212 |
Zero123++ 切图布局修复(cols=2/rows=3) |
CL-20260420-1501 |
后端 watchfiles 依赖修复,uvicorn --reload 生效 |
PF-20260420-1212 |
Grid 切图布局坑("3×2" 措辞歧义) |
PF-20260420-1501 |
Windows uvicorn --reload 无 watchfiles 退化坑 |
1 · 核心决策
1.1 三段式流水线
[输入: 1 张 2D 图]
↓
【阶段 1】单图 3D 重建 → 生成 textured .glb + 预渲染 360° 视频
↓
【阶段 2】从视频抽帧 / 自定义相机渲染 → 多视角"几何参考图"
↓
【阶段 3】SDXL + ControlNet + IP-Adapter 二次重绘 → 还原原画风
↓
[输出: N 张保留风格、几何一致的 2D 新视角图]
1.2 模型选型
| 阶段 | 主选 | 备选 / 高级选项 | 理由 |
|---|---|---|---|
| 阶段 1 | Trellis (firtoz/trellis) |
Hunyuan3D-2 (tencent/hunyuan3d-2) |
Trellis $0.041/30s 且自带 color_video,Hunyuan 贵 3×慢 4×但 mesh 更扎实 |
| 阶段 2 | ffmpeg 从 Trellis color_video 抽帧 |
pyrender 加载 .glb 任意角度渲染 | Trellis 已送 360° 环绕视频,首版完全省事 |
| 阶段 3 | chigozienri/ip_adapter-sdxl-controlnet-depth |
自建 SDXL + 多 ControlNet 组合 | 一个 Replicate 模型打包了 SDXL+ControlNet-Depth+IP-Adapter |
1.3 为什么不用 Hunyuan3D-2 作默认
- 贵 3 倍($0.12 vs $0.041)
- 慢 4 倍(127s vs 30s)
- 不返回预渲染视频 → 必须额外实现阶段 2(pyrender / blender 渲染器)
- 唯一优势:mesh 几何质量更高
→ 留作"高质量模式"供用户显式选择,一期不默认启用。
1.4 为什么不用 ControlNet-Depth 必须先估深度
chigozienri/ip_adapter-sdxl-controlnet-depth 的 controlnet_input 要求已经是 depth map。两条路:
- 路 A:从 Trellis
normal_video抽帧,把 normal 当"结构约束"直接喂(近似方案,不完美但可用) - 路 B:从 color_video 抽帧后,额外调用
chenxwh/depth-anything-v2生成 depth map
一期走路 A 简化;若效果不足再升级路 B(多一次 API 调用 + $0.003/张)。
2 · 技术数据清单(Schema)
2.1 Trellis — firtoz/trellis
- 版本 ID:
e8f6c45206993f297372f5436b90350817bd9b4a0d52d2a76df50c1c8afa2b3c - 成本:$0.041/次(~24 次/$1)
- 耗时:~30 秒
- 硬件:Nvidia A100 80GB
- 输入关键字段:
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
images |
array[uri] |
必填 | 输入图(支持多图,一期只传 1 张) |
seed |
int | 0 | 种子 |
randomize_seed |
bool | true | 一期设为 false 便于复现 |
texture_size |
int (512-2048) | 1024 | GLB 纹理分辨率 |
mesh_simplify |
float (0.9-0.98) | 0.95 | 网格简化,建议保持默认 |
generate_color |
bool | true | 必开,用于得到 color_video |
generate_normal |
bool | true | 一期开启,便于阶段 3 做结构约束 |
generate_model |
bool | true | 必开,否则不输出 .glb |
save_gaussian_ply |
bool | false | 不需要 |
ss_sampling_steps |
int (1-50) | 12 | 默认即可 |
slat_sampling_steps |
int (1-50) | 12 | 默认即可 |
ss_guidance_strength |
float (0-10) | 7.5 | 默认即可 |
slat_guidance_strength |
float (0-10) | 3 | 默认即可 |
- 输出字段(⚠️ 实测修订 2026-04-20 16:15,版本
e8f6c452...):
| 字段 | 类型 | 实测行为 |
|---|---|---|
model_file |
uri | ✅ .glb 文件(generate_model=true 时) |
color_video |
uri | ❌ 恒为 null — 该部署版不单独输出 |
normal_video |
uri | ❌ 恒为 null — 该部署版不单独输出 |
combined_video |
uri | ✅ 唯一可用的视频 — color+normal 左右并排 mp4 |
gaussian_ply |
uri | ✅ 高斯点云(本项目不用) |
no_background_images |
array[uri] | ✅ 去背景的预处理图 |
实测 schema 踩坑(已记为 PF-20260420-1600):
- 输入字段必须用
images(数组)—— 传image(单数字符串)会 422input: images is required,即使 Replicate README example 里写的是image。 - 尽管
generate_color=True和generate_normal=True都开,color_video和normal_video字段也恒为 null,只有combined_video可用。 - 因此 Phase 2 抽帧的数据源是
combined_video,抽帧后需要切左半 = color 帧、切右半 = normal 帧。
2.2 Hunyuan3D-2 — tencent/hunyuan3d-2(备选)
- 版本 ID:
b1b9449a1277e10402781c5d41eb30c0a0683504fb23fab591ca9dfc2aabe1cb - 成本:$0.12/次
- 耗时:~127 秒
- 硬件:Nvidia L40S
- 输入:
image,steps(20-50, default 50),guidance_scale(1-20, default 5.5),seed,octree_resolution(default 256),remove_background(default true) - 输出:
mesh(uri, .glb) —— 无视频无多视角预览,必须配套阶段 2 自定义渲染
2.3 ControlNet + IP-Adapter — chigozienri/ip_adapter-sdxl-controlnet-depth
- 版本 ID:
0436c8702ef52616be5c30948551b3af6a86c821cca9b01f11ac297624fff14c - 成本:$0.070/次
- 耗时:~72 秒
- 硬件:Nvidia L40S
- 输入关键字段:
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
image |
uri | 必填 | IP-Adapter 参考图(此处传用户原图保持风格) |
controlnet_input |
uri | 必填 | Depth / Normal / Lineart 参考图(此处传阶段 2 抽出来的 normal 帧) |
scale |
float (0-1) | 0.6 | IP-Adapter 权重,建议调到 0.7-0.8 强化风格 |
controlnet_conditioning_scale |
float (0-1) | 0.6 | 结构约束权重,建议 0.7-0.9 |
prompt |
str | "" | 留空或用 "same building, same art style" |
negative_prompt |
str | "" | "blurry, distorted, different style" |
num_outputs |
int (1-4) | 1 | 一期 1 |
num_inference_steps |
int (1-500) | 30 | 默认即可 |
seed |
int | 随机 | 调参阶段固定 |
2.4 依赖清单
一期必装(首版走 Trellis + ffmpeg 抽帧,最小化依赖):
# backend requirements.txt
ffmpeg-python==0.2.0 # 或者直接在后端宿主机装 ffmpeg 可执行文件
二期可选(若要上 Hunyuan3D-2 + 自定义相机):
trimesh==4.5.0
pyrender==0.1.45
PyOpenGL==3.1.7
# Windows 额外需要 OSMesa 或改用 Blender headless(二选一)
系统依赖:
ffmpeg可执行文件(Windows:choco install ffmpeg或手动放 PATH)- 若二期启用:Windows 上 OSMesa 编译困难,推荐用 Blender 4.x headless 替代
3 · 数据流与接口设计
3.1 新增后端服务模块
art-agent/backend/app/services/
├── view_transform.py # [改造] 管道调度器
├── mesh_generator.py # [新增] 阶段 1:调用 Trellis / Hunyuan3D-2
├── video_frame_extractor.py # [新增] 阶段 2(轻量):ffmpeg 抽帧
├── mesh_renderer.py # [新增, 二期] 阶段 2(自由相机):pyrender 加载 .glb 渲染任意角度
└── style_restorer.py # [新增] 阶段 3:ControlNet + IP-Adapter 重绘
3.2 管道调度伪代码
# services/view_transform.py
async def transform_view_mesh_pipeline(
image_path: str,
model_id: str = "trellis", # or "hunyuan3d"
azimuths: list[int] = [0, 60, 120, 180, 240, 300],
elevations: list[int] = [0, 0, 0, 0, 0, 0],
preserve_style: bool = True, # 是否走阶段 3
) -> dict:
# === 阶段 1 ===
mesh_result = await mesh_generator.generate(image_path, model_id)
# 返回 {glb_url, color_video_url?, normal_video_url?}
# === 阶段 2 ===
if model_id == "trellis":
# 从视频抽帧(Trellis 的 360° 视频约 5s,对应 az 0→360°)
frames = await video_frame_extractor.extract_by_azimuth(
color_video_url=mesh_result["color_video_url"],
normal_video_url=mesh_result["normal_video_url"],
azimuths=azimuths,
total_rotation_deg=360,
)
else: # hunyuan3d
# 二期:自定义相机渲染
frames = await mesh_renderer.render_views(
glb_path=mesh_result["glb_path"],
azimuths=azimuths,
elevations=elevations,
)
# frames = [{az, el, color_png, normal_png}, ...]
# === 阶段 3 ===
if preserve_style:
final_images = await asyncio.gather(*[
style_restorer.restore(
original_image=image_path,
structure_image=f["normal_png"],
azimuth=f["az"],
elevation=f["el"],
)
for f in frames
])
else:
final_images = [f["color_png"] for f in frames]
return {
"success": True,
"images": [
{"url": img, "azimuth": az, "elevation": el}
for img, (az, el) in zip(final_images, zip(azimuths, elevations))
],
"mesh_url": mesh_result.get("glb_url"),
"model_name": f"Mesh Pipeline ({model_id})",
}
3.3 config.py 扩展
VIEW_TRANSFORM_MODELS = {
"zero123plus": {...}, # 保留不动
"trellis": {
"id": "trellis",
"name": "Trellis (Mesh Pipeline)",
"provider": "replicate",
"model_id": "firtoz/trellis:e8f6c45206993f297372f5436b90350817bd9b4a0d52d2a76df50c1c8afa2b3c",
"description": "3D 重建 + 任意视角 + 风格还原,建筑友好(~30s + 风格化 ~72s/张)",
"pipeline": "mesh", # 新增字段区分管道类型
"default_params": {
"texture_size": 1024,
"mesh_simplify": 0.95,
"generate_color": True,
"generate_normal": True,
"generate_model": True,
},
},
"hunyuan3d": {
"id": "hunyuan3d",
"name": "Hunyuan3D-2 (高质量)",
"provider": "replicate",
"model_id": "tencent/hunyuan3d-2:b1b9449a1277e10402781c5d41eb30c0a0683504fb23fab591ca9dfc2aabe1cb",
"description": "几何质量最佳(~127s),需自定义渲染(二期启用)",
"pipeline": "mesh",
"enabled": False, # 一期先禁用
},
}
IMAGE_MODELS["ip-adapter-controlnet-depth"] = {
"id": "ip-adapter-controlnet-depth",
"name": "IP-Adapter + ControlNet Depth (内部)",
"provider": "replicate",
"model_id": "chigozienri/ip_adapter-sdxl-controlnet-depth:0436c8702ef52616be5c30948551b3af6a86c821cca9b01f11ac297624fff14c",
"internal": True, # 不在前端展示,仅用于阶段 3
...
}
3.4 工具层 tools.py
transform_view 工具参数扩展(向后兼容):
{
"name": "transform_view",
"parameters": {
"image_path": {...},
"model_id": {
"enum": ["zero123plus", "trellis", "hunyuan3d"],
"default": "zero123plus",
},
# 以下为 mesh pipeline 专属参数
"azimuths": {"type": "array", "default": [0, 60, 120, 180, 240, 300]},
"elevations": {"type": "array", "default": [0, 0, 0, 0, 0, 0]},
"preserve_style": {"type": "boolean", "default": True},
},
}
3.5 前端改造
- 模型下拉增加 "Trellis (Mesh Pipeline)" 和 "Hunyuan3D-2 (高质量)" 选项
- 选中 mesh pipeline 时,额外显示:
- "保留原画风格" 开关(默认开)
- 角度输入:简化为"快速预设(6/8/12 视角)" + "自定义 azimuth 数组"(高级)
- 结果区域:除了 N 张图,还展示
color_video可预览
4 · 施工任务清单(跨会话可独立执行)
Phase 1:Trellis 接入(预计 1.5h)
验收标准:用 curl / Replicate SDK 能跑通一次 Trellis,拿到 .glb + color_video URL,下载到本地。
- P1-1
services/mesh_generator.py新建,封装generate_with_trellis(image_path)函数(调用 Replicate + 下载结果到GENERATED_DIR) - P1-2
config.py新增VIEW_TRANSFORM_MODELS["trellis"]条目 - P1-3
services/view_transform.py根据pipeline == "mesh"分流到mesh_generator - P1-4
tools.py的transform_view增加model_id参数默认值兼容 - P1-5 本地手动测试:
scripts/test_trellis.py可独立运行验证 Trellis → .glb + color_video + normal_video 本地落地(等用户执行)
Phase 2:ffmpeg 抽帧(预计 1h)
验收标准:从 color_video.mp4 抽出指定 azimuth 对应的帧,保存为 PNG,帧数正确、角度映射正确。
- P2-1 宿主机 ffmpeg 未装,改用
imageio-ffmpeg==0.5.1(静态二进制随包,免系统依赖),已写入requirements.txt - P2-2
services/video_frame_extractor.py新建,实现extract_by_azimuth(combined_video_path, azimuths, elevations=None, total_rotation_deg=360)- 策略改为"一次抽全帧到 temp dir + 按帧索引挑" —— 比
-ss逐帧抽更稳(不受 keyframe 对齐影响),且 5s 视频成本可忽略 - 抽出后用 PIL 按中线切:左半 → color_png、右半 → normal_png(实测 1024×512 → 512×512 方形)
ffmpeg + PIL是阻塞的,用run_in_executor丢到线程池避免堵住 async 事件循环- 临时目录抽完即清理,只保留切好的最终帧
- 策略改为"一次抽全帧到 temp dir + 按帧索引挑" —— 比
- P2-3
view_transform._transform_view_mesh串接 Stage 1 → Stage 2:默认azimuths=[0,60,120,180,240,300];Stage 2 失败不会把整体置为失败(Stage 1 的 .glb / video 仍有交付价值,error字段单独带回 Stage 2 错误) - P2-4 本地测试脚本
scripts/test_frame_extract.py(等用户执行验收)- Agent 已自测:120 帧视频 → az=0/60/120/180/240/300 映射到 frame_idx=0/20/40/60/80/100,完全均匀 ✓
- 12 个 color/normal PNG 全部落盘,尺寸 512×512 方形 ✓
Phase 3:风格还原重绘(预计 1.5h)
验收标准:6 张视角图通过 IP-Adapter+ControlNet 重绘后,风格与原图一致、几何不变形。
- P3-1
config.py注册IMAGE_MODELS["ip-adapter-controlnet-depth"],标internal=True,同时改get_image_models_list()过滤 internal,不污染前端下拉 - P3-2
services/style_restorer.py新建,实现restore(original_image, structure_image, ...)+restore_batch()(带并发 Semaphore 防 Replicate rate limit) - P3-3
view_transform.py增加阶段 3;preserve_style=True时对 Stage 2 的每一帧做重绘;单帧失败自动回退为 Stage 2 color 帧,不阻塞整体 - P3-4 等待 Checkpoint 3:调参轮次需要用户执行
scripts/test_style_restore.py <原图>,分别尝试scale=0.6/0.7/0.8×controlnet_conditioning_scale=0.6/0.7/0.9,选出最佳组合写入默认参数
Phase 4:前端 + 端到端联调(预计 1h)
- P4-1
types.ts扩展ViewTransformModel类型 - P4-2 前端模型下拉新增两个选项
- P4-3 工作台选中 mesh 管道时显示"保留原画风"开关
- P4-4 结果面板支持展示视频(color_video)+ N 张风格化后的视角图
- P4-5 端到端联调:前端上传一张卡通建筑图 → 选 Trellis → 确认 N 张结果正确显示
Phase 5:Hunyuan3D-2 + 自由相机(可选,二期,预计 3-4h)
仅在 Phase 1-4 完成且用户明确要求自由 elevation/远近相机时启动。
- P5-1 venv 安装
trimesh + pyrender + PyOpenGL;Windows 上验证 headless 可用性 - P5-2 若 pyrender 在 Windows 不可行 → 改用 Blender 4.x headless(需
blender.exe -b --python render.py) - P5-3
services/mesh_renderer.py新建,实现render_views(glb_path, azimuths, elevations, distance=2.0, fov=45) - P5-4 启用
config.py的hunyuan3d条目(enabled=True) - P5-5 前端"高级模式"解锁 elevation 滑块
Phase 6:收尾
- P6-1
changelog-full.md/-recent.md/-headlines.md三层同步记录 - P6-2 发现的坑 →
pitfalls.md - P6-3 更新
art-agent/README.md里视角变换段落
5 · 风险与兜底
| 风险 | 概率 | 影响 | 兜底 |
|---|---|---|---|
| Trellis 对 2D 卡通描边图重建几何偏糊 | 中 | 阶段 3 结构约束失效 | 先用 SDXL+InstantStyle 把原图"半写实化"一版给 Trellis 吃,最后阶段 3 用原 2D 图做 IP-Adapter 还原风格 |
| 从 color_video 抽帧只有水平环绕(elevation=0),不能仰视/俯视 | 高 | 无法满足"仰视大教堂"等需求 | 二期启用 Phase 5 的 pyrender 自由相机,或改用 Hunyuan3D-2 + 自定义渲染 |
| IP-Adapter+ControlNet 6 次调用并发打满 Replicate rate limit | 低 | 部分帧失败 | 改成串行 + 指数退避 + 失败单帧重试 |
| 总链路太慢(>3 分钟)用户失去耐心 | 中 | 产品体验差 | 前端用 SSE 流式展示中间产物:阶段 1 完成显示视频 → 阶段 3 每张完成立即插入 |
| ffmpeg 未装 | 高(Windows) | Phase 2 不能跑 | 开工前检查 ffmpeg -version,未装先 choco install ffmpeg 或用 Python 库 imageio-ffmpeg 绑定 |
| Trellis 某次输出 video 是 4s 某次 6s,固定 total_rotation_deg=360 可能不准 | 低 | 抽帧角度偏差 | 用 ffprobe 动态读取总帧数;如有疑问就固定 24 帧均匀抽样全部保留 |
6 · 成本与性能预估
一次完整请求(6 视角,保留风格):
| 阶段 | 耗时 | 成本 |
|---|---|---|
| Trellis 重建 | ~30s | $0.041 |
| ffmpeg 抽 6 帧 | ~2s(本地) | 0 |
| ControlNet+IP-Adapter × 6(并发) | ~72s | $0.42 |
| 合计 | ~105s | ~$0.46 |
参考:当前 Zero123++ 一次 ~$0.02,~15s。新管道贵约 23×、慢约 7×,但产出质量对建筑是跨代提升。
7 · 跨会话恢复指引
新会话的 Agent 在开工前务必:
- 读本文件 §0-§3,建立完整技术背景
- 读
art-agent/backend/app/services/view_transform.py当前实现(Zero123++ 的做法作参照) - 读
art-agent/backend/app/config.py的VIEW_TRANSFORM_MODELS/IMAGE_MODELS当前结构 - 读
art-agent/backend/app/agent/tools.py看transform_view工具定义 - 按 §4 的 Phase 顺序推进,Phase 之间互相独立,完成一个交付一个
- 每个 Phase 完成后在本文件对应 checkbox 打勾(改
[ ]为[x]),并在本节底部追加简短进度 note
不要一次 Phase 1-6 全做完再交付——每个 Phase 完成后停下来让用户测试/审阅。
进度日志
- 2026-04-20 · 会话"Zero123++ 切图诊断 + 方案调研" → 完成 §2 全部 schema 查证,写入本 SPEC。尚未开工 Phase 1。
- 2026-04-20 · 会话"按计划实施 Mesh Pipeline" → 完成 Phase 1(P1-1 ~ P1-5):新增
mesh_generator.py、config.py注册 trellis/hunyuan3d(后者 enabled=False)、view_transform.py按pipeline字段分流、tools.py扩model_id/azimuths/preserve_style参数,额外提供scripts/test_trellis.py供用户手动验收。 - 2026-04-20 16:15 · Checkpoint 1 通过 → Agent 运行
scripts/test_trellis.py实测发现:- ✅ Trellis 调用链路完全打通:Replicate token / 代理 / httpx 下载 / GENERATED_DIR 落盘均正常
- ✅
.glb(1.89MB) 下载正常 - ⚠️ 意外发现:该部署版
color_video/normal_video字段恒为 null,只有combined_video可用(color+normal 左右并排 mp4 ~450KB) - 修订 §2.1 输出字段表为实测版本,P2-2 任务改为"从 combined_video 抽帧 + 切左右半",已记 PF-20260420-1600 踩坑
- Phase 1 verdict:functionally green,可以开 Phase 2
- 2026-04-20 · 会话"继续执行 Phase 2" → 完成 Phase 2 全部 item(P2-1 ~ P2-4):
- 放弃系统 ffmpeg,改用
imageio-ffmpeg自带二进制(22.6MB wheel,Win amd64 下已测 v4.2.2 ok) - 新增
services/video_frame_extractor.py— 一次全帧抽取 + 按索引挑 + PIL 切左右半的极简实现 view_transform.py的 mesh 管道调度器现已走到 Stage 2,返回的images[]含{url, azimuth, elevation, normal_url, frame_idx}- 新增
scripts/test_frame_extract.py供用户复用已有 combined_video 做 Checkpoint 2 验收(无需再花钱跑 Trellis) - Agent 自测:120 帧 → 6 视角 frame_idx 均匀分布 (0/20/40/60/80/100),所有切图 512×512 方形,逻辑正确
- 等待 Checkpoint 2 用户验收:跑
python scripts/test_frame_extract.py并目视检查generated/view_*_color.png6 张图的角度顺序
- 放弃系统 ffmpeg,改用
- 2026-04-20 · 会话"继续执行 Phase 3(风格还原)" → 完成 P3-1 ~ P3-3:
config.py注册内部模型ip-adapter-controlnet-depth(internal=True),并让get_image_models_list()自动过滤,不会污染前端下拉;新增 helperget_style_restore_model_id()- 新增
services/style_restorer.py:restore()单帧调用 +restore_batch()带 Semaphore 并发 3 的批量接口;统一处理 FileOutput/list/str 的 Replicate 返回 view_transform._transform_view_mesh接入 Stage 3:当preserve_style=True对每一帧做 IP-Adapter+ControlNet 重绘;单帧失败会自动回退为 Stage 2 color 帧,不阻塞整体;images[i]新增restyled布尔和color_url(保留原 color 便于对比)- 最终返回的
_stage字段从stage2升级为stage3 (N/M restyled),便于前端 / 日志快速判断链路完整度 - 新增
scripts/test_style_restore.py供 Checkpoint 3 用户验收:支持--single冒烟、--prefix指定 normal 帧组、--scale/--cn-scale覆盖参数,复用 Phase 2 已有帧无需再跑 Trellis - 等待 Checkpoint 3 用户验收:跑
python scripts/test_style_restore.py <原图> --single做冒烟,通过后再全量 6 帧并调参(P3-4)
8 · 开放问题(留给未来决策)
- 前端角度输入 UX:要不要做一个"3D 预览转盘"让用户拖动选角度?(Phase 4+ 再说)
- 是否把 mesh
.glb作为资产保存到用户的 gallery?(涉及存储与用户系统对接) - Hunyuan3D-2 路线的 Windows 渲染器:pyrender vs Blender 的选型需要一次实测才能决定
- 是否对同一原图的重复请求加缓存?(Trellis 结果相对稳定,可按 image_hash 缓存 .glb)