From 808819a0459b451e0f1ca5f16c2c98603aae63ce Mon Sep 17 00:00:00 2001 From: Goodlyay Date: Fri, 10 May 2024 23:18:05 -0700 Subject: [PATCH] Add a generic, reusable queue for future lighting logic --- src/ClassiCube.vcxproj | 2 + src/ClassiCube.vcxproj.filters | 6 ++ src/ModernLighting.c | 106 +++++++-------------------------- src/Queue.c | 67 +++++++++++++++++++++ src/Queue.h | 22 +++++++ 5 files changed, 118 insertions(+), 85 deletions(-) create mode 100644 src/Queue.c create mode 100644 src/Queue.h diff --git a/src/ClassiCube.vcxproj b/src/ClassiCube.vcxproj index 8e308cd77..90dfcbcc4 100644 --- a/src/ClassiCube.vcxproj +++ b/src/ClassiCube.vcxproj @@ -416,6 +416,7 @@ + @@ -530,6 +531,7 @@ + diff --git a/src/ClassiCube.vcxproj.filters b/src/ClassiCube.vcxproj.filters index c9bfcac9c..05077b2c5 100644 --- a/src/ClassiCube.vcxproj.filters +++ b/src/ClassiCube.vcxproj.filters @@ -351,6 +351,9 @@ Source Files\Window + + Header Files\Utils + @@ -755,6 +758,9 @@ Source Files\Map + + Source Files\Utils + diff --git a/src/ModernLighting.c b/src/ModernLighting.c index 77daf7ec0..b3628078d 100644 --- a/src/ModernLighting.c +++ b/src/ModernLighting.c @@ -11,79 +11,15 @@ #include "Chat.h" #include "ExtMath.h" #include "Options.h" - -/*########################################################################################################################* -*----------------------------------------------------Queue thing ---------------------------------------------------------* -*#########################################################################################################################*/ - -struct LightQueue { - IVec3* entries; /* Buffer holding the items in the Block queue */ - int capacity; /* Max number of elements in the buffer */ - int mask; /* capacity - 1, as capacity is always a power of two */ - int count; /* Number of used elements */ - int head; /* Head index into the buffer */ - int tail; /* Tail index into the buffer */ -}; -IVec3 LightQueue_EntryAtIndex(struct LightQueue* queue, int index) { - return queue->entries[(queue->head + index) & queue->mask]; -} -void LightQueue_Init(struct LightQueue* queue) { - queue->entries = NULL; - queue->capacity = 0; - queue->mask = 0; - queue->count = 0; - queue->head = 0; - queue->tail = 0; -} -static void LightQueue_Clear(struct LightQueue* queue) { - if (!queue->entries) return; - Mem_Free(queue->entries); - LightQueue_Init(queue); -} -static void LightQueue_Resize(struct LightQueue* queue) { - IVec3* entries; - int i, idx, capacity; - if (queue->capacity >= (Int32_MaxValue / 4)) { - Chat_AddRaw("&cToo many block queue entries, clearing"); - LightQueue_Clear(queue); - return; - } - capacity = queue->capacity * 2; - if (capacity < 32) capacity = 32; - entries = (IVec3*)Mem_Alloc(capacity, sizeof(IVec3), "Light queue"); - for (i = 0; i < queue->count; i++) { - idx = (queue->head + i) & queue->mask; - entries[i] = queue->entries[idx]; - } - Mem_Free(queue->entries); - queue->entries = entries; - queue->capacity = capacity; - queue->mask = capacity - 1; /* capacity is power of two */ - queue->head = 0; - queue->tail = queue->count; -} -/* Appends an entry to the end of the queue, resizing if necessary. */ -void LightQueue_Enqueue(struct LightQueue* queue, IVec3 item) { - if (queue->count == queue->capacity) - LightQueue_Resize(queue); - queue->entries[queue->tail] = item; - queue->tail = (queue->tail + 1) & queue->mask; - queue->count++; -} -/* Retrieves the entry from the front of the queue. */ -IVec3 LightQueue_Dequeue(struct LightQueue* queue) { - IVec3 result = queue->entries[queue->head]; - queue->head = (queue->head + 1) & queue->mask; - queue->count--; - return result; -} -static struct LightQueue lightQueue; +#include "Queue.h" /*########################################################################################################################* *----------------------------------------------------Modern lighting------------------------------------------------------* *#########################################################################################################################*/ +static struct Queue lightQueue; + /* A 16x16 palette of sun and block light colors. */ /* It is indexed by a byte where the leftmost 4 bits represent sunlight level and the rightmost 4 bits represent blocklight level */ /* E.G. modernLighting_palette[0b_0010_0001] will give us the color for sun level 2 and block level 1 (lowest level is 0) */ @@ -173,7 +109,7 @@ static void ModernLighting_AllocState(void) { chunkLightingDataFlags = (cc_uint8*)Mem_TryAllocCleared(chunksCount, sizeof(cc_uint8)); chunkLightingData = (LightingChunk*)Mem_TryAllocCleared(chunksCount, sizeof(LightingChunk)); - LightQueue_Init(&lightQueue); + Queue_Init(&lightQueue, sizeof(IVec3)); } @@ -194,7 +130,7 @@ static void ModernLighting_FreeState(void) { Mem_Free(chunkLightingData); chunkLightingDataFlags = NULL; chunkLightingData = NULL; - LightQueue_Clear(&lightQueue); + Queue_Clear(&lightQueue); } /* Converts chunk x/y/z coordinates to the corresponding index in chunks array/list */ @@ -254,12 +190,12 @@ static cc_bool CanLightPass(BlockID thisBlock, Face face) { static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) { SetBlocklight(blockLight, x, y, z, false); IVec3 entry = { x, y, z }; - LightQueue_Enqueue(&lightQueue, entry); + Queue_Enqueue(&lightQueue, &entry); //if (Blocks.BlocksLight[World_GetBlock(x, y, z)]) { return; } while (lightQueue.count > 0) { - IVec3 curNode = LightQueue_Dequeue(&lightQueue); + IVec3 curNode = *(IVec3*)(Queue_Dequeue(&lightQueue)); cc_uint8 curLight = GetBlocklight(curNode.x, curNode.y, curNode.z, false); if (curLight <= 0) { Platform_Log1("but there were still %i entries left...", &lightQueue.capacity); @@ -277,7 +213,7 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) { CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_XMIN) && GetBlocklight(curNode.x, curNode.y, curNode.z, false) < curLight) { SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, false); - LightQueue_Enqueue(&lightQueue, curNode); + Queue_Enqueue(&lightQueue, &curNode); } curNode.x += 2; if (curNode.x < World.MaxX && @@ -285,7 +221,7 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) { CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_XMAX) && GetBlocklight(curNode.x, curNode.y, curNode.z, false) < curLight) { SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, false); - LightQueue_Enqueue(&lightQueue, curNode); + Queue_Enqueue(&lightQueue, &curNode); } curNode.x--; @@ -295,7 +231,7 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) { CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_YMIN) && GetBlocklight(curNode.x, curNode.y, curNode.z, false) < curLight) { SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, false); - LightQueue_Enqueue(&lightQueue, curNode); + Queue_Enqueue(&lightQueue, &curNode); } curNode.y += 2; if (curNode.y < World.MaxY && @@ -303,7 +239,7 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) { CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_YMAX) && GetBlocklight(curNode.x, curNode.y, curNode.z, false) < curLight) { SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, false); - LightQueue_Enqueue(&lightQueue, curNode); + Queue_Enqueue(&lightQueue, &curNode); } curNode.y--; @@ -313,7 +249,7 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) { CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_ZMIN) && GetBlocklight(curNode.x, curNode.y, curNode.z, false) < curLight) { SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, false); - LightQueue_Enqueue(&lightQueue, curNode); + Queue_Enqueue(&lightQueue, &curNode); } curNode.z += 2; if (curNode.z < World.MaxZ && @@ -321,7 +257,7 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) { CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_ZMAX) && GetBlocklight(curNode.x, curNode.y, curNode.z, false) < curLight) { SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, false); - LightQueue_Enqueue(&lightQueue, curNode); + Queue_Enqueue(&lightQueue, &curNode); } } } @@ -329,12 +265,12 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) { static void CalcSkyLight(cc_uint8 blockLight, int x, int y, int z) { SetBlocklight(blockLight, x, y, z, true); IVec3 entry = { x, y, z }; - LightQueue_Enqueue(&lightQueue, entry); + Queue_Enqueue(&lightQueue, &entry); //if (Blocks.BlocksLight[World_GetBlock(x, y, z)]) { return; } while (lightQueue.count > 0) { - IVec3 curNode = LightQueue_Dequeue(&lightQueue); + IVec3 curNode = *(IVec3*)(Queue_Dequeue(&lightQueue)); cc_uint8 curLight = GetBlocklight(curNode.x, curNode.y, curNode.z, true); if (curLight <= 0) { Platform_Log1("but there were still %i entries left...", &lightQueue.capacity); @@ -354,7 +290,7 @@ static void CalcSkyLight(cc_uint8 blockLight, int x, int y, int z) { GetBlocklight(curNode.x, curNode.y, curNode.z, true) < curLight) { SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, true); IVec3 entry = { curNode.x, curNode.y, curNode.z }; - LightQueue_Enqueue(&lightQueue, entry); + Queue_Enqueue(&lightQueue, &entry); } curNode.x += 2; if (curNode.x < World.MaxX && @@ -363,7 +299,7 @@ static void CalcSkyLight(cc_uint8 blockLight, int x, int y, int z) { CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_XMAX) && GetBlocklight(curNode.x, curNode.y, curNode.z, true) < curLight) { SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, true); - LightQueue_Enqueue(&lightQueue, curNode); + Queue_Enqueue(&lightQueue, &curNode); } curNode.x--; @@ -374,7 +310,7 @@ static void CalcSkyLight(cc_uint8 blockLight, int x, int y, int z) { CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_YMIN) && GetBlocklight(curNode.x, curNode.y, curNode.z, true) < curLight) { SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, true); - LightQueue_Enqueue(&lightQueue, curNode); + Queue_Enqueue(&lightQueue, &curNode); } curNode.y += 2; if (curNode.y < World.MaxY && @@ -383,7 +319,7 @@ static void CalcSkyLight(cc_uint8 blockLight, int x, int y, int z) { CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_YMAX) && GetBlocklight(curNode.x, curNode.y, curNode.z, true) < curLight) { SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, true); - LightQueue_Enqueue(&lightQueue, curNode); + Queue_Enqueue(&lightQueue, &curNode); } curNode.y--; @@ -394,7 +330,7 @@ static void CalcSkyLight(cc_uint8 blockLight, int x, int y, int z) { CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_ZMIN) && GetBlocklight(curNode.x, curNode.y, curNode.z, true) < curLight) { SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, true); - LightQueue_Enqueue(&lightQueue, curNode); + Queue_Enqueue(&lightQueue, &curNode); } curNode.z += 2; if (curNode.z < World.MaxZ && @@ -403,7 +339,7 @@ static void CalcSkyLight(cc_uint8 blockLight, int x, int y, int z) { CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_ZMAX) && GetBlocklight(curNode.x, curNode.y, curNode.z, true) < curLight) { SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, true); - LightQueue_Enqueue(&lightQueue, curNode); + Queue_Enqueue(&lightQueue, &curNode); } } } diff --git a/src/Queue.c b/src/Queue.c new file mode 100644 index 000000000..d12efba95 --- /dev/null +++ b/src/Queue.c @@ -0,0 +1,67 @@ +#include "Core.h" +#include "Constants.h" +#include "Chat.h" +#include "Platform.h" +#include "Queue.h" + +void Queue_Init(struct Queue* queue, cc_uint32 structSize) { + queue->entries = NULL; + queue->structSize = structSize; + queue->capacity = 0; + queue->mask = 0; + queue->count = 0; + queue->head = 0; + queue->tail = 0; +} +void Queue_Clear(struct Queue* queue) { + if (!queue->entries) return; + Mem_Free(queue->entries); + Queue_Init(queue, queue->structSize); +} +static void Queue_Resize(struct Queue* queue) { + cc_uint8* entries; + int i, idx, capacity, headToEndSize, byteOffsetToHead; + if (queue->capacity >= (Int32_MaxValue / 4)) { + Chat_AddRaw("&cToo many generic queue entries, clearing"); + Queue_Clear(queue); + return; + } + capacity = queue->capacity * 2; + if (capacity < 32) capacity = 32; + entries = (cc_uint8*)Mem_Alloc(capacity, queue->structSize, "Generic queue"); + + /* Elements must be readjusted to avoid index wrapping issues */ + headToEndSize = (queue->capacity - queue->head) * queue->structSize; + byteOffsetToHead = queue->head * queue->structSize; + /* Copy from head to end */ + Mem_Copy(entries, queue->entries + byteOffsetToHead, headToEndSize); + if (queue->head != 0) { + /* If there's any leftover before the head, copy that bit too */ + Mem_Copy(entries + headToEndSize, queue->entries, byteOffsetToHead); + } + + Mem_Free(queue->entries); + + queue->entries = entries; + queue->capacity = capacity; + queue->mask = capacity - 1; /* capacity is power of two */ + queue->head = 0; + queue->tail = queue->count; +} +/* Appends an entry to the end of the queue, resizing if necessary. */ +void Queue_Enqueue(struct Queue* queue, void* item) { + if (queue->count == queue->capacity) + Queue_Resize(queue); + + //queue->entries[queue->tail] = item; + Mem_Copy(queue->entries + queue->tail * queue->structSize, item, queue->structSize); + queue->tail = (queue->tail + 1) & queue->mask; + queue->count++; +} +/* Retrieves the entry from the front of the queue. */ +void* Queue_Dequeue(struct Queue* queue) { + void* result = queue->entries + queue->head * queue->structSize; + queue->head = (queue->head + 1) & queue->mask; + queue->count--; + return result; +} \ No newline at end of file diff --git a/src/Queue.h b/src/Queue.h new file mode 100644 index 000000000..f62c94102 --- /dev/null +++ b/src/Queue.h @@ -0,0 +1,22 @@ +#include "Core.h" + +#ifndef CC_QUEUE_H +#define CC_QUEUE_H + +struct Queue { + cc_uint8* entries; /* Buffer holding the bytes of the queue */ + int structSize; /* Size in bytes of the type of structure this queue holds */ + int capacity; /* Max number of elements in the buffer */ + int mask; /* capacity - 1, as capacity is always a power of two */ + int count; /* Number of used elements */ + int head; /* Head index into the buffer */ + int tail; /* Tail index into the buffer */ +}; +void Queue_Init(struct Queue* queue, cc_uint32 structSize); +/* Appends an entry to the end of the queue, resizing if necessary. */ +void Queue_Enqueue(struct Queue* queue, void* item); +/* Retrieves the entry from the front of the queue. */ +void* Queue_Dequeue(struct Queue* queue); +/* Frees the memory of the queue and resets the members to 0. */ +void Queue_Clear(struct Queue* queue); +#endif \ No newline at end of file