reze-engine 0.21.2 → 0.22.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 +5 -1
- package/dist/camera-animation.d.ts +20 -0
- package/dist/camera-animation.d.ts.map +1 -0
- package/dist/camera-animation.js +66 -0
- package/dist/camera.d.ts +12 -0
- package/dist/camera.d.ts.map +1 -1
- package/dist/camera.js +44 -1
- package/dist/engine.d.ts +34 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +101 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/math.d.ts +1 -0
- package/dist/math.d.ts.map +1 -1
- package/dist/math.js +17 -0
- package/dist/model.d.ts +9 -0
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +21 -3
- package/dist/vmd-loader.d.ts +16 -0
- package/dist/vmd-loader.d.ts.map +1 -1
- package/dist/vmd-loader.js +41 -0
- package/package.json +1 -1
- package/src/camera-animation.ts +93 -0
- package/src/camera.ts +45 -1
- package/src/engine.ts +112 -2
- package/src/index.ts +3 -0
- package/src/math.ts +17 -0
- package/src/model.ts +25 -3
- package/src/vmd-loader.ts +54 -0
package/src/vmd-loader.ts
CHANGED
|
@@ -20,6 +20,18 @@ export interface VMDKeyFrame {
|
|
|
20
20
|
morphFrames: MorphFrame[]
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
/** One MMD camera keyframe. The camera looks at `target` from `distance` away, oriented by
|
|
24
|
+
* `rotation` (euler radians), with `fov` degrees. `interpolation` is 24 bytes: 6 channels
|
|
25
|
+
* (posX, posY, posZ, rotation, distance, fov) × 4 bezier bytes (x1, x2, y1, y2). */
|
|
26
|
+
export interface CameraKeyframe {
|
|
27
|
+
frame: number
|
|
28
|
+
distance: number
|
|
29
|
+
target: Vec3
|
|
30
|
+
rotation: Vec3 // euler radians
|
|
31
|
+
fov: number // degrees
|
|
32
|
+
interpolation: Uint8Array // 24 bytes
|
|
33
|
+
}
|
|
34
|
+
|
|
23
35
|
export class VMDLoader {
|
|
24
36
|
private view: DataView
|
|
25
37
|
private offset = 0
|
|
@@ -46,6 +58,48 @@ export class VMDLoader {
|
|
|
46
58
|
return loader.parse()
|
|
47
59
|
}
|
|
48
60
|
|
|
61
|
+
/** Parse only the camera track (a dedicated camera VMD, or the camera block of any VMD).
|
|
62
|
+
* Returns [] if the file has no camera block (motion-only VMDs end after the morph block). */
|
|
63
|
+
static async loadCamera(url: string): Promise<CameraKeyframe[]> {
|
|
64
|
+
const loader = new VMDLoader(await fetch(url).then((r) => r.arrayBuffer()))
|
|
65
|
+
return loader.parseCamera()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static loadCameraFromBuffer(buffer: ArrayBuffer): CameraKeyframe[] {
|
|
69
|
+
return new VMDLoader(buffer).parseCamera()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Seek past the bone + morph blocks (fixed record sizes) to the camera block, then read it.
|
|
73
|
+
// bone frame = 111 B (15 name + 4 frame + 12 pos + 16 rot + 64 interp); morph = 23 B
|
|
74
|
+
// (15 name + 4 frame + 4 weight); camera = 61 B.
|
|
75
|
+
private parseCamera(): CameraKeyframe[] {
|
|
76
|
+
this.offset = 0
|
|
77
|
+
const header = this.getString(30)
|
|
78
|
+
if (!header.startsWith("Vocaloid Motion Data")) throw new Error("Invalid VMD file header")
|
|
79
|
+
this.skip(20)
|
|
80
|
+
const boneCount = this.getUint32()
|
|
81
|
+
this.skip(boneCount * 111)
|
|
82
|
+
const morphCount = this.getUint32()
|
|
83
|
+
this.skip(morphCount * 23)
|
|
84
|
+
if (this.offset + 4 > this.view.buffer.byteLength) return [] // no camera block
|
|
85
|
+
const cameraCount = this.getUint32()
|
|
86
|
+
|
|
87
|
+
const frames: CameraKeyframe[] = []
|
|
88
|
+
for (let i = 0; i < cameraCount; i++) {
|
|
89
|
+
const frame = this.getUint32()
|
|
90
|
+
const distance = this.getFloat32()
|
|
91
|
+
const target = new Vec3(this.getFloat32(), this.getFloat32(), this.getFloat32())
|
|
92
|
+
const rotation = new Vec3(this.getFloat32(), this.getFloat32(), this.getFloat32())
|
|
93
|
+
const interpolation = new Uint8Array(24)
|
|
94
|
+
for (let j = 0; j < 24; j++) interpolation[j] = this.getUint8()
|
|
95
|
+
const fov = this.getUint32()
|
|
96
|
+
this.skip(1) // perspective flag (0 = perspective) — unused
|
|
97
|
+
frames.push({ frame, distance, target, rotation, fov, interpolation })
|
|
98
|
+
}
|
|
99
|
+
frames.sort((a, b) => a.frame - b.frame)
|
|
100
|
+
return frames
|
|
101
|
+
}
|
|
102
|
+
|
|
49
103
|
private parse(): VMDKeyFrame[] {
|
|
50
104
|
// Read header (30 bytes)
|
|
51
105
|
const header = this.getString(30)
|