minecraft-renderer 0.1.23 → 0.1.25
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/mesherWasm.js +5 -5
- package/dist/minecraft-renderer.js +58 -58
- package/dist/threeWorker.js +417 -417
- package/package.json +2 -1
- package/src/sign-renderer/index.ts +6 -0
- package/src/three/cameraShake.ts +1 -1
- package/src/three/entities.ts +6 -2
- package/src/three/entity/EntityMesh.ts +56 -34
- package/src/three/entity/gltfAnimationUtils.ts +141 -0
- package/src/three/modules/rain.ts +5 -5
- package/src/three/modules/sciFiWorldReveal.ts +2 -2
- package/src/three/modules/starfield.ts +1 -1
- package/src/three/rendererModuleSystem.ts +1 -1
- package/src/three/worldRendererThree.ts +7 -2
- package/wasm/wasm_mesher.d.ts +2 -2
- package/wasm/wasm_mesher.js +4 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "minecraft-renderer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.25",
|
|
4
4
|
"description": "The most Modular Minecraft world renderer with Three.js WebGL backend",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -120,6 +120,7 @@
|
|
|
120
120
|
"build:lib:minify": "node scripts/buildLib.mjs --minify",
|
|
121
121
|
"watch:lib": "node scripts/buildLib.mjs -w",
|
|
122
122
|
"build:mesher": "node scripts/buildMesherWorker.mjs",
|
|
123
|
+
"build:wasm": "cd wasm-mesher && ./build.sh web",
|
|
123
124
|
"watch:mesher": "pnpm build:mesher -w",
|
|
124
125
|
"build:threeworker": "node scripts/buildThreeWorker.mjs",
|
|
125
126
|
"watch:threeworker": "pnpm build:threeworker -w",
|
|
@@ -100,6 +100,7 @@ export const renderComponent = (
|
|
|
100
100
|
defaultColor: string,
|
|
101
101
|
offset = 0
|
|
102
102
|
) => {
|
|
103
|
+
let textRendered = false
|
|
103
104
|
// todo: in pre flatenning it seems the format was not json
|
|
104
105
|
const parsed = typeof text === 'string' && (text?.startsWith('{') || text?.startsWith('"')) ? parseSafe(text ?? '""', 'sign text') : text
|
|
105
106
|
if (!parsed || (typeof parsed !== 'object' && typeof parsed !== 'string')) return
|
|
@@ -162,6 +163,9 @@ export const renderComponent = (
|
|
|
162
163
|
}
|
|
163
164
|
|
|
164
165
|
const addTextPart = (text: string, formatting: Formatting) => {
|
|
166
|
+
if (!textRendered) {
|
|
167
|
+
textRendered = text.trim() !== ''
|
|
168
|
+
}
|
|
165
169
|
plainText += text
|
|
166
170
|
textWidths[textOffset] = ctx.measureText(plainText).width
|
|
167
171
|
let color = formatting.color ?? defaultColor
|
|
@@ -214,4 +218,6 @@ export const renderComponent = (
|
|
|
214
218
|
}
|
|
215
219
|
renderedWidth += ctx.measureText(text).width
|
|
216
220
|
}
|
|
221
|
+
|
|
222
|
+
return textRendered
|
|
217
223
|
}
|
package/src/three/cameraShake.ts
CHANGED
|
@@ -10,7 +10,7 @@ export class CameraShake {
|
|
|
10
10
|
private basePitch = 0
|
|
11
11
|
private baseYaw = 0
|
|
12
12
|
|
|
13
|
-
constructor(public worldRenderer: WorldRendererThree, public onRenderCallbacks: Array<() => void>) {
|
|
13
|
+
constructor(public worldRenderer: WorldRendererThree, public onRenderCallbacks: Array<(deltaTime: number) => void>) {
|
|
14
14
|
onRenderCallbacks.push(() => {
|
|
15
15
|
this.update()
|
|
16
16
|
})
|
package/src/three/entities.ts
CHANGED
|
@@ -133,21 +133,25 @@ function getUsernameTexture({
|
|
|
133
133
|
|
|
134
134
|
ctx.globalAlpha = nameTagTextOpacity / 255
|
|
135
135
|
|
|
136
|
-
renderComponent(username, PrismarineChat, canvas, fontSize, 'white', -padding + fontSize)
|
|
136
|
+
const textRendered = renderComponent(username, PrismarineChat, canvas, fontSize, 'white', -padding + fontSize)
|
|
137
|
+
if (!textRendered) return undefined
|
|
137
138
|
|
|
138
139
|
ctx.globalAlpha = 1
|
|
139
140
|
|
|
140
141
|
return canvas
|
|
141
142
|
}
|
|
142
143
|
|
|
144
|
+
globalThis.getUsernameTexture = getUsernameTexture
|
|
145
|
+
|
|
143
146
|
const addNametag = (entity, options: { fontFamily: string }, mesh, version: string) => {
|
|
144
147
|
for (const c of mesh.children) {
|
|
145
148
|
if (c.name === 'nametag') {
|
|
146
149
|
c.removeFromParent()
|
|
147
150
|
}
|
|
148
151
|
}
|
|
149
|
-
if (entity.username !== undefined) {
|
|
152
|
+
if (entity.username !== undefined && !entity.username.startsWith('EMPTY')) {
|
|
150
153
|
const canvas = getUsernameTexture(entity, options, version)
|
|
154
|
+
if (!canvas) return
|
|
151
155
|
const tex = new THREE.Texture(canvas)
|
|
152
156
|
tex.needsUpdate = true
|
|
153
157
|
let nameTag: THREE.Object3D
|
|
@@ -13,6 +13,7 @@ import { WorldRendererThree } from '../worldRendererThree'
|
|
|
13
13
|
import entities from './entities.json'
|
|
14
14
|
import { externalModels } from './objModels'
|
|
15
15
|
import externalTexturesJson from './externalTextures.json'
|
|
16
|
+
import { createAnimatedObject } from './gltfAnimationUtils'
|
|
16
17
|
|
|
17
18
|
interface ElemFace {
|
|
18
19
|
dir: [number, number, number]
|
|
@@ -67,6 +68,8 @@ interface EntityOverrides {
|
|
|
67
68
|
offset?: { x?: number, y?: number, z?: number }
|
|
68
69
|
texture?: string
|
|
69
70
|
textures?: Record<string, string>
|
|
71
|
+
animation?: string
|
|
72
|
+
animationLoop?: boolean
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
}
|
|
@@ -242,23 +245,23 @@ export function getMesh(
|
|
|
242
245
|
overrides: EntityOverrides = {},
|
|
243
246
|
debugFlags: EntityDebugFlags = {}
|
|
244
247
|
): THREE.SkinnedMesh {
|
|
245
|
-
|
|
246
|
-
|
|
248
|
+
let textureWidth = jsonModel.texturewidth ?? 64
|
|
249
|
+
let textureHeight = jsonModel.textureheight ?? 64
|
|
247
250
|
let textureOffset: number[] | undefined
|
|
248
251
|
const useBlockTexture = texture.startsWith('block:')
|
|
249
252
|
const blocksTexture = worldRenderer?.material.map
|
|
250
253
|
if (useBlockTexture) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
254
|
+
if (!worldRenderer) throw new Error('worldRenderer is required for block textures')
|
|
255
|
+
const blockName = texture.slice(6)
|
|
256
|
+
const textureInfo = worldRenderer.resourcesManager.currentResources.blocksAtlasJson.textures[blockName]
|
|
257
|
+
if (textureInfo) {
|
|
258
|
+
textureWidth = blocksTexture?.image.width ?? textureWidth
|
|
259
|
+
textureHeight = blocksTexture?.image.height ?? textureHeight
|
|
260
|
+
// todo support su/sv
|
|
261
|
+
textureOffset = [textureInfo.u, textureInfo.v]
|
|
262
|
+
} else {
|
|
263
|
+
console.error(`Unknown block ${blockName}`)
|
|
264
|
+
}
|
|
262
265
|
}
|
|
263
266
|
|
|
264
267
|
const bones: Record<string, THREE.Bone> = {}
|
|
@@ -450,7 +453,9 @@ export type EntityDebugFlags = {
|
|
|
450
453
|
export class EntityMesh {
|
|
451
454
|
mesh!: THREE.Object3D
|
|
452
455
|
animations?: THREE.AnimationClip[]
|
|
453
|
-
|
|
456
|
+
private animationController?: ReturnType<typeof createAnimatedObject>
|
|
457
|
+
private initialAnimation?: string
|
|
458
|
+
private initialLoop?: boolean
|
|
454
459
|
|
|
455
460
|
constructor(
|
|
456
461
|
version: string,
|
|
@@ -468,17 +473,19 @@ export class EntityMesh {
|
|
|
468
473
|
|
|
469
474
|
// Handle custom model override
|
|
470
475
|
if (overrides.customModel) {
|
|
476
|
+
// empty mesh to allow "handled" entity and not pink box
|
|
477
|
+
this.mesh = new THREE.Object3D()
|
|
478
|
+
|
|
471
479
|
const { modelPath, modelType, metadata } = overrides.customModel
|
|
472
480
|
|
|
473
481
|
switch (modelType) {
|
|
474
482
|
case 'gltf': {
|
|
475
483
|
const loader = new GLTFLoader()
|
|
476
|
-
const gltfData = loader.parseAsync(modelPath
|
|
484
|
+
const gltfData = loader.parseAsync(modelPath, '')
|
|
477
485
|
|
|
478
486
|
gltfData.then(gltf => {
|
|
479
|
-
this.mesh
|
|
487
|
+
this.mesh.add(gltf.scene)
|
|
480
488
|
this.animations = gltf.animations
|
|
481
|
-
this.mixer = new THREE.AnimationMixer(this.mesh)
|
|
482
489
|
|
|
483
490
|
// Apply metadata overrides if available
|
|
484
491
|
if (metadata?.scale) {
|
|
@@ -505,6 +512,29 @@ export class EntityMesh {
|
|
|
505
512
|
}
|
|
506
513
|
})
|
|
507
514
|
}
|
|
515
|
+
|
|
516
|
+
// Handle animations: play from config if provided, otherwise play first animation if present
|
|
517
|
+
if (gltf.animations && gltf.animations.length > 0) {
|
|
518
|
+
this.animations = gltf.animations
|
|
519
|
+
const animationName = metadata?.animation
|
|
520
|
+
const loop = metadata?.animationLoop ?? true
|
|
521
|
+
|
|
522
|
+
// Store initial animation settings for later use
|
|
523
|
+
this.initialAnimation = animationName
|
|
524
|
+
this.initialLoop = loop
|
|
525
|
+
|
|
526
|
+
// Create animation controller with onBeforeRender support
|
|
527
|
+
this.animationController = createAnimatedObject(this.mesh, gltf.animations)
|
|
528
|
+
|
|
529
|
+
if (animationName) {
|
|
530
|
+
// Play animation from config
|
|
531
|
+
this.playAnimation(animationName, loop)
|
|
532
|
+
} else {
|
|
533
|
+
// Play first animation
|
|
534
|
+
const clip = gltf.animations[0]
|
|
535
|
+
this.animationController.playAnimation(clip.name, loop)
|
|
536
|
+
}
|
|
537
|
+
}
|
|
508
538
|
}).catch(err => {
|
|
509
539
|
console.error('Failed to load GLTF model:', err)
|
|
510
540
|
})
|
|
@@ -666,29 +696,21 @@ export class EntityMesh {
|
|
|
666
696
|
}
|
|
667
697
|
|
|
668
698
|
playAnimation(name: string, loop = false) {
|
|
669
|
-
if (!this.
|
|
670
|
-
|
|
671
|
-
// Find animation by name
|
|
672
|
-
const clip = this.animations.find(a => a.name === name)
|
|
673
|
-
if (!clip) {
|
|
674
|
-
console.warn(`Animation "${name}" not found`)
|
|
699
|
+
if (!this.animationController || !this.animations) {
|
|
700
|
+
console.warn('No animation controller available')
|
|
675
701
|
return
|
|
676
702
|
}
|
|
677
703
|
|
|
678
|
-
//
|
|
679
|
-
this.
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
action.setLoop(loop ? THREE.LoopRepeat : THREE.LoopOnce, Infinity)
|
|
684
|
-
action.clampWhenFinished = !loop
|
|
685
|
-
action.reset().play()
|
|
704
|
+
// Play animation using the controller
|
|
705
|
+
const success = this.animationController.playAnimation(name, loop)
|
|
706
|
+
if (!success) {
|
|
707
|
+
console.warn(`Animation "${name}" not found`)
|
|
708
|
+
}
|
|
686
709
|
}
|
|
687
710
|
|
|
688
711
|
update(deltaTime: number) {
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
}
|
|
712
|
+
// Animation updates are now handled by onBeforeRender callback
|
|
713
|
+
// This method is kept for compatibility but no longer needed
|
|
692
714
|
}
|
|
693
715
|
|
|
694
716
|
static getStaticData(name: string): { boneNames: string[] } {
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import * as THREE from 'three'
|
|
3
|
+
|
|
4
|
+
export interface AnimationState {
|
|
5
|
+
mixer: THREE.AnimationMixer
|
|
6
|
+
animations: THREE.AnimationClip[]
|
|
7
|
+
actions: Map<string, THREE.AnimationAction>
|
|
8
|
+
speed: number
|
|
9
|
+
loop: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class AnimationManager {
|
|
13
|
+
private readonly clock = new THREE.Clock()
|
|
14
|
+
private readonly animatedObjects = new Set<THREE.Object3D>()
|
|
15
|
+
state!: AnimationState
|
|
16
|
+
|
|
17
|
+
constructor(
|
|
18
|
+
public object: THREE.Object3D,
|
|
19
|
+
public animations: THREE.AnimationClip[]
|
|
20
|
+
) {
|
|
21
|
+
// Private constructor for singleton
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Creates an animation state for a Three.js object
|
|
26
|
+
*/
|
|
27
|
+
createAnimationState(): AnimationState {
|
|
28
|
+
const mixer = new THREE.AnimationMixer(this.object)
|
|
29
|
+
const actions = new Map<string, THREE.AnimationAction>()
|
|
30
|
+
|
|
31
|
+
// Store clips as actions for easy access
|
|
32
|
+
for (const clip of this.animations) {
|
|
33
|
+
actions.set(clip.name, mixer.clipAction(clip))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
this.state = {
|
|
37
|
+
mixer,
|
|
38
|
+
animations: this.animations,
|
|
39
|
+
actions,
|
|
40
|
+
speed: 1,
|
|
41
|
+
loop: true
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Set up onBeforeRender callback for renderable objects
|
|
45
|
+
// onBeforeRender only works on renderable objects (Mesh, Line, Points, Sprite)
|
|
46
|
+
this.object.traverse((child) => {
|
|
47
|
+
if (child instanceof THREE.Mesh || child instanceof THREE.Line || child instanceof THREE.Points || child instanceof THREE.Sprite) {
|
|
48
|
+
const originalOnBeforeRender = child.onBeforeRender
|
|
49
|
+
child.onBeforeRender = (renderer, scene, camera, geometry, material, group) => {
|
|
50
|
+
const delta = this.clock.getDelta()
|
|
51
|
+
mixer.update(delta)
|
|
52
|
+
// Call original onBeforeRender if it existed
|
|
53
|
+
originalOnBeforeRender?.(renderer, scene, camera, geometry, material, group)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
// Track animated objects
|
|
59
|
+
this.animatedObjects.add(this.object)
|
|
60
|
+
|
|
61
|
+
return this.state
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Plays an animation by name
|
|
66
|
+
*/
|
|
67
|
+
playAnimation(name: string, loop?: boolean, speed?: number): boolean {
|
|
68
|
+
const action = this.state.actions.get(name)
|
|
69
|
+
if (!action) {
|
|
70
|
+
console.warn(`Animation "${name}" not found`)
|
|
71
|
+
return false
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Stop any existing animations
|
|
75
|
+
this.state.mixer.stopAllAction()
|
|
76
|
+
|
|
77
|
+
// Configure animation
|
|
78
|
+
const shouldLoop = loop ?? this.state.loop
|
|
79
|
+
action.setLoop(shouldLoop ? THREE.LoopRepeat : THREE.LoopOnce, Infinity)
|
|
80
|
+
action.clampWhenFinished = !shouldLoop
|
|
81
|
+
|
|
82
|
+
if (speed === undefined) {
|
|
83
|
+
action.timeScale = this.state.speed
|
|
84
|
+
} else {
|
|
85
|
+
action.timeScale = speed
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
action.reset().fadeIn(0.1).play()
|
|
89
|
+
return true
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Updates animation parameters for a state
|
|
94
|
+
*/
|
|
95
|
+
updateAnimationParams(speed?: number, loop?: boolean): void {
|
|
96
|
+
if (speed !== undefined) {
|
|
97
|
+
this.state.speed = speed
|
|
98
|
+
}
|
|
99
|
+
if (loop !== undefined) {
|
|
100
|
+
this.state.loop = loop
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Update existing actions
|
|
104
|
+
for (const action of this.state.actions.values()) {
|
|
105
|
+
if (speed !== undefined) {
|
|
106
|
+
action.timeScale = speed
|
|
107
|
+
}
|
|
108
|
+
if (loop !== undefined) {
|
|
109
|
+
action.setLoop(loop ? THREE.LoopRepeat : THREE.LoopOnce, Infinity)
|
|
110
|
+
action.clampWhenFinished = !loop
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Stops all animations for a state
|
|
117
|
+
*/
|
|
118
|
+
stopAnimations(): void {
|
|
119
|
+
this.state.mixer.stopAllAction()
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Gets the current clock delta (useful for manual updates)
|
|
124
|
+
*/
|
|
125
|
+
getDelta(): number {
|
|
126
|
+
return this.clock.getDelta()
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Convenience function to create and manage animations for an object
|
|
132
|
+
*/
|
|
133
|
+
export function createAnimatedObject(
|
|
134
|
+
object: THREE.Object3D,
|
|
135
|
+
animations: THREE.AnimationClip[]
|
|
136
|
+
) {
|
|
137
|
+
const manager = new AnimationManager(object, animations)
|
|
138
|
+
manager.createAnimationState()
|
|
139
|
+
|
|
140
|
+
return manager
|
|
141
|
+
}
|
|
@@ -12,9 +12,9 @@ interface RainParticleData {
|
|
|
12
12
|
const PARTICLE_COUNT = 2000
|
|
13
13
|
const RANGE = 32
|
|
14
14
|
const HEIGHT = 32
|
|
15
|
-
const FALL_SPEED_MIN =
|
|
16
|
-
const FALL_SPEED_MAX =
|
|
17
|
-
const HORIZONTAL_DRIFT =
|
|
15
|
+
const FALL_SPEED_MIN = 12
|
|
16
|
+
const FALL_SPEED_MAX = 24
|
|
17
|
+
const HORIZONTAL_DRIFT = 1.2
|
|
18
18
|
const RESPAWN_BELOW = -5
|
|
19
19
|
|
|
20
20
|
export class RainModule implements RendererModuleController {
|
|
@@ -52,7 +52,7 @@ export class RainModule implements RendererModuleController {
|
|
|
52
52
|
return this.worldRenderer.worldRendererConfig.isRaining === true
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
render?: () => void = () => {
|
|
55
|
+
render?: (deltaTime: number) => void = (deltaTime) => {
|
|
56
56
|
if (!this.enabled || !this.instancedMesh) return
|
|
57
57
|
|
|
58
58
|
const cameraPos = this.worldRenderer.getCameraPosition()
|
|
@@ -72,7 +72,7 @@ export class RainModule implements RendererModuleController {
|
|
|
72
72
|
this.instancedMesh.getMatrixAt(i, dummy)
|
|
73
73
|
dummy.decompose(position, quaternion, scale)
|
|
74
74
|
|
|
75
|
-
position.
|
|
75
|
+
position.addScaledVector(particle.velocity, deltaTime)
|
|
76
76
|
|
|
77
77
|
const relativeY = position.y
|
|
78
78
|
const horizontalDist = Math.sqrt(position.x * position.x + position.z * position.z)
|
|
@@ -108,9 +108,9 @@ export class SciFiWorldRevealModule implements RendererModuleController {
|
|
|
108
108
|
return this.enabled
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
render?: () => void = () => {
|
|
111
|
+
render?: (deltaTime: number) => void = (deltaTime) => {
|
|
112
112
|
if (!this.enabled) return
|
|
113
|
-
this.update(
|
|
113
|
+
this.update(deltaTime * 1000)
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
dispose(): void {
|
|
@@ -72,7 +72,7 @@ export class StarfieldModule implements RendererModuleController {
|
|
|
72
72
|
return this.currentTime > nightTime && this.currentTime < morningStart
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
render?: () => void = () => {
|
|
75
|
+
render?: (deltaTime: number) => void = (_deltaTime) => {
|
|
76
76
|
if (!this.points) return
|
|
77
77
|
this.points.position.copy(this.worldRenderer.getCameraPosition())
|
|
78
78
|
; (this.points.material as StarfieldMaterial).uniforms.time.value =
|
|
@@ -11,7 +11,7 @@ export interface RendererModuleController {
|
|
|
11
11
|
|
|
12
12
|
enablementCheck?: () => boolean
|
|
13
13
|
autoEnableCheck?: () => boolean // Called when config updates, returns true to enable, false to disable
|
|
14
|
-
render?: () => void
|
|
14
|
+
render?: (deltaTime: number) => void
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -57,7 +57,8 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|
|
57
57
|
material = new THREE.MeshLambertMaterial({ vertexColors: true, transparent: true, alphaTest: 0.1 })
|
|
58
58
|
itemsTexture!: THREE.Texture
|
|
59
59
|
cursorBlock: CursorBlock
|
|
60
|
-
onRender: Array<() => void> = []
|
|
60
|
+
onRender: Array<(deltaTime: number) => void> = []
|
|
61
|
+
private lastRenderTime = 0
|
|
61
62
|
cameraShake: CameraShake
|
|
62
63
|
cameraContainer!: THREE.Object3D
|
|
63
64
|
media: ThreeJsMedia
|
|
@@ -928,6 +929,10 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|
|
928
929
|
this.debugChunksVisibilityOverride()
|
|
929
930
|
const start = performance.now()
|
|
930
931
|
this.lastRendered = performance.now()
|
|
932
|
+
const deltaTime = this.lastRenderTime > 0
|
|
933
|
+
? Math.min(Math.max((start - this.lastRenderTime) / 1000, 0), 0.1)
|
|
934
|
+
: 1 / 60
|
|
935
|
+
this.lastRenderTime = start
|
|
931
936
|
this.cursorBlock.render()
|
|
932
937
|
this.updateSectionOffsets()
|
|
933
938
|
|
|
@@ -974,7 +979,7 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|
|
974
979
|
this.fireworks.update()
|
|
975
980
|
|
|
976
981
|
for (const onRender of this.onRender) {
|
|
977
|
-
onRender()
|
|
982
|
+
onRender(deltaTime)
|
|
978
983
|
}
|
|
979
984
|
const end = performance.now()
|
|
980
985
|
const totalTime = end - start
|
package/wasm/wasm_mesher.d.ts
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* Input: Serialized chunk data as TypedArrays
|
|
8
8
|
* Output: Geometry data (positions, normals, colors, uvs, indices)
|
|
9
9
|
*/
|
|
10
|
-
export function generate_geometry(section_x: number, section_y: number, section_z: number, section_height: number, world_min_y: number, world_max_y: number,
|
|
10
|
+
export function generate_geometry(section_x: number, section_y: number, section_z: number, section_height: number, world_min_y: number, world_max_y: number, block_states: Uint16Array, block_light: Uint8Array, sky_light: Uint8Array, biomes: Uint8Array, invisible_blocks: Uint16Array, transparent_blocks: Uint16Array, no_ao_blocks: Uint16Array, cull_identical_blocks: Uint16Array, occluding_blocks: Uint16Array, enable_lighting: boolean, smooth_lighting: boolean, sky_light_value: number): any;
|
|
11
11
|
|
|
12
|
-
export function generate_geometry_multi(section_x: number, section_y: number, section_z: number, section_height: number, world_min_y: number, world_max_y: number,
|
|
12
|
+
export function generate_geometry_multi(section_x: number, section_y: number, section_z: number, section_height: number, world_min_y: number, world_max_y: number, chunk_xs: Int32Array, chunk_zs: Int32Array, block_states: Uint16Array, block_light: Uint8Array, sky_light: Uint8Array, biomes: Uint8Array, invisible_blocks: Uint16Array, transparent_blocks: Uint16Array, no_ao_blocks: Uint16Array, cull_identical_blocks: Uint16Array, occluding_blocks: Uint16Array, enable_lighting: boolean, smooth_lighting: boolean, sky_light_value: number): any;
|
|
13
13
|
|
|
14
14
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
15
15
|
|
package/wasm/wasm_mesher.js
CHANGED
|
@@ -227,7 +227,6 @@ let WASM_VECTOR_LEN = 0;
|
|
|
227
227
|
* @param {number} section_height
|
|
228
228
|
* @param {number} world_min_y
|
|
229
229
|
* @param {number} world_max_y
|
|
230
|
-
* @param {number} section_data_start_y
|
|
231
230
|
* @param {Uint16Array} block_states
|
|
232
231
|
* @param {Uint8Array} block_light
|
|
233
232
|
* @param {Uint8Array} sky_light
|
|
@@ -242,14 +241,13 @@ let WASM_VECTOR_LEN = 0;
|
|
|
242
241
|
* @param {number} sky_light_value
|
|
243
242
|
* @returns {any}
|
|
244
243
|
*/
|
|
245
|
-
export function generate_geometry(section_x, section_y, section_z, section_height, world_min_y, world_max_y,
|
|
244
|
+
export function generate_geometry(section_x, section_y, section_z, section_height, world_min_y, world_max_y, block_states, block_light, sky_light, biomes, invisible_blocks, transparent_blocks, no_ao_blocks, cull_identical_blocks, occluding_blocks, enable_lighting, smooth_lighting, sky_light_value) {
|
|
246
245
|
_assertNum(section_x);
|
|
247
246
|
_assertNum(section_y);
|
|
248
247
|
_assertNum(section_z);
|
|
249
248
|
_assertNum(section_height);
|
|
250
249
|
_assertNum(world_min_y);
|
|
251
250
|
_assertNum(world_max_y);
|
|
252
|
-
_assertNum(section_data_start_y);
|
|
253
251
|
const ptr0 = passArray16ToWasm0(block_states, wasm.__wbindgen_malloc);
|
|
254
252
|
const len0 = WASM_VECTOR_LEN;
|
|
255
253
|
const ptr1 = passArray8ToWasm0(block_light, wasm.__wbindgen_malloc);
|
|
@@ -271,7 +269,7 @@ export function generate_geometry(section_x, section_y, section_z, section_heigh
|
|
|
271
269
|
_assertBoolean(enable_lighting);
|
|
272
270
|
_assertBoolean(smooth_lighting);
|
|
273
271
|
_assertNum(sky_light_value);
|
|
274
|
-
const ret = wasm.generate_geometry(section_x, section_y, section_z, section_height, world_min_y, world_max_y,
|
|
272
|
+
const ret = wasm.generate_geometry(section_x, section_y, section_z, section_height, world_min_y, world_max_y, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4, ptr5, len5, ptr6, len6, ptr7, len7, ptr8, len8, enable_lighting, smooth_lighting, sky_light_value);
|
|
275
273
|
return ret;
|
|
276
274
|
}
|
|
277
275
|
|
|
@@ -298,14 +296,13 @@ export function generate_geometry(section_x, section_y, section_z, section_heigh
|
|
|
298
296
|
* @param {number} sky_light_value
|
|
299
297
|
* @returns {any}
|
|
300
298
|
*/
|
|
301
|
-
export function generate_geometry_multi(section_x, section_y, section_z, section_height, world_min_y, world_max_y,
|
|
299
|
+
export function generate_geometry_multi(section_x, section_y, section_z, section_height, world_min_y, world_max_y, chunk_xs, chunk_zs, block_states, block_light, sky_light, biomes, invisible_blocks, transparent_blocks, no_ao_blocks, cull_identical_blocks, occluding_blocks, enable_lighting, smooth_lighting, sky_light_value) {
|
|
302
300
|
_assertNum(section_x);
|
|
303
301
|
_assertNum(section_y);
|
|
304
302
|
_assertNum(section_z);
|
|
305
303
|
_assertNum(section_height);
|
|
306
304
|
_assertNum(world_min_y);
|
|
307
305
|
_assertNum(world_max_y);
|
|
308
|
-
_assertNum(section_data_start_y);
|
|
309
306
|
const ptr0 = passArray32ToWasm0(chunk_xs, wasm.__wbindgen_malloc);
|
|
310
307
|
const len0 = WASM_VECTOR_LEN;
|
|
311
308
|
const ptr1 = passArray32ToWasm0(chunk_zs, wasm.__wbindgen_malloc);
|
|
@@ -331,7 +328,7 @@ export function generate_geometry_multi(section_x, section_y, section_z, section
|
|
|
331
328
|
_assertBoolean(enable_lighting);
|
|
332
329
|
_assertBoolean(smooth_lighting);
|
|
333
330
|
_assertNum(sky_light_value);
|
|
334
|
-
const ret = wasm.generate_geometry_multi(section_x, section_y, section_z, section_height, world_min_y, world_max_y,
|
|
331
|
+
const ret = wasm.generate_geometry_multi(section_x, section_y, section_z, section_height, world_min_y, world_max_y, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4, ptr5, len5, ptr6, len6, ptr7, len7, ptr8, len8, ptr9, len9, ptr10, len10, enable_lighting, smooth_lighting, sky_light_value);
|
|
335
332
|
return ret;
|
|
336
333
|
}
|
|
337
334
|
|