minerender 2.1.0-alpha.126 → 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/bundle.js CHANGED
@@ -43305,6 +43305,7 @@ ${key}` : key, async () => {
43305
43305
  if (!object(data)) return false;
43306
43306
  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)));
43307
43307
  if (dataset === "legacyBlocks") return object(data.blocks) && Object.values(data.blocks).every((value) => typeof value === "string");
43308
+ 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")));
43308
43309
  return Object.values(data).every((value) => {
43309
43310
  if (!object(value)) return false;
43310
43311
  switch (dataset) {
@@ -108033,6 +108034,41 @@ gl_FragDepth=readDepth(vUv);
108033
108034
  };
108034
108035
  }
108035
108036
 
108037
+ // src/world/_culling/BlockCulling.ts
108038
+ init_dirname();
108039
+ init_buffer2();
108040
+ init_process2();
108041
+ init_Assets();
108042
+ init_MineRenderData();
108043
+ init_CubeFace();
108044
+ async function loadBlockCulling(root) {
108045
+ const { manifest } = await MineRenderData.resolve(root);
108046
+ return manifest.datasets.blockCulling ? MineRenderData.get("blockCulling", root) : void 0;
108047
+ }
108048
+ function blockCullingRule(data, type) {
108049
+ if (!type.includes(":")) type = `${DEFAULT_NAMESPACE}:${type}`;
108050
+ return Object.prototype.hasOwnProperty.call(data.blocks, type) ? data.profiles[data.blocks[type]] : void 0;
108051
+ }
108052
+ function skipsBlockFace(data, rule, block, neighbor, face) {
108053
+ const type = block.type.includes(":") ? block.type : `${DEFAULT_NAMESPACE}:${block.type}`;
108054
+ const other = neighbor.type.includes(":") ? neighbor.type : `${DEFAULT_NAMESPACE}:${neighbor.type}`;
108055
+ const same = type === other;
108056
+ const vertical = CUBE_FACES[face] === "up" /* UP */ || CUBE_FACES[face] === "down" /* DOWN */;
108057
+ switch (rule.type) {
108058
+ case "same_block":
108059
+ return same;
108060
+ case "same_block_vertical":
108061
+ return same && vertical;
108062
+ case "connected": {
108063
+ if (vertical) return same;
108064
+ const group = rule.group ? data.groups?.[rule.group] : void 0;
108065
+ return (same || !!group?.includes(type) && group.includes(other)) && String(block.properties?.[CUBE_FACES[face]]) === "true" && String(neighbor.properties?.[CUBE_FACES[face ^ 1]]) === "true";
108066
+ }
108067
+ default:
108068
+ return false;
108069
+ }
108070
+ }
108071
+
108036
108072
  // src/world/MineRenderWorld.ts
108037
108073
  var MineRenderWorld = class {
108038
108074
  constructor(scene, options = {}) {
@@ -108421,15 +108457,23 @@ gl_FragDepth=readDepth(vUv);
108421
108457
  return this.culling ?? (this.culling = Promise.resolve().then(async () => {
108422
108458
  let sliceStart = performance.now();
108423
108459
  try {
108460
+ const culling = await loadBlockCulling();
108424
108461
  while (this.pendingCulling.size) {
108425
108462
  const batch = [...this.pendingCulling];
108426
108463
  this.pendingCulling.clear();
108427
108464
  for (const [chunk, indices] of batch) {
108428
108465
  const neighbors = CUBE_FACE_OFFSETS.map(([x4, y5, z4]) => this._chunks.get(`${chunk.x + x4}_${chunk.y + y5}_${chunk.z + z4}`));
108429
- const masks = chunk.updateCullMasks(indices === "all" ? void 0 : indices, (x4, y5, z4) => {
108466
+ const neighborAt = (x4, y5, z4) => {
108430
108467
  const lx = x4 - chunk.x * 16, ly = y5 - chunk.y * 16, lz = z4 - chunk.z * 16;
108431
108468
  const section = neighbors[lx >= 16 ? 0 : lx < 0 ? 1 : ly >= 16 ? 2 : ly < 0 ? 3 : lz >= 16 ? 4 : 5];
108432
- return section?.isOccludingIndex((ly & 15) * 256 + (lz & 15) * 16 + (lx & 15)) ?? false;
108469
+ return [section, (ly & 15) * 256 + (lz & 15) * 16 + (lx & 15)];
108470
+ };
108471
+ const masks = chunk.updateCullMasks(indices === "all" ? void 0 : indices, (x4, y5, z4) => {
108472
+ const [section, i4] = neighborAt(x4, y5, z4);
108473
+ return section?.isOccludingIndex(i4) ?? false;
108474
+ }, culling, (x4, y5, z4) => {
108475
+ const [section, i4] = neighborAt(x4, y5, z4);
108476
+ return section?.visibleBlockIndex(i4);
108433
108477
  });
108434
108478
  const fluidIndices = indices === "all" ? function* () {
108435
108479
  for (let index = 0; index < 4096; index++) yield index;
@@ -109559,6 +109603,10 @@ gl_FragDepth=readDepth(vUv);
109559
109603
  isBlockVisibleIndex(index) {
109560
109604
  return this.renderedBlocks.has(index) && !this.hiddenBlocks.has(index);
109561
109605
  }
109606
+ /** Stored state of a rendered, visible cell, or `undefined`. */
109607
+ visibleBlockIndex(index) {
109608
+ return this.isBlockVisibleIndex(index) ? this.data.stateAt(this.data.idAt(index)) : void 0;
109609
+ }
109562
109610
  /** Fluid kind bits and level of a cell, or 0. Hidden cells report 0. */
109563
109611
  fluidByteIndex(index) {
109564
109612
  return this.hiddenBlocks.has(index) ? 0 : this.fluidCells[index];
@@ -109577,18 +109625,30 @@ gl_FragDepth=readDepth(vUv);
109577
109625
  async setCullMaskAt(pos, mask) {
109578
109626
  await this.setCullMaskIndex(_Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos)), mask);
109579
109627
  }
109580
- /** Recomputes section masks and returns changed per-block masks. Omit indices to visit every cell. */
109581
- updateCullMasks(indices, occludes) {
109628
+ /**
109629
+ * Recomputes section masks and returns changed per-block masks. Omit indices to visit every cell.
109630
+ * `culling` supplies neighbor face rules; `blockAt` supplies visible states outside this chunk.
109631
+ */
109632
+ updateCullMasks(indices, occludes, culling, blockAt) {
109582
109633
  const changed = [];
109634
+ const rules = [];
109583
109635
  for (const index of indices ?? this.fluidCells.keys()) {
109584
109636
  if (!this.isBlockVisibleIndex(index)) continue;
109585
109637
  const x4 = index % 16, y5 = Math.floor(index / 256), z4 = Math.floor(index / 16) % 16;
109638
+ const id = this.data.idAt(index);
109639
+ let rule = rules[id];
109640
+ if (culling && rule === void 0) rules[id] = rule = blockCullingRule(culling, this.data.stateAt(id).type) ?? null;
109641
+ const block = rule ? this.data.stateAt(id) : void 0;
109586
109642
  let mask = 0;
109587
109643
  for (let face = 0; face < CUBE_FACE_OFFSETS.length; face++) {
109588
109644
  const [dx, dy, dz] = CUBE_FACE_OFFSETS[face];
109589
109645
  const nx = x4 + dx, ny = y5 + dy, nz = z4 + dz;
109590
109646
  const inner = nx >= 0 && nx < 16 && ny >= 0 && ny < 16 && nz >= 0 && nz < 16;
109591
109647
  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;
109648
+ else if (rule) {
109649
+ const neighbor = inner ? this.visibleBlockIndex(ny * 256 + nz * 16 + nx) : blockAt?.(this.x * 16 + nx, this.y * 16 + ny, this.z * 16 + nz);
109650
+ if (neighbor && skipsBlockFace(culling, rule, block, neighbor, face)) mask |= 1 << face;
109651
+ }
109592
109652
  }
109593
109653
  if (this.fluidCells[index]) this.meshDirty = true;
109594
109654
  const entries = this.sectionBlocks.get(index);