Add a generic, reusable queue for future lighting logic

This commit is contained in:
Goodlyay 2024-05-10 23:18:05 -07:00
parent 04cbf398eb
commit 808819a045
5 changed files with 118 additions and 85 deletions

View File

@ -416,6 +416,7 @@
<ClInclude Include="Particle.h" />
<ClInclude Include="BlockPhysics.h" />
<ClInclude Include="Picking.h" />
<ClInclude Include="Queue.h" />
<ClInclude Include="SelOutlineRenderer.h" />
<ClInclude Include="Resources.h" />
<ClInclude Include="Screens.h" />
@ -530,6 +531,7 @@
<ClCompile Include="PackedCol.c" />
<ClCompile Include="Particle.c" />
<ClCompile Include="BlockPhysics.c" />
<ClCompile Include="Queue.c" />
<ClCompile Include="SelOutlineRenderer.c" />
<ClCompile Include="Picking.c" />
<ClCompile Include="main.c" />

View File

@ -351,6 +351,9 @@
<ClInclude Include="VirtualKeyboard.h">
<Filter>Source Files\Window</Filter>
</ClInclude>
<ClInclude Include="Queue.h">
<Filter>Header Files\Utils</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="String.c">
@ -755,6 +758,9 @@
<ClCompile Include="ModernLighting.c">
<Filter>Source Files\Map</Filter>
</ClCompile>
<ClCompile Include="Queue.c">
<Filter>Source Files\Utils</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\misc\windows\CCicon.rc">

View File

@ -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);
}
}
}

67
src/Queue.c Normal file
View File

@ -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;
}

22
src/Queue.h Normal file
View File

@ -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