minerender 2.1.0-alpha.125 → 2.1.0-alpha.127
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/index.d.mts +25 -3
- package/dist/browser/index.d.ts +25 -3
- package/dist/browser/index.js +78 -11
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +78 -11
- package/dist/browser/index.mjs.map +1 -1
- package/dist/bundle.js +81 -11
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +25 -3
- package/dist/node/index.d.ts +25 -3
- package/dist/node/index.js +78 -11
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +78 -11
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.mjs
CHANGED
|
@@ -1534,6 +1534,11 @@ var init_DisplayTransforms = __esm({
|
|
|
1534
1534
|
}
|
|
1535
1535
|
/** Build a display pose for geometry already centered at the model's [8, 8, 8] pivot. */
|
|
1536
1536
|
static getMatrix(display, position) {
|
|
1537
|
+
const transform = this.getTransform(display, position);
|
|
1538
|
+
return new Matrix4().compose(transform.position, transform.quaternion, transform.scale);
|
|
1539
|
+
}
|
|
1540
|
+
/** Position, rotation, and scale of a display pose for geometry already centered at the model's [8, 8, 8] pivot. */
|
|
1541
|
+
static getTransform(display, position) {
|
|
1537
1542
|
const transform = this.withHandFallbacks(display)?.[position] ?? {};
|
|
1538
1543
|
const left = position === "firstperson_lefthand" /* FIRSTPERSON_LEFTHAND */ || position === "thirdperson_lefthand" /* THIRDPERSON_LEFTHAND */;
|
|
1539
1544
|
const sign = left ? -1 : 1;
|
|
@@ -1542,7 +1547,7 @@ var init_DisplayTransforms = __esm({
|
|
|
1542
1547
|
const translation = new Vector32(...transform.translation ?? [0, 0, 0]).clampScalar(-80, 80);
|
|
1543
1548
|
translation.x *= sign;
|
|
1544
1549
|
const scale = new Vector32(...transform.scale ?? [1, 1, 1]).clampScalar(-4, 4);
|
|
1545
|
-
return
|
|
1550
|
+
return { position: translation, quaternion: rotation, scale };
|
|
1546
1551
|
}
|
|
1547
1552
|
/** Transforms geometry in place and reverses triangle winding when the matrix reflects it. */
|
|
1548
1553
|
static apply(geometry, matrix) {
|
|
@@ -1727,6 +1732,7 @@ ${key}` : key, async () => {
|
|
|
1727
1732
|
if (!object(data)) return false;
|
|
1728
1733
|
if (dataset === "potionColors") return object(data.effects) && Object.values(data.effects).every(Number.isInteger) && object(data.potions) && Object.values(data.potions).every((effects) => Array.isArray(effects) && effects.every((effect) => object(effect) && typeof effect.id === "string" && Number.isInteger(effect.amplifier)));
|
|
1729
1734
|
if (dataset === "legacyBlocks") return object(data.blocks) && Object.values(data.blocks).every((value) => typeof value === "string");
|
|
1735
|
+
if (dataset === "blockCulling") return Array.isArray(data.profiles) && data.profiles.every((profile) => object(profile) && typeof profile.type === "string") && object(data.blocks) && Object.values(data.blocks).every((index) => Number.isInteger(index) && index >= 0 && index < data.profiles.length) && (data.groups === void 0 || object(data.groups) && Object.values(data.groups).every((group) => Array.isArray(group) && group.every((type) => typeof type === "string")));
|
|
1730
1736
|
return Object.values(data).every((value) => {
|
|
1731
1737
|
if (!object(value)) return false;
|
|
1732
1738
|
switch (dataset) {
|
|
@@ -7116,16 +7122,21 @@ var init_ModelObject = __esm({
|
|
|
7116
7122
|
const special = this.originalModel.special;
|
|
7117
7123
|
if (special) {
|
|
7118
7124
|
const parts2 = await SpecialItems.getParts(special, this.originalModel.key?.root, this.originalModel.components);
|
|
7119
|
-
const
|
|
7120
|
-
|
|
7125
|
+
const display = new SceneObject();
|
|
7126
|
+
if (this.options.displayPosition) {
|
|
7127
|
+
const transform = DisplayTransforms.getTransform(this.originalModel.display, this.options.displayPosition);
|
|
7128
|
+
display.position.copy(transform.position);
|
|
7129
|
+
display.quaternion.copy(transform.quaternion);
|
|
7130
|
+
display.scale.copy(transform.scale);
|
|
7131
|
+
}
|
|
7132
|
+
this.add(display);
|
|
7133
|
+
const offset = new Matrix48().makeTranslation(-8, -8, -8);
|
|
7121
7134
|
try {
|
|
7122
7135
|
const targets = [];
|
|
7123
7136
|
for (const part of parts2) {
|
|
7124
7137
|
const object4 = new EntityObject(part.model, { flip: false, wireframe: this.options.wireframe, tints: part.tints, faces: part.faces });
|
|
7125
|
-
object4.matrix.
|
|
7126
|
-
object4
|
|
7127
|
-
object4.matrixAutoUpdate = false;
|
|
7128
|
-
this.add(object4);
|
|
7138
|
+
object4.matrix.multiplyMatrices(offset, part.transform).decompose(object4.position, object4.quaternion, object4.scale);
|
|
7139
|
+
display.add(object4);
|
|
7129
7140
|
await object4.init(part.material);
|
|
7130
7141
|
object4.iterateAllMeshes((mesh) => {
|
|
7131
7142
|
const source = mesh.material;
|
|
@@ -17662,6 +17673,38 @@ function sampleSectionLight(light, index) {
|
|
|
17662
17673
|
};
|
|
17663
17674
|
}
|
|
17664
17675
|
|
|
17676
|
+
// src/world/_culling/BlockCulling.ts
|
|
17677
|
+
init_Assets();
|
|
17678
|
+
init_MineRenderData();
|
|
17679
|
+
init_CubeFace();
|
|
17680
|
+
async function loadBlockCulling(root) {
|
|
17681
|
+
const { manifest } = await MineRenderData.resolve(root);
|
|
17682
|
+
return manifest.datasets.blockCulling ? MineRenderData.get("blockCulling", root) : void 0;
|
|
17683
|
+
}
|
|
17684
|
+
function blockCullingRule(data, type) {
|
|
17685
|
+
if (!type.includes(":")) type = `${DEFAULT_NAMESPACE}:${type}`;
|
|
17686
|
+
return Object.prototype.hasOwnProperty.call(data.blocks, type) ? data.profiles[data.blocks[type]] : void 0;
|
|
17687
|
+
}
|
|
17688
|
+
function skipsBlockFace(data, rule, block, neighbor, face) {
|
|
17689
|
+
const type = block.type.includes(":") ? block.type : `${DEFAULT_NAMESPACE}:${block.type}`;
|
|
17690
|
+
const other = neighbor.type.includes(":") ? neighbor.type : `${DEFAULT_NAMESPACE}:${neighbor.type}`;
|
|
17691
|
+
const same = type === other;
|
|
17692
|
+
const vertical = CUBE_FACES[face] === "up" /* UP */ || CUBE_FACES[face] === "down" /* DOWN */;
|
|
17693
|
+
switch (rule.type) {
|
|
17694
|
+
case "same_block":
|
|
17695
|
+
return same;
|
|
17696
|
+
case "same_block_vertical":
|
|
17697
|
+
return same && vertical;
|
|
17698
|
+
case "connected": {
|
|
17699
|
+
if (vertical) return same;
|
|
17700
|
+
const group = rule.group ? data.groups?.[rule.group] : void 0;
|
|
17701
|
+
return (same || !!group?.includes(type) && group.includes(other)) && String(block.properties?.[CUBE_FACES[face]]) === "true" && String(neighbor.properties?.[CUBE_FACES[face ^ 1]]) === "true";
|
|
17702
|
+
}
|
|
17703
|
+
default:
|
|
17704
|
+
return false;
|
|
17705
|
+
}
|
|
17706
|
+
}
|
|
17707
|
+
|
|
17665
17708
|
// src/world/MineRenderWorld.ts
|
|
17666
17709
|
var MineRenderWorld = class {
|
|
17667
17710
|
constructor(scene, options = {}) {
|
|
@@ -18050,15 +18093,23 @@ var MineRenderWorld = class {
|
|
|
18050
18093
|
return this.culling ??= Promise.resolve().then(async () => {
|
|
18051
18094
|
let sliceStart = performance.now();
|
|
18052
18095
|
try {
|
|
18096
|
+
const culling = await loadBlockCulling();
|
|
18053
18097
|
while (this.pendingCulling.size) {
|
|
18054
18098
|
const batch = [...this.pendingCulling];
|
|
18055
18099
|
this.pendingCulling.clear();
|
|
18056
18100
|
for (const [chunk, indices] of batch) {
|
|
18057
18101
|
const neighbors = CUBE_FACE_OFFSETS.map(([x, y, z]) => this._chunks.get(`${chunk.x + x}_${chunk.y + y}_${chunk.z + z}`));
|
|
18058
|
-
const
|
|
18102
|
+
const neighborAt = (x, y, z) => {
|
|
18059
18103
|
const lx = x - chunk.x * 16, ly = y - chunk.y * 16, lz = z - chunk.z * 16;
|
|
18060
18104
|
const section = neighbors[lx >= 16 ? 0 : lx < 0 ? 1 : ly >= 16 ? 2 : ly < 0 ? 3 : lz >= 16 ? 4 : 5];
|
|
18061
|
-
return section
|
|
18105
|
+
return [section, (ly & 15) * 256 + (lz & 15) * 16 + (lx & 15)];
|
|
18106
|
+
};
|
|
18107
|
+
const masks = chunk.updateCullMasks(indices === "all" ? void 0 : indices, (x, y, z) => {
|
|
18108
|
+
const [section, i] = neighborAt(x, y, z);
|
|
18109
|
+
return section?.isOccludingIndex(i) ?? false;
|
|
18110
|
+
}, culling, (x, y, z) => {
|
|
18111
|
+
const [section, i] = neighborAt(x, y, z);
|
|
18112
|
+
return section?.visibleBlockIndex(i);
|
|
18062
18113
|
});
|
|
18063
18114
|
const fluidIndices = indices === "all" ? function* () {
|
|
18064
18115
|
for (let index = 0; index < 4096; index++) yield index;
|
|
@@ -19174,6 +19225,10 @@ var Chunk = class _Chunk {
|
|
|
19174
19225
|
isBlockVisibleIndex(index) {
|
|
19175
19226
|
return this.renderedBlocks.has(index) && !this.hiddenBlocks.has(index);
|
|
19176
19227
|
}
|
|
19228
|
+
/** Stored state of a rendered, visible cell, or `undefined`. */
|
|
19229
|
+
visibleBlockIndex(index) {
|
|
19230
|
+
return this.isBlockVisibleIndex(index) ? this.data.stateAt(this.data.idAt(index)) : void 0;
|
|
19231
|
+
}
|
|
19177
19232
|
/** Fluid kind bits and level of a cell, or 0. Hidden cells report 0. */
|
|
19178
19233
|
fluidByteIndex(index) {
|
|
19179
19234
|
return this.hiddenBlocks.has(index) ? 0 : this.fluidCells[index];
|
|
@@ -19192,18 +19247,30 @@ var Chunk = class _Chunk {
|
|
|
19192
19247
|
async setCullMaskAt(pos, mask) {
|
|
19193
19248
|
await this.setCullMaskIndex(_Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos)), mask);
|
|
19194
19249
|
}
|
|
19195
|
-
/**
|
|
19196
|
-
|
|
19250
|
+
/**
|
|
19251
|
+
* Recomputes section masks and returns changed per-block masks. Omit indices to visit every cell.
|
|
19252
|
+
* `culling` supplies neighbor face rules; `blockAt` supplies visible states outside this chunk.
|
|
19253
|
+
*/
|
|
19254
|
+
updateCullMasks(indices, occludes, culling, blockAt) {
|
|
19197
19255
|
const changed = [];
|
|
19256
|
+
const rules = [];
|
|
19198
19257
|
for (const index of indices ?? this.fluidCells.keys()) {
|
|
19199
19258
|
if (!this.isBlockVisibleIndex(index)) continue;
|
|
19200
19259
|
const x = index % 16, y = Math.floor(index / 256), z = Math.floor(index / 16) % 16;
|
|
19260
|
+
const id = this.data.idAt(index);
|
|
19261
|
+
let rule = rules[id];
|
|
19262
|
+
if (culling && rule === void 0) rules[id] = rule = blockCullingRule(culling, this.data.stateAt(id).type) ?? null;
|
|
19263
|
+
const block = rule ? this.data.stateAt(id) : void 0;
|
|
19201
19264
|
let mask = 0;
|
|
19202
19265
|
for (let face = 0; face < CUBE_FACE_OFFSETS.length; face++) {
|
|
19203
19266
|
const [dx, dy, dz] = CUBE_FACE_OFFSETS[face];
|
|
19204
19267
|
const nx = x + dx, ny = y + dy, nz = z + dz;
|
|
19205
19268
|
const inner = nx >= 0 && nx < 16 && ny >= 0 && ny < 16 && nz >= 0 && nz < 16;
|
|
19206
19269
|
if (inner ? this.isOccludingIndex(ny * 256 + nz * 16 + nx) : occludes(this.x * 16 + nx, this.y * 16 + ny, this.z * 16 + nz)) mask |= 1 << face;
|
|
19270
|
+
else if (rule) {
|
|
19271
|
+
const neighbor = inner ? this.visibleBlockIndex(ny * 256 + nz * 16 + nx) : blockAt?.(this.x * 16 + nx, this.y * 16 + ny, this.z * 16 + nz);
|
|
19272
|
+
if (neighbor && skipsBlockFace(culling, rule, block, neighbor, face)) mask |= 1 << face;
|
|
19273
|
+
}
|
|
19207
19274
|
}
|
|
19208
19275
|
if (this.fluidCells[index]) this.meshDirty = true;
|
|
19209
19276
|
const entries = this.sectionBlocks.get(index);
|