Skip to content

Commit 4c9b709

Browse files
committed
Smarter chunk loading
1 parent 4e335bc commit 4c9b709

File tree

5 files changed

+55
-66
lines changed

5 files changed

+55
-66
lines changed

client/src/chunk/chunk.h

-5
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,6 @@ typedef struct Chunk{
4343
bool onlyAir;
4444
} Chunk;
4545

46-
typedef struct QueuedChunk {
47-
Chunk *chunk;
48-
int state;
49-
} QueuedChunk;
50-
5146
typedef struct LightNode{
5247
int index;
5348
Chunk *chunk;

client/src/gui/screens.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ void Screen_MakeOptions(void) {
169169
if (newDrawDistance != world.drawDistance) {
170170
if(newDrawDistance > world.drawDistance) {
171171
world.drawDistance = newDrawDistance;
172-
World_LoadChunks(false);
172+
World_LoadChunks();
173173
} else {
174174
world.drawDistance = newDrawDistance;
175175
World_Reload();

client/src/player.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ void Player_Update() {
273273
if (floor(oldPosition.x / 16) != floor(player.position.x / 16) ||
274274
floor(oldPosition.y / 16) != floor(player.position.y / 16) ||
275275
floor(oldPosition.z / 16) != floor(player.position.z / 16)) {
276-
World_LoadChunks(true);
276+
World_LoadChunks();
277277
}
278278

279279
//Place Camera

client/src/world.c

+48-56
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ void World_LoadSingleplayer(void) {
6666
Screen_Switch(SCREEN_GAME);
6767

6868
world.loadChunks = true;
69-
World_LoadChunks(false);
69+
World_LoadChunks();
7070
}
7171

7272
clock_t updateClock;
@@ -82,17 +82,24 @@ void World_Update(void) {
8282
}
8383

8484
pthread_mutex_t chunk_mutex;
85+
pthread_mutex_t genChunk_mutex;
8586
void *World_ReadChunksQueues(void *state) {
8687
while(true) {
8788

8889
pthread_mutex_lock(&chunk_mutex);
8990

90-
QueuedChunk *queuedChunk = world.generateChunksQueue;
91-
92-
if(world.loadChunks == true && queuedChunk != NULL) {
93-
Chunk_Generate(queuedChunk->chunk);
91+
if(world.loadChunks == true) {
92+
93+
Vector3 pos = (Vector3) {(int)floor(player.position.x / CHUNK_SIZE_X), (int)floor(player.position.y / CHUNK_SIZE_Y), (int)floor(player.position.z / CHUNK_SIZE_Z)};
94+
int index = World_GetClosestChunkIndex(world.generateChunksQueue, pos);
9495

95-
if(arrlen(world.generateChunksQueue) > 0) arrdel(world.generateChunksQueue, 0);
96+
if(index != -1) {
97+
Chunk_Generate(world.generateChunksQueue[index]);
98+
pthread_mutex_lock(&genChunk_mutex);
99+
arrdel(world.generateChunksQueue, index);
100+
pthread_mutex_unlock(&genChunk_mutex);
101+
}
102+
96103
}
97104

98105
pthread_mutex_unlock(&chunk_mutex);
@@ -101,22 +108,35 @@ void *World_ReadChunksQueues(void *state) {
101108
return NULL;
102109
}
103110

111+
int World_GetClosestChunkIndex(Chunk* *array, Vector3 pos) {
112+
int arrLength = arrlen(array);
113+
if(arrLength > 0) {
114+
Chunk* queuedChunk = array[0];
115+
int index = 0;
116+
for(int i = 0; i < arrLength; i++) {
117+
if(Vector3Distance(array[i]->position, pos) < Vector3Distance(queuedChunk->position, pos)) {
118+
queuedChunk = array[i];
119+
index = i;
120+
}
121+
}
122+
return index;
123+
}
124+
125+
return -1;
126+
}
127+
104128
void World_QueueChunk(Chunk *chunk) {
105129

106130
if(chunk->hasStartedGenerating == false) {
107-
QueuedChunk queued;
108-
queued.chunk = chunk;
109-
queued.state = 0;
110-
arrput(world.generateChunksQueue, queued);
131+
pthread_mutex_lock(&genChunk_mutex);
132+
arrput(world.generateChunksQueue, chunk);
133+
pthread_mutex_unlock(&genChunk_mutex);
111134

112135
}
113136
chunk->hasStartedGenerating = true;
114137

115138
if(chunk->isBuilding == false) {
116-
QueuedChunk queued;
117-
queued.chunk = chunk;
118-
queued.state = 0;
119-
arrput(world.buildChunksQueue, queued);
139+
arrput(world.buildChunksQueue, chunk);
120140
chunk->isBuilding = true;
121141
}
122142
}
@@ -164,68 +184,40 @@ void World_UpdateChunks(void) {
164184

165185
int meshUpdatesCount = 4;
166186

167-
for (int i = arrlen(world.buildChunksQueue) - 1; i >= 0; i--) {
168-
Chunk *chunk = world.buildChunksQueue[i].chunk;
187+
for (int i = 0; i < meshUpdatesCount; i++) {
188+
Vector3 pos = (Vector3) {(int)floor(player.position.x / CHUNK_SIZE_X), (int)floor(player.position.y / CHUNK_SIZE_Y), (int)floor(player.position.z / CHUNK_SIZE_Z)};
189+
int index = World_GetClosestChunkIndex(world.buildChunksQueue, pos);
190+
if(index == -1) continue;
191+
Chunk *chunk = world.buildChunksQueue[index];
169192
if(chunk->isLightGenerated == true) {
170193
if(Chunk_AreNeighbourGenerated(chunk) == true) {
171194
Chunk_BuildMesh(chunk);
172195
chunk->isBuilding = false;
173-
arrdel(world.buildChunksQueue, i);
174-
if(--meshUpdatesCount == 0) return;
196+
arrdel(world.buildChunksQueue, index);
175197

176198
continue;
177199
}
178200
}
179201
}
202+
180203
}
181204

182-
void World_LoadChunks(bool loadEdges) {
205+
void World_LoadChunks(void) {
183206

184207
if(!world.loadChunks) return;
185208

186209
Vector3 pos = (Vector3) {(int)floor(player.position.x / CHUNK_SIZE_X), (int)floor(player.position.y / CHUNK_SIZE_Y), (int)floor(player.position.z / CHUNK_SIZE_Z)};
187-
210+
188211
//Create chunks or prepare array of chunks to be sorted
189212
int loadingHeight = fmin(world.drawDistance, 4);
190-
int sortedLength = 0;
191-
struct { Vector3 chunkPos; float dist; } sortedChunks[(world.drawDistance + 1) * 2 * (world.drawDistance + 1) * 2 * (loadingHeight + 1) * 2];
192-
for(int x = -world.drawDistance ; x <= world.drawDistance; x++) {
193-
for(int z = -world.drawDistance ; z <= world.drawDistance; z++) {
194-
for(int y = -loadingHeight ; y <= loadingHeight; y++) {
213+
for(int y = loadingHeight; y >= -loadingHeight; y--) {
214+
for(int x = -world.drawDistance ; x <= world.drawDistance; x++) {
215+
for(int z = -world.drawDistance ; z <= world.drawDistance; z++) {
195216
Vector3 chunkPos = (Vector3) {pos.x + x, pos.y + y, pos.z + z};
196-
if(!loadEdges) {
197-
sortedChunks[sortedLength].chunkPos = chunkPos;
198-
sortedChunks[sortedLength].dist = Vector3Distance(chunkPos, pos);
199-
sortedLength++;
200-
} else if(Vector3Distance(chunkPos, pos) >= world.drawDistance - 1) {
201-
World_AddChunk(chunkPos);
202-
}
217+
World_AddChunk(chunkPos);
203218
}
204219
}
205220
}
206-
207-
if(!loadEdges) {
208-
//Sort array of chunks front to back
209-
for(int i = 1; i < sortedLength; i++) {
210-
int j = i;
211-
while(j > 0 && sortedChunks[j-1].dist > sortedChunks[j].dist) {
212-
213-
struct { Vector3 chunkPos; float dist; } tempC;
214-
tempC.chunkPos = sortedChunks[j].chunkPos;
215-
tempC.dist = sortedChunks[j].dist;
216-
217-
sortedChunks[j] = sortedChunks[j - 1];
218-
sortedChunks[j - 1].chunkPos = tempC.chunkPos;
219-
sortedChunks[j - 1].dist = tempC.dist;
220-
j = j - 1;
221-
}
222-
}
223-
224-
//Create the chunks
225-
for(int i = 0; i < sortedLength; i++) {
226-
World_AddChunk(sortedChunks[i].chunkPos);
227-
}
228-
}
229221

230222
//destroy far chunks
231223
for (int i = hmlen(world.chunks) - 1; i >= 0 ; i--) {
@@ -247,7 +239,7 @@ void World_LoadChunks(bool loadEdges) {
247239
void World_Reload(void) {
248240
World_Unload();
249241
world.loadChunks = true;
250-
World_LoadChunks(false);
242+
World_LoadChunks();
251243
}
252244

253245
void World_Unload(void) {

client/src/world.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
typedef struct World{
1919
Entity *entities;
2020
struct { long int key; Chunk* value; } *chunks;
21-
QueuedChunk *generateChunksQueue;
22-
QueuedChunk *buildChunksQueue;
21+
Chunk* *generateChunksQueue;
22+
Chunk* *buildChunksQueue;
2323
Material mat;
2424
int drawDistance;
2525
float time;
@@ -37,13 +37,15 @@ void World_Update(void);
3737
//Build Chunks mesh in queue
3838
void World_UpdateChunks(void);
3939
//Load & Unload Chunks around players.
40-
void World_LoadChunks(bool loadEdges);
40+
void World_LoadChunks(void);
4141
//Read Queue to generate chunks.
4242
void *World_ReadChunksQueues(void *state);
4343
//Queue a chunk to build it.
4444
void World_QueueChunk(Chunk *chunk);
4545
//Add a chunk.
4646
void World_AddChunk(Vector3 position);
47+
//Get closest chunk from position in array
48+
int World_GetClosestChunkIndex(Chunk* *array, Vector3 pos);
4749
//Unload the world.
4850
void World_Unload(void);
4951
//Reload chunks.

0 commit comments

Comments
 (0)