@ikijs/engine 0.2.0 → 0.3.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 +23 -29
- package/dist/index.d.mts +58 -2
- package/dist/index.d.ts +58 -2
- package/dist/index.js +74 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +73 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1063,6 +1063,22 @@ function randomInDisk(rng, radius) {
|
|
|
1063
1063
|
return [r * Math.cos(theta), r * Math.sin(theta)];
|
|
1064
1064
|
}
|
|
1065
1065
|
var IdleMotion = class {
|
|
1066
|
+
/**
|
|
1067
|
+
* Every parameter id {@link update} and `emitRestingPose` write, in write
|
|
1068
|
+
* order. Published so a host (or IkiMotion) can restore them after it
|
|
1069
|
+
* stops driving — keep in step with those two methods; the test suite
|
|
1070
|
+
* pins this list to the actual emissions.
|
|
1071
|
+
*/
|
|
1072
|
+
drivenParameterIds = [
|
|
1073
|
+
StandardParameter.EyeOpenLeft,
|
|
1074
|
+
StandardParameter.EyeOpenRight,
|
|
1075
|
+
StandardParameter.Breath,
|
|
1076
|
+
StandardParameter.EyeballX,
|
|
1077
|
+
StandardParameter.EyeballY,
|
|
1078
|
+
StandardParameter.AngleX,
|
|
1079
|
+
StandardParameter.AngleY,
|
|
1080
|
+
StandardParameter.AngleZ
|
|
1081
|
+
];
|
|
1066
1082
|
sink;
|
|
1067
1083
|
rng;
|
|
1068
1084
|
// Internal clock: advances by clamped dt, NOT by raw wall-clock jumps.
|
|
@@ -1195,6 +1211,8 @@ function signedNormalized(value, param) {
|
|
|
1195
1211
|
return clamp((value - rest) / den, -1, 1);
|
|
1196
1212
|
}
|
|
1197
1213
|
var PhysicsMotion = class {
|
|
1214
|
+
/** The output parameter of every rig, in rig order — what `emit` writes. */
|
|
1215
|
+
drivenParameterIds;
|
|
1198
1216
|
rigs;
|
|
1199
1217
|
read;
|
|
1200
1218
|
sink;
|
|
@@ -1208,6 +1226,7 @@ var PhysicsMotion = class {
|
|
|
1208
1226
|
this.sink = sink;
|
|
1209
1227
|
this.params = new Map(params.map((p) => [p.id, p]));
|
|
1210
1228
|
this.state = rigs.map(() => ({ x: 0, v: 0 }));
|
|
1229
|
+
this.drivenParameterIds = rigs.map((rig) => rig.output.parameter);
|
|
1211
1230
|
}
|
|
1212
1231
|
/**
|
|
1213
1232
|
* Advance every rig to the given wall-clock timestamp (milliseconds).
|
|
@@ -1278,6 +1297,8 @@ var PhysicsMotion = class {
|
|
|
1278
1297
|
var DEG2RAD = Math.PI / 180;
|
|
1279
1298
|
var RAD2DEG = 180 / Math.PI;
|
|
1280
1299
|
var HairChainMotion = class {
|
|
1300
|
+
/** Every segment's output, chain by chain — what `emitSegment` writes. */
|
|
1301
|
+
drivenParameterIds;
|
|
1281
1302
|
chainData;
|
|
1282
1303
|
params;
|
|
1283
1304
|
deformers;
|
|
@@ -1298,6 +1319,9 @@ var HairChainMotion = class {
|
|
|
1298
1319
|
),
|
|
1299
1320
|
state: chain.segments.map(() => ({ angle: 0, angularVelocity: 0 }))
|
|
1300
1321
|
}));
|
|
1322
|
+
this.drivenParameterIds = chains.flatMap(
|
|
1323
|
+
(c) => c.segments.map((s) => s.output.parameter)
|
|
1324
|
+
);
|
|
1301
1325
|
}
|
|
1302
1326
|
/**
|
|
1303
1327
|
* Advance every chain to the given wall-clock timestamp (milliseconds).
|
|
@@ -1410,9 +1434,58 @@ var HairChainMotion = class {
|
|
|
1410
1434
|
);
|
|
1411
1435
|
}
|
|
1412
1436
|
};
|
|
1437
|
+
|
|
1438
|
+
// src/iki-motion.ts
|
|
1439
|
+
var IkiMotion = class {
|
|
1440
|
+
/**
|
|
1441
|
+
* Idle ids, then rig outputs, then chain-segment outputs, deduplicated and
|
|
1442
|
+
* insertion-ordered. May name ids the model lacks (the player silently
|
|
1443
|
+
* drops writes to unknown ids) — intersect with the model's parameters if
|
|
1444
|
+
* you mirror into your own store.
|
|
1445
|
+
*/
|
|
1446
|
+
drivenParameterIds;
|
|
1447
|
+
idle;
|
|
1448
|
+
physics;
|
|
1449
|
+
chains;
|
|
1450
|
+
constructor(model, read, sink) {
|
|
1451
|
+
const rigs = model.physics ?? [];
|
|
1452
|
+
const chains = model.physicsChains ?? [];
|
|
1453
|
+
this.idle = new IdleMotion(sink);
|
|
1454
|
+
this.physics = new PhysicsMotion(rigs, model.parameters, read, sink);
|
|
1455
|
+
this.chains = new HairChainMotion(
|
|
1456
|
+
chains,
|
|
1457
|
+
model.parameters,
|
|
1458
|
+
model.deformers ?? [],
|
|
1459
|
+
read,
|
|
1460
|
+
sink
|
|
1461
|
+
);
|
|
1462
|
+
this.drivenParameterIds = [
|
|
1463
|
+
.../* @__PURE__ */ new Set([
|
|
1464
|
+
...this.idle.drivenParameterIds,
|
|
1465
|
+
...this.physics.drivenParameterIds,
|
|
1466
|
+
...this.chains.drivenParameterIds
|
|
1467
|
+
])
|
|
1468
|
+
];
|
|
1469
|
+
}
|
|
1470
|
+
/**
|
|
1471
|
+
* Advance idle, then physics, then chains to the same wall-clock timestamp
|
|
1472
|
+
* (milliseconds). Order is load-bearing: `PhysicsMotion` reads its input
|
|
1473
|
+
* parameters (typically `ParamAngleX/Z`) through `read`, and the head sway
|
|
1474
|
+
* idle wrote THIS frame is what the springs must lag behind; `HairChainMotion`
|
|
1475
|
+
* then resolves its anchor deformer's world rotation from that same
|
|
1476
|
+
* just-written pose (which may include a physics output). One timestamp for
|
|
1477
|
+
* all three keeps their dt in lockstep.
|
|
1478
|
+
*/
|
|
1479
|
+
update(nowMs) {
|
|
1480
|
+
this.idle.update(nowMs);
|
|
1481
|
+
this.physics.update(nowMs);
|
|
1482
|
+
this.chains.update(nowMs);
|
|
1483
|
+
}
|
|
1484
|
+
};
|
|
1413
1485
|
export {
|
|
1414
1486
|
HairChainMotion,
|
|
1415
1487
|
IdleMotion,
|
|
1488
|
+
IkiMotion,
|
|
1416
1489
|
IkiPlayer,
|
|
1417
1490
|
ParameterStore,
|
|
1418
1491
|
PhysicsMotion,
|