minecraft-renderer 0.1.0
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/README.md +297 -0
- package/dist/index.html +83 -0
- package/dist/static/image/arrow.6f27b59f.png +0 -0
- package/dist/static/image/blocksAtlasLatest.7850afa3.png +0 -0
- package/dist/static/image/blocksAtlasLegacy.5c76823d.png +0 -0
- package/dist/static/image/itemsAtlasLatest.36036f95.png +0 -0
- package/dist/static/image/itemsAtlasLegacy.dcb1b58d.png +0 -0
- package/dist/static/image/tipped_arrow.6f27b59f.png +0 -0
- package/dist/static/js/365.f05233ab.js +8462 -0
- package/dist/static/js/365.f05233ab.js.LICENSE.txt +52 -0
- package/dist/static/js/async/738.efa27644.js +1 -0
- package/dist/static/js/index.092ec5be.js +56 -0
- package/dist/static/js/lib-polyfill.98986ac5.js +1 -0
- package/dist/static/js/lib-react.5c9129e0.js +2 -0
- package/dist/static/js/lib-react.5c9129e0.js.LICENSE.txt +39 -0
- package/package.json +104 -0
- package/src/assets/destroy_stage_0.png +0 -0
- package/src/assets/destroy_stage_1.png +0 -0
- package/src/assets/destroy_stage_2.png +0 -0
- package/src/assets/destroy_stage_3.png +0 -0
- package/src/assets/destroy_stage_4.png +0 -0
- package/src/assets/destroy_stage_5.png +0 -0
- package/src/assets/destroy_stage_6.png +0 -0
- package/src/assets/destroy_stage_7.png +0 -0
- package/src/assets/destroy_stage_8.png +0 -0
- package/src/assets/destroy_stage_9.png +0 -0
- package/src/examples/README.md +146 -0
- package/src/examples/appViewerExample.ts +205 -0
- package/src/examples/initialMenuStart.ts +161 -0
- package/src/graphicsBackend/appViewer.ts +297 -0
- package/src/graphicsBackend/config.ts +119 -0
- package/src/graphicsBackend/index.ts +10 -0
- package/src/graphicsBackend/playerState.ts +61 -0
- package/src/graphicsBackend/types.ts +143 -0
- package/src/index.ts +97 -0
- package/src/lib/DebugGui.ts +190 -0
- package/src/lib/animationController.ts +85 -0
- package/src/lib/buildSharedConfig.mjs +1 -0
- package/src/lib/cameraBobbing.ts +94 -0
- package/src/lib/canvas2DOverlay.example.ts +361 -0
- package/src/lib/canvas2DOverlay.quickstart.ts +242 -0
- package/src/lib/canvas2DOverlay.ts +381 -0
- package/src/lib/cleanupDecorator.ts +29 -0
- package/src/lib/createPlayerObject.ts +55 -0
- package/src/lib/frameTimingCollector.ts +164 -0
- package/src/lib/guiRenderer.ts +283 -0
- package/src/lib/items.ts +140 -0
- package/src/lib/mesherlogReader.ts +131 -0
- package/src/lib/moreBlockDataGenerated.json +714 -0
- package/src/lib/preflatMap.json +1741 -0
- package/src/lib/simpleUtils.ts +40 -0
- package/src/lib/smoothSwitcher.ts +168 -0
- package/src/lib/spiral.ts +29 -0
- package/src/lib/ui/newStats.ts +120 -0
- package/src/lib/utils/proxy.ts +23 -0
- package/src/lib/utils/skins.ts +63 -0
- package/src/lib/utils.ts +76 -0
- package/src/lib/workerProxy.ts +342 -0
- package/src/lib/worldrendererCommon.ts +1088 -0
- package/src/mesher/mesher.ts +253 -0
- package/src/mesher/models.ts +769 -0
- package/src/mesher/modelsGeometryCommon.ts +142 -0
- package/src/mesher/shared.ts +80 -0
- package/src/mesher/standaloneRenderer.ts +270 -0
- package/src/mesher/test/a.ts +3 -0
- package/src/mesher/test/mesherTester.ts +76 -0
- package/src/mesher/test/playground.ts +19 -0
- package/src/mesher/test/test-perf.ts +74 -0
- package/src/mesher/test/tests.test.ts +56 -0
- package/src/mesher/world.ts +294 -0
- package/src/mesher/worldConstants.ts +1 -0
- package/src/modules/index.ts +11 -0
- package/src/modules/starfield.ts +313 -0
- package/src/modules/types.ts +110 -0
- package/src/playerState/playerState.ts +78 -0
- package/src/playerState/types.ts +36 -0
- package/src/playground/allEntitiesDebug.ts +170 -0
- package/src/playground/baseScene.ts +587 -0
- package/src/playground/mobileControls.tsx +268 -0
- package/src/playground/playground.html +83 -0
- package/src/playground/playground.ts +11 -0
- package/src/playground/playgroundUi.tsx +140 -0
- package/src/playground/reactUtils.ts +71 -0
- package/src/playground/scenes/allEntities.ts +13 -0
- package/src/playground/scenes/entities.ts +37 -0
- package/src/playground/scenes/floorRandom.ts +33 -0
- package/src/playground/scenes/frequentUpdates.ts +148 -0
- package/src/playground/scenes/geometryExport.ts +142 -0
- package/src/playground/scenes/index.ts +12 -0
- package/src/playground/scenes/lightingStarfield.ts +40 -0
- package/src/playground/scenes/main.ts +313 -0
- package/src/playground/scenes/railsCobweb.ts +14 -0
- package/src/playground/scenes/rotationIssue.ts +7 -0
- package/src/playground/scenes/slabsOptimization.ts +16 -0
- package/src/playground/scenes/transparencyIssue.ts +11 -0
- package/src/playground/shared.ts +79 -0
- package/src/resourcesManager/index.ts +5 -0
- package/src/resourcesManager/resourcesManager.ts +314 -0
- package/src/shims/minecraftData.ts +41 -0
- package/src/sign-renderer/index.html +21 -0
- package/src/sign-renderer/index.ts +216 -0
- package/src/sign-renderer/noop.js +1 -0
- package/src/sign-renderer/playground.ts +38 -0
- package/src/sign-renderer/tests.test.ts +69 -0
- package/src/sign-renderer/vite.config.ts +10 -0
- package/src/three/appShared.ts +75 -0
- package/src/three/bannerRenderer.ts +275 -0
- package/src/three/cameraShake.ts +120 -0
- package/src/three/cinimaticScript.ts +350 -0
- package/src/three/documentRenderer.ts +491 -0
- package/src/three/entities.ts +1580 -0
- package/src/three/entity/EntityMesh.ts +707 -0
- package/src/three/entity/animations.js +171 -0
- package/src/three/entity/armorModels.json +204 -0
- package/src/three/entity/armorModels.ts +36 -0
- package/src/three/entity/entities.json +6230 -0
- package/src/three/entity/exportedModels.js +38 -0
- package/src/three/entity/externalTextures.json +1 -0
- package/src/three/entity/models/allay.obj +325 -0
- package/src/three/entity/models/arrow.obj +60 -0
- package/src/three/entity/models/axolotl.obj +509 -0
- package/src/three/entity/models/blaze.obj +601 -0
- package/src/three/entity/models/boat.obj +417 -0
- package/src/three/entity/models/camel.obj +1061 -0
- package/src/three/entity/models/cat.obj +509 -0
- package/src/three/entity/models/chicken.obj +371 -0
- package/src/three/entity/models/cod.obj +371 -0
- package/src/three/entity/models/creeper.obj +279 -0
- package/src/three/entity/models/dolphin.obj +371 -0
- package/src/three/entity/models/ender_dragon.obj +2993 -0
- package/src/three/entity/models/enderman.obj +325 -0
- package/src/three/entity/models/endermite.obj +187 -0
- package/src/three/entity/models/fox.obj +463 -0
- package/src/three/entity/models/frog.obj +739 -0
- package/src/three/entity/models/ghast.obj +463 -0
- package/src/three/entity/models/goat.obj +601 -0
- package/src/three/entity/models/guardian.obj +1015 -0
- package/src/three/entity/models/horse.obj +1061 -0
- package/src/three/entity/models/llama.obj +509 -0
- package/src/three/entity/models/minecart.obj +233 -0
- package/src/three/entity/models/parrot.obj +509 -0
- package/src/three/entity/models/piglin.obj +739 -0
- package/src/three/entity/models/pillager.obj +371 -0
- package/src/three/entity/models/rabbit.obj +555 -0
- package/src/three/entity/models/sheep.obj +555 -0
- package/src/three/entity/models/shulker.obj +141 -0
- package/src/three/entity/models/sniffer.obj +693 -0
- package/src/three/entity/models/spider.obj +509 -0
- package/src/three/entity/models/tadpole.obj +95 -0
- package/src/three/entity/models/turtle.obj +371 -0
- package/src/three/entity/models/vex.obj +325 -0
- package/src/three/entity/models/villager.obj +509 -0
- package/src/three/entity/models/warden.obj +463 -0
- package/src/three/entity/models/witch.obj +647 -0
- package/src/three/entity/models/wolf.obj +509 -0
- package/src/three/entity/models/zombie_villager.obj +463 -0
- package/src/three/entity/objModels.js +1 -0
- package/src/three/fireworks.ts +661 -0
- package/src/three/fireworksRenderer.ts +434 -0
- package/src/three/globals.d.ts +7 -0
- package/src/three/graphicsBackend.ts +274 -0
- package/src/three/graphicsBackendOffThread.ts +107 -0
- package/src/three/hand.ts +89 -0
- package/src/three/holdingBlock.ts +926 -0
- package/src/three/index.ts +20 -0
- package/src/three/itemMesh.ts +427 -0
- package/src/three/modules.d.ts +14 -0
- package/src/three/panorama.ts +308 -0
- package/src/three/panoramaShared.ts +1 -0
- package/src/three/renderSlot.ts +82 -0
- package/src/three/skyboxRenderer.ts +406 -0
- package/src/three/starField.ts +13 -0
- package/src/three/threeJsMedia.ts +731 -0
- package/src/three/threeJsMethods.ts +15 -0
- package/src/three/threeJsParticles.ts +160 -0
- package/src/three/threeJsSound.ts +95 -0
- package/src/three/threeJsUtils.ts +90 -0
- package/src/three/waypointSprite.ts +435 -0
- package/src/three/waypoints.ts +163 -0
- package/src/three/world/cursorBlock.ts +172 -0
- package/src/three/world/vr.ts +257 -0
- package/src/three/worldGeometryExport.ts +259 -0
- package/src/three/worldGeometryHandler.ts +279 -0
- package/src/three/worldRendererThree.ts +1381 -0
- package/src/worldView/index.ts +6 -0
- package/src/worldView/types.ts +66 -0
- package/src/worldView/worldView.ts +424 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { BlockModelPartsResolved } from './world'
|
|
2
|
+
|
|
3
|
+
export type BlockElement = NonNullable<BlockModelPartsResolved[0][0]['elements']>[0]
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export function buildRotationMatrix (axis, degree) {
|
|
7
|
+
const radians = degree / 180 * Math.PI
|
|
8
|
+
const cos = Math.cos(radians)
|
|
9
|
+
const sin = Math.sin(radians)
|
|
10
|
+
|
|
11
|
+
const axis0 = { x: 0, y: 1, z: 2 }[axis]
|
|
12
|
+
const axis1 = (axis0 + 1) % 3
|
|
13
|
+
const axis2 = (axis0 + 2) % 3
|
|
14
|
+
|
|
15
|
+
const matrix = [
|
|
16
|
+
[0, 0, 0],
|
|
17
|
+
[0, 0, 0],
|
|
18
|
+
[0, 0, 0]
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
matrix[axis0][axis0] = 1
|
|
22
|
+
matrix[axis1][axis1] = cos
|
|
23
|
+
matrix[axis1][axis2] = -sin
|
|
24
|
+
matrix[axis2][axis1] = +sin
|
|
25
|
+
matrix[axis2][axis2] = cos
|
|
26
|
+
|
|
27
|
+
return matrix
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function vecadd3 (a, b) {
|
|
31
|
+
if (!b) return a
|
|
32
|
+
return [a[0] + b[0], a[1] + b[1], a[2] + b[2]]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function vecsub3 (a, b) {
|
|
36
|
+
if (!b) return a
|
|
37
|
+
return [a[0] - b[0], a[1] - b[1], a[2] - b[2]]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function matmul3 (matrix, vector): [number, number, number] {
|
|
41
|
+
if (!matrix) return vector
|
|
42
|
+
return [
|
|
43
|
+
matrix[0][0] * vector[0] + matrix[0][1] * vector[1] + matrix[0][2] * vector[2],
|
|
44
|
+
matrix[1][0] * vector[0] + matrix[1][1] * vector[1] + matrix[1][2] * vector[2],
|
|
45
|
+
matrix[2][0] * vector[0] + matrix[2][1] * vector[1] + matrix[2][2] * vector[2]
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function matmulmat3 (a, b) {
|
|
50
|
+
const te = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
|
|
51
|
+
|
|
52
|
+
const a11 = a[0][0]; const a12 = a[1][0]; const a13 = a[2][0]
|
|
53
|
+
const a21 = a[0][1]; const a22 = a[1][1]; const a23 = a[2][1]
|
|
54
|
+
const a31 = a[0][2]; const a32 = a[1][2]; const a33 = a[2][2]
|
|
55
|
+
|
|
56
|
+
const b11 = b[0][0]; const b12 = b[1][0]; const b13 = b[2][0]
|
|
57
|
+
const b21 = b[0][1]; const b22 = b[1][1]; const b23 = b[2][1]
|
|
58
|
+
const b31 = b[0][2]; const b32 = b[1][2]; const b33 = b[2][2]
|
|
59
|
+
|
|
60
|
+
te[0][0] = a11 * b11 + a12 * b21 + a13 * b31
|
|
61
|
+
te[1][0] = a11 * b12 + a12 * b22 + a13 * b32
|
|
62
|
+
te[2][0] = a11 * b13 + a12 * b23 + a13 * b33
|
|
63
|
+
|
|
64
|
+
te[0][1] = a21 * b11 + a22 * b21 + a23 * b31
|
|
65
|
+
te[1][1] = a21 * b12 + a22 * b22 + a23 * b32
|
|
66
|
+
te[2][1] = a21 * b13 + a22 * b23 + a23 * b33
|
|
67
|
+
|
|
68
|
+
te[0][2] = a31 * b11 + a32 * b21 + a33 * b31
|
|
69
|
+
te[1][2] = a31 * b12 + a32 * b22 + a33 * b32
|
|
70
|
+
te[2][2] = a31 * b13 + a32 * b23 + a33 * b33
|
|
71
|
+
|
|
72
|
+
return te
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const elemFaces = {
|
|
76
|
+
up: {
|
|
77
|
+
dir: [0, 1, 0],
|
|
78
|
+
mask1: [1, 1, 0],
|
|
79
|
+
mask2: [0, 1, 1],
|
|
80
|
+
corners: [
|
|
81
|
+
[0, 1, 1, 0, 1],
|
|
82
|
+
[1, 1, 1, 1, 1],
|
|
83
|
+
[0, 1, 0, 0, 0],
|
|
84
|
+
[1, 1, 0, 1, 0]
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
down: {
|
|
88
|
+
dir: [0, -1, 0],
|
|
89
|
+
mask1: [1, 1, 0],
|
|
90
|
+
mask2: [0, 1, 1],
|
|
91
|
+
corners: [
|
|
92
|
+
[1, 0, 1, 0, 1],
|
|
93
|
+
[0, 0, 1, 1, 1],
|
|
94
|
+
[1, 0, 0, 0, 0],
|
|
95
|
+
[0, 0, 0, 1, 0]
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
east: {
|
|
99
|
+
dir: [1, 0, 0],
|
|
100
|
+
mask1: [1, 1, 0],
|
|
101
|
+
mask2: [1, 0, 1],
|
|
102
|
+
corners: [
|
|
103
|
+
[1, 1, 1, 0, 0],
|
|
104
|
+
[1, 0, 1, 0, 1],
|
|
105
|
+
[1, 1, 0, 1, 0],
|
|
106
|
+
[1, 0, 0, 1, 1]
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
west: {
|
|
110
|
+
dir: [-1, 0, 0],
|
|
111
|
+
mask1: [1, 1, 0],
|
|
112
|
+
mask2: [1, 0, 1],
|
|
113
|
+
corners: [
|
|
114
|
+
[0, 1, 0, 0, 0],
|
|
115
|
+
[0, 0, 0, 0, 1],
|
|
116
|
+
[0, 1, 1, 1, 0],
|
|
117
|
+
[0, 0, 1, 1, 1]
|
|
118
|
+
]
|
|
119
|
+
},
|
|
120
|
+
north: {
|
|
121
|
+
dir: [0, 0, -1],
|
|
122
|
+
mask1: [1, 0, 1],
|
|
123
|
+
mask2: [0, 1, 1],
|
|
124
|
+
corners: [
|
|
125
|
+
[1, 0, 0, 1, 1],
|
|
126
|
+
[0, 0, 0, 0, 1],
|
|
127
|
+
[1, 1, 0, 1, 0],
|
|
128
|
+
[0, 1, 0, 0, 0]
|
|
129
|
+
]
|
|
130
|
+
},
|
|
131
|
+
south: {
|
|
132
|
+
dir: [0, 0, 1],
|
|
133
|
+
mask1: [1, 0, 1],
|
|
134
|
+
mask2: [0, 1, 1],
|
|
135
|
+
corners: [
|
|
136
|
+
[0, 0, 1, 0, 1],
|
|
137
|
+
[1, 0, 1, 1, 1],
|
|
138
|
+
[0, 1, 1, 0, 0],
|
|
139
|
+
[1, 1, 1, 1, 0]
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { BlockType } from '../../../playground/shared'
|
|
2
|
+
|
|
3
|
+
// only here for easier testing
|
|
4
|
+
export const defaultMesherConfig = {
|
|
5
|
+
version: '',
|
|
6
|
+
worldMaxY: 256,
|
|
7
|
+
worldMinY: 0,
|
|
8
|
+
enableLighting: true,
|
|
9
|
+
skyLight: 15,
|
|
10
|
+
smoothLighting: false,
|
|
11
|
+
outputFormat: 'threeJs' as 'threeJs' | 'webgpu',
|
|
12
|
+
// textureSize: 1024, // for testing
|
|
13
|
+
debugModelVariant: undefined as undefined | number[],
|
|
14
|
+
clipWorldBelowY: undefined as undefined | number,
|
|
15
|
+
disableBlockEntityTextures: false
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type CustomBlockModels = {
|
|
19
|
+
[blockPosKey: string]: string // blockPosKey is "x,y,z" -> model name
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type MesherConfig = typeof defaultMesherConfig
|
|
23
|
+
|
|
24
|
+
export type MesherGeometryOutput = {
|
|
25
|
+
sectionYNumber: number,
|
|
26
|
+
chunkKey: string,
|
|
27
|
+
sectionStartY: number,
|
|
28
|
+
sectionEndY: number,
|
|
29
|
+
sectionStartX: number,
|
|
30
|
+
sectionEndX: number,
|
|
31
|
+
sectionStartZ: number,
|
|
32
|
+
sectionEndZ: number,
|
|
33
|
+
// three.js
|
|
34
|
+
sx: number,
|
|
35
|
+
sy: number,
|
|
36
|
+
sz: number,
|
|
37
|
+
// resulting: float32array
|
|
38
|
+
positions: any,
|
|
39
|
+
normals: any,
|
|
40
|
+
colors: any,
|
|
41
|
+
uvs: any,
|
|
42
|
+
t_positions?: number[],
|
|
43
|
+
t_normals?: number[],
|
|
44
|
+
t_colors?: number[],
|
|
45
|
+
t_uvs?: number[],
|
|
46
|
+
|
|
47
|
+
indices: Uint32Array | Uint16Array | number[],
|
|
48
|
+
indicesCount: number,
|
|
49
|
+
using32Array: boolean,
|
|
50
|
+
tiles: Record<string, BlockType>,
|
|
51
|
+
heads: Record<string, any>,
|
|
52
|
+
signs: Record<string, any>,
|
|
53
|
+
banners: Record<string, any>,
|
|
54
|
+
// isFull: boolean
|
|
55
|
+
hadErrors: boolean
|
|
56
|
+
blocksCount: number
|
|
57
|
+
customBlockModels?: CustomBlockModels
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface MesherMainEvents {
|
|
61
|
+
geometry: { type: 'geometry'; key: string; geometry: MesherGeometryOutput; workerIndex: number };
|
|
62
|
+
sectionFinished: { type: 'sectionFinished'; key: string; workerIndex: number; processTime?: number };
|
|
63
|
+
blockStateModelInfo: { type: 'blockStateModelInfo'; info: Record<string, BlockStateModelInfo> };
|
|
64
|
+
heightmap: { type: 'heightmap'; key: string; heightmap: Uint8Array };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type MesherMainEvent = MesherMainEvents[keyof MesherMainEvents]
|
|
68
|
+
|
|
69
|
+
export type HighestBlockInfo = { y: number, stateId: number | undefined, biomeId: number | undefined }
|
|
70
|
+
|
|
71
|
+
export type BlockStateModelInfo = {
|
|
72
|
+
cacheKey: string
|
|
73
|
+
issues: string[]
|
|
74
|
+
modelNames: string[]
|
|
75
|
+
conditions: string[]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const getBlockAssetsCacheKey = (stateId: number, modelNameOverride?: string) => {
|
|
79
|
+
return modelNameOverride ? `${stateId}:${modelNameOverride}` : String(stateId)
|
|
80
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/* eslint-disable @stylistic/function-call-argument-newline */
|
|
2
|
+
import { Vec3 } from 'vec3'
|
|
3
|
+
import { Block } from 'prismarine-block'
|
|
4
|
+
import { IndexedData } from 'minecraft-data'
|
|
5
|
+
import * as THREE from 'three'
|
|
6
|
+
import { BlockModelPartsResolved } from './world'
|
|
7
|
+
import { BlockElement, buildRotationMatrix, elemFaces, matmul3, matmulmat3, vecadd3, vecsub3 } from './modelsGeometryCommon'
|
|
8
|
+
|
|
9
|
+
type NeighborSide = 'up' | 'down' | 'east' | 'west' | 'north' | 'south'
|
|
10
|
+
|
|
11
|
+
function tintToGl (tint) {
|
|
12
|
+
const r = (tint >> 16) & 0xff
|
|
13
|
+
const g = (tint >> 8) & 0xff
|
|
14
|
+
const b = tint & 0xff
|
|
15
|
+
return [r / 255, g / 255, b / 255]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type Neighbors = Partial<Record<NeighborSide, boolean>>
|
|
19
|
+
function renderElement (element: BlockElement, doAO: boolean, attr, globalMatrix, globalShift, block: Block | undefined, biome: string, neighbors: Neighbors) {
|
|
20
|
+
const cursor = new Vec3(0, 0, 0)
|
|
21
|
+
|
|
22
|
+
// const key = `${position.x},${position.y},${position.z}`
|
|
23
|
+
// if (!globalThis.allowedBlocks.includes(key)) return
|
|
24
|
+
// const cullIfIdentical = block.name.indexOf('glass') >= 0
|
|
25
|
+
|
|
26
|
+
// eslint-disable-next-line guard-for-in
|
|
27
|
+
for (const face in element.faces) {
|
|
28
|
+
const eFace = element.faces[face]
|
|
29
|
+
const { corners, mask1, mask2 } = elemFaces[face]
|
|
30
|
+
const dir = matmul3(globalMatrix, elemFaces[face].dir)
|
|
31
|
+
|
|
32
|
+
if (eFace.cullface) {
|
|
33
|
+
if (neighbors[face]) continue
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const minx = element.from[0]
|
|
37
|
+
const miny = element.from[1]
|
|
38
|
+
const minz = element.from[2]
|
|
39
|
+
const maxx = element.to[0]
|
|
40
|
+
const maxy = element.to[1]
|
|
41
|
+
const maxz = element.to[2]
|
|
42
|
+
|
|
43
|
+
const texture = eFace.texture as any
|
|
44
|
+
const { u } = texture
|
|
45
|
+
const { v } = texture
|
|
46
|
+
const { su } = texture
|
|
47
|
+
const { sv } = texture
|
|
48
|
+
|
|
49
|
+
const ndx = Math.floor(attr.positions.length / 3)
|
|
50
|
+
|
|
51
|
+
let tint = [1, 1, 1]
|
|
52
|
+
if (eFace.tintindex !== undefined) {
|
|
53
|
+
if (eFace.tintindex === 0) {
|
|
54
|
+
// TODO
|
|
55
|
+
// if (block.name === 'redstone_wire') {
|
|
56
|
+
// tint = tints.redstone[`${block.getProperties().power}`]
|
|
57
|
+
// } else if (block.name === 'birch_leaves' ||
|
|
58
|
+
// block.name === 'spruce_leaves' ||
|
|
59
|
+
// block.name === 'lily_pad') {
|
|
60
|
+
// tint = tints.constant[block.name]
|
|
61
|
+
// } else if (block.name.includes('leaves') || block.name === 'vine') {
|
|
62
|
+
// tint = tints.foliage[biome]
|
|
63
|
+
// } else {
|
|
64
|
+
// tint = tints.grass[biome]
|
|
65
|
+
// }
|
|
66
|
+
const grassTint = [145 / 255, 189 / 255, 89 / 255]
|
|
67
|
+
tint = grassTint
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// UV rotation
|
|
72
|
+
const r = eFace.rotation || 0
|
|
73
|
+
const uvcs = Math.cos(r * Math.PI / 180)
|
|
74
|
+
const uvsn = -Math.sin(r * Math.PI / 180)
|
|
75
|
+
|
|
76
|
+
let localMatrix = null as any
|
|
77
|
+
let localShift = null as any
|
|
78
|
+
|
|
79
|
+
if (element.rotation) {
|
|
80
|
+
// todo do we support rescale?
|
|
81
|
+
localMatrix = buildRotationMatrix(
|
|
82
|
+
element.rotation.axis,
|
|
83
|
+
element.rotation.angle
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
localShift = vecsub3(
|
|
87
|
+
element.rotation.origin,
|
|
88
|
+
matmul3(
|
|
89
|
+
localMatrix,
|
|
90
|
+
element.rotation.origin
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const aos: number[] = []
|
|
96
|
+
// const neighborPos = position.plus(new Vec3(...dir))
|
|
97
|
+
// const baseLight = world.getLight(neighborPos, undefined, undefined, block.name) / 15
|
|
98
|
+
const baseLight = 1
|
|
99
|
+
for (const pos of corners) {
|
|
100
|
+
let vertex = [
|
|
101
|
+
(pos[0] ? maxx : minx),
|
|
102
|
+
(pos[1] ? maxy : miny),
|
|
103
|
+
(pos[2] ? maxz : minz)
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
vertex = vecadd3(matmul3(localMatrix, vertex), localShift)
|
|
107
|
+
vertex = vecadd3(matmul3(globalMatrix, vertex), globalShift)
|
|
108
|
+
vertex = vertex.map(v => v / 16)
|
|
109
|
+
|
|
110
|
+
attr.positions.push(
|
|
111
|
+
vertex[0]/* + (cursor.x & 15) - 8 */,
|
|
112
|
+
vertex[1]/* + (cursor.y & 15) x */,
|
|
113
|
+
vertex[2]/* + (cursor.z & 15) - 8 */
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
attr.normals.push(...dir)
|
|
117
|
+
|
|
118
|
+
const baseu = (pos[3] - 0.5) * uvcs - (pos[4] - 0.5) * uvsn + 0.5
|
|
119
|
+
const basev = (pos[3] - 0.5) * uvsn + (pos[4] - 0.5) * uvcs + 0.5
|
|
120
|
+
attr.uvs.push(baseu * su + u, basev * sv + v)
|
|
121
|
+
|
|
122
|
+
let light = 1
|
|
123
|
+
if (doAO) {
|
|
124
|
+
const cornerLightResult = 15
|
|
125
|
+
|
|
126
|
+
const side1Block = 0
|
|
127
|
+
const side2Block = 0
|
|
128
|
+
const cornerBlock = 0
|
|
129
|
+
|
|
130
|
+
const ao = (side1Block && side2Block) ? 0 : (3 - (side1Block + side2Block + cornerBlock))
|
|
131
|
+
// todo light should go upper on lower blocks
|
|
132
|
+
light = (ao + 1) / 4 * (cornerLightResult / 15)
|
|
133
|
+
aos.push(ao)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
attr.colors.push(baseLight * tint[0] * light, baseLight * tint[1] * light, baseLight * tint[2] * light)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// if (needTiles) {
|
|
140
|
+
// attr.tiles[`${cursor.x},${cursor.y},${cursor.z}`] ??= {
|
|
141
|
+
// block: block.name,
|
|
142
|
+
// faces: [],
|
|
143
|
+
// }
|
|
144
|
+
// attr.tiles[`${cursor.x},${cursor.y},${cursor.z}`].faces.push({
|
|
145
|
+
// face,
|
|
146
|
+
// neighbor: `${neighborPos.x},${neighborPos.y},${neighborPos.z}`,
|
|
147
|
+
// light: baseLight
|
|
148
|
+
// // texture: eFace.texture.name,
|
|
149
|
+
// })
|
|
150
|
+
// }
|
|
151
|
+
|
|
152
|
+
if (doAO && aos[0] + aos[3] >= aos[1] + aos[2]) {
|
|
153
|
+
attr.indices.push(
|
|
154
|
+
|
|
155
|
+
ndx, ndx + 3, ndx + 2,
|
|
156
|
+
ndx, ndx + 1, ndx + 3
|
|
157
|
+
)
|
|
158
|
+
} else {
|
|
159
|
+
attr.indices.push(
|
|
160
|
+
|
|
161
|
+
ndx, ndx + 1, ndx + 2,
|
|
162
|
+
ndx + 2, ndx + 1, ndx + 3
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export const renderBlockThreeAttr = (models: BlockModelPartsResolved, block: Block | undefined, biome: string, mcData: IndexedData, variants = [], neighbors: Neighbors = {}) => {
|
|
169
|
+
const sx = 0
|
|
170
|
+
const sy = 0
|
|
171
|
+
const sz = 0
|
|
172
|
+
|
|
173
|
+
const attr = {
|
|
174
|
+
sx: sx + 0.5,
|
|
175
|
+
sy: sy + 0.5,
|
|
176
|
+
sz: sz + 0.5,
|
|
177
|
+
positions: [],
|
|
178
|
+
normals: [],
|
|
179
|
+
colors: [],
|
|
180
|
+
uvs: [],
|
|
181
|
+
t_positions: [],
|
|
182
|
+
t_normals: [],
|
|
183
|
+
t_colors: [],
|
|
184
|
+
t_uvs: [],
|
|
185
|
+
indices: [],
|
|
186
|
+
tiles: {},
|
|
187
|
+
} as Record<string, any>
|
|
188
|
+
|
|
189
|
+
for (const [i, modelVars] of models.entries()) {
|
|
190
|
+
const model = modelVars[variants[i]] ?? modelVars[0]
|
|
191
|
+
if (!model) continue
|
|
192
|
+
let globalMatrix = null as any
|
|
193
|
+
let globalShift = null as any
|
|
194
|
+
for (const axis of ['x', 'y', 'z'] as const) {
|
|
195
|
+
if (axis in model) {
|
|
196
|
+
if (globalMatrix) { globalMatrix = matmulmat3(globalMatrix, buildRotationMatrix(axis, -(model[axis] ?? 0))) } else { globalMatrix = buildRotationMatrix(axis, -(model[axis] ?? 0)) }
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (globalMatrix) {
|
|
200
|
+
globalShift = [8, 8, 8]
|
|
201
|
+
globalShift = vecsub3(globalShift, matmul3(globalMatrix, globalShift))
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const ao = model.ao ?? true
|
|
205
|
+
|
|
206
|
+
for (const element of model.elements ?? []) {
|
|
207
|
+
renderElement(element, ao, attr, globalMatrix, globalShift, block, biome, neighbors)
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
let ndx = attr.positions.length / 3
|
|
212
|
+
for (let i = 0; i < attr.t_positions.length / 12; i++) {
|
|
213
|
+
attr.indices.push(
|
|
214
|
+
ndx, ndx + 1, ndx + 2, ndx + 2, ndx + 1, ndx + 3,
|
|
215
|
+
// back face
|
|
216
|
+
ndx, ndx + 2, ndx + 1, ndx + 2, ndx + 3, ndx + 1
|
|
217
|
+
)
|
|
218
|
+
ndx += 4
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
attr.positions.push(...attr.t_positions)
|
|
222
|
+
attr.normals.push(...attr.t_normals)
|
|
223
|
+
attr.colors.push(...attr.t_colors)
|
|
224
|
+
attr.uvs.push(...attr.t_uvs)
|
|
225
|
+
|
|
226
|
+
delete attr.t_positions
|
|
227
|
+
delete attr.t_normals
|
|
228
|
+
delete attr.t_colors
|
|
229
|
+
delete attr.t_uvs
|
|
230
|
+
|
|
231
|
+
attr.positions = new Float32Array(attr.positions) as any
|
|
232
|
+
attr.normals = new Float32Array(attr.normals) as any
|
|
233
|
+
attr.colors = new Float32Array(attr.colors) as any
|
|
234
|
+
attr.uvs = new Float32Array(attr.uvs) as any
|
|
235
|
+
|
|
236
|
+
return attr
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export const renderBlockThree = (...args: Parameters<typeof renderBlockThreeAttr>) => {
|
|
240
|
+
const attr = renderBlockThreeAttr(...args)
|
|
241
|
+
const data = {
|
|
242
|
+
geometry: attr
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const geometry = new THREE.BufferGeometry()
|
|
246
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(data.geometry.positions, 3))
|
|
247
|
+
geometry.setAttribute('normal', new THREE.BufferAttribute(data.geometry.normals, 3))
|
|
248
|
+
geometry.setAttribute('color', new THREE.BufferAttribute(data.geometry.colors, 3))
|
|
249
|
+
geometry.setAttribute('uv', new THREE.BufferAttribute(data.geometry.uvs, 2))
|
|
250
|
+
geometry.setIndex(data.geometry.indices)
|
|
251
|
+
geometry.name = 'block-geometry'
|
|
252
|
+
|
|
253
|
+
return geometry
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export const getThreeBlockModelGroup = (material: THREE.Material, ...args: Parameters<typeof renderBlockThree>) => {
|
|
257
|
+
const geometry = renderBlockThree(...args)
|
|
258
|
+
const mesh = new THREE.Mesh(geometry, material)
|
|
259
|
+
mesh.position.set(-0.5, -0.5, -0.5)
|
|
260
|
+
const group = new THREE.Group()
|
|
261
|
+
group.add(mesh)
|
|
262
|
+
group.rotation.set(0, -THREE.MathUtils.degToRad(90), 0, 'ZYX')
|
|
263
|
+
globalThis.mesh = group
|
|
264
|
+
return group
|
|
265
|
+
// return new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshPhongMaterial({ color: 0x00_00_ff, transparent: true, opacity: 0.5 }))
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export const setBlockPosition = (object: THREE.Object3D, position: { x: number, y: number, z: number }) => {
|
|
269
|
+
object.position.set(position.x + 0.5, position.y + 0.5, position.z + 0.5)
|
|
270
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import ChunkLoader, { PCChunk } from 'prismarine-chunk'
|
|
2
|
+
import { Vec3 } from 'vec3'
|
|
3
|
+
import MinecraftData from 'minecraft-data'
|
|
4
|
+
import blocksAtlasesJson from 'mc-assets/dist/blocksAtlases.json'
|
|
5
|
+
import { World as MesherWorld } from '../world'
|
|
6
|
+
import { setBlockStatesData, getSectionGeometry } from '../models'
|
|
7
|
+
|
|
8
|
+
export const setup = (version, initialBlocks: Array<[number[], string]>) => {
|
|
9
|
+
const mcData = MinecraftData(version)
|
|
10
|
+
const blockStatesModels = require(`mc-assets/dist/blockStatesModels.json`)
|
|
11
|
+
const mesherWorld = new MesherWorld(version)
|
|
12
|
+
const Chunk = ChunkLoader(version)
|
|
13
|
+
const chunk1 = new Chunk(undefined as any)
|
|
14
|
+
|
|
15
|
+
const pos = new Vec3(2, 5, 2)
|
|
16
|
+
for (const [addPos, name] of initialBlocks) {
|
|
17
|
+
chunk1.setBlockStateId(pos.offset(addPos[0], addPos[1], addPos[2]), mcData.blocksByName[name].defaultState)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const getGeometry = () => {
|
|
21
|
+
const sectionGeometry = getSectionGeometry(0, 0, 0, mesherWorld)
|
|
22
|
+
const centerFaces = sectionGeometry.tiles[`${pos.x},${pos.y},${pos.z}`]?.faces.length ?? 0
|
|
23
|
+
const totalTiles = Object.values(sectionGeometry.tiles).reduce((acc, val: any) => acc + val.faces.length, 0)
|
|
24
|
+
const centerTileNeighbors = Object.entries(sectionGeometry.tiles).reduce((acc, [key, val]: any) => {
|
|
25
|
+
return acc + val.faces.filter((face: any) => face.neighbor === `${pos.x},${pos.y},${pos.z}`).length
|
|
26
|
+
}, 0)
|
|
27
|
+
return {
|
|
28
|
+
centerFaces,
|
|
29
|
+
totalTiles,
|
|
30
|
+
centerTileNeighbors,
|
|
31
|
+
faces: sectionGeometry.tiles[`${pos.x},${pos.y},${pos.z}`]?.faces ?? [],
|
|
32
|
+
attr: sectionGeometry
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
setBlockStatesData(blockStatesModels, blocksAtlasesJson, true, false, version)
|
|
37
|
+
const reload = () => {
|
|
38
|
+
mesherWorld.removeColumn(0, 0)
|
|
39
|
+
mesherWorld.addColumn(0, 0, chunk1.toJson())
|
|
40
|
+
}
|
|
41
|
+
reload()
|
|
42
|
+
|
|
43
|
+
const getLights = () => {
|
|
44
|
+
return Object.fromEntries(getGeometry().faces.map(({ face, light }) => ([face, (light ?? 0) * 15 - 2])))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const setLight = (x: number, y: number, z: number, val = 0) => {
|
|
48
|
+
// create columns first
|
|
49
|
+
chunk1.setBlockLight(pos.offset(x, y, z), 15)
|
|
50
|
+
chunk1.setSkyLight(pos.offset(x, y, z), 15)
|
|
51
|
+
chunk1.setBlockLight(pos.offset(x, y, z), val)
|
|
52
|
+
chunk1.setSkyLight(pos.offset(x, y, z), 0)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
mesherWorld,
|
|
57
|
+
setLight,
|
|
58
|
+
getLights,
|
|
59
|
+
getGeometry,
|
|
60
|
+
pos,
|
|
61
|
+
mcData,
|
|
62
|
+
reload,
|
|
63
|
+
chunk: chunk1 as PCChunk
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// surround it
|
|
68
|
+
const addPositions = [
|
|
69
|
+
// [[0, 0, 0], 'diamond_block'],
|
|
70
|
+
[[1, 0, 0], 'stone'],
|
|
71
|
+
[[-1, 0, 0], 'stone'],
|
|
72
|
+
[[0, 1, 0], 'stone'],
|
|
73
|
+
[[0, -1, 0], 'stone'],
|
|
74
|
+
[[0, 0, 1], 'stone'],
|
|
75
|
+
[[0, 0, -1], 'stone'],
|
|
76
|
+
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { setup } from './mesherTester'
|
|
2
|
+
|
|
3
|
+
const addPositions = [
|
|
4
|
+
// [[0, 0, 0], 'diamond_block'],
|
|
5
|
+
[[1, 0, 0], 'stone'],
|
|
6
|
+
[[-1, 0, 0], 'stone'],
|
|
7
|
+
[[0, 1, 0], 'stone'],
|
|
8
|
+
[[0, -1, 0], 'stone'],
|
|
9
|
+
[[0, 0, 1], 'stone'],
|
|
10
|
+
[[0, 0, -1], 'stone'],
|
|
11
|
+
] as const
|
|
12
|
+
|
|
13
|
+
const { mesherWorld, getGeometry, pos, mcData } = setup('1.21.1', addPositions as any)
|
|
14
|
+
|
|
15
|
+
// mesherWorld.setBlockStateId(pos, 712)
|
|
16
|
+
// mesherWorld.setBlockStateId(pos, mcData.blocksByName.stone_slab.defaultState)
|
|
17
|
+
mesherWorld.setBlockStateId(pos, 11_225)
|
|
18
|
+
|
|
19
|
+
console.log(getGeometry().centerTileNeighbors)
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { generateSpiralMatrix } from 'flying-squid/dist/utils'
|
|
2
|
+
import PrismarineWorld from 'prismarine-world'
|
|
3
|
+
import PrismarineChunk from 'prismarine-chunk'
|
|
4
|
+
import { Vec3 } from 'vec3'
|
|
5
|
+
import MinecraftData from 'minecraft-data'
|
|
6
|
+
import { defaultMesherConfig } from '../shared'
|
|
7
|
+
import { setup } from './mesherTester.js'
|
|
8
|
+
|
|
9
|
+
// const version = '1.8.8'
|
|
10
|
+
const version = '1.21.1'
|
|
11
|
+
const World = PrismarineWorld(version)
|
|
12
|
+
const Chunk = PrismarineChunk(version)
|
|
13
|
+
const data = MinecraftData(version)
|
|
14
|
+
|
|
15
|
+
const { chunk, getGeometry, reload } = setup(version, [])
|
|
16
|
+
|
|
17
|
+
const fillers = {
|
|
18
|
+
// 10 iterations no smooth light 66ms m1 pro
|
|
19
|
+
worstPossibleFull () {
|
|
20
|
+
for (let x = 0; x < 16; x++) {
|
|
21
|
+
for (let z = 0; z < 16; z++) {
|
|
22
|
+
for (let y = -64; y < 320; y++) {
|
|
23
|
+
// Create a 3D checkerboard pattern where each block is surrounded by air
|
|
24
|
+
const isEvalPoint = (x % 3 === 0) && (z % 3 === 0) && (y % 3 === 0)
|
|
25
|
+
// chunk.setBlockStateId(new Vec3(x, y, z), isEvalPoint ? 1 : 0)
|
|
26
|
+
chunk.setBlockType(new Vec3(x, y, z), isEvalPoint ? 1 : 0)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
allFilled () {
|
|
32
|
+
for (let x = 0; x < 16; x++) {
|
|
33
|
+
for (let z = 0; z < 16; z++) {
|
|
34
|
+
for (let y = -64; y < 320; y++) {
|
|
35
|
+
chunk.setBlockType(new Vec3(x, y, z), 1)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
defaultMesherConfig.enableLighting = true
|
|
43
|
+
defaultMesherConfig.smoothLighting = false
|
|
44
|
+
|
|
45
|
+
fillers.worstPossibleFull()
|
|
46
|
+
reload()
|
|
47
|
+
|
|
48
|
+
const sectionsY = Math.floor(384 / 16)
|
|
49
|
+
const chunks = generateSpiralMatrix(5).length
|
|
50
|
+
// const sections = chunks * sectionsY
|
|
51
|
+
const sections = 10
|
|
52
|
+
|
|
53
|
+
const testIterations = 10 * 16 * 16 * 16 * 6
|
|
54
|
+
|
|
55
|
+
console.time('iterate')
|
|
56
|
+
// for (let i = 0; i < testIterations; i++) {
|
|
57
|
+
// const a = new Vec3(Math.random(), Math.random(), Math.random())
|
|
58
|
+
// a[0]
|
|
59
|
+
// }
|
|
60
|
+
|
|
61
|
+
for (let i = 0; i < sections; i++) {
|
|
62
|
+
const { totalTiles } = getGeometry()
|
|
63
|
+
console.log('totalTiles', totalTiles)
|
|
64
|
+
// for (let x = 0; x < 16; x++) {
|
|
65
|
+
// for (let z = 0; z < 16; z++) {
|
|
66
|
+
// for (let y = -64; y < 320; y++) {
|
|
67
|
+
// world.getBlockStateId(new Vec3(x, y, z))
|
|
68
|
+
// }
|
|
69
|
+
// }
|
|
70
|
+
// }
|
|
71
|
+
}
|
|
72
|
+
console.timeEnd('iterate')
|
|
73
|
+
console.log(globalThis.tasksTiming)
|
|
74
|
+
console.log(sections)
|