@rig-c/play 1.18.0 → 1.20.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/dist/DomRenderer.d.ts +7 -2
- package/dist/DomRenderer.d.ts.map +1 -1
- package/dist/DomTexture.d.ts +8 -0
- package/dist/DomTexture.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +157 -39
- package/dist/index.js.map +1 -1
- package/dist/loadModel.d.ts +10 -6
- package/dist/loadModel.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/DomRenderer.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LiveFrame } from './liveFrame.js';
|
|
2
|
-
import { type RegionImage } from './DomTexture.js';
|
|
2
|
+
import { type AtlasRegion, type RegionImage } from './DomTexture.js';
|
|
3
3
|
import type { PosedFrame } from './posedFrame.js';
|
|
4
4
|
/** Rasterizer used for the mesh (deform) tier. */
|
|
5
5
|
export type MeshBackend = 'canvas2d' | 'webgl';
|
|
@@ -40,6 +40,7 @@ export declare class DomRenderer {
|
|
|
40
40
|
private readonly root;
|
|
41
41
|
private readonly regionImages;
|
|
42
42
|
private readonly pages;
|
|
43
|
+
private readonly atlasRegions;
|
|
43
44
|
/**
|
|
44
45
|
* Apply the clips the frame carries (default). Each element drawn inside a
|
|
45
46
|
* clip gets a CSS `clip-path` in its own local frame — an element-level
|
|
@@ -63,6 +64,8 @@ export declare class DomRenderer {
|
|
|
63
64
|
clipping: boolean;
|
|
64
65
|
/** Clips applied last frame — distinct clip polygons over the drawn slots. */
|
|
65
66
|
clipCount: number;
|
|
67
|
+
/** Atlas rigid canvases rasterized in the last frame; never includes meshes. */
|
|
68
|
+
rigidRasterCount: number;
|
|
66
69
|
/**
|
|
67
70
|
* Clips in the frame NOT applied last frame: `clipping` is false, or the
|
|
68
71
|
* polygon has fewer than three points. A clip the runtime itself ignores (a
|
|
@@ -171,11 +174,13 @@ export declare class DomRenderer {
|
|
|
171
174
|
* and scaling of the root belong to the caller.
|
|
172
175
|
* @param regionImages Unpacked per-region bitmaps (for the rigid tier),
|
|
173
176
|
* keyed by region name — `PosedRegion.region`.
|
|
177
|
+
* @param atlasRegions Optional page-backed rigid sources, from createAtlasRegions
|
|
178
|
+
* or ModelAssets.atlasRegions. A matching entry takes precedence over regionImages.
|
|
174
179
|
* @param pages Page images (for the mesh tier), keyed by page name —
|
|
175
180
|
* `PosedMesh.page`. Read on every mesh draw, so a caller may fill it after
|
|
176
181
|
* construction.
|
|
177
182
|
*/
|
|
178
|
-
constructor(root: HTMLElement, regionImages: ReadonlyMap<string, RegionImage>, pages?: ReadonlyMap<string, HTMLImageElement>);
|
|
183
|
+
constructor(root: HTMLElement, regionImages: ReadonlyMap<string, RegionImage>, pages?: ReadonlyMap<string, HTMLImageElement>, atlasRegions?: ReadonlyMap<string, AtlasRegion>);
|
|
179
184
|
/**
|
|
180
185
|
* Backing-store pixels currently allocated across the mesh canvases
|
|
181
186
|
* (Σ width × height). Computed on demand from the views — nothing is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DomRenderer.d.ts","sourceRoot":"","sources":["../src/DomRenderer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,
|
|
1
|
+
{"version":3,"file":"DomRenderer.d.ts","sourceRoot":"","sources":["../src/DomRenderer.ts"],"names":[],"mappings":"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"}
|
package/dist/DomTexture.d.ts
CHANGED
|
@@ -46,6 +46,14 @@ export interface RegionImage {
|
|
|
46
46
|
/** Unpacked height in atlas units — see `width`. */
|
|
47
47
|
height: number;
|
|
48
48
|
}
|
|
49
|
+
/** One region's page-backed source, without an encoded per-region URL. */
|
|
50
|
+
export interface AtlasRegion {
|
|
51
|
+
readonly page: PageLayout;
|
|
52
|
+
readonly region: PageRegion;
|
|
53
|
+
readonly image: HTMLImageElement;
|
|
54
|
+
}
|
|
55
|
+
/** Maps atlas entries in layout order; duplicate names keep the last entry. */
|
|
56
|
+
export declare function createAtlasRegions(pages: readonly PageLayout[], images: ReadonlyMap<string, HTMLImageElement>): Map<string, AtlasRegion>;
|
|
49
57
|
/**
|
|
50
58
|
* Page pixels in the alpha convention a DOM/canvas2d consumer needs: the page
|
|
51
59
|
* image itself, or the derived canvas below when the page is premultiplied.
|
package/dist/DomTexture.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DomTexture.d.ts","sourceRoot":"","sources":["../src/DomTexture.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,SAAS,UAAU,EAAE,CAAC;CAChC;AAQD,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;;;OASG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;CAChB;
|
|
1
|
+
{"version":3,"file":"DomTexture.d.ts","sourceRoot":"","sources":["../src/DomTexture.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,SAAS,UAAU,EAAE,CAAC;CAChC;AAQD,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;;;OASG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,0EAA0E;AAC1E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;CAClC;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAC5C,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAQ1B;AAwBD;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;AAqC9D;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,OAAO,GAAG,UAAU,CAcpF;AAiTD;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,oBAAoB;IACnC,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACjD,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CA4EnC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,IAAI,CAEpE"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { type CanvasBackend, CanvasRenderer, type CanvasViewport } from './CanvasRenderer.js';
|
|
2
2
|
export { DomRenderer, type MeshBackend, type MeshSourceRect } from './DomRenderer.js';
|
|
3
|
-
export { type PageLayout, type PageRegion, type RegionEncoding, type RegionImage, revokeRegions, type UnpackRegionsOptions, unpackRegions } from './DomTexture.js';
|
|
3
|
+
export { type AtlasRegion, createAtlasRegions, type PageLayout, type PageRegion, type RegionEncoding, type RegionImage, revokeRegions, type UnpackRegionsOptions, unpackRegions } from './DomTexture.js';
|
|
4
4
|
export { type LoadModelOptions, loadModel, type ModelAssets, type ModelDocument, readSetupMesh, type RegionLoading, type RigSet, type SetupMesh, type SetupMeshTarget } from './loadModel.js';
|
|
5
5
|
export { type AdjustableBones, type BoneAdjust, type BoneAdjustContext, type BoneLocals, type BoneWorld, type PhysicsParameters, type PhysicsParameterPatch, type PhysicsParameterRead, type PlayOptions, type PoseBounds, type QueueOptions, type RenderMode, type RigComplete, type RigEnvironment, type RigEvent, RigPlayer, type RigPlayerOptions, type SetActivationOptions, type SlotFilter, type SlotIdentity, type SlotIdentityReason, type SlotIdentitySnapshot, type TrackEntry } from './player.js';
|
|
6
6
|
export type { BlendMode, PosedClip, PosedFrame, PosedMesh, PosedRegion, PosedSlot, } from './posedFrame.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACtF,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACtF,OAAO,EAAE,KAAK,WAAW,EAAE,kBAAkB,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACzM,OAAO,EAAE,KAAK,gBAAgB,EAAE,SAAS,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC9L,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,iBAAiB,EAAE,KAAK,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,KAAK,QAAQ,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAC/e,YAAY,EACV,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,EACT,WAAW,EACX,SAAS,GACV,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -964,7 +964,8 @@ function clipHalf(input, p, q) {
|
|
|
964
964
|
return { points: out, cut };
|
|
965
965
|
}
|
|
966
966
|
function clipThrough(shape, vertices, triangles, uvs, clip = clipTriangles, reading = {}) {
|
|
967
|
-
|
|
967
|
+
let plan = clipShapeOf(shape);
|
|
968
|
+
if (plan.kind === "pieces") plan = clipShapeOf({ ...shape, polygon: shape.polygon.map(Math.fround) });
|
|
968
969
|
if (plan.kind === "refused") return null;
|
|
969
970
|
if (plan.kind === "convex") return clip(plan.polygon, vertices, triangles, uvs);
|
|
970
971
|
const f = Math.fround;
|
|
@@ -6703,6 +6704,19 @@ function drawnRegions(doc, shown, order, source) {
|
|
|
6703
6704
|
if (unmeasured.length > 0) return { drawn: null, why: `${unmeasured.join("; ")} — which of the two counts the runtime steps it over was not measured` };
|
|
6704
6705
|
return { drawn, why: null };
|
|
6705
6706
|
}
|
|
6707
|
+
function createAtlasRegions(pages, images) {
|
|
6708
|
+
const result = /* @__PURE__ */ new Map();
|
|
6709
|
+
for (const page of pages) {
|
|
6710
|
+
const image = images.get(page.name);
|
|
6711
|
+
if (!image) throw new Error(`Missing page image: ${page.name}`);
|
|
6712
|
+
for (const region of page.regions) result.set(region.name, { page, region, image });
|
|
6713
|
+
}
|
|
6714
|
+
return result;
|
|
6715
|
+
}
|
|
6716
|
+
function drawAtlasRegion(canvas, entry, ratio) {
|
|
6717
|
+
const plan = planCut(entry, entry.image);
|
|
6718
|
+
paintRegion(canvas, entry, entry.image, plan, ratio);
|
|
6719
|
+
}
|
|
6706
6720
|
const ownedUrls = /* @__PURE__ */ new Set();
|
|
6707
6721
|
function revokeOwned(url) {
|
|
6708
6722
|
if (!ownedUrls.delete(url)) return;
|
|
@@ -6794,16 +6808,7 @@ async function cutRegion(placed, pageImages, encoding) {
|
|
|
6794
6808
|
const plan = planCut(placed, image);
|
|
6795
6809
|
if (plan.passThrough) return { url: image.src, width: w, height: h };
|
|
6796
6810
|
const canvas = document.createElement("canvas");
|
|
6797
|
-
canvas
|
|
6798
|
-
canvas.height = plan.ch;
|
|
6799
|
-
const ctx = canvas.getContext("2d");
|
|
6800
|
-
if (!ctx) throw new Error("2d context unavailable");
|
|
6801
|
-
if (region.degrees === 90) {
|
|
6802
|
-
ctx.translate(plan.cw, 0);
|
|
6803
|
-
ctx.rotate(Math.PI / 2);
|
|
6804
|
-
}
|
|
6805
|
-
const source = straightAlphaSource(image, page.pma === true);
|
|
6806
|
-
ctx.drawImage(source, plan.sx, plan.sy, plan.sw, plan.sh, 0, 0, plan.sw, plan.sh);
|
|
6811
|
+
paintRegion(canvas, placed, image, plan);
|
|
6807
6812
|
if (encoding === "data") return { url: canvas.toDataURL("image/png"), width: w, height: h };
|
|
6808
6813
|
const blob = await new Promise((resolve, reject) => {
|
|
6809
6814
|
canvas.toBlob((b) => b ? resolve(b) : reject(new Error("toBlob failed")), "image/png");
|
|
@@ -6812,6 +6817,22 @@ async function cutRegion(placed, pageImages, encoding) {
|
|
|
6812
6817
|
ownedUrls.add(url);
|
|
6813
6818
|
return { url, width: w, height: h };
|
|
6814
6819
|
}
|
|
6820
|
+
function paintRegion(canvas, placed, image, plan, ratio) {
|
|
6821
|
+
canvas.width = ratio === void 0 ? plan.cw : Math.min(plan.cw, Math.max(1, Math.ceil(placed.region.width * ratio)));
|
|
6822
|
+
canvas.height = ratio === void 0 ? plan.ch : Math.min(plan.ch, Math.max(1, Math.ceil(placed.region.height * ratio)));
|
|
6823
|
+
const ctx = canvas.getContext("2d");
|
|
6824
|
+
if (!ctx) throw new Error("2d context unavailable");
|
|
6825
|
+
if (ratio !== void 0) {
|
|
6826
|
+
ctx.imageSmoothingQuality = "high";
|
|
6827
|
+
ctx.scale(canvas.width / plan.cw, canvas.height / plan.ch);
|
|
6828
|
+
}
|
|
6829
|
+
if (placed.region.degrees === 90) {
|
|
6830
|
+
ctx.translate(plan.cw, 0);
|
|
6831
|
+
ctx.rotate(Math.PI / 2);
|
|
6832
|
+
}
|
|
6833
|
+
const source = straightAlphaSource(image, placed.page.pma === true);
|
|
6834
|
+
ctx.drawImage(source, plan.sx, plan.sy, plan.sw, plan.sh, 0, 0, plan.sw, plan.sh);
|
|
6835
|
+
}
|
|
6815
6836
|
async function unpackRegions(pages, pageImages, options = {}) {
|
|
6816
6837
|
const encoding = options.encoding ?? "blob";
|
|
6817
6838
|
if (encoding !== "blob" && encoding !== "data") throw new Error(`encoding must be 'blob' or 'data', got ${String(options.encoding)}`);
|
|
@@ -7403,14 +7424,17 @@ class DomRenderer {
|
|
|
7403
7424
|
* and scaling of the root belong to the caller.
|
|
7404
7425
|
* @param regionImages Unpacked per-region bitmaps (for the rigid tier),
|
|
7405
7426
|
* keyed by region name — `PosedRegion.region`.
|
|
7427
|
+
* @param atlasRegions Optional page-backed rigid sources, from createAtlasRegions
|
|
7428
|
+
* or ModelAssets.atlasRegions. A matching entry takes precedence over regionImages.
|
|
7406
7429
|
* @param pages Page images (for the mesh tier), keyed by page name —
|
|
7407
7430
|
* `PosedMesh.page`. Read on every mesh draw, so a caller may fill it after
|
|
7408
7431
|
* construction.
|
|
7409
7432
|
*/
|
|
7410
|
-
constructor(root, regionImages, pages = /* @__PURE__ */ new Map()) {
|
|
7433
|
+
constructor(root, regionImages, pages = /* @__PURE__ */ new Map(), atlasRegions = /* @__PURE__ */ new Map()) {
|
|
7411
7434
|
this.root = root;
|
|
7412
7435
|
this.regionImages = regionImages;
|
|
7413
7436
|
this.pages = pages;
|
|
7437
|
+
this.atlasRegions = atlasRegions;
|
|
7414
7438
|
}
|
|
7415
7439
|
/**
|
|
7416
7440
|
* Apply the clips the frame carries (default). Each element drawn inside a
|
|
@@ -7435,6 +7459,8 @@ class DomRenderer {
|
|
|
7435
7459
|
clipping = true;
|
|
7436
7460
|
/** Clips applied last frame — distinct clip polygons over the drawn slots. */
|
|
7437
7461
|
clipCount = 0;
|
|
7462
|
+
/** Atlas rigid canvases rasterized in the last frame; never includes meshes. */
|
|
7463
|
+
rigidRasterCount = 0;
|
|
7438
7464
|
/**
|
|
7439
7465
|
* Clips in the frame NOT applied last frame: `clipping` is false, or the
|
|
7440
7466
|
* polygon has fewer than three points. A clip the runtime itself ignores (a
|
|
@@ -7604,6 +7630,7 @@ class DomRenderer {
|
|
|
7604
7630
|
render(input) {
|
|
7605
7631
|
const frame2 = renderFrameOf(input);
|
|
7606
7632
|
this.clipCount = 0;
|
|
7633
|
+
this.rigidRasterCount = 0;
|
|
7607
7634
|
this.clipSkipCount = 0;
|
|
7608
7635
|
this.clipWriteCount = 0;
|
|
7609
7636
|
this.meshCount = 0;
|
|
@@ -7690,16 +7717,10 @@ class DomRenderer {
|
|
|
7690
7717
|
}
|
|
7691
7718
|
// --- rigid tier -----------------------------------------------------------
|
|
7692
7719
|
renderRegion(slot) {
|
|
7693
|
-
const
|
|
7720
|
+
const atlas = this.atlasRegions.get(slot.region);
|
|
7721
|
+
const regionImage = atlas ? atlas.region : this.regionImages.get(slot.region);
|
|
7694
7722
|
if (!regionImage) return null;
|
|
7695
|
-
const view = this.view(slot.slot, "image");
|
|
7696
|
-
const img = view.el;
|
|
7697
|
-
if (view.regionName !== slot.region) {
|
|
7698
|
-
view.regionName = slot.region;
|
|
7699
|
-
img.src = regionImage.url;
|
|
7700
|
-
img.width = regionImage.width;
|
|
7701
|
-
img.height = regionImage.height;
|
|
7702
|
-
}
|
|
7723
|
+
const view = this.view(slot.slot, atlas ? "region-canvas" : "image");
|
|
7703
7724
|
const corners = slot.corners;
|
|
7704
7725
|
for (let v = 0; v < 8; v++) regionVertices[v] = corners[v];
|
|
7705
7726
|
const blx = regionVertices[0], bly = -regionVertices[1];
|
|
@@ -7711,6 +7732,23 @@ class DomRenderer {
|
|
|
7711
7732
|
const b = (ury - uly) / w;
|
|
7712
7733
|
const c = (blx - ulx) / h;
|
|
7713
7734
|
const d = (bly - uly) / h;
|
|
7735
|
+
const effective = this.pixelRatio * Math.max(Math.hypot(a, b), Math.hypot(c, d));
|
|
7736
|
+
const band = effective > 0 && effective < 1 ? 1.25 ** Math.ceil(Math.log(effective) / Math.log(1.25)) : 1;
|
|
7737
|
+
if (view.regionName !== slot.region || atlas && view.regionRatio !== band) {
|
|
7738
|
+
view.regionName = slot.region;
|
|
7739
|
+
view.regionRatio = band;
|
|
7740
|
+
if (atlas) {
|
|
7741
|
+
drawAtlasRegion(view.el, atlas, band < 1 ? band : void 0);
|
|
7742
|
+
view.el.style.width = `${w}px`;
|
|
7743
|
+
view.el.style.height = `${h}px`;
|
|
7744
|
+
this.rigidRasterCount++;
|
|
7745
|
+
} else {
|
|
7746
|
+
const img = view.el;
|
|
7747
|
+
img.src = this.regionImages.get(slot.region).url;
|
|
7748
|
+
img.width = w;
|
|
7749
|
+
img.height = h;
|
|
7750
|
+
}
|
|
7751
|
+
}
|
|
7714
7752
|
this.setTransform(view, `matrix(${a},${b},${c},${d},${ulx},${uly})`);
|
|
7715
7753
|
this.applyClip(view, a, b, c, d, ulx, uly, w, h);
|
|
7716
7754
|
this.applyCommon(view, slot);
|
|
@@ -8135,6 +8173,7 @@ class DomRenderer {
|
|
|
8135
8173
|
kind,
|
|
8136
8174
|
el,
|
|
8137
8175
|
regionName: "",
|
|
8176
|
+
regionRatio: -1,
|
|
8138
8177
|
visible: false,
|
|
8139
8178
|
zIndex: -1,
|
|
8140
8179
|
opacity: 1,
|
|
@@ -8944,8 +8983,8 @@ async function loadModel(options) {
|
|
|
8944
8983
|
);
|
|
8945
8984
|
}
|
|
8946
8985
|
const regions = options.regions ?? "blob";
|
|
8947
|
-
if (regions !== "blob" && regions !== "data" && regions !== "none") {
|
|
8948
|
-
throw new Error(`regions must be 'blob', 'data' or 'none', got ${String(options.regions)}`);
|
|
8986
|
+
if (regions !== "atlas" && regions !== "blob" && regions !== "data" && regions !== "none") {
|
|
8987
|
+
throw new Error(`regions must be 'atlas', 'blob', 'data' or 'none', got ${String(options.regions)}`);
|
|
8949
8988
|
}
|
|
8950
8989
|
const fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
8951
8990
|
const resolvePage = options.resolvePage ?? resolveAgainstModel;
|
|
@@ -8958,7 +8997,7 @@ async function loadModel(options) {
|
|
|
8958
8997
|
})
|
|
8959
8998
|
);
|
|
8960
8999
|
const sets = await loadSets(fetchImpl, modelUrl, options.setsUrl, read.doc);
|
|
8961
|
-
const regionImages = regions === "none" ? /* @__PURE__ */ new Map() : await unpackRegions(pages, pageImages, { encoding: regions });
|
|
9000
|
+
const regionImages = regions === "none" || regions === "atlas" ? /* @__PURE__ */ new Map() : await unpackRegions(pages, pageImages, { encoding: regions });
|
|
8962
9001
|
let disposed = false;
|
|
8963
9002
|
return {
|
|
8964
9003
|
spec: read.spec,
|
|
@@ -8968,6 +9007,7 @@ async function loadModel(options) {
|
|
|
8968
9007
|
stage: stageOf(read.doc),
|
|
8969
9008
|
regions,
|
|
8970
9009
|
regionImages,
|
|
9010
|
+
atlasRegions: regions === "atlas" ? createAtlasRegions(pages, pageImages) : /* @__PURE__ */ new Map(),
|
|
8971
9011
|
pageImages,
|
|
8972
9012
|
document: read,
|
|
8973
9013
|
dispose() {
|
|
@@ -9034,7 +9074,37 @@ function channelValue(curve, i, c, t) {
|
|
|
9034
9074
|
const y0 = p[o + q - 1];
|
|
9035
9075
|
return y0 + (t - x0) / (p[o + q] - x0) * (p[o + q + 1] - y0);
|
|
9036
9076
|
}
|
|
9037
|
-
|
|
9077
|
+
function compileDeformCurve(keys) {
|
|
9078
|
+
const curve = compileCurve(keys.map((k) => ({ time: k.time, values: [0], curve: "linear", stated: { time: k.stated, values: [0] } })), 1);
|
|
9079
|
+
for (let i = 0; i < keys.length; i++) {
|
|
9080
|
+
const a = keys[i];
|
|
9081
|
+
curve.kinds[i] = a.curve === "linear" ? CURVE_LINEAR : a.curve === "stepped" ? CURVE_STEPPED : CURVE_BEZIER;
|
|
9082
|
+
if (typeof a.curve === "string" || i + 1 === keys.length) continue;
|
|
9083
|
+
const b = keys[i + 1];
|
|
9084
|
+
const c = a.curve;
|
|
9085
|
+
const inner = bezierPolyline(a.stated, 0, c[0], c[1], c[2], c[3], b.stated, DEFORM_CURVE_END);
|
|
9086
|
+
const o = i * POLYLINE;
|
|
9087
|
+
curve.polylines[o] = a.time;
|
|
9088
|
+
curve.polylines[o + 1] = 0;
|
|
9089
|
+
curve.polylines.set(inner, o + 2);
|
|
9090
|
+
curve.polylines[o + POLYLINE - 2] = b.time;
|
|
9091
|
+
curve.polylines[o + POLYLINE - 1] = 1;
|
|
9092
|
+
}
|
|
9093
|
+
return curve;
|
|
9094
|
+
}
|
|
9095
|
+
function deformFraction(curve, i, t) {
|
|
9096
|
+
if (curve.kinds[i] === CURVE_STEPPED) return 0;
|
|
9097
|
+
if (curve.kinds[i] === CURVE_LINEAR) return (t - curve.times[i]) / (curve.times[i + 1] - curve.times[i]);
|
|
9098
|
+
const p = curve.polylines;
|
|
9099
|
+
const o = i * POLYLINE;
|
|
9100
|
+
let q = 2;
|
|
9101
|
+
while (q < POLYLINE - 2 && p[o + q] < t) q += 2;
|
|
9102
|
+
const x0 = p[o + q - 2], y0 = p[o + q - 1], x1 = p[o + q], y1 = p[o + q + 1];
|
|
9103
|
+
if (q === 2) return y1 * (t - x0) / (x1 - x0);
|
|
9104
|
+
if (q === POLYLINE - 2) return y0 + (1 - y0) * (t - x0) / (x1 - x0);
|
|
9105
|
+
return y0 + (t - x0) / (x1 - x0) * (y1 - y0);
|
|
9106
|
+
}
|
|
9107
|
+
const RUNTIME_STAGE = 2;
|
|
9038
9108
|
function missingText(m) {
|
|
9039
9109
|
return `${m.feature}: ${m.detail}${m.animation === null ? "" : ` (animation "${m.animation}")`}`;
|
|
9040
9110
|
}
|
|
@@ -9178,6 +9248,7 @@ function compileRuntime(doc, options = {}, plant = {}) {
|
|
|
9178
9248
|
}
|
|
9179
9249
|
const attachments = [];
|
|
9180
9250
|
let vertexCount = 0;
|
|
9251
|
+
let deformCount = 0;
|
|
9181
9252
|
const sourceOf = sourceOfDoc(doc);
|
|
9182
9253
|
const attachmentView = plant.attachmentSkin === void 0 ? doc : underSkin(doc, plant.attachmentSkin);
|
|
9183
9254
|
const resolvedBySlot = doc.slots.map(() => /* @__PURE__ */ new Map());
|
|
@@ -9198,7 +9269,7 @@ function compileRuntime(doc, options = {}, plant = {}) {
|
|
|
9198
9269
|
if ("conflict" in shown) return { index: -1, missing: ["skin-conflict", `slot "${slot.name}" placeholder "${placeholder}" is filled by skins that disagree`] };
|
|
9199
9270
|
const row = shownRow(shown);
|
|
9200
9271
|
const g = shown.record.geometry;
|
|
9201
|
-
const at = { slot: si, name: row.name, skin: shown.skin, placeholder: shown.placeholder, path: CORE_REGION_KINDS.has(shown.record.kind) ? row.path : null, bone: indexOf(slot.bone), offset: vertexCount };
|
|
9272
|
+
const at = { timeline: timelineIdentity(slot.name, shown), deformOffset: deformCount, slot: si, name: row.name, skin: shown.skin, placeholder: shown.placeholder, path: CORE_REGION_KINDS.has(shown.record.kind) ? row.path : null, bone: indexOf(slot.bone), offset: vertexCount };
|
|
9202
9273
|
let made = null;
|
|
9203
9274
|
let missing = null;
|
|
9204
9275
|
if (g?.kind === "clipping") missing = ["clipping", `slot "${slot.name}" shows clipping attachment "${row.name}"`];
|
|
@@ -9240,6 +9311,7 @@ function compileRuntime(doc, options = {}, plant = {}) {
|
|
|
9240
9311
|
if (made === null) made = vertexAttachment(at, DRAW_NONE, new Float64Array(0), 0);
|
|
9241
9312
|
attachments.push(made);
|
|
9242
9313
|
vertexCount += made.count;
|
|
9314
|
+
deformCount += made.deformCount;
|
|
9243
9315
|
return { index: attachments.length - 1, missing };
|
|
9244
9316
|
};
|
|
9245
9317
|
const slots = doc.slots.map((slot, si) => {
|
|
@@ -9261,7 +9333,7 @@ function compileRuntime(doc, options = {}, plant = {}) {
|
|
|
9261
9333
|
const refused = [];
|
|
9262
9334
|
let cursorMax = 0;
|
|
9263
9335
|
for (const anim of doc.animations) {
|
|
9264
|
-
const compiled = compileAnimation(anim, refusals, ignoreEvents, boneIndex2, slotIndex, slots, constraints, (si, ph) => resolve(si, ph, anim.name));
|
|
9336
|
+
const compiled = compileAnimation(anim, refusals, ignoreEvents, boneIndex2, slotIndex, slots, constraints, doc, (si, ph) => resolve(si, ph, anim.name));
|
|
9265
9337
|
const missing = refusals.byAnimation.get(anim.name);
|
|
9266
9338
|
if (missing !== void 0 && missing.length > 0) refused.push({ animation: anim.name, missing });
|
|
9267
9339
|
else {
|
|
@@ -9272,6 +9344,9 @@ function compileRuntime(doc, options = {}, plant = {}) {
|
|
|
9272
9344
|
if (refusals.model.length > 0) throw new RuntimeRefusal(refusals.model);
|
|
9273
9345
|
const names = doc.animations.map((a) => a.name);
|
|
9274
9346
|
return {
|
|
9347
|
+
omitDeform: plant.omitDeform === true,
|
|
9348
|
+
deformAfterWeights: plant.deformAfterWeights === true,
|
|
9349
|
+
deformCount,
|
|
9275
9350
|
eventWrapOffByOne: plant.eventWrapOffByOne === true,
|
|
9276
9351
|
restoreEventsFromStart: plant.restoreEventsFromStart === true,
|
|
9277
9352
|
doc,
|
|
@@ -9303,7 +9378,7 @@ function compileRuntime(doc, options = {}, plant = {}) {
|
|
|
9303
9378
|
const NO_INTS = new Int32Array(0);
|
|
9304
9379
|
const NO_NUMBERS = new Float64Array(0);
|
|
9305
9380
|
function vertexAttachment(at, draw, local, count) {
|
|
9306
|
-
return { ...at, draw, local, count, bindingCounts: NO_INTS, bindingBones: NO_INTS, bindingX: NO_NUMBERS, bindingY: NO_NUMBERS, bindingWeights: NO_NUMBERS };
|
|
9381
|
+
return { ...at, draw, local, count, deformCount: draw === DRAW_MESH ? count : 0, bindingCounts: NO_INTS, bindingBones: NO_INTS, bindingX: NO_NUMBERS, bindingY: NO_NUMBERS, bindingWeights: NO_NUMBERS };
|
|
9307
9382
|
}
|
|
9308
9383
|
function meshAttachment(at, vertices, indexOf, rewrite, bones) {
|
|
9309
9384
|
if (!vertices.weighted) {
|
|
@@ -9327,7 +9402,7 @@ function meshAttachment(at, vertices, indexOf, rewrite, bones) {
|
|
|
9327
9402
|
ws.push(Math.fround(b.weight));
|
|
9328
9403
|
}
|
|
9329
9404
|
}
|
|
9330
|
-
return { ...at, draw: DRAW_WEIGHTED, local: NO_NUMBERS, count: counts.length * 2, bindingCounts: Int32Array.from(counts), bindingBones: Int32Array.from(ids), bindingX: Float64Array.from(xs), bindingY: Float64Array.from(ys), bindingWeights: Float64Array.from(ws) };
|
|
9405
|
+
return { ...at, deformCount: ids.length * 2, draw: DRAW_WEIGHTED, local: NO_NUMBERS, count: counts.length * 2, bindingCounts: Int32Array.from(counts), bindingBones: Int32Array.from(ids), bindingX: Float64Array.from(xs), bindingY: Float64Array.from(ys), bindingWeights: Float64Array.from(ws) };
|
|
9331
9406
|
}
|
|
9332
9407
|
function compileIk(r, index, applied, bones, indexOf) {
|
|
9333
9408
|
return {
|
|
@@ -9387,13 +9462,12 @@ function compileTransform(r, index, applied, bones, indexOf) {
|
|
|
9387
9462
|
clamp: r.clamp
|
|
9388
9463
|
};
|
|
9389
9464
|
}
|
|
9390
|
-
function compileAnimation(anim, refusals, ignoreEvents, boneIndex2, slotIndex, slots, constraints, resolve) {
|
|
9465
|
+
function compileAnimation(anim, refusals, ignoreEvents, boneIndex2, slotIndex, slots, constraints, doc, resolve) {
|
|
9391
9466
|
const tl = anim.timelines;
|
|
9392
9467
|
const name = anim.name;
|
|
9393
9468
|
let cursors = 0;
|
|
9394
9469
|
const deform = tl.attachments.filter((a) => a.deform !== null);
|
|
9395
9470
|
const sequence = tl.attachments.filter((a) => a.sequence !== null);
|
|
9396
|
-
if (deform.length > 0) refusals.note("deform-timeline", `${deform.length} deform timeline(s): ${deform.slice(0, 3).map((a) => `${a.skin}/${a.slot}/${a.attachment}`).join(", ")}${deform.length > 3 ? ", …" : ""}`, name);
|
|
9397
9471
|
if (sequence.length > 0) refusals.note("sequence-timeline", `${sequence.length} sequence timeline(s): ${sequence.slice(0, 3).map((a) => `${a.skin}/${a.slot}/${a.attachment}`).join(", ")}${sequence.length > 3 ? ", …" : ""}`, name);
|
|
9398
9472
|
if (tl.drawOrder.length > 0) refusals.note("draw-order-timeline", `${tl.drawOrder.length} draw-order key(s)`, name);
|
|
9399
9473
|
const lastBy = (targets) => new Map(targets.map((t) => [t.name, t]));
|
|
@@ -9441,7 +9515,14 @@ function compileAnimation(anim, refusals, ignoreEvents, boneIndex2, slotIndex, s
|
|
|
9441
9515
|
constraintTimelines[c.index] = { constraint: c.index, curve: compileCurve(keyed.keys, TRANSFORM_PROPERTIES.length), cursor: cursors++, flags: null };
|
|
9442
9516
|
}
|
|
9443
9517
|
}
|
|
9444
|
-
|
|
9518
|
+
const deforms = deform.map((a) => {
|
|
9519
|
+
const g = doc.skins.find((s) => s.name === a.skin)?.attachments[a.slot]?.[a.attachment]?.geometry;
|
|
9520
|
+
if (g === void 0 || g.kind === "region" || g.kind === "linkedmesh") throw new RuntimeInputError(`deform "${a.skin}/${a.slot}/${a.attachment}" has no vertex geometry (readModel refuses it first)`);
|
|
9521
|
+
const keys = a.deform;
|
|
9522
|
+
const arrays = keys.map((k) => heldArray(g.vertices, k));
|
|
9523
|
+
return { identity: `${a.skin}/${a.slot}/${a.attachment}`, cursor: cursors++, curve: compileDeformCurve(keys), count: arrays[0].length, held: Float64Array.from(arrays.flat()) };
|
|
9524
|
+
});
|
|
9525
|
+
return { name, duration: tl.duration, deforms, bones, slots: slotTimelines, constraints: constraintTimelines, cursors, events: tl.events.length, eventKeys: Object.freeze(ignoreEvents ? [] : tl.events.map((key) => Object.freeze({ name: key.name, time: key.time, int: key.int, float: key.float, string: key.string, volume: key.volume ?? 0, balance: key.balance ?? 0 }))) };
|
|
9445
9526
|
}
|
|
9446
9527
|
const DEG = RUNTIME_DEG;
|
|
9447
9528
|
const TWO_PI = 2 * RUNTIME_PI;
|
|
@@ -9474,6 +9555,8 @@ class RuntimePose {
|
|
|
9474
9555
|
this.light = new Float64Array(ns * 4);
|
|
9475
9556
|
this.shown = new Int32Array(ns);
|
|
9476
9557
|
this.vertices = new Float64Array(model.vertexCount);
|
|
9558
|
+
this.deform = new Float64Array(model.deformCount);
|
|
9559
|
+
this.deformed = new Uint8Array(model.attachments.length);
|
|
9477
9560
|
this.cursors = new Int32Array(Math.max(1, model.cursors)).fill(-1);
|
|
9478
9561
|
this.ikMix = new Float64Array(nc);
|
|
9479
9562
|
this.ikSoftness = new Float64Array(nc);
|
|
@@ -9523,6 +9606,7 @@ class RuntimePose {
|
|
|
9523
9606
|
this.constraintValues(null, 0);
|
|
9524
9607
|
this.solveConstraints();
|
|
9525
9608
|
this.slotValues(null, 0);
|
|
9609
|
+
this.deformValues(null, 0);
|
|
9526
9610
|
}
|
|
9527
9611
|
/** The animation posed at its time `t`, from the setup pose (the header). */
|
|
9528
9612
|
apply(t) {
|
|
@@ -9536,6 +9620,7 @@ class RuntimePose {
|
|
|
9536
9620
|
this.constraintValues(anim, t);
|
|
9537
9621
|
this.solveConstraints();
|
|
9538
9622
|
this.slotValues(anim, t);
|
|
9623
|
+
this.deformValues(anim, t);
|
|
9539
9624
|
}
|
|
9540
9625
|
/** One step of a looping track: the track time moved by `dt`, the animation posed at it wrapped by the duration (`loopedTime` in src/core/raw.ts). */
|
|
9541
9626
|
step(dt) {
|
|
@@ -10245,6 +10330,31 @@ class RuntimePose {
|
|
|
10245
10330
|
}
|
|
10246
10331
|
}
|
|
10247
10332
|
}
|
|
10333
|
+
/** Reset on every pose, then match source identity after switches; no old frame's offsets survive. */
|
|
10334
|
+
deformValues(anim, t) {
|
|
10335
|
+
this.deformed.fill(0);
|
|
10336
|
+
this.deform.fill(0);
|
|
10337
|
+
if (anim === null || this.model.omitDeform) return;
|
|
10338
|
+
for (let k = 0; k < anim.deforms.length; k++) {
|
|
10339
|
+
const tl = anim.deforms[k];
|
|
10340
|
+
const i = keyAt(tl.curve, this.cursors, tl.cursor, t);
|
|
10341
|
+
if (i < 0) continue;
|
|
10342
|
+
const held = i + 1 === tl.curve.keys || tl.curve.kinds[i] === CURVE_STEPPED;
|
|
10343
|
+
const p = held ? 0 : deformFraction(tl.curve, i, t);
|
|
10344
|
+
const start = i * tl.count;
|
|
10345
|
+
for (let s = 0; s < this.shown.length; s++) {
|
|
10346
|
+
const index = this.shown[s];
|
|
10347
|
+
if (index < 0 || !this.model.slots[s].live) continue;
|
|
10348
|
+
const at = this.model.attachments[index];
|
|
10349
|
+
if (at.timeline !== tl.identity || at.deformCount === 0) continue;
|
|
10350
|
+
this.deformed[index] = 1;
|
|
10351
|
+
for (let q = 0; q < tl.count; q++) {
|
|
10352
|
+
const v = tl.held[start + q];
|
|
10353
|
+
this.deform[at.deformOffset + q] = held ? v : v + (tl.held[start + tl.count + q] - v) * p;
|
|
10354
|
+
}
|
|
10355
|
+
}
|
|
10356
|
+
}
|
|
10357
|
+
}
|
|
10248
10358
|
/** Every shown attachment's world vertices into `vertices` at its offset (`regionCorners`, `worldVertices`). */
|
|
10249
10359
|
computeVertices() {
|
|
10250
10360
|
const m = this.model;
|
|
@@ -10266,7 +10376,8 @@ class RuntimePose {
|
|
|
10266
10376
|
const d = W[b + W_D];
|
|
10267
10377
|
const wx = W[b + W_X];
|
|
10268
10378
|
const wy = W[b + W_Y];
|
|
10269
|
-
const local = at.local;
|
|
10379
|
+
const local = this.deformed[index] && at.draw === DRAW_MESH ? this.deform : at.local;
|
|
10380
|
+
const lo = this.deformed[index] && at.draw === DRAW_MESH ? at.deformOffset : 0;
|
|
10270
10381
|
if (at.draw === DRAW_REGION) {
|
|
10271
10382
|
for (let q = 0; q < 8; q += 2) {
|
|
10272
10383
|
const lx = local[q];
|
|
@@ -10276,8 +10387,8 @@ class RuntimePose {
|
|
|
10276
10387
|
}
|
|
10277
10388
|
} else {
|
|
10278
10389
|
for (let q = 0; q < at.count; q += 2) {
|
|
10279
|
-
const x = local[q];
|
|
10280
|
-
const y = local[q + 1];
|
|
10390
|
+
const x = local[lo + q];
|
|
10391
|
+
const y = local[lo + q + 1];
|
|
10281
10392
|
out[o++] = x * a + y * bb + wx;
|
|
10282
10393
|
out[o++] = x * c + y * d + wy;
|
|
10283
10394
|
}
|
|
@@ -10296,9 +10407,15 @@ class RuntimePose {
|
|
|
10296
10407
|
const end = n + counts[v];
|
|
10297
10408
|
for (; n < end; n++) {
|
|
10298
10409
|
const b = bones[n] * WORLDS;
|
|
10299
|
-
const x = xs[n];
|
|
10300
|
-
const y = ys[n];
|
|
10301
10410
|
const weight = weights[n];
|
|
10411
|
+
const deformed = this.deformed[index] !== 0;
|
|
10412
|
+
const x = deformed ? xs[n] + this.deform[at.deformOffset + n * 2] : xs[n];
|
|
10413
|
+
const y = deformed ? ys[n] + this.deform[at.deformOffset + n * 2 + 1] : ys[n];
|
|
10414
|
+
if (deformed && m.deformAfterWeights) {
|
|
10415
|
+
wx += (xs[n] * W[b + W_A] + ys[n] * W[b + W_B] + W[b + W_X]) * weight + this.deform[at.deformOffset + n * 2];
|
|
10416
|
+
wy += (xs[n] * W[b + W_C] + ys[n] * W[b + W_D] + W[b + W_Y]) * weight + this.deform[at.deformOffset + n * 2 + 1];
|
|
10417
|
+
continue;
|
|
10418
|
+
}
|
|
10302
10419
|
wx += (x * W[b + W_A] + y * W[b + W_B] + W[b + W_X]) * weight;
|
|
10303
10420
|
wy += (x * W[b + W_C] + y * W[b + W_D] + W[b + W_Y]) * weight;
|
|
10304
10421
|
}
|
|
@@ -11195,10 +11312,10 @@ class RigPlayer {
|
|
|
11195
11312
|
if (mode !== "dom") throw new Error(`mode must be 'dom' or 'canvas', got ${String(mode)}`);
|
|
11196
11313
|
if (this.assets.regions === "none") {
|
|
11197
11314
|
throw new Error(
|
|
11198
|
-
"these assets were loaded with regions: 'none' (no region bitmaps, for the canvas mode only); the DOM mode needs a load with regions 'blob' or 'data'"
|
|
11315
|
+
"these assets were loaded with regions: 'none' (no region bitmaps, for the canvas mode only); the DOM mode needs a load with regions 'atlas', 'blob' or 'data'"
|
|
11199
11316
|
);
|
|
11200
11317
|
}
|
|
11201
|
-
const renderer = new DomRenderer(this.root, this.assets.regionImages, this.assets.pageImages);
|
|
11318
|
+
const renderer = new DomRenderer(this.root, this.assets.regionImages, this.assets.pageImages, this.assets.atlasRegions);
|
|
11202
11319
|
if (this.meshBackend) renderer.meshBackend = this.meshBackend;
|
|
11203
11320
|
return renderer;
|
|
11204
11321
|
}
|
|
@@ -12663,6 +12780,7 @@ export {
|
|
|
12663
12780
|
CanvasRenderer,
|
|
12664
12781
|
DomRenderer,
|
|
12665
12782
|
RigPlayer,
|
|
12783
|
+
createAtlasRegions,
|
|
12666
12784
|
loadModel,
|
|
12667
12785
|
readSetupMesh,
|
|
12668
12786
|
revokeRegions,
|