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/browser/index.mjs
CHANGED
|
@@ -1478,6 +1478,11 @@ var init_DisplayTransforms = __esm({
|
|
|
1478
1478
|
}
|
|
1479
1479
|
/** Build a display pose for geometry already centered at the model's [8, 8, 8] pivot. */
|
|
1480
1480
|
static getMatrix(display, position) {
|
|
1481
|
+
const transform = this.getTransform(display, position);
|
|
1482
|
+
return new Matrix4().compose(transform.position, transform.quaternion, transform.scale);
|
|
1483
|
+
}
|
|
1484
|
+
/** Position, rotation, and scale of a display pose for geometry already centered at the model's [8, 8, 8] pivot. */
|
|
1485
|
+
static getTransform(display, position) {
|
|
1481
1486
|
const transform = this.withHandFallbacks(display)?.[position] ?? {};
|
|
1482
1487
|
const left = position === "firstperson_lefthand" /* FIRSTPERSON_LEFTHAND */ || position === "thirdperson_lefthand" /* THIRDPERSON_LEFTHAND */;
|
|
1483
1488
|
const sign = left ? -1 : 1;
|
|
@@ -1486,7 +1491,7 @@ var init_DisplayTransforms = __esm({
|
|
|
1486
1491
|
const translation = new Vector32(...transform.translation ?? [0, 0, 0]).clampScalar(-80, 80);
|
|
1487
1492
|
translation.x *= sign;
|
|
1488
1493
|
const scale = new Vector32(...transform.scale ?? [1, 1, 1]).clampScalar(-4, 4);
|
|
1489
|
-
return
|
|
1494
|
+
return { position: translation, quaternion: rotation, scale };
|
|
1490
1495
|
}
|
|
1491
1496
|
/** Transforms geometry in place and reverses triangle winding when the matrix reflects it. */
|
|
1492
1497
|
static apply(geometry, matrix) {
|
|
@@ -1671,6 +1676,7 @@ ${key}` : key, async () => {
|
|
|
1671
1676
|
if (!object(data)) return false;
|
|
1672
1677
|
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)));
|
|
1673
1678
|
if (dataset === "legacyBlocks") return object(data.blocks) && Object.values(data.blocks).every((value) => typeof value === "string");
|
|
1679
|
+
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")));
|
|
1674
1680
|
return Object.values(data).every((value) => {
|
|
1675
1681
|
if (!object(value)) return false;
|
|
1676
1682
|
switch (dataset) {
|
|
@@ -7014,16 +7020,21 @@ var init_ModelObject = __esm({
|
|
|
7014
7020
|
const special = this.originalModel.special;
|
|
7015
7021
|
if (special) {
|
|
7016
7022
|
const parts2 = await SpecialItems.getParts(special, this.originalModel.key?.root, this.originalModel.components);
|
|
7017
|
-
const
|
|
7018
|
-
|
|
7023
|
+
const display = new SceneObject();
|
|
7024
|
+
if (this.options.displayPosition) {
|
|
7025
|
+
const transform = DisplayTransforms.getTransform(this.originalModel.display, this.options.displayPosition);
|
|
7026
|
+
display.position.copy(transform.position);
|
|
7027
|
+
display.quaternion.copy(transform.quaternion);
|
|
7028
|
+
display.scale.copy(transform.scale);
|
|
7029
|
+
}
|
|
7030
|
+
this.add(display);
|
|
7031
|
+
const offset = new Matrix48().makeTranslation(-8, -8, -8);
|
|
7019
7032
|
try {
|
|
7020
7033
|
const targets = [];
|
|
7021
7034
|
for (const part of parts2) {
|
|
7022
7035
|
const object4 = new EntityObject(part.model, { flip: false, wireframe: this.options.wireframe, tints: part.tints, faces: part.faces });
|
|
7023
|
-
object4.matrix.
|
|
7024
|
-
object4
|
|
7025
|
-
object4.matrixAutoUpdate = false;
|
|
7026
|
-
this.add(object4);
|
|
7036
|
+
object4.matrix.multiplyMatrices(offset, part.transform).decompose(object4.position, object4.quaternion, object4.scale);
|
|
7037
|
+
display.add(object4);
|
|
7027
7038
|
await object4.init(part.material);
|
|
7028
7039
|
object4.iterateAllMeshes((mesh) => {
|
|
7029
7040
|
const source = mesh.material;
|
|
@@ -17626,6 +17637,38 @@ function sampleSectionLight(light, index) {
|
|
|
17626
17637
|
};
|
|
17627
17638
|
}
|
|
17628
17639
|
|
|
17640
|
+
// src/world/_culling/BlockCulling.ts
|
|
17641
|
+
init_Assets();
|
|
17642
|
+
init_MineRenderData();
|
|
17643
|
+
init_CubeFace();
|
|
17644
|
+
async function loadBlockCulling(root) {
|
|
17645
|
+
const { manifest } = await MineRenderData.resolve(root);
|
|
17646
|
+
return manifest.datasets.blockCulling ? MineRenderData.get("blockCulling", root) : void 0;
|
|
17647
|
+
}
|
|
17648
|
+
function blockCullingRule(data, type) {
|
|
17649
|
+
if (!type.includes(":")) type = `${DEFAULT_NAMESPACE}:${type}`;
|
|
17650
|
+
return Object.prototype.hasOwnProperty.call(data.blocks, type) ? data.profiles[data.blocks[type]] : void 0;
|
|
17651
|
+
}
|
|
17652
|
+
function skipsBlockFace(data, rule, block, neighbor, face) {
|
|
17653
|
+
const type = block.type.includes(":") ? block.type : `${DEFAULT_NAMESPACE}:${block.type}`;
|
|
17654
|
+
const other = neighbor.type.includes(":") ? neighbor.type : `${DEFAULT_NAMESPACE}:${neighbor.type}`;
|
|
17655
|
+
const same = type === other;
|
|
17656
|
+
const vertical = CUBE_FACES[face] === "up" /* UP */ || CUBE_FACES[face] === "down" /* DOWN */;
|
|
17657
|
+
switch (rule.type) {
|
|
17658
|
+
case "same_block":
|
|
17659
|
+
return same;
|
|
17660
|
+
case "same_block_vertical":
|
|
17661
|
+
return same && vertical;
|
|
17662
|
+
case "connected": {
|
|
17663
|
+
if (vertical) return same;
|
|
17664
|
+
const group = rule.group ? data.groups?.[rule.group] : void 0;
|
|
17665
|
+
return (same || !!group?.includes(type) && group.includes(other)) && String(block.properties?.[CUBE_FACES[face]]) === "true" && String(neighbor.properties?.[CUBE_FACES[face ^ 1]]) === "true";
|
|
17666
|
+
}
|
|
17667
|
+
default:
|
|
17668
|
+
return false;
|
|
17669
|
+
}
|
|
17670
|
+
}
|
|
17671
|
+
|
|
17629
17672
|
// src/world/MineRenderWorld.ts
|
|
17630
17673
|
var MineRenderWorld = class {
|
|
17631
17674
|
constructor(scene, options = {}) {
|
|
@@ -18014,15 +18057,23 @@ var MineRenderWorld = class {
|
|
|
18014
18057
|
return this.culling ?? (this.culling = Promise.resolve().then(async () => {
|
|
18015
18058
|
let sliceStart = performance.now();
|
|
18016
18059
|
try {
|
|
18060
|
+
const culling = await loadBlockCulling();
|
|
18017
18061
|
while (this.pendingCulling.size) {
|
|
18018
18062
|
const batch = [...this.pendingCulling];
|
|
18019
18063
|
this.pendingCulling.clear();
|
|
18020
18064
|
for (const [chunk, indices] of batch) {
|
|
18021
18065
|
const neighbors = CUBE_FACE_OFFSETS.map(([x, y, z]) => this._chunks.get(`${chunk.x + x}_${chunk.y + y}_${chunk.z + z}`));
|
|
18022
|
-
const
|
|
18066
|
+
const neighborAt = (x, y, z) => {
|
|
18023
18067
|
const lx = x - chunk.x * 16, ly = y - chunk.y * 16, lz = z - chunk.z * 16;
|
|
18024
18068
|
const section = neighbors[lx >= 16 ? 0 : lx < 0 ? 1 : ly >= 16 ? 2 : ly < 0 ? 3 : lz >= 16 ? 4 : 5];
|
|
18025
|
-
return section
|
|
18069
|
+
return [section, (ly & 15) * 256 + (lz & 15) * 16 + (lx & 15)];
|
|
18070
|
+
};
|
|
18071
|
+
const masks = chunk.updateCullMasks(indices === "all" ? void 0 : indices, (x, y, z) => {
|
|
18072
|
+
const [section, i] = neighborAt(x, y, z);
|
|
18073
|
+
return section?.isOccludingIndex(i) ?? false;
|
|
18074
|
+
}, culling, (x, y, z) => {
|
|
18075
|
+
const [section, i] = neighborAt(x, y, z);
|
|
18076
|
+
return section?.visibleBlockIndex(i);
|
|
18026
18077
|
});
|
|
18027
18078
|
const fluidIndices = indices === "all" ? function* () {
|
|
18028
18079
|
for (let index = 0; index < 4096; index++) yield index;
|
|
@@ -19137,6 +19188,10 @@ var Chunk = class _Chunk {
|
|
|
19137
19188
|
isBlockVisibleIndex(index) {
|
|
19138
19189
|
return this.renderedBlocks.has(index) && !this.hiddenBlocks.has(index);
|
|
19139
19190
|
}
|
|
19191
|
+
/** Stored state of a rendered, visible cell, or `undefined`. */
|
|
19192
|
+
visibleBlockIndex(index) {
|
|
19193
|
+
return this.isBlockVisibleIndex(index) ? this.data.stateAt(this.data.idAt(index)) : void 0;
|
|
19194
|
+
}
|
|
19140
19195
|
/** Fluid kind bits and level of a cell, or 0. Hidden cells report 0. */
|
|
19141
19196
|
fluidByteIndex(index) {
|
|
19142
19197
|
return this.hiddenBlocks.has(index) ? 0 : this.fluidCells[index];
|
|
@@ -19155,18 +19210,30 @@ var Chunk = class _Chunk {
|
|
|
19155
19210
|
async setCullMaskAt(pos, mask) {
|
|
19156
19211
|
await this.setCullMaskIndex(_Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos)), mask);
|
|
19157
19212
|
}
|
|
19158
|
-
/**
|
|
19159
|
-
|
|
19213
|
+
/**
|
|
19214
|
+
* Recomputes section masks and returns changed per-block masks. Omit indices to visit every cell.
|
|
19215
|
+
* `culling` supplies neighbor face rules; `blockAt` supplies visible states outside this chunk.
|
|
19216
|
+
*/
|
|
19217
|
+
updateCullMasks(indices, occludes, culling, blockAt) {
|
|
19160
19218
|
const changed = [];
|
|
19219
|
+
const rules = [];
|
|
19161
19220
|
for (const index of indices ?? this.fluidCells.keys()) {
|
|
19162
19221
|
if (!this.isBlockVisibleIndex(index)) continue;
|
|
19163
19222
|
const x = index % 16, y = Math.floor(index / 256), z = Math.floor(index / 16) % 16;
|
|
19223
|
+
const id = this.data.idAt(index);
|
|
19224
|
+
let rule = rules[id];
|
|
19225
|
+
if (culling && rule === void 0) rules[id] = rule = blockCullingRule(culling, this.data.stateAt(id).type) ?? null;
|
|
19226
|
+
const block = rule ? this.data.stateAt(id) : void 0;
|
|
19164
19227
|
let mask = 0;
|
|
19165
19228
|
for (let face = 0; face < CUBE_FACE_OFFSETS.length; face++) {
|
|
19166
19229
|
const [dx, dy, dz] = CUBE_FACE_OFFSETS[face];
|
|
19167
19230
|
const nx = x + dx, ny = y + dy, nz = z + dz;
|
|
19168
19231
|
const inner = nx >= 0 && nx < 16 && ny >= 0 && ny < 16 && nz >= 0 && nz < 16;
|
|
19169
19232
|
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;
|
|
19233
|
+
else if (rule) {
|
|
19234
|
+
const neighbor = inner ? this.visibleBlockIndex(ny * 256 + nz * 16 + nx) : blockAt?.(this.x * 16 + nx, this.y * 16 + ny, this.z * 16 + nz);
|
|
19235
|
+
if (neighbor && skipsBlockFace(culling, rule, block, neighbor, face)) mask |= 1 << face;
|
|
19236
|
+
}
|
|
19170
19237
|
}
|
|
19171
19238
|
if (this.fluidCells[index]) this.meshDirty = true;
|
|
19172
19239
|
const entries = this.sectionBlocks.get(index);
|