minerender 2.1.0-beta.5 → 2.1.0-beta.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/dist/browser/esm/Materials.mjs +6 -3
- package/dist/browser/esm/Materials.mjs.map +1 -1
- package/dist/browser/esm/Ticker.mjs +3 -1
- package/dist/browser/esm/Ticker.mjs.map +1 -1
- package/dist/browser/esm/UVMapper.mjs +9 -9
- package/dist/browser/esm/UVMapper.mjs.map +1 -1
- package/dist/browser/esm/assets/AssetDefaults.mjs +8 -0
- package/dist/browser/esm/assets/AssetDefaults.mjs.map +1 -0
- package/dist/browser/esm/assets/AssetKey.mjs +1 -1
- package/dist/browser/esm/assets/AssetKey.mjs.map +1 -1
- package/dist/browser/esm/assets/AssetLoader.mjs +5 -5
- package/dist/browser/esm/assets/AssetLoader.mjs.map +1 -1
- package/dist/browser/esm/assets/Assets.mjs +1 -5
- package/dist/browser/esm/assets/Assets.mjs.map +1 -1
- package/dist/browser/esm/assets/BlockEntities.mjs +3 -1
- package/dist/browser/esm/assets/BlockEntities.mjs.map +1 -1
- package/dist/browser/esm/assets/BlockStates.mjs +1 -1
- package/dist/browser/esm/assets/BlockStates.mjs.map +1 -1
- package/dist/browser/esm/assets/Entities.mjs +1 -1
- package/dist/browser/esm/assets/Entities.mjs.map +1 -1
- package/dist/browser/esm/assets/Fonts.mjs +31 -4
- package/dist/browser/esm/assets/Fonts.mjs.map +1 -1
- package/dist/browser/esm/assets/Models.mjs +1 -1
- package/dist/browser/esm/assets/Models.mjs.map +1 -1
- package/dist/browser/esm/assets/_fonts/Unihex.mjs +168 -0
- package/dist/browser/esm/assets/_fonts/Unihex.mjs.map +1 -0
- package/dist/browser/esm/assets/index.mjs +1 -0
- package/dist/browser/esm/assets/index.mjs.map +1 -1
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs +19 -9
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs.map +1 -1
- package/dist/browser/esm/assets/source/parser/AssetParsers.mjs +1 -0
- package/dist/browser/esm/assets/source/parser/AssetParsers.mjs.map +1 -1
- package/dist/browser/esm/cache/Caching.mjs +2 -0
- package/dist/browser/esm/cache/Caching.mjs.map +1 -1
- package/dist/browser/esm/entity/scene/EntityAnimationPlayer.mjs +62 -11
- package/dist/browser/esm/entity/scene/EntityAnimationPlayer.mjs.map +1 -1
- package/dist/browser/esm/entity/scene/EntityObject.mjs +53 -20
- package/dist/browser/esm/entity/scene/EntityObject.mjs.map +1 -1
- package/dist/browser/esm/env/browser/BrowserCache.mjs +3 -3
- package/dist/browser/esm/env/browser/BrowserCache.mjs.map +1 -1
- package/dist/browser/esm/env/browser/section.worker.mjs +5 -3
- package/dist/browser/esm/env/browser/section.worker.mjs.map +1 -1
- package/dist/browser/esm/gui/GuiText.mjs +4 -3
- package/dist/browser/esm/gui/GuiText.mjs.map +1 -1
- package/dist/browser/esm/image/ImageLoader.mjs +3 -3
- package/dist/browser/esm/image/ImageLoader.mjs.map +1 -1
- package/dist/browser/esm/index.browser.d.mts +115 -20
- package/dist/browser/esm/inspector/SceneInspector.mjs +3 -3
- package/dist/browser/esm/inspector/SceneInspector.mjs.map +1 -1
- package/dist/browser/esm/instance/InstanceManager.mjs +4 -4
- package/dist/browser/esm/instance/InstanceManager.mjs.map +1 -1
- package/dist/browser/esm/model/block/scene/BlockObject.mjs +3 -1
- package/dist/browser/esm/model/block/scene/BlockObject.mjs.map +1 -1
- package/dist/browser/esm/model/multiblock/StructureParser.mjs +7 -4
- package/dist/browser/esm/model/multiblock/StructureParser.mjs.map +1 -1
- package/dist/browser/esm/model/scene/ModelObject.mjs +8 -4
- package/dist/browser/esm/model/scene/ModelObject.mjs.map +1 -1
- package/dist/browser/esm/nbt/NBTHelper.mjs +5 -2
- package/dist/browser/esm/nbt/NBTHelper.mjs.map +1 -1
- package/dist/browser/esm/renderer/Renderer.mjs +4 -2
- package/dist/browser/esm/renderer/Renderer.mjs.map +1 -1
- package/dist/browser/esm/renderer/SceneObject.mjs +0 -6
- package/dist/browser/esm/renderer/SceneObject.mjs.map +1 -1
- package/dist/browser/esm/request/Requests.mjs +3 -3
- package/dist/browser/esm/request/Requests.mjs.map +1 -1
- package/dist/browser/esm/skin/Skins.mjs +6 -4
- package/dist/browser/esm/skin/Skins.mjs.map +1 -1
- package/dist/browser/esm/texture/TextureLoader.mjs +4 -2
- package/dist/browser/esm/texture/TextureLoader.mjs.map +1 -1
- package/dist/browser/esm/util/log.mjs +75 -0
- package/dist/browser/esm/util/log.mjs.map +1 -1
- package/dist/browser/esm/util/model.mjs +7 -7
- package/dist/browser/esm/util/model.mjs.map +1 -1
- package/dist/browser/esm/util/performance.mjs.map +1 -1
- package/dist/browser/esm/world/Chunk.mjs +8 -5
- package/dist/browser/esm/world/Chunk.mjs.map +1 -1
- package/dist/browser/esm/world/MineRenderWorld.mjs +96 -54
- package/dist/browser/esm/world/MineRenderWorld.mjs.map +1 -1
- package/dist/browser/esm/world/SectionGeometry.mjs +5 -3
- package/dist/browser/esm/world/SectionGeometry.mjs.map +1 -1
- package/dist/browser/esm/world/SectionMesh.mjs +4 -0
- package/dist/browser/esm/world/SectionMesh.mjs.map +1 -1
- package/dist/browser/esm/world/SectionModels.mjs +2 -2
- package/dist/browser/esm/world/SectionModels.mjs.map +1 -1
- package/dist/browser/esm/world/WorldStreamer.mjs +21 -20
- package/dist/browser/esm/world/WorldStreamer.mjs.map +1 -1
- package/dist/browser/esm/world/_culling/BlockCulling.mjs +1 -1
- package/dist/browser/esm/world/_culling/BlockCulling.mjs.map +1 -1
- package/dist/browser/esm/world/_entities/WorldEntities.mjs +3 -1
- package/dist/browser/esm/world/_entities/WorldEntities.mjs.map +1 -1
- package/dist/browser/index.d.ts +115 -20
- package/dist/browser/index.js +3449 -3025
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +13217 -12745
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +115 -20
- package/dist/node/index.d.ts +115 -20
- package/dist/node/index.js +3477 -3046
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +3456 -3027
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/entity/scene/EntityAnimationPlayer.ts"],"sourcesContent":["import { Euler, Vector3 } from \"three\";\nimport type { Object3D } from \"three\";\nimport { EntityAnimation, sampleEntityAnimation } from \"../EntityAnimation\";\nimport type { EntityModelPart } from \"../EntityModel\";\n\n/** Playback settings passed to {@link EntityObject.playAnimation}, {@link EntityObject.playAnimations}, or {@link EntityAnimationPlayer.play}. */\nexport interface EntityAnimationOptions {\n /** Overrides the animation's own `loop` flag. */\n loop?: boolean;\n /** Playback rate applied to advanced time; defaults to 1. */\n speed?: number;\n /** Start time in seconds; defaults to 0. */\n time?: number;\n}\n\nconst ZERO: readonly number[] = [0, 0, 0];\n\ninterface AnimatedPart {\n bone: string;\n object: Object3D;\n position: Vector3;\n rotation: Euler;\n scale: Vector3;\n basePosition: Vector3;\n baseRotation: Euler;\n baseScale: Vector3;\n}\n\n/**\n * Poses part groups from a keyframe animation the way vanilla does: every update restores the\n * default pose of each animated part, then adds the sampled offsets to its position, Euler angles and scale.\n * It owns no timer; the owner advances it.\n */\nexport class EntityAnimationPlayer {\n\n private parts: AnimatedPart[] = [];\n private _animation?: EntityAnimation;\n private _time = 0;\n private loop = false;\n private speed = 1;\n\n get animation(): EntityAnimation | undefined {\n return this._animation;\n }\n\n get time(): number {\n return this._time;\n }\n\n /**\n * Starts an animation on matching named parts. Supplied baked poses are the baseline for offsets;\n * without them, the current pose is used. Stopping restores the pose from before playback.\n */\n play(layers: Object3D[], animation: EntityAnimation, options: EntityAnimationOptions = {},\n poses?: ReadonlyMap<Object3D, EntityModelPart[\"pose\"]>): void {\n this.stop();\n this._animation = animation;\n this._time = options.time ?? 0;\n this.loop = options.loop ?? animation.loop;\n this.speed = options.speed ?? 1;\n for (const layer of layers) {\n const objects: Object3D[] = [];\n if (poses) {\n layer.traverse(object => { if (poses.has(object)) objects.push(object); });\n } else {\n for (const bone of Object.keys(animation.bones)) {\n const object = layer.getObjectByName(`group:${bone}`);\n if (object) objects.push(object);\n }\n }\n for (const object of objects) {\n const bone = object.name.slice(\"group:\".length);\n const pose = poses?.get(object);\n this.parts.push({\n bone, object, position: object.position.clone(), rotation: object.rotation.clone(), scale: object.scale.clone(),\n basePosition: pose ? new Vector3(...pose.offset) : object.position.clone(),\n baseRotation: pose ? new Euler(...pose.rotation, \"ZYX\") : object.rotation.clone(),\n baseScale: pose ? new Vector3(...(pose.scale ?? [1, 1, 1])) : object.scale.clone()\n });\n }\n }\n this.apply();\n }\n\n /** Restores the poses from before playback. Returns whether an animation was active. */\n stop(): boolean {\n if (!this._animation) return false;\n for (const part of this.parts) {\n part.object.position.copy(part.position);\n part.object.rotation.copy(part.rotation);\n part.object.scale.copy(part.scale);\n }\n this.clear();\n return true;\n }\n\n /** Forgets the animation without touching the parts, for parts that no longer exist. */\n clear(): void {\n this.parts = [];\n this._animation = undefined;\n this._time = 0;\n }\n\n /** Applies the pose at an absolute playback time. Returns `false` when no clip is active. */\n setTime(seconds: number): boolean {\n if (!this._animation) return false;\n this._time = seconds;\n this.apply();\n return true;\n }\n\n /** Advances playback by elapsed seconds multiplied by the speed passed to {@link play}. */\n advance(deltaSeconds: number): boolean {\n return this.setTime(this._time + deltaSeconds * this.speed);\n }\n\n private apply(): void {\n const pose = sampleEntityAnimation(this._animation!, this._time, this.loop);\n for (const part of this.parts) {\n const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone] ?? {};\n part.object.position.set(part.basePosition.x + position[0], part.basePosition.y + position[1], part.basePosition.z + position[2]);\n // Vanilla adds to the Euler angles themselves, so the part keeps its rotation order.\n part.object.rotation.set(part.baseRotation.x + rotation[0], part.baseRotation.y + rotation[1], part.baseRotation.z + rotation[2], part.baseRotation.order);\n part.object.scale.set(part.baseScale.x + scale[0], part.baseScale.y + scale[1], part.baseScale.z + scale[2]);\n }\n }\n\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/entity/scene/EntityAnimationPlayer.ts"],"sourcesContent":["import { Euler, Vector3 } from \"three\";\nimport type { Object3D } from \"three\";\nimport { ENTITY_ANIMATION_CHANNELS, EntityAnimation, sampleEntityAnimation } from \"../EntityAnimation\";\nimport type { EntityAnimationPose } from \"../EntityAnimation\";\nimport type { EntityModelPart } from \"../EntityModel\";\n\n/** Playback settings passed to {@link EntityObject.playAnimation}, {@link EntityObject.playAnimations}, or {@link EntityAnimationPlayer.play}. */\nexport interface EntityAnimationOptions {\n /** Overrides the animation's own `loop` flag. */\n loop?: boolean;\n /** Playback rate applied to advanced time; defaults to 1. */\n speed?: number;\n /** Start time in seconds; defaults to 0. */\n time?: number;\n /** Nonnegative finite weights in clip order; defaults to 1 per clip. Offsets add without normalizing weights. */\n weights?: readonly number[];\n}\n\nconst ZERO: readonly number[] = [0, 0, 0];\n\ninterface AnimatedPart {\n bone: string;\n object: Object3D;\n position: Vector3;\n rotation: Euler;\n scale: Vector3;\n basePosition: Vector3;\n baseRotation: Euler;\n baseScale: Vector3;\n}\n\n/**\n * Poses part groups from keyframe animations: every update restores the default pose of each\n * animated part, then adds weighted sampled offsets to its position, Euler angles and scale.\n * It owns no timer; the owner advances it.\n */\nexport class EntityAnimationPlayer {\n\n private parts: AnimatedPart[] = [];\n private _animations: EntityAnimation[] = [];\n private _weights: number[] = [];\n private loops: boolean[] = [];\n private _time = 0;\n private speed = 1;\n\n get animation(): EntityAnimation | undefined {\n return this._animations[0];\n }\n\n get animations(): readonly EntityAnimation[] {\n return this._animations.slice();\n }\n\n get weights(): readonly number[] {\n return this._weights.slice();\n }\n\n get time(): number {\n return this._time;\n }\n\n /**\n * Starts an animation on matching named parts. Supplied baked poses are the baseline for offsets;\n * without them, the current pose is used. Stopping restores the pose from before playback.\n */\n play(layers: Object3D[], animation: EntityAnimation, options: EntityAnimationOptions = {},\n poses?: ReadonlyMap<Object3D, EntityModelPart[\"pose\"]>): void {\n this.playAnimations(layers, [animation], options, poses);\n }\n\n /**\n * Starts clips on matching parts with a shared clock. Weighted offsets add to the supplied baked poses\n * or, without poses, to each animated part's pose when playback starts.\n */\n playAnimations(layers: Object3D[], animations: readonly EntityAnimation[], options: EntityAnimationOptions = {},\n poses?: ReadonlyMap<Object3D, EntityModelPart[\"pose\"]>): void {\n const weights = validateAnimationWeights(options.weights ?? animations.map(() => 1), animations.length);\n this.stop();\n this._animations = animations.slice();\n this._weights = weights;\n if (!animations.length) return;\n this._time = options.time ?? 0;\n this.loops = animations.map(animation => options.loop ?? animation.loop);\n this.speed = options.speed ?? 1;\n for (const layer of layers) {\n const objects: Object3D[] = [];\n if (poses) {\n layer.traverse(object => { if (poses.has(object)) objects.push(object); });\n } else {\n const bones = new Set(animations.flatMap(animation => Object.keys(animation.bones)));\n for (const bone of bones) {\n const object = layer.getObjectByName(`group:${bone}`);\n if (object) objects.push(object);\n }\n }\n for (const object of objects) {\n const bone = object.name.slice(\"group:\".length);\n const pose = poses?.get(object);\n this.parts.push({\n bone, object, position: object.position.clone(), rotation: object.rotation.clone(), scale: object.scale.clone(),\n basePosition: pose ? new Vector3(...pose.offset) : object.position.clone(),\n baseRotation: pose ? new Euler(...pose.rotation, \"ZYX\") : object.rotation.clone(),\n baseScale: pose ? new Vector3(...(pose.scale ?? [1, 1, 1])) : object.scale.clone()\n });\n }\n }\n this.apply();\n }\n\n /** Restores the poses from before playback. Returns whether an animation was active. */\n stop(): boolean {\n if (!this._animations.length) return false;\n for (const part of this.parts) {\n part.object.position.copy(part.position);\n part.object.rotation.copy(part.rotation);\n part.object.scale.copy(part.scale);\n }\n this.clear();\n return true;\n }\n\n /** Forgets the animation without touching the parts, for parts that no longer exist. */\n clear(): void {\n this.parts = [];\n this._animations = [];\n this._weights = [];\n this.loops = [];\n this._time = 0;\n }\n\n /** Applies the pose at an absolute playback time. Returns `false` when no clip is active. */\n setTime(seconds: number): boolean {\n if (!this._animations.length) return false;\n this._time = seconds;\n this.apply();\n return true;\n }\n\n /** Advances playback by elapsed seconds multiplied by the speed passed to {@link play}. */\n advance(deltaSeconds: number): boolean {\n return this.setTime(this._time + deltaSeconds * this.speed);\n }\n\n /** Changes weights in clip order and reapplies the current time without restarting playback. */\n setWeights(weights: readonly number[]): boolean {\n if (!this._animations.length) return false;\n const validated = validateAnimationWeights(weights, this._animations.length);\n this._weights = validated;\n this.apply();\n return true;\n }\n\n private apply(): void {\n const pose: EntityAnimationPose = Object.create(null);\n for (let i = 0; i < this._animations.length; i++) {\n const weight = this._weights[i];\n if (weight === 0) continue;\n const sampled = sampleEntityAnimation(this._animations[i], this._time, this.loops[i]);\n for (const [bone, channels] of Object.entries(sampled)) {\n const blended = pose[bone] ??= {};\n for (const channel of ENTITY_ANIMATION_CHANNELS) {\n const value = channels[channel];\n if (!value) continue;\n const target = blended[channel] ??= [0, 0, 0];\n for (let axis = 0; axis < 3; axis++) target[axis] += value[axis] * weight;\n }\n }\n }\n for (const part of this.parts) {\n const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone] ?? {};\n part.object.position.set(part.basePosition.x + position[0], part.basePosition.y + position[1], part.basePosition.z + position[2]);\n // Vanilla adds to the Euler angles themselves, so the part keeps its rotation order.\n part.object.rotation.set(part.baseRotation.x + rotation[0], part.baseRotation.y + rotation[1], part.baseRotation.z + rotation[2], part.baseRotation.order);\n part.object.scale.set(part.baseScale.x + scale[0], part.baseScale.y + scale[1], part.baseScale.z + scale[2]);\n }\n }\n\n}\n\n/** @internal */\nexport function validateAnimationWeights(weights: readonly number[], count: number): number[] {\n const values = Array.from(weights);\n if (values.length !== count || values.some(weight => !Number.isFinite(weight) || weight < 0)) {\n throw new Error(\"Animation weights must match the clip count and contain only finite nonnegative numbers\");\n }\n return values;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -11,7 +11,7 @@ import { Materials } from "../../Materials.mjs";
|
|
|
11
11
|
import { MinecraftCubeTexture } from "../../MinecraftCubeTexture.mjs";
|
|
12
12
|
import { CUBE_FACES } from "../../CubeFace.mjs";
|
|
13
13
|
import { isMesh } from "../../util/three.mjs";
|
|
14
|
-
import { EntityAnimationPlayer } from "./EntityAnimationPlayer.mjs";
|
|
14
|
+
import { EntityAnimationPlayer, validateAnimationWeights } from "./EntityAnimationPlayer.mjs";
|
|
15
15
|
var _EntityObject = class _EntityObject extends SceneObject {
|
|
16
16
|
constructor(entity, options) {
|
|
17
17
|
super();
|
|
@@ -49,7 +49,7 @@ var _EntityObject = class _EntityObject extends SceneObject {
|
|
|
49
49
|
for (const geometry of this.geometries) geometry.dispose();
|
|
50
50
|
this.geometries.clear();
|
|
51
51
|
for (const dispose of this.disposeWireframes.splice(0)) dispose();
|
|
52
|
-
for (const player of this.animationPlayers.splice(0)) player.clear();
|
|
52
|
+
for (const { player } of this.animationPlayers.splice(0)) player.clear();
|
|
53
53
|
this.partPoses.clear();
|
|
54
54
|
super.disposeAndRemoveAllChildren();
|
|
55
55
|
}
|
|
@@ -84,15 +84,31 @@ var _EntityObject = class _EntityObject extends SceneObject {
|
|
|
84
84
|
//<editor-fold desc="ANIMATION">
|
|
85
85
|
/** The first active clip, until playback is stopped or the object is disposed. */
|
|
86
86
|
get animation() {
|
|
87
|
-
return this.animationPlayers[0]?.animation;
|
|
87
|
+
return this.animationPlayers[0]?.player.animation;
|
|
88
88
|
}
|
|
89
|
-
/** Clips playing together,
|
|
89
|
+
/** Clips playing together, in the order passed to {@link playAnimations}. */
|
|
90
90
|
get activeAnimations() {
|
|
91
|
-
|
|
91
|
+
const animations = [];
|
|
92
|
+
for (const { player, indices } of this.animationPlayers) {
|
|
93
|
+
player.animations.forEach((animation, i) => {
|
|
94
|
+
animations[indices[i]] = animation;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return animations;
|
|
98
|
+
}
|
|
99
|
+
/** Weights of the active clips, in the same order as {@link activeAnimations}. */
|
|
100
|
+
get animationWeights() {
|
|
101
|
+
const weights = [];
|
|
102
|
+
for (const { player, indices } of this.animationPlayers) {
|
|
103
|
+
player.weights.forEach((weight, i) => {
|
|
104
|
+
weights[indices[i]] = weight;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return weights;
|
|
92
108
|
}
|
|
93
109
|
/** Seconds since the animation started, before looping. */
|
|
94
110
|
get animationTime() {
|
|
95
|
-
return this.animationPlayers[0]?.time ?? 0;
|
|
111
|
+
return this.animationPlayers[0]?.player.time ?? 0;
|
|
96
112
|
}
|
|
97
113
|
/**
|
|
98
114
|
* Plays a clip from {@link Entities.getAnimations}, replacing all active clips.
|
|
@@ -103,42 +119,59 @@ var _EntityObject = class _EntityObject extends SceneObject {
|
|
|
103
119
|
playAnimation(animation, options) {
|
|
104
120
|
this.playAnimations([animation], options);
|
|
105
121
|
}
|
|
106
|
-
/**
|
|
122
|
+
/**
|
|
123
|
+
* Plays clips with a shared clock, adding their weighted offsets within each geometry layer.
|
|
124
|
+
* Weights default to 1 and are not normalized. Selected layers without their own clip follow `main`.
|
|
125
|
+
*/
|
|
107
126
|
playAnimations(animations, options) {
|
|
108
|
-
const
|
|
109
|
-
const selections =
|
|
127
|
+
const weights = validateAnimationWeights(options?.weights ?? animations.map(() => 1), animations.length);
|
|
128
|
+
const selections = /* @__PURE__ */ new Map();
|
|
129
|
+
animations.forEach((animation, index) => {
|
|
110
130
|
const layer = animation.layer ?? "main";
|
|
111
|
-
if (targets.has(layer)) throw new Error(`Multiple animations target layer "${layer}"`);
|
|
112
|
-
targets.add(layer);
|
|
113
131
|
const names = Object.keys(this.entityLayers).filter((name) => name.split("#")[0] === layer);
|
|
114
132
|
if (!names.length) throw new Error(`Entity ${this.entity.id} has no selected animation layer "${layer}"`);
|
|
115
|
-
|
|
133
|
+
let selection = selections.get(layer);
|
|
134
|
+
if (!selection) selections.set(layer, selection = { animations: [], names, indices: [] });
|
|
135
|
+
selection.animations.push(animation);
|
|
136
|
+
selection.indices.push(index);
|
|
116
137
|
});
|
|
117
|
-
const main = selections.
|
|
118
|
-
if (main) main.names.push(...Object.keys(this.entityLayers).filter((name) => !
|
|
138
|
+
const main = selections.get("main");
|
|
139
|
+
if (main) main.names.push(...Object.keys(this.entityLayers).filter((name) => !selections.has(name.split("#")[0])));
|
|
119
140
|
this.createMeshes();
|
|
120
141
|
this.stopAnimation();
|
|
121
|
-
for (const {
|
|
142
|
+
for (const { animations: clips, names, indices } of selections.values()) {
|
|
122
143
|
const player = new EntityAnimationPlayer();
|
|
123
|
-
player.
|
|
124
|
-
|
|
144
|
+
player.playAnimations(
|
|
145
|
+
names.map((name) => this.getLayerGroup(name)),
|
|
146
|
+
clips,
|
|
147
|
+
{ ...options, weights: indices.map((index) => weights[index]) },
|
|
148
|
+
this.partPoses
|
|
149
|
+
);
|
|
150
|
+
this.animationPlayers.push({ player, indices });
|
|
125
151
|
}
|
|
126
152
|
this.notifyDirty();
|
|
127
153
|
}
|
|
154
|
+
/** Changes weights in active clip order, notifying the scene without restarting the shared clock. Has no effect without an animation. */
|
|
155
|
+
setAnimationWeights(weights) {
|
|
156
|
+
if (!this.animationPlayers.length) return;
|
|
157
|
+
const values = validateAnimationWeights(weights, this.activeAnimations.length);
|
|
158
|
+
for (const { player, indices } of this.animationPlayers) player.setWeights(indices.map((index) => values[index]));
|
|
159
|
+
this.notifyDirty();
|
|
160
|
+
}
|
|
128
161
|
/** Stops all clips and restores the poses from before playback. */
|
|
129
162
|
stopAnimation() {
|
|
130
163
|
const players = this.animationPlayers.splice(0);
|
|
131
|
-
for (const player of players) player.stop();
|
|
164
|
+
for (const { player } of players) player.stop();
|
|
132
165
|
if (players.length) this.notifyDirty();
|
|
133
166
|
}
|
|
134
167
|
/** Poses the object at an explicit time in seconds. Has no effect without an animation. */
|
|
135
168
|
setAnimationTime(seconds) {
|
|
136
|
-
for (const player of this.animationPlayers) player.setTime(seconds);
|
|
169
|
+
for (const { player } of this.animationPlayers) player.setTime(seconds);
|
|
137
170
|
if (this.animationPlayers.length) this.notifyDirty();
|
|
138
171
|
}
|
|
139
172
|
/** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */
|
|
140
173
|
advanceAnimation(deltaSeconds) {
|
|
141
|
-
for (const player of this.animationPlayers) player.advance(deltaSeconds);
|
|
174
|
+
for (const { player } of this.animationPlayers) player.advance(deltaSeconds);
|
|
142
175
|
if (this.animationPlayers.length) this.notifyDirty();
|
|
143
176
|
}
|
|
144
177
|
//</editor-fold>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/entity/scene/EntityObject.ts"],"sourcesContent":["import { SceneObject } from \"../../renderer/SceneObject\";\nimport { SceneObjectOptions } from \"../../renderer/SceneObjectOptions\";\nimport { Caching } from \"../../cache/Caching\";\nimport { merge } from \"../../util/_internal/merge\";\nimport { Color, Object3D } from \"three\";\nimport type { BufferGeometry, ColorRepresentation, Material, Mesh, MeshBasicMaterial } from \"three\";\nimport { Ticker } from \"../../Ticker\";\nimport { addWireframeToMesh } from \"../../util/model\";\nimport { ModelTextures } from \"../../assets/ModelTextures\";\nimport { AssetKey, isAssetKey } from \"../../assets/AssetKey\";\nimport { ExtractableImageData } from \"../../ExtractableImageData\";\nimport { Materials } from \"../../Materials\";\nimport { MinecraftCubeTexture } from \"../../MinecraftCubeTexture\";\nimport { CUBE_FACES, CubeFace } from \"../../CubeFace\";\nimport { EntityLayer, EntityModel, EntityModelPart } from \"../EntityModel\";\nimport type { DoubleArray } from \"../../model/Model\";\nimport type { Maybe } from \"../../util/util\";\nimport { isMesh } from \"../../util/three\";\nimport type { EntityAnimation } from \"../EntityAnimation\";\nimport { EntityAnimationOptions, EntityAnimationPlayer } from \"./EntityAnimationPlayer\";\n\n/** Renders selected entity layers as named part groups. Create it through {@link MineRenderScene.addEntity}. */\nexport class EntityObject extends SceneObject {\n\n public readonly isEntityObject: true = true;\n\n public static readonly DEFAULT_OPTIONS: EntityObjectOptions = merge({}, SceneObject.DEFAULT_OPTIONS);\n public readonly options: EntityObjectOptions;\n\n private meshesCreated: boolean = false;\n private readonly geometries = new Set<BufferGeometry>();\n private readonly disposeWireframes: (() => void)[] = [];\n /** Scrolling materials are owned: their texture offset follows this entity's age. */\n private readonly scrollMaterials: { material: Material, offset: { set(x: number, y: number): unknown }, speed: [number, number] }[] = [];\n private scrollTicker: Maybe<number>;\n /** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */\n public age: number = 0;\n private readonly animationPlayers: EntityAnimationPlayer[] = [];\n private readonly partPoses = new Map<Object3D, EntityModelPart[\"pose\"]>();\n\n constructor(readonly entity: EntityModel, options?: Partial<EntityObjectOptions>) {\n super();\n this.options = merge({}, EntityObject.DEFAULT_OPTIONS, options ?? {});\n this.addEventListener(\"added\", () => this.updateScrollSubscription());\n this.addEventListener(\"removed\", () => this.updateScrollSubscription());\n }\n\n /** An optional shared material replaces texture loading for every selected draw; its owner retains disposal. */\n async init(material?: Material): Promise<void> {\n this.createMeshes();\n if (material) {\n this.clearScrollMaterials();\n this.iterateAllMeshes(mesh => { mesh.material = material; });\n this.notifyDirty();\n } else await this.applyTextures();\n }\n\n dispose() {\n super.dispose();\n }\n\n public disposeAndRemoveAllChildren() {\n this.clearScrollMaterials();\n for (const geometry of this.geometries) geometry.dispose();\n this.geometries.clear();\n for (const dispose of this.disposeWireframes.splice(0)) dispose();\n // The animated part groups are removed with the children.\n for (const player of this.animationPlayers.splice(0)) player.clear();\n this.partPoses.clear();\n super.disposeAndRemoveAllChildren();\n }\n\n private clearScrollMaterials() {\n Ticker.remove(this.scrollTicker);\n this.scrollTicker = undefined;\n for (const { material } of this.scrollMaterials.splice(0)) {\n (material as { map?: { dispose(): void } }).map?.dispose();\n material.dispose();\n }\n }\n\n private updateScrollSubscription() {\n if (this.parent && this.scrollMaterials.length) {\n if (this.scrollTicker === undefined) {\n this.scrollTicker = Ticker.add(() => {\n this.age++;\n this.updateScroll();\n });\n }\n } else {\n Ticker.remove(this.scrollTicker);\n this.scrollTicker = undefined;\n }\n }\n\n /** Applies the entity age to the scrolling materials; the ticker calls this 20 times per second. */\n private updateScroll() {\n for (const { offset, speed } of this.scrollMaterials) {\n // Texture V points up here and down in vanilla.\n offset.set((this.age * speed[0]) % 1, 0 - (this.age * speed[1]) % 1);\n }\n this.notifyDirty();\n }\n\n //<editor-fold desc=\"ANIMATION\">\n\n /** The first active clip, until playback is stopped or the object is disposed. */\n public get animation(): Maybe<EntityAnimation> {\n return this.animationPlayers[0]?.animation;\n }\n\n /** Clips playing together, each targeting a separate geometry layer. */\n public get activeAnimations(): readonly EntityAnimation[] {\n return this.animationPlayers.map(player => player.animation!);\n }\n\n /** Seconds since the animation started, before looping. */\n public get animationTime(): number {\n return this.animationPlayers[0]?.time ?? 0;\n }\n\n /**\n * Plays a clip from {@link Entities.getAnimations}, replacing all active clips.\n * Offsets apply to the baked pose in the clip's layer (`main` by default) and its repeated draws.\n * A `main` clip also poses every selected layer without a clip of its own.\n * The object owns no clock: call {@link advanceAnimation} per frame, or {@link setAnimationTime}.\n */\n public playAnimation(animation: EntityAnimation, options?: EntityAnimationOptions): void {\n this.playAnimations([animation], options);\n }\n\n /** Plays clips with a shared clock and no blending. Selected layers without their own clip follow `main`. */\n public playAnimations(animations: readonly EntityAnimation[], options?: EntityAnimationOptions): void {\n const targets = new Set<string>();\n const selections = animations.map(animation => {\n const layer = animation.layer ?? \"main\";\n if (targets.has(layer)) throw new Error(`Multiple animations target layer \"${layer}\"`);\n targets.add(layer);\n const names = Object.keys(this.entityLayers).filter(name => name.split(\"#\")[0] === layer);\n if (!names.length) throw new Error(`Entity ${this.entity.id} has no selected animation layer \"${layer}\"`);\n return { animation, names };\n });\n const main = selections.find(({ animation }) => (animation.layer ?? \"main\") === \"main\");\n if (main) main.names.push(...Object.keys(this.entityLayers).filter(name => !targets.has(name.split(\"#\")[0])));\n this.createMeshes();\n this.stopAnimation();\n for (const { animation, names } of selections) {\n const player = new EntityAnimationPlayer();\n player.play(names.map(name => this.getLayerGroup(name)!), animation, options, this.partPoses);\n this.animationPlayers.push(player);\n }\n this.notifyDirty();\n }\n\n /** Stops all clips and restores the poses from before playback. */\n public stopAnimation(): void {\n const players = this.animationPlayers.splice(0);\n for (const player of players) player.stop();\n if (players.length) this.notifyDirty();\n }\n\n /** Poses the object at an explicit time in seconds. Has no effect without an animation. */\n public setAnimationTime(seconds: number): void {\n for (const player of this.animationPlayers) player.setTime(seconds);\n if (this.animationPlayers.length) this.notifyDirty();\n }\n\n /** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */\n public advanceAnimation(deltaSeconds: number): void {\n for (const player of this.animationPlayers) player.advance(deltaSeconds);\n if (this.animationPlayers.length) this.notifyDirty();\n }\n\n //</editor-fold>\n\n /** Finds a selected draw by its layer key, such as `main` or `main#2`, or returns `undefined`. */\n public getLayerGroup(name: string): Maybe<Object3D> {\n return super.getGroupByName(`layer:${name}`);\n }\n\n /** Finds a part name without `group:`. Supply `layerName` to restrict the search to one draw. */\n public getGroupByName(name: string, layerName?: string): Maybe<Object3D> {\n return layerName === undefined ? super.getGroupByName(name)\n : this.getLayerGroup(layerName)?.getObjectByName(`group:${name}`);\n }\n\n /** Finds a mesh name without `mesh:`. Supply `layerName` to restrict the search to one draw. */\n public getMeshByName(name: string, layerName?: string): Maybe<Mesh> {\n return layerName === undefined ? super.getMeshByName(name)\n : this.getLayerGroup(layerName)?.getObjectByName(`mesh:${name}`) as Maybe<Mesh>;\n }\n\n private get entityLayers(): Record<string, EntityLayer> {\n return this.entity.layers ?? { main: this.entity };\n }\n\n private getTextureKey(layer: EntityLayer): AssetKey {\n if (layer.texture) return layer.texture;\n const key = layer.key;\n return new AssetKey(\n key.namespace,\n isAssetKey(key) ? key.getFullPath() : key.path,\n \"textures\",\n \"entity\",\n \"assets\",\n \".png\"\n );\n }\n\n protected async loadTextures(layer: EntityLayer = this.entity): Promise<Maybe<ExtractableImageData>> {\n return ModelTextures.get(this.getTextureKey(layer));\n }\n\n protected createMeshes(force: boolean = false) {\n if (this.meshesCreated && !force) return;\n\n const modelRoot = new Object3D();\n let transformNode = modelRoot;\n // Keep Minecraft's model coordinates separate from caller placement and scale.\n const transform = this.options.flip === undefined ? this.entity.transform : undefined;\n if (transform) {\n // One position, rotation and scale cannot express nonuniform scale followed by rotation.\n // Nested nodes preserve each operation and avoid manual matrices, which leave bounds stale.\n for (const [index, op] of transform.entries()) {\n if (index > 0) {\n const child = new Object3D();\n transformNode.add(child);\n transformNode = child;\n }\n if (\"scale\" in op) transformNode.scale.set(...op.scale);\n else if (\"translate\" in op) transformNode.position.set(...op.translate);\n else transformNode.rotation.set(...op.rotate, \"ZYX\");\n }\n } else if (this.options.flip ?? true) {\n modelRoot.scale.set(-1, -1, 1);\n }\n this.add(modelRoot);\n Object.entries(this.entityLayers).forEach(([name, layer], index) => {\n const group = this.createGroup(`layer:${name}`);\n transformNode.add(group);\n const inward = !Materials.entityModeCulls(layer.render ?? layer.layer.render);\n this.createPart(\"root\", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index, inward, this.options.faces?.[name]);\n });\n this.meshesCreated = true;\n }\n\n private createPart(name: string, part: EntityModelPart, parent: Object3D, textureSize: DoubleArray, material: Material, renderOrder: number, inward: boolean = true, faces?: CubeFace[]) {\n const anchor = this.createGroup(name);\n anchor.position.fromArray(part.pose.offset);\n anchor.rotation.set(...part.pose.rotation, \"ZYX\");\n anchor.scale.fromArray(part.pose.scale ?? [1, 1, 1]);\n this.partPoses.set(anchor, part.pose);\n parent.add(anchor);\n const size = part.texture ?? textureSize;\n\n for (const cube of part.cubes) {\n const [width, height, depth] = cube.size;\n const [growX, growY, growZ] = cube.grow ?? [0, 0, 0];\n const texture = new MinecraftCubeTexture(...cube.uv, ...size);\n const uv = size[0] === 0 || size[1] === 0 ? new Array<number>(48).fill(0) : texture.toUvArray(width, height, depth, cube.mirror);\n const geometry = this._getBoxGeometryForDimensionsAndUv(\n width + growX * 2, height + growY * 2, depth + growZ * 2, uv\n ).clone();\n this.geometries.add(geometry);\n geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);\n if (faces) {\n geometry.setIndex(Array.from(geometry.getIndex()!.array).filter((_, index) => faces.includes(CUBE_FACES[Math.floor(index / 6)])));\n geometry.clearGroups();\n }\n // Vanilla draws most entity render types without backface culling, e.g. chicken legs are only painted on faces seen from inside.\n // Zero-thickness cubes keep one face per side, as their coplanar faces would z-fight.\n if (inward && Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {\n const index = Array.from(geometry.getIndex()!.array);\n geometry.setIndex(index.concat(index.slice().reverse()));\n }\n const mesh = this.createMesh(name, geometry, material);\n mesh.renderOrder = renderOrder;\n anchor.add(mesh);\n if (this.options.wireframe) this.disposeWireframes.push(addWireframeToMesh(geometry, mesh));\n }\n for (const [childName, child] of Object.entries(part.children)) {\n this.createPart(childName, child, anchor, size, material, renderOrder, inward, faces);\n }\n }\n\n protected async applyTextures() {\n this.clearScrollMaterials();\n const results = await Promise.allSettled(Object.entries(this.entityLayers).map(async ([name, layer]) => {\n const mode = layer.render ?? layer.layer.render ?? \"cutout\";\n const tint = layer.tint === undefined ? undefined : this.options.tints?.[layer.tint];\n const scroll = Materials.entityModeScroll(mode);\n const assetKeyStr = this.getTextureKey(layer).serialize();\n const keyStr = `entity:${ mode }:${ tint === undefined ? \"\" : new Color(tint).getHexString() }:${ assetKeyStr }`;\n let mat = scroll ? undefined : Caching.materialCache.getIfPresent(keyStr);\n if (!mat) {\n const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);\n const imageData = await this.loadTextures(layer);\n if (!imageData) return;\n const canvas = (imageData.data as CanvasRenderingContext2D).canvas;\n const createMaterial = () => Materials.createEntityCanvasMaterial(canvas, mode, tint);\n // A cache clear during decoding must not restore an older source's material.\n // Scrolling materials stay out of the cache, as their texture offset belongs to this entity.\n mat = !scroll && cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset\n ? Caching.materialCache.get(keyStr, createMaterial)\n : createMaterial();\n if (scroll) {\n this.scrollMaterials.push({ material: mat!, offset: (mat as MeshBasicMaterial).map!.offset, speed: scroll });\n }\n }\n this.getLayerGroup(name)?.traverse(object => {\n if (isMesh(object)) object.material = mat!;\n });\n }));\n if (!this.children.length) {\n // Disposed while the textures were loading: nothing is left to scroll.\n this.clearScrollMaterials();\n } else if (this.scrollMaterials.length) {\n this.updateScroll();\n }\n this.updateScrollSubscription();\n this.notifyDirty();\n const failure = results.find(result => result.status === \"rejected\");\n if (failure?.status === \"rejected\") throw failure.reason;\n }\n\n\n}\n\n/** Render settings passed to `scene.addEntity(entity, options)` or the EntityObject constructor. */\nexport interface EntityObjectOptions extends SceneObjectOptions {\n /**\n * `true` applies only vanilla's entity flip, scale (-1, -1, 1); `false` keeps raw model space.\n * By default the model's dataset transform is used, or the flip for models without one.\n */\n flip?: boolean;\n /** Colours for the dataset's tint labels, e.g. `{ wool_color: 0xf9801d }`; a pass whose label is absent stays untinted. */\n tints?: Record<string, ColorRepresentation>;\n /** Cube faces by layer key; omitted layers draw all six faces. */\n faces?: Record<string, CubeFace[]>;\n}\n\nexport function isEntityObject(obj: any): obj is EntityObject {\n return (<EntityObject>obj).isEntityObject;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/entity/scene/EntityObject.ts"],"sourcesContent":["import { SceneObject } from \"../../renderer/SceneObject\";\nimport { SceneObjectOptions } from \"../../renderer/SceneObjectOptions\";\nimport { Caching } from \"../../cache/Caching\";\nimport { merge } from \"../../util/_internal/merge\";\nimport { Color, Object3D } from \"three\";\nimport type { BufferGeometry, ColorRepresentation, Material, Mesh, MeshBasicMaterial } from \"three\";\nimport { Ticker } from \"../../Ticker\";\nimport { addWireframeToMesh } from \"../../util/model\";\nimport { ModelTextures } from \"../../assets/ModelTextures\";\nimport { AssetKey, isAssetKey } from \"../../assets/AssetKey\";\nimport { ExtractableImageData } from \"../../ExtractableImageData\";\nimport { Materials } from \"../../Materials\";\nimport { MinecraftCubeTexture } from \"../../MinecraftCubeTexture\";\nimport { CUBE_FACES, CubeFace } from \"../../CubeFace\";\nimport { EntityLayer, EntityModel, EntityModelPart } from \"../EntityModel\";\nimport type { DoubleArray } from \"../../model/Model\";\nimport type { Maybe } from \"../../util/util\";\nimport { isMesh } from \"../../util/three\";\nimport type { EntityAnimation } from \"../EntityAnimation\";\nimport { EntityAnimationOptions, EntityAnimationPlayer, validateAnimationWeights } from \"./EntityAnimationPlayer\";\n\n/** Renders selected entity layers as named part groups. Create it through {@link MineRenderScene.addEntity}. */\nexport class EntityObject extends SceneObject {\n\n public readonly isEntityObject: true = true;\n\n public static readonly DEFAULT_OPTIONS: EntityObjectOptions = merge({}, SceneObject.DEFAULT_OPTIONS);\n public readonly options: EntityObjectOptions;\n\n private meshesCreated: boolean = false;\n private readonly geometries = new Set<BufferGeometry>();\n private readonly disposeWireframes: (() => void)[] = [];\n /** Scrolling materials are owned: their texture offset follows this entity's age. */\n private readonly scrollMaterials: { material: Material, offset: { set(x: number, y: number): unknown }, speed: [number, number] }[] = [];\n private scrollTicker: Maybe<number>;\n /** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */\n public age: number = 0;\n private readonly animationPlayers: { player: EntityAnimationPlayer, indices: number[] }[] = [];\n private readonly partPoses = new Map<Object3D, EntityModelPart[\"pose\"]>();\n\n constructor(readonly entity: EntityModel, options?: Partial<EntityObjectOptions>) {\n super();\n this.options = merge({}, EntityObject.DEFAULT_OPTIONS, options ?? {});\n this.addEventListener(\"added\", () => this.updateScrollSubscription());\n this.addEventListener(\"removed\", () => this.updateScrollSubscription());\n }\n\n /** An optional shared material replaces texture loading for every selected draw; its owner retains disposal. */\n async init(material?: Material): Promise<void> {\n this.createMeshes();\n if (material) {\n this.clearScrollMaterials();\n this.iterateAllMeshes(mesh => { mesh.material = material; });\n this.notifyDirty();\n } else await this.applyTextures();\n }\n\n dispose() {\n super.dispose();\n }\n\n public disposeAndRemoveAllChildren() {\n this.clearScrollMaterials();\n for (const geometry of this.geometries) geometry.dispose();\n this.geometries.clear();\n for (const dispose of this.disposeWireframes.splice(0)) dispose();\n // The animated part groups are removed with the children.\n for (const { player } of this.animationPlayers.splice(0)) player.clear();\n this.partPoses.clear();\n super.disposeAndRemoveAllChildren();\n }\n\n private clearScrollMaterials() {\n Ticker.remove(this.scrollTicker);\n this.scrollTicker = undefined;\n for (const { material } of this.scrollMaterials.splice(0)) {\n (material as { map?: { dispose(): void } }).map?.dispose();\n material.dispose();\n }\n }\n\n private updateScrollSubscription() {\n if (this.parent && this.scrollMaterials.length) {\n if (this.scrollTicker === undefined) {\n this.scrollTicker = Ticker.add(() => {\n this.age++;\n this.updateScroll();\n });\n }\n } else {\n Ticker.remove(this.scrollTicker);\n this.scrollTicker = undefined;\n }\n }\n\n /** Applies the entity age to the scrolling materials; the ticker calls this 20 times per second. */\n private updateScroll() {\n for (const { offset, speed } of this.scrollMaterials) {\n // Texture V points up here and down in vanilla.\n offset.set((this.age * speed[0]) % 1, 0 - (this.age * speed[1]) % 1);\n }\n this.notifyDirty();\n }\n\n //<editor-fold desc=\"ANIMATION\">\n\n /** The first active clip, until playback is stopped or the object is disposed. */\n public get animation(): Maybe<EntityAnimation> {\n return this.animationPlayers[0]?.player.animation;\n }\n\n /** Clips playing together, in the order passed to {@link playAnimations}. */\n public get activeAnimations(): readonly EntityAnimation[] {\n const animations: EntityAnimation[] = [];\n for (const { player, indices } of this.animationPlayers) {\n player.animations.forEach((animation, i) => { animations[indices[i]] = animation; });\n }\n return animations;\n }\n\n /** Weights of the active clips, in the same order as {@link activeAnimations}. */\n public get animationWeights(): readonly number[] {\n const weights: number[] = [];\n for (const { player, indices } of this.animationPlayers) {\n player.weights.forEach((weight, i) => { weights[indices[i]] = weight; });\n }\n return weights;\n }\n\n /** Seconds since the animation started, before looping. */\n public get animationTime(): number {\n return this.animationPlayers[0]?.player.time ?? 0;\n }\n\n /**\n * Plays a clip from {@link Entities.getAnimations}, replacing all active clips.\n * Offsets apply to the baked pose in the clip's layer (`main` by default) and its repeated draws.\n * A `main` clip also poses every selected layer without a clip of its own.\n * The object owns no clock: call {@link advanceAnimation} per frame, or {@link setAnimationTime}.\n */\n public playAnimation(animation: EntityAnimation, options?: EntityAnimationOptions): void {\n this.playAnimations([animation], options);\n }\n\n /**\n * Plays clips with a shared clock, adding their weighted offsets within each geometry layer.\n * Weights default to 1 and are not normalized. Selected layers without their own clip follow `main`.\n */\n public playAnimations(animations: readonly EntityAnimation[], options?: EntityAnimationOptions): void {\n const weights = validateAnimationWeights(options?.weights ?? animations.map(() => 1), animations.length);\n const selections = new Map<string, { animations: EntityAnimation[], names: string[], indices: number[] }>();\n animations.forEach((animation, index) => {\n const layer = animation.layer ?? \"main\";\n const names = Object.keys(this.entityLayers).filter(name => name.split(\"#\")[0] === layer);\n if (!names.length) throw new Error(`Entity ${this.entity.id} has no selected animation layer \"${layer}\"`);\n let selection = selections.get(layer);\n if (!selection) selections.set(layer, selection = { animations: [], names, indices: [] });\n selection.animations.push(animation);\n selection.indices.push(index);\n });\n const main = selections.get(\"main\");\n if (main) main.names.push(...Object.keys(this.entityLayers).filter(name => !selections.has(name.split(\"#\")[0])));\n this.createMeshes();\n this.stopAnimation();\n for (const { animations: clips, names, indices } of selections.values()) {\n const player = new EntityAnimationPlayer();\n player.playAnimations(names.map(name => this.getLayerGroup(name)!), clips,\n { ...options, weights: indices.map(index => weights[index]) }, this.partPoses);\n this.animationPlayers.push({ player, indices });\n }\n this.notifyDirty();\n }\n\n /** Changes weights in active clip order, notifying the scene without restarting the shared clock. Has no effect without an animation. */\n public setAnimationWeights(weights: readonly number[]): void {\n if (!this.animationPlayers.length) return;\n const values = validateAnimationWeights(weights, this.activeAnimations.length);\n for (const { player, indices } of this.animationPlayers) player.setWeights(indices.map(index => values[index]));\n this.notifyDirty();\n }\n\n /** Stops all clips and restores the poses from before playback. */\n public stopAnimation(): void {\n const players = this.animationPlayers.splice(0);\n for (const { player } of players) player.stop();\n if (players.length) this.notifyDirty();\n }\n\n /** Poses the object at an explicit time in seconds. Has no effect without an animation. */\n public setAnimationTime(seconds: number): void {\n for (const { player } of this.animationPlayers) player.setTime(seconds);\n if (this.animationPlayers.length) this.notifyDirty();\n }\n\n /** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */\n public advanceAnimation(deltaSeconds: number): void {\n for (const { player } of this.animationPlayers) player.advance(deltaSeconds);\n if (this.animationPlayers.length) this.notifyDirty();\n }\n\n //</editor-fold>\n\n /** Finds a selected draw by its layer key, such as `main` or `main#2`, or returns `undefined`. */\n public getLayerGroup(name: string): Maybe<Object3D> {\n return super.getGroupByName(`layer:${name}`);\n }\n\n /** Finds a part name without `group:`. Supply `layerName` to restrict the search to one draw. */\n public getGroupByName(name: string, layerName?: string): Maybe<Object3D> {\n return layerName === undefined ? super.getGroupByName(name)\n : this.getLayerGroup(layerName)?.getObjectByName(`group:${name}`);\n }\n\n /** Finds a mesh name without `mesh:`. Supply `layerName` to restrict the search to one draw. */\n public getMeshByName(name: string, layerName?: string): Maybe<Mesh> {\n return layerName === undefined ? super.getMeshByName(name)\n : this.getLayerGroup(layerName)?.getObjectByName(`mesh:${name}`) as Maybe<Mesh>;\n }\n\n private get entityLayers(): Record<string, EntityLayer> {\n return this.entity.layers ?? { main: this.entity };\n }\n\n private getTextureKey(layer: EntityLayer): AssetKey {\n if (layer.texture) return layer.texture;\n const key = layer.key;\n return new AssetKey(\n key.namespace,\n isAssetKey(key) ? key.getFullPath() : key.path,\n \"textures\",\n \"entity\",\n \"assets\",\n \".png\"\n );\n }\n\n protected async loadTextures(layer: EntityLayer = this.entity): Promise<Maybe<ExtractableImageData>> {\n return ModelTextures.get(this.getTextureKey(layer));\n }\n\n protected createMeshes(force: boolean = false) {\n if (this.meshesCreated && !force) return;\n\n const modelRoot = new Object3D();\n let transformNode = modelRoot;\n // Keep Minecraft's model coordinates separate from caller placement and scale.\n const transform = this.options.flip === undefined ? this.entity.transform : undefined;\n if (transform) {\n // One position, rotation and scale cannot express nonuniform scale followed by rotation.\n // Nested nodes preserve each operation and avoid manual matrices, which leave bounds stale.\n for (const [index, op] of transform.entries()) {\n if (index > 0) {\n const child = new Object3D();\n transformNode.add(child);\n transformNode = child;\n }\n if (\"scale\" in op) transformNode.scale.set(...op.scale);\n else if (\"translate\" in op) transformNode.position.set(...op.translate);\n else transformNode.rotation.set(...op.rotate, \"ZYX\");\n }\n } else if (this.options.flip ?? true) {\n modelRoot.scale.set(-1, -1, 1);\n }\n this.add(modelRoot);\n Object.entries(this.entityLayers).forEach(([name, layer], index) => {\n const group = this.createGroup(`layer:${name}`);\n transformNode.add(group);\n const inward = !Materials.entityModeCulls(layer.render ?? layer.layer.render);\n this.createPart(\"root\", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index, inward, this.options.faces?.[name]);\n });\n this.meshesCreated = true;\n }\n\n private createPart(name: string, part: EntityModelPart, parent: Object3D, textureSize: DoubleArray, material: Material, renderOrder: number, inward: boolean = true, faces?: CubeFace[]) {\n const anchor = this.createGroup(name);\n anchor.position.fromArray(part.pose.offset);\n anchor.rotation.set(...part.pose.rotation, \"ZYX\");\n anchor.scale.fromArray(part.pose.scale ?? [1, 1, 1]);\n this.partPoses.set(anchor, part.pose);\n parent.add(anchor);\n const size = part.texture ?? textureSize;\n\n for (const cube of part.cubes) {\n const [width, height, depth] = cube.size;\n const [growX, growY, growZ] = cube.grow ?? [0, 0, 0];\n const texture = new MinecraftCubeTexture(...cube.uv, ...size);\n const uv = size[0] === 0 || size[1] === 0 ? new Array<number>(48).fill(0) : texture.toUvArray(width, height, depth, cube.mirror);\n const geometry = this._getBoxGeometryForDimensionsAndUv(\n width + growX * 2, height + growY * 2, depth + growZ * 2, uv\n ).clone();\n this.geometries.add(geometry);\n geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);\n if (faces) {\n geometry.setIndex(Array.from(geometry.getIndex()!.array).filter((_, index) => faces.includes(CUBE_FACES[Math.floor(index / 6)])));\n geometry.clearGroups();\n }\n // Vanilla draws most entity render types without backface culling, e.g. chicken legs are only painted on faces seen from inside.\n // Zero-thickness cubes keep one face per side, as their coplanar faces would z-fight.\n if (inward && Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {\n const index = Array.from(geometry.getIndex()!.array);\n geometry.setIndex(index.concat(index.slice().reverse()));\n }\n const mesh = this.createMesh(name, geometry, material);\n mesh.renderOrder = renderOrder;\n anchor.add(mesh);\n if (this.options.wireframe) this.disposeWireframes.push(addWireframeToMesh(geometry, mesh));\n }\n for (const [childName, child] of Object.entries(part.children)) {\n this.createPart(childName, child, anchor, size, material, renderOrder, inward, faces);\n }\n }\n\n protected async applyTextures() {\n this.clearScrollMaterials();\n const results = await Promise.allSettled(Object.entries(this.entityLayers).map(async ([name, layer]) => {\n const mode = layer.render ?? layer.layer.render ?? \"cutout\";\n const tint = layer.tint === undefined ? undefined : this.options.tints?.[layer.tint];\n const scroll = Materials.entityModeScroll(mode);\n const assetKeyStr = this.getTextureKey(layer).serialize();\n const keyStr = `entity:${ mode }:${ tint === undefined ? \"\" : new Color(tint).getHexString() }:${ assetKeyStr }`;\n let mat = scroll ? undefined : Caching.materialCache.getIfPresent(keyStr);\n if (!mat) {\n const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);\n const imageData = await this.loadTextures(layer);\n if (!imageData) return;\n const canvas = (imageData.data as CanvasRenderingContext2D).canvas;\n const createMaterial = () => Materials.createEntityCanvasMaterial(canvas, mode, tint);\n // A cache clear during decoding must not restore an older source's material.\n // Scrolling materials stay out of the cache, as their texture offset belongs to this entity.\n mat = !scroll && cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset\n ? Caching.materialCache.get(keyStr, createMaterial)\n : createMaterial();\n if (scroll) {\n this.scrollMaterials.push({ material: mat!, offset: (mat as MeshBasicMaterial).map!.offset, speed: scroll });\n }\n }\n this.getLayerGroup(name)?.traverse(object => {\n if (isMesh(object)) object.material = mat!;\n });\n }));\n if (!this.children.length) {\n // Disposed while the textures were loading: nothing is left to scroll.\n this.clearScrollMaterials();\n } else if (this.scrollMaterials.length) {\n this.updateScroll();\n }\n this.updateScrollSubscription();\n this.notifyDirty();\n const failure = results.find(result => result.status === \"rejected\");\n if (failure?.status === \"rejected\") throw failure.reason;\n }\n\n\n}\n\n/** Render settings passed to `scene.addEntity(entity, options)` or the EntityObject constructor. */\nexport interface EntityObjectOptions extends SceneObjectOptions {\n /**\n * `true` applies only vanilla's entity flip, scale (-1, -1, 1); `false` keeps raw model space.\n * By default the model's dataset transform is used, or the flip for models without one.\n */\n flip?: boolean;\n /** Colours for the dataset's tint labels, e.g. `{ wool_color: 0xf9801d }`; a pass whose label is absent stays untinted. */\n tints?: Record<string, ColorRepresentation>;\n /** Cube faces by layer key; omitted layers draw all six faces. */\n faces?: Record<string, CubeFace[]>;\n}\n\nexport function isEntityObject(obj: any): obj is EntityObject {\n return (<EntityObject>obj).isEntityObject;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/env/browser/BrowserCache.ts
|
|
2
2
|
import { PersistentCache } from "../../cache/PersistentCache.mjs";
|
|
3
|
-
import {
|
|
4
|
-
var
|
|
3
|
+
import { logger } from "../../util/log.mjs";
|
|
4
|
+
var log = logger("BrowserCache");
|
|
5
5
|
var BrowserCache = class extends PersistentCache {
|
|
6
6
|
constructor(backing) {
|
|
7
7
|
super(backing);
|
|
@@ -12,7 +12,7 @@ var BrowserCache = class extends PersistentCache {
|
|
|
12
12
|
return true;
|
|
13
13
|
} catch (error) {
|
|
14
14
|
this.memory = /* @__PURE__ */ new Map();
|
|
15
|
-
|
|
15
|
+
log.warn("Could not open browser storage; using an in-memory store", error);
|
|
16
16
|
return false;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/env/browser/BrowserCache.ts"],"sourcesContent":["import { PersistentCache } from \"../../cache/PersistentCache\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../../src/env/browser/BrowserCache.ts"],"sourcesContent":["import { PersistentCache } from \"../../cache/PersistentCache\";\nimport { logger } from \"../../util/log\";\n\nconst log = logger(\"BrowserCache\");\n\n/**\n * {@link PersistentCache} backed by localforage (IndexedDB / WebSQL / localStorage).\n * Uses an in-memory store when browser storage cannot be opened.\n */\nexport class BrowserCache extends PersistentCache<LocalForage> {\n\n private initialized?: Promise<boolean>;\n private memory?: Map<string, unknown>;\n\n constructor(backing: LocalForage) {\n super(backing);\n }\n\n private async initialize(): Promise<boolean> {\n try {\n await this.backing.ready();\n return true;\n } catch (error) {\n this.memory = new Map();\n log.warn(\"Could not open browser storage; using an in-memory store\", error);\n return false;\n }\n }\n\n private async run<T>(operation: () => Promise<T>, fallback: (memory: Map<string, unknown>) => T): Promise<T> {\n if (await (this.initialized ??= this.initialize())) return operation();\n return fallback(this.memory!);\n }\n\n get<T>(key: string): Promise<T> {\n return this.run(() => this.backing.getItem<T>(key), memory => memory.get(key) as T) as Promise<T>;\n }\n\n put<T>(key: string, value: T): Promise<T> {\n return this.run(() => this.backing.setItem<T>(key, value), memory => {\n memory.set(key, value);\n return value;\n });\n }\n\n delete<T>(key: string): Promise<void> {\n return this.run(() => this.backing.removeItem(key), memory => { memory.delete(key); });\n }\n\n clear(): Promise<void> {\n return this.run(() => this.backing.clear(), memory => memory.clear());\n }\n\n length(): Promise<number> {\n return this.run(() => this.backing.length(), memory => memory.size);\n }\n\n keys(): Promise<string[]> {\n return this.run(() => this.backing.keys(), memory => [...memory.keys()]);\n }\n\n forEach<T>(callback: (v: T, k: string) => void): Promise<void> {\n return this.run(() => this.backing.iterate<T, void>((value, key) => {\n callback(value, key);\n }), memory => memory.forEach((value, key) => callback(value as T, key)));\n }\n\n}\n"],"mappings":";AAAA,SAAS,uBAAuB;AAChC,SAAS,cAAc;AAEvB,IAAM,MAAM,OAAO,cAAc;AAM1B,IAAM,eAAN,cAA2B,gBAA6B;AAAA,EAK3D,YAAY,SAAsB;AAC9B,UAAM,OAAO;AAAA,EACjB;AAAA,EAEA,MAAc,aAA+B;AACzC,QAAI;AACA,YAAM,KAAK,QAAQ,MAAM;AACzB,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,WAAK,SAAS,oBAAI,IAAI;AACtB,UAAI,KAAK,4DAA4D,KAAK;AAC1E,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAc,IAAO,WAA6B,UAA2D;AACzG,QAAI,OAAO,KAAK,gBAAL,KAAK,cAAgB,KAAK,WAAW,IAAI,QAAO,UAAU;AACrE,WAAO,SAAS,KAAK,MAAO;AAAA,EAChC;AAAA,EAEA,IAAO,KAAyB;AAC5B,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,QAAW,GAAG,GAAG,YAAU,OAAO,IAAI,GAAG,CAAM;AAAA,EACtF;AAAA,EAEA,IAAO,KAAa,OAAsB;AACtC,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,QAAW,KAAK,KAAK,GAAG,YAAU;AACjE,aAAO,IAAI,KAAK,KAAK;AACrB,aAAO;AAAA,IACX,CAAC;AAAA,EACL;AAAA,EAEA,OAAU,KAA4B;AAClC,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,WAAW,GAAG,GAAG,YAAU;AAAE,aAAO,OAAO,GAAG;AAAA,IAAG,CAAC;AAAA,EACzF;AAAA,EAEA,QAAuB;AACnB,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,MAAM,GAAG,YAAU,OAAO,MAAM,CAAC;AAAA,EACxE;AAAA,EAEA,SAA0B;AACtB,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,OAAO,GAAG,YAAU,OAAO,IAAI;AAAA,EACtE;AAAA,EAEA,OAA0B;AACtB,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,KAAK,GAAG,YAAU,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC;AAAA,EAC3E;AAAA,EAEA,QAAW,UAAoD;AAC3D,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,QAAiB,CAAC,OAAO,QAAQ;AAChE,eAAS,OAAO,GAAG;AAAA,IACvB,CAAC,GAAG,YAAU,OAAO,QAAQ,CAAC,OAAO,QAAQ,SAAS,OAAY,GAAG,CAAC,CAAC;AAAA,EAC3E;AAEJ;","names":[]}
|
|
@@ -196,7 +196,7 @@ function buildSectionGeometry(input) {
|
|
|
196
196
|
const cornerBrightness2 = ambientOcclusion ? new Float32Array(4) : void 0;
|
|
197
197
|
for (const template of templateData) {
|
|
198
198
|
const { quads } = template;
|
|
199
|
-
if (template.positions.length !== quads * 12 || template.normals.length !== quads * 12 || template.uvs.length !== quads * 8 || template.uvBounds.length !== quads * 16 || template.colors.length !== quads * 12 || template.indices.length !== quads * 6 || template.cullFaces.length !== quads || template.biomeTint && template.biomeTint.length !== quads) {
|
|
199
|
+
if (template.positions.length !== quads * 12 || template.normals.length !== quads * 12 || template.uvs.length !== quads * 8 || template.uvBounds.length !== quads * 16 || template.colors.length !== quads * 12 || template.indices.length !== quads * 6 || template.cullFaces.length !== quads || template.shade && template.shade.length !== quads * 4 || template.biomeTint && template.biomeTint.length !== quads) {
|
|
200
200
|
throw new RangeError("Section template arrays do not match its quad count");
|
|
201
201
|
}
|
|
202
202
|
}
|
|
@@ -287,6 +287,7 @@ function buildSectionGeometry(input) {
|
|
|
287
287
|
}
|
|
288
288
|
const positions = new Float32Array(faces * 12), normals = new Float32Array(faces * 12);
|
|
289
289
|
const uvs = new Float32Array(faces * 8), uvBounds = new Float32Array(faces * 16), colors = new Float32Array(faces * 12);
|
|
290
|
+
const shade = new Float32Array(faces * 4).fill(1);
|
|
290
291
|
const outputIndices = new Uint32Array(faces * 6);
|
|
291
292
|
const blockIndices = new Uint16Array(faces);
|
|
292
293
|
let vertex = 0, indexOffset = 0;
|
|
@@ -316,6 +317,7 @@ function buildSectionGeometry(input) {
|
|
|
316
317
|
normals[vertex * 3] = template.normals[source * 3];
|
|
317
318
|
normals[vertex * 3 + 1] = template.normals[source * 3 + 1];
|
|
318
319
|
normals[vertex * 3 + 2] = template.normals[source * 3 + 2];
|
|
320
|
+
shade[vertex] = template.shade?.[source] ?? 1;
|
|
319
321
|
uvs[vertex * 2] = mapU(template.uvs[source * 2]);
|
|
320
322
|
uvs[vertex * 2 + 1] = mapV(template.uvs[source * 2 + 1]);
|
|
321
323
|
uvBounds[vertex * 4] = mapU(template.uvBounds[source * 4]);
|
|
@@ -368,11 +370,11 @@ function buildSectionGeometry(input) {
|
|
|
368
370
|
indexOffset += 6;
|
|
369
371
|
}
|
|
370
372
|
}
|
|
371
|
-
return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices, blockIndices };
|
|
373
|
+
return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, shade, indices: outputIndices, blockIndices };
|
|
372
374
|
});
|
|
373
375
|
}
|
|
374
376
|
function sectionGeometryTransferables(pages) {
|
|
375
|
-
return pages.flatMap((page) => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.indices.buffer, page.blockIndices.buffer]);
|
|
377
|
+
return pages.flatMap((page) => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.shade.buffer, page.indices.buffer, page.blockIndices.buffer]);
|
|
376
378
|
}
|
|
377
379
|
|
|
378
380
|
// src/env/browser/section.worker.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/model/fluid/FluidQuads.ts","../../../../../src/world/_light/AmbientOcclusion.ts","../../../../../src/world/_light/FaceLight.ts","../../../../../src/world/SectionGeometry.ts","../../../../../src/env/browser/section.worker.ts"],"sourcesContent":["import type { DoubleArray, TripleArray } from \"../Model\";\n\nexport type FluidKind = \"water\" | \"lava\";\n\n/** Reads the fluid kind from bits 4 and 5 of a section cell byte. */\nexport function fluidKindOf(byte: number): FluidKind | undefined {\n const kind = byte & 48;\n return kind === 16 ? \"water\" : kind === 32 ? \"lava\" : undefined;\n}\n\n/** A neighboring cell's fluid level and full-cube occlusion state. */\nexport interface FluidSample {\n fluid?: FluidKind;\n level?: number;\n solid?: boolean;\n}\n\n/** Reads cells at integer block offsets relative to the fluid being rendered, with `(0, 0, 0)` as the center. */\nexport type FluidSampler = (x: number, y: number, z: number) => FluidSample;\n\nconst HORIZONTAL = [[0, -1], [0, 1], [-1, 0], [1, 0]] as const;\nconst EPSILON = 0.001;\n\nfunction ownHeight(sample: FluidSample): number {\n const level = sample.level ?? 0;\n return (level === 0 || level >= 8 ? 8 : 8 - level) / 9;\n}\n\n/** Fluid faces as quads centered on the block, four vertices each, in emission order. */\nexport interface FluidQuads {\n positions: number[];\n normals: number[];\n uvs: number[];\n sprites: number[];\n}\n\n/** Builds centered fluid quads with sprite 0 (still) or 1 (flowing). */\nexport function buildFluidQuads(kind: FluidKind, sample: FluidSampler): FluidQuads {\n const positions: number[] = [], normals: number[] = [], uvs: number[] = [], sprites: number[] = [];\n const self = sample(0, 0, 0);\n const height = (x: number, z: number): number => {\n const state = sample(x, 0, z);\n if (state.fluid !== kind) return state.solid ? -1 : 0;\n return sample(x, 1, z).fluid === kind ? 1 : ownHeight(state);\n };\n const selfHeight = height(0, 0);\n const corner = (x: number, z: number): number => {\n if (selfHeight >= 1) return 1;\n const adjacent = [height(x, 0), height(0, z)];\n if (adjacent.some(value => value >= 1)) return 1;\n const values = [selfHeight, ...adjacent];\n if (adjacent.some(value => value > 0)) {\n const diagonal = height(x, z);\n if (diagonal >= 1) return 1;\n values.push(diagonal);\n }\n let sum = 0, weights = 0;\n for (const value of values) {\n if (value < 0) continue;\n const weight = value >= 0.8 ? 10 : 1;\n sum += value * weight;\n weights += weight;\n }\n return sum / weights;\n };\n const heights = [corner(-1, -1), corner(-1, 1), corner(1, 1), corner(1, -1)];\n const above = sample(0, 1, 0), below = sample(0, -1, 0);\n const renderTop = above.fluid !== kind && !(above.solid && Math.min(...heights) >= 1);\n const renderBottom = below.fluid !== kind && !below.solid;\n const bottom = renderBottom ? EPSILON : 0;\n const face = (vertices: TripleArray[], uv: DoubleArray[], normal: TripleArray, material: number) => {\n sprites.push(material);\n for (let i = 0; i < 4; i++) {\n positions.push(...vertices[i].map(value => value * 16 - 8));\n normals.push(...normal);\n uvs.push(uv[i][0], 1 - uv[i][1]);\n }\n };\n\n if (renderTop) {\n for (let i = 0; i < heights.length; i++) heights[i] -= EPSILON;\n let flowX = 0, flowZ = 0;\n for (const [x, z] of HORIZONTAL) {\n const neighbor = sample(x, 0, z);\n if (neighbor.fluid && neighbor.fluid !== kind) continue;\n let difference = 0;\n if (neighbor.fluid === kind) {\n difference = ownHeight(self) - ownHeight(neighbor);\n } else if (!neighbor.solid) {\n const lower = sample(x, -1, z);\n if (lower.fluid === kind) difference = ownHeight(self) - (ownHeight(lower) - 8 / 9);\n }\n flowX += x * difference;\n flowZ += z * difference;\n }\n const flowing = flowX !== 0 || flowZ !== 0;\n let uv: DoubleArray[] = [[0, 0], [0, 1], [1, 1], [1, 0]];\n if (flowing) {\n const angle = Math.atan2(flowZ, flowX) - Math.PI / 2;\n const s = Math.sin(angle) / 4, c = Math.cos(angle) / 4;\n uv = [[0.5 - c - s, 0.5 - c + s], [0.5 - c + s, 0.5 + c + s],\n [0.5 + c + s, 0.5 + c - s], [0.5 + c - s, 0.5 - c - s]];\n }\n face([[0, heights[0], 0], [0, heights[1], 1], [1, heights[2], 1], [1, heights[3], 0]], uv, [0, 1, 0], flowing ? 1 : 0);\n }\n if (renderBottom) {\n face([[0, bottom, 0], [1, bottom, 0], [1, bottom, 1], [0, bottom, 1]],\n [[0, 0], [1, 0], [1, 1], [0, 1]], [0, -1, 0], 0);\n }\n const sides = [\n { x: 0, z: -1, corners: [0, 3], edge: [[0, EPSILON], [1, EPSILON]] },\n { x: 0, z: 1, corners: [2, 1], edge: [[1, 1 - EPSILON], [0, 1 - EPSILON]] },\n { x: -1, z: 0, corners: [1, 0], edge: [[EPSILON, 1], [EPSILON, 0]] },\n { x: 1, z: 0, corners: [3, 2], edge: [[1 - EPSILON, 0], [1 - EPSILON, 1]] }\n ];\n for (const { x, z, corners, edge } of sides) {\n const neighbor = sample(x, 0, z);\n if (neighbor.fluid === kind || neighbor.solid) continue;\n const [h0, h1] = corners.map(index => heights[index]);\n const [[x0, z0], [x1, z1]] = edge;\n face([[x0, h0, z0], [x1, h1, z1], [x1, bottom, z1], [x0, bottom, z0]],\n [[0, (1 - h0) / 2], [0.5, (1 - h1) / 2], [0.5, 0.5], [0, 0.5]], [x, 0, z], 1);\n }\n return { positions, normals, uvs, sprites };\n}\n","const AXIS_STRIDES = [1, 9, 3] as const;\n\n/** Reads the edge and corner blockers around one cell in an 18×18×18 section neighborhood. */\nexport function sectionAmbientOcclusionMask(cells: Uint8Array, center: number): number {\n let mask = 0;\n for (let y = -1; y <= 1; y++) for (let z = -1; z <= 1; z++) for (let x = -1; x <= 1; x++) {\n if (Math.abs(x) + Math.abs(y) + Math.abs(z) < 2) continue;\n if (cells[center + y * 324 + z * 18 + x]) mask |= 1 << ((y + 1) * 9 + (z + 1) * 3 + x + 1);\n }\n return mask;\n}\n\nfunction cornerBrightness(mask: number, center: number, u: number, v: number): number {\n const sideU = (mask >>> (center + u)) & 1;\n const sideV = (mask >>> (center + v)) & 1;\n const corner = sideU && sideV ? 1 : (mask >>> (center + u + v)) & 1;\n return 1 - (sideU + sideV + corner) * 0.2;\n}\n\n/** Writes four linear AO factors for a boundary quad; inset or non-axis-aligned quads remain unchanged. */\nexport function quadAmbientOcclusion(positions: ArrayLike<number>, normals: ArrayLike<number>, quad: number,\n mask: number, output: Float32Array): void {\n output.fill(1);\n if (!mask) return;\n const start = quad * 12;\n let axis = 0;\n if (Math.abs(normals[start + 1]) > Math.abs(normals[start + axis])) axis = 1;\n if (Math.abs(normals[start + 2]) > Math.abs(normals[start + axis])) axis = 2;\n const uAxis = (axis + 1) % 3, vAxis = (axis + 2) % 3;\n if (Math.abs(Math.abs(normals[start + axis]) - 1) > 1e-6 ||\n Math.abs(normals[start + uAxis]) > 1e-6 || Math.abs(normals[start + vAxis]) > 1e-6) return;\n const sign = normals[start + axis] > 0 ? 1 : -1;\n for (let vertex = 0; vertex < 4; vertex++) {\n const offset = start + vertex * 3;\n if (Math.abs(positions[offset + axis] - sign * 8) > 0.0016 ||\n Math.abs(positions[offset + uAxis]) > 8.0016 || Math.abs(positions[offset + vAxis]) > 8.0016) return;\n }\n const center = 13 + sign * AXIS_STRIDES[axis];\n const u = AXIS_STRIDES[uAxis], v = AXIS_STRIDES[vAxis];\n const lowLow = cornerBrightness(mask, center, -u, -v);\n const highLow = cornerBrightness(mask, center, u, -v);\n const lowHigh = cornerBrightness(mask, center, -u, v);\n const highHigh = cornerBrightness(mask, center, u, v);\n for (let vertex = 0; vertex < 4; vertex++) {\n const offset = start + vertex * 3;\n const a = Math.max(0, Math.min(1, (positions[offset + uAxis] + 8) / 16));\n const b = Math.max(0, Math.min(1, (positions[offset + vAxis] + 8) / 16));\n output[vertex] = (lowLow * (1 - a) + highLow * a) * (1 - b) + (lowHigh * (1 - a) + highHigh * a) * b;\n }\n}\n","/** Converts a saved light level to linear brightness; unknown samples retain preview brightness. */\nexport function lightBrightness(level: number, ambient = 0): number {\n if (level === 255) return 1;\n const curve = level / (60 - 3 * level);\n return curve + ambient * (1 - curve);\n}\n\n/** Selects the adjacent light sample for a boundary quad, or the center sample for an inset quad. */\nexport function quadLightIndex(positions: ArrayLike<number>, normals: ArrayLike<number>, quad: number): number {\n const start = quad * 12;\n let axis = 0;\n if (Math.abs(normals[start + 1]) > Math.abs(normals[start + axis])) axis = 1;\n if (Math.abs(normals[start + 2]) > Math.abs(normals[start + axis])) axis = 2;\n const positive = normals[start + axis] > 0;\n const boundary = positive ? 8 : -8;\n for (let vertex = 0; vertex < 4; vertex++) {\n if (Math.abs(positions[start + vertex * 3 + axis] - boundary) > 0.0016) return 0;\n }\n return axis * 2 + (positive ? 1 : 2);\n}\n\n/** Fluids sample the brighter of their own cell and the cell above, or below for bottom faces. */\nexport function fluidLightLevel(center: number, neighbor: number): number {\n return Math.max(center === 255 ? 15 : center, neighbor === 255 ? 15 : neighbor);\n}\n\n/** Offsets for center and face samples in an 18×18×18 section neighborhood. */\nexport const LIGHT_SAMPLE_OFFSETS = [0, 1, -1, 324, -324, 18, -18] as const;\n","import { buildFluidQuads, fluidKindOf } from \"../model/fluid/FluidQuads\";\nimport type { FluidKind, FluidQuads } from \"../model/fluid/FluidQuads\";\nimport { quadAmbientOcclusion, sectionAmbientOcclusionMask } from \"./_light/AmbientOcclusion\";\nimport { fluidLightLevel, LIGHT_SAMPLE_OFFSETS, lightBrightness, quadLightIndex } from \"./_light/FaceLight\";\n\n/** Static model geometry as quads: four vertices per quad, in quad order. */\nexport interface SectionTemplateData {\n quads: number;\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n uvBounds: Float32Array;\n colors: Float32Array;\n indices: Uint16Array;\n cullFaces: Uint8Array;\n biomeTint?: Uint8Array;\n atlas: number;\n layer: number;\n ambientOcclusion?: boolean;\n}\n\n/** The pixel dimensions and animation state of a source atlas. */\nexport interface SectionAtlasSize {\n width: number;\n height: number;\n animated: boolean;\n}\n\n/** One fluid kind's sprite rectangles in atlas pixels and its linear-light vertex tint. */\nexport interface SectionFluidKind {\n atlas: number;\n still: [x: number, y: number, width: number, height: number];\n flow: [x: number, y: number, width: number, height: number];\n tint: [r: number, g: number, b: number];\n}\n\n/** Fluid cells of the section plus a one-cell shell, 18×18×18, x fastest, then z, then y. */\nexport interface SectionFluidInput {\n /** Bit 128 marks a surface rendered elsewhere; the cell still supplies neighbor fluid samples. */\n cells: Uint8Array;\n /** Linear RGB per section cell, indexed by (x + 16z + 256y) * 3. Omission uses the water kind's tint. */\n waterTints?: Float32Array;\n water?: SectionFluidKind;\n lava?: SectionFluidKind;\n}\n\n/** Section placements and their shared templates, ready for geometry building. */\nexport interface SectionGeometryInput {\n count: number;\n indices: Uint16Array;\n templates: Uint16Array;\n cullMasks: Uint8Array;\n /** Linear RGB per placement; three NaN values preserve the template's colors. */\n biomeTints?: Float32Array;\n templateData: SectionTemplateData[];\n atlases: SectionAtlasSize[];\n maxAtlasSize: number;\n fluids?: SectionFluidInput;\n /** Saved brightness levels for an 18×18×18 neighborhood; 255 means unknown/full brightness. */\n light?: Uint8Array;\n /** Minimum brightness for known light levels, from 0 to 1. */\n ambientLight?: number;\n /** Opaque full cubes in an 18×18×18 neighborhood, stored as zero or one. */\n ambientOcclusion?: Uint8Array;\n}\n\n/** Merged quads and source-atlas placements for one atlas page. */\nexport interface SectionGeometryPage {\n layer: number;\n width: number;\n height: number;\n placements: { atlas: number; x: number; y: number }[];\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n uvBounds: Float32Array;\n colors: Float32Array;\n indices: Uint32Array;\n /** Owning section cell for each quad; each quad contributes two consecutive triangles. */\n blockIndices: Uint16Array;\n}\n\n/** Builds section-local geometry from visible quads, with bounded atlas pages per layer. */\nexport function buildSectionGeometry(input: SectionGeometryInput): SectionGeometryPage[] {\n const { count, indices, templates, cullMasks, templateData, atlases, maxAtlasSize, fluids, light, ambientLight, ambientOcclusion, biomeTints } = input;\n if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError(\"Section atlas size must be a positive integer\");\n if (count > indices.length || count > templates.length || count > cullMasks.length) throw new RangeError(\"Section entry count exceeds its arrays\");\n if (biomeTints && biomeTints.length !== count * 3) throw new RangeError(\"Section biome tints must contain RGB for each placement\");\n if (fluids && fluids.cells.length !== 5832) throw new RangeError(\"Section fluid cells must cover an 18×18×18 neighborhood\");\n if (fluids?.waterTints && fluids.waterTints.length !== 4096 * 3) throw new RangeError(\"Section water tints must contain RGB for 4096 cells\");\n if (light && (light.length !== 5832 || light.some(level => level > 15 && level !== 255))) {\n throw new RangeError(\"Section light must cover an 18×18×18 neighborhood with levels from 0 to 15 or 255\");\n }\n if (ambientLight !== undefined && (!Number.isFinite(ambientLight) || ambientLight < 0 || ambientLight > 1)) {\n throw new RangeError(\"Section ambient light must be a number from 0 to 1\");\n }\n if (ambientOcclusion && (ambientOcclusion.length !== 5832 || ambientOcclusion.some(value => value > 1))) {\n throw new RangeError(\"Section ambient occlusion must cover an 18×18×18 neighborhood with zero or one per cell\");\n }\n const cornerBrightness = ambientOcclusion ? new Float32Array(4) : undefined;\n for (const template of templateData) {\n const { quads } = template;\n if (template.positions.length !== quads * 12 || template.normals.length !== quads * 12 ||\n template.uvs.length !== quads * 8 || template.uvBounds.length !== quads * 16 ||\n template.colors.length !== quads * 12 || template.indices.length !== quads * 6 || template.cullFaces.length !== quads ||\n (template.biomeTint && template.biomeTint.length !== quads)) {\n throw new RangeError(\"Section template arrays do not match its quad count\");\n }\n }\n const visible: number[] = [];\n const visibleAtlases = new Map<number, Set<number>>();\n for (let entry = 0; entry < count; entry++) {\n const template = templateData[templates[entry]];\n if (!template.cullFaces.some(direction => !(cullMasks[entry] & direction))) continue;\n visible.push(entry);\n if (!visibleAtlases.has(template.layer)) visibleAtlases.set(template.layer, new Set());\n visibleAtlases.get(template.layer)!.add(template.atlas);\n }\n const pages: {\n layer: number; placements: SectionGeometryPage[\"placements\"]; entries: number[];\n fluids: { quads: FluidQuads; x: number; y: number; z: number; data: SectionFluidKind; tint: ArrayLike<number> }[];\n x: number; y: number; rowHeight: number; width: number; height: number;\n }[] = [];\n const locations = new Map<number, { page: number; x: number; y: number }>();\n for (const [layer, layerAtlases] of [...visibleAtlases].sort(([a], [b]) => a - b)) {\n const firstPage = pages.length;\n for (const atlas of [...layerAtlases].sort((a, b) => Number(atlases[a].animated) - Number(atlases[b].animated) ||\n (atlases[a].animated ? a - b : atlases[b].height - atlases[a].height))) {\n const { width, height, animated } = atlases[atlas];\n if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError(\"Model atlas exceeds the section atlas size limit\");\n let selected = -1;\n for (let i = firstPage; !animated && i < pages.length; i++) {\n const page = pages[i];\n const nextRow = page.x + width > maxAtlasSize;\n if ((nextRow ? page.y + page.rowHeight : page.y) + height > maxAtlasSize) continue;\n if (nextRow) {\n page.y += page.rowHeight;\n page.x = 0;\n page.rowHeight = 0;\n }\n selected = i;\n break;\n }\n if (selected < 0) {\n selected = pages.length;\n pages.push({ layer, placements: [], entries: [], fluids: [], x: 0, y: 0, rowHeight: 0, width: 0, height: 0 });\n }\n const page = pages[selected];\n page.placements.push({ atlas, x: page.x, y: page.y });\n locations.set(atlas, { page: selected, x: page.x, y: page.y });\n page.x += width;\n page.rowHeight = Math.max(page.rowHeight, height);\n page.width = Math.max(page.width, page.x);\n page.height = Math.max(page.height, page.y + height);\n }\n }\n for (const entry of visible) pages[locations.get(templateData[templates[entry]].atlas)!.page].entries.push(entry);\n\n if (fluids) {\n const fluidPages = new Map<FluidKind, (typeof pages)[number]>();\n for (let y = 0; y < 16; y++) for (let z = 0; z < 16; z++) for (let x = 0; x < 16; x++) {\n const byte = fluids.cells[(y + 1) * 324 + (z + 1) * 18 + x + 1];\n const fluid = fluidKindOf(byte);\n if (!fluid || (byte & 128)) continue;\n const data = fluids[fluid];\n if (!data) throw new RangeError(\"Section fluid input lacks the atlas for a present fluid\");\n const quads = buildFluidQuads(fluid, (dx, dy, dz) => {\n const cell = fluids.cells[(y + 1 + dy) * 324 + (z + 1 + dz) * 18 + x + 1 + dx];\n return { fluid: fluidKindOf(cell), level: cell & 15, solid: !!(cell & 64) };\n });\n if (!quads.sprites.length) continue;\n if (!fluidPages.has(fluid)) {\n const { width, height } = atlases[data.atlas];\n if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError(\"Model atlas exceeds the section atlas size limit\");\n fluidPages.set(fluid, { layer: 2, placements: [{ atlas: data.atlas, x: 0, y: 0 }], entries: [], fluids: [],\n x: 0, y: 0, rowHeight: 0, width, height });\n }\n const tintIndex = (x + z * 16 + y * 256) * 3;\n const tint = fluid === \"water\" && fluids.waterTints ? fluids.waterTints.subarray(tintIndex, tintIndex + 3) : data.tint;\n fluidPages.get(fluid)!.fluids.push({ quads, x, y, z, data, tint });\n }\n pages.push(...[...fluidPages.values()].sort((a, b) => Number(atlases[a.placements[0].atlas].animated) -\n Number(atlases[b.placements[0].atlas].animated) || a.placements[0].atlas - b.placements[0].atlas));\n }\n\n return pages.map(page => {\n let faces = page.fluids.reduce((sum, fluid) => sum + fluid.quads.sprites.length, 0);\n for (const entry of page.entries) {\n const template = templateData[templates[entry]];\n for (let quad = 0; quad < template.quads; quad++) {\n if (!(cullMasks[entry] & template.cullFaces[quad])) faces++;\n }\n }\n const positions = new Float32Array(faces * 12), normals = new Float32Array(faces * 12);\n const uvs = new Float32Array(faces * 8), uvBounds = new Float32Array(faces * 16), colors = new Float32Array(faces * 12);\n const outputIndices = new Uint32Array(faces * 6);\n const blockIndices = new Uint16Array(faces);\n let vertex = 0, indexOffset = 0;\n for (const entry of page.entries) {\n const template = templateData[templates[entry]];\n const atlas = atlases[template.atlas];\n const placement = locations.get(template.atlas)!;\n const mapU = (u: number) => (placement.x + u * atlas.width) / page.width;\n const mapV = (v: number) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;\n const offsetX = (indices[entry] % 16) * 16;\n const offsetY = Math.floor(indices[entry] / 256) * 16;\n const offsetZ = (Math.floor(indices[entry] / 16) % 16) * 16;\n const lightIndex = (offsetY / 16 + 1) * 324 + (offsetZ / 16 + 1) * 18 + offsetX / 16 + 1;\n const ambientMask = ambientOcclusion && template.ambientOcclusion !== false\n ? sectionAmbientOcclusionMask(ambientOcclusion, lightIndex) : 0;\n for (let quad = 0; quad < template.quads; quad++) {\n if (cullMasks[entry] & template.cullFaces[quad]) continue;\n blockIndices[indexOffset / 6] = indices[entry];\n if (ambientMask) quadAmbientOcclusion(template.positions, template.normals, quad, ambientMask, cornerBrightness!);\n const brightness = light ? lightBrightness(light[lightIndex + LIGHT_SAMPLE_OFFSETS[\n quadLightIndex(template.positions, template.normals, quad)]], ambientLight) : 1;\n const tint = biomeTints && template.biomeTint?.[quad] && !Number.isNaN(biomeTints[entry * 3]) ? entry * 3 : undefined;\n const start = vertex;\n for (let corner = 0; corner < 4; corner++, vertex++) {\n const source = quad * 4 + corner;\n positions[vertex * 3] = template.positions[source * 3] + offsetX;\n positions[vertex * 3 + 1] = template.positions[source * 3 + 1] + offsetY;\n positions[vertex * 3 + 2] = template.positions[source * 3 + 2] + offsetZ;\n normals[vertex * 3] = template.normals[source * 3];\n normals[vertex * 3 + 1] = template.normals[source * 3 + 1];\n normals[vertex * 3 + 2] = template.normals[source * 3 + 2];\n uvs[vertex * 2] = mapU(template.uvs[source * 2]);\n uvs[vertex * 2 + 1] = mapV(template.uvs[source * 2 + 1]);\n uvBounds[vertex * 4] = mapU(template.uvBounds[source * 4]);\n uvBounds[vertex * 4 + 1] = mapV(template.uvBounds[source * 4 + 1]);\n uvBounds[vertex * 4 + 2] = mapU(template.uvBounds[source * 4 + 2]);\n uvBounds[vertex * 4 + 3] = mapV(template.uvBounds[source * 4 + 3]);\n const factor = brightness * (ambientMask ? cornerBrightness![corner] : 1);\n colors[vertex * 3] = (tint === undefined ? template.colors[source * 3] : biomeTints![tint]) * factor;\n colors[vertex * 3 + 1] = (tint === undefined ? template.colors[source * 3 + 1] : biomeTints![tint + 1]) * factor;\n colors[vertex * 3 + 2] = (tint === undefined ? template.colors[source * 3 + 2] : biomeTints![tint + 2]) * factor;\n }\n for (let corner = 0; corner < 6; corner++) outputIndices[indexOffset++] = start + template.indices[quad * 6 + corner];\n }\n }\n for (const { quads, x, y, z, data, tint } of page.fluids) {\n const atlas = atlases[data.atlas];\n const placement = page.placements[0];\n const mapU = (u: number) => (placement.x + u * atlas.width) / page.width;\n const mapV = (v: number) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;\n const lightIndex = (y + 1) * 324 + (z + 1) * 18 + x + 1;\n for (let quad = 0; quad < quads.sprites.length; quad++) {\n blockIndices[indexOffset / 6] = x + z * 16 + y * 256;\n const rect = quads.sprites[quad] === 0 ? data.still : data.flow;\n const brightness = light ? lightBrightness(fluidLightLevel(light[lightIndex],\n light[lightIndex + (quads.normals[quad * 12 + 1] < 0 ? -324 : 324)]), ambientLight) : 1;\n const start = vertex;\n for (let corner = 0; corner < 4; corner++, vertex++) {\n const source = quad * 4 + corner;\n positions[vertex * 3] = quads.positions[source * 3] + x * 16;\n positions[vertex * 3 + 1] = quads.positions[source * 3 + 1] + y * 16;\n positions[vertex * 3 + 2] = quads.positions[source * 3 + 2] + z * 16;\n normals[vertex * 3] = quads.normals[source * 3];\n normals[vertex * 3 + 1] = quads.normals[source * 3 + 1];\n normals[vertex * 3 + 2] = quads.normals[source * 3 + 2];\n uvs[vertex * 2] = mapU((rect[0] + quads.uvs[source * 2] * rect[2]) / atlas.width);\n uvs[vertex * 2 + 1] = mapV(1 - (rect[1] + (1 - quads.uvs[source * 2 + 1]) * rect[3]) / atlas.height);\n uvBounds.set([mapU(rect[0] / atlas.width), mapV(1 - (rect[1] + rect[3]) / atlas.height),\n mapU((rect[0] + rect[2]) / atlas.width), mapV(1 - rect[1] / atlas.height)], vertex * 4);\n colors[vertex * 3] = tint[0] * brightness;\n colors[vertex * 3 + 1] = tint[1] * brightness;\n colors[vertex * 3 + 2] = tint[2] * brightness;\n }\n outputIndices.set([start, start + 1, start + 2, start, start + 2, start + 3], indexOffset);\n indexOffset += 6;\n }\n }\n return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices, blockIndices };\n });\n}\n\n/** Returns the buffers behind each page's typed arrays for transfer to another thread. */\nexport function sectionGeometryTransferables(pages: readonly SectionGeometryPage[]): ArrayBuffer[] {\n return pages.flatMap(page => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.indices.buffer, page.blockIndices.buffer]);\n}\n","import { buildSectionGeometry, sectionGeometryTransferables, SectionGeometryInput } from \"../../world/SectionGeometry\";\n\naddEventListener(\"message\", (event: MessageEvent<{ id: number; type: \"build\"; input: SectionGeometryInput }>) => {\n const { id, input } = event.data;\n try {\n const pages = buildSectionGeometry(input);\n postMessage({ id, type: \"pages\", pages }, { transfer: sectionGeometryTransferables(pages) });\n } catch (error) {\n postMessage({ id, type: \"error\", message: error instanceof Error ? error.message : String(error) });\n }\n});\n"],"mappings":"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","names":["cornerBrightness","page"]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/model/fluid/FluidQuads.ts","../../../../../src/world/_light/AmbientOcclusion.ts","../../../../../src/world/_light/FaceLight.ts","../../../../../src/world/SectionGeometry.ts","../../../../../src/env/browser/section.worker.ts"],"sourcesContent":["import type { DoubleArray, TripleArray } from \"../Model\";\n\nexport type FluidKind = \"water\" | \"lava\";\n\n/** Reads the fluid kind from bits 4 and 5 of a section cell byte. */\nexport function fluidKindOf(byte: number): FluidKind | undefined {\n const kind = byte & 48;\n return kind === 16 ? \"water\" : kind === 32 ? \"lava\" : undefined;\n}\n\n/** A neighboring cell's fluid level and full-cube occlusion state. */\nexport interface FluidSample {\n fluid?: FluidKind;\n level?: number;\n solid?: boolean;\n}\n\n/** Reads cells at integer block offsets relative to the fluid being rendered, with `(0, 0, 0)` as the center. */\nexport type FluidSampler = (x: number, y: number, z: number) => FluidSample;\n\nconst HORIZONTAL = [[0, -1], [0, 1], [-1, 0], [1, 0]] as const;\nconst EPSILON = 0.001;\n\nfunction ownHeight(sample: FluidSample): number {\n const level = sample.level ?? 0;\n return (level === 0 || level >= 8 ? 8 : 8 - level) / 9;\n}\n\n/** Fluid faces as quads centered on the block, four vertices each, in emission order. */\nexport interface FluidQuads {\n positions: number[];\n normals: number[];\n uvs: number[];\n sprites: number[];\n}\n\n/** Builds centered fluid quads with sprite 0 (still) or 1 (flowing). */\nexport function buildFluidQuads(kind: FluidKind, sample: FluidSampler): FluidQuads {\n const positions: number[] = [], normals: number[] = [], uvs: number[] = [], sprites: number[] = [];\n const self = sample(0, 0, 0);\n const height = (x: number, z: number): number => {\n const state = sample(x, 0, z);\n if (state.fluid !== kind) return state.solid ? -1 : 0;\n return sample(x, 1, z).fluid === kind ? 1 : ownHeight(state);\n };\n const selfHeight = height(0, 0);\n const corner = (x: number, z: number): number => {\n if (selfHeight >= 1) return 1;\n const adjacent = [height(x, 0), height(0, z)];\n if (adjacent.some(value => value >= 1)) return 1;\n const values = [selfHeight, ...adjacent];\n if (adjacent.some(value => value > 0)) {\n const diagonal = height(x, z);\n if (diagonal >= 1) return 1;\n values.push(diagonal);\n }\n let sum = 0, weights = 0;\n for (const value of values) {\n if (value < 0) continue;\n const weight = value >= 0.8 ? 10 : 1;\n sum += value * weight;\n weights += weight;\n }\n return sum / weights;\n };\n const heights = [corner(-1, -1), corner(-1, 1), corner(1, 1), corner(1, -1)];\n const above = sample(0, 1, 0), below = sample(0, -1, 0);\n const renderTop = above.fluid !== kind && !(above.solid && Math.min(...heights) >= 1);\n const renderBottom = below.fluid !== kind && !below.solid;\n const bottom = renderBottom ? EPSILON : 0;\n const face = (vertices: TripleArray[], uv: DoubleArray[], normal: TripleArray, material: number) => {\n sprites.push(material);\n for (let i = 0; i < 4; i++) {\n positions.push(...vertices[i].map(value => value * 16 - 8));\n normals.push(...normal);\n uvs.push(uv[i][0], 1 - uv[i][1]);\n }\n };\n\n if (renderTop) {\n for (let i = 0; i < heights.length; i++) heights[i] -= EPSILON;\n let flowX = 0, flowZ = 0;\n for (const [x, z] of HORIZONTAL) {\n const neighbor = sample(x, 0, z);\n if (neighbor.fluid && neighbor.fluid !== kind) continue;\n let difference = 0;\n if (neighbor.fluid === kind) {\n difference = ownHeight(self) - ownHeight(neighbor);\n } else if (!neighbor.solid) {\n const lower = sample(x, -1, z);\n if (lower.fluid === kind) difference = ownHeight(self) - (ownHeight(lower) - 8 / 9);\n }\n flowX += x * difference;\n flowZ += z * difference;\n }\n const flowing = flowX !== 0 || flowZ !== 0;\n let uv: DoubleArray[] = [[0, 0], [0, 1], [1, 1], [1, 0]];\n if (flowing) {\n const angle = Math.atan2(flowZ, flowX) - Math.PI / 2;\n const s = Math.sin(angle) / 4, c = Math.cos(angle) / 4;\n uv = [[0.5 - c - s, 0.5 - c + s], [0.5 - c + s, 0.5 + c + s],\n [0.5 + c + s, 0.5 + c - s], [0.5 + c - s, 0.5 - c - s]];\n }\n face([[0, heights[0], 0], [0, heights[1], 1], [1, heights[2], 1], [1, heights[3], 0]], uv, [0, 1, 0], flowing ? 1 : 0);\n }\n if (renderBottom) {\n face([[0, bottom, 0], [1, bottom, 0], [1, bottom, 1], [0, bottom, 1]],\n [[0, 0], [1, 0], [1, 1], [0, 1]], [0, -1, 0], 0);\n }\n const sides = [\n { x: 0, z: -1, corners: [0, 3], edge: [[0, EPSILON], [1, EPSILON]] },\n { x: 0, z: 1, corners: [2, 1], edge: [[1, 1 - EPSILON], [0, 1 - EPSILON]] },\n { x: -1, z: 0, corners: [1, 0], edge: [[EPSILON, 1], [EPSILON, 0]] },\n { x: 1, z: 0, corners: [3, 2], edge: [[1 - EPSILON, 0], [1 - EPSILON, 1]] }\n ];\n for (const { x, z, corners, edge } of sides) {\n const neighbor = sample(x, 0, z);\n if (neighbor.fluid === kind || neighbor.solid) continue;\n const [h0, h1] = corners.map(index => heights[index]);\n const [[x0, z0], [x1, z1]] = edge;\n face([[x0, h0, z0], [x1, h1, z1], [x1, bottom, z1], [x0, bottom, z0]],\n [[0, (1 - h0) / 2], [0.5, (1 - h1) / 2], [0.5, 0.5], [0, 0.5]], [x, 0, z], 1);\n }\n return { positions, normals, uvs, sprites };\n}\n","const AXIS_STRIDES = [1, 9, 3] as const;\n\n/** Reads the edge and corner blockers around one cell in an 18×18×18 section neighborhood. */\nexport function sectionAmbientOcclusionMask(cells: Uint8Array, center: number): number {\n let mask = 0;\n for (let y = -1; y <= 1; y++) for (let z = -1; z <= 1; z++) for (let x = -1; x <= 1; x++) {\n if (Math.abs(x) + Math.abs(y) + Math.abs(z) < 2) continue;\n if (cells[center + y * 324 + z * 18 + x]) mask |= 1 << ((y + 1) * 9 + (z + 1) * 3 + x + 1);\n }\n return mask;\n}\n\nfunction cornerBrightness(mask: number, center: number, u: number, v: number): number {\n const sideU = (mask >>> (center + u)) & 1;\n const sideV = (mask >>> (center + v)) & 1;\n const corner = sideU && sideV ? 1 : (mask >>> (center + u + v)) & 1;\n return 1 - (sideU + sideV + corner) * 0.2;\n}\n\n/** Writes four linear AO factors for a boundary quad; inset or non-axis-aligned quads remain unchanged. */\nexport function quadAmbientOcclusion(positions: ArrayLike<number>, normals: ArrayLike<number>, quad: number,\n mask: number, output: Float32Array): void {\n output.fill(1);\n if (!mask) return;\n const start = quad * 12;\n let axis = 0;\n if (Math.abs(normals[start + 1]) > Math.abs(normals[start + axis])) axis = 1;\n if (Math.abs(normals[start + 2]) > Math.abs(normals[start + axis])) axis = 2;\n const uAxis = (axis + 1) % 3, vAxis = (axis + 2) % 3;\n if (Math.abs(Math.abs(normals[start + axis]) - 1) > 1e-6 ||\n Math.abs(normals[start + uAxis]) > 1e-6 || Math.abs(normals[start + vAxis]) > 1e-6) return;\n const sign = normals[start + axis] > 0 ? 1 : -1;\n for (let vertex = 0; vertex < 4; vertex++) {\n const offset = start + vertex * 3;\n if (Math.abs(positions[offset + axis] - sign * 8) > 0.0016 ||\n Math.abs(positions[offset + uAxis]) > 8.0016 || Math.abs(positions[offset + vAxis]) > 8.0016) return;\n }\n const center = 13 + sign * AXIS_STRIDES[axis];\n const u = AXIS_STRIDES[uAxis], v = AXIS_STRIDES[vAxis];\n const lowLow = cornerBrightness(mask, center, -u, -v);\n const highLow = cornerBrightness(mask, center, u, -v);\n const lowHigh = cornerBrightness(mask, center, -u, v);\n const highHigh = cornerBrightness(mask, center, u, v);\n for (let vertex = 0; vertex < 4; vertex++) {\n const offset = start + vertex * 3;\n const a = Math.max(0, Math.min(1, (positions[offset + uAxis] + 8) / 16));\n const b = Math.max(0, Math.min(1, (positions[offset + vAxis] + 8) / 16));\n output[vertex] = (lowLow * (1 - a) + highLow * a) * (1 - b) + (lowHigh * (1 - a) + highHigh * a) * b;\n }\n}\n","/** Converts a saved light level to linear brightness; unknown samples retain preview brightness. */\nexport function lightBrightness(level: number, ambient = 0): number {\n if (level === 255) return 1;\n const curve = level / (60 - 3 * level);\n return curve + ambient * (1 - curve);\n}\n\n/** Selects the adjacent light sample for a boundary quad, or the center sample for an inset quad. */\nexport function quadLightIndex(positions: ArrayLike<number>, normals: ArrayLike<number>, quad: number): number {\n const start = quad * 12;\n let axis = 0;\n if (Math.abs(normals[start + 1]) > Math.abs(normals[start + axis])) axis = 1;\n if (Math.abs(normals[start + 2]) > Math.abs(normals[start + axis])) axis = 2;\n const positive = normals[start + axis] > 0;\n const boundary = positive ? 8 : -8;\n for (let vertex = 0; vertex < 4; vertex++) {\n if (Math.abs(positions[start + vertex * 3 + axis] - boundary) > 0.0016) return 0;\n }\n return axis * 2 + (positive ? 1 : 2);\n}\n\n/** Fluids sample the brighter of their own cell and the cell above, or below for bottom faces. */\nexport function fluidLightLevel(center: number, neighbor: number): number {\n return Math.max(center === 255 ? 15 : center, neighbor === 255 ? 15 : neighbor);\n}\n\n/** Offsets for center and face samples in an 18×18×18 section neighborhood. */\nexport const LIGHT_SAMPLE_OFFSETS = [0, 1, -1, 324, -324, 18, -18] as const;\n","import { buildFluidQuads, fluidKindOf } from \"../model/fluid/FluidQuads\";\nimport type { FluidKind, FluidQuads } from \"../model/fluid/FluidQuads\";\nimport { quadAmbientOcclusion, sectionAmbientOcclusionMask } from \"./_light/AmbientOcclusion\";\nimport { fluidLightLevel, LIGHT_SAMPLE_OFFSETS, lightBrightness, quadLightIndex } from \"./_light/FaceLight\";\n\n/** Static model geometry as quads: four vertices per quad, in quad order. */\nexport interface SectionTemplateData {\n quads: number;\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n uvBounds: Float32Array;\n colors: Float32Array;\n shade?: Float32Array;\n indices: Uint16Array;\n cullFaces: Uint8Array;\n biomeTint?: Uint8Array;\n atlas: number;\n layer: number;\n ambientOcclusion?: boolean;\n}\n\n/** The pixel dimensions and animation state of a source atlas. */\nexport interface SectionAtlasSize {\n width: number;\n height: number;\n animated: boolean;\n}\n\n/** One fluid kind's sprite rectangles in atlas pixels and its linear-light vertex tint. */\nexport interface SectionFluidKind {\n atlas: number;\n still: [x: number, y: number, width: number, height: number];\n flow: [x: number, y: number, width: number, height: number];\n tint: [r: number, g: number, b: number];\n}\n\n/** Fluid cells of the section plus a one-cell shell, 18×18×18, x fastest, then z, then y. */\nexport interface SectionFluidInput {\n /** Bit 128 marks a surface rendered elsewhere; the cell still supplies neighbor fluid samples. */\n cells: Uint8Array;\n /** Linear RGB per section cell, indexed by (x + 16z + 256y) * 3. Omission uses the water kind's tint. */\n waterTints?: Float32Array;\n water?: SectionFluidKind;\n lava?: SectionFluidKind;\n}\n\n/** Section placements and their shared templates, ready for geometry building. */\nexport interface SectionGeometryInput {\n count: number;\n indices: Uint16Array;\n templates: Uint16Array;\n cullMasks: Uint8Array;\n /** Linear RGB per placement; three NaN values preserve the template's colors. */\n biomeTints?: Float32Array;\n templateData: SectionTemplateData[];\n atlases: SectionAtlasSize[];\n maxAtlasSize: number;\n fluids?: SectionFluidInput;\n /** Saved brightness levels for an 18×18×18 neighborhood; 255 means unknown/full brightness. */\n light?: Uint8Array;\n /** Minimum brightness for known light levels, from 0 to 1. */\n ambientLight?: number;\n /** Opaque full cubes in an 18×18×18 neighborhood, stored as zero or one. */\n ambientOcclusion?: Uint8Array;\n}\n\n/** Merged quads and source-atlas placements for one atlas page. */\nexport interface SectionGeometryPage {\n layer: number;\n width: number;\n height: number;\n placements: { atlas: number; x: number; y: number }[];\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n uvBounds: Float32Array;\n colors: Float32Array;\n shade: Float32Array;\n indices: Uint32Array;\n /** Owning section cell for each quad; each quad contributes two consecutive triangles. */\n blockIndices: Uint16Array;\n}\n\n/** Builds section-local geometry from visible quads, with bounded atlas pages per layer. */\nexport function buildSectionGeometry(input: SectionGeometryInput): SectionGeometryPage[] {\n const { count, indices, templates, cullMasks, templateData, atlases, maxAtlasSize, fluids, light, ambientLight, ambientOcclusion, biomeTints } = input;\n if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError(\"Section atlas size must be a positive integer\");\n if (count > indices.length || count > templates.length || count > cullMasks.length) throw new RangeError(\"Section entry count exceeds its arrays\");\n if (biomeTints && biomeTints.length !== count * 3) throw new RangeError(\"Section biome tints must contain RGB for each placement\");\n if (fluids && fluids.cells.length !== 5832) throw new RangeError(\"Section fluid cells must cover an 18×18×18 neighborhood\");\n if (fluids?.waterTints && fluids.waterTints.length !== 4096 * 3) throw new RangeError(\"Section water tints must contain RGB for 4096 cells\");\n if (light && (light.length !== 5832 || light.some(level => level > 15 && level !== 255))) {\n throw new RangeError(\"Section light must cover an 18×18×18 neighborhood with levels from 0 to 15 or 255\");\n }\n if (ambientLight !== undefined && (!Number.isFinite(ambientLight) || ambientLight < 0 || ambientLight > 1)) {\n throw new RangeError(\"Section ambient light must be a number from 0 to 1\");\n }\n if (ambientOcclusion && (ambientOcclusion.length !== 5832 || ambientOcclusion.some(value => value > 1))) {\n throw new RangeError(\"Section ambient occlusion must cover an 18×18×18 neighborhood with zero or one per cell\");\n }\n const cornerBrightness = ambientOcclusion ? new Float32Array(4) : undefined;\n for (const template of templateData) {\n const { quads } = template;\n if (template.positions.length !== quads * 12 || template.normals.length !== quads * 12 ||\n template.uvs.length !== quads * 8 || template.uvBounds.length !== quads * 16 ||\n template.colors.length !== quads * 12 || template.indices.length !== quads * 6 || template.cullFaces.length !== quads ||\n (template.shade && template.shade.length !== quads * 4) ||\n (template.biomeTint && template.biomeTint.length !== quads)) {\n throw new RangeError(\"Section template arrays do not match its quad count\");\n }\n }\n const visible: number[] = [];\n const visibleAtlases = new Map<number, Set<number>>();\n for (let entry = 0; entry < count; entry++) {\n const template = templateData[templates[entry]];\n if (!template.cullFaces.some(direction => !(cullMasks[entry] & direction))) continue;\n visible.push(entry);\n if (!visibleAtlases.has(template.layer)) visibleAtlases.set(template.layer, new Set());\n visibleAtlases.get(template.layer)!.add(template.atlas);\n }\n const pages: {\n layer: number; placements: SectionGeometryPage[\"placements\"]; entries: number[];\n fluids: { quads: FluidQuads; x: number; y: number; z: number; data: SectionFluidKind; tint: ArrayLike<number> }[];\n x: number; y: number; rowHeight: number; width: number; height: number;\n }[] = [];\n const locations = new Map<number, { page: number; x: number; y: number }>();\n for (const [layer, layerAtlases] of [...visibleAtlases].sort(([a], [b]) => a - b)) {\n const firstPage = pages.length;\n for (const atlas of [...layerAtlases].sort((a, b) => Number(atlases[a].animated) - Number(atlases[b].animated) ||\n (atlases[a].animated ? a - b : atlases[b].height - atlases[a].height))) {\n const { width, height, animated } = atlases[atlas];\n if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError(\"Model atlas exceeds the section atlas size limit\");\n let selected = -1;\n for (let i = firstPage; !animated && i < pages.length; i++) {\n const page = pages[i];\n const nextRow = page.x + width > maxAtlasSize;\n if ((nextRow ? page.y + page.rowHeight : page.y) + height > maxAtlasSize) continue;\n if (nextRow) {\n page.y += page.rowHeight;\n page.x = 0;\n page.rowHeight = 0;\n }\n selected = i;\n break;\n }\n if (selected < 0) {\n selected = pages.length;\n pages.push({ layer, placements: [], entries: [], fluids: [], x: 0, y: 0, rowHeight: 0, width: 0, height: 0 });\n }\n const page = pages[selected];\n page.placements.push({ atlas, x: page.x, y: page.y });\n locations.set(atlas, { page: selected, x: page.x, y: page.y });\n page.x += width;\n page.rowHeight = Math.max(page.rowHeight, height);\n page.width = Math.max(page.width, page.x);\n page.height = Math.max(page.height, page.y + height);\n }\n }\n for (const entry of visible) pages[locations.get(templateData[templates[entry]].atlas)!.page].entries.push(entry);\n\n if (fluids) {\n const fluidPages = new Map<FluidKind, (typeof pages)[number]>();\n for (let y = 0; y < 16; y++) for (let z = 0; z < 16; z++) for (let x = 0; x < 16; x++) {\n const byte = fluids.cells[(y + 1) * 324 + (z + 1) * 18 + x + 1];\n const fluid = fluidKindOf(byte);\n if (!fluid || (byte & 128)) continue;\n const data = fluids[fluid];\n if (!data) throw new RangeError(\"Section fluid input lacks the atlas for a present fluid\");\n const quads = buildFluidQuads(fluid, (dx, dy, dz) => {\n const cell = fluids.cells[(y + 1 + dy) * 324 + (z + 1 + dz) * 18 + x + 1 + dx];\n return { fluid: fluidKindOf(cell), level: cell & 15, solid: !!(cell & 64) };\n });\n if (!quads.sprites.length) continue;\n if (!fluidPages.has(fluid)) {\n const { width, height } = atlases[data.atlas];\n if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError(\"Model atlas exceeds the section atlas size limit\");\n fluidPages.set(fluid, { layer: 2, placements: [{ atlas: data.atlas, x: 0, y: 0 }], entries: [], fluids: [],\n x: 0, y: 0, rowHeight: 0, width, height });\n }\n const tintIndex = (x + z * 16 + y * 256) * 3;\n const tint = fluid === \"water\" && fluids.waterTints ? fluids.waterTints.subarray(tintIndex, tintIndex + 3) : data.tint;\n fluidPages.get(fluid)!.fluids.push({ quads, x, y, z, data, tint });\n }\n pages.push(...[...fluidPages.values()].sort((a, b) => Number(atlases[a.placements[0].atlas].animated) -\n Number(atlases[b.placements[0].atlas].animated) || a.placements[0].atlas - b.placements[0].atlas));\n }\n\n return pages.map(page => {\n let faces = page.fluids.reduce((sum, fluid) => sum + fluid.quads.sprites.length, 0);\n for (const entry of page.entries) {\n const template = templateData[templates[entry]];\n for (let quad = 0; quad < template.quads; quad++) {\n if (!(cullMasks[entry] & template.cullFaces[quad])) faces++;\n }\n }\n const positions = new Float32Array(faces * 12), normals = new Float32Array(faces * 12);\n const uvs = new Float32Array(faces * 8), uvBounds = new Float32Array(faces * 16), colors = new Float32Array(faces * 12);\n const shade = new Float32Array(faces * 4).fill(1);\n const outputIndices = new Uint32Array(faces * 6);\n const blockIndices = new Uint16Array(faces);\n let vertex = 0, indexOffset = 0;\n for (const entry of page.entries) {\n const template = templateData[templates[entry]];\n const atlas = atlases[template.atlas];\n const placement = locations.get(template.atlas)!;\n const mapU = (u: number) => (placement.x + u * atlas.width) / page.width;\n const mapV = (v: number) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;\n const offsetX = (indices[entry] % 16) * 16;\n const offsetY = Math.floor(indices[entry] / 256) * 16;\n const offsetZ = (Math.floor(indices[entry] / 16) % 16) * 16;\n const lightIndex = (offsetY / 16 + 1) * 324 + (offsetZ / 16 + 1) * 18 + offsetX / 16 + 1;\n const ambientMask = ambientOcclusion && template.ambientOcclusion !== false\n ? sectionAmbientOcclusionMask(ambientOcclusion, lightIndex) : 0;\n for (let quad = 0; quad < template.quads; quad++) {\n if (cullMasks[entry] & template.cullFaces[quad]) continue;\n blockIndices[indexOffset / 6] = indices[entry];\n if (ambientMask) quadAmbientOcclusion(template.positions, template.normals, quad, ambientMask, cornerBrightness!);\n const brightness = light ? lightBrightness(light[lightIndex + LIGHT_SAMPLE_OFFSETS[\n quadLightIndex(template.positions, template.normals, quad)]], ambientLight) : 1;\n const tint = biomeTints && template.biomeTint?.[quad] && !Number.isNaN(biomeTints[entry * 3]) ? entry * 3 : undefined;\n const start = vertex;\n for (let corner = 0; corner < 4; corner++, vertex++) {\n const source = quad * 4 + corner;\n positions[vertex * 3] = template.positions[source * 3] + offsetX;\n positions[vertex * 3 + 1] = template.positions[source * 3 + 1] + offsetY;\n positions[vertex * 3 + 2] = template.positions[source * 3 + 2] + offsetZ;\n normals[vertex * 3] = template.normals[source * 3];\n normals[vertex * 3 + 1] = template.normals[source * 3 + 1];\n normals[vertex * 3 + 2] = template.normals[source * 3 + 2];\n shade[vertex] = template.shade?.[source] ?? 1;\n uvs[vertex * 2] = mapU(template.uvs[source * 2]);\n uvs[vertex * 2 + 1] = mapV(template.uvs[source * 2 + 1]);\n uvBounds[vertex * 4] = mapU(template.uvBounds[source * 4]);\n uvBounds[vertex * 4 + 1] = mapV(template.uvBounds[source * 4 + 1]);\n uvBounds[vertex * 4 + 2] = mapU(template.uvBounds[source * 4 + 2]);\n uvBounds[vertex * 4 + 3] = mapV(template.uvBounds[source * 4 + 3]);\n const factor = brightness * (ambientMask ? cornerBrightness![corner] : 1);\n colors[vertex * 3] = (tint === undefined ? template.colors[source * 3] : biomeTints![tint]) * factor;\n colors[vertex * 3 + 1] = (tint === undefined ? template.colors[source * 3 + 1] : biomeTints![tint + 1]) * factor;\n colors[vertex * 3 + 2] = (tint === undefined ? template.colors[source * 3 + 2] : biomeTints![tint + 2]) * factor;\n }\n for (let corner = 0; corner < 6; corner++) outputIndices[indexOffset++] = start + template.indices[quad * 6 + corner];\n }\n }\n for (const { quads, x, y, z, data, tint } of page.fluids) {\n const atlas = atlases[data.atlas];\n const placement = page.placements[0];\n const mapU = (u: number) => (placement.x + u * atlas.width) / page.width;\n const mapV = (v: number) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;\n const lightIndex = (y + 1) * 324 + (z + 1) * 18 + x + 1;\n for (let quad = 0; quad < quads.sprites.length; quad++) {\n blockIndices[indexOffset / 6] = x + z * 16 + y * 256;\n const rect = quads.sprites[quad] === 0 ? data.still : data.flow;\n const brightness = light ? lightBrightness(fluidLightLevel(light[lightIndex],\n light[lightIndex + (quads.normals[quad * 12 + 1] < 0 ? -324 : 324)]), ambientLight) : 1;\n const start = vertex;\n for (let corner = 0; corner < 4; corner++, vertex++) {\n const source = quad * 4 + corner;\n positions[vertex * 3] = quads.positions[source * 3] + x * 16;\n positions[vertex * 3 + 1] = quads.positions[source * 3 + 1] + y * 16;\n positions[vertex * 3 + 2] = quads.positions[source * 3 + 2] + z * 16;\n normals[vertex * 3] = quads.normals[source * 3];\n normals[vertex * 3 + 1] = quads.normals[source * 3 + 1];\n normals[vertex * 3 + 2] = quads.normals[source * 3 + 2];\n uvs[vertex * 2] = mapU((rect[0] + quads.uvs[source * 2] * rect[2]) / atlas.width);\n uvs[vertex * 2 + 1] = mapV(1 - (rect[1] + (1 - quads.uvs[source * 2 + 1]) * rect[3]) / atlas.height);\n uvBounds.set([mapU(rect[0] / atlas.width), mapV(1 - (rect[1] + rect[3]) / atlas.height),\n mapU((rect[0] + rect[2]) / atlas.width), mapV(1 - rect[1] / atlas.height)], vertex * 4);\n colors[vertex * 3] = tint[0] * brightness;\n colors[vertex * 3 + 1] = tint[1] * brightness;\n colors[vertex * 3 + 2] = tint[2] * brightness;\n }\n outputIndices.set([start, start + 1, start + 2, start, start + 2, start + 3], indexOffset);\n indexOffset += 6;\n }\n }\n return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, shade, indices: outputIndices, blockIndices };\n });\n}\n\n/** Returns the buffers behind each page's typed arrays for transfer to another thread. */\nexport function sectionGeometryTransferables(pages: readonly SectionGeometryPage[]): ArrayBuffer[] {\n return pages.flatMap(page => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.shade.buffer, page.indices.buffer, page.blockIndices.buffer]);\n}\n","import { buildSectionGeometry, sectionGeometryTransferables, SectionGeometryInput } from \"../../world/SectionGeometry\";\n\naddEventListener(\"message\", (event: MessageEvent<{ id: number; type: \"build\"; input: SectionGeometryInput }>) => {\n const { id, input } = event.data;\n try {\n const pages = buildSectionGeometry(input);\n postMessage({ id, type: \"pages\", pages }, { transfer: sectionGeometryTransferables(pages) });\n } catch (error) {\n postMessage({ id, type: \"error\", message: error instanceof Error ? error.message : String(error) });\n }\n});\n"],"mappings":"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","names":["cornerBrightness","page"]}
|