chunk_manager.c (5440B)
1 #include "chunk_manager.h" 2 3 #include <math.h> 4 #include <stdlib.h> 5 6 static void ChunkManager_setChunkCount(ChunkManager *cm) 7 { 8 cm->chunk_count = 0; 9 for (i32 x = -cm->radius; x <= cm->radius; x++) 10 { 11 for (i32 y = -cm->radius; y <= cm->radius; y++) 12 { 13 for (i32 z = -cm->radius; z <= cm->radius; z++) 14 { 15 cm->chunk_count += 1; 16 } 17 } 18 } 19 } 20 21 static void ChunkManager_createOffsets(ChunkManager *cm) 22 { 23 cm->offsets = malloc(sizeof *cm->offsets * cm->chunk_count); 24 for (i32 i = 0, x = -cm->radius; x <= cm->radius; x++) 25 { 26 for (i32 y = -cm->radius; y <= cm->radius; y++) 27 { 28 for (i32 z = -cm->radius; z <= cm->radius; z++, i++) 29 { 30 cm->offsets[i][0] = x; 31 cm->offsets[i][1] = y; 32 cm->offsets[i][2] = z; 33 } 34 } 35 } 36 } 37 38 static void ChunkManager_createChunks(ChunkManager *cm) 39 { 40 cm->chunks = malloc(sizeof *cm->chunks * cm->chunk_count); 41 for (u32 i = 0; i < cm->chunk_count; i++) 42 { 43 Chunk_init(&cm->chunks[i]); 44 45 IVec3 chunk_origin = { 46 cm->origin[0] + cm->offsets[i][0], 47 cm->origin[1] + cm->offsets[i][1], 48 cm->origin[2] + cm->offsets[i][2] 49 }; 50 Chunk_updateOrigin(&cm->chunks[i], chunk_origin); 51 Chunk_updateMesh(&cm->chunks[i], cm->f, cm->isolevel, cm->pool); 52 } 53 } 54 55 static void ChunkManager_resetFlags(ChunkManager *cm) 56 { 57 for (u32 i = 0; i < cm->chunk_count; i++) 58 { 59 cm->is_new_offset[i] = true; 60 cm->is_old_chunk[i] = true; 61 } 62 } 63 64 static void ChunkManager_updateFlags(ChunkManager *cm) 65 { 66 for (u32 i = 0; i < cm->chunk_count; i++) 67 { 68 IVec3 chunk_origin = { 69 cm->origin[0] + cm->offsets[i][0], 70 cm->origin[1] + cm->offsets[i][1], 71 cm->origin[2] + cm->offsets[i][2] 72 }; 73 for (u32 j = 0; j < cm->chunk_count; j++) 74 { 75 if (IVec3_equal(chunk_origin, cm->chunks[j].origin)) 76 { 77 cm->is_new_offset[i] = false; 78 cm->is_old_chunk[j] = false; 79 break; 80 } 81 } 82 } 83 } 84 85 static void ChunkManager_updateChunkMeshes(ChunkManager *cm) 86 { 87 for (u32 i = 0; i < cm->chunk_count; i++) 88 { 89 if (cm->is_new_offset[i]) 90 { 91 for (u32 j = 0; j < cm->chunk_count; j++) 92 { 93 if (cm->is_old_chunk[j]) 94 { 95 IVec3 chunk_origin = { 96 cm->origin[0] + cm->offsets[i][0], 97 cm->origin[1] + cm->offsets[i][1], 98 cm->origin[2] + cm->offsets[i][2] 99 }; 100 Chunk_updateOrigin(&cm->chunks[j], chunk_origin); 101 Chunk_updateMesh(&cm->chunks[j], cm->f, cm->isolevel, 102 cm->pool); 103 104 cm->is_new_offset[i] = false; 105 cm->is_old_chunk[j] = false; 106 break; 107 } 108 } 109 } 110 } 111 } 112 113 static void ChunkManager_updateChunks(ChunkManager *cm) 114 { 115 ChunkManager_resetFlags(cm); 116 ChunkManager_updateFlags(cm); 117 ChunkManager_updateChunkMeshes(cm); 118 } 119 120 static void ChunkManager_worldToChunk(const Vec3 src, IVec3 dst) 121 { 122 dst[0] = (i32)floorf(src[0] / CHUNK_WIDTH); 123 dst[1] = (i32)floorf(src[1] / CHUNK_WIDTH); 124 dst[2] = (i32)floorf(src[2] / CHUNK_WIDTH); 125 } 126 127 static void ChunkManager_chunkToWorld(const IVec3 src, Vec3 dst) 128 { 129 dst[0] = src[0] * CHUNK_WIDTH; 130 dst[1] = src[1] * CHUNK_WIDTH; 131 dst[2] = src[2] * CHUNK_WIDTH; 132 } 133 134 ChunkManager ChunkManager_create( 135 const Vec3 target, 136 i32 radius, 137 SDF f, 138 f32 isolevel 139 ) 140 { 141 ChunkManager cm; 142 143 cm.pool = ThreadPool_make(5); 144 145 ChunkManager_worldToChunk(target, cm.origin); 146 cm.radius = radius; 147 148 cm.f = f; 149 cm.isolevel = isolevel; 150 151 ChunkManager_setChunkCount(&cm); 152 ChunkManager_createOffsets(&cm); 153 ChunkManager_createChunks(&cm); 154 155 cm.is_new_offset = malloc(sizeof *cm.is_new_offset * cm.chunk_count); 156 cm.is_old_chunk = malloc(sizeof *cm.is_old_chunk * cm.chunk_count); 157 158 return cm; 159 } 160 161 void ChunkManager_free(ChunkManager *cm) 162 { 163 free(cm->offsets); 164 165 ThreadPool_free(cm->pool); 166 167 for (u32 i = 0; i < cm->chunk_count; i++) 168 { 169 Chunk_free(&cm->chunks[i]); 170 } 171 free(cm->chunks); 172 173 free(cm->is_new_offset); 174 free(cm->is_old_chunk); 175 176 cm->chunk_count = 0; 177 } 178 179 void ChunkManager_recenter(ChunkManager *cm, const Vec3 target) 180 { 181 IVec3 new_origin; 182 ChunkManager_worldToChunk(target, new_origin); 183 if (!IVec3_equal(new_origin, cm->origin)) 184 { 185 cm->origin[0] = new_origin[0]; 186 cm->origin[1] = new_origin[1]; 187 cm->origin[2] = new_origin[2]; 188 ChunkManager_updateChunks(cm); 189 } 190 } 191 192 void ChunkManager_drawChunks(const ChunkManager *cm, const Camera *camera) 193 { 194 for (u32 i = 0; i < cm->chunk_count; i++) 195 { 196 Vec3 chunk_center; 197 ChunkManager_chunkToWorld(cm->chunks[i].origin, chunk_center); 198 chunk_center[0] += CHUNK_WIDTH / 2; 199 chunk_center[1] += CHUNK_WIDTH / 2; 200 chunk_center[2] += CHUNK_WIDTH / 2; 201 202 f32 chunk_radius = CHUNK_WIDTH * 0.866025f; 203 204 if (Camera_sphereInFrustum(camera, chunk_center, chunk_radius)) 205 { 206 Chunk_drawMesh(&cm->chunks[i]); 207 } 208 } 209 }