reze-engine 0.9.5 → 0.10.1
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 +92 -72
- package/dist/animation.d.ts +26 -13
- package/dist/animation.d.ts.map +1 -1
- package/dist/animation.js +95 -35
- package/dist/engine.d.ts +0 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +1 -10
- package/dist/ik-solver.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/model.d.ts +9 -11
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +61 -38
- package/dist/vmd-writer.d.ts +5 -0
- package/dist/vmd-writer.d.ts.map +1 -0
- package/dist/vmd-writer.js +162 -0
- package/package.json +4 -3
- package/src/animation.ts +124 -40
- package/src/engine.ts +34 -44
- package/src/ik-solver.ts +7 -7
- package/src/index.ts +10 -5
- package/src/model.ts +69 -42
- package/src/vmd-writer.ts +180 -0
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A minimal-dependency WebGPU engine for real-time MMD/PMX rendering. Only external dependency is Ammo.js for physics.
|
|
4
4
|
|
|
5
|
+

|
|
6
|
+
|
|
5
7
|
## Install
|
|
6
8
|
|
|
7
9
|
```bash
|
|
@@ -14,76 +16,113 @@ npm install reze-engine
|
|
|
14
16
|
- VMD animation with IK solver and Bullet physics
|
|
15
17
|
- Orbit camera with bone-follow mode
|
|
16
18
|
- GPU picking (double-click/tap)
|
|
17
|
-
- Ground plane with PCF shadow mapping
|
|
19
|
+
- Ground plane with PCF shadow mapping
|
|
18
20
|
- Multi-model support
|
|
19
21
|
|
|
20
|
-
##
|
|
22
|
+
## Usage
|
|
21
23
|
|
|
22
24
|
```javascript
|
|
23
|
-
import { Engine, Vec3 } from "reze-engine"
|
|
25
|
+
import { Engine, Vec3 } from "reze-engine";
|
|
24
26
|
|
|
25
27
|
const engine = new Engine(canvas, {
|
|
26
28
|
ambientColor: new Vec3(0.88, 0.92, 0.99),
|
|
27
29
|
cameraDistance: 31.5, // MMD units (1 unit = 8 cm)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
await
|
|
33
|
-
model.
|
|
34
|
-
model.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
engine.
|
|
38
|
-
engine.
|
|
30
|
+
cameraTarget: new Vec3(0, 11.5, 0),
|
|
31
|
+
});
|
|
32
|
+
await engine.init();
|
|
33
|
+
|
|
34
|
+
const model = await engine.loadModel("hero", "/models/hero/hero.pmx");
|
|
35
|
+
await model.loadVmd("idle", "/animations/idle.vmd");
|
|
36
|
+
model.show("idle");
|
|
37
|
+
model.play();
|
|
38
|
+
|
|
39
|
+
engine.setCameraFollow(model, "センター", new Vec3(0, 3.5, 0));
|
|
40
|
+
engine.addGround({ width: 160, height: 160 });
|
|
41
|
+
engine.runRenderLoop();
|
|
39
42
|
```
|
|
40
43
|
|
|
41
44
|
## API
|
|
42
45
|
|
|
46
|
+
One WebGPU **Engine** per page (singleton after `init()`). Load models via `engine.loadModel(path)` or `engine.loadModel(name, path)`.
|
|
47
|
+
|
|
43
48
|
### Engine
|
|
44
49
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
50
|
+
```javascript
|
|
51
|
+
engine.init()
|
|
52
|
+
engine.loadModel(name, path)
|
|
53
|
+
engine.getModel(name)
|
|
54
|
+
engine.getModelNames()
|
|
55
|
+
engine.removeModel(name)
|
|
56
|
+
|
|
57
|
+
engine.setMaterialVisible(name, material, visible)
|
|
58
|
+
engine.toggleMaterialVisible(name, material)
|
|
59
|
+
engine.isMaterialVisible(name, material)
|
|
60
|
+
|
|
61
|
+
engine.setIKEnabled(enabled)
|
|
62
|
+
engine.setPhysicsEnabled(enabled)
|
|
63
|
+
|
|
64
|
+
engine.setCameraFollow(model, bone?, offset?)
|
|
65
|
+
engine.setCameraFollow(null)
|
|
66
|
+
engine.setCameraTarget(vec3)
|
|
67
|
+
engine.setCameraDistance(d)
|
|
68
|
+
engine.setCameraAlpha(a)
|
|
69
|
+
engine.setCameraBeta(b)
|
|
70
|
+
|
|
71
|
+
engine.addGround(options?)
|
|
72
|
+
engine.runRenderLoop(callback?)
|
|
73
|
+
engine.stopRenderLoop()
|
|
74
|
+
engine.getStats()
|
|
75
|
+
engine.dispose()
|
|
76
|
+
```
|
|
68
77
|
|
|
69
78
|
### Model
|
|
70
79
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
```javascript
|
|
81
|
+
await model.loadVmd(name, url)
|
|
82
|
+
model.loadClip(name, clip)
|
|
83
|
+
model.show(name)
|
|
84
|
+
model.play(name)
|
|
85
|
+
model.play(name, { priority: 8 }) // higher number = higher priority (0 default/lowest)
|
|
86
|
+
model.play(name, { loop: true }) // repeat until stop/pause or another play
|
|
87
|
+
model.pause()
|
|
88
|
+
model.stop()
|
|
89
|
+
model.seek(time)
|
|
90
|
+
model.getAnimationProgress()
|
|
91
|
+
model.getClip(name)
|
|
92
|
+
model.exportVmd(name) // returns ArrayBuffer
|
|
93
|
+
|
|
94
|
+
model.rotateBones({ 首: quat, 頭: quat }, ms?)
|
|
95
|
+
model.moveBones({ センター: vec3 }, ms?)
|
|
96
|
+
model.setMorphWeight(name, weight, ms?)
|
|
97
|
+
model.resetAllBones()
|
|
98
|
+
model.resetAllMorphs()
|
|
99
|
+
model.getBoneWorldPosition(name)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### Animation data
|
|
103
|
+
|
|
104
|
+
`AnimationClip` holds keyframes only: bone/morph tracks keyed by `frame`, and `frameCount` (last keyframe index). Time advances at fixed `FPS` (see package export `FPS`, default 30).
|
|
105
|
+
|
|
106
|
+
#### VMD Export
|
|
107
|
+
|
|
108
|
+
`model.exportVmd(name)` serialises a loaded clip back to the VMD binary format and returns an `ArrayBuffer`. Bone and morph names are Shift-JIS encoded for compatibility with standard MMD tools.
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
const buffer = model.exportVmd("idle")
|
|
112
|
+
const blob = new Blob([buffer], { type: "application/octet-stream" })
|
|
113
|
+
const link = document.createElement("a")
|
|
114
|
+
link.href = URL.createObjectURL(blob)
|
|
115
|
+
link.download = "idle.vmd"
|
|
116
|
+
link.click()
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### Playback
|
|
120
|
+
|
|
121
|
+
Call `model.play(name, options?)` to start or switch motion. `loop: true` makes the playhead wrap at the end of the clip until you stop, pause, or call `play` with something else. `priority` chooses which request wins when several clips compete.
|
|
122
|
+
|
|
123
|
+
#### Progress
|
|
124
|
+
|
|
125
|
+
`getAnimationProgress()` reports `current` and `duration` in seconds, plus `playing`, `paused`, `looping`, and related fields.
|
|
87
126
|
|
|
88
127
|
### Engine Options
|
|
89
128
|
|
|
@@ -108,25 +147,6 @@ engine.runRenderLoop()
|
|
|
108
147
|
|
|
109
148
|
`constraintSolverKeywords` — joints whose name contains any keyword use the Bullet 2.75 constraint solver; all others keep the stable Ammo 2.82+ default. See [babylon-mmd: Fix Constraint Behavior](https://noname0310.github.io/babylon-mmd/docs/reference/runtime/apply-physics-to-mmd-models/#fix-constraint-behavior) for details.
|
|
110
149
|
|
|
111
|
-
### Ground Options
|
|
112
|
-
|
|
113
|
-
```javascript
|
|
114
|
-
engine.addGround({
|
|
115
|
-
width: 100, // ground plane width
|
|
116
|
-
height: 100, // ground plane depth
|
|
117
|
-
diffuseColor: Vec3, // base color (default: 0.8, 0.1, 1.0)
|
|
118
|
-
fadeStart: 5.0, // distance where edge fade begins
|
|
119
|
-
fadeEnd: 60.0, // distance where ground fully fades out
|
|
120
|
-
shadowMapSize: 4096, // shadow map resolution
|
|
121
|
-
shadowStrength: 1.0, // shadow darkness
|
|
122
|
-
gridSpacing: 5.0, // world-space distance between grid lines
|
|
123
|
-
gridLineWidth: 0.012, // thickness of grid lines
|
|
124
|
-
gridLineOpacity: 0.4, // grid line visibility (0–1)
|
|
125
|
-
gridLineColor: Vec3, // grid line color (default: 0.8, 0.8, 0.8)
|
|
126
|
-
noiseStrength: 0.08, // frosted/matte micro-texture intensity
|
|
127
|
-
})
|
|
128
|
-
```
|
|
129
|
-
|
|
130
150
|
## Projects Using This Engine
|
|
131
151
|
|
|
132
152
|
- **[MiKaPo](https://mikapo.vercel.app)** — Real-time motion capture for MMD
|
package/dist/animation.d.ts
CHANGED
|
@@ -15,31 +15,46 @@ export interface BoneKeyframe {
|
|
|
15
15
|
rotation: Quat;
|
|
16
16
|
translation: Vec3;
|
|
17
17
|
interpolation: BoneInterpolation;
|
|
18
|
-
time: number;
|
|
19
18
|
}
|
|
20
19
|
export interface MorphKeyframe {
|
|
21
20
|
morphName: string;
|
|
22
21
|
frame: number;
|
|
23
22
|
weight: number;
|
|
24
|
-
time: number;
|
|
25
23
|
}
|
|
26
24
|
export interface AnimationClip {
|
|
27
25
|
boneTracks: Map<string, BoneKeyframe[]>;
|
|
28
26
|
morphTracks: Map<string, MorphKeyframe[]>;
|
|
29
|
-
|
|
27
|
+
frameCount: number;
|
|
28
|
+
}
|
|
29
|
+
export interface AnimationPlayOptions {
|
|
30
|
+
priority?: number;
|
|
30
31
|
loop?: boolean;
|
|
31
32
|
}
|
|
33
|
+
/** Wall-clock playback progress; `current`/`duration` are seconds (clip span uses `AnimationClip.frameCount`, not `duration`). */
|
|
34
|
+
export interface AnimationProgress {
|
|
35
|
+
animationName: string | null;
|
|
36
|
+
current: number;
|
|
37
|
+
duration: number;
|
|
38
|
+
percentage: number;
|
|
39
|
+
looping: boolean;
|
|
40
|
+
/** True while the timeline is advancing (not idle at end, not paused). */
|
|
41
|
+
playing: boolean;
|
|
42
|
+
paused: boolean;
|
|
43
|
+
}
|
|
44
|
+
export declare const FPS = 30;
|
|
32
45
|
export declare class AnimationState {
|
|
33
46
|
private animations;
|
|
34
47
|
private currentAnimationName;
|
|
35
|
-
private
|
|
48
|
+
private currentFrame;
|
|
49
|
+
private currentPriority;
|
|
50
|
+
private currentLoop;
|
|
36
51
|
private isPlaying;
|
|
37
52
|
private isPaused;
|
|
38
|
-
private
|
|
53
|
+
private nextAnimation;
|
|
39
54
|
private onEnd;
|
|
40
55
|
loadAnimation(name: string, clip: AnimationClip): void;
|
|
41
56
|
removeAnimation(name: string): void;
|
|
42
|
-
play(name: string): boolean;
|
|
57
|
+
play(name: string, options?: AnimationPlayOptions): boolean;
|
|
43
58
|
play(): void;
|
|
44
59
|
update(deltaTime: number): {
|
|
45
60
|
ended: boolean;
|
|
@@ -47,17 +62,15 @@ export declare class AnimationState {
|
|
|
47
62
|
};
|
|
48
63
|
pause(): void;
|
|
49
64
|
stop(): void;
|
|
50
|
-
seek(
|
|
65
|
+
seek(seconds: number): void;
|
|
51
66
|
getCurrentClip(): AnimationClip | null;
|
|
67
|
+
getAnimationClip(name: string): AnimationClip | null;
|
|
52
68
|
getCurrentAnimation(): string | null;
|
|
53
69
|
getCurrentTime(): number;
|
|
70
|
+
getCurrentFrame(): number;
|
|
71
|
+
/** Clip length in seconds (`frameCount / FPS`). */
|
|
54
72
|
getDuration(): number;
|
|
55
|
-
getProgress():
|
|
56
|
-
animationName: string | null;
|
|
57
|
-
current: number;
|
|
58
|
-
duration: number;
|
|
59
|
-
percentage: number;
|
|
60
|
-
};
|
|
73
|
+
getProgress(): AnimationProgress;
|
|
61
74
|
getAnimationNames(): string[];
|
|
62
75
|
hasAnimation(name: string): boolean;
|
|
63
76
|
show(name: string): void;
|
package/dist/animation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"animation.d.ts","sourceRoot":"","sources":["../src/animation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAEnC,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB,YAAY,EAAE,YAAY,EAAE,CAAA;IAC5B,YAAY,EAAE,YAAY,EAAE,CAAA;IAC5B,YAAY,EAAE,YAAY,EAAE,CAAA;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,IAAI,CAAA;IACd,WAAW,EAAE,IAAI,CAAA;IACjB,aAAa,EAAE,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"animation.d.ts","sourceRoot":"","sources":["../src/animation.ts"],"names":[],"mappings":"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"}
|
package/dist/animation.js
CHANGED
|
@@ -1,30 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
export const FPS = 30;
|
|
2
|
+
// Priority-aware playback: higher priority preempts, otherwise latest request is queued.
|
|
2
3
|
export class AnimationState {
|
|
3
4
|
constructor() {
|
|
4
5
|
this.animations = new Map();
|
|
5
6
|
this.currentAnimationName = null;
|
|
6
|
-
this.
|
|
7
|
+
this.currentFrame = 0;
|
|
8
|
+
this.currentPriority = 0;
|
|
9
|
+
this.currentLoop = false;
|
|
7
10
|
this.isPlaying = false;
|
|
8
11
|
this.isPaused = false;
|
|
9
|
-
this.
|
|
12
|
+
this.nextAnimation = null;
|
|
10
13
|
this.onEnd = null;
|
|
11
14
|
}
|
|
12
15
|
loadAnimation(name, clip) {
|
|
13
|
-
this.animations.set(name,
|
|
16
|
+
this.animations.set(name, {
|
|
17
|
+
boneTracks: clip.boneTracks,
|
|
18
|
+
morphTracks: clip.morphTracks,
|
|
19
|
+
frameCount: clip.frameCount,
|
|
20
|
+
});
|
|
14
21
|
}
|
|
15
22
|
removeAnimation(name) {
|
|
16
23
|
this.animations.delete(name);
|
|
17
24
|
if (this.currentAnimationName === name) {
|
|
18
25
|
this.currentAnimationName = null;
|
|
19
|
-
this.
|
|
26
|
+
this.currentFrame = 0;
|
|
27
|
+
this.currentPriority = 0;
|
|
28
|
+
this.currentLoop = false;
|
|
20
29
|
this.isPlaying = false;
|
|
21
|
-
this.
|
|
30
|
+
this.nextAnimation = this.nextAnimation?.name === name ? null : this.nextAnimation;
|
|
22
31
|
}
|
|
23
|
-
else if (this.
|
|
24
|
-
this.
|
|
32
|
+
else if (this.nextAnimation?.name === name) {
|
|
33
|
+
this.nextAnimation = null;
|
|
25
34
|
}
|
|
26
35
|
}
|
|
27
|
-
play(name) {
|
|
36
|
+
play(name, options) {
|
|
28
37
|
if (name === undefined) {
|
|
29
38
|
if (this.currentAnimationName && this.animations.has(this.currentAnimationName)) {
|
|
30
39
|
this.isPaused = false;
|
|
@@ -34,15 +43,37 @@ export class AnimationState {
|
|
|
34
43
|
}
|
|
35
44
|
if (!this.animations.has(name))
|
|
36
45
|
return false;
|
|
46
|
+
const priority = options?.priority ?? 0;
|
|
47
|
+
const loop = options?.loop ?? false;
|
|
48
|
+
if (this.currentAnimationName === name) {
|
|
49
|
+
this.currentFrame = 0;
|
|
50
|
+
this.currentPriority = priority;
|
|
51
|
+
this.currentLoop = loop;
|
|
52
|
+
this.isPlaying = true;
|
|
53
|
+
this.isPaused = false;
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
37
56
|
if (this.isPlaying && !this.isPaused) {
|
|
38
|
-
this.
|
|
57
|
+
if (priority > this.currentPriority) {
|
|
58
|
+
this.currentAnimationName = name;
|
|
59
|
+
this.currentFrame = 0;
|
|
60
|
+
this.currentPriority = priority;
|
|
61
|
+
this.currentLoop = loop;
|
|
62
|
+
this.isPlaying = true;
|
|
63
|
+
this.isPaused = false;
|
|
64
|
+
this.nextAnimation = null;
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
this.nextAnimation = { name, priority, loop };
|
|
39
68
|
return true;
|
|
40
69
|
}
|
|
41
70
|
this.currentAnimationName = name;
|
|
42
|
-
this.
|
|
71
|
+
this.currentFrame = 0;
|
|
72
|
+
this.currentPriority = priority;
|
|
73
|
+
this.currentLoop = loop;
|
|
43
74
|
this.isPlaying = true;
|
|
44
75
|
this.isPaused = false;
|
|
45
|
-
this.
|
|
76
|
+
this.nextAnimation = null;
|
|
46
77
|
return true;
|
|
47
78
|
}
|
|
48
79
|
update(deltaTime) {
|
|
@@ -52,21 +83,28 @@ export class AnimationState {
|
|
|
52
83
|
const clip = this.animations.get(this.currentAnimationName);
|
|
53
84
|
if (!clip)
|
|
54
85
|
return { ended: false, animationName: this.currentAnimationName };
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
86
|
+
const frameCount = clip.frameCount;
|
|
87
|
+
if (frameCount <= 0 || !Number.isFinite(frameCount)) {
|
|
88
|
+
return { ended: false, animationName: this.currentAnimationName };
|
|
89
|
+
}
|
|
90
|
+
this.currentFrame += deltaTime * FPS;
|
|
91
|
+
if (this.currentFrame >= frameCount) {
|
|
92
|
+
if (this.currentLoop) {
|
|
93
|
+
while (this.currentFrame >= frameCount) {
|
|
94
|
+
this.currentFrame -= frameCount;
|
|
95
|
+
}
|
|
61
96
|
return { ended: false, animationName: this.currentAnimationName };
|
|
62
97
|
}
|
|
98
|
+
this.currentFrame = frameCount;
|
|
63
99
|
const finishedName = this.currentAnimationName;
|
|
64
100
|
this.onEnd?.(finishedName);
|
|
65
|
-
if (this.
|
|
66
|
-
const next = this.
|
|
67
|
-
this.
|
|
68
|
-
this.currentAnimationName = next;
|
|
69
|
-
this.
|
|
101
|
+
if (this.nextAnimation !== null) {
|
|
102
|
+
const next = this.nextAnimation;
|
|
103
|
+
this.nextAnimation = null;
|
|
104
|
+
this.currentAnimationName = next.name;
|
|
105
|
+
this.currentFrame = 0;
|
|
106
|
+
this.currentPriority = next.priority;
|
|
107
|
+
this.currentLoop = next.loop;
|
|
70
108
|
this.isPlaying = true;
|
|
71
109
|
this.isPaused = false;
|
|
72
110
|
return { ended: true, animationName: finishedName };
|
|
@@ -82,37 +120,57 @@ export class AnimationState {
|
|
|
82
120
|
stop() {
|
|
83
121
|
this.isPlaying = false;
|
|
84
122
|
this.isPaused = false;
|
|
85
|
-
this.
|
|
86
|
-
this.
|
|
123
|
+
this.currentFrame = 0;
|
|
124
|
+
this.currentPriority = 0;
|
|
125
|
+
this.currentLoop = false;
|
|
126
|
+
this.nextAnimation = null;
|
|
87
127
|
}
|
|
88
|
-
|
|
128
|
+
// Seek by absolute timeline seconds, not frame index.
|
|
129
|
+
seek(seconds) {
|
|
89
130
|
const clip = this.getCurrentClip();
|
|
90
|
-
if (!clip)
|
|
131
|
+
if (!clip || clip.frameCount <= 0 || !Number.isFinite(clip.frameCount))
|
|
91
132
|
return;
|
|
92
|
-
|
|
133
|
+
const targetFrame = seconds * FPS;
|
|
134
|
+
this.currentFrame = Math.max(0, Math.min(targetFrame, clip.frameCount));
|
|
93
135
|
}
|
|
94
136
|
getCurrentClip() {
|
|
95
137
|
return this.currentAnimationName !== null ? this.animations.get(this.currentAnimationName) ?? null : null;
|
|
96
138
|
}
|
|
139
|
+
getAnimationClip(name) {
|
|
140
|
+
return this.animations.get(name) ?? null;
|
|
141
|
+
}
|
|
97
142
|
getCurrentAnimation() {
|
|
98
143
|
return this.currentAnimationName;
|
|
99
144
|
}
|
|
100
145
|
getCurrentTime() {
|
|
101
|
-
|
|
146
|
+
const clip = this.getCurrentClip();
|
|
147
|
+
if (!clip)
|
|
148
|
+
return 0;
|
|
149
|
+
return this.currentFrame / FPS;
|
|
150
|
+
}
|
|
151
|
+
getCurrentFrame() {
|
|
152
|
+
return this.currentFrame;
|
|
102
153
|
}
|
|
154
|
+
/** Clip length in seconds (`frameCount / FPS`). */
|
|
103
155
|
getDuration() {
|
|
104
156
|
const clip = this.getCurrentClip();
|
|
105
|
-
|
|
157
|
+
if (!clip || clip.frameCount <= 0 || !Number.isFinite(clip.frameCount))
|
|
158
|
+
return 0;
|
|
159
|
+
return clip.frameCount / FPS;
|
|
106
160
|
}
|
|
107
161
|
getProgress() {
|
|
108
162
|
const clip = this.getCurrentClip();
|
|
109
|
-
const duration = clip ? clip.
|
|
110
|
-
const
|
|
163
|
+
const duration = clip && clip.frameCount > 0 ? clip.frameCount / FPS : 0;
|
|
164
|
+
const current = clip ? this.currentFrame / FPS : 0;
|
|
165
|
+
const percentage = duration > 0 ? (current / duration) * 100 : 0;
|
|
111
166
|
return {
|
|
112
167
|
animationName: this.currentAnimationName,
|
|
113
|
-
current
|
|
168
|
+
current,
|
|
114
169
|
duration,
|
|
115
170
|
percentage,
|
|
171
|
+
looping: this.currentLoop,
|
|
172
|
+
playing: this.isPlaying && !this.isPaused,
|
|
173
|
+
paused: this.isPaused,
|
|
116
174
|
};
|
|
117
175
|
}
|
|
118
176
|
getAnimationNames() {
|
|
@@ -125,10 +183,12 @@ export class AnimationState {
|
|
|
125
183
|
if (!this.animations.has(name))
|
|
126
184
|
return;
|
|
127
185
|
this.currentAnimationName = name;
|
|
128
|
-
this.
|
|
186
|
+
this.currentFrame = 0;
|
|
187
|
+
this.currentPriority = 0;
|
|
188
|
+
this.currentLoop = false;
|
|
129
189
|
this.isPlaying = false;
|
|
130
190
|
this.isPaused = false;
|
|
131
|
-
this.
|
|
191
|
+
this.nextAnimation = null;
|
|
132
192
|
}
|
|
133
193
|
setOnEnd(callback) {
|
|
134
194
|
this.onEnd = callback;
|
package/dist/engine.d.ts
CHANGED
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,IAAI,EAAE,MAAM,QAAQ,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAE/B,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,WAAW,CAAA;AAExD,MAAM,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;AAEpH,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,CAAC,EAAE,IAAI,CAAA;IACnB,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,YAAY,CAAC,EAAE,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,eAAe,CAAA;IAC3B,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,oBAAoB,CAAC,EAAE,IAAI,CAAA;CAC5B,CAAA;AAED,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;CAWlC,CAAA;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;CAClB;AA2CD,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAsB;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.js
CHANGED
|
@@ -623,7 +623,7 @@ export class Engine {
|
|
|
623
623
|
// Screen-stable edgeline: extrusion ∝ camera distance (same idea as MMD viewers / babylon-mmd-style scaling)
|
|
624
624
|
let camDist = max(length(camera.viewPos - worldPos), 0.25);
|
|
625
625
|
let refDist = 30.0;
|
|
626
|
-
let edgeScale = 0.
|
|
626
|
+
let edgeScale = 0.025;
|
|
627
627
|
let expandedPos = worldPos + worldNormal * material.edgeSize * edgeScale * (camDist / refDist);
|
|
628
628
|
output.position = camera.projection * camera.view * vec4f(expandedPos, 1.0);
|
|
629
629
|
return output;
|
|
@@ -880,15 +880,6 @@ export class Engine {
|
|
|
880
880
|
this.lightData[3] = this.minSpecularIntensity; // ambientColor.w = minSpecularIntensity
|
|
881
881
|
this.updateLightBuffer();
|
|
882
882
|
}
|
|
883
|
-
clearLights() {
|
|
884
|
-
this.lightCount = 0;
|
|
885
|
-
// Clear all light data by setting intensity to 0
|
|
886
|
-
for (let i = 0; i < 4; i++) {
|
|
887
|
-
const baseIndex = 4 + i * 8;
|
|
888
|
-
this.lightData[baseIndex + 7] = 0; // color.w / intensity
|
|
889
|
-
}
|
|
890
|
-
this.updateLightBuffer();
|
|
891
|
-
}
|
|
892
883
|
addLight(direction, color, intensity = 1.0) {
|
|
893
884
|
if (this.lightCount >= 4)
|
|
894
885
|
return false;
|
package/dist/ik-solver.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ik-solver.d.ts","sourceRoot":"","sources":["../src/ik-solver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACzC,OAAO,EAAE,IAAI,EAAU,QAAQ,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAG7D,MAAM,MAAM,mBAAmB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;AAoE/E,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAS;IACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAuB;
|
|
1
|
+
{"version":3,"file":"ik-solver.d.ts","sourceRoot":"","sources":["../src/ik-solver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACzC,OAAO,EAAE,IAAI,EAAU,QAAQ,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAG7D,MAAM,MAAM,mBAAmB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;AAoE/E,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAS;IACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAuB;IAExD,MAAM,CAAC,KAAK,CACV,SAAS,EAAE,QAAQ,EAAE,EACrB,KAAK,EAAE,IAAI,EAAE,EACb,cAAc,EAAE,IAAI,EAAE,EACtB,iBAAiB,EAAE,IAAI,EAAE,EACzB,aAAa,EAAE,IAAI,EAAE,EACrB,WAAW,EAAE,WAAW,EAAE,EAC1B,iBAAiB,CAAC,EAAE,mBAAmB,GACtC,IAAI;IAMP,OAAO,CAAC,MAAM,CAAC,OAAO;IAoFtB,OAAO,CAAC,MAAM,CAAC,UAAU;IAqGzB,OAAO,CAAC,MAAM,CAAC,UAAU;IAYzB,OAAO,CAAC,MAAM,CAAC,WAAW;IAM1B,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAKlC,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAmCjC,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAQ/B,OAAO,CAAC,MAAM,CAAC,wBAAwB;IAqBvC,OAAO,CAAC,MAAM,CAAC,4BAA4B;IAc3C,OAAO,CAAC,MAAM,CAAC,eAAe;IAS9B,OAAO,CAAC,MAAM,CAAC,iBAAiB;CAoCjC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { Engine, type EngineStats } from "./engine";
|
|
2
2
|
export { Model } from "./model";
|
|
3
3
|
export { Vec3, Quat, Mat4 } from "./math";
|
|
4
|
-
export {
|
|
4
|
+
export type { AnimationClip, AnimationPlayOptions, AnimationProgress, BoneKeyframe, MorphKeyframe, BoneInterpolation, ControlPoint, } from "./animation";
|
|
5
|
+
export { FPS } from "./animation";
|
|
5
6
|
export { Physics, type PhysicsOptions } from "./physics";
|
|
7
|
+
export { VMDWriter } from "./vmd-writer";
|
|
6
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACzC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACzC,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,YAAY,GACb,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAA;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { Engine } from "./engine";
|
|
2
2
|
export { Model } from "./model";
|
|
3
3
|
export { Vec3, Quat, Mat4 } from "./math";
|
|
4
|
-
export {
|
|
4
|
+
export { FPS } from "./animation";
|
|
5
5
|
export { Physics } from "./physics";
|
|
6
|
+
export { VMDWriter } from "./vmd-writer";
|
package/dist/model.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Mat4, Quat, Vec3 } from "./math";
|
|
2
2
|
import { Rigidbody, Joint } from "./physics";
|
|
3
|
-
import {
|
|
3
|
+
import { AnimationClip, AnimationPlayOptions, AnimationProgress } from "./animation";
|
|
4
4
|
export interface Texture {
|
|
5
5
|
path: string;
|
|
6
6
|
name: string;
|
|
@@ -145,26 +145,24 @@ export declare class Model {
|
|
|
145
145
|
setMorphWeight(name: string, weight: number, durationMs?: number): void;
|
|
146
146
|
private applyMorphs;
|
|
147
147
|
private buildClipFromVmdKeyFrames;
|
|
148
|
-
|
|
148
|
+
loadVmd(name: string, url: string): Promise<void>;
|
|
149
|
+
loadClip(name: string, clip: AnimationClip): void;
|
|
149
150
|
resetAllBones(): void;
|
|
150
151
|
resetAllMorphs(): void;
|
|
151
|
-
|
|
152
|
+
getClip(name: string): AnimationClip | null;
|
|
153
|
+
exportVmd(name: string): ArrayBuffer;
|
|
152
154
|
play(): void;
|
|
153
155
|
play(name: string): boolean;
|
|
156
|
+
play(name: string, options?: AnimationPlayOptions): boolean;
|
|
154
157
|
show(name: string): void;
|
|
155
158
|
playAnimation(): void;
|
|
156
159
|
pause(): void;
|
|
157
160
|
pauseAnimation(): void;
|
|
158
161
|
stop(): void;
|
|
159
162
|
stopAnimation(): void;
|
|
160
|
-
seek(
|
|
161
|
-
seekAnimation(
|
|
162
|
-
getAnimationProgress():
|
|
163
|
-
current: number;
|
|
164
|
-
duration: number;
|
|
165
|
-
percentage: number;
|
|
166
|
-
animationName: string | null;
|
|
167
|
-
};
|
|
163
|
+
seek(seconds: number): void;
|
|
164
|
+
seekAnimation(seconds: number): void;
|
|
165
|
+
getAnimationProgress(): AnimationProgress;
|
|
168
166
|
private static upperBound;
|
|
169
167
|
private findKeyframeIndex;
|
|
170
168
|
private applyPoseFromClip;
|