Skip to content

Commit 1349373

Browse files
committed
chunkLoading priority queue
1 parent a466156 commit 1349373

File tree

4 files changed

+106
-85
lines changed

4 files changed

+106
-85
lines changed

src/client/scripts/World/ChunkMesher.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ const CustomRender = {
164164
pos
165165
) {
166166
const uv = this.getUV("grass");
167-
console.log(uv);
167+
// console.log(uv);
168168
// prettier-ignore
169169
const faceVertex = {
170170
pos: [
@@ -326,7 +326,7 @@ class ChunkMesher {
326326

327327
getUV(name) {
328328
let { x: toxX, y: toxY } = this.blocksMapping[name];
329-
console.log(toxX);
329+
// console.log(toxX);
330330
toxX -= 1;
331331
toxY -= 1;
332332
const x1 = this.q * toxX;

src/client/scripts/World/ChunkTerrain.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ class ChunkTerrain {
99
this.blocksDef = options.blocksDef;
1010
}
1111

12-
vec3(x, y, z) {
13-
x = parseInt(x);
14-
y = parseInt(y);
15-
z = parseInt(z);
16-
return `${x}:${y}:${z}`;
12+
vecToStr(x, y, z) {
13+
return `${parseInt(x)}:${parseInt(y)}:${parseInt(z)}`;
14+
}
15+
16+
strToVec(str) {
17+
str = str.split(":");
18+
return [parseInt(str[0]), parseInt(str[1]), parseInt(str[2])];
1719
}
1820

1921
computeVoxelOffset(voxelX, voxelY, voxelZ) {
@@ -32,7 +34,7 @@ class ChunkTerrain {
3234
}
3335

3436
addChunkForVoxel(voxelX, voxelY, voxelZ) {
35-
var cellId = this.vec3(
37+
var cellId = this.vecToStr(
3638
...this.computeChunkForVoxel(voxelX, voxelY, voxelZ)
3739
);
3840
var cell = this.chunks[cellId];
@@ -46,7 +48,7 @@ class ChunkTerrain {
4648
}
4749

4850
getChunkForVoxel(voxelX, voxelY, voxelZ) {
49-
var cellId = this.vec3(
51+
var cellId = this.vecToStr(
5052
...this.computeChunkForVoxel(voxelX, voxelY, voxelZ)
5153
);
5254
return this.chunks[cellId];
@@ -71,7 +73,7 @@ class ChunkTerrain {
7173
}
7274

7375
setChunk(chunkX, chunkY, chunkZ, buffer) {
74-
this.chunks[this.vec3(chunkX, chunkY, chunkZ)] = buffer;
76+
this.chunks[this.vecToStr(chunkX, chunkY, chunkZ)] = buffer;
7577
}
7678

7779
getBlock(blockX, blockY, blockZ) {

src/client/scripts/World/World.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ var World = class World {
5555
*/
5656
updateRenderOrder(cell) {
5757
for (var i in this.cellMesh) {
58-
var n = i.split(":");
59-
var x = new vec3(parseInt(n[0]), parseInt(n[1]), parseInt(n[2]));
58+
var x = new vec3(this.chunkTerrain.strToVec(i));
6059
this.cellMesh[i].renderOrder = -vec3(...cell).distanceTo(x);
6160
}
6261
}
@@ -110,7 +109,7 @@ var World = class World {
110109
* @param data - cell Data
111110
*/
112111
updateChunk(data) {
113-
var cellId = this.chunkTerrain.vec3(...data.info);
112+
var cellId = this.chunkTerrain.vecToStr(...data.info);
114113
var cell = data.cell;
115114
var mesh = this.cellMesh[cellId];
116115
var geometry = new THREE.BufferGeometry();

src/client/scripts/World/chunk.worker.js

Lines changed: 92 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ChunkTerrain } from "./ChunkTerrain.js";
22
import { ChunkMesher } from "./ChunkMesher.js";
3+
import vec3 from "vec3";
34

45
var terrain = null;
56

@@ -8,8 +9,6 @@ class TerrainManager {
89
this.chunkTerrain = new ChunkTerrain({
910
blocksDef: data.blocksDef,
1011
});
11-
this.chunkNeedsUpdate = {};
12-
this.loadedMeshes = {};
1312
this.chunkMesher = new ChunkMesher({
1413
blocksTex: data.blocksTex,
1514
blocksMapping: data.blocksMapping,
@@ -24,114 +23,135 @@ class TerrainManager {
2423
[0, 0, -1],
2524
[0, 0, 1],
2625
];
26+
this.states = {
27+
needsUpdate: 0,
28+
disposed: 1,
29+
};
30+
this.chunkState = {};
31+
this.generatedChunks = {};
32+
this.renderRadius = 10;
33+
this.playerChunk = [0, 0, 0];
34+
this.loop();
2735
}
36+
37+
distance(chunkId) {
38+
var data = this.chunkTerrain.strToVec(chunkId);
39+
var chunk = vec3(...data);
40+
var chunkP = vec3(...this.playerChunk);
41+
return chunkP.distanceTo(chunk);
42+
}
43+
2844
setVoxel(data) {
2945
this.chunkTerrain.setVoxel(...data);
30-
var chunkId = this.chunkTerrain.vec3(
46+
var chunkId = this.chunkTerrain.vecToStr(
3147
...terrain.chunkTerrain.computeChunkForVoxel(
3248
data[0],
3349
data[1],
3450
data[2]
3551
)
3652
);
37-
this.chunkNeedsUpdate[chunkId] = true;
53+
this.chunkState[chunkId] = this.states.needsUpdate;
3854
for (var l = 0; l < this.neighbours.length; l++) {
3955
var nei = this.neighbours[l];
40-
var neiChunkId = this.chunkTerrain.vec3(
56+
var neiChunkId = this.chunkTerrain.vecToStr(
4157
...this.chunkTerrain.computeChunkForVoxel(
4258
data[0] + nei[0],
4359
data[1] + nei[1],
4460
data[2] + nei[2]
4561
)
4662
);
47-
this.chunkNeedsUpdate[neiChunkId] = true;
63+
this.chunkState[neiChunkId] = this.states.needsUpdate;
4864
}
4965
}
50-
genChunkGeo(data) {
51-
queueMicrotask(() => {
52-
if (
53-
this.chunkTerrain.vec3(...data) in this.chunkTerrain.chunks ===
54-
true
55-
) {
56-
var geo = this.chunkMesher.genChunkGeo(...data);
57-
postMessage({
58-
type: "cellGeo",
59-
data: {
60-
cell: geo,
61-
info: data,
62-
p: performance.now(),
63-
},
64-
});
65-
}
66-
});
67-
}
66+
6867
setChunk(data) {
69-
this.chunkNeedsUpdate[
70-
terrain.chunkTerrain.vec3(data[0], data[1], data[2])
71-
] = true;
7268
this.chunkTerrain.setChunk(data[0], data[1], data[2], data[3]);
69+
var chunkId = terrain.chunkTerrain.vecToStr(data[0], data[1], data[2]);
70+
this.chunkState[chunkId] = this.states.needsUpdate;
7371
for (var l = 0; l < this.neighbours.length; l++) {
7472
var nei = this.neighbours[l];
75-
var neiCellId = this.chunkTerrain.vec3(
73+
var neiChunkId = this.chunkTerrain.vecToStr(
7674
data[0] + nei[0],
7775
data[1] + nei[1],
7876
data[2] + nei[2]
7977
);
80-
this.chunkNeedsUpdate[neiCellId] = true;
78+
this.chunkState[neiChunkId] = this.states.needsUpdate;
8179
}
8280
}
83-
updateChunksAroundPlayer(data) {
84-
var chunk = data[0];
85-
var radius = data[1];
86-
var odw = {};
87-
var chunkBlackList = {};
88-
for (var k in this.loadedMeshes) {
89-
var v = this.loadedMeshes[k];
90-
if (v === true) {
91-
chunkBlackList[k] = true;
81+
82+
sortQueue() {
83+
this.chunkQueue.sort((a, b) => {
84+
var chunkA = vec3(...this.chunkTerrain.strToVec(a));
85+
var chunkB = vec3(...this.chunkTerrain.strToVec(b));
86+
var chunkP = vec3(...this.playerChunk);
87+
var roz1 = chunkP.distanceTo(chunkA);
88+
var roz2 = chunkP.distanceTo(chunkB);
89+
if (roz1 < roz2) {
90+
return -1;
91+
} else if (roz1 > roz2) {
92+
return 1;
93+
} else {
94+
return 0;
9295
}
93-
}
94-
for (var i = 0; i <= radius; i++) {
95-
for (var x = -i; x <= i; x++) {
96-
for (var y = -i; y <= i; y++) {
97-
for (var z = -i; z <= i; z++) {
98-
if (!odw[`${x}:${y}:${z}`]) {
99-
odw[`${x}:${y}:${z}`] = true;
100-
var pchunk = [
101-
chunk[0] + x,
102-
chunk[1] + y,
103-
chunk[2] + z,
104-
];
105-
var chunkId = this.chunkTerrain.vec3(...pchunk);
106-
chunkBlackList[chunkId] = false;
107-
var gen = false;
108-
if (this.chunkNeedsUpdate[chunkId]) {
109-
delete terrain.chunkNeedsUpdate[chunkId];
110-
this.genChunkGeo(pchunk);
111-
gen = true;
112-
}
113-
if (this.loadedMeshes[chunkId] === "disposed") {
114-
if (!gen) {
115-
this.genChunkGeo(pchunk);
116-
}
117-
}
118-
this.loadedMeshes[chunkId] = true;
119-
}
120-
}
121-
}
96+
});
97+
}
98+
99+
genNearestChunk() {
100+
var nearestChunkId = "";
101+
var nearestDistance = -1;
102+
var isNearest = false;
103+
for (var chunkId in this.chunkState) {
104+
var dist = this.distance(chunkId);
105+
if (
106+
(nearestDistance === -1 || nearestDistance > dist) &&
107+
dist <= this.renderRadius
108+
) {
109+
isNearest = true;
110+
nearestDistance = dist;
111+
nearestChunkId = chunkId;
122112
}
123113
}
124-
for (k in chunkBlackList) {
125-
v = chunkBlackList[k];
126-
if (v === true) {
127-
this.loadedMeshes[k] = "disposed";
114+
if (isNearest) {
115+
var data = this.chunkTerrain.strToVec(nearestChunkId);
116+
this.generatedChunks[nearestChunkId] = true;
117+
postMessage({
118+
type: "cellGeo",
119+
data: {
120+
cell: this.chunkMesher.genChunkGeo(...data),
121+
info: data,
122+
p: performance.now(),
123+
},
124+
});
125+
delete this.chunkState[nearestChunkId];
126+
}
127+
}
128+
129+
removeChunks() {
130+
for (var chunkId in this.generatedChunks) {
131+
var dist = this.distance(chunkId);
132+
if (dist > this.renderRadius) {
133+
delete this.generatedChunks[chunkId];
134+
this.chunkState[chunkId] = this.states.disposed;
128135
postMessage({
129136
type: "removeCell",
130-
data: k,
137+
data: chunkId,
131138
});
132139
}
133140
}
134141
}
142+
143+
loop() {
144+
this.removeChunks();
145+
this.genNearestChunk();
146+
requestAnimationFrame(() => {
147+
this.loop();
148+
});
149+
}
150+
151+
updateChunksAroundPlayer(data) {
152+
this.playerChunk = data[0];
153+
this.renderRadius = data[1];
154+
}
135155
}
136156

137157
addEventListener("message", function (e) {

0 commit comments

Comments
 (0)