@melite/3d-img-to-mesh 0.1.4-alpha → 0.1.5-pre-alpha
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 +38 -0
- package/lib/card.d.ts +2 -4
- package/lib/card.js +26 -11
- package/lib/client.js +20 -4
- package/lib/index.d.ts +1 -1
- package/package.json +9 -11
package/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Image-to-mesh card that boards three mesh families — pixal3d, trellis2-native, and transfer_rig — plus the mesh studio client.
|
|
3
|
+
kind: package-library
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @melite/3d-img-to-mesh
|
|
7
|
+
|
|
8
|
+
`@melite/3d-img-to-mesh` is the image-to-mesh card. One card serves three families, each with its own declared action: `pixal3d` and `trellis2-native` run the `mesh` action (image in, mesh out); `transfer_rig` runs `transfer` (rig transfers between two GLBs). The cardPackages SSOT composes the card from `./card`; the browser studio rides `./client`.
|
|
9
|
+
|
|
10
|
+
## Contract
|
|
11
|
+
|
|
12
|
+
- `./card` — the card definition (`id: 'img-to-mesh'`). Family dispatch keys on `model.family ?? model.id`; an unbound family refuses loudly. Per-family requirements: pixal3d needs the `ComfyUI-MoGe` pack, transfer_rig needs `melite-autorig-nodes`, trellis2-native needs none; the card-level `requires` is the union. Flow seats: `input_image` (image), `rigged_glb` and `target_glb` (mesh) in; mesh out, bound to `Save3DAdvanced.0` or `SaveRiggedModel.0` per action. Autofill literals (RemeshMesh band/project_back, ImageCropToMask background/grow_mask, MoGeInference apply_mask/batch_size/force_projection/fov_x_degrees) ride the compose; `remesh_qef`, `remesh_drop_inverted`, `remesh_drop_enclosed`, and `remesh_fix_poles` are card params.
|
|
13
|
+
- `./client` — `ImgToMeshStudio`, a DeclarativeStudio registration exposing the `input` and `generation` stages with the mesh preview; the plugin injects into `slots`.
|
|
14
|
+
- `.` — the row-mounted host face; it registers nothing.
|
|
15
|
+
- `./package.json` — the manifest.
|
|
16
|
+
|
|
17
|
+
## Model Experience
|
|
18
|
+
|
|
19
|
+
### Request context and condition
|
|
20
|
+
|
|
21
|
+
A run conditions the mesh graph only when the card composes; the package ships no agent tool face.
|
|
22
|
+
|
|
23
|
+
#### What the model sees
|
|
24
|
+
|
|
25
|
+
The active family's mesh model receives `input_image` plus the gated card params; the transfer action receives both GLBs.
|
|
26
|
+
|
|
27
|
+
#### Token effect
|
|
28
|
+
|
|
29
|
+
zero-direct — the package contributes no prompt or schema to any language-model context.
|
|
30
|
+
|
|
31
|
+
#### KV Cache effect
|
|
32
|
+
|
|
33
|
+
independent — nothing here appends to or reshapes a session cache.
|
|
34
|
+
|
|
35
|
+
## Known Limitations and Deferred Work
|
|
36
|
+
|
|
37
|
+
- **Per-family surfaces differ** — only pixal3d and transfer_rig carry pack requirements today; a new family must declare both its action and its slice.
|
|
38
|
+
- **Studio exposure is fixed** — `ImgToMeshStudio` folds the input and generation stages; other stages are not exposed yet.
|
package/lib/card.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type { Context } from '@
|
|
2
|
-
import type
|
|
3
|
-
import type { GraphBuilder } from '@melite/comfyui-card-kit/graph';
|
|
1
|
+
import type { Context } from '@melite/comfyui-card-kit/card-definition';
|
|
2
|
+
import { type ActionBinding as Binding } from '@melite/comfyui-card-kit';
|
|
4
3
|
export declare const inject: string[];
|
|
5
4
|
export declare const identity: {
|
|
6
5
|
label: string;
|
|
@@ -8,7 +7,6 @@ export declare const identity: {
|
|
|
8
7
|
genre: string;
|
|
9
8
|
icon: string;
|
|
10
9
|
};
|
|
11
|
-
export type Binding = (p: Record<string, unknown>, model: ModelFacts, g: GraphBuilder, runId: string) => void;
|
|
12
10
|
export declare const ACTION_BINDINGS: Record<string, Binding>;
|
|
13
11
|
export declare function apply(ctx: Context): void;
|
|
14
12
|
//# sourceMappingURL=card.d.ts.map
|
package/lib/card.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import z from '@deepseek-ai/schemastery';
|
|
2
|
-
import { declaredAction, instantiateAction, MESH_RESOLUTIONS,
|
|
2
|
+
import { declaredAction, instantiateAction, MESH_RESOLUTIONS, MESH_PIXAL_FOVS, MESH_ATLAS_SIZES, MESH_AO_SIZES, MESH_NORMAL_SIZES } from '@melite/comfyui-card-kit';
|
|
3
3
|
import { DECL as pixal3dDecl } from '@melite/models-pixal3d';
|
|
4
4
|
import { DECL as trellis2NativeDecl } from '@melite/models-trellis2-native';
|
|
5
5
|
import { DECL as transferRigDecl } from '@melite/models-transfer_rig';
|
|
6
6
|
import { SAMPLERS, SCHEDULERS, vocabulary } from '@melite/comfyui-card-kit/vocab';
|
|
7
7
|
import { bag } from '@melite/contracts/extraKeys';
|
|
8
|
-
import {
|
|
8
|
+
import { ComposeRefusal } from '@melite/comfyui-card-kit/errors';
|
|
9
|
+
import { seedExtra } from '@melite/comfyui-card-kit/fields';
|
|
10
|
+
import { callableSchema, gatedResolve } from '@melite/comfyui-card-kit/admission';
|
|
9
11
|
const schema = z.object({
|
|
10
12
|
// Ride keys (no .default — the compose-door cascade overlays model
|
|
11
13
|
// defaults, then explicit params): input_image is required; the
|
|
@@ -14,16 +16,15 @@ const schema = z.object({
|
|
|
14
16
|
// lift call never names them and a rig call names both. Bare
|
|
15
17
|
// z.string() is the image-gen prompt precedent (optional at parse,
|
|
16
18
|
// refused loud at compose).
|
|
17
|
-
input_image: z.string().role('path').description("Source image").extra('extra', bag({ order: 0, group: "input", columns: 1, tooltip: "One clear object, tight framing
|
|
19
|
+
input_image: z.string().role('path').description("Source image").extra('extra', bag({ order: 0, group: "input", columns: 1, tooltip: "One clear object, tight framing — the lane crops it to a square and conditions on it directly.", required: true, families: ['pixal3d', 'trellis2-native'], wtype: 'image', })),
|
|
18
20
|
rigged_glb: z.string().role('path').description("Rigged source GLB").extra('extra', bag({ order: 0, group: "input", columns: 1, tooltip: "The SOMA-rigged clean mesh — JOINTS_0/WEIGHTS_0 + armature. The rig donor.", families: ['transfer_rig'], wtype: 'mesh' })),
|
|
19
21
|
target_glb: z.string().role('path').description("Target GLB").extra('extra', bag({ order: 1, group: "input", columns: 1, tooltip: "The clothed mesh — geometry + textures, no rig. Receives the rig.", families: ['transfer_rig'], wtype: 'mesh' })),
|
|
20
|
-
seed: z.number().description("Seed").step(1).extra('extra', bag({ order: 1, group:
|
|
22
|
+
seed: z.number().description("Seed").step(1).extra('extra', bag(seedExtra({ order: 1, group: 'input', width: 1, tooltip: 'Same seed + image = same mesh take.', families: ['pixal3d', 'trellis2-native'] }))),
|
|
21
23
|
// Select knobs coerce wire strings at compose (the skin map_size
|
|
22
24
|
// precedent) — enum hints ride extra.options, never validation.
|
|
23
25
|
resolution: vocabulary(MESH_RESOLUTIONS).description("Resolution").extra('extra', bag({ order: 0, group: "generation", width: 1, tooltip: "Upsample target (the live node accepts 1024–2048; the family routes serve 1024 and 1536). All tiers run the full official chain — upsample + both texture passes + remesh tail.", families: ['pixal3d', 'trellis2-native'], wtype: 'select' })),
|
|
24
26
|
steps: z.number().description("Steps").min(4).max(60).step(1).extra('extra', bag({ order: 1, group: "generation", width: 1, tooltip: "STRUCTURE stage steps (the lift). Shape + texture stages ride their own knobs in the Stage section.", families: ['pixal3d', 'trellis2-native'], wtype: 'number' })),
|
|
25
27
|
cfg: z.number().description("CFG").min(1).max(15).step(0.5).extra('extra', bag({ order: 2, group: "generation", width: 1, tooltip: "Structure-stage guidance. 7.5 is the official template calibration (2026-09-06: the 3.0 default sampled the coarse shape at under half guidance — blobby trash out of the box). Lower runs looser.", families: ['pixal3d', 'trellis2-native'] })),
|
|
26
|
-
bg_removal: vocabulary(MESH_BG_MODES).description("Background removal").extra('extra', bag({ order: 3, group: "generation", width: 1, tooltip: "auto/on: birefnet cuts the background (recommended). off: feed a pre-cleaned or alpha-cut image straight to conditioning.", families: ['pixal3d', 'trellis2-native'], wtype: 'select' })),
|
|
27
28
|
camera_fov: vocabulary(MESH_PIXAL_FOVS).description("Camera FoV").extra('extra', bag({ order: 4, group: "generation", width: 1, tooltip: "Pixal3D only — per-image horizontal FoV feeding the camera transform matrix. auto: MoGeInference estimates from the source image (recommended); a literal degree value skips MoGe (operator-vouched camera, e.g. calibrated).", families: ['pixal3d'], wtype: 'select' })),
|
|
28
29
|
shape_steps: z.number().description("Shape steps").min(4).max(60).step(1).extra('extra', bag({ order: 0, group: "stage", width: 1, tooltip: "Shape-stage steps. 20 is the official template calibration.", families: ['pixal3d', 'trellis2-native'], wtype: 'number' })),
|
|
29
30
|
shape_cfg: z.number().description("Shape CFG").min(1).max(15).step(0.5).extra('extra', bag({ order: 1, group: "stage", width: 1, tooltip: "Shape-stage guidance. 7.5 is the official template calibration.", families: ['pixal3d', 'trellis2-native'] })),
|
|
@@ -61,12 +62,7 @@ const schema = z.object({
|
|
|
61
62
|
// never a declared knob, and compose never reads it: prefixes are
|
|
62
63
|
// family constants below).
|
|
63
64
|
});
|
|
64
|
-
|
|
65
|
-
* registration's schema carrier and the compose strict resolve's
|
|
66
|
-
* judge): schemastery schemas are callable (Schema.resolve) but
|
|
67
|
-
* carry a typed data parameter, while both card-seam consumers
|
|
68
|
-
* take unknown. */
|
|
69
|
-
const schemaFn = schema;
|
|
65
|
+
const schemaFn = callableSchema(schema);
|
|
70
66
|
export const inject = ['comfyui'];
|
|
71
67
|
|
|
72
68
|
// identity ring; the card owns its label/description/genre/icon).
|
|
@@ -76,6 +72,11 @@ export const identity = {
|
|
|
76
72
|
genre: '3d',
|
|
77
73
|
icon: 'box',
|
|
78
74
|
};
|
|
75
|
+
// THE FAMILY BINDINGS (the atom vocabulary, stroke 3): every
|
|
76
|
+
// boarded family's declared action, keyed by the row's family
|
|
77
|
+
// address — the id-switch dispatch died with them. A family-less
|
|
78
|
+
// row (the declared fallback) rides the legacy lane arms below —
|
|
79
|
+
// never a silent second copy.
|
|
79
80
|
export const ACTION_BINDINGS = {
|
|
80
81
|
[pixal3dDecl.id]: (p, model, g, runId) => void instantiateAction(declaredAction(pixal3dDecl, 'mesh'), p, model, g, runId),
|
|
81
82
|
[trellis2NativeDecl.id]: (p, model, g, runId) => void instantiateAction(declaredAction(trellis2NativeDecl, 'mesh'), p, model, g, runId),
|
|
@@ -146,6 +147,20 @@ export function apply(ctx) {
|
|
|
146
147
|
// their rows), fills defaults, passes undeclared keys through
|
|
147
148
|
// inert. The composer's reads below are reads of the GATED doc.
|
|
148
149
|
const doc = gatedResolve('img-to-mesh', schemaFn, ['model', 'input_image', 'rigged_glb', 'target_glb'], p);
|
|
150
|
+
// THE PAIRED GLB LANE (round-22 compose audit Q4b, EXHAUSTIVE-WHEN):
|
|
151
|
+
// rigged_glb and target_glb are one paired transfer lane — both or
|
|
152
|
+
// neither, on EVERY family. The lift arms ignore the pair, so a
|
|
153
|
+
// mixed state composed fine there and the producer walk then
|
|
154
|
+
// selected no output at all: zero outputs, silently. The mixed
|
|
155
|
+
// state refuses here, before any arm; the producer predicates
|
|
156
|
+
// stay exclusive on the states that remain reachable.
|
|
157
|
+
const riggedSet = String(doc.rigged_glb ?? '').trim() !== '';
|
|
158
|
+
const targetSet = String(doc.target_glb ?? '').trim() !== '';
|
|
159
|
+
if (riggedSet !== targetSet) {
|
|
160
|
+
throw new ComposeRefusal('bad-value', `card 'img-to-mesh': rigged_glb and target_glb are one paired transfer lane — ` +
|
|
161
|
+
`${riggedSet ? "rigged_glb is set but target_glb is empty" : "target_glb is set but rigged_glb is empty"}; ` +
|
|
162
|
+
`set both for the rig transfer, or neither for the image-to-mesh lift`);
|
|
163
|
+
}
|
|
149
164
|
// The arm IS the family's declared action (runId rides the
|
|
150
165
|
// signature; prefixes are family constants, not run-scoped,
|
|
151
166
|
// not knobs).
|
package/lib/client.js
CHANGED
|
@@ -20,14 +20,30 @@ window.__ModuleLoader__.load({
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
23
27
|
const SURFACE = (0, _melite_card_base_client.defineStudioDeclaration)({
|
|
24
28
|
model: "img-to-mesh",
|
|
25
29
|
expose: ["input", "generation"],
|
|
26
30
|
folds: {
|
|
27
|
-
stage:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
stage: {
|
|
32
|
+
title: "Stage passes",
|
|
33
|
+
icon: "branch"
|
|
34
|
+
},
|
|
35
|
+
mesh: {
|
|
36
|
+
title: "Mesh",
|
|
37
|
+
icon: "box"
|
|
38
|
+
},
|
|
39
|
+
bake: {
|
|
40
|
+
title: "Bake maps",
|
|
41
|
+
icon: "layers"
|
|
42
|
+
},
|
|
43
|
+
lab: {
|
|
44
|
+
title: "Lab (samplers & overrides)",
|
|
45
|
+
icon: "sliders"
|
|
46
|
+
}
|
|
31
47
|
},
|
|
32
48
|
preview: "mesh"
|
|
33
49
|
});
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Context } from '@
|
|
1
|
+
import type { Context } from '@melite/comfyui-card-kit/card-definition';
|
|
2
2
|
export declare const name = "@melite/3d-img-to-mesh";
|
|
3
3
|
export declare const inject: string[];
|
|
4
4
|
export declare function apply(_ctx: Context): void;
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.
|
|
2
|
+
"version": "0.1.5-pre-alpha",
|
|
3
3
|
"license": "SSPL-1.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "the img-to-mesh card (the 3d lane) — one card one package: card.ts host face + ui/
|
|
5
|
+
"description": "the img-to-mesh card (the 3d lane) — one card one package: card.ts host face + agents/ context (no tool face, no ui/ — the view is constructed by @melite/card-base from the emission)",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
8
8
|
"types": "./lib/index.d.ts",
|
|
@@ -20,15 +20,13 @@
|
|
|
20
20
|
"@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.1",
|
|
21
21
|
"@deepseek-ai/schemastery": "3.18.4",
|
|
22
22
|
"react": "^19.3.0",
|
|
23
|
-
"@melite-plugin/melite-run-wire": "0.1.
|
|
24
|
-
"@melite/
|
|
25
|
-
"@melite/comfyui-
|
|
26
|
-
"@melite/contracts": "0.1.
|
|
27
|
-
"@melite/models-pixal3d": "0.1.
|
|
28
|
-
"@melite/models-transfer_rig": "0.1.
|
|
29
|
-
"@melite/models-trellis2-native": "0.1.
|
|
30
|
-
"@melite/card-base": "0.1.4-alpha",
|
|
31
|
-
"@melite-plugin/3d": "0.1.4-alpha"
|
|
23
|
+
"@melite-plugin/melite-run-wire": "0.1.5-pre-alpha",
|
|
24
|
+
"@melite/card-base": "0.1.5-pre-alpha",
|
|
25
|
+
"@melite/comfyui-card-kit": "0.1.5-pre-alpha",
|
|
26
|
+
"@melite/contracts": "0.1.5-pre-alpha",
|
|
27
|
+
"@melite/models-pixal3d": "0.1.5-pre-alpha",
|
|
28
|
+
"@melite/models-transfer_rig": "0.1.5-pre-alpha",
|
|
29
|
+
"@melite/models-trellis2-native": "0.1.5-pre-alpha"
|
|
32
30
|
},
|
|
33
31
|
"devDependencies": {
|
|
34
32
|
"@testing-library/jest-dom": "*",
|