@combos-fun/plugin-renderer-3d-model 0.0.45 → 0.0.46

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.
Files changed (2) hide show
  1. package/agent-skill.md +47 -70
  2. package/package.json +4 -4
package/agent-skill.md CHANGED
@@ -1,103 +1,80 @@
1
1
  # `@combos-fun/plugin-renderer-3d-model` — Agent notes
2
2
 
3
- Loads a named 3D model through the engine resource system and drives included animations with Three.js `AnimationMixer`. `resource` is an engine **name**, never a URL.
3
+ Loads named 3D model resources and drives embedded clips with Three.js `AnimationMixer`. Supported runtime formats are GLB/glTF (Draco, KTX2, meshopt), FBX, OBJ with optional MTL, STL, DAE/Collada, and PLY. Prefer GLB; DCC source files are not runtime formats.
4
4
 
5
- Formats: `.glb` / `.gltf` (Draco, KTX2, meshopt), `.fbx`, `.obj` (+ optional `src.mtl`), `.stl`, `.dae`, `.ply`. Prefer `.glb` when you control the export. DCC sources (`.blend` / `.max` / `.c4d` / `.ma`) are not runtime-loadable.
5
+ Prerequisite: follow the parent `@combos-fun/plugin-renderer-3d` skill for system order, named resources, pose seeding, hierarchy, and the normal stale-async contract.
6
6
 
7
- ## When to read
8
-
9
- Read for any 3D character / prop / scenery model: registering a model resource, choosing animation clips, scrubbing animation speed.
10
-
11
- ## Public API
7
+ ## Public API and registration
12
8
 
13
9
  ```ts
14
- import { Model3D, Model3DSystem, type Model3DParams } from '@combos-fun/plugin-renderer-3d-model';
15
- import { resource, RESOURCE_TYPE } from '@combos-fun/engine';
10
+ import {
11
+ Model3D,
12
+ Model3DSystem,
13
+ type Model3DParams,
14
+ type ParsedModel,
15
+ type ModelResourceInstance,
16
+ } from '@combos-fun/plugin-renderer-3d-model';
16
17
  ```
17
18
 
18
- `componentName = 'Model3D'`, `systemName = 'Model3DSystem'`. Importing this package registers `RESOURCE_TYPE.MODEL` (and the `GLB` alias) instance factories.
19
+ `componentName = 'Model3D'`; `systemName = 'Model3DSystem'`.
20
+ The standard package entry loads `Model3DSystem`, whose `parseModel` import
21
+ registers `RESOURCE_TYPE.MODEL` and `GLB`. Deep-importing only the component
22
+ bypasses that registration.
23
+
24
+ ## Parameters
19
25
 
20
- ### `Model3DParams`
26
+ | Field | Type | Default | Behavior |
27
+ |-------|------|---------|----------|
28
+ | `resource` | `string` | `''` | MODEL name; empty on ADD is a silent no-op |
29
+ | `autoPlay` | `boolean` | `true` | Consulted only when a newly loaded model is attached; it is not a runtime play/pause control |
30
+ | `animationIndex` | `number` | `0` | Index into `animations` |
31
+ | `speed` | `number` | `1` | Assigned to the selected action's `timeScale` |
32
+ | `positionX/Y/Z` | `number` | `0` | Local pose compatibility fields |
33
+ | `rotationX/Y/Z` | `number` | `0` | Radians |
34
+ | `scaleX/Y/Z` | `number` | `1` | Model scale |
21
35
 
22
- | Field | Type | Default | Notes |
23
- |-------|------|---------|-------|
24
- | `resource` | `string` | `''` | Engine resource name (`RESOURCE_TYPE.MODEL`). Missing name throws; URLs are not accepted. |
25
- | `autoPlay` | `boolean` | `true` | |
26
- | `animationIndex` | `number` | `0` | Index into the model's `animations` array |
27
- | `speed` | `number` | `1` | `AnimationMixer.timeScale` |
28
- | `positionX` / `Y` / `Z` | `number` | `0` |
29
- | `rotationX` / `Y` / `Z` | `number` | `0` |
30
- | `scaleX` / `Y` / `Z` | `number` | `1` |
36
+ `autoPlay` is not observed after load. By contrast, changing either `animationIndex` **or** `speed` at runtime always calls `playAnimation`: all actions are stopped and the selected clip is restarted at the requested speed, even when `autoPlay` is false. An out-of-range index therefore stops current playback and starts nothing.
31
37
 
32
- Changing `animationIndex` or `speed` restarts the animation cleanly.
38
+ ## Resource shape
33
39
 
34
- ### Resource registration
40
+ Use a `model`, `glb`, or `gltf` source slot; parsed data may likewise be in `data.model`, `data.glb`, or `data.gltf`. OBJ may add an `mtl` slot. Relative glTF/OBJ sidecars are resolved from the main asset directory.
35
41
 
36
42
  ```ts
37
- resource.addResource([
38
- {
39
- name: 'hero',
40
- type: RESOURCE_TYPE.MODEL,
41
- src: { model: { type: 'glb', url: 'https://cdn.example/hero.glb' } },
42
- preload: true,
43
- },
44
- {
45
- name: 'crate',
46
- type: RESOURCE_TYPE.MODEL,
47
- src: {
48
- model: { type: 'obj', url: 'https://cdn.example/crate.obj' },
49
- mtl: { type: 'mtl', url: 'https://cdn.example/crate.mtl' },
50
- },
51
- preload: true,
52
- },
53
- ]);
43
+ resource.addResource([{
44
+ name: 'hero',
45
+ type: RESOURCE_TYPE.MODEL,
46
+ src: { model: { type: 'glb', url: 'https://cdn.example/hero.glb' } },
47
+ preload: true,
48
+ }]);
54
49
  ```
