minecraft-renderer 0.1.79 → 0.1.81

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.
Files changed (205) hide show
  1. package/README.md +66 -26
  2. package/dist/mesher.js +36 -36
  3. package/dist/mesher.js.map +4 -4
  4. package/dist/mesherWasm.js +217 -217
  5. package/dist/minecraft-renderer.js +66 -66
  6. package/dist/minecraft-renderer.js.meta.json +1 -1
  7. package/dist/threeWorker.js +450 -450
  8. package/package.json +5 -2
  9. package/src/bundler/bundlePrepare.ts +3 -8
  10. package/src/graphicsBackend/appViewer.ts +10 -7
  11. package/src/graphicsBackend/config.ts +1 -5
  12. package/src/graphicsBackend/playerState.ts +35 -34
  13. package/src/graphicsBackend/preloadWorkers.ts +43 -41
  14. package/src/graphicsBackend/rendererDefaultOptions.ts +68 -70
  15. package/src/graphicsBackend/rendererOptionsSync.ts +24 -50
  16. package/src/graphicsBackend/types.ts +2 -2
  17. package/src/index.ts +6 -27
  18. package/src/lib/DebugGui.ts +34 -31
  19. package/src/lib/animationController.ts +9 -9
  20. package/src/lib/bakeLegacyLight.ts +1 -6
  21. package/src/lib/bindAbortableListener.test.ts +32 -12
  22. package/src/lib/bindAbortableListener.ts +14 -6
  23. package/src/lib/blockEntityLightRegistry.ts +11 -20
  24. package/src/lib/blockEntityLighting.test.ts +1 -6
  25. package/src/lib/blockEntityLighting.ts +5 -5
  26. package/src/lib/buildSharedConfig.mjs +4 -4
  27. package/src/lib/buildWorkerMcDataIndexes.test.ts +4 -4
  28. package/src/lib/buildWorkerMcDataIndexes.ts +11 -19
  29. package/src/lib/cameraBobbing.ts +1 -1
  30. package/src/lib/canvas2DOverlay.example.ts +13 -33
  31. package/src/lib/canvas2DOverlay.quickstart.ts +24 -54
  32. package/src/lib/canvas2DOverlay.ts +28 -47
  33. package/src/lib/cleanupDecorator.ts +2 -2
  34. package/src/lib/createPlayerObject.test.ts +2 -7
  35. package/src/lib/createPlayerObject.ts +18 -25
  36. package/src/lib/frameTimingCollector.ts +2 -5
  37. package/src/lib/guiRenderer.ts +57 -42
  38. package/src/lib/items.ts +15 -9
  39. package/src/lib/mesherlogReader.ts +5 -6
  40. package/src/lib/simpleUtils.ts +5 -5
  41. package/src/lib/skyLight.ts +3 -3
  42. package/src/lib/smoothSwitcher.ts +11 -18
  43. package/src/lib/ui/newStats.ts +10 -12
  44. package/src/lib/utils/proxy.ts +7 -1
  45. package/src/lib/utils/skins.ts +4 -4
  46. package/src/lib/utils.ts +1 -1
  47. package/src/lib/workerMessageSanitize.ts +5 -12
  48. package/src/lib/workerProxy.ts +52 -42
  49. package/src/lib/workerSyncOps.test.ts +58 -41
  50. package/src/lib/worldrendererCommon.reconfigure.test.ts +24 -21
  51. package/src/lib/worldrendererCommon.removeColumn.test.ts +11 -13
  52. package/src/lib/worldrendererCommon.ts +349 -211
  53. package/src/mesher-legacy/mesher.ts +9 -4
  54. package/src/mesher-legacy/test/a.ts +1 -1
  55. package/src/mesher-legacy/test/mesherTester.ts +2 -2
  56. package/src/mesher-legacy/test/playground.ts +1 -1
  57. package/src/mesher-legacy/test/run/test-js.ts +1 -1
  58. package/src/mesher-legacy/test/snapshotUtils.ts +3 -8
  59. package/src/mesher-legacy/test/test-perf.ts +1 -1
  60. package/src/mesher-legacy/test/tests.test.ts +2 -2
  61. package/src/mesher-shared/blockEntityMetadata.test.ts +7 -5
  62. package/src/mesher-shared/blockEntityMetadata.ts +28 -19
  63. package/src/mesher-shared/blockPropertiesForMeshing.ts +2 -2
  64. package/src/mesher-shared/computeHeightmap.ts +2 -4
  65. package/src/mesher-shared/exportedGeometryTypes.ts +3 -3
  66. package/src/mesher-shared/faceOcclusion.ts +324 -0
  67. package/src/mesher-shared/models.ts +80 -131
  68. package/src/mesher-shared/modelsGeometryCommon.ts +30 -15
  69. package/src/mesher-shared/shared.ts +46 -46
  70. package/src/mesher-shared/standaloneRenderer.ts +40 -44
  71. package/src/mesher-shared/tests/faceOcclusion.test.ts +179 -0
  72. package/src/mesher-shared/tests/liquidQuadInvariant.test.ts +12 -8
  73. package/src/mesher-shared/vertexShading.ts +2 -11
  74. package/src/mesher-shared/world.ts +19 -19
  75. package/src/mesher-shared/worldLighting.test.ts +2 -2
  76. package/src/performanceMonitor/PerformanceMonitor.ts +4 -13
  77. package/src/performanceMonitor/formatPerformanceFactorsDebug.ts +2 -2
  78. package/src/performanceMonitor/index.ts +1 -5
  79. package/src/performanceMonitor/types.ts +1 -1
  80. package/src/playerState/playerState.ts +55 -50
  81. package/src/playerState/types.ts +2 -8
  82. package/src/playground/allEntitiesDebug.ts +19 -16
  83. package/src/playground/baseScene.ts +29 -32
  84. package/src/playground/mobileControls.tsx +133 -129
  85. package/src/playground/playground.html +76 -73
  86. package/src/playground/playground.ts +14 -1
  87. package/src/playground/playgroundUi.tsx +100 -74
  88. package/src/playground/reactUtils.ts +3 -7
  89. package/src/playground/scenes/entities.ts +10 -7
  90. package/src/playground/scenes/frequentUpdates.ts +5 -5
  91. package/src/playground/scenes/geometryExport.ts +6 -20
  92. package/src/playground/scenes/highPosEntityUpdates.ts +2 -10
  93. package/src/playground/scenes/index.ts +1 -1
  94. package/src/playground/scenes/lightingStarfield.ts +18 -12
  95. package/src/playground/scenes/main.ts +15 -11
  96. package/src/playground/scenes/partialBlockCulling.ts +31 -0
  97. package/src/playground/scenes/railsCobweb.ts +1 -1
  98. package/src/playground/scenes/rotationIssue.ts +1 -1
  99. package/src/playground/scenes/slabsOptimization.ts +1 -2
  100. package/src/playground/scenes/transparencyIssue.ts +1 -1
  101. package/src/playground/shared.ts +2 -2
  102. package/src/resourcesManager/resourcesManager.ts +29 -54
  103. package/src/resourcesManager/resourcesManager.worker.test.ts +6 -10
  104. package/src/shims/minecraftData.ts +70 -24
  105. package/src/sign-renderer/index.html +10 -12
  106. package/src/sign-renderer/index.ts +29 -29
  107. package/src/sign-renderer/playground.ts +22 -15
  108. package/src/sign-renderer/tests.test.ts +16 -13
  109. package/src/sign-renderer/vite.config.ts +2 -2
  110. package/src/three/appShared.ts +46 -25
  111. package/src/three/bannerRenderer.ts +33 -61
  112. package/src/three/cameraCollisionBlockCache.ts +156 -0
  113. package/src/three/cameraCollisionSolidity.ts +50 -0
  114. package/src/three/cameraShake.ts +15 -6
  115. package/src/three/chunkMeshManager.ts +223 -390
  116. package/src/three/cinimaticScript.ts +26 -15
  117. package/src/three/cubeDrawSpans.ts +27 -37
  118. package/src/three/cubeMultiDraw.ts +9 -22
  119. package/src/three/documentRenderer.ts +15 -18
  120. package/src/three/entities.ts +175 -150
  121. package/src/three/entity/EntityMesh.ts +114 -108
  122. package/src/three/entity/animations.js +3 -3
  123. package/src/three/entity/armorModels.ts +15 -15
  124. package/src/three/entity/gltfAnimationUtils.ts +2 -5
  125. package/src/three/fireworks.ts +34 -32
  126. package/src/three/fireworksRenderer.ts +32 -29
  127. package/src/three/globalBlockBuffer.ts +167 -100
  128. package/src/three/globalLegacyBuffer.ts +248 -264
  129. package/src/three/graphicsBackendBase.ts +19 -25
  130. package/src/three/graphicsBackendOffThread.ts +12 -15
  131. package/src/three/hand.ts +21 -21
  132. package/src/three/handLegacy.ts +3 -13
  133. package/src/three/holdingBlock.ts +116 -79
  134. package/src/three/holdingBlockFactory.ts +1 -4
  135. package/src/three/holdingBlockItemIdentity.test.ts +25 -17
  136. package/src/three/holdingBlockItemIdentity.ts +9 -6
  137. package/src/three/holdingBlockLegacy.ts +113 -132
  138. package/src/three/itemMesh.ts +20 -29
  139. package/src/three/legacyMultiDraw.ts +10 -16
  140. package/src/three/legacySectionCull.ts +8 -14
  141. package/src/three/menuBackground/activeView.ts +1 -4
  142. package/src/three/menuBackground/assetUrl.ts +1 -1
  143. package/src/three/menuBackground/classic.ts +4 -12
  144. package/src/three/menuBackground/gpuPreference.ts +1 -3
  145. package/src/three/menuBackground/index.ts +2 -11
  146. package/src/three/menuBackground/renderer.ts +1 -5
  147. package/src/three/menuBackground/types.ts +1 -4
  148. package/src/three/menuBackground/v2.ts +196 -96
  149. package/src/three/menuBackground/v2Meta.ts +3 -3
  150. package/src/three/menuBackground/worldBlocks.ts +37 -35
  151. package/src/three/modules/blockBreakParticles.ts +59 -28
  152. package/src/three/modules/cameraBobbing.ts +3 -6
  153. package/src/three/modules/index.ts +1 -1
  154. package/src/three/modules/rain.ts +10 -23
  155. package/src/three/modules/sciFiWorldReveal.ts +11 -25
  156. package/src/three/modules/starfield.ts +7 -13
  157. package/src/three/renderSlot.ts +28 -16
  158. package/src/three/rendererModuleSystem.ts +1 -3
  159. package/src/three/sceneOrigin.ts +96 -33
  160. package/src/three/sectionRaycastAabb.ts +24 -110
  161. package/src/three/shaderCubeMesh.ts +6 -17
  162. package/src/three/shaders/cubeBlockShader.ts +85 -96
  163. package/src/three/shaders/legacyBlockShader.ts +21 -43
  164. package/src/three/shaders/textureIndexMapping.ts +89 -95
  165. package/src/three/shaders/tintPalette.ts +156 -170
  166. package/src/three/signTextureCache.ts +9 -12
  167. package/src/three/skyboxRenderer.ts +62 -70
  168. package/src/three/tests/chunkMeshManagerLegacy.test.ts +34 -64
  169. package/src/three/tests/cubeDrawSpans.test.ts +55 -25
  170. package/src/three/tests/globalBlockBuffer.test.ts +217 -0
  171. package/src/three/tests/globalLegacyBuffer.test.ts +300 -41
  172. package/src/three/tests/legacyMultiDraw.test.ts +8 -29
  173. package/src/three/tests/pr3PerFrameCpuCuts.test.ts +106 -29
  174. package/src/three/tests/signTextureCache.test.ts +4 -4
  175. package/src/three/thirdPersonVoxelRaycast.ts +120 -0
  176. package/src/three/threeJsMedia.ts +55 -72
  177. package/src/three/threeJsParticles.ts +32 -41
  178. package/src/three/threeJsSound.ts +3 -3
  179. package/src/three/threeJsUtils.ts +3 -3
  180. package/src/three/threeWorker.ts +2 -2
  181. package/src/three/waypointSprite.ts +55 -82
  182. package/src/three/waypoints.ts +20 -23
  183. package/src/three/world/cursorBlock.ts +25 -12
  184. package/src/three/world/vr.ts +11 -17
  185. package/src/three/worldGeometryExport.ts +15 -34
  186. package/src/three/worldRendererThree.ts +144 -166
  187. package/src/wasm-mesher/bridge/convertChunk.ts +3 -9
  188. package/src/wasm-mesher/bridge/render-from-wasm.ts +204 -229
  189. package/src/wasm-mesher/bridge/shaderCubeBridge.ts +26 -67
  190. package/src/wasm-mesher/tests/cameraCollisionBlockCache.test.ts +82 -0
  191. package/src/wasm-mesher/tests/cullingRegression.test.ts +307 -0
  192. package/src/wasm-mesher/tests/heightmapParity.test.ts +8 -18
  193. package/src/wasm-mesher/tests/mesherWasmConversionCache.test.ts +2 -2
  194. package/src/wasm-mesher/tests/sectionRaycastAabb.test.ts +1 -93
  195. package/src/wasm-mesher/tests/shaderCubeInstances.test.ts +103 -141
  196. package/src/wasm-mesher/tests/splitColumnWasmOutput.test.ts +14 -22
  197. package/src/wasm-mesher/tests/thirdPersonVoxelRaycast.test.ts +63 -0
  198. package/src/wasm-mesher/worker/mesherWasm.ts +150 -141
  199. package/src/wasm-mesher/worker/mesherWasmConversionCache.ts +2 -8
  200. package/src/wasm-mesher/worker/mesherWasmLightDirty.test.ts +1 -3
  201. package/src/wasm-mesher/worker/mesherWasmLightDirty.ts +1 -5
  202. package/src/wasm-mesher/worker/mesherWasmRequestTracker.ts +42 -42
  203. package/src/worldView/worldView.spiral.test.ts +1 -1
  204. package/src/worldView/worldView.ts +34 -39
  205. package/src/worldView/worldViewWorkerBridge.test.ts +4 -4
