@doki-land/live2d-renderer 0.0.0 → 0.0.12

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.
@@ -0,0 +1,534 @@
1
+ /**
2
+ * Official MOC3 section layout (clean-room).
3
+ *
4
+ * Header (64) + Section Offset Table (160 × u32) + body arrays.
5
+ * Layout order follows public MOC3 memory-map descriptions (OpenL2D hexpat /
6
+ * independent format notes). Deformer evaluation is deferred — default pose
7
+ * uses each art mesh's first keyform only.
8
+ */
9
+
10
+ export const MOC3_MAGIC = "MOC3";
11
+ export const MOC3_HEADER_SIZE = 64;
12
+ export const MOC3_SOT_COUNT = 160;
13
+ export const MOC3_COUNT_MAX = 23;
14
+
15
+ export const Moc3Version = {
16
+ V3_00: 1,
17
+ V3_03: 2,
18
+ V4_00: 3,
19
+ V4_02: 4,
20
+ V5_00: 5,
21
+ } as const;
22
+
23
+ export type Moc3Version = (typeof Moc3Version)[keyof typeof Moc3Version];
24
+
25
+ export const CountIdx = {
26
+ PARTS: 0,
27
+ DEFORMERS: 1,
28
+ WARP_DEFORMERS: 2,
29
+ ROTATION_DEFORMERS: 3,
30
+ ART_MESHES: 4,
31
+ PARAMETERS: 5,
32
+ PART_KEYFORMS: 6,
33
+ WARP_DEFORMER_KEYFORMS: 7,
34
+ ROTATION_DEFORMER_KEYFORMS: 8,
35
+ ART_MESH_KEYFORMS: 9,
36
+ KEYFORM_POSITIONS: 10,
37
+ KEYFORM_BINDING_INDICES: 11,
38
+ KEYFORM_BINDING_BANDS: 12,
39
+ KEYFORM_BINDINGS: 13,
40
+ KEYS: 14,
41
+ UVS: 15,
42
+ POSITION_INDICES: 16,
43
+ DRAWABLE_MASKS: 17,
44
+ DRAW_ORDER_GROUPS: 18,
45
+ DRAW_ORDER_GROUP_OBJECTS: 19,
46
+ GLUES: 20,
47
+ GLUE_INFOS: 21,
48
+ GLUE_KEYFORMS: 22,
49
+ } as const;
50
+
51
+ export type ElemType =
52
+ | "runtime"
53
+ | "str64"
54
+ | "i32"
55
+ | "f32"
56
+ | "i16"
57
+ | "bool"
58
+ | "u8";
59
+
60
+ export interface SectionEntry {
61
+ readonly name: string;
62
+ readonly elemType: ElemType;
63
+ readonly countIdx: number;
64
+ }
65
+
66
+ /** V3.00 section list after countInfo + canvasInfo (SOT index = layoutIndex + 2). */
67
+ export const MOC3_SECTION_LAYOUT: readonly SectionEntry[] = [
68
+ {
69
+ name: "part.runtime_space",
70
+ elemType: "runtime",
71
+ countIdx: CountIdx.PARTS,
72
+ },
73
+ { name: "part.ids", elemType: "str64", countIdx: CountIdx.PARTS },
74
+ {
75
+ name: "part.keyform_binding_band_indices",
76
+ elemType: "i32",
77
+ countIdx: CountIdx.PARTS,
78
+ },
79
+ {
80
+ name: "part.keyform_begin_indices",
81
+ elemType: "i32",
82
+ countIdx: CountIdx.PARTS,
83
+ },
84
+ { name: "part.keyform_counts", elemType: "i32", countIdx: CountIdx.PARTS },
85
+ { name: "part.visibles", elemType: "bool", countIdx: CountIdx.PARTS },
86
+ { name: "part.enables", elemType: "bool", countIdx: CountIdx.PARTS },
87
+ {
88
+ name: "part.parent_part_indices",
89
+ elemType: "i32",
90
+ countIdx: CountIdx.PARTS,
91
+ },
92
+
93
+ {
94
+ name: "deformer.runtime_space",
95
+ elemType: "runtime",
96
+ countIdx: CountIdx.DEFORMERS,
97
+ },
98
+ { name: "deformer.ids", elemType: "str64", countIdx: CountIdx.DEFORMERS },
99
+ {
100
+ name: "deformer.keyform_binding_band_indices",
101
+ elemType: "i32",
102
+ countIdx: CountIdx.DEFORMERS,
103
+ },
104
+ {
105
+ name: "deformer.visibles",
106
+ elemType: "bool",
107
+ countIdx: CountIdx.DEFORMERS,
108
+ },
109
+ {
110
+ name: "deformer.enables",
111
+ elemType: "bool",
112
+ countIdx: CountIdx.DEFORMERS,
113
+ },
114
+ {
115
+ name: "deformer.parent_part_indices",
116
+ elemType: "i32",
117
+ countIdx: CountIdx.DEFORMERS,
118
+ },
119
+ {
120
+ name: "deformer.parent_deformer_indices",
121
+ elemType: "i32",
122
+ countIdx: CountIdx.DEFORMERS,
123
+ },
124
+ { name: "deformer.types", elemType: "i32", countIdx: CountIdx.DEFORMERS },
125
+ {
126
+ name: "deformer.specific_indices",
127
+ elemType: "i32",
128
+ countIdx: CountIdx.DEFORMERS,
129
+ },
130
+
131
+ {
132
+ name: "warp_deformer.keyform_binding_band_indices",
133
+ elemType: "i32",
134
+ countIdx: CountIdx.WARP_DEFORMERS,
135
+ },
136
+ {
137
+ name: "warp_deformer.keyform_begin_indices",
138
+ elemType: "i32",
139
+ countIdx: CountIdx.WARP_DEFORMERS,
140
+ },
141
+ {
142
+ name: "warp_deformer.keyform_counts",
143
+ elemType: "i32",
144
+ countIdx: CountIdx.WARP_DEFORMERS,
145
+ },
146
+ {
147
+ name: "warp_deformer.vertex_counts",
148
+ elemType: "i32",
149
+ countIdx: CountIdx.WARP_DEFORMERS,
150
+ },
151
+ {
152
+ name: "warp_deformer.rows",
153
+ elemType: "i32",
154
+ countIdx: CountIdx.WARP_DEFORMERS,
155
+ },
156
+ {
157
+ name: "warp_deformer.cols",
158
+ elemType: "i32",
159
+ countIdx: CountIdx.WARP_DEFORMERS,
160
+ },
161
+
162
+ {
163
+ name: "rotation_deformer.keyform_binding_band_indices",
164
+ elemType: "i32",
165
+ countIdx: CountIdx.ROTATION_DEFORMERS,
166
+ },
167
+ {
168
+ name: "rotation_deformer.keyform_begin_indices",
169
+ elemType: "i32",
170
+ countIdx: CountIdx.ROTATION_DEFORMERS,
171
+ },
172
+ {
173
+ name: "rotation_deformer.keyform_counts",
174
+ elemType: "i32",
175
+ countIdx: CountIdx.ROTATION_DEFORMERS,
176
+ },
177
+ {
178
+ name: "rotation_deformer.base_angles",
179
+ elemType: "f32",
180
+ countIdx: CountIdx.ROTATION_DEFORMERS,
181
+ },
182
+
183
+ {
184
+ name: "art_mesh.runtime_space_0",
185
+ elemType: "runtime",
186
+ countIdx: CountIdx.ART_MESHES,
187
+ },
188
+ {
189
+ name: "art_mesh.runtime_space_1",
190
+ elemType: "runtime",
191
+ countIdx: CountIdx.ART_MESHES,
192
+ },
193
+ {
194
+ name: "art_mesh.runtime_space_2",
195
+ elemType: "runtime",
196
+ countIdx: CountIdx.ART_MESHES,
197
+ },
198
+ {
199
+ name: "art_mesh.runtime_space_3",
200
+ elemType: "runtime",
201
+ countIdx: CountIdx.ART_MESHES,
202
+ },
203
+ { name: "art_mesh.ids", elemType: "str64", countIdx: CountIdx.ART_MESHES },
204
+ {
205
+ name: "art_mesh.keyform_binding_band_indices",
206
+ elemType: "i32",
207
+ countIdx: CountIdx.ART_MESHES,
208
+ },
209
+ {
210
+ name: "art_mesh.keyform_begin_indices",
211
+ elemType: "i32",
212
+ countIdx: CountIdx.ART_MESHES,
213
+ },
214
+ {
215
+ name: "art_mesh.keyform_counts",
216
+ elemType: "i32",
217
+ countIdx: CountIdx.ART_MESHES,
218
+ },
219
+ {
220
+ name: "art_mesh.visibles",
221
+ elemType: "bool",
222
+ countIdx: CountIdx.ART_MESHES,
223
+ },
224
+ {
225
+ name: "art_mesh.enables",
226
+ elemType: "bool",
227
+ countIdx: CountIdx.ART_MESHES,
228
+ },
229
+ {
230
+ name: "art_mesh.parent_part_indices",
231
+ elemType: "i32",
232
+ countIdx: CountIdx.ART_MESHES,
233
+ },
234
+ {
235
+ name: "art_mesh.parent_deformer_indices",
236
+ elemType: "i32",
237
+ countIdx: CountIdx.ART_MESHES,
238
+ },
239
+ {
240
+ name: "art_mesh.texture_indices",
241
+ elemType: "i32",
242
+ countIdx: CountIdx.ART_MESHES,
243
+ },
244
+ {
245
+ name: "art_mesh.drawable_flags",
246
+ elemType: "i32",
247
+ countIdx: CountIdx.ART_MESHES,
248
+ },
249
+ // NOTE: names match observed Wanko SOT payloads (vertex count then UV/index tables).
250
+ {
251
+ name: "art_mesh.vertex_counts",
252
+ elemType: "i32",
253
+ countIdx: CountIdx.ART_MESHES,
254
+ },
255
+ {
256
+ name: "art_mesh.uv_begin_indices",
257
+ elemType: "i32",
258
+ countIdx: CountIdx.ART_MESHES,
259
+ },
260
+ {
261
+ name: "art_mesh.position_index_begin_indices",
262
+ elemType: "i32",
263
+ countIdx: CountIdx.ART_MESHES,
264
+ },
265
+ {
266
+ name: "art_mesh.position_index_counts",
267
+ elemType: "i32",
268
+ countIdx: CountIdx.ART_MESHES,
269
+ },
270
+ {
271
+ name: "art_mesh.mask_begin_indices",
272
+ elemType: "i32",
273
+ countIdx: CountIdx.ART_MESHES,
274
+ },
275
+ {
276
+ name: "art_mesh.mask_counts",
277
+ elemType: "i32",
278
+ countIdx: CountIdx.ART_MESHES,
279
+ },
280
+
281
+ {
282
+ name: "parameter.runtime_space",
283
+ elemType: "runtime",
284
+ countIdx: CountIdx.PARAMETERS,
285
+ },
286
+ { name: "parameter.ids", elemType: "str64", countIdx: CountIdx.PARAMETERS },
287
+ {
288
+ name: "parameter.max_values",
289
+ elemType: "f32",
290
+ countIdx: CountIdx.PARAMETERS,
291
+ },
292
+ {
293
+ name: "parameter.min_values",
294
+ elemType: "f32",
295
+ countIdx: CountIdx.PARAMETERS,
296
+ },
297
+ {
298
+ name: "parameter.default_values",
299
+ elemType: "f32",
300
+ countIdx: CountIdx.PARAMETERS,
301
+ },
302
+ {
303
+ name: "parameter.repeats",
304
+ elemType: "bool",
305
+ countIdx: CountIdx.PARAMETERS,
306
+ },
307
+ {
308
+ name: "parameter.decimal_places",
309
+ elemType: "i32",
310
+ countIdx: CountIdx.PARAMETERS,
311
+ },
312
+ {
313
+ name: "parameter.keyform_binding_begin_indices",
314
+ elemType: "i32",
315
+ countIdx: CountIdx.PARAMETERS,
316
+ },
317
+ {
318
+ name: "parameter.keyform_binding_counts",
319
+ elemType: "i32",
320
+ countIdx: CountIdx.PARAMETERS,
321
+ },
322
+
323
+ {
324
+ name: "part_keyform.draw_orders",
325
+ elemType: "f32",
326
+ countIdx: CountIdx.PART_KEYFORMS,
327
+ },
328
+
329
+ {
330
+ name: "warp_deformer_keyform.opacities",
331
+ elemType: "f32",
332
+ countIdx: CountIdx.WARP_DEFORMER_KEYFORMS,
333
+ },
334
+ {
335
+ name: "warp_deformer_keyform.keyform_position_begin_indices",
336
+ elemType: "i32",
337
+ countIdx: CountIdx.WARP_DEFORMER_KEYFORMS,
338
+ },
339
+
340
+ {
341
+ name: "rotation_deformer_keyform.opacities",
342
+ elemType: "f32",
343
+ countIdx: CountIdx.ROTATION_DEFORMER_KEYFORMS,
344
+ },
345
+ {
346
+ name: "rotation_deformer_keyform.angles",
347
+ elemType: "f32",
348
+ countIdx: CountIdx.ROTATION_DEFORMER_KEYFORMS,
349
+ },
350
+ {
351
+ name: "rotation_deformer_keyform.origin_xs",
352
+ elemType: "f32",
353
+ countIdx: CountIdx.ROTATION_DEFORMER_KEYFORMS,
354
+ },
355
+ {
356
+ name: "rotation_deformer_keyform.origin_ys",
357
+ elemType: "f32",
358
+ countIdx: CountIdx.ROTATION_DEFORMER_KEYFORMS,
359
+ },
360
+ {
361
+ name: "rotation_deformer_keyform.scales",
362
+ elemType: "f32",
363
+ countIdx: CountIdx.ROTATION_DEFORMER_KEYFORMS,
364
+ },
365
+ {
366
+ name: "rotation_deformer_keyform.reflect_xs",
367
+ elemType: "bool",
368
+ countIdx: CountIdx.ROTATION_DEFORMER_KEYFORMS,
369
+ },
370
+ {
371
+ name: "rotation_deformer_keyform.reflect_ys",
372
+ elemType: "bool",
373
+ countIdx: CountIdx.ROTATION_DEFORMER_KEYFORMS,
374
+ },
375
+
376
+ {
377
+ name: "art_mesh_keyform.opacities",
378
+ elemType: "f32",
379
+ countIdx: CountIdx.ART_MESH_KEYFORMS,
380
+ },
381
+ {
382
+ name: "art_mesh_keyform.draw_orders",
383
+ elemType: "f32",
384
+ countIdx: CountIdx.ART_MESH_KEYFORMS,
385
+ },
386
+ {
387
+ name: "art_mesh_keyform.keyform_position_begin_indices",
388
+ elemType: "i32",
389
+ countIdx: CountIdx.ART_MESH_KEYFORMS,
390
+ },
391
+
392
+ {
393
+ name: "keyform_position.xys",
394
+ elemType: "f32",
395
+ countIdx: CountIdx.KEYFORM_POSITIONS,
396
+ },
397
+
398
+ {
399
+ name: "keyform_binding_index.indices",
400
+ elemType: "i32",
401
+ countIdx: CountIdx.KEYFORM_BINDING_INDICES,
402
+ },
403
+
404
+ {
405
+ name: "keyform_binding_band.begin_indices",
406
+ elemType: "i32",
407
+ countIdx: CountIdx.KEYFORM_BINDING_BANDS,
408
+ },
409
+ {
410
+ name: "keyform_binding_band.counts",
411
+ elemType: "i32",
412
+ countIdx: CountIdx.KEYFORM_BINDING_BANDS,
413
+ },
414
+
415
+ {
416
+ name: "keyform_binding.keys_begin_indices",
417
+ elemType: "i32",
418
+ countIdx: CountIdx.KEYFORM_BINDINGS,
419
+ },
420
+ {
421
+ name: "keyform_binding.keys_counts",
422
+ elemType: "i32",
423
+ countIdx: CountIdx.KEYFORM_BINDINGS,
424
+ },
425
+
426
+ { name: "keys.values", elemType: "f32", countIdx: CountIdx.KEYS },
427
+
428
+ { name: "uv.xys", elemType: "f32", countIdx: CountIdx.UVS },
429
+
430
+ {
431
+ name: "position_index.indices",
432
+ elemType: "i16",
433
+ countIdx: CountIdx.POSITION_INDICES,
434
+ },
435
+
436
+ {
437
+ name: "drawable_mask.art_mesh_indices",
438
+ elemType: "i32",
439
+ countIdx: CountIdx.DRAWABLE_MASKS,
440
+ },
441
+
442
+ {
443
+ name: "draw_order_group.object_begin_indices",
444
+ elemType: "i32",
445
+ countIdx: CountIdx.DRAW_ORDER_GROUPS,
446
+ },
447
+ {
448
+ name: "draw_order_group.object_counts",
449
+ elemType: "i32",
450
+ countIdx: CountIdx.DRAW_ORDER_GROUPS,
451
+ },
452
+ {
453
+ name: "draw_order_group.object_total_counts",
454
+ elemType: "i32",
455
+ countIdx: CountIdx.DRAW_ORDER_GROUPS,
456
+ },
457
+ {
458
+ name: "draw_order_group.min_draw_orders",
459
+ elemType: "i32",
460
+ countIdx: CountIdx.DRAW_ORDER_GROUPS,
461
+ },
462
+ {
463
+ name: "draw_order_group.max_draw_orders",
464
+ elemType: "i32",
465
+ countIdx: CountIdx.DRAW_ORDER_GROUPS,
466
+ },
467
+
468
+ {
469
+ name: "draw_order_group_object.types",
470
+ elemType: "i32",
471
+ countIdx: CountIdx.DRAW_ORDER_GROUP_OBJECTS,
472
+ },
473
+ {
474
+ name: "draw_order_group_object.indices",
475
+ elemType: "i32",
476
+ countIdx: CountIdx.DRAW_ORDER_GROUP_OBJECTS,
477
+ },
478
+ {
479
+ name: "draw_order_group_object.group_indices",
480
+ elemType: "i32",
481
+ countIdx: CountIdx.DRAW_ORDER_GROUP_OBJECTS,
482
+ },
483
+
484
+ {
485
+ name: "glue.runtime_space",
486
+ elemType: "runtime",
487
+ countIdx: CountIdx.GLUES,
488
+ },
489
+ { name: "glue.ids", elemType: "str64", countIdx: CountIdx.GLUES },
490
+ {
491
+ name: "glue.keyform_binding_band_indices",
492
+ elemType: "i32",
493
+ countIdx: CountIdx.GLUES,
494
+ },
495
+ {
496
+ name: "glue.keyform_begin_indices",
497
+ elemType: "i32",
498
+ countIdx: CountIdx.GLUES,
499
+ },
500
+ { name: "glue.keyform_counts", elemType: "i32", countIdx: CountIdx.GLUES },
501
+ {
502
+ name: "glue.art_mesh_index_as",
503
+ elemType: "i32",
504
+ countIdx: CountIdx.GLUES,
505
+ },
506
+ {
507
+ name: "glue.art_mesh_index_bs",
508
+ elemType: "i32",
509
+ countIdx: CountIdx.GLUES,
510
+ },
511
+ {
512
+ name: "glue.info_begin_indices",
513
+ elemType: "i32",
514
+ countIdx: CountIdx.GLUES,
515
+ },
516
+ { name: "glue.info_counts", elemType: "i32", countIdx: CountIdx.GLUES },
517
+
518
+ {
519
+ name: "glue_info.weights",
520
+ elemType: "f32",
521
+ countIdx: CountIdx.GLUE_INFOS,
522
+ },
523
+ {
524
+ name: "glue_info.position_indices",
525
+ elemType: "i16",
526
+ countIdx: CountIdx.GLUE_INFOS,
527
+ },
528
+
529
+ {
530
+ name: "glue_keyform.intensities",
531
+ elemType: "f32",
532
+ countIdx: CountIdx.GLUE_KEYFORMS,
533
+ },
534
+ ];
@@ -0,0 +1,45 @@
1
+ import type { Moc3Document } from "./moc3-reader.js";
2
+
3
+ export interface Moc3PartTables {
4
+ readonly ids: readonly string[];
5
+ readonly parentPartIndices: Int32Array;
6
+ readonly artMeshParentPartIndices: Int32Array;
7
+ }
8
+
9
+ export function readMoc3PartTables(doc: Moc3Document): Moc3PartTables | null {
10
+ const ids = doc.sections.get("part.ids");
11
+ const parents = doc.sections.get("part.parent_part_indices");
12
+ const meshParents = doc.sections.get("art_mesh.parent_part_indices");
13
+ if (!Array.isArray(ids) || !(parents instanceof Int32Array)) return null;
14
+ return {
15
+ ids: ids as string[],
16
+ parentPartIndices: parents,
17
+ artMeshParentPartIndices:
18
+ meshParents instanceof Int32Array ? meshParents : new Int32Array(0),
19
+ };
20
+ }
21
+
22
+ /**
23
+ * Cascaded part opacity for an art mesh (motion / pose overrides × parents).
24
+ * Missing override → 1.
25
+ */
26
+ export function cascadedPartOpacity(
27
+ tables: Moc3PartTables,
28
+ artMeshIndex: number,
29
+ overrides: ReadonlyMap<string, number>,
30
+ ): number {
31
+ const root = tables.artMeshParentPartIndices[artMeshIndex] ?? -1;
32
+ let partIndex = root;
33
+ let opacity = 1;
34
+ let guard = 0;
35
+ while (partIndex >= 0 && guard < 64) {
36
+ const id = tables.ids[partIndex];
37
+ if (id !== undefined) {
38
+ const o = overrides.get(id);
39
+ if (o !== undefined) opacity *= o;
40
+ }
41
+ partIndex = tables.parentPartIndices[partIndex] ?? -1;
42
+ guard += 1;
43
+ }
44
+ return opacity;
45
+ }