55
50
 
56
- CDN / http URLs belong in `src`, not on `Model3D.resource`. Sidecar files (gltf `.bin` / images, obj `.mtl`) should share the same directory as the main file, or be listed as extra `src` slots (`mtl`, `bin`).
57
-
58
- ## Required setup
59
-
60
- `Renderer3DSystem` then `Model3DSystem`. Gate `new Game(...)` on `resource.once(LOAD_EVENT.COMPLETE, ...)`.
61
-
62
- ## Runtime behaviour
63
-
64
- - Loading is async. While the model is parsing, the GameObject has no visible mesh.
65
- - The system uses `increaseAsyncId` / `validateAsyncId` to drop stale loads if the component is removed mid-fetch.
66
- - Each GameObject gets a cloned scene (`SkeletonUtils.clone`) so two heroes can share one resource.
67
- - The `AnimationMixer` is owned by `ThreeContext`; switching `animationIndex` calls `mixer.stopAllAction()` then plays the new clip.
68
-
69
- ### Physics
70
-
71
- A sibling `Physics3D` on the same GameObject defaults to `collider: 'aabb'` when `type` / `parts` are omitted (bounding box after load, including `scale*`). Use `collider: 'hull'` for convex props, `collider: 'trimesh'` only on **static** scenery (`mass` is forced to 0). Animation does not rebuild the collider. See `@combos-fun/plugin-cannon`.
72
-
73
- `GameObject.addChild` parents the loaded group under the ancestor `Transform3D` root (or nearest 3D visual). Child `position*` are local.
51
+ ## Runtime and lifecycle
74
52
 
75
- When `Renderer3DSystem({ shadows: true })`, every mesh in the cloned model gets `castShadow` and `receiveShadow`.
53
+ - Parsing is async; no model is visible until it completes. Parsed resources are cached, then each GameObject receives a `SkeletonUtils.clone`.
54
+ - Each attached animated clone gets its own mixer in `ThreeContext`.
55
+ - `resource` replacement removes the prior model and loads a new clone. Removal stops its mixer and disposes clone geometry/materials.
56
+ - Unlike the normal parent contract, async-id validation happens after attachment; removing or replacing the component during parsing can leave a stale clone attached.
57
+ - Renderer shadows traverse every mesh in the clone.
76
58
 
77
- ## Common pitfalls
59
+ ## Package-specific pitfalls
78
60
 
79
- | Symptom | Fix |
80
- |---------|-----|
81
- | `Unknown resource` throw | Register the name with `resource.addResource` + `RESOURCE_TYPE.MODEL`; do not pass a URL to `Model3D.resource` |
82
- | Model not visible | Loaded at origin; adjust `position*` or check camera distance (camera is at z=5 by default) |
83
- | Wrong scale | Use `scaleX` / `Y` / `Z`; many GLBs export at meter scale |
84
- | Animation doesn't play | `autoPlay: true` is the default — check `animationIndex` is within `animations.length` (OBJ/STL/PLY have none) |
85
- | Draco / KTX2 glTF fails | Decoder WASM is fetched from Google Draco / unpkg three `basis/` — the page must allow that network |
86
- | 404 / CORS | Verify `src.model.url` returns the file; check network tab |
61
+ - OBJ/STL/PLY commonly have no animation clips.
62
+ - Draco and KTX2 decoder assets are fetched from the configured Google/unpkg CDN paths, so CSP/network access must allow them.
63
+ - Exported model units vary; adjust `scaleX/Y/Z`.
64
+ - A sibling `Material3D` can override clone materials after load.
65
+ - A sibling Cannon `Physics3D` may derive an AABB/hull after load. Use trimesh only for static scenery; animation does not rebuild a collider.
87
66
 
88
67
  ## Minimal example
89
68
 
90
69
  ```ts
91
- const hero = new GameObject('hero');
92
70
  hero.addComponent(new Model3D({
93
71
  resource: 'hero',
94
72
  autoPlay: true,
95
73
  animationIndex: 0,
96
74
  speed: 1,
97
- positionY: 0,
98
75
  }));
99
76
  ```
100
77
 
101
78
  ## Verification
102
79
 
103
- `pnpm --filter @combos-fun/plugin-renderer-3d-model run build`.
80
+ `pnpm --filter @combos-fun/plugin-renderer-3d-model run build`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@combos-fun/plugin-renderer-3d-model",
3
- "version": "0.0.45",
3
+ "version": "0.0.46",
4
4
  "description": "Named 3D model loader (glTF/GLB, FBX, OBJ, STL, Collada, PLY) and animator",
5
5
  "main": "index.js",
6
6
  "module": "dist/plugin-renderer-3d-model.esm.js",
@@ -27,9 +27,9 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "three": "^0.172.0",
30
- "@combos-fun/plugin-renderer-3d": "0.0.45",
31
- "@combos-fun/inspector-decorator": "0.0.45",
32
- "@combos-fun/engine": "0.0.45"
30
+ "@combos-fun/engine": "0.0.46",
31
+ "@combos-fun/plugin-renderer-3d": "0.0.46",
32
+ "@combos-fun/inspector-decorator": "0.0.46"
33
33
  },
34
34
  "keywords": [
35
35
  "combos-fun",