@nodecraft/rendermite 1.0.5 → 1.0.7
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 +5 -0
- package/dist/atlas/registry.d.ts +3 -3
- package/dist/atlas/sources.d.ts +1 -1
- package/dist/{blend-Qvrn6YgK.d.ts → blend-CEHoJ7tM.d.ts} +3 -2
- package/dist/{blend-CHP2-j9U.js → blend-D0XWgVQr.js} +20 -8
- package/dist/cache-Cr2ON3RQ.js +66 -0
- package/dist/cli.js +12 -6
- package/dist/compose-lWPrB7wh.js +104 -0
- package/dist/descriptor-DWebtkI1.js +26 -0
- package/dist/{discovery-D89pVVJA.d.ts → discovery-wiJBGryo.d.ts} +1 -1
- package/dist/dynamic/generators.d.ts +1 -1
- package/dist/dynamic/generators.js +1 -1
- package/dist/{encode-C5kdAm45.d.ts → encode-CaSK8-mi.d.ts} +1 -1
- package/dist/{encode-3u49i-eD.js → encode-Df_tWzkl.js} +44 -16
- package/dist/{entity-fallback-DfL0_eyf.js → entity-fallback-D9QTGU9X.js} +1 -1
- package/dist/{face-CpVdnf-w.d.ts → face-C49L66sQ.d.ts} +10 -4
- package/dist/{face-D-N1amV4.js → face-Cl1O4m2i.js} +24 -11
- package/dist/{generators-CcVRG30y.js → generators-BlG4KmtP.js} +1 -1
- package/dist/{generators-CCB8h0mP.d.ts → generators-DhRov4RB.d.ts} +1 -1
- package/dist/{geo-Dq2zve09.js → geo-DHiWBa-C.js} +7 -4
- package/dist/index.d.ts +14 -14
- package/dist/index.js +12 -12
- package/dist/{item-styles-DJ3LWZS2.js → item-styles-upgEO1yP.js} +1 -1
- package/dist/items/discovery.d.ts +1 -1
- package/dist/{jar-6T3xdgaL.d.ts → jar-CFkA-VgT.d.ts} +2 -1
- package/dist/{jar-Bt3i0ls4.js → jar-D9z-X7tA.js} +12 -12
- package/dist/{legacy-reshape-CewShfF3.js → legacy-reshape-C05SfAPR.js} +1 -1
- package/dist/{loader-A-BZa8J4.js → loader-B8NJO7pR.js} +12 -3
- package/dist/{loader-CBzn3Koc.js → loader-CfXMxcEV.js} +37 -7
- package/dist/{loader-C-6QN3xv.d.ts → loader-D22zZME7.d.ts} +2 -2
- package/dist/{loader-TFFNV4Jl.d.ts → loader-Myy22TDL.d.ts} +8 -2
- package/dist/{manager-dfI7b9N4.js → manager-CkletR5K.js} +29 -2
- package/dist/{manager-CoZaeQTu.d.ts → manager-Cv1NeFyF.d.ts} +28 -1
- package/dist/models/loader.d.ts +1 -1
- package/dist/models/loader.js +1 -1
- package/dist/mods/prepare.d.ts +1 -1
- package/dist/mods/prepare.js +1 -1
- package/dist/mods/synthesize.d.ts +2 -2
- package/dist/mods/synthesize.js +1 -1
- package/dist/mods/tints.d.ts +2 -2
- package/dist/mods/tints.js +1 -1
- package/dist/output/encode.d.ts +1 -1
- package/dist/output/encode.js +1 -1
- package/dist/output/item-styles.js +1 -1
- package/dist/pipeline-Da2Kavba.js +221 -0
- package/dist/pipeline-HiA3DC71.d.ts +58 -0
- package/dist/pool-CKGp1qup.js +131 -0
- package/dist/{prepare-BeUpXwaP.js → prepare-BESRrh6K.js} +4 -4
- package/dist/{prepare-gfR1aIjt.d.ts → prepare-CPxO0kKz.d.ts} +1 -1
- package/dist/{prepare-C8wRjAXP.js → prepare-Cc8QZ3j0.js} +4 -4
- package/dist/{prepare-wfWtaz_X.d.ts → prepare-Cs6QDqie.d.ts} +1 -1
- package/dist/{rasterizer-BHWDrmGz.js → rasterizer-76qO8TDh.js} +42 -4
- package/dist/{rasterizer-Dh35qXbn.d.ts → rasterizer-B9ZGJI3-.d.ts} +21 -2
- package/dist/render/blend.d.ts +1 -1
- package/dist/render/blend.js +1 -1
- package/dist/render/compose.d.ts +2 -2
- package/dist/render/compose.js +1 -1
- package/dist/render/entity-fallback.d.ts +6 -6
- package/dist/render/entity-fallback.js +1 -1
- package/dist/render/face.d.ts +2 -2
- package/dist/render/face.js +1 -1
- package/dist/render/fluid-bucket.d.ts +2 -2
- package/dist/render/geo.d.ts +4 -4
- package/dist/render/geo.js +1 -1
- package/dist/render/legacy-tints.d.ts +2 -2
- package/dist/render/obj.d.ts +5 -5
- package/dist/render/obj.js +1 -1
- package/dist/render/pipeline.d.ts +2 -0
- package/dist/render/pipeline.js +2 -0
- package/dist/render/rasterizer.d.ts +2 -2
- package/dist/render/rasterizer.js +2 -2
- package/dist/render/renderer.d.ts +2 -2
- package/dist/render/renderer.js +1 -1
- package/dist/render/tints.d.ts +1 -1
- package/dist/{renderer-nbMCw1Pl.d.ts → renderer-B20ssjRm.d.ts} +23 -6
- package/dist/{renderer-LDhBNHcl.js → renderer-gQW_I7YG.js} +146 -63
- package/dist/resources/cache.d.ts +30 -0
- package/dist/resources/cache.js +2 -0
- package/dist/resources/descriptor.d.ts +2 -0
- package/dist/resources/descriptor.js +2 -0
- package/dist/resources/jar.d.ts +1 -1
- package/dist/resources/jar.js +1 -1
- package/dist/resources/manager.d.ts +1 -1
- package/dist/resources/manager.js +1 -1
- package/dist/resources/synthetic.d.ts +1 -1
- package/dist/resources/synthetic.js +1 -1
- package/dist/resources/zip-reader.d.ts +5 -0
- package/dist/resources/zip-reader.js +2 -0
- package/dist/run-B0qPw3zf.js +209 -0
- package/dist/{run-BlSZw9Qk.d.ts → run-CT3VtFqg.d.ts} +12 -2
- package/dist/run.d.ts +1 -1
- package/dist/run.js +1 -1
- package/dist/{sources-DH9dk3KF.d.ts → sources-B9X9w3qP.d.ts} +1 -1
- package/dist/{synthesize-CRgSEmEp.js → synthesize-3Q0aaOnK.js} +1 -1
- package/dist/{synthetic-CDsj--li.d.ts → synthetic-Qk-BSUXO.d.ts} +5 -1
- package/dist/{synthetic-DC2bSnGe.js → synthetic-ZAUjXT7E.js} +0 -0
- package/dist/textures/loader.d.ts +1 -1
- package/dist/textures/loader.js +1 -1
- package/dist/{tints-CuG6GwQJ.js → tints-B8UJmZMu.js} +2 -2
- package/dist/{tints-txt-8xI5.d.ts → tints-BH9l0ND0.d.ts} +2 -2
- package/dist/versions/legacy-reshape.d.ts +1 -1
- package/dist/versions/legacy-reshape.js +1 -1
- package/dist/versions/prepare.d.ts +1 -1
- package/dist/versions/prepare.js +1 -1
- package/dist/workers/pool.d.ts +36 -5
- package/dist/workers/pool.js +2 -67
- package/dist/workers/render-worker.d.ts +15 -0
- package/dist/workers/render-worker.js +40 -0
- package/dist/zip-reader-BSbJKUT1.js +156 -0
- package/package.json +4 -2
- package/dist/compose-qjhyBvnS.js +0 -41
- package/dist/run-CfnWIRY4.js +0 -316
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as TextureLoader } from "../loader-
|
|
2
|
-
import {
|
|
1
|
+
import { i as TextureLoader } from "../loader-Myy22TDL.js";
|
|
2
|
+
import { r as TintColor } from "../face-C49L66sQ.js";
|
|
3
3
|
//#region src/render/legacy-tints.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Tints for a model rendered without an item definition (pre-1.21.4 eras and
|
package/dist/render/obj.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as ResourceManager } from "../manager-
|
|
2
|
-
import { i as TextureLoader } from "../loader-
|
|
3
|
-
import { r as ResolvedModel } from "../loader-
|
|
4
|
-
import { t as FloatTexture } from "../blend-
|
|
1
|
+
import { a as ResourceManager } from "../manager-Cv1NeFyF.js";
|
|
2
|
+
import { i as TextureLoader } from "../loader-Myy22TDL.js";
|
|
3
|
+
import { r as ResolvedModel } from "../loader-D22zZME7.js";
|
|
4
|
+
import { t as FloatTexture } from "../blend-CEHoJ7tM.js";
|
|
5
5
|
import { n as Vec3 } from "../vector-DRKRi4--.js";
|
|
6
|
-
import {
|
|
6
|
+
import { i as RenderOptions } from "../renderer-B20ssjRm.js";
|
|
7
7
|
//#region src/render/obj.d.ts
|
|
8
8
|
interface ObjTriangle {
|
|
9
9
|
positions: [Vec3, Vec3, Vec3];
|
package/dist/render/obj.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { c as renderObjModel, o as parseMtl, s as parseObj } from "../renderer-
|
|
1
|
+
import { c as renderObjModel, o as parseMtl, s as parseObj } from "../renderer-gQW_I7YG.js";
|
|
2
2
|
export { parseMtl, parseObj, renderObjModel };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { FaceBuffer, RasterPoint, RowCursor, compactFaceBuffer, createFaceBuffer, drawTexturedTriangle, phpRound };
|
|
1
|
+
import { a as clearFaceBuffer, c as drawTexturedTriangle, i as RowCursor, l as phpRound, n as FaceBuffer, o as compactFaceBuffer, r as RasterPoint, s as createFaceBuffer, t as DirtyRect } from "../rasterizer-B9ZGJI3-.js";
|
|
2
|
+
export { DirtyRect, FaceBuffer, RasterPoint, RowCursor, clearFaceBuffer, compactFaceBuffer, createFaceBuffer, drawTexturedTriangle, phpRound };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { RowCursor, compactFaceBuffer, createFaceBuffer, drawTexturedTriangle, phpRound };
|
|
1
|
+
import { a as drawTexturedTriangle, i as createFaceBuffer, n as clearFaceBuffer, o as phpRound, r as compactFaceBuffer, t as RowCursor } from "../rasterizer-76qO8TDh.js";
|
|
2
|
+
export { RowCursor, clearFaceBuffer, compactFaceBuffer, createFaceBuffer, drawTexturedTriangle, phpRound };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { ItemRenderError, RenderOptions, RenderedFrames, boxDownscale, pointResize, renderModel, renderModelFrames };
|
|
1
|
+
import { a as RenderedFrames, c as renderModel, i as RenderOptions, l as renderModelFrames, n as AnimationLimits, o as boxDownscale, r as ItemRenderError, s as pointResize, t as AnimationDiagnostics } from "../renderer-B20ssjRm.js";
|
|
2
|
+
export { AnimationDiagnostics, AnimationLimits, ItemRenderError, RenderOptions, RenderedFrames, boxDownscale, pointResize, renderModel, renderModelFrames };
|
package/dist/render/renderer.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as renderModelFrames, i as renderModel, n as boxDownscale, r as pointResize, t as ItemRenderError } from "../renderer-
|
|
1
|
+
import { a as renderModelFrames, i as renderModel, n as boxDownscale, r as pointResize, t as ItemRenderError } from "../renderer-gQW_I7YG.js";
|
|
2
2
|
export { ItemRenderError, boxDownscale, pointResize, renderModel, renderModelFrames };
|
package/dist/render/tints.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as resolveTint, i as parseTintValue, n as InvalidTinterDefinitionError, o as resolveTints, r as TintContext, t as DYE_COLORS } from "../tints-
|
|
1
|
+
import { a as resolveTint, i as parseTintValue, n as InvalidTinterDefinitionError, o as resolveTints, r as TintContext, t as DYE_COLORS } from "../tints-BH9l0ND0.js";
|
|
2
2
|
export { DYE_COLORS, InvalidTinterDefinitionError, TintContext, parseTintValue, resolveTint, resolveTints };
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
import { a as ResourceManager } from "./manager-
|
|
2
|
-
import { i as TextureLoader } from "./loader-
|
|
3
|
-
import { r as ResolvedModel } from "./loader-
|
|
4
|
-
import { t as FloatTexture } from "./blend-
|
|
1
|
+
import { a as ResourceManager } from "./manager-Cv1NeFyF.js";
|
|
2
|
+
import { i as TextureLoader } from "./loader-Myy22TDL.js";
|
|
3
|
+
import { r as ResolvedModel } from "./loader-D22zZME7.js";
|
|
4
|
+
import { t as FloatTexture } from "./blend-CEHoJ7tM.js";
|
|
5
5
|
import { t as Mat4 } from "./vector-DRKRi4--.js";
|
|
6
6
|
import { a as LightingProfileName } from "./lighting-3FGRC3Af.js";
|
|
7
|
-
import {
|
|
7
|
+
import { r as TintColor } from "./face-C49L66sQ.js";
|
|
8
8
|
//#region src/render/renderer.d.ts
|
|
9
|
+
interface AnimationLimits {
|
|
10
|
+
/** Emitted frames per icon (default 128). */
|
|
11
|
+
maxFrames?: number;
|
|
12
|
+
}
|
|
9
13
|
interface RenderOptions {
|
|
10
14
|
size: number;
|
|
11
15
|
quality: number;
|
|
12
16
|
lightingProfile: LightingProfileName;
|
|
17
|
+
/** Bounds on animated timelines; defaults apply when omitted. */
|
|
18
|
+
animation?: AnimationLimits;
|
|
13
19
|
/** Accumulated item-definition transformation (inner matrix). */
|
|
14
20
|
itemTransform?: Mat4;
|
|
15
21
|
/** Tint colors by index (face tintindex / generated layer number). */
|
|
@@ -22,6 +28,17 @@ interface RenderedFrames {
|
|
|
22
28
|
frames: FloatTexture[];
|
|
23
29
|
/** Display duration per frame in milliseconds (50ms per game tick). */
|
|
24
30
|
delaysMs: number[];
|
|
31
|
+
/** What the timeline did, so a bounded animation is never a silent one. */
|
|
32
|
+
animation?: AnimationDiagnostics;
|
|
33
|
+
}
|
|
34
|
+
interface AnimationDiagnostics {
|
|
35
|
+
/** Combined cycle length in game ticks (the lcm of the textures' periods). */
|
|
36
|
+
ticks: number;
|
|
37
|
+
/** Ticks considered before identical neighbours were coalesced. */
|
|
38
|
+
candidates: number;
|
|
39
|
+
/** Whether the frame cap forced even sampling instead of exact frames. */
|
|
40
|
+
sampled: boolean;
|
|
41
|
+
interpolated: boolean;
|
|
25
42
|
}
|
|
26
43
|
/**
|
|
27
44
|
* Render every animation frame of a model (a single frame for unanimated
|
|
@@ -41,4 +58,4 @@ declare function pointResize(texture: FloatTexture, width: number, height: numbe
|
|
|
41
58
|
*/
|
|
42
59
|
declare function boxDownscale(texture: FloatTexture, factor: number): FloatTexture;
|
|
43
60
|
//#endregion
|
|
44
|
-
export {
|
|
61
|
+
export { RenderedFrames as a, renderModel as c, RenderOptions as i, renderModelFrames as l, AnimationLimits as n, boxDownscale as o, ItemRenderError as r, pointResize as s, AnimationDiagnostics as t };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { c as normalize, g as transformVector, m as sub, n as displayMatrix, o as identity, r as dot, s as multiply, t as cross } from "./vector-CCxLae_T.js";
|
|
2
2
|
import { n as ResourceLocator } from "./locator-ycZzh_6z.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { t as
|
|
6
|
-
import {
|
|
7
|
-
import { n as renderFace, t as faceMaxZ } from "./face-D-N1amV4.js";
|
|
3
|
+
import { a as tintTexture, n as cloneFloatTexture, r as darkenTexture, s as toFloatTexture, t as blendPixel } from "./blend-D0XWgVQr.js";
|
|
4
|
+
import { t as combineFaceBuffers } from "./compose-lWPrB7wh.js";
|
|
5
|
+
import { a as drawTexturedTriangle, i as createFaceBuffer, n as clearFaceBuffer, o as phpRound, t as RowCursor } from "./rasterizer-76qO8TDh.js";
|
|
6
|
+
import { n as renderFace, t as faceMaxZ } from "./face-Cl1O4m2i.js";
|
|
8
7
|
import { t as paintBucketFluid } from "./fluid-bucket-D-GpUQjg.js";
|
|
9
8
|
import { r as buildElementFaces } from "./geometry-uIDha8S4.js";
|
|
10
9
|
import { c as lightsForProfile } from "./lighting--5myudVu.js";
|
|
10
|
+
import { i as resolveTexture } from "./loader-B8NJO7pR.js";
|
|
11
11
|
//#region src/render/obj.ts
|
|
12
12
|
/**
|
|
13
13
|
* Forge/NeoForge OBJ model rendering — the class the old pipeline left
|
|
@@ -140,6 +140,7 @@ async function renderObjModel(model, resources, textures, options) {
|
|
|
140
140
|
const transformation = multiply(guiMatrix, options.itemTransform ?? identity());
|
|
141
141
|
const renderSize = options.size * options.quality;
|
|
142
142
|
const out = createFaceBuffer(renderSize, renderSize);
|
|
143
|
+
const scratch = createFaceBuffer(renderSize, renderSize);
|
|
143
144
|
const shaded = /* @__PURE__ */ new Map();
|
|
144
145
|
for (const triangle of parsed.triangles) {
|
|
145
146
|
const transformed = triangle.positions.map((position) => transformVector(transformation, position));
|
|
@@ -164,7 +165,7 @@ async function renderObjModel(model, resources, textures, options) {
|
|
|
164
165
|
darkenTexture(texture, 1 - bucket / 64, 0, 0, texture.width, texture.height);
|
|
165
166
|
shaded.set(key, texture);
|
|
166
167
|
}
|
|
167
|
-
|
|
168
|
+
clearFaceBuffer(scratch);
|
|
168
169
|
const cursor = new RowCursor();
|
|
169
170
|
const point = (index) => {
|
|
170
171
|
return {
|
|
@@ -176,7 +177,8 @@ async function renderObjModel(model, resources, textures, options) {
|
|
|
176
177
|
};
|
|
177
178
|
};
|
|
178
179
|
drawTexturedTriangle(point(0), point(1), point(2), scratch, texture, cursor);
|
|
179
|
-
for (let
|
|
180
|
+
for (let y = Math.max(scratch.dirty.minY, 0); y <= Math.min(scratch.dirty.maxY, renderSize - 1); y++) for (let x = Math.max(scratch.dirty.minX, 0); x <= Math.min(scratch.dirty.maxX, renderSize - 1); x++) {
|
|
181
|
+
const pixel = y * renderSize + x;
|
|
180
182
|
const offset = pixel * 4;
|
|
181
183
|
const alpha = scratch.colors[offset + 3];
|
|
182
184
|
if (alpha <= 0) continue;
|
|
@@ -241,16 +243,19 @@ async function renderModelFrames(model, textures, options) {
|
|
|
241
243
|
ticks = ticks / gcd(ticks, texture.tickLength) * texture.tickLength;
|
|
242
244
|
interpolated ||= texture.interpolated;
|
|
243
245
|
}
|
|
244
|
-
const
|
|
246
|
+
const maxFrames = Math.max(1, options.animation?.maxFrames ?? MAX_ANIMATION_FRAMES);
|
|
247
|
+
const exact = interpolated ? null : changeTicks(animated.values().toArray(), ticks, maxFrames);
|
|
248
|
+
const candidates = exact ?? evenlySpacedTicks(ticks, maxFrames);
|
|
245
249
|
const frames = [];
|
|
246
250
|
const emitTicks = [];
|
|
247
251
|
let lastKey = null;
|
|
248
|
-
|
|
249
|
-
for (
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
252
|
+
const session = createSession();
|
|
253
|
+
for (const tick of candidates) {
|
|
254
|
+
const key = animated.values().map((texture) => {
|
|
255
|
+
const resolved = texture.resolveFrame(tick);
|
|
256
|
+
return texture.interpolated ? `${resolved.frame}+${resolved.interpolation}` : String(resolved.frame);
|
|
257
|
+
}).toArray().join(",");
|
|
258
|
+
if (key === lastKey) continue;
|
|
254
259
|
const supplier = async (reference) => {
|
|
255
260
|
if (skipped.has(reference)) return null;
|
|
256
261
|
const texture = animated.get(reference);
|
|
@@ -258,20 +263,59 @@ async function renderModelFrames(model, textures, options) {
|
|
|
258
263
|
return texture.at(tick);
|
|
259
264
|
};
|
|
260
265
|
const renderSize = options.size * options.quality;
|
|
261
|
-
const full = model.builtinParent === "builtin/generated" ? await renderGeneratedItemWith(model, supplier, renderSize, options.tints) : await renderElementModelWith(model, supplier, renderSize, options);
|
|
266
|
+
const full = model.builtinParent === "builtin/generated" ? await renderGeneratedItemWith(model, supplier, renderSize, options.tints) : await renderElementModelWith(model, supplier, renderSize, options, session);
|
|
262
267
|
frames.push(options.quality === 1 ? full : boxDownscale(full, options.quality));
|
|
263
268
|
emitTicks.push(tick);
|
|
264
269
|
lastKey = key;
|
|
265
|
-
sinceLast = 0;
|
|
266
270
|
}
|
|
267
271
|
return {
|
|
268
272
|
frames,
|
|
269
273
|
delaysMs: emitTicks.map((tick, index) => {
|
|
270
274
|
const next = index + 1 < emitTicks.length ? emitTicks[index + 1] : ticks;
|
|
271
275
|
return Math.max(TICK_MS, (next - tick) * TICK_MS);
|
|
272
|
-
})
|
|
276
|
+
}),
|
|
277
|
+
animation: {
|
|
278
|
+
ticks,
|
|
279
|
+
candidates: candidates.length,
|
|
280
|
+
sampled: exact === null && ticks > frames.length,
|
|
281
|
+
interpolated
|
|
282
|
+
}
|
|
273
283
|
};
|
|
274
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* Every tick in the combined timeline where some texture switches frame, or
|
|
287
|
+
* null once that exceeds `limit` — past that the caller samples instead, and
|
|
288
|
+
* enumerating a multi-minute timeline in full would be the very cost this
|
|
289
|
+
* bound exists to avoid.
|
|
290
|
+
*/
|
|
291
|
+
function changeTicks(textures, ticks, limit) {
|
|
292
|
+
const found = /* @__PURE__ */ new Set([0]);
|
|
293
|
+
for (const texture of textures) {
|
|
294
|
+
if (texture.frameCount <= 1) continue;
|
|
295
|
+
const period = Math.max(1, texture.tickLength);
|
|
296
|
+
const starts = texture.frameStartTicks();
|
|
297
|
+
for (let base = 0; base < ticks; base += period) for (const start of starts) {
|
|
298
|
+
const tick = base + start;
|
|
299
|
+
if (tick < ticks) found.add(tick);
|
|
300
|
+
if (found.size > limit) return null;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return [...found].toSorted((left, right) => left - right);
|
|
304
|
+
}
|
|
305
|
+
/** `count` tick positions spread evenly across the cycle, always starting at 0. */
|
|
306
|
+
function evenlySpacedTicks(ticks, maxFrames) {
|
|
307
|
+
const count = Math.min(ticks, maxFrames);
|
|
308
|
+
const sampled = [];
|
|
309
|
+
let previous = -1;
|
|
310
|
+
for (let index = 0; index < count; index++) {
|
|
311
|
+
const tick = Math.floor(index * ticks / count);
|
|
312
|
+
if (tick !== previous) {
|
|
313
|
+
sampled.push(tick);
|
|
314
|
+
previous = tick;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return sampled;
|
|
318
|
+
}
|
|
275
319
|
async function loadAnimatedTexture(model, textures, reference) {
|
|
276
320
|
const locator = resolveTexture(model, reference);
|
|
277
321
|
if (locator) {
|
|
@@ -391,11 +435,23 @@ async function renderElementModel(model, textures, renderSize, options) {
|
|
|
391
435
|
};
|
|
392
436
|
return renderElementModelWith(model, supplier, renderSize, options);
|
|
393
437
|
}
|
|
394
|
-
|
|
438
|
+
function createSession() {
|
|
439
|
+
return {
|
|
440
|
+
geometry: null,
|
|
441
|
+
order: null,
|
|
442
|
+
transformation: null,
|
|
443
|
+
scratch: null,
|
|
444
|
+
shadeCache: /* @__PURE__ */ new WeakMap(),
|
|
445
|
+
floatTextures: /* @__PURE__ */ new Map(),
|
|
446
|
+
faceBuffers: []
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
/** Interpolated frames are new objects every tick; don't grow without bound. */
|
|
450
|
+
const MAX_CACHED_FLOAT_TEXTURES = 32;
|
|
451
|
+
async function renderElementModelWith(model, supplier, renderSize, options, session = createSession()) {
|
|
395
452
|
const lights = lightsForProfile(options.lightingProfile);
|
|
396
453
|
const light = model.elementsGuiLight === "side" ? lights.side : lights.front;
|
|
397
454
|
const loadedTextures = /* @__PURE__ */ new Map();
|
|
398
|
-
const floatTextures = /* @__PURE__ */ new Map();
|
|
399
455
|
const load = (reference) => {
|
|
400
456
|
let pending = loadedTextures.get(reference);
|
|
401
457
|
if (!pending) {
|
|
@@ -404,47 +460,68 @@ async function renderElementModelWith(model, supplier, renderSize, options) {
|
|
|
404
460
|
}
|
|
405
461
|
return pending;
|
|
406
462
|
};
|
|
407
|
-
|
|
463
|
+
if (!session.geometry) {
|
|
464
|
+
const geometry = [];
|
|
465
|
+
for (const element of model.elements) for (const face of buildElementFaces(element)) geometry.push({
|
|
466
|
+
geometry: face,
|
|
467
|
+
maxZ: faceMaxZ(face)
|
|
468
|
+
});
|
|
469
|
+
session.geometry = geometry;
|
|
470
|
+
session.order = geometry.map((_, index) => index).toSorted((left, right) => geometry[left].maxZ - geometry[right].maxZ);
|
|
471
|
+
}
|
|
472
|
+
const specs = session.geometry;
|
|
473
|
+
const order = session.order ?? [];
|
|
408
474
|
let skippedFaces = 0;
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
475
|
+
let drawable = 0;
|
|
476
|
+
for (const spec of specs) if (await load(spec.geometry.textureRef)) drawable++;
|
|
477
|
+
else skippedFaces++;
|
|
478
|
+
if (drawable === 0 && skippedFaces > 0) throw new ItemRenderError(`Every face texture unresolved in ${model.locator} (would render invisible)`);
|
|
479
|
+
if (!session.transformation) {
|
|
480
|
+
const gui = model.display.gui;
|
|
481
|
+
const guiMatrix = displayMatrix(gui?.rotation ?? [
|
|
482
|
+
0,
|
|
483
|
+
0,
|
|
484
|
+
0
|
|
485
|
+
], gui?.translation ?? [
|
|
486
|
+
0,
|
|
487
|
+
0,
|
|
488
|
+
0
|
|
489
|
+
], gui?.scale ?? [
|
|
490
|
+
1,
|
|
491
|
+
1,
|
|
492
|
+
1
|
|
493
|
+
]);
|
|
494
|
+
session.transformation = multiply(guiMatrix, options.itemTransform ?? identity());
|
|
495
|
+
}
|
|
496
|
+
session.scratch ??= createFaceBuffer(renderSize, renderSize);
|
|
497
|
+
if (session.floatTextures.size > MAX_CACHED_FLOAT_TEXTURES) session.floatTextures.clear();
|
|
498
|
+
const buffers = [];
|
|
499
|
+
for (const index of order) {
|
|
500
|
+
const spec = specs[index];
|
|
501
|
+
const texture = await load(spec.geometry.textureRef);
|
|
502
|
+
if (!texture) continue;
|
|
503
|
+
let float = session.floatTextures.get(texture);
|
|
416
504
|
if (!float) {
|
|
417
505
|
float = toFloatTexture(texture);
|
|
418
|
-
floatTextures.set(texture, float);
|
|
506
|
+
session.floatTextures.set(texture, float);
|
|
419
507
|
}
|
|
420
|
-
|
|
421
|
-
|
|
508
|
+
const cached = session.faceBuffers[index];
|
|
509
|
+
if (cached?.texture === float) {
|
|
510
|
+
if (cached.buffer) buffers.push(cached.buffer);
|
|
511
|
+
continue;
|
|
512
|
+
}
|
|
513
|
+
const face = {
|
|
514
|
+
geometry: spec.geometry,
|
|
422
515
|
texture: float,
|
|
423
516
|
light,
|
|
424
|
-
tint: geometry.tintIndex !== null ? options.tints?.[geometry.tintIndex] ?? null : null,
|
|
425
|
-
maxZ:
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
0,
|
|
433
|
-
0,
|
|
434
|
-
0
|
|
435
|
-
], gui?.translation ?? [
|
|
436
|
-
0,
|
|
437
|
-
0,
|
|
438
|
-
0
|
|
439
|
-
], gui?.scale ?? [
|
|
440
|
-
1,
|
|
441
|
-
1,
|
|
442
|
-
1
|
|
443
|
-
]);
|
|
444
|
-
const transformation = multiply(guiMatrix, options.itemTransform ?? identity());
|
|
445
|
-
const buffers = [];
|
|
446
|
-
for (const face of faces) {
|
|
447
|
-
const buffer = renderFace(face, renderSize, renderSize, transformation);
|
|
517
|
+
tint: spec.geometry.tintIndex !== null ? options.tints?.[spec.geometry.tintIndex] ?? null : null,
|
|
518
|
+
maxZ: spec.maxZ
|
|
519
|
+
};
|
|
520
|
+
const buffer = renderFace(face, renderSize, renderSize, session.transformation, session.scratch, session.shadeCache);
|
|
521
|
+
session.faceBuffers[index] = {
|
|
522
|
+
texture: float,
|
|
523
|
+
buffer
|
|
524
|
+
};
|
|
448
525
|
if (buffer) buffers.push(buffer);
|
|
449
526
|
}
|
|
450
527
|
return combineFaceBuffers(renderSize, renderSize, buffers);
|
|
@@ -452,14 +529,19 @@ async function renderElementModelWith(model, supplier, renderSize, options) {
|
|
|
452
529
|
/** Nearest-neighbour resize matching Imagick FILTER_POINT (destination-center sampling). */
|
|
453
530
|
function pointResize(texture, width, height) {
|
|
454
531
|
const data = new Float64Array(width * height * 4);
|
|
532
|
+
const srcXs = new Int32Array(width);
|
|
533
|
+
for (let x = 0; x < width; x++) {
|
|
534
|
+
const srcX = Math.floor((x + .5) * texture.width / width);
|
|
535
|
+
srcXs[x] = srcX >= texture.width ? texture.width - 1 : srcX;
|
|
536
|
+
}
|
|
455
537
|
for (let y = 0; y < height; y++) {
|
|
456
538
|
let srcY = Math.floor((y + .5) * texture.height / height);
|
|
457
539
|
srcY = srcY >= texture.height ? texture.height - 1 : srcY;
|
|
540
|
+
const srcRow = srcY * texture.width;
|
|
541
|
+
const dstRow = y * width;
|
|
458
542
|
for (let x = 0; x < width; x++) {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
const src = (srcY * texture.width + srcX) * 4;
|
|
462
|
-
const dst = (y * width + x) * 4;
|
|
543
|
+
const src = (srcRow + srcXs[x]) * 4;
|
|
544
|
+
const dst = (dstRow + x) * 4;
|
|
463
545
|
data[dst] = texture.data[src];
|
|
464
546
|
data[dst + 1] = texture.data[src + 1];
|
|
465
547
|
data[dst + 2] = texture.data[src + 2];
|
|
@@ -485,6 +567,7 @@ function boxPass(texture, factor, isHorizontal) {
|
|
|
485
567
|
const width = isHorizontal ? Math.round(texture.width / factor) : texture.width;
|
|
486
568
|
const height = isHorizontal ? texture.height : Math.round(texture.height / factor);
|
|
487
569
|
const data = new Float64Array(width * height * 4);
|
|
570
|
+
const { data: src } = texture;
|
|
488
571
|
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
489
572
|
let r = 0;
|
|
490
573
|
let g = 0;
|
|
@@ -492,11 +575,11 @@ function boxPass(texture, factor, isHorizontal) {
|
|
|
492
575
|
let alphaSum = 0;
|
|
493
576
|
for (let i = 0; i < factor; i++) {
|
|
494
577
|
const srcX = isHorizontal ? x * factor + i : x;
|
|
495
|
-
const
|
|
496
|
-
const alpha = Math.round(
|
|
497
|
-
r += Math.round(
|
|
498
|
-
g += Math.round(
|
|
499
|
-
b += Math.round(
|
|
578
|
+
const srcOffset = ((isHorizontal ? y : y * factor + i) * texture.width + srcX) * 4;
|
|
579
|
+
const alpha = Math.round(src[srcOffset + 3] * 65535);
|
|
580
|
+
r += Math.round(src[srcOffset] * 65535) * alpha;
|
|
581
|
+
g += Math.round(src[srcOffset + 1] * 65535) * alpha;
|
|
582
|
+
b += Math.round(src[srcOffset + 2] * 65535) * alpha;
|
|
500
583
|
alphaSum += alpha;
|
|
501
584
|
}
|
|
502
585
|
const dst = (y * width + x) * 4;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/resources/cache.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Least-recently-used map used by the model and texture loaders. Their caches
|
|
4
|
+
* were unbounded, which is fine for one namespace and not fine for a run that
|
|
5
|
+
* walks thousands of them in a single process — resident memory only ever grew.
|
|
6
|
+
*/
|
|
7
|
+
declare class LruCache<K, V> {
|
|
8
|
+
private readonly entries;
|
|
9
|
+
private readonly maxEntries;
|
|
10
|
+
private readonly weigh;
|
|
11
|
+
private readonly maxWeight;
|
|
12
|
+
private readonly weights;
|
|
13
|
+
private weight;
|
|
14
|
+
constructor(maxEntries: number, options?: {
|
|
15
|
+
maxWeight?: number;
|
|
16
|
+
weigh?: (value: V) => number;
|
|
17
|
+
});
|
|
18
|
+
private evict;
|
|
19
|
+
get size(): number;
|
|
20
|
+
get(key: K): V | undefined;
|
|
21
|
+
set(key: K, value: V): void;
|
|
22
|
+
/**
|
|
23
|
+
* Record a value's real cost once it is known. Loaders cache promises, so the
|
|
24
|
+
* weight of a decoded texture only exists after it resolves.
|
|
25
|
+
*/
|
|
26
|
+
settle(key: K, value: V): void;
|
|
27
|
+
clear(): void;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { LruCache };
|
package/dist/resources/jar.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as UnsafeJarError, r as isUnsafeEntryPath, t as JarResourceManager } from "../jar-
|
|
1
|
+
import { n as UnsafeJarError, r as isUnsafeEntryPath, t as JarResourceManager } from "../jar-CFkA-VgT.js";
|
|
2
2
|
export { JarResourceManager, UnsafeJarError, isUnsafeEntryPath };
|
package/dist/resources/jar.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as UnsafeJarError, r as isUnsafeEntryPath, t as JarResourceManager } from "../jar-
|
|
1
|
+
import { n as UnsafeJarError, r as isUnsafeEntryPath, t as JarResourceManager } from "../jar-D9z-X7tA.js";
|
|
2
2
|
export { JarResourceManager, UnsafeJarError, isUnsafeEntryPath };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as ResourceManager, i as ResourceKindName, n as LayeredResourceManager, r as ResourceKind, t as FolderResourceManager } from "../manager-
|
|
1
|
+
import { a as ResourceManager, i as ResourceKindName, n as LayeredResourceManager, r as ResourceKind, t as FolderResourceManager } from "../manager-Cv1NeFyF.js";
|
|
2
2
|
export { FolderResourceManager, LayeredResourceManager, ResourceKind, ResourceKindName, ResourceManager };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as LayeredResourceManager, r as ResourceKind, t as FolderResourceManager } from "../manager-
|
|
1
|
+
import { n as LayeredResourceManager, r as ResourceKind, t as FolderResourceManager } from "../manager-CkletR5K.js";
|
|
2
2
|
export { FolderResourceManager, LayeredResourceManager, ResourceKind };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as MapResourceManager, t as KindFilteredResourceManager } from "../synthetic-
|
|
1
|
+
import { n as MapResourceManager, t as KindFilteredResourceManager } from "../synthetic-Qk-BSUXO.js";
|
|
2
2
|
export { KindFilteredResourceManager, MapResourceManager };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as MapResourceManager, t as KindFilteredResourceManager } from "../synthetic-
|
|
1
|
+
import { n as MapResourceManager, t as KindFilteredResourceManager } from "../synthetic-ZAUjXT7E.js";
|
|
2
2
|
export { KindFilteredResourceManager, MapResourceManager };
|