tripo-cli 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/commands/completion.js +1 -1
- package/dist/commands/process-groups.js +11 -2
- package/dist/core/download.js +2 -1
- package/dist/knowledge/chains.js +2 -0
- package/dist/knowledge/models.js +1 -1
- package/dist/knowledge/params.js +15 -4
- package/package.json +1 -1
- package/skill/SKILL.md +1 -1
- package/skill/commands/make.md +1 -1
- package/skill/commands/process.md +6 -2
- package/skill/common-errors.md +3 -1
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Works with both Tripo regions from the same install — international (`openapi.
|
|
|
35
35
|
| `tripo login / logout / whoami / use` | device flow: browser approves, key arrives automatically (paste fallback); stored 0600 in `~/.tripo/config.json`; `use` switches accounts |
|
|
36
36
|
| `tripo topup / balance / usage` | open the billing page + detect the credits arriving; check spend |
|
|
37
37
|
| `tripo generate <endpoint>` | deterministic access to all 8 generation endpoints |
|
|
38
|
-
| `tripo model / anim / mesh <step>` | refine, texture, stylize, convert, import, rig-check, rig, retarget, segment, complete, decimate, smartsegment |
|
|
38
|
+
| `tripo model / anim / mesh <step>` | refine, texture, stylize, convert, import, rig-check, rig, retarget, segment, complete, decimate, uv, smartsegment |
|
|
39
39
|
| `tripo task get/list/watch` | query and stream task progress (NDJSON in `--json` mode) |
|
|
40
40
|
| `tripo files upload` | upload a file, print the `file_token` |
|
|
41
41
|
| `tripo batch run <manifest.yaml>` | bulk pipelines with concurrency, retries, and resume |
|
|
@@ -11,7 +11,7 @@ const SUBS = {
|
|
|
11
11
|
generate: ['text-to-model', 'image-to-model', 'multiview-to-model', 'text-to-image', 'image-to-image', 'image-to-multiview', 'edit-multiview', 'image-to-splat'],
|
|
12
12
|
model: ['refine', 'texture', 'stylize', 'convert', 'import'],
|
|
13
13
|
anim: ['check', 'rig', 'retarget'],
|
|
14
|
-
mesh: ['segment', 'complete', 'decimate', ...(isMeshEditEnabled() ? ['edit'] : []), 'smartsegment'],
|
|
14
|
+
mesh: ['segment', 'complete', 'decimate', 'uv', ...(isMeshEditEnabled() ? ['edit'] : []), 'smartsegment'],
|
|
15
15
|
task: ['get', 'list', 'watch'],
|
|
16
16
|
files: ['upload'],
|
|
17
17
|
batch: ['run'],
|
|
@@ -77,7 +77,9 @@ function collectStepArgs(step, flags) {
|
|
|
77
77
|
case 'retarget':
|
|
78
78
|
return pick(['animation', 'out_format', 'animate_in_place']);
|
|
79
79
|
case 'decimate':
|
|
80
|
-
return pick(['face_limit', 'quad', 'bake']);
|
|
80
|
+
return pick(['model', 'face_limit', 'quad', 'smart_uv', 'bake']);
|
|
81
|
+
case 'uv':
|
|
82
|
+
return pick(['bake', 'export_orientation']);
|
|
81
83
|
case 'segment':
|
|
82
84
|
return pick(['model']);
|
|
83
85
|
case 'complete':
|
|
@@ -147,7 +149,7 @@ export function registerProcessCommands(program) {
|
|
|
147
149
|
await makeStepAction('retarget')(input, flags);
|
|
148
150
|
});
|
|
149
151
|
// ---- tripo mesh ----
|
|
150
|
-
const mesh = program.command('mesh').description('mesh ops: segment / complete / decimate / smartsegment');
|
|
152
|
+
const mesh = program.command('mesh').description('mesh ops: segment / complete / decimate / uv / smartsegment');
|
|
151
153
|
withTaskOptions(mesh.command('segment [input]').description('segment a model into parts').option('--model <v>', 'v1.0-20250506|v2.0-20260430')).action(makeStepAction('segment'));
|
|
152
154
|
withTaskOptions(mesh
|
|
153
155
|
.command('complete [input]')
|
|
@@ -156,9 +158,16 @@ export function registerProcessCommands(program) {
|
|
|
156
158
|
withTaskOptions(mesh
|
|
157
159
|
.command('decimate [input]')
|
|
158
160
|
.description('high-poly → low-poly (bakes textures by default)')
|
|
161
|
+
.option('--model <v>', 'v3.0|v2.0|v1.0 (default v2.0)')
|
|
159
162
|
.option('--face-limit <n>', 'target faces 500–20000 tri / 500–10000 quad', (v) => Number(v))
|
|
160
163
|
.option('--quad', 'quad output')
|
|
164
|
+
.option('--smart-uv', 'unwrap UVs in the same task (v3.0 only; selects v3.0 when --model is omitted)')
|
|
161
165
|
.option('--no-bake', 'skip baking textures onto the low-poly')).action(makeStepAction('decimate'));
|
|
166
|
+
withTaskOptions(mesh
|
|
167
|
+
.command('uv [input]')
|
|
168
|
+
.description('smart UV unwrap; remaps textures/rig/animation (input ≤80k equivalent triangles)')
|
|
169
|
+
.option('--no-bake', 'skip baking textures onto the new UV layout (geometry + UVs only)')
|
|
170
|
+
.option('--export-orientation <o>', '+x|-x|+y|-y')).action(makeStepAction('uv'));
|
|
162
171
|
// Hidden until /v3/mesh/edit is live server-side (see isMeshEditEnabled).
|
|
163
172
|
if (isMeshEditEnabled()) {
|
|
164
173
|
withTaskOptions(mesh
|
package/dist/core/download.js
CHANGED
|
@@ -73,7 +73,8 @@ export async function downloadArtifacts(task, outputDir, historyEntry, options =
|
|
|
73
73
|
const ext = extname(name).toLowerCase();
|
|
74
74
|
if (!modelFile && MODEL_EXTS.has(ext))
|
|
75
75
|
modelFile = dest;
|
|
76
|
-
|
|
76
|
+
// uv_render (mesh/uv) is a flat UV atlas, not a render of the model.
|
|
77
|
+
if (!preview && !/uv_render/.test(field) && (IMAGE_EXTS.has(ext) || /rendered|preview/i.test(field)))
|
|
77
78
|
preview = dest;
|
|
78
79
|
}
|
|
79
80
|
// Normalize the preview name so agents can rely on preview.png existing.
|
package/dist/knowledge/chains.js
CHANGED
|
@@ -17,6 +17,7 @@ export const MODEL_PRODUCING_TYPES = new Set([
|
|
|
17
17
|
'mesh_segmentation',
|
|
18
18
|
'mesh_completion',
|
|
19
19
|
'mesh_edit',
|
|
20
|
+
'mesh_uv',
|
|
20
21
|
'animate_rig',
|
|
21
22
|
'animate_retarget',
|
|
22
23
|
]);
|
|
@@ -32,6 +33,7 @@ export const STEPS = [
|
|
|
32
33
|
{ name: 'segment', endpoint: '/v3/mesh/segment', produces: 'mesh_segmentation', accepts: 'any-model', acceptsFile: true, describe: { zh: '把网格分割成部件', en: 'segment the mesh into parts' } },
|
|
33
34
|
{ name: 'complete', endpoint: '/v3/mesh/complete', produces: 'mesh_completion', accepts: ['mesh_segmentation'], acceptsFile: false, describe: { zh: '补全分割后的部件', en: 'complete the segmented parts' } },
|
|
34
35
|
{ name: 'decimate', endpoint: '/v3/mesh/decimate', produces: 'highpoly_to_lowpoly', accepts: 'any-model', acceptsFile: true, aliases: ['lowpoly'], describe: { zh: '减面到目标面数', en: 'decimate to a target face count' } },
|
|
36
|
+
{ name: 'uv', endpoint: '/v3/mesh/uv', produces: 'mesh_uv', accepts: 'any-model', acceptsFile: true, describe: { zh: '智能展 UV,原贴图/骨骼/动画映射到新布局', en: 'smart UV unwrap; remaps textures/rig/animation onto the new layout' } },
|
|
35
37
|
// mesh/edit: local retry/refine inside a bbox, P2 pipeline (model fixed to P2-20260801).
|
|
36
38
|
{ name: 'edit', endpoint: '/v3/mesh/edit', produces: 'mesh_edit', accepts: 'any-model', acceptsFile: true, describe: { zh: '在 bbox 区域内局部重做(P2 管线)', en: 'redo one bbox region locally (P2 pipeline)' } },
|
|
37
39
|
// smartsegment's `input` is file_token/URL only (the server does not resolve
|
package/dist/knowledge/models.js
CHANGED
|
@@ -109,7 +109,7 @@ export const TEXTURE_MODELS = ['v3.0-20250812', 'v2.5-20250123'];
|
|
|
109
109
|
/** mesh_segmentation whitelist (ALLOWED_SEGMENT_MODELS). */
|
|
110
110
|
export const SEGMENT_MODELS = ['v1.0-20250506', 'v2.0-20260430'];
|
|
111
111
|
/** mesh/decimate whitelist (ALLOWED_DECIMATE_MODELS; blank/"default" → server default v2.0). */
|
|
112
|
-
export const DECIMATE_MODELS = ['v2.0', 'v1.0'];
|
|
112
|
+
export const DECIMATE_MODELS = ['v3.0', 'v2.0', 'v1.0'];
|
|
113
113
|
/** Server whitelists differ per endpoint (ImageGenerationValidation). */
|
|
114
114
|
export const TEXT_TO_IMAGE_TEMPLATES = [
|
|
115
115
|
'asset_extraction',
|
package/dist/knowledge/params.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Every rule here prevents a guaranteed 400 or a silently wasted credit.
|
|
6
6
|
* Rules marked [hard] mirror server enforcement; [soft] are CLI smart defaults.
|
|
7
7
|
*/
|
|
8
|
-
import { CONVERT_FORMATS, EXPORT_ORIENTATIONS, FBX_PRESETS, MODEL_P2, P1_FACE_LIMIT, P1_FORBIDDEN_PARAMS, P2_FACE_LIMIT, P2_FORBIDDEN_PARAMS, TEXTURE_FORMATS, TEXTURE_QUALITIES, isP1, isP2, normalizeModel, } from './models.js';
|
|
8
|
+
import { CONVERT_FORMATS, DECIMATE_MODELS, EXPORT_ORIENTATIONS, FBX_PRESETS, MODEL_P2, P1_FACE_LIMIT, P1_FORBIDDEN_PARAMS, P2_FACE_LIMIT, P2_FORBIDDEN_PARAMS, TEXTURE_FORMATS, TEXTURE_QUALITIES, isP1, isP2, normalizeModel, } from './models.js';
|
|
9
9
|
const PROMPT_MAX = 1024;
|
|
10
10
|
const NEGATIVE_PROMPT_MAX = 255;
|
|
11
11
|
/** Validate + auto-fix parameters for 3D generation (text/image/multiview-to-model). */
|
|
@@ -168,7 +168,8 @@ export function validateConvertParams(input) {
|
|
|
168
168
|
}
|
|
169
169
|
/**
|
|
170
170
|
* Validate parameters for mesh/decimate (ModelPostProcessValidation):
|
|
171
|
-
* v2.0 (default): face_limit 500–20000 tri / 500–10000 quad.
|
|
171
|
+
* v2.0 (default) / v3.0: face_limit 500–20000 tri / 500–10000 quad.
|
|
172
|
+
* v3.0 only: smart_uv (UV unwrap in the same task).
|
|
172
173
|
* v1.0: face_limit REQUIRED, 500–2,000,000 tri / 500–150,000 quad; no bake/part_names.
|
|
173
174
|
*/
|
|
174
175
|
export function validateDecimateParams(input) {
|
|
@@ -176,8 +177,18 @@ export function validateDecimateParams(input) {
|
|
|
176
177
|
const warnings = [];
|
|
177
178
|
const errors = [];
|
|
178
179
|
const model = typeof params.model === 'string' ? params.model.toLowerCase() : undefined;
|
|
179
|
-
if (model !== undefined &&
|
|
180
|
-
errors.push(`decimate model must be
|
|
180
|
+
if (model !== undefined && model !== 'default' && !DECIMATE_MODELS.includes(model)) {
|
|
181
|
+
errors.push(`decimate model must be ${DECIMATE_MODELS.join('/')} (got "${String(params.model)}")`);
|
|
182
|
+
}
|
|
183
|
+
// [hard] smart_uv is v3.0-only (server: 1004 on v1.0/v2.0); [soft] no model given → v3.0.
|
|
184
|
+
if (params.smart_uv === true) {
|
|
185
|
+
if (model === undefined) {
|
|
186
|
+
params.model = 'v3.0';
|
|
187
|
+
warnings.push('smart_uv requires decimate v3.0: using model=v3.0 (35 credits tri / 40 quad; v2.0 is 30)');
|
|
188
|
+
}
|
|
189
|
+
else if (model !== 'v3.0') {
|
|
190
|
+
errors.push(`smart_uv only works with decimate model v3.0 (got "${String(params.model)}")`);
|
|
191
|
+
}
|
|
181
192
|
}
|
|
182
193
|
const isV1 = model === 'v1.0';
|
|
183
194
|
const quad = params.quad === true;
|
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -50,7 +50,7 @@ tripo make @last --then convert:fbx --json --yes # continue from last t
|
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
- `--for` scenario presets: `game-mobile` `game-pc` `film` `print` `ar-web` `anim` `toy`
|
|
53
|
-
- `--then` chain steps: `refine texture stylize convert import rig-check rig retarget segment complete decimate smartsegment`
|
|
53
|
+
- `--then` chain steps: `refine texture stylize convert import rig-check rig retarget segment complete decimate uv smartsegment`
|
|
54
54
|
- step args: `convert:format=FBX,texture_size=2048` (bare value = primary arg: `convert:fbx`, `stylize:lego`, `decimate:5000`)
|
|
55
55
|
- Output JSON: `{"task_id","type","status","credits_consumed","output_dir","files",["model_file"],["preview"],["chain"],["credits_breakdown"]}` — with `--then`, `credits_consumed` is the **total** for the run and `credits_breakdown` itemizes every task (`[{task_id,type,credits_consumed}]`, generation first)
|
|
56
56
|
|
package/skill/commands/make.md
CHANGED
|
@@ -40,7 +40,7 @@ In a TTY it then asks `Run this plan?`; answering no exits 0 with `cancelled; no
|
|
|
40
40
|
## Options
|
|
41
41
|
|
|
42
42
|
- `--for <scenario>` — `game-mobile` `game-pc` `film` `print` `ar-web` `anim` `toy`. Sets model+params+chain+format from the domain knowledge base.
|
|
43
|
-
- `--then <steps>` — processing chain, comma-separated. Steps: `refine texture stylize convert import rig-check rig retarget segment complete decimate smartsegment`. Args: `step:key=value,...`; bare value maps to the step's primary arg (`convert:fbx` → format, `stylize:lego` → style, `decimate:5000` → face_limit, `retarget:preset:walk` → animation). Overrides the scenario chain.
|
|
43
|
+
- `--then <steps>` — processing chain, comma-separated. Steps: `refine texture stylize convert import rig-check rig retarget segment complete decimate uv smartsegment`. Args: `step:key=value,...`; bare value maps to the step's primary arg (`convert:fbx` → format, `stylize:lego` → style, `decimate:5000` → face_limit, `retarget:preset:walk` → animation). Overrides the scenario chain.
|
|
44
44
|
- `--model <m>` — force `tripo-v3.1` (high fidelity, default), `tripo-p1` (low-poly; face_limit 50–20000; quad/parts/geometry_quality unsupported and stripped) or `tripo-p2` (P-series preview; adds quad, face_limit 48–50000 tri / 48–25000 quad; never auto-selected). The CLI normalizes these aliases to the wire versions (`v3.1-20260211` / `P1-20260311` / `P2-20260801`) the server actually accepts. Full table with status (GA / Preview / Legacy) and official links: `tripo docs --topic commands/generate` → "Models & Versions".
|
|
45
45
|
- `-n, --candidates <n>` — up to 4 parallel candidates with different seeds (interactive pick when chaining).
|
|
46
46
|
- `--seed <n>` — fixed model_seed for reproducible geometry.
|
|
@@ -92,7 +92,8 @@ All prefixed `preset:biped:`
|
|
|
92
92
|
```bash
|
|
93
93
|
tripo mesh segment [input] [--model v1.0-20250506|v2.0-20260430]
|
|
94
94
|
tripo mesh complete [input] [--completion-mode ai_completion|quick_cap] # needs a segment task
|
|
95
|
-
tripo mesh decimate [input] --face-limit 5000 [--quad] [--no-bake]
|
|
95
|
+
tripo mesh decimate [input] --face-limit 5000 [--model v3.0|v2.0|v1.0] [--quad] [--smart-uv] [--no-bake] # 500–20000 tri / 500–10000 quad
|
|
96
|
+
tripo mesh uv [input] [--no-bake] [--export-orientation +x|-x|+y|-y] # input ≤ 80,000 equivalent triangles
|
|
96
97
|
tripo mesh smartsegment <file-or-url> [--seg-type image|model] [--granularity coarse|medium|fine] [--hint "..."]
|
|
97
98
|
```
|
|
98
99
|
|
|
@@ -100,9 +101,12 @@ tripo mesh smartsegment <file-or-url> [--seg-type image|model] [--granularity co
|
|
|
100
101
|
| --- | --- | --- |
|
|
101
102
|
| `segment` | task / file / URL | `model` `v1.0-20250506` (default, geometry-based) / `v2.0-20260430` (Beta, semantic labels + geometry). **v2 only**: `segmentation_granularity` simple/balanced/detailed (default balanced), `split_by_connectivity` (default true), `ref_image` file_token/URL — when `ref_image` is set the other two are ignored; setting `ref_image` on v1 → `1004` |
|
|
102
103
|
| `complete` | **segment task only** | `completion_mode` `ai_completion` (AI diffusion, default) / `quick_cap` (fast hole-fill, no AI); `part_names` (default: all parts); `model` `v1.0-20250506` (only version) |
|
|
103
|
-
| `decimate` | task / file | `
|
|
104
|
+
| `decimate` | task / file / URL | `model` `v2.0` (default, smart retopology, 30 credits) / `v3.0` (newest retopology, 35 credits tri / 40 quad) / `v1.0` (basic decimation, 10 credits); `face_limit` (v2.0/v3.0: optional, 500–20000 tri / 500–10000 quad, adaptive if omitted); `quad`; `bake` (default true — bake textures onto the low-poly, right for LODs); `part_names`; `smart_uv` (**v3.0 only**, default false — unwrap UVs in the same task, no extra cost, no UV atlas image; `--smart-uv` without `--model` selects v3.0, an explicit v1.0/v2.0 is rejected locally because the server answers `1004`). `--model v1.0`: up to 2,000,000 tri / 150,000 quad but `face_limit` becomes required and `bake`/`part_names` are unsupported |
|
|
105
|
+
| `uv` | task / file / URL | re-unwraps UVs and remaps the existing textures, rig and animation onto the new layout; **20 credits**. `bake` (default true; `--no-bake` returns geometry + UVs only); `export_orientation` `+x`/`-x`/`+y`/`-y`; `compress` `geometry` (meshopt, `-p compress=geometry`); `model` `default` (only value). **Input ≤ 80,000 equivalent triangles** (a quad counts as two): larger inputs are accepted, then the task fails and refunds — decimate first |
|
|
104
106
|
| `smartsegment` | **file / URL only (no task ids)** | `seg_type` `image` (photo → auto-model → segment, **85 credits**) / `model` (existing **GLB only** → segment, **55 credits**; CLI default); `granularity` coarse/medium/fine (default medium); `hint` free text describing the parts; `transform` 4×4 column-major matrix required for `model` — the CLI auto-fills identity |
|
|
105
107
|
|
|
106
108
|
- `segment` vs `smartsegment`: segment only splits an existing model; smartsegment is the end-to-end pipeline (asset → auto modelling → segmentation).
|
|
107
109
|
- smartsegment output: `prompt` (comma-separated part labels), `mask_url` (PNG semantic mask), `seg_model_url` (segmented GLB), `seg_task_id` (inner segmentation task), `model_task_id` (inner image_to_model / import task). Task types: `smartsegment_image` / `smartsegment_model`.
|
|
108
110
|
- `mesh complete` only accepts segmentation tasks; segmented / completed parts can then be exported selectively via `convert -p 'part_names=[...]'`.
|
|
111
|
+
- UVs in one task or two: `decimate --smart-uv` (v3.0) unwraps during retopology — one task, no atlas image. `uv` is its own task that also returns the UV atlas; run it on models that are already under the limit, e.g. `--then decimate:20000,uv`.
|
|
112
|
+
- uv output: the model plus `uv_render.webp` (the UV atlas). It is a flat layout, not a render of the model, so the CLI does not copy it to `preview.png`.
|
package/skill/common-errors.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
| --- | --- | --- | --- |
|
|
5
5
|
| 3 | 1002 | authentication failed (invalid/missing API key) | set `TRIPO_API_KEY` or run `tripo login`; check the key wasn't revoked |
|
|
6
6
|
| 3 | 1005 | forbidden (no permission for this resource) | check account permissions |
|
|
7
|
-
| 2 | 1003/1004 | malformed request / invalid parameter | check spelling against `tripo docs --topic commands/<cmd>`; the CLI already strips illegal P1 params. Classic 1004s: `generate_parts=true` with texture/pbr on, `ref_image` on segment v1, `quad=true` on P1, non-GLB input to smartsegment `model` / rig-check. `invalid model`: the API only accepts dated wire values (`P2-20260801`, `v3.1-20260211`…) — pass the CLI alias (`--model tripo-p2`) and let the CLI normalize, or the wire value itself; never `tripo-*` straight to the API. Table: `commands/generate` § "Models & Versions" |
|
|
7
|
+
| 2 | 1003/1004 | malformed request / invalid parameter | check spelling against `tripo docs --topic commands/<cmd>`; the CLI already strips illegal P1 params. Classic 1004s: `generate_parts=true` with texture/pbr on, `ref_image` on segment v1, `quad=true` on P1, `smart_uv=true` on decimate v1.0/v2.0, non-GLB input to smartsegment `model` / rig-check. `invalid model`: the API only accepts dated wire values (`P2-20260801`, `v3.1-20260211`…) — pass the CLI alias (`--model tripo-p2`) and let the CLI normalize, or the wire value itself; never `tripo-*` straight to the API. Table: `commands/generate` § "Models & Versions" |
|
|
8
8
|
| 9 | 1007 | per-API-key rate limit | wait and retry with backoff; honour `Retry-After` / `X-RateLimit-Reset` headers |
|
|
9
9
|
| 9 | 2000 | per-account concurrency pool full (see table below) | wait for a task in that category to finish, or lower `--concurrency` in batch; other categories are unaffected |
|
|
10
10
|
| 8 | 2001 | task not found | task ids are account-scoped — same key that created it? right region (ov/cn)? |
|
|
@@ -42,6 +42,7 @@ Pools are independent: a full H-series pool does not block P-series or image tas
|
|
|
42
42
|
- `complete` only accepts a `segment` task; `retarget` only accepts a `rig` task
|
|
43
43
|
- quad + GLTF export → rejected (quads cannot be stored in glTF); use FBX/OBJ/USDZ
|
|
44
44
|
- P1 + face_limit outside 50–20000 → rejected with a suggestion to use v3.1
|
|
45
|
+
- decimate `smart_uv` on an explicit v1.0/v2.0 → rejected (v3.0 only); with no model given the CLI selects v3.0
|
|
45
46
|
- multiview without a front view → rejected (name a file "front" or pass it first)
|
|
46
47
|
- `-n` with `--then` needs an interactive terminal (pick the winner first, then chain)
|
|
47
48
|
|
|
@@ -57,3 +58,4 @@ All of these surface in `tripo make ... --dry-run --json` as `errors` (blocking)
|
|
|
57
58
|
- A downstream step after a generation that used `export_orientation` succeeds but comes out **wrongly oriented** — no error is raised. Set the orientation on the final `convert` step instead.
|
|
58
59
|
- `generate_parts` with `smart_low_poly=true` silently produces no parts (smart_low_poly wins); with `quad=true` the parts are triangles.
|
|
59
60
|
- `image-to-splat` yields a `.splat`, not a mesh — texture / rig / convert steps cannot follow it.
|
|
61
|
+
- `uv` accepts any model at creation, but an input over 80,000 equivalent triangles fails at run time (credits refunded) — decimate first: `--then decimate:20000,uv`.
|