reze-engine 0.3.11 → 0.3.13
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/dist/bezier-interpolate.d.ts +15 -0
- package/dist/bezier-interpolate.d.ts.map +1 -0
- package/dist/bezier-interpolate.js +40 -0
- package/dist/engine.d.ts +3 -8
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +23 -34
- package/dist/ik.d.ts +32 -0
- package/dist/ik.d.ts.map +1 -0
- package/dist/ik.js +337 -0
- package/dist/pool-scene.d.ts +52 -0
- package/dist/pool-scene.d.ts.map +1 -0
- package/dist/pool-scene.js +1122 -0
- package/dist/pool.d.ts +38 -0
- package/dist/pool.d.ts.map +1 -0
- package/dist/pool.js +422 -0
- package/dist/rzm-converter.d.ts +12 -0
- package/dist/rzm-converter.d.ts.map +1 -0
- package/dist/rzm-converter.js +40 -0
- package/dist/rzm-loader.d.ts +24 -0
- package/dist/rzm-loader.d.ts.map +1 -0
- package/dist/rzm-loader.js +488 -0
- package/dist/rzm-writer.d.ts +27 -0
- package/dist/rzm-writer.d.ts.map +1 -0
- package/dist/rzm-writer.js +701 -0
- package/package.json +1 -1
- package/src/engine.ts +32 -32
- package/src/player.ts +0 -290
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import { Model, } from "./model";
|
|
2
|
+
import { Vec3, Mat4 } from "./math";
|
|
3
|
+
/**
|
|
4
|
+
* RZM (Reze Model) Binary Format Loader
|
|
5
|
+
*
|
|
6
|
+
* Reads the RZM binary format and reconstructs a Model
|
|
7
|
+
*/
|
|
8
|
+
var SectionType;
|
|
9
|
+
(function (SectionType) {
|
|
10
|
+
SectionType[SectionType["GEOMETRY"] = 1] = "GEOMETRY";
|
|
11
|
+
SectionType[SectionType["SKELETON"] = 2] = "SKELETON";
|
|
12
|
+
SectionType[SectionType["SKINNING"] = 3] = "SKINNING";
|
|
13
|
+
SectionType[SectionType["MORPHING"] = 4] = "MORPHING";
|
|
14
|
+
SectionType[SectionType["MATERIALS"] = 5] = "MATERIALS";
|
|
15
|
+
SectionType[SectionType["TEXTURES"] = 6] = "TEXTURES";
|
|
16
|
+
SectionType[SectionType["PHYSICS"] = 7] = "PHYSICS";
|
|
17
|
+
})(SectionType || (SectionType = {}));
|
|
18
|
+
export class RzmLoader {
|
|
19
|
+
constructor(buffer) {
|
|
20
|
+
this.offset = 0;
|
|
21
|
+
this.sections = new Map();
|
|
22
|
+
this.view = new DataView(buffer);
|
|
23
|
+
}
|
|
24
|
+
static async load(url) {
|
|
25
|
+
const response = await fetch(url);
|
|
26
|
+
const buffer = await response.arrayBuffer();
|
|
27
|
+
const loader = new RzmLoader(buffer);
|
|
28
|
+
return loader.parse();
|
|
29
|
+
}
|
|
30
|
+
static loadFromBuffer(buffer) {
|
|
31
|
+
const loader = new RzmLoader(buffer);
|
|
32
|
+
return loader.parse();
|
|
33
|
+
}
|
|
34
|
+
parse() {
|
|
35
|
+
this.parseHeader();
|
|
36
|
+
this.parseSectionTable();
|
|
37
|
+
// Parse all sections
|
|
38
|
+
const geometry = this.parseGeometry();
|
|
39
|
+
const skeleton = this.parseSkeleton();
|
|
40
|
+
const skinning = this.parseSkinning();
|
|
41
|
+
const morphing = this.parseMorphing();
|
|
42
|
+
const materials = this.parseMaterials();
|
|
43
|
+
const textures = this.parseTextures();
|
|
44
|
+
const physics = this.parsePhysics();
|
|
45
|
+
// Create new arrays with ArrayBuffer to satisfy type requirements
|
|
46
|
+
const vertexData = new Float32Array(geometry.vertexData.length);
|
|
47
|
+
vertexData.set(geometry.vertexData);
|
|
48
|
+
const indexData = new Uint32Array(geometry.indexData.length);
|
|
49
|
+
indexData.set(geometry.indexData);
|
|
50
|
+
return new Model(vertexData, indexData, textures, materials, skeleton, skinning, morphing, physics.rigidbodies, physics.joints);
|
|
51
|
+
}
|
|
52
|
+
parseHeader() {
|
|
53
|
+
// Read magic
|
|
54
|
+
const magic = String.fromCharCode(this.view.getUint8(0), this.view.getUint8(1), this.view.getUint8(2), this.view.getUint8(3));
|
|
55
|
+
if (magic !== RzmLoader.MAGIC) {
|
|
56
|
+
throw new Error(`Invalid RZM file: expected magic "${RzmLoader.MAGIC}", got "${magic}"`);
|
|
57
|
+
}
|
|
58
|
+
this.offset = 4;
|
|
59
|
+
const version = this.view.getUint32(this.offset, true);
|
|
60
|
+
if (version !== RzmLoader.VERSION) {
|
|
61
|
+
throw new Error(`Unsupported RZM version: ${version}, expected ${RzmLoader.VERSION}`);
|
|
62
|
+
}
|
|
63
|
+
this.offset += 4;
|
|
64
|
+
// Skip file size (uint64)
|
|
65
|
+
this.offset += 8;
|
|
66
|
+
// Skip section count (will be read from section table)
|
|
67
|
+
this.offset += 4;
|
|
68
|
+
// Skip reserved (16 bytes)
|
|
69
|
+
this.offset += 16;
|
|
70
|
+
}
|
|
71
|
+
parseSectionTable() {
|
|
72
|
+
const sectionCount = this.view.getUint32(12, true); // Section count is at offset 12
|
|
73
|
+
this.offset = RzmLoader.HEADER_SIZE;
|
|
74
|
+
for (let i = 0; i < sectionCount; i++) {
|
|
75
|
+
const type = this.view.getUint32(this.offset, true);
|
|
76
|
+
this.offset += 4;
|
|
77
|
+
const offset = Number(this.view.getBigUint64(this.offset, true));
|
|
78
|
+
this.offset += 8;
|
|
79
|
+
const size = Number(this.view.getBigUint64(this.offset, true));
|
|
80
|
+
this.offset += 8;
|
|
81
|
+
this.sections.set(type, { type, offset, size });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
parseGeometry() {
|
|
85
|
+
const section = this.sections.get(SectionType.GEOMETRY);
|
|
86
|
+
if (!section)
|
|
87
|
+
throw new Error("Missing GEOMETRY section");
|
|
88
|
+
this.offset = section.offset;
|
|
89
|
+
const vertexCount = this.view.getUint32(this.offset, true);
|
|
90
|
+
this.offset += 4;
|
|
91
|
+
const vertexData = new Float32Array(this.view.buffer.slice(this.offset, this.offset + vertexCount * 8 * 4));
|
|
92
|
+
this.offset += vertexCount * 8 * 4;
|
|
93
|
+
const indexCount = this.view.getUint32(this.offset, true);
|
|
94
|
+
this.offset += 4;
|
|
95
|
+
const indexData = new Uint32Array(this.view.buffer.slice(this.offset, this.offset + indexCount * 4));
|
|
96
|
+
this.offset += indexCount * 4;
|
|
97
|
+
return { vertexData, indexData };
|
|
98
|
+
}
|
|
99
|
+
parseSkeleton() {
|
|
100
|
+
const section = this.sections.get(SectionType.SKELETON);
|
|
101
|
+
if (!section)
|
|
102
|
+
throw new Error("Missing SKELETON section");
|
|
103
|
+
this.offset = section.offset;
|
|
104
|
+
const boneCount = this.view.getUint32(this.offset, true);
|
|
105
|
+
this.offset += 4;
|
|
106
|
+
const bones = [];
|
|
107
|
+
for (let i = 0; i < boneCount; i++) {
|
|
108
|
+
const nameLen = this.view.getUint32(this.offset, true);
|
|
109
|
+
this.offset += 4;
|
|
110
|
+
const nameBytes = new Uint8Array(this.view.buffer, this.offset, nameLen);
|
|
111
|
+
const name = new TextDecoder().decode(nameBytes);
|
|
112
|
+
this.offset += nameLen;
|
|
113
|
+
const parentIndex = this.view.getInt32(this.offset, true);
|
|
114
|
+
this.offset += 4;
|
|
115
|
+
const bindTranslation = [
|
|
116
|
+
this.view.getFloat32(this.offset, true),
|
|
117
|
+
this.view.getFloat32(this.offset + 4, true),
|
|
118
|
+
this.view.getFloat32(this.offset + 8, true),
|
|
119
|
+
];
|
|
120
|
+
this.offset += 12;
|
|
121
|
+
const appendParentIndex = this.view.getInt32(this.offset, true);
|
|
122
|
+
this.offset += 4;
|
|
123
|
+
const appendRatio = this.view.getFloat32(this.offset, true);
|
|
124
|
+
this.offset += 4;
|
|
125
|
+
const appendRotate = this.view.getUint8(this.offset) === 1;
|
|
126
|
+
this.offset += 1;
|
|
127
|
+
const appendMove = this.view.getUint8(this.offset) === 1;
|
|
128
|
+
this.offset += 1;
|
|
129
|
+
const ikTargetIndex = this.view.getInt32(this.offset, true);
|
|
130
|
+
this.offset += 4;
|
|
131
|
+
const ikIteration = this.view.getInt32(this.offset, true);
|
|
132
|
+
this.offset += 4;
|
|
133
|
+
const ikLimitAngle = this.view.getFloat32(this.offset, true);
|
|
134
|
+
this.offset += 4;
|
|
135
|
+
const ikLinkCount = this.view.getUint32(this.offset, true);
|
|
136
|
+
this.offset += 4;
|
|
137
|
+
const ikLinks = [];
|
|
138
|
+
for (let j = 0; j < ikLinkCount; j++) {
|
|
139
|
+
const boneIndex = this.view.getInt32(this.offset, true);
|
|
140
|
+
this.offset += 4;
|
|
141
|
+
const hasLimit = this.view.getUint8(this.offset) === 1;
|
|
142
|
+
this.offset += 1;
|
|
143
|
+
let minAngle = undefined;
|
|
144
|
+
let maxAngle = undefined;
|
|
145
|
+
if (hasLimit) {
|
|
146
|
+
minAngle = new Vec3(this.view.getFloat32(this.offset, true), this.view.getFloat32(this.offset + 4, true), this.view.getFloat32(this.offset + 8, true));
|
|
147
|
+
this.offset += 12;
|
|
148
|
+
maxAngle = new Vec3(this.view.getFloat32(this.offset, true), this.view.getFloat32(this.offset + 4, true), this.view.getFloat32(this.offset + 8, true));
|
|
149
|
+
this.offset += 12;
|
|
150
|
+
}
|
|
151
|
+
ikLinks.push({ boneIndex, hasLimit, minAngle, maxAngle });
|
|
152
|
+
}
|
|
153
|
+
const bone = {
|
|
154
|
+
name,
|
|
155
|
+
parentIndex: parentIndex >= 0 ? parentIndex : -1,
|
|
156
|
+
bindTranslation,
|
|
157
|
+
children: [], // Will be populated later
|
|
158
|
+
appendParentIndex: appendParentIndex >= 0 ? appendParentIndex : undefined,
|
|
159
|
+
appendRatio: appendRatio !== 0 ? appendRatio : undefined,
|
|
160
|
+
appendRotate: appendRotate || undefined,
|
|
161
|
+
appendMove: appendMove || undefined,
|
|
162
|
+
ikTargetIndex: ikTargetIndex >= 0 ? ikTargetIndex : undefined,
|
|
163
|
+
ikIteration: ikIteration > 0 ? ikIteration : undefined,
|
|
164
|
+
ikLimitAngle: ikLimitAngle > 0 ? ikLimitAngle : undefined,
|
|
165
|
+
ikLinks: ikLinks.length > 0 ? ikLinks : undefined,
|
|
166
|
+
};
|
|
167
|
+
bones.push(bone);
|
|
168
|
+
}
|
|
169
|
+
// Read inverse bind matrices
|
|
170
|
+
const invBindMatrices = new Float32Array(this.view.buffer.slice(this.offset, this.offset + boneCount * 16 * 4));
|
|
171
|
+
return { bones, inverseBindMatrices: invBindMatrices };
|
|
172
|
+
}
|
|
173
|
+
parseSkinning() {
|
|
174
|
+
const section = this.sections.get(SectionType.SKINNING);
|
|
175
|
+
if (!section)
|
|
176
|
+
throw new Error("Missing SKINNING section");
|
|
177
|
+
this.offset = section.offset;
|
|
178
|
+
const jointsLength = this.view.getUint32(this.offset, true);
|
|
179
|
+
this.offset += 4;
|
|
180
|
+
const joints = new Uint16Array(this.view.buffer, this.offset, jointsLength);
|
|
181
|
+
this.offset += jointsLength * 2;
|
|
182
|
+
const weightsLength = this.view.getUint32(this.offset, true);
|
|
183
|
+
this.offset += 4;
|
|
184
|
+
const weights = new Uint8Array(this.view.buffer, this.offset, weightsLength);
|
|
185
|
+
this.offset += weightsLength;
|
|
186
|
+
return { joints, weights };
|
|
187
|
+
}
|
|
188
|
+
parseMorphing() {
|
|
189
|
+
const section = this.sections.get(SectionType.MORPHING);
|
|
190
|
+
if (!section)
|
|
191
|
+
throw new Error("Missing MORPHING section");
|
|
192
|
+
this.offset = section.offset;
|
|
193
|
+
const morphCount = this.view.getUint32(this.offset, true);
|
|
194
|
+
this.offset += 4;
|
|
195
|
+
const morphs = [];
|
|
196
|
+
for (let i = 0; i < morphCount; i++) {
|
|
197
|
+
const nameLen = this.view.getUint32(this.offset, true);
|
|
198
|
+
this.offset += 4;
|
|
199
|
+
const nameBytes = new Uint8Array(this.view.buffer, this.offset, nameLen);
|
|
200
|
+
const name = new TextDecoder().decode(nameBytes);
|
|
201
|
+
this.offset += nameLen;
|
|
202
|
+
const type = this.view.getUint8(this.offset);
|
|
203
|
+
this.offset += 1;
|
|
204
|
+
const vertexOffsetCount = this.view.getUint32(this.offset, true);
|
|
205
|
+
this.offset += 4;
|
|
206
|
+
const vertexOffsets = [];
|
|
207
|
+
for (let j = 0; j < vertexOffsetCount; j++) {
|
|
208
|
+
const vertexIndex = this.view.getUint32(this.offset, true);
|
|
209
|
+
this.offset += 4;
|
|
210
|
+
const positionOffset = [
|
|
211
|
+
this.view.getFloat32(this.offset, true),
|
|
212
|
+
this.view.getFloat32(this.offset + 4, true),
|
|
213
|
+
this.view.getFloat32(this.offset + 8, true),
|
|
214
|
+
];
|
|
215
|
+
this.offset += 12;
|
|
216
|
+
vertexOffsets.push({ vertexIndex, positionOffset });
|
|
217
|
+
}
|
|
218
|
+
const groupRefCount = this.view.getUint32(this.offset, true);
|
|
219
|
+
this.offset += 4;
|
|
220
|
+
const groupReferences = [];
|
|
221
|
+
for (let j = 0; j < groupRefCount; j++) {
|
|
222
|
+
const morphIndex = this.view.getInt32(this.offset, true);
|
|
223
|
+
this.offset += 4;
|
|
224
|
+
const ratio = this.view.getFloat32(this.offset, true);
|
|
225
|
+
this.offset += 4;
|
|
226
|
+
groupReferences.push({ morphIndex, ratio });
|
|
227
|
+
}
|
|
228
|
+
morphs.push({
|
|
229
|
+
name,
|
|
230
|
+
type,
|
|
231
|
+
vertexOffsets,
|
|
232
|
+
groupReferences: groupReferences.length > 0 ? groupReferences : undefined,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
// Read offsets buffer
|
|
236
|
+
const vertexCount = this.view.getUint32(this.sections.get(SectionType.GEOMETRY).offset, true);
|
|
237
|
+
const offsetsBufferSize = morphCount * vertexCount * 3;
|
|
238
|
+
const offsetsBuffer = new Float32Array(this.view.buffer, this.offset, offsetsBufferSize);
|
|
239
|
+
return { morphs, offsetsBuffer };
|
|
240
|
+
}
|
|
241
|
+
parseMaterials() {
|
|
242
|
+
const section = this.sections.get(SectionType.MATERIALS);
|
|
243
|
+
if (!section)
|
|
244
|
+
throw new Error("Missing MATERIALS section");
|
|
245
|
+
this.offset = section.offset;
|
|
246
|
+
const materialCount = this.view.getUint32(this.offset, true);
|
|
247
|
+
this.offset += 4;
|
|
248
|
+
const materials = [];
|
|
249
|
+
for (let i = 0; i < materialCount; i++) {
|
|
250
|
+
const nameLen = this.view.getUint32(this.offset, true);
|
|
251
|
+
this.offset += 4;
|
|
252
|
+
const nameBytes = new Uint8Array(this.view.buffer, this.offset, nameLen);
|
|
253
|
+
const name = new TextDecoder().decode(nameBytes);
|
|
254
|
+
this.offset += nameLen;
|
|
255
|
+
const diffuse = [
|
|
256
|
+
this.view.getFloat32(this.offset, true),
|
|
257
|
+
this.view.getFloat32(this.offset + 4, true),
|
|
258
|
+
this.view.getFloat32(this.offset + 8, true),
|
|
259
|
+
this.view.getFloat32(this.offset + 12, true),
|
|
260
|
+
];
|
|
261
|
+
this.offset += 16;
|
|
262
|
+
const specular = [
|
|
263
|
+
this.view.getFloat32(this.offset, true),
|
|
264
|
+
this.view.getFloat32(this.offset + 4, true),
|
|
265
|
+
this.view.getFloat32(this.offset + 8, true),
|
|
266
|
+
];
|
|
267
|
+
this.offset += 12;
|
|
268
|
+
const shininess = this.view.getFloat32(this.offset, true);
|
|
269
|
+
this.offset += 4;
|
|
270
|
+
const ambient = [
|
|
271
|
+
this.view.getFloat32(this.offset, true),
|
|
272
|
+
this.view.getFloat32(this.offset + 4, true),
|
|
273
|
+
this.view.getFloat32(this.offset + 8, true),
|
|
274
|
+
];
|
|
275
|
+
this.offset += 12;
|
|
276
|
+
const diffuseTextureIndex = this.view.getInt32(this.offset, true);
|
|
277
|
+
this.offset += 4;
|
|
278
|
+
const normalTextureIndex = this.view.getInt32(this.offset, true);
|
|
279
|
+
this.offset += 4;
|
|
280
|
+
const sphereTextureIndex = this.view.getInt32(this.offset, true);
|
|
281
|
+
this.offset += 4;
|
|
282
|
+
const sphereMode = this.view.getUint8(this.offset);
|
|
283
|
+
this.offset += 1;
|
|
284
|
+
const toonTextureIndex = this.view.getInt32(this.offset, true);
|
|
285
|
+
this.offset += 4;
|
|
286
|
+
const edgeFlag = this.view.getUint8(this.offset);
|
|
287
|
+
this.offset += 1;
|
|
288
|
+
const edgeColor = [
|
|
289
|
+
this.view.getFloat32(this.offset, true),
|
|
290
|
+
this.view.getFloat32(this.offset + 4, true),
|
|
291
|
+
this.view.getFloat32(this.offset + 8, true),
|
|
292
|
+
this.view.getFloat32(this.offset + 12, true),
|
|
293
|
+
];
|
|
294
|
+
this.offset += 16;
|
|
295
|
+
const edgeSize = this.view.getFloat32(this.offset, true);
|
|
296
|
+
this.offset += 4;
|
|
297
|
+
const vertexCount = this.view.getUint32(this.offset, true);
|
|
298
|
+
this.offset += 4;
|
|
299
|
+
const isEye = this.view.getUint8(this.offset) === 1;
|
|
300
|
+
this.offset += 1;
|
|
301
|
+
const isFace = this.view.getUint8(this.offset) === 1;
|
|
302
|
+
this.offset += 1;
|
|
303
|
+
const isHair = this.view.getUint8(this.offset) === 1;
|
|
304
|
+
this.offset += 1;
|
|
305
|
+
materials.push({
|
|
306
|
+
name,
|
|
307
|
+
diffuse,
|
|
308
|
+
specular,
|
|
309
|
+
ambient,
|
|
310
|
+
shininess,
|
|
311
|
+
diffuseTextureIndex,
|
|
312
|
+
normalTextureIndex,
|
|
313
|
+
sphereTextureIndex,
|
|
314
|
+
sphereMode,
|
|
315
|
+
toonTextureIndex,
|
|
316
|
+
edgeFlag,
|
|
317
|
+
edgeColor,
|
|
318
|
+
edgeSize,
|
|
319
|
+
vertexCount,
|
|
320
|
+
isEye,
|
|
321
|
+
isFace,
|
|
322
|
+
isHair,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
return materials;
|
|
326
|
+
}
|
|
327
|
+
parseTextures() {
|
|
328
|
+
const section = this.sections.get(SectionType.TEXTURES);
|
|
329
|
+
if (!section)
|
|
330
|
+
throw new Error("Missing TEXTURES section");
|
|
331
|
+
this.offset = section.offset;
|
|
332
|
+
const textureCount = this.view.getUint32(this.offset, true);
|
|
333
|
+
this.offset += 4;
|
|
334
|
+
const textures = [];
|
|
335
|
+
for (let i = 0; i < textureCount; i++) {
|
|
336
|
+
const nameLen = this.view.getUint32(this.offset, true);
|
|
337
|
+
this.offset += 4;
|
|
338
|
+
const nameBytes = new Uint8Array(this.view.buffer, this.offset, nameLen);
|
|
339
|
+
const name = new TextDecoder().decode(nameBytes);
|
|
340
|
+
this.offset += nameLen;
|
|
341
|
+
const pathLen = this.view.getUint32(this.offset, true);
|
|
342
|
+
this.offset += 4;
|
|
343
|
+
const pathBytes = new Uint8Array(this.view.buffer, this.offset, pathLen);
|
|
344
|
+
const path = new TextDecoder().decode(pathBytes);
|
|
345
|
+
this.offset += pathLen;
|
|
346
|
+
// Read width, height, format, dataSize, and extract embedded data
|
|
347
|
+
const width = this.view.getUint32(this.offset, true);
|
|
348
|
+
this.offset += 4;
|
|
349
|
+
const height = this.view.getUint32(this.offset, true);
|
|
350
|
+
this.offset += 4;
|
|
351
|
+
const format = this.view.getUint8(this.offset);
|
|
352
|
+
this.offset += 1;
|
|
353
|
+
const dataSize = this.view.getUint32(this.offset, true);
|
|
354
|
+
this.offset += 4;
|
|
355
|
+
// Extract embedded texture data
|
|
356
|
+
let textureData = undefined;
|
|
357
|
+
if (dataSize > 0) {
|
|
358
|
+
textureData = this.view.buffer.slice(this.offset, this.offset + dataSize);
|
|
359
|
+
}
|
|
360
|
+
this.offset += dataSize;
|
|
361
|
+
textures.push({ name, path, data: textureData });
|
|
362
|
+
}
|
|
363
|
+
return textures;
|
|
364
|
+
}
|
|
365
|
+
parsePhysics() {
|
|
366
|
+
const section = this.sections.get(SectionType.PHYSICS);
|
|
367
|
+
if (!section) {
|
|
368
|
+
return { rigidbodies: [], joints: [] };
|
|
369
|
+
}
|
|
370
|
+
this.offset = section.offset;
|
|
371
|
+
const rigidbodyCount = this.view.getUint32(this.offset, true);
|
|
372
|
+
this.offset += 4;
|
|
373
|
+
const rigidbodies = [];
|
|
374
|
+
for (let i = 0; i < rigidbodyCount; i++) {
|
|
375
|
+
const nameLen = this.view.getUint32(this.offset, true);
|
|
376
|
+
this.offset += 4;
|
|
377
|
+
const nameBytes = new Uint8Array(this.view.buffer, this.offset, nameLen);
|
|
378
|
+
const name = new TextDecoder().decode(nameBytes);
|
|
379
|
+
this.offset += nameLen;
|
|
380
|
+
const englishNameLen = this.view.getUint32(this.offset, true);
|
|
381
|
+
this.offset += 4;
|
|
382
|
+
const englishNameBytes = new Uint8Array(this.view.buffer, this.offset, englishNameLen);
|
|
383
|
+
const englishName = new TextDecoder().decode(englishNameBytes);
|
|
384
|
+
this.offset += englishNameLen;
|
|
385
|
+
const boneIndex = this.view.getInt32(this.offset, true);
|
|
386
|
+
this.offset += 4;
|
|
387
|
+
const group = this.view.getUint8(this.offset);
|
|
388
|
+
this.offset += 1;
|
|
389
|
+
const collisionMask = this.view.getUint16(this.offset, true);
|
|
390
|
+
this.offset += 2;
|
|
391
|
+
const shape = this.view.getUint8(this.offset);
|
|
392
|
+
this.offset += 1;
|
|
393
|
+
const size = new Vec3(this.view.getFloat32(this.offset, true), this.view.getFloat32(this.offset + 4, true), this.view.getFloat32(this.offset + 8, true));
|
|
394
|
+
this.offset += 12;
|
|
395
|
+
const shapePosition = new Vec3(this.view.getFloat32(this.offset, true), this.view.getFloat32(this.offset + 4, true), this.view.getFloat32(this.offset + 8, true));
|
|
396
|
+
this.offset += 12;
|
|
397
|
+
const shapeRotation = new Vec3(this.view.getFloat32(this.offset, true), this.view.getFloat32(this.offset + 4, true), this.view.getFloat32(this.offset + 8, true));
|
|
398
|
+
this.offset += 12;
|
|
399
|
+
const mass = this.view.getFloat32(this.offset, true);
|
|
400
|
+
this.offset += 4;
|
|
401
|
+
const linearDamping = this.view.getFloat32(this.offset, true);
|
|
402
|
+
this.offset += 4;
|
|
403
|
+
const angularDamping = this.view.getFloat32(this.offset, true);
|
|
404
|
+
this.offset += 4;
|
|
405
|
+
const restitution = this.view.getFloat32(this.offset, true);
|
|
406
|
+
this.offset += 4;
|
|
407
|
+
const friction = this.view.getFloat32(this.offset, true);
|
|
408
|
+
this.offset += 4;
|
|
409
|
+
const type = this.view.getUint8(this.offset);
|
|
410
|
+
this.offset += 1;
|
|
411
|
+
rigidbodies.push({
|
|
412
|
+
name,
|
|
413
|
+
englishName,
|
|
414
|
+
boneIndex,
|
|
415
|
+
group,
|
|
416
|
+
collisionMask,
|
|
417
|
+
shape,
|
|
418
|
+
size,
|
|
419
|
+
shapePosition,
|
|
420
|
+
shapeRotation,
|
|
421
|
+
mass,
|
|
422
|
+
linearDamping,
|
|
423
|
+
angularDamping,
|
|
424
|
+
restitution,
|
|
425
|
+
friction,
|
|
426
|
+
type,
|
|
427
|
+
bodyOffsetMatrixInverse: Mat4.identity(),
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
const jointCount = this.view.getUint32(this.offset, true);
|
|
431
|
+
this.offset += 4;
|
|
432
|
+
const joints = [];
|
|
433
|
+
for (let i = 0; i < jointCount; i++) {
|
|
434
|
+
const nameLen = this.view.getUint32(this.offset, true);
|
|
435
|
+
this.offset += 4;
|
|
436
|
+
const nameBytes = new Uint8Array(this.view.buffer, this.offset, nameLen);
|
|
437
|
+
const name = new TextDecoder().decode(nameBytes);
|
|
438
|
+
this.offset += nameLen;
|
|
439
|
+
const englishNameLen = this.view.getUint32(this.offset, true);
|
|
440
|
+
this.offset += 4;
|
|
441
|
+
const englishNameBytes = new Uint8Array(this.view.buffer, this.offset, englishNameLen);
|
|
442
|
+
const englishName = new TextDecoder().decode(englishNameBytes);
|
|
443
|
+
this.offset += englishNameLen;
|
|
444
|
+
const type = this.view.getUint8(this.offset);
|
|
445
|
+
this.offset += 1;
|
|
446
|
+
const rigidbodyIndexA = this.view.getInt32(this.offset, true);
|
|
447
|
+
this.offset += 4;
|
|
448
|
+
const rigidbodyIndexB = this.view.getInt32(this.offset, true);
|
|
449
|
+
this.offset += 4;
|
|
450
|
+
const position = new Vec3(this.view.getFloat32(this.offset, true), this.view.getFloat32(this.offset + 4, true), this.view.getFloat32(this.offset + 8, true));
|
|
451
|
+
this.offset += 12;
|
|
452
|
+
const rotation = new Vec3(this.view.getFloat32(this.offset, true), this.view.getFloat32(this.offset + 4, true), this.view.getFloat32(this.offset + 8, true));
|
|
453
|
+
this.offset += 12;
|
|
454
|
+
const positionMin = new Vec3(this.view.getFloat32(this.offset, true), this.view.getFloat32(this.offset + 4, true), this.view.getFloat32(this.offset + 8, true));
|
|
455
|
+
this.offset += 12;
|
|
456
|
+
const positionMax = new Vec3(this.view.getFloat32(this.offset, true), this.view.getFloat32(this.offset + 4, true), this.view.getFloat32(this.offset + 8, true));
|
|
457
|
+
this.offset += 12;
|
|
458
|
+
const rotationMin = new Vec3(this.view.getFloat32(this.offset, true), this.view.getFloat32(this.offset + 4, true), this.view.getFloat32(this.offset + 8, true));
|
|
459
|
+
this.offset += 12;
|
|
460
|
+
const rotationMax = new Vec3(this.view.getFloat32(this.offset, true), this.view.getFloat32(this.offset + 4, true), this.view.getFloat32(this.offset + 8, true));
|
|
461
|
+
this.offset += 12;
|
|
462
|
+
const springPosition = new Vec3(this.view.getFloat32(this.offset, true), this.view.getFloat32(this.offset + 4, true), this.view.getFloat32(this.offset + 8, true));
|
|
463
|
+
this.offset += 12;
|
|
464
|
+
const springRotation = new Vec3(this.view.getFloat32(this.offset, true), this.view.getFloat32(this.offset + 4, true), this.view.getFloat32(this.offset + 8, true));
|
|
465
|
+
this.offset += 12;
|
|
466
|
+
joints.push({
|
|
467
|
+
name,
|
|
468
|
+
englishName,
|
|
469
|
+
type,
|
|
470
|
+
rigidbodyIndexA,
|
|
471
|
+
rigidbodyIndexB,
|
|
472
|
+
position,
|
|
473
|
+
rotation,
|
|
474
|
+
positionMin,
|
|
475
|
+
positionMax,
|
|
476
|
+
rotationMin,
|
|
477
|
+
rotationMax,
|
|
478
|
+
springPosition,
|
|
479
|
+
springRotation,
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
return { rigidbodies, joints };
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
RzmLoader.HEADER_SIZE = 36;
|
|
486
|
+
RzmLoader.SECTION_TABLE_ENTRY_SIZE = 20;
|
|
487
|
+
RzmLoader.MAGIC = "RZM\0";
|
|
488
|
+
RzmLoader.VERSION = 1;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Model } from "./model";
|
|
2
|
+
export declare class RzmWriter {
|
|
3
|
+
private sections;
|
|
4
|
+
private currentOffset;
|
|
5
|
+
private static readonly HEADER_SIZE;
|
|
6
|
+
private static readonly SECTION_TABLE_ENTRY_SIZE;
|
|
7
|
+
private static readonly MAGIC;
|
|
8
|
+
private static readonly VERSION;
|
|
9
|
+
/**
|
|
10
|
+
* Convert a Model to RZM binary format
|
|
11
|
+
* @param model The model to convert
|
|
12
|
+
* @param textureData Map of texture paths to their binary data (PNG/JPEG bytes)
|
|
13
|
+
* @returns RZM binary data as ArrayBuffer
|
|
14
|
+
*/
|
|
15
|
+
static write(model: Model, textureData: Map<string, ArrayBuffer>): Promise<ArrayBuffer>;
|
|
16
|
+
private writeModel;
|
|
17
|
+
private writeGeometry;
|
|
18
|
+
private writeSkeleton;
|
|
19
|
+
private writeSkinning;
|
|
20
|
+
private writeMorphing;
|
|
21
|
+
private writeMaterials;
|
|
22
|
+
private writeTextures;
|
|
23
|
+
private writePhysics;
|
|
24
|
+
private addSection;
|
|
25
|
+
private finalize;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=rzm-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rzm-writer.d.ts","sourceRoot":"","sources":["../src/rzm-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAgE,MAAM,SAAS,CAAA;AA4C7F,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,aAAa,CAAI;IAGzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAK;IACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAK;IACrD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAU;IACvC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAI;IAEnC;;;;;OAKG;WACU,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;YAM/E,UAAU;IAiBxB,OAAO,CAAC,aAAa;IAwBrB,OAAO,CAAC,aAAa;IA2GrB,OAAO,CAAC,aAAa;IAyBrB,OAAO,CAAC,aAAa;IAqFrB,OAAO,CAAC,cAAc;YAgGR,aAAa;IAqH3B,OAAO,CAAC,YAAY;IA+NpB,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,QAAQ;CA2CjB"}
|