@doki-land/live2d-renderer 0.0.18 → 0.0.19
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/index.d.ts +12 -2
- package/dist/index.js +510 -136
- package/package.json +2 -2
- package/src/cpu/evaluate.ts +63 -4
- package/src/moc/moc2-to-program.ts +89 -3
- package/src/moc/moc2.ts +151 -75
- package/src/moc/moc3-to-program.ts +193 -3
- package/src/moc/moc3.ts +160 -81
- package/src/runtime/model-runtime.ts +6 -0
- package/src/types.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -2551,10 +2551,21 @@ function createModelInstance(program) {
|
|
|
2551
2551
|
timeSeconds: 0
|
|
2552
2552
|
};
|
|
2553
2553
|
}
|
|
2554
|
+
var paramIndexCache = /* @__PURE__ */ new WeakMap();
|
|
2555
|
+
function parameterIndex(instance, parameterId) {
|
|
2556
|
+
let map = paramIndexCache.get(instance.program);
|
|
2557
|
+
if (!map) {
|
|
2558
|
+
map = /* @__PURE__ */ new Map();
|
|
2559
|
+
for (let i = 0; i < instance.program.parameters.length; i++) {
|
|
2560
|
+
map.set(instance.program.parameters[i].id, i);
|
|
2561
|
+
}
|
|
2562
|
+
paramIndexCache.set(instance.program, map);
|
|
2563
|
+
}
|
|
2564
|
+
const index = map.get(parameterId);
|
|
2565
|
+
return index ?? -1;
|
|
2566
|
+
}
|
|
2554
2567
|
function setParameterValue(instance, parameterId, value) {
|
|
2555
|
-
const index = instance
|
|
2556
|
-
(p2) => p2.id === parameterId
|
|
2557
|
-
);
|
|
2568
|
+
const index = parameterIndex(instance, parameterId);
|
|
2558
2569
|
if (index < 0) {
|
|
2559
2570
|
throw new Error(
|
|
2560
2571
|
`@doki-land/live2d-renderer: unknown parameter "${parameterId}"`
|
|
@@ -2604,6 +2615,32 @@ function evaluateFrame(instance) {
|
|
|
2604
2615
|
drawables
|
|
2605
2616
|
};
|
|
2606
2617
|
}
|
|
2618
|
+
function evaluateFrameInto(instance, meshes, poseOpacity) {
|
|
2619
|
+
const byIndex = /* @__PURE__ */ new Map();
|
|
2620
|
+
for (const m of meshes) byIndex.set(m.index, m);
|
|
2621
|
+
for (const d of instance.program.drawables) {
|
|
2622
|
+
const sink = byIndex.get(d.index);
|
|
2623
|
+
if (!sink) continue;
|
|
2624
|
+
let positions = sink.vertexPositions;
|
|
2625
|
+
if (positions.length !== d.positions.length) {
|
|
2626
|
+
positions = new Float32Array(d.positions.length);
|
|
2627
|
+
sink.vertexPositions = positions;
|
|
2628
|
+
}
|
|
2629
|
+
positions.set(d.positions);
|
|
2630
|
+
if (d.deformParamIndex >= 0 && d.deformDeltas) {
|
|
2631
|
+
const w = paramWeight(instance, d.deformParamIndex);
|
|
2632
|
+
for (let i = 0; i < positions.length; i++) {
|
|
2633
|
+
positions[i] = positions[i] + w * d.deformDeltas[i];
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
sink.opacity = d.opacity;
|
|
2637
|
+
sink.renderOrder = d.renderOrder;
|
|
2638
|
+
sink.visible = d.visible;
|
|
2639
|
+
if (d.index >= 0 && d.index < poseOpacity.length) {
|
|
2640
|
+
poseOpacity[d.index] = d.opacity;
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2607
2644
|
function fingerprintSnapshot(snapshot) {
|
|
2608
2645
|
const parts = [`t=${snapshot.timeSeconds.toFixed(4)}`];
|
|
2609
2646
|
for (const d of snapshot.drawables) {
|
|
@@ -3611,16 +3648,81 @@ function moc2ParamGetterFromValues(params, values) {
|
|
|
3611
3648
|
}
|
|
3612
3649
|
return (id) => byId.get(id) ?? 0;
|
|
3613
3650
|
}
|
|
3614
|
-
function
|
|
3651
|
+
function normalizePositionsInto(positions, canvasWidth, canvasHeight, out) {
|
|
3615
3652
|
const w = canvasWidth > 0 ? canvasWidth : 1;
|
|
3616
3653
|
const h = canvasHeight > 0 ? canvasHeight : 1;
|
|
3617
|
-
const out = new Float32Array(positions.length);
|
|
3618
3654
|
for (let i = 0; i + 1 < positions.length; i += 2) {
|
|
3619
3655
|
out[i] = positions[i] / w * 2 - 1;
|
|
3620
3656
|
out[i + 1] = 1 - positions[i + 1] / h * 2;
|
|
3621
3657
|
}
|
|
3658
|
+
}
|
|
3659
|
+
function normalizePositions(positions, canvasWidth, canvasHeight) {
|
|
3660
|
+
const out = new Float32Array(positions.length);
|
|
3661
|
+
normalizePositionsInto(positions, canvasWidth, canvasHeight, out);
|
|
3622
3662
|
return out;
|
|
3623
3663
|
}
|
|
3664
|
+
function evaluateMoc2PoseInto(model, getParam, byId) {
|
|
3665
|
+
const ops = bakeDeformerOps(model, getParam);
|
|
3666
|
+
const w = model.canvasWidth;
|
|
3667
|
+
const h = model.canvasHeight;
|
|
3668
|
+
for (const part of model.parts) {
|
|
3669
|
+
for (const mesh of part.drawData) {
|
|
3670
|
+
const sink = byId.get(mesh.id);
|
|
3671
|
+
if (!sink) continue;
|
|
3672
|
+
const floatCount = mesh.numPoints * 2;
|
|
3673
|
+
const local = interpolateKeyforms(
|
|
3674
|
+
mesh.keyforms,
|
|
3675
|
+
mesh.pivotManager,
|
|
3676
|
+
getParam,
|
|
3677
|
+
floatCount
|
|
3678
|
+
);
|
|
3679
|
+
const world = transformDrawablePositions(mesh, local, ops);
|
|
3680
|
+
let pos = sink.vertexPositions;
|
|
3681
|
+
if (pos.length !== world.length) {
|
|
3682
|
+
pos = new Float32Array(world.length);
|
|
3683
|
+
sink.vertexPositions = pos;
|
|
3684
|
+
}
|
|
3685
|
+
normalizePositionsInto(world, w, h, pos);
|
|
3686
|
+
sink.opacity = interpolateScalarTable(
|
|
3687
|
+
mesh.opacities,
|
|
3688
|
+
mesh.pivotManager,
|
|
3689
|
+
getParam,
|
|
3690
|
+
1
|
|
3691
|
+
);
|
|
3692
|
+
sink.renderOrder = Math.round(
|
|
3693
|
+
interpolateScalarTable(
|
|
3694
|
+
mesh.drawOrders,
|
|
3695
|
+
mesh.pivotManager,
|
|
3696
|
+
getParam,
|
|
3697
|
+
mesh.averageDrawOrder
|
|
3698
|
+
)
|
|
3699
|
+
);
|
|
3700
|
+
sink.visible = part.visible;
|
|
3701
|
+
}
|
|
3702
|
+
}
|
|
3703
|
+
}
|
|
3704
|
+
function moc2DrawableIdsInProgramOrder(model, getParam) {
|
|
3705
|
+
const paramDefs = model.paramDefSet?.params ?? [];
|
|
3706
|
+
const gp = getParam ?? buildParamGetter(paramDefs);
|
|
3707
|
+
const drafts = [];
|
|
3708
|
+
for (const part of model.parts) {
|
|
3709
|
+
for (const mesh of part.drawData) {
|
|
3710
|
+
drafts.push({
|
|
3711
|
+
id: mesh.id,
|
|
3712
|
+
renderOrder: Math.round(
|
|
3713
|
+
interpolateScalarTable(
|
|
3714
|
+
mesh.drawOrders,
|
|
3715
|
+
mesh.pivotManager,
|
|
3716
|
+
gp,
|
|
3717
|
+
mesh.averageDrawOrder
|
|
3718
|
+
)
|
|
3719
|
+
)
|
|
3720
|
+
});
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
drafts.sort((a, b) => a.renderOrder - b.renderOrder);
|
|
3724
|
+
return drafts.map((d) => d.id);
|
|
3725
|
+
}
|
|
3624
3726
|
function lowerDrawable(mesh, getParam, ops, canvasWidth, canvasHeight, partVisible) {
|
|
3625
3727
|
const floatCount = mesh.numPoints * 2;
|
|
3626
3728
|
const local = interpolateKeyforms(
|
|
@@ -4851,15 +4953,24 @@ function meanGlueSeamDistance(positionsByMesh, glue) {
|
|
|
4851
4953
|
}
|
|
4852
4954
|
|
|
4853
4955
|
// src/moc/moc3-to-program.ts
|
|
4854
|
-
function
|
|
4956
|
+
function normalizePositionsInto2(positions, canvasWidth, canvasHeight, pixelsPerUnit, out) {
|
|
4855
4957
|
const ppu = pixelsPerUnit > 0 ? pixelsPerUnit : 1;
|
|
4856
4958
|
const hw = canvasWidth > 0 ? canvasWidth / ppu * 0.5 : 0.5;
|
|
4857
4959
|
const hh = canvasHeight > 0 ? canvasHeight / ppu * 0.5 : 0.5;
|
|
4858
|
-
const out = new Float32Array(positions.length);
|
|
4859
4960
|
for (let i = 0; i + 1 < positions.length; i += 2) {
|
|
4860
4961
|
out[i] = positions[i] / hw;
|
|
4861
4962
|
out[i + 1] = -positions[i + 1] / hh;
|
|
4862
4963
|
}
|
|
4964
|
+
}
|
|
4965
|
+
function normalizePositions2(positions, canvasWidth, canvasHeight, pixelsPerUnit) {
|
|
4966
|
+
const out = new Float32Array(positions.length);
|
|
4967
|
+
normalizePositionsInto2(
|
|
4968
|
+
positions,
|
|
4969
|
+
canvasWidth,
|
|
4970
|
+
canvasHeight,
|
|
4971
|
+
pixelsPerUnit,
|
|
4972
|
+
out
|
|
4973
|
+
);
|
|
4863
4974
|
return out;
|
|
4864
4975
|
}
|
|
4865
4976
|
function moc3DocumentToProgram(doc, options = {}) {
|
|
@@ -5045,6 +5156,155 @@ function moc3DocumentToProgram(doc, options = {}) {
|
|
|
5045
5156
|
drawables
|
|
5046
5157
|
};
|
|
5047
5158
|
}
|
|
5159
|
+
function moc3ArtMeshIndicesInProgramOrder(doc, getParamByIndex) {
|
|
5160
|
+
const meshCount = doc.counts[CountIdx.ART_MESHES] ?? 0;
|
|
5161
|
+
const defaultValues = moc3SectionF32(doc, "parameter.default_values");
|
|
5162
|
+
const gp = getParamByIndex ?? ((index) => defaultValues[index] ?? 0);
|
|
5163
|
+
const keyTables = loadMoc3KeyTables(doc);
|
|
5164
|
+
const enables = moc3SectionI32(doc, "art_mesh.enables");
|
|
5165
|
+
const vertexCounts = moc3SectionI32(doc, "art_mesh.vertex_counts");
|
|
5166
|
+
const indexCounts = moc3SectionI32(doc, "art_mesh.position_index_counts");
|
|
5167
|
+
const keyformBegins = moc3SectionI32(doc, "art_mesh.keyform_begin_indices");
|
|
5168
|
+
const keyformCounts = moc3SectionI32(doc, "art_mesh.keyform_counts");
|
|
5169
|
+
const bandIndices = moc3SectionI32(
|
|
5170
|
+
doc,
|
|
5171
|
+
"art_mesh.keyform_binding_band_indices"
|
|
5172
|
+
);
|
|
5173
|
+
const keyformDrawOrders = moc3SectionF32(
|
|
5174
|
+
doc,
|
|
5175
|
+
"art_mesh_keyform.draw_orders"
|
|
5176
|
+
);
|
|
5177
|
+
const drafts = [];
|
|
5178
|
+
for (let i = 0; i < meshCount; i++) {
|
|
5179
|
+
if ((enables[i] ?? 1) === 0) continue;
|
|
5180
|
+
const vertexCount = vertexCounts[i] ?? 0;
|
|
5181
|
+
const indexCount = indexCounts[i] ?? 0;
|
|
5182
|
+
if (vertexCount <= 0 || indexCount < 3) continue;
|
|
5183
|
+
const kfBegin = keyformBegins[i] ?? 0;
|
|
5184
|
+
const kfCount = keyformCounts[i] ?? 0;
|
|
5185
|
+
if (kfCount <= 0) continue;
|
|
5186
|
+
const band = bandIndices[i] ?? -1;
|
|
5187
|
+
const blend = resolveMoc3KeyformBlend(keyTables, band, gp);
|
|
5188
|
+
drafts.push({
|
|
5189
|
+
artMeshIndex: i,
|
|
5190
|
+
renderOrder: Math.round(
|
|
5191
|
+
blendKeyformScalar(
|
|
5192
|
+
keyformDrawOrders,
|
|
5193
|
+
kfBegin,
|
|
5194
|
+
kfCount,
|
|
5195
|
+
blend,
|
|
5196
|
+
i
|
|
5197
|
+
)
|
|
5198
|
+
)
|
|
5199
|
+
});
|
|
5200
|
+
}
|
|
5201
|
+
drafts.sort((a, b) => a.renderOrder - b.renderOrder);
|
|
5202
|
+
return drafts.map((d) => d.artMeshIndex);
|
|
5203
|
+
}
|
|
5204
|
+
function evaluateMoc3PoseInto(doc, getParamByIndex, byArtMesh, poseOpacity) {
|
|
5205
|
+
const meshCount = doc.counts[CountIdx.ART_MESHES] ?? 0;
|
|
5206
|
+
const keyTables = loadMoc3KeyTables(doc);
|
|
5207
|
+
const deformers = bakeMoc3Deformers(doc, keyTables, getParamByIndex);
|
|
5208
|
+
const glues = loadMoc3Glues(doc);
|
|
5209
|
+
const glueIntensities = moc3SectionF32(doc, "glue_keyform.intensities");
|
|
5210
|
+
const visibles = moc3SectionI32(doc, "art_mesh.visibles");
|
|
5211
|
+
const enables = moc3SectionI32(doc, "art_mesh.enables");
|
|
5212
|
+
const vertexCounts = moc3SectionI32(doc, "art_mesh.vertex_counts");
|
|
5213
|
+
const indexCounts = moc3SectionI32(doc, "art_mesh.position_index_counts");
|
|
5214
|
+
const keyformBegins = moc3SectionI32(doc, "art_mesh.keyform_begin_indices");
|
|
5215
|
+
const keyformCounts = moc3SectionI32(doc, "art_mesh.keyform_counts");
|
|
5216
|
+
const bandIndices = moc3SectionI32(
|
|
5217
|
+
doc,
|
|
5218
|
+
"art_mesh.keyform_binding_band_indices"
|
|
5219
|
+
);
|
|
5220
|
+
const parentDeformers = moc3SectionI32(
|
|
5221
|
+
doc,
|
|
5222
|
+
"art_mesh.parent_deformer_indices"
|
|
5223
|
+
);
|
|
5224
|
+
const keyformOpacities = moc3SectionF32(doc, "art_mesh_keyform.opacities");
|
|
5225
|
+
const keyformDrawOrders = moc3SectionF32(
|
|
5226
|
+
doc,
|
|
5227
|
+
"art_mesh_keyform.draw_orders"
|
|
5228
|
+
);
|
|
5229
|
+
const keyformPosBegins = moc3SectionI32(
|
|
5230
|
+
doc,
|
|
5231
|
+
"art_mesh_keyform.keyform_position_begin_indices"
|
|
5232
|
+
);
|
|
5233
|
+
const keyformPositions = moc3SectionF32(doc, "keyform_position.xys");
|
|
5234
|
+
const cw = doc.canvas.canvasWidth;
|
|
5235
|
+
const ch = doc.canvas.canvasHeight;
|
|
5236
|
+
const ppu = doc.canvas.pixelsPerUnit;
|
|
5237
|
+
const worldByMesh = /* @__PURE__ */ new Map();
|
|
5238
|
+
const opacityByMesh = /* @__PURE__ */ new Map();
|
|
5239
|
+
const orderByMesh = /* @__PURE__ */ new Map();
|
|
5240
|
+
const visibleByMesh = /* @__PURE__ */ new Map();
|
|
5241
|
+
for (let i = 0; i < meshCount; i++) {
|
|
5242
|
+
if (!byArtMesh.has(i)) continue;
|
|
5243
|
+
if ((enables[i] ?? 1) === 0) continue;
|
|
5244
|
+
const vertexCount = vertexCounts[i] ?? 0;
|
|
5245
|
+
const indexCount = indexCounts[i] ?? 0;
|
|
5246
|
+
if (vertexCount <= 0 || indexCount < 3) continue;
|
|
5247
|
+
const kfBegin = keyformBegins[i] ?? 0;
|
|
5248
|
+
const kfCount = keyformCounts[i] ?? 0;
|
|
5249
|
+
if (kfCount <= 0) continue;
|
|
5250
|
+
const band = bandIndices[i] ?? -1;
|
|
5251
|
+
const blend = resolveMoc3KeyformBlend(keyTables, band, getParamByIndex);
|
|
5252
|
+
const local = blendKeyformFloats(
|
|
5253
|
+
keyformPositions,
|
|
5254
|
+
keyformPosBegins,
|
|
5255
|
+
kfBegin,
|
|
5256
|
+
kfCount,
|
|
5257
|
+
vertexCount * 2,
|
|
5258
|
+
blend
|
|
5259
|
+
);
|
|
5260
|
+
const parentIndex = parentDeformers[i] ?? -1;
|
|
5261
|
+
const parent = parentIndex >= 0 ? deformers[parentIndex] ?? null : null;
|
|
5262
|
+
const world = parent ? applyParentToPoints(local, parent) : local;
|
|
5263
|
+
worldByMesh.set(i, world);
|
|
5264
|
+
opacityByMesh.set(
|
|
5265
|
+
i,
|
|
5266
|
+
blendKeyformScalar(keyformOpacities, kfBegin, kfCount, blend, 1)
|
|
5267
|
+
);
|
|
5268
|
+
orderByMesh.set(
|
|
5269
|
+
i,
|
|
5270
|
+
Math.round(
|
|
5271
|
+
blendKeyformScalar(
|
|
5272
|
+
keyformDrawOrders,
|
|
5273
|
+
kfBegin,
|
|
5274
|
+
kfCount,
|
|
5275
|
+
blend,
|
|
5276
|
+
i
|
|
5277
|
+
)
|
|
5278
|
+
)
|
|
5279
|
+
);
|
|
5280
|
+
visibleByMesh.set(i, (visibles[i] ?? 1) !== 0);
|
|
5281
|
+
}
|
|
5282
|
+
applyMoc3Glues(
|
|
5283
|
+
worldByMesh,
|
|
5284
|
+
glues,
|
|
5285
|
+
keyTables,
|
|
5286
|
+
getParamByIndex,
|
|
5287
|
+
glueIntensities
|
|
5288
|
+
);
|
|
5289
|
+
for (const [artMeshIndex, world] of worldByMesh) {
|
|
5290
|
+
const sink = byArtMesh.get(artMeshIndex);
|
|
5291
|
+
if (!sink) continue;
|
|
5292
|
+
let pos = sink.vertexPositions;
|
|
5293
|
+
if (pos.length !== world.length) {
|
|
5294
|
+
pos = new Float32Array(world.length);
|
|
5295
|
+
sink.vertexPositions = pos;
|
|
5296
|
+
}
|
|
5297
|
+
normalizePositionsInto2(world, cw, ch, ppu, pos);
|
|
5298
|
+
const opacity = opacityByMesh.get(artMeshIndex) ?? 1;
|
|
5299
|
+
sink.renderOrder = orderByMesh.get(artMeshIndex) ?? sink.renderOrder;
|
|
5300
|
+
sink.visible = visibleByMesh.get(artMeshIndex) ?? true;
|
|
5301
|
+
const slot = sink.index;
|
|
5302
|
+
if (slot >= 0 && slot < poseOpacity.length) {
|
|
5303
|
+
poseOpacity[slot] = opacity;
|
|
5304
|
+
}
|
|
5305
|
+
sink.opacity = opacity;
|
|
5306
|
+
}
|
|
5307
|
+
}
|
|
5048
5308
|
|
|
5049
5309
|
// src/moc/decode.ts
|
|
5050
5310
|
function readMagic2(bytes) {
|
|
@@ -5095,49 +5355,90 @@ async function decodeMoc3(bytes) {
|
|
|
5095
5355
|
|
|
5096
5356
|
// src/moc/moc2.ts
|
|
5097
5357
|
import { detectModelSettingsFormat as detectModelSettingsFormat2 } from "@doki-land/live2d-core";
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5358
|
+
var stateByModel = /* @__PURE__ */ new WeakMap();
|
|
5359
|
+
function allocateMeshesFromProgram(program, drawableIds) {
|
|
5360
|
+
const meshes = [];
|
|
5361
|
+
const byId = /* @__PURE__ */ new Map();
|
|
5362
|
+
for (let i = 0; i < program.drawables.length; i++) {
|
|
5363
|
+
const d = program.drawables[i];
|
|
5364
|
+
const mesh = {
|
|
5365
|
+
index: d.index,
|
|
5366
|
+
textureIndex: d.textureIndex,
|
|
5367
|
+
vertexPositions: new Float32Array(d.positions),
|
|
5368
|
+
uvs: d.uvs,
|
|
5369
|
+
indices: d.indices,
|
|
5370
|
+
opacity: d.opacity,
|
|
5371
|
+
blendMode: d.blendMode,
|
|
5372
|
+
invertedMask: d.invertedMask,
|
|
5373
|
+
renderOrder: d.renderOrder,
|
|
5374
|
+
dynamicFlag: true,
|
|
5375
|
+
maskIndices: [...d.maskIndices],
|
|
5376
|
+
visible: d.visible
|
|
5377
|
+
};
|
|
5378
|
+
meshes.push(mesh);
|
|
5379
|
+
const id = drawableIds[i];
|
|
5380
|
+
if (id) byId.set(id, mesh);
|
|
5381
|
+
}
|
|
5382
|
+
return { meshes, byId };
|
|
5383
|
+
}
|
|
5384
|
+
function buildBindings(instance) {
|
|
5385
|
+
const bindings = [];
|
|
5386
|
+
const paramIndexById = /* @__PURE__ */ new Map();
|
|
5387
|
+
for (let i = 0; i < instance.program.parameters.length; i++) {
|
|
5388
|
+
const p = instance.program.parameters[i];
|
|
5389
|
+
const binding = {
|
|
5390
|
+
id: p.id,
|
|
5391
|
+
min: p.min,
|
|
5392
|
+
max: p.max,
|
|
5393
|
+
defaultValue: p.defaultValue,
|
|
5394
|
+
value: instance.parameterValues[i] ?? p.defaultValue
|
|
5395
|
+
};
|
|
5396
|
+
bindings.push(binding);
|
|
5397
|
+
paramIndexById.set(p.id, i);
|
|
5398
|
+
}
|
|
5399
|
+
return { bindings, paramIndexById };
|
|
5113
5400
|
}
|
|
5114
|
-
function
|
|
5115
|
-
let
|
|
5116
|
-
|
|
5117
|
-
|
|
5401
|
+
function syncBindingValues(state) {
|
|
5402
|
+
for (let i = 0; i < state.bindings.length; i++) {
|
|
5403
|
+
const b = state.bindings[i];
|
|
5404
|
+
b.value = state.instance.parameterValues[i] ?? b.defaultValue;
|
|
5118
5405
|
}
|
|
5119
|
-
return s;
|
|
5120
5406
|
}
|
|
5121
|
-
|
|
5407
|
+
function refreshDrawView(state) {
|
|
5408
|
+
const view = state.drawView;
|
|
5409
|
+
view.length = 0;
|
|
5410
|
+
for (const m of state.meshes) view.push(m);
|
|
5411
|
+
view.sort((a, b) => a.renderOrder - b.renderOrder || a.index - b.index);
|
|
5412
|
+
}
|
|
5122
5413
|
function bakePose(state) {
|
|
5123
|
-
|
|
5124
|
-
const
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5414
|
+
if (!state.poseDirty) return;
|
|
5415
|
+
const getParam = moc2ParamGetterFromValues(
|
|
5416
|
+
state.instance.program.parameters,
|
|
5417
|
+
state.instance.parameterValues
|
|
5418
|
+
);
|
|
5419
|
+
evaluateMoc2PoseInto(state.moc, getParam, state.byId);
|
|
5420
|
+
refreshDrawView(state);
|
|
5421
|
+
syncBindingValues(state);
|
|
5422
|
+
state.poseDirty = false;
|
|
5423
|
+
}
|
|
5424
|
+
function frameFromMeshes(meshes, timeSeconds) {
|
|
5425
|
+
const drawables = [];
|
|
5426
|
+
for (const m of meshes) {
|
|
5427
|
+
drawables.push({
|
|
5428
|
+
index: m.index,
|
|
5429
|
+
textureIndex: m.textureIndex,
|
|
5430
|
+
positions: m.vertexPositions,
|
|
5431
|
+
uvs: m.uvs,
|
|
5432
|
+
indices: m.indices,
|
|
5433
|
+
opacity: m.opacity,
|
|
5434
|
+
blendMode: m.blendMode,
|
|
5435
|
+
renderOrder: m.renderOrder,
|
|
5436
|
+
visible: m.visible,
|
|
5437
|
+
invertedMask: m.invertedMask,
|
|
5438
|
+
maskIndices: m.maskIndices
|
|
5439
|
+
});
|
|
5128
5440
|
}
|
|
5129
|
-
|
|
5130
|
-
getParam: moc2ParamGetterFromValues(
|
|
5131
|
-
state.moc.paramDefSet.params,
|
|
5132
|
-
values
|
|
5133
|
-
)
|
|
5134
|
-
});
|
|
5135
|
-
const next = createModelInstance(program);
|
|
5136
|
-
next.parameterValues.set(values);
|
|
5137
|
-
next.timeSeconds = timeSeconds;
|
|
5138
|
-
state.instance = next;
|
|
5139
|
-
state.bakedFingerprint = fp;
|
|
5140
|
-
state.lastFrame = evaluateFrame(next);
|
|
5441
|
+
return { timeSeconds, drawables };
|
|
5141
5442
|
}
|
|
5142
5443
|
var Moc2Backend = class {
|
|
5143
5444
|
format = "moc2";
|
|
@@ -5158,17 +5459,30 @@ var Moc2Backend = class {
|
|
|
5158
5459
|
const moc = shared?.moc2Model ?? new Moc2Parser(bytes).parseModel();
|
|
5159
5460
|
const program = moc2ModelToProgram(moc);
|
|
5160
5461
|
const instance = createModelInstance(program);
|
|
5462
|
+
const drawableIds = moc2DrawableIdsInProgramOrder(moc);
|
|
5463
|
+
const { meshes, byId } = allocateMeshesFromProgram(
|
|
5464
|
+
program,
|
|
5465
|
+
drawableIds
|
|
5466
|
+
);
|
|
5467
|
+
const { bindings, paramIndexById } = buildBindings(instance);
|
|
5468
|
+
const drawView = [];
|
|
5161
5469
|
const model = {
|
|
5162
5470
|
id: settings.name ?? settings.url,
|
|
5163
5471
|
settings,
|
|
5164
5472
|
format: "moc2"
|
|
5165
5473
|
};
|
|
5166
|
-
|
|
5474
|
+
const state = {
|
|
5167
5475
|
moc,
|
|
5168
5476
|
instance,
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5477
|
+
meshes,
|
|
5478
|
+
drawView,
|
|
5479
|
+
byId,
|
|
5480
|
+
poseDirty: true,
|
|
5481
|
+
bindings,
|
|
5482
|
+
paramIndexById
|
|
5483
|
+
};
|
|
5484
|
+
bakePose(state);
|
|
5485
|
+
stateByModel.set(model, state);
|
|
5172
5486
|
return model;
|
|
5173
5487
|
}
|
|
5174
5488
|
updateModel(model, deltaTimeSeconds) {
|
|
@@ -5176,46 +5490,43 @@ var Moc2Backend = class {
|
|
|
5176
5490
|
if (!state) return;
|
|
5177
5491
|
state.instance.timeSeconds += deltaTimeSeconds;
|
|
5178
5492
|
bakePose(state);
|
|
5179
|
-
if (state.lastFrame) {
|
|
5180
|
-
state.lastFrame = {
|
|
5181
|
-
...state.lastFrame,
|
|
5182
|
-
timeSeconds: state.instance.timeSeconds
|
|
5183
|
-
};
|
|
5184
|
-
}
|
|
5185
5493
|
}
|
|
5186
5494
|
getDrawables(model) {
|
|
5187
5495
|
const state = stateByModel.get(model);
|
|
5188
5496
|
if (!state) return [];
|
|
5189
5497
|
bakePose(state);
|
|
5190
|
-
|
|
5191
|
-
state.lastFrame = frame;
|
|
5192
|
-
return frame.drawables.map(toDrawableMesh);
|
|
5498
|
+
return state.drawView;
|
|
5193
5499
|
}
|
|
5194
5500
|
captureFrame(model) {
|
|
5195
5501
|
const state = stateByModel.get(model);
|
|
5196
5502
|
if (!state) return null;
|
|
5197
5503
|
bakePose(state);
|
|
5198
|
-
|
|
5199
|
-
state.lastFrame = frame;
|
|
5200
|
-
return frame;
|
|
5504
|
+
return frameFromMeshes(state.drawView, state.instance.timeSeconds);
|
|
5201
5505
|
}
|
|
5202
5506
|
setParameter(model, id, value) {
|
|
5203
5507
|
const state = stateByModel.get(model);
|
|
5204
5508
|
if (!state) return;
|
|
5205
5509
|
setParameterValue(state.instance, id, value);
|
|
5206
|
-
|
|
5207
|
-
|
|
5510
|
+
const index = state.paramIndexById.get(id);
|
|
5511
|
+
if (index !== void 0) {
|
|
5512
|
+
const binding = state.bindings[index];
|
|
5513
|
+
if (binding) {
|
|
5514
|
+
binding.value = state.instance.parameterValues[index] ?? binding.defaultValue;
|
|
5515
|
+
}
|
|
5516
|
+
}
|
|
5517
|
+
state.poseDirty = true;
|
|
5518
|
+
}
|
|
5519
|
+
resolveParameter(model, id) {
|
|
5520
|
+
const state = stateByModel.get(model);
|
|
5521
|
+
if (!state) return void 0;
|
|
5522
|
+
return state.paramIndexById.get(id);
|
|
5208
5523
|
}
|
|
5209
5524
|
listParameters(model) {
|
|
5210
5525
|
const state = stateByModel.get(model);
|
|
5211
5526
|
if (!state) return [];
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
max: p.max,
|
|
5216
|
-
defaultValue: p.defaultValue,
|
|
5217
|
-
value: state.instance.parameterValues[i] ?? p.defaultValue
|
|
5218
|
-
}));
|
|
5527
|
+
bakePose(state);
|
|
5528
|
+
syncBindingValues(state);
|
|
5529
|
+
return state.bindings;
|
|
5219
5530
|
}
|
|
5220
5531
|
hitTest(_model, _x, _y) {
|
|
5221
5532
|
return null;
|
|
@@ -5223,6 +5534,10 @@ var Moc2Backend = class {
|
|
|
5223
5534
|
destroyModel(model) {
|
|
5224
5535
|
stateByModel.delete(model);
|
|
5225
5536
|
}
|
|
5537
|
+
/** Test/harness: stable program + instance refs. */
|
|
5538
|
+
getResidentInstance(model) {
|
|
5539
|
+
return stateByModel.get(model)?.instance ?? null;
|
|
5540
|
+
}
|
|
5226
5541
|
};
|
|
5227
5542
|
function createMoc2Backend() {
|
|
5228
5543
|
return new Moc2Backend();
|
|
@@ -5261,11 +5576,12 @@ function cascadedPartOpacity(tables, artMeshIndex, overrides) {
|
|
|
5261
5576
|
}
|
|
5262
5577
|
|
|
5263
5578
|
// src/moc/moc3.ts
|
|
5264
|
-
|
|
5265
|
-
|
|
5579
|
+
var stateByModel2 = /* @__PURE__ */ new WeakMap();
|
|
5580
|
+
function allocateMeshesFromProgram2(program) {
|
|
5581
|
+
return program.drawables.map((d) => ({
|
|
5266
5582
|
index: d.index,
|
|
5267
5583
|
textureIndex: d.textureIndex,
|
|
5268
|
-
vertexPositions: d.positions,
|
|
5584
|
+
vertexPositions: new Float32Array(d.positions),
|
|
5269
5585
|
uvs: d.uvs,
|
|
5270
5586
|
indices: d.indices,
|
|
5271
5587
|
opacity: d.opacity,
|
|
@@ -5275,34 +5591,82 @@ function toDrawableMesh2(d) {
|
|
|
5275
5591
|
dynamicFlag: true,
|
|
5276
5592
|
maskIndices: [...d.maskIndices],
|
|
5277
5593
|
visible: d.visible
|
|
5278
|
-
};
|
|
5594
|
+
}));
|
|
5595
|
+
}
|
|
5596
|
+
function buildBindings2(instance) {
|
|
5597
|
+
const bindings = [];
|
|
5598
|
+
const paramIndexById = /* @__PURE__ */ new Map();
|
|
5599
|
+
for (let i = 0; i < instance.program.parameters.length; i++) {
|
|
5600
|
+
const p = instance.program.parameters[i];
|
|
5601
|
+
bindings.push({
|
|
5602
|
+
id: p.id,
|
|
5603
|
+
min: p.min,
|
|
5604
|
+
max: p.max,
|
|
5605
|
+
defaultValue: p.defaultValue,
|
|
5606
|
+
value: instance.parameterValues[i] ?? p.defaultValue
|
|
5607
|
+
});
|
|
5608
|
+
paramIndexById.set(p.id, i);
|
|
5609
|
+
}
|
|
5610
|
+
return { bindings, paramIndexById };
|
|
5279
5611
|
}
|
|
5280
|
-
function
|
|
5281
|
-
let
|
|
5282
|
-
|
|
5283
|
-
|
|
5612
|
+
function syncBindingValues2(state) {
|
|
5613
|
+
for (let i = 0; i < state.bindings.length; i++) {
|
|
5614
|
+
const b = state.bindings[i];
|
|
5615
|
+
b.value = state.instance.parameterValues[i] ?? b.defaultValue;
|
|
5616
|
+
}
|
|
5617
|
+
}
|
|
5618
|
+
function refreshDrawView2(state) {
|
|
5619
|
+
const view = state.drawView;
|
|
5620
|
+
view.length = 0;
|
|
5621
|
+
for (const m of state.meshes) view.push(m);
|
|
5622
|
+
view.sort((a, b) => a.renderOrder - b.renderOrder || a.index - b.index);
|
|
5623
|
+
}
|
|
5624
|
+
function applyPartOpacity(state) {
|
|
5625
|
+
const tables = state.doc ? readMoc3PartTables(state.doc) : null;
|
|
5626
|
+
for (const mesh of state.meshes) {
|
|
5627
|
+
const base = state.poseOpacity[mesh.index] ?? mesh.opacity;
|
|
5628
|
+
if (!tables || state.partOpacity.size === 0) {
|
|
5629
|
+
mesh.opacity = base;
|
|
5630
|
+
continue;
|
|
5631
|
+
}
|
|
5632
|
+
mesh.opacity = base * cascadedPartOpacity(tables, mesh.index, state.partOpacity);
|
|
5284
5633
|
}
|
|
5285
|
-
return s;
|
|
5286
5634
|
}
|
|
5287
|
-
var stateByModel2 = /* @__PURE__ */ new WeakMap();
|
|
5288
5635
|
function bakePose2(state) {
|
|
5289
|
-
if (!state.
|
|
5290
|
-
|
|
5291
|
-
|
|
5636
|
+
if (!state.poseDirty) return;
|
|
5637
|
+
if (state.doc) {
|
|
5638
|
+
const values = state.instance.parameterValues;
|
|
5639
|
+
evaluateMoc3PoseInto(
|
|
5640
|
+
state.doc,
|
|
5641
|
+
(i) => values[i] ?? 0,
|
|
5642
|
+
state.byArtMesh,
|
|
5643
|
+
state.poseOpacity
|
|
5644
|
+
);
|
|
5645
|
+
} else {
|
|
5646
|
+
evaluateFrameInto(state.instance, state.meshes, state.poseOpacity);
|
|
5292
5647
|
}
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5648
|
+
refreshDrawView2(state);
|
|
5649
|
+
syncBindingValues2(state);
|
|
5650
|
+
state.poseDirty = false;
|
|
5651
|
+
}
|
|
5652
|
+
function frameFromMeshes2(meshes, timeSeconds) {
|
|
5653
|
+
const drawables = [];
|
|
5654
|
+
for (const m of meshes) {
|
|
5655
|
+
drawables.push({
|
|
5656
|
+
index: m.index,
|
|
5657
|
+
textureIndex: m.textureIndex,
|
|
5658
|
+
positions: m.vertexPositions,
|
|
5659
|
+
uvs: m.uvs,
|
|
5660
|
+
indices: m.indices,
|
|
5661
|
+
opacity: m.opacity,
|
|
5662
|
+
blendMode: m.blendMode,
|
|
5663
|
+
renderOrder: m.renderOrder,
|
|
5664
|
+
visible: m.visible,
|
|
5665
|
+
invertedMask: m.invertedMask,
|
|
5666
|
+
maskIndices: m.maskIndices
|
|
5667
|
+
});
|
|
5668
|
+
}
|
|
5669
|
+
return { timeSeconds, drawables };
|
|
5306
5670
|
}
|
|
5307
5671
|
var Moc3Backend = class {
|
|
5308
5672
|
format = "moc3";
|
|
@@ -5330,18 +5694,39 @@ var Moc3Backend = class {
|
|
|
5330
5694
|
program = moc3DocumentToProgram(doc);
|
|
5331
5695
|
}
|
|
5332
5696
|
const instance = createModelInstance(program);
|
|
5697
|
+
const meshes = allocateMeshesFromProgram2(program);
|
|
5698
|
+
const byArtMesh = /* @__PURE__ */ new Map();
|
|
5699
|
+
if (doc) {
|
|
5700
|
+
const artOrder = moc3ArtMeshIndicesInProgramOrder(doc);
|
|
5701
|
+
for (let i = 0; i < artOrder.length; i++) {
|
|
5702
|
+
const art = artOrder[i];
|
|
5703
|
+
const mesh = meshes[i];
|
|
5704
|
+
if (mesh) byArtMesh.set(art, mesh);
|
|
5705
|
+
}
|
|
5706
|
+
}
|
|
5707
|
+
const poseOpacity = new Float32Array(meshes.length);
|
|
5708
|
+
for (const m of meshes) poseOpacity[m.index] = m.opacity;
|
|
5709
|
+
const { bindings, paramIndexById } = buildBindings2(instance);
|
|
5333
5710
|
const model = {
|
|
5334
5711
|
id: settings.name ?? settings.url,
|
|
5335
5712
|
settings,
|
|
5336
5713
|
format: "moc3"
|
|
5337
5714
|
};
|
|
5338
|
-
|
|
5715
|
+
const state = {
|
|
5339
5716
|
doc,
|
|
5340
5717
|
instance,
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5718
|
+
meshes,
|
|
5719
|
+
drawView: [],
|
|
5720
|
+
byArtMesh,
|
|
5721
|
+
poseOpacity,
|
|
5722
|
+
poseDirty: true,
|
|
5723
|
+
partOpacity: /* @__PURE__ */ new Map(),
|
|
5724
|
+
bindings,
|
|
5725
|
+
paramIndexById
|
|
5726
|
+
};
|
|
5727
|
+
bakePose2(state);
|
|
5728
|
+
applyPartOpacity(state);
|
|
5729
|
+
stateByModel2.set(model, state);
|
|
5345
5730
|
return model;
|
|
5346
5731
|
}
|
|
5347
5732
|
updateModel(model, deltaTimeSeconds) {
|
|
@@ -5349,49 +5734,34 @@ var Moc3Backend = class {
|
|
|
5349
5734
|
if (!state) return;
|
|
5350
5735
|
state.instance.timeSeconds += deltaTimeSeconds;
|
|
5351
5736
|
bakePose2(state);
|
|
5352
|
-
|
|
5353
|
-
state.lastFrame = {
|
|
5354
|
-
...state.lastFrame,
|
|
5355
|
-
timeSeconds: state.instance.timeSeconds
|
|
5356
|
-
};
|
|
5357
|
-
}
|
|
5737
|
+
applyPartOpacity(state);
|
|
5358
5738
|
}
|
|
5359
5739
|
getDrawables(model) {
|
|
5360
5740
|
const state = stateByModel2.get(model);
|
|
5361
5741
|
if (!state) return [];
|
|
5362
5742
|
bakePose2(state);
|
|
5363
|
-
|
|
5364
|
-
state.
|
|
5365
|
-
const tables = state.doc ? readMoc3PartTables(state.doc) : null;
|
|
5366
|
-
return frame.drawables.map((d) => {
|
|
5367
|
-
const mesh = toDrawableMesh2(d);
|
|
5368
|
-
if (!tables || state.partOpacity.size === 0) return mesh;
|
|
5369
|
-
const mul = cascadedPartOpacity(tables, d.index, state.partOpacity);
|
|
5370
|
-
return { ...mesh, opacity: mesh.opacity * mul };
|
|
5371
|
-
});
|
|
5743
|
+
applyPartOpacity(state);
|
|
5744
|
+
return state.drawView;
|
|
5372
5745
|
}
|
|
5373
5746
|
captureFrame(model) {
|
|
5374
5747
|
const state = stateByModel2.get(model);
|
|
5375
5748
|
if (!state) return null;
|
|
5376
5749
|
bakePose2(state);
|
|
5377
|
-
|
|
5378
|
-
state.
|
|
5379
|
-
const tables = state.doc ? readMoc3PartTables(state.doc) : null;
|
|
5380
|
-
if (!tables || state.partOpacity.size === 0) return frame;
|
|
5381
|
-
return {
|
|
5382
|
-
...frame,
|
|
5383
|
-
drawables: frame.drawables.map((d) => ({
|
|
5384
|
-
...d,
|
|
5385
|
-
opacity: d.opacity * cascadedPartOpacity(tables, d.index, state.partOpacity)
|
|
5386
|
-
}))
|
|
5387
|
-
};
|
|
5750
|
+
applyPartOpacity(state);
|
|
5751
|
+
return frameFromMeshes2(state.drawView, state.instance.timeSeconds);
|
|
5388
5752
|
}
|
|
5389
5753
|
setParameter(model, id, value) {
|
|
5390
5754
|
const state = stateByModel2.get(model);
|
|
5391
5755
|
if (!state) return;
|
|
5392
5756
|
setParameterValue(state.instance, id, value);
|
|
5393
|
-
|
|
5394
|
-
|
|
5757
|
+
const index = state.paramIndexById.get(id);
|
|
5758
|
+
if (index !== void 0) {
|
|
5759
|
+
const binding = state.bindings[index];
|
|
5760
|
+
if (binding) {
|
|
5761
|
+
binding.value = state.instance.parameterValues[index] ?? binding.defaultValue;
|
|
5762
|
+
}
|
|
5763
|
+
}
|
|
5764
|
+
state.poseDirty = true;
|
|
5395
5765
|
}
|
|
5396
5766
|
setPartOpacity(model, id, value) {
|
|
5397
5767
|
const state = stateByModel2.get(model);
|
|
@@ -5399,16 +5769,17 @@ var Moc3Backend = class {
|
|
|
5399
5769
|
const v = Number.isFinite(value) ? Math.min(1, Math.max(0, value)) : 1;
|
|
5400
5770
|
state.partOpacity.set(id, v);
|
|
5401
5771
|
}
|
|
5772
|
+
resolveParameter(model, id) {
|
|
5773
|
+
const state = stateByModel2.get(model);
|
|
5774
|
+
if (!state) return void 0;
|
|
5775
|
+
return state.paramIndexById.get(id);
|
|
5776
|
+
}
|
|
5402
5777
|
listParameters(model) {
|
|
5403
5778
|
const state = stateByModel2.get(model);
|
|
5404
5779
|
if (!state) return [];
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
max: p.max,
|
|
5409
|
-
defaultValue: p.defaultValue,
|
|
5410
|
-
value: state.instance.parameterValues[i] ?? p.defaultValue
|
|
5411
|
-
}));
|
|
5780
|
+
bakePose2(state);
|
|
5781
|
+
syncBindingValues2(state);
|
|
5782
|
+
return state.bindings;
|
|
5412
5783
|
}
|
|
5413
5784
|
hitTest(_model, _x, _y) {
|
|
5414
5785
|
return null;
|
|
@@ -5416,6 +5787,9 @@ var Moc3Backend = class {
|
|
|
5416
5787
|
destroyModel(model) {
|
|
5417
5788
|
stateByModel2.delete(model);
|
|
5418
5789
|
}
|
|
5790
|
+
getResidentInstance(model) {
|
|
5791
|
+
return stateByModel2.get(model)?.instance ?? null;
|
|
5792
|
+
}
|
|
5419
5793
|
};
|
|
5420
5794
|
function createMoc3Backend() {
|
|
5421
5795
|
return new Moc3Backend();
|