@@ -10,12 +10,13 @@ import { INVISIBLE_BLOCKS } from './worldConstants'
10
10
  import { MesherGeometryOutput, HighestBlockInfo } from './shared'
11
11
  import { collectBlockEntityMetadata } from './blockEntityMetadata'
12
12
  import { preflatBlockCalculation, resolveBlockPropertiesForMeshing } from './blockPropertiesForMeshing'
13
+ import { faceIsCulled, roundCardinalDir } from './faceOcclusion'
13
14
 
14
15
  export { preflatBlockCalculation, resolveBlockPropertiesForMeshing } from './blockPropertiesForMeshing'
15
16
 
16
17
  // Log function disabled by default for zero overhead in production hot loops
17
18
  const ENABLE_TS_LOGS = false
18
- const tsLog = ENABLE_TS_LOGS ? console.log : () => { }
19
+ const tsLog = ENABLE_TS_LOGS ? console.log : () => {}
19
20
 
20
21
  let blockProvider: WorldBlockProvider
21
22
 
@@ -35,12 +36,12 @@ export type MesherGeometryBucket = {
35
36
  indicesCount: number
36
37
  }
37
38
 
38
- function vertexTintAoColor (
39
+ function vertexTintAoColor(
39
40
  tint: [number, number, number],
40
41
  ao: number,
41
42
  faceDir: [number, number, number],
42
43
  shadingTheme: 'vanilla' | 'high-contrast',
43
- cardinalLight: string,
44
+ cardinalLight: string
44
45
  ): [number, number, number] {
45
46
  const sideShading = getSideShading(faceDir, shadingTheme, cardinalLight)
46
47
  if (shadingTheme === 'high-contrast') {
@@ -51,7 +52,7 @@ function vertexTintAoColor (
51
52
  return [tint[0] * f, tint[1] * f, tint[2] * f]
52
53
  }
53
54
 
54
- export function isSemiTransparentBlockName (name: string): boolean {
55
+ export function isSemiTransparentBlockName(name: string): boolean {
55
56
  return semiTransparentBlocks.includes(name)
56
57
  }
57
58
 
@@ -95,7 +96,8 @@ function tintToGl(tint) {
95
96
  function getLiquidRenderHeight(world: World, block: WorldBlock | null, type: number, pos: Vec3, isWater: boolean, isRealWater: boolean) {
96
97
  if ((isWater && !isRealWater) || (block && isBlockWaterlogged(block))) return 8 / 9
97
98
  if (!block || block.type !== type) return 1 / 9
98
- if (block.metadata === 0) { // source block
99
+ if (block.metadata === 0) {
100
+ // source block
99
101
  const blockAbove = world.getBlock(pos.offset(0, 1, 0))
100
102
  if (blockAbove && blockAbove.type === type) return 1
101
103
  return 8 / 9
@@ -103,15 +105,16 @@ function getLiquidRenderHeight(world: World, block: WorldBlock | null, type: num
103
105
  return ((block.metadata >= 8 ? 8 : 7 - block.metadata) + 1) / 9
104
106
  }
105
107
 
106
-
107
108
  const isCube = (block: Block) => {
108
109
  if (!block || block.transparent) return false
109
110
  if (block.isCube) return true
110
111
  if (!block.models?.length || block.models.length !== 1) return false
111
112
  // all variants
112
- return block.models[0].every(v => v.elements.every(e => {
113
- return e.from[0] === 0 && e.from[1] === 0 && e.from[2] === 0 && e.to[0] === 16 && e.to[1] === 16 && e.to[2] === 16
114
- }))
113
+ return block.models[0].every(v =>
114
+ v.elements.every(e => {
115
+ return e.from[0] === 0 && e.from[1] === 0 && e.from[2] === 0 && e.to[0] === 16 && e.to[1] === 16 && e.to[2] === 16
116
+ })
117
+ )
115
118
  }
116
119
 
117
120
  const getVec = (v: Vec3, dir: Vec3) => {
@@ -121,7 +124,17 @@ const getVec = (v: Vec3, dir: Vec3) => {
121
124
  return v.plus(dir)
122
125
  }
123
126
 
124
- function renderLiquid(world: World, cursor: Vec3, texture: any | undefined, type: number, biome: string, water: boolean, bucket: MesherGeometryBucket, attr: MesherGeometryOutput, isRealWater: boolean) {
127
+ function renderLiquid(
128
+ world: World,
129
+ cursor: Vec3,
130
+ texture: any | undefined,
131
+ type: number,
132
+ biome: string,
133
+ water: boolean,
134
+ bucket: MesherGeometryBucket,
135
+ attr: MesherGeometryOutput,
136
+ isRealWater: boolean
137
+ ) {
125
138
  const heights: number[] = []
126
139
  for (let z = -1; z <= 1; z++) {
127
140
  for (let x = -1; x <= 1; x++) {
@@ -141,7 +154,7 @@ function renderLiquid(world: World, cursor: Vec3, texture: any | undefined, type
141
154
  const { dir, corners, mask1, mask2 } = elemFaces[face]
142
155
  const isUp = dir[1] === 1
143
156
 
144
- const neighborPos = cursor.offset(...dir as [number, number, number])
157
+ const neighborPos = cursor.offset(...(dir as [number, number, number]))
145
158
  const neighbor = world.getBlock(neighborPos)
146
159
  if (!neighbor) continue
147
160
  if (neighbor.type === type || (water && (neighbor.name === 'water' || isBlockWaterlogged(neighbor)))) continue
@@ -160,13 +173,13 @@ function renderLiquid(world: World, cursor: Vec3, texture: any | undefined, type
160
173
  const tiles = attr.tiles as Tiles
161
174
  tiles[`${cursor.x},${cursor.y},${cursor.z}`] ??= {
162
175
  block: 'water',
163
- faces: [],
176
+ faces: []
164
177
  }
165
178
  tiles[`${cursor.x},${cursor.y},${cursor.z}`].faces.push({
166
179
  face,
167
180
  neighbor: `${neighborPos.x},${neighborPos.y},${neighborPos.z}`,
168
181
  side: 0, // todo
169
- textureIndex: 0,
182
+ textureIndex: 0
170
183
  // texture: eFace.texture.name,
171
184
  })
172
185
  }
@@ -201,7 +214,7 @@ function renderLiquid(world: World, cursor: Vec3, texture: any | undefined, type
201
214
  const side1Dir: [number, number, number] = [dx * mask1[0], dy * mask1[1], dz * mask1[2]]
202
215
  const side2Dir: [number, number, number] = [dx * mask2[0], dy * mask2[1], dz * mask2[2]]
203
216
 
204
- const dirVec = new Vec3(...dir as [number, number, number])
217
+ const dirVec = new Vec3(...(dir as [number, number, number]))
205
218
 
206
219
  const side1LightDir = getVec(new Vec3(...side1Dir), dirVec)
207
220
  const side2DirLight = getVec(new Vec3(...side2Dir), dirVec)
@@ -249,65 +262,36 @@ function renderLiquid(world: World, cursor: Vec3, texture: any | undefined, type
249
262
  }
250
263
  }
251
264
 
252
- const identicalCull = (currentElement: BlockElement, neighbor: Block, direction: Vec3) => {
253
- const dirStr = `${direction.x},${direction.y},${direction.z}`
254
- const lookForOppositeSide = {
255
- '0,1,0': 'down',
256
- '0,-1,0': 'up',
257
- '1,0,0': 'east',
258
- '-1,0,0': 'west',
259
- '0,0,1': 'south',
260
- '0,0,-1': 'north',
261
- }[dirStr]!
262
- const elemCompareForm = {
263
- '0,1,0': (e: BlockElement) => `${e.from[0]},${e.from[2]}:${e.to[0]},${e.to[2]}`,
264
- '0,-1,0': (e: BlockElement) => `${e.to[0]},${e.to[2]}:${e.from[0]},${e.from[2]}`,
265
- '1,0,0': (e: BlockElement) => `${e.from[2]},${e.from[1]}:${e.to[2]},${e.to[1]}`,
266
- '-1,0,0': (e: BlockElement) => `${e.to[2]},${e.to[1]}:${e.from[2]},${e.from[1]}`,
267
- '0,0,1': (e: BlockElement) => `${e.from[1]},${e.from[2]}:${e.to[1]},${e.to[2]}`,
268
- '0,0,-1': (e: BlockElement) => `${e.to[1]},${e.to[2]}:${e.from[1]},${e.from[2]}`,
269
- }[dirStr]!
270
- const elementEdgeValidator = {
271
- '0,1,0': (e: BlockElement) => currentElement.from[1] === 0 && e.to[2] === 16,
272
- '0,-1,0': (e: BlockElement) => currentElement.from[1] === 0 && e.to[2] === 16,
273
- '1,0,0': (e: BlockElement) => currentElement.from[0] === 0 && e.to[1] === 16,
274
- '-1,0,0': (e: BlockElement) => currentElement.from[0] === 0 && e.to[1] === 16,
275
- '0,0,1': (e: BlockElement) => currentElement.from[2] === 0 && e.to[0] === 16,
276
- '0,0,-1': (e: BlockElement) => currentElement.from[2] === 0 && e.to[0] === 16,
277
- }[dirStr]!
278
- const useVar = 0
279
- const models = neighbor.models?.map(m => m[useVar] ?? m[0]) ?? []
280
- // TODO we should support it! rewrite with optimizing general pipeline
281
- if (models.some(m => m.x || m.y || m.z)) return
282
- return models.every(model => {
283
- return (model.elements ?? []).every(element => {
284
- // todo check alfa on texture
285
- return !!(element.faces[lookForOppositeSide]?.cullface && elemCompareForm(currentElement) === elemCompareForm(element) && elementEdgeValidator(element))
286
- })
287
- })
288
- }
289
-
290
265
  let needSectionRecomputeOnChange = false
291
266
 
292
- function renderElement(world: World, cursor: Vec3, element: BlockElement, doAO: boolean, bucket: MesherGeometryBucket, attr: MesherGeometryOutput, globalMatrix: any, globalShift: any, block: Block, biome: string) {
267
+ function renderElement(
268
+ world: World,
269
+ cursor: Vec3,
270
+ element: BlockElement,
271
+ doAO: boolean,
272
+ bucket: MesherGeometryBucket,
273
+ attr: MesherGeometryOutput,
274
+ globalMatrix: any,
275
+ globalShift: any,
276
+ block: Block,
277
+ biome: string
278
+ ) {
293
279
  const position = cursor
294
280
  // const key = `${position.x},${position.y},${position.z}`
295
281
  // if (!globalThis.allowedBlocks.includes(key)) return
296
- const cullIfIdentical = block.name.includes('glass') || block.name.includes('ice')
297
-
298
282
  // eslint-disable-next-line guard-for-in
299
283
  for (const face in element.faces) {
300
284
  const eFace = element.faces[face]
301
285
  const { corners, mask1, mask2, side } = elemFaces[face]
302
286
  const dir = matmul3(globalMatrix, elemFaces[face].dir)
287
+ const worldDir = roundCardinalDir(dir)
303
288
 
304
- tsLog(`[TS] Processing face ${face} at (${cursor.x}, ${cursor.y}, ${cursor.z}), dir=[${dir.join(',')}]`)
289
+ tsLog(`[TS] Processing face ${face} at (${cursor.x}, ${cursor.y}, ${cursor.z}), dir=[${worldDir.join(',')}]`)
305
290
 
306
291
  if (eFace.cullface) {
307
- const neighbor = world.getBlock(cursor.plus(new Vec3(...dir)), blockProvider, {})
292
+ const neighbor = world.getBlock(cursor.plus(new Vec3(...worldDir)), blockProvider, {})
308
293
  if (neighbor) {
309
- if (cullIfIdentical && neighbor.stateId === block.stateId) continue
310
- if (!neighbor.transparent && (isCube(neighbor) || identicalCull(element, neighbor, new Vec3(...dir)))) continue
294
+ if (faceIsCulled(world.config.version, element, face, neighbor.stateId, block, blockProvider, worldDir, globalMatrix)) continue
311
295
  } else {
312
296
  needSectionRecomputeOnChange = true
313
297
  // continue
@@ -336,9 +320,7 @@ function renderElement(world: World, cursor: Vec3, element: BlockElement, doAO:
336
320
  if (eFace.tintindex === 0) {
337
321
  if (block.name === 'redstone_wire') {
338
322
  tint = tints.redstone[`${block.getProperties().power}`]
339
- } else if (block.name === 'birch_leaves' ||
340
- block.name === 'spruce_leaves' ||
341
- block.name === 'lily_pad') {
323
+ } else if (block.name === 'birch_leaves' || block.name === 'spruce_leaves' || block.name === 'lily_pad') {
342
324
  tint = tints.constant[block.name]
343
325
  } else if (block.name.includes('leaves') || block.name === 'vine') {
344
326
  tint = tints.foliage[biome]
@@ -353,31 +335,22 @@ function renderElement(world: World, cursor: Vec3, element: BlockElement, doAO:
353
335
  if (face === 'down') {
354
336
  r += 180
355
337
  }
356
- const uvcs = Math.cos(r * Math.PI / 180)
357
- const uvsn = -Math.sin(r * Math.PI / 180)
338
+ const uvcs = Math.cos((r * Math.PI) / 180)
339
+ const uvsn = -Math.sin((r * Math.PI) / 180)
358
340
 
359
341
  let localMatrix = null as any
360
342
  let localShift = null as any
361
343
 
362
344
  if (element.rotation && !needTiles) {
363
345
  // Rescale support for block model rotations
364
- localMatrix = buildRotationMatrix(
365
- element.rotation.axis,
366
- element.rotation.angle
367
- )
346
+ localMatrix = buildRotationMatrix(element.rotation.axis, element.rotation.angle)
368
347
 
369
- localShift = vecsub3(
370
- element.rotation.origin,
371
- matmul3(
372
- localMatrix,
373
- element.rotation.origin
374
- )
375
- )
348
+ localShift = vecsub3(element.rotation.origin, matmul3(localMatrix, element.rotation.origin))
376
349
 
377
350
  // Apply rescale if specified
378
351
  if (element.rotation.rescale) {
379
352
  const FIT_TO_BLOCK_SCALE_MULTIPLIER = 2 - Math.sqrt(2)
380
- const angleRad = element.rotation.angle * Math.PI / 180
353
+ const angleRad = (element.rotation.angle * Math.PI) / 180
381
354
  const scale = Math.abs(Math.sin(angleRad)) * FIT_TO_BLOCK_SCALE_MULTIPLIER
382
355
 
383
356
  // Get axis vector components (1 for the rotation axis, 0 for others)
@@ -396,13 +369,7 @@ function renderElement(world: World, cursor: Vec3, element: BlockElement, doAO:
396
369
  localMatrix = matmulmat3(localMatrix, scaleMatrix)
397
370
 
398
371
  // Recalculate shift with the new matrix
399
- localShift = vecsub3(
400
- element.rotation.origin,
401
- matmul3(
402
- localMatrix,
403
- element.rotation.origin
404
- )
405
- )
372
+ localShift = vecsub3(element.rotation.origin, matmul3(localMatrix, element.rotation.origin))
406
373
  }
407
374
  }
408
375
 
@@ -412,22 +379,15 @@ function renderElement(world: World, cursor: Vec3, element: BlockElement, doAO:
412
379
  const baseChannels = world.getChannelLightNorm(neighborPos)
413
380
  const faceDir = dir as [number, number, number]
414
381
  for (const pos of corners) {
415
- let vertex = [
416
- (pos[0] ? maxx : minx),
417
- (pos[1] ? maxy : miny),
418
- (pos[2] ? maxz : minz)
419
- ]
382
+ let vertex = [pos[0] ? maxx : minx, pos[1] ? maxy : miny, pos[2] ? maxz : minz]
420
383
 
421
- if (!needTiles) { // 10%
384
+ if (!needTiles) {
385
+ // 10%
422
386
  vertex = vecadd3(matmul3(localMatrix, vertex), localShift)
423
387
  vertex = vecadd3(matmul3(globalMatrix, vertex), globalShift)
424
388
  vertex = vertex.map(v => v / 16)
425
389
 
426
- const worldPos = [
427
- vertex[0] + (cursor.x & 15) - 8,
428
- vertex[1] + (cursor.y & 15) - 8,
429
- vertex[2] + (cursor.z & 15) - 8
430
- ]
390
+ const worldPos = [vertex[0] + (cursor.x & 15) - 8, vertex[1] + (cursor.y & 15) - 8, vertex[2] + (cursor.z & 15) - 8]
431
391
 
432
392
  tsLog(`[TS] Corner ${pos.join(',')}: vertex=[${vertex.map(v => v.toFixed(3)).join(',')}], worldPos=[${worldPos.map(v => v.toFixed(3)).join(',')}]`)
433
393
 
@@ -439,7 +399,9 @@ function renderElement(world: World, cursor: Vec3, element: BlockElement, doAO:
439
399
  const basev = (pos[3] - 0.5) * uvsn + (pos[4] - 0.5) * uvcs + 0.5
440
400
  const finalU = baseu * su + u
441
401
  const finalV = basev * sv + v
442
- tsLog(`[TS] UV: cornerUV=[${pos[3]},${pos[4]}], baseUV=[${baseu.toFixed(6)},${basev.toFixed(6)}], finalUV=[${finalU.toFixed(6)},${finalV.toFixed(6)}], texture=[u=${u},v=${v},su=${su},sv=${sv}], rotation=${r}`)
402
+ tsLog(
403
+ `[TS] UV: cornerUV=[${pos[3]},${pos[4]}], baseUV=[${baseu.toFixed(6)},${basev.toFixed(6)}], finalUV=[${finalU.toFixed(6)},${finalV.toFixed(6)}], texture=[u=${u},v=${v},su=${su},sv=${sv}], rotation=${r}`
404
+ )
443
405
  bucket.uvs.push(finalU, finalV)
444
406
  }
445
407
 
@@ -479,7 +441,7 @@ function renderElement(world: World, cursor: Vec3, element: BlockElement, doAO:
479
441
  const side2Block = world.shouldMakeAo(side2) ? 1 : 0
480
442
  const cornerBlock = world.shouldMakeAo(corner) ? 1 : 0
481
443
 
482
- ao = (side1Block && side2Block) ? 0 : (3 - (side1Block + side2Block + cornerBlock))
444
+ ao = side1Block && side2Block ? 0 : 3 - (side1Block + side2Block + cornerBlock)
483
445
  aos.push(ao)
484
446
 
485
447
  const cornerIdx = aos.length - 1
@@ -500,7 +462,7 @@ function renderElement(world: World, cursor: Vec3, element: BlockElement, doAO:
500
462
  const tiles = attr.tiles as Tiles
501
463
  tiles[`${cursor.x},${cursor.y},${cursor.z}`] ??= {
502
464
  block: block.name,
503
- faces: [],
465
+ faces: []
504
466
  }
505
467
  const needsOnlyOneFace = false
506
468
  const isTilesEmpty = tiles[`${cursor.x},${cursor.y},${cursor.z}`].faces.length < 1
@@ -513,7 +475,7 @@ function renderElement(world: World, cursor: Vec3, element: BlockElement, doAO:
513
475
  light: Math.max(baseChannels.block, baseChannels.sky),
514
476
  tint: lightWithColor,
515
477
  //@ts-expect-error debug prop
516
- texture: eFace.texture.debugName || block.name,
478
+ texture: eFace.texture.debugName || block.name
517
479
  } satisfies BlockType['faces'][number])
518
480
  }
519
481
  }
@@ -545,13 +507,7 @@ function renderElement(world: World, cursor: Vec3, element: BlockElement, doAO:
545
507
  }
546
508
  }
547
509
 
548
- const ALWAYS_WATERLOGGED = new Set([
549
- 'seagrass',
550
- 'tall_seagrass',
551
- 'kelp',
552
- 'kelp_plant',
553
- 'bubble_column'
554
- ])
510
+ const ALWAYS_WATERLOGGED = new Set(['seagrass', 'tall_seagrass', 'kelp', 'kelp_plant', 'bubble_column'])
555
511
  const isBlockWaterlogged = (block: Block) => {
556
512
  return block.getProperties().waterlogged === true || block.getProperties().waterlogged === 'true' || ALWAYS_WATERLOGGED.has(block.name)
557
513
  }
@@ -599,7 +555,7 @@ export function getSectionGeometry(sx: number, sy: number, sz: number, world: Wo
599
555
  blockLights: attr.blockLights as number[],
600
556
  uvs: attr.uvs as number[],
601
557
  indices: attr.indices as number[],
602
- indicesCount: attr.indicesCount,
558
+ indicesCount: attr.indicesCount
603
559
  }
604
560
  const blendBucket: MesherGeometryBucket = {
605
561
  positions: [],
@@ -609,7 +565,7 @@ export function getSectionGeometry(sx: number, sy: number, sz: number, world: Wo
609
565
  blockLights: [],
610
566
  uvs: [],
611
567
  indices: [],
612
- indicesCount: 0,
568
+ indicesCount: 0
613
569
  }
614
570
 
615
571
  const cursor = new Vec3(0, 0, 0)
@@ -621,7 +577,8 @@ export function getSectionGeometry(sx: number, sy: number, sz: number, world: Wo
621
577
  collectBlockEntityMetadata(block, cursor.x, cursor.y, cursor.z, attr, { disableBlockEntityTextures: world.config.disableBlockEntityTextures }, world)
622
578
  const biome = block.biome.name
623
579
 
624
- if (world.preflat) { // 10% perf
580
+ if (world.preflat) {
581
+ // 10% perf
625
582
  const patchProperties = preflatBlockCalculation(block, world, cursor)
626
583
  if (patchProperties) {
627
584
  block._originalProperties ??= block._properties
@@ -673,9 +630,9 @@ export function getSectionGeometry(sx: number, sy: number, sz: number, world: Wo
673
630
  let globalShift = null as any
674
631
  for (const axis of ['x', 'y', 'z'] as const) {
675
632
  if (axis in model) {
676
- globalMatrix = globalMatrix ?
677
- matmulmat3(globalMatrix, buildRotationMatrix(axis, -(model[axis] ?? 0))) :
678
- buildRotationMatrix(axis, -(model[axis] ?? 0))
633
+ globalMatrix = globalMatrix
634
+ ? matmulmat3(globalMatrix, buildRotationMatrix(axis, -(model[axis] ?? 0)))
635
+ : buildRotationMatrix(axis, -(model[axis] ?? 0))
679
636
  }
680
637
  }
681
638
  if (globalMatrix) {
@@ -732,9 +689,7 @@ export function getSectionGeometry(sx: number, sy: number, sz: number, world: Wo
732
689
  skyLights: new Float32Array(blendBucket.skyLights),
733
690
  blockLights: new Float32Array(blendBucket.blockLights),
734
691
  uvs: new Float32Array(blendBucket.uvs),
735
- indices: blendUsing32
736
- ? new Uint32Array(blendBucket.indices)
737
- : new Uint16Array(blendBucket.indices),
692
+ indices: blendUsing32 ? new Uint32Array(blendBucket.indices) : new Uint16Array(blendBucket.indices)
738
693
  }
739
694
  }
740
695
 
@@ -758,20 +713,23 @@ export function getSectionGeometry(sx: number, sy: number, sz: number, world: Wo
758
713
 
759
714
  // copied from three.js
760
715
  function arrayNeedsUint32(array) {
761
-
762
716
  // assumes larger values usually on last
763
717
 
764
718
  for (let i = array.length - 1; i >= 0; --i) {
765
-
766
719
  if (array[i] >= 65_535) return true // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
767
-
768
720
  }
769
721
 
770
722
  return false
771
-
772
723
  }
773
724
 
774
- export const setBlockStatesData = (blockstatesModels, blocksAtlas: any, _needTiles = false, useUnknownBlockModel = true, version = 'latest', mcData = (globalThis as any).mcData) => {
725
+ export const setBlockStatesData = (
726
+ blockstatesModels,
727
+ blocksAtlas: any,
728
+ _needTiles = false,
729
+ useUnknownBlockModel = true,
730
+ version = 'latest',
731
+ mcData = (globalThis as any).mcData
732
+ ) => {
775
733
  blockProvider = worldBlockProvider(blockstatesModels, blocksAtlas, version)
776
734
  globalThis.blockProvider = blockProvider
777
735
  if (useUnknownBlockModel) {
@@ -807,7 +765,7 @@ export const setBlockStatesData = (blockstatesModels, blocksAtlas: any, _needTil
807
765
 
808
766
  export function computeWireframeEdgesJS(positions: Float32Array | number[], indices: Uint32Array | Uint16Array | number[]): Float32Array {
809
767
  const pos = positions instanceof Float32Array ? positions : new Float32Array(positions as number[])
810
- const idx = indices instanceof Uint32Array ? indices : (indices instanceof Uint16Array ? new Uint32Array(indices) : new Uint32Array(indices as number[]))
768
+ const idx = indices instanceof Uint32Array ? indices : indices instanceof Uint16Array ? new Uint32Array(indices) : new Uint32Array(indices as number[])
811
769
 
812
770
  const linePositions: number[] = []
813
771
  const edgeSet = new Set<number>()
@@ -825,13 +783,7 @@ export function computeWireframeEdgesJS(positions: Float32Array | number[], indi
825
783
  return new Float32Array(linePositions)
826
784
  }
827
785
 
828
- function addEdgeJS(
829
- positions: Float32Array,
830
- i0: number,
831
- i1: number,
832
- linePositions: number[],
833
- edgeSet: Set<number>
834
- ): void {
786
+ function addEdgeJS(positions: Float32Array, i0: number, i1: number, linePositions: number[], edgeSet: Set<number>): void {
835
787
  const minI = i0 < i1 ? i0 : i1
836
788
  const maxI = i0 < i1 ? i1 : i0
837
789
  // Pack two indices into a single number (safe while indices < 2^24 — far above per-section vertex counts).
@@ -840,8 +792,5 @@ function addEdgeJS(
840
792
  if (edgeSet.has(key)) return
841
793
  edgeSet.add(key)
842
794
 
843
- linePositions.push(
844
- positions[i0 * 3]!, positions[i0 * 3 + 1]!, positions[i0 * 3 + 2]!,
845
- positions[i1 * 3]!, positions[i1 * 3 + 1]!, positions[i1 * 3 + 2]!
846
- )
795
+ linePositions.push(positions[i0 * 3]!, positions[i0 * 3 + 1]!, positions[i0 * 3 + 2]!, positions[i1 * 3]!, positions[i1 * 3 + 1]!, positions[i1 * 3 + 2]!)
847
796
  }
@@ -3,9 +3,8 @@ import { BlockModelPartsResolved } from './world'
3
3
 
4
4
  export type BlockElement = NonNullable<BlockModelPartsResolved[0][0]['elements']>[0]
5
5
 
6
-
7
- export function buildRotationMatrix (axis, degree) {
8
- const radians = degree / 180 * Math.PI
6
+ export function buildRotationMatrix(axis, degree) {
7
+ const radians = (degree / 180) * Math.PI
9
8
  const cos = Math.cos(radians)
10
9
  const sin = Math.sin(radians)
11
10
 
@@ -28,17 +27,17 @@ export function buildRotationMatrix (axis, degree) {
28
27
  return matrix
29
28
  }
30
29
 
31
- export function vecadd3 (a, b) {
30
+ export function vecadd3(a, b) {
32
31
  if (!b) return a
33
32
  return [a[0] + b[0], a[1] + b[1], a[2] + b[2]]
34
33
  }
35
34
 
36
- export function vecsub3 (a, b) {
35
+ export function vecsub3(a, b) {
37
36
  if (!b) return a
38
37
  return [a[0] - b[0], a[1] - b[1], a[2] - b[2]]
39
38
  }
40
39
 
41
- export function matmul3 (matrix, vector): [number, number, number] {
40
+ export function matmul3(matrix, vector): [number, number, number] {
42
41
  if (!matrix) return vector
43
42
  return [
44
43
  matrix[0][0] * vector[0] + matrix[0][1] * vector[1] + matrix[0][2] * vector[2],
@@ -47,16 +46,32 @@ export function matmul3 (matrix, vector): [number, number, number] {
47
46
  ]
48
47
  }
49
48
 
50
- export function matmulmat3 (a, b) {
51
- const te = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
52
-
53
- const a11 = a[0][0]; const a12 = a[1][0]; const a13 = a[2][0]
54
- const a21 = a[0][1]; const a22 = a[1][1]; const a23 = a[2][1]
55
- const a31 = a[0][2]; const a32 = a[1][2]; const a33 = a[2][2]
49
+ export function matmulmat3(a, b) {
50
+ const te = [
51
+ [0, 0, 0],
52
+ [0, 0, 0],
53
+ [0, 0, 0]
54
+ ]
56
55
 
57
- const b11 = b[0][0]; const b12 = b[1][0]; const b13 = b[2][0]
58
- const b21 = b[0][1]; const b22 = b[1][1]; const b23 = b[2][1]
59
- const b31 = b[0][2]; const b32 = b[1][2]; const b33 = b[2][2]
56
+ const a11 = a[0][0]
57
+ const a12 = a[1][0]
58
+ const a13 = a[2][0]
59
+ const a21 = a[0][1]
60
+ const a22 = a[1][1]
61
+ const a23 = a[2][1]
62
+ const a31 = a[0][2]
63
+ const a32 = a[1][2]
64
+ const a33 = a[2][2]
65
+
66
+ const b11 = b[0][0]
67
+ const b12 = b[1][0]
68
+ const b13 = b[2][0]
69
+ const b21 = b[0][1]
70
+ const b22 = b[1][1]
71
+ const b23 = b[2][1]
72
+ const b31 = b[0][2]
73
+ const b32 = b[1][2]
74
+ const b33 = b[2][2]
60
75
 
61
76
  te[0][0] = a11 * b11 + a12 * b21 + a13 * b31
62
77
  te[1][0] = a11 * b12 + a12 * b22 + a13 * b32
@@ -21,7 +21,7 @@ export const defaultMesherConfig = {
21
21
  disableConversionCache: false,
22
22
  computeWireframeEdges: false,
23
23
  /** Pack eligible full-cube faces as GPU-instanced shader words during WASM post-processing. */
24
- shaderCubeBlocks: false,
24
+ shaderCubeBlocks: false
25
25
  }
26
26
 
27
27
  export type CustomBlockModels = {
@@ -42,35 +42,35 @@ export type MesherGeometryBucketData = {
42
42
  }
43
43
 
44
44
  export type MesherGeometryOutput = {
45
- sectionYNumber: number,
46
- chunkKey: string,
47
- sectionStartY: number,
48
- sectionEndY: number,
49
- sectionStartX: number,
50
- sectionEndX: number,
51
- sectionStartZ: number,
52
- sectionEndZ: number,
45
+ sectionYNumber: number
46
+ chunkKey: string
47
+ sectionStartY: number
48
+ sectionEndY: number
49
+ sectionStartX: number
50
+ sectionEndX: number
51
+ sectionStartZ: number
52
+ sectionEndZ: number
53
53
  // three.js
54
- sx: number,
55
- sy: number,
56
- sz: number,
54
+ sx: number
55
+ sy: number
56
+ sz: number
57
57
  // resulting: float32array
58
- positions: any,
59
- normals: any,
60
- colors: any,
61
- skyLights: any,
62
- blockLights: any,
63
- uvs: any,
58
+ positions: any
59
+ normals: any
60
+ colors: any
61
+ skyLights: any
62
+ blockLights: any
63
+ uvs: any
64
64
  /** Per-section blend geometry (water, lava, stained glass, ice, etc.). */
65
- blend?: MesherGeometryBucketData,
65
+ blend?: MesherGeometryBucketData
66
66
 
67
- indices: Uint32Array | Uint16Array | number[],
68
- indicesCount: number,
69
- using32Array: boolean,
70
- tiles: Record<string, BlockType>,
71
- heads: Record<string, any>,
72
- signs: Record<string, any>,
73
- banners: Record<string, any>,
67
+ indices: Uint32Array | Uint16Array | number[]
68
+ indicesCount: number
69
+ using32Array: boolean
70
+ tiles: Record<string, BlockType>
71
+ heads: Record<string, any>
72
+ signs: Record<string, any>
73
+ banners: Record<string, any>
74
74
  // isFull: boolean
75
75
  hadErrors: boolean
76
76
  blocksCount: number
@@ -85,36 +85,36 @@ export type MesherGeometryOutput = {
85
85
  }
86
86
 
87
87
  export interface MesherMainEvents {
88
- geometry: { type: 'geometry'; key: string; geometry: MesherGeometryOutput; workerIndex: number };
88
+ geometry: { type: 'geometry'; key: string; geometry: MesherGeometryOutput; workerIndex: number }
89
89
  sectionFinished: {
90
- type: 'sectionFinished';
91
- key: string;
92
- workerIndex: number;
93
- processTime?: number;
94
- pre?: number;
95
- wasm?: number;
96
- post?: number;
90
+ type: 'sectionFinished'
91
+ key: string
92
+ workerIndex: number
93
+ processTime?: number
94
+ pre?: number
95
+ wasm?: number
96
+ post?: number
97
97
  // Pre-stage substages (added for column-mode perf instrumentation).
98
98
  // All times in ms. `preNeighborConvert` is a SUM across neighbors;
99
99
  // divide by `preNeighborCount` for per-neighbor average.
100
- preTargetConvert?: number;
101
- preNeighborConvert?: number;
102
- preNeighborCount?: number;
103
- preTypedArrayBuild?: number;
104
- preOther?: number;
100
+ preTargetConvert?: number
101
+ preNeighborConvert?: number
102
+ preNeighborCount?: number
103
+ preTypedArrayBuild?: number
104
+ preOther?: number
105
105
  // Per-event counts for the column-mode conversion cache.
106
- preCacheHits?: number;
107
- preCacheMisses?: number;
108
- };
109
- blockStateModelInfo: { type: 'blockStateModelInfo'; info: Record<string, BlockStateModelInfo> };
110
- heightmap: { type: 'heightmap'; key: string; heightmap: Int16Array };
106
+ preCacheHits?: number
107
+ preCacheMisses?: number
108
+ }
109
+ blockStateModelInfo: { type: 'blockStateModelInfo'; info: Record<string, BlockStateModelInfo> }
110
+ heightmap: { type: 'heightmap'; key: string; heightmap: Int16Array }
111
111
  /** Reply to `{ type: 'mc-web-ping', t?, workerIndex? }` from the main thread (not batched in worker). */
112
- mcWebPong: { type: 'mc-web-pong'; workerIndex: number; t?: number; recvAt?: number };
112
+ mcWebPong: { type: 'mc-web-pong'; workerIndex: number; t?: number; recvAt?: number }
113
113
  }
114
114
 
115
115
  export type MesherMainEvent = MesherMainEvents[keyof MesherMainEvents]
116
116
 
117
- export type HighestBlockInfo = { y: number, stateId: number | undefined, biomeId: number | undefined }
117
+ export type HighestBlockInfo = { y: number; stateId: number | undefined; biomeId: number | undefined }
118
118
 
119
119
  export type BlockStateModelInfo = {
120
120
  cacheKey: string