mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-18 12:05:14 -04:00
Part 1 of lighting refactor
This commit is contained in:
parent
726a75c0a0
commit
1fa0e789c0
@ -268,7 +268,7 @@ static void Physics_HandleDirt(int index, BlockID block) {
|
||||
int x, y, z;
|
||||
World_Unpack(index, x, y, z);
|
||||
|
||||
if (Lighting_IsLit(x, y, z)) {
|
||||
if (Lighting.IsLit(x, y, z)) {
|
||||
Game_UpdateBlock(x, y, z, BLOCK_GRASS);
|
||||
}
|
||||
}
|
||||
@ -277,7 +277,7 @@ static void Physics_HandleGrass(int index, BlockID block) {
|
||||
int x, y, z;
|
||||
World_Unpack(index, x, y, z);
|
||||
|
||||
if (!Lighting_IsLit(x, y, z)) {
|
||||
if (!Lighting.IsLit(x, y, z)) {
|
||||
Game_UpdateBlock(x, y, z, BLOCK_DIRT);
|
||||
}
|
||||
}
|
||||
@ -287,7 +287,7 @@ static void Physics_HandleFlower(int index, BlockID block) {
|
||||
int x, y, z;
|
||||
World_Unpack(index, x, y, z);
|
||||
|
||||
if (!Lighting_IsLit(x, y, z)) {
|
||||
if (!Lighting.IsLit(x, y, z)) {
|
||||
Game_UpdateBlock(x, y, z, BLOCK_AIR);
|
||||
Physics_ActivateNeighbours(x, y, z, index);
|
||||
return;
|
||||
@ -306,7 +306,7 @@ static void Physics_HandleMushroom(int index, BlockID block) {
|
||||
int x, y, z;
|
||||
World_Unpack(index, x, y, z);
|
||||
|
||||
if (Lighting_IsLit(x, y, z)) {
|
||||
if (Lighting.IsLit(x, y, z)) {
|
||||
Game_UpdateBlock(x, y, z, BLOCK_AIR);
|
||||
Physics_ActivateNeighbours(x, y, z, index);
|
||||
return;
|
||||
|
@ -357,7 +357,7 @@ static cc_bool BuildChunk(int x1, int y1, int z1, struct ChunkInfo* info) {
|
||||
|
||||
info->AllAir = allAir;
|
||||
if (allAir || allSolid) return false;
|
||||
Lighting_LightHint(x1 - 1, z1 - 1);
|
||||
Lighting.LightHint(x1 - 1, z1 - 1);
|
||||
|
||||
Mem_Set(counts, 1, CHUNK_SIZE_3 * FACE_COUNT);
|
||||
xMax = min(World.Width, x1 + CHUNK_SIZE);
|
||||
@ -501,7 +501,7 @@ static void Builder_DrawSprite(int x, int y, int z) {
|
||||
|
||||
bright = Blocks.FullBright[Builder_Block];
|
||||
part = &Builder_Parts[Atlas1D_Index(loc)];
|
||||
v.Col = bright ? PACKEDCOL_WHITE : Lighting_Color_Sprite_Fast(x, y, z);
|
||||
v.Col = bright ? PACKEDCOL_WHITE : Lighting.Color_Sprite_Fast(x, y, z);
|
||||
Block_Tint(v.Col, Builder_Block);
|
||||
|
||||
/* Draw Z axis */
|
||||
@ -544,17 +544,17 @@ static PackedCol Normal_LightCol(int x, int y, int z, Face face, BlockID block)
|
||||
|
||||
switch (face) {
|
||||
case FACE_XMIN:
|
||||
return x < offset ? Env.SunXSide : Lighting_Color_XSide_Fast(x - offset, y, z);
|
||||
return x < offset ? Env.SunXSide : Lighting.Color_XSide_Fast(x - offset, y, z);
|
||||
case FACE_XMAX:
|
||||
return x > (World.MaxX - offset) ? Env.SunXSide : Lighting_Color_XSide_Fast(x + offset, y, z);
|
||||
return x > (World.MaxX - offset) ? Env.SunXSide : Lighting.Color_XSide_Fast(x + offset, y, z);
|
||||
case FACE_ZMIN:
|
||||
return z < offset ? Env.SunZSide : Lighting_Color_ZSide_Fast(x, y, z - offset);
|
||||
return z < offset ? Env.SunZSide : Lighting.Color_ZSide_Fast(x, y, z - offset);
|
||||
case FACE_ZMAX:
|
||||
return z > (World.MaxZ - offset) ? Env.SunZSide : Lighting_Color_ZSide_Fast(x, y, z + offset);
|
||||
return z > (World.MaxZ - offset) ? Env.SunZSide : Lighting.Color_ZSide_Fast(x, y, z + offset);
|
||||
case FACE_YMIN:
|
||||
return y <= 0 ? Env.SunYMin : Lighting_Color_YMin_Fast(x, y - offset, z);
|
||||
return y <= 0 ? Env.SunYMin : Lighting.Color_YMin_Fast(x, y - offset, z);
|
||||
case FACE_YMAX:
|
||||
return y >= World.MaxY ? Env.SunCol : Lighting_Color_YMax_Fast(x, (y + 1) - offset, z);
|
||||
return y >= World.MaxY ? Env.SunCol : Lighting.Color_YMax_Fast(x, (y + 1) - offset, z);
|
||||
}
|
||||
return 0; /* should never happen */
|
||||
}
|
||||
@ -674,7 +674,7 @@ static void NormalBuilder_RenderBlock(int index, int x, int y, int z) {
|
||||
part = &Builder_Parts[baseOffset + Atlas1D_Index(loc)];
|
||||
|
||||
col = fullBright ? PACKEDCOL_WHITE :
|
||||
x >= offset ? Lighting_Color_XSide_Fast(x - offset, y, z) : Env.SunXSide;
|
||||
x >= offset ? Lighting.Color_XSide_Fast(x - offset, y, z) : Env.SunXSide;
|
||||
Drawer_XMin(count_XMin, col, loc, &part->fVertices[FACE_XMIN]);
|
||||
}
|
||||
|
||||
@ -684,7 +684,7 @@ static void NormalBuilder_RenderBlock(int index, int x, int y, int z) {
|
||||
part = &Builder_Parts[baseOffset + Atlas1D_Index(loc)];
|
||||
|
||||
col = fullBright ? PACKEDCOL_WHITE :
|
||||
x <= (World.MaxX - offset) ? Lighting_Color_XSide_Fast(x + offset, y, z) : Env.SunXSide;
|
||||
x <= (World.MaxX - offset) ? Lighting.Color_XSide_Fast(x + offset, y, z) : Env.SunXSide;
|
||||
Drawer_XMax(count_XMax, col, loc, &part->fVertices[FACE_XMAX]);
|
||||
}
|
||||
|
||||
@ -694,7 +694,7 @@ static void NormalBuilder_RenderBlock(int index, int x, int y, int z) {
|
||||
part = &Builder_Parts[baseOffset + Atlas1D_Index(loc)];
|
||||
|
||||
col = fullBright ? PACKEDCOL_WHITE :
|
||||
z >= offset ? Lighting_Color_ZSide_Fast(x, y, z - offset) : Env.SunZSide;
|
||||
z >= offset ? Lighting.Color_ZSide_Fast(x, y, z - offset) : Env.SunZSide;
|
||||
Drawer_ZMin(count_ZMin, col, loc, &part->fVertices[FACE_ZMIN]);
|
||||
}
|
||||
|
||||
@ -704,7 +704,7 @@ static void NormalBuilder_RenderBlock(int index, int x, int y, int z) {
|
||||
part = &Builder_Parts[baseOffset + Atlas1D_Index(loc)];
|
||||
|
||||
col = fullBright ? PACKEDCOL_WHITE :
|
||||
z <= (World.MaxZ - offset) ? Lighting_Color_ZSide_Fast(x, y, z + offset) : Env.SunZSide;
|
||||
z <= (World.MaxZ - offset) ? Lighting.Color_ZSide_Fast(x, y, z + offset) : Env.SunZSide;
|
||||
Drawer_ZMax(count_ZMax, col, loc, &part->fVertices[FACE_ZMAX]);
|
||||
}
|
||||
|
||||
@ -713,7 +713,7 @@ static void NormalBuilder_RenderBlock(int index, int x, int y, int z) {
|
||||
offset = (lightFlags >> FACE_YMIN) & 1;
|
||||
part = &Builder_Parts[baseOffset + Atlas1D_Index(loc)];
|
||||
|
||||
col = fullBright ? PACKEDCOL_WHITE : Lighting_Color_YMin_Fast(x, y - offset, z);
|
||||
col = fullBright ? PACKEDCOL_WHITE : Lighting.Color_YMin_Fast(x, y - offset, z);
|
||||
Drawer_YMin(count_YMin, col, loc, &part->fVertices[FACE_YMIN]);
|
||||
}
|
||||
|
||||
@ -722,7 +722,7 @@ static void NormalBuilder_RenderBlock(int index, int x, int y, int z) {
|
||||
offset = (lightFlags >> FACE_YMAX) & 1;
|
||||
part = &Builder_Parts[baseOffset + Atlas1D_Index(loc)];
|
||||
|
||||
col = fullBright ? PACKEDCOL_WHITE : Lighting_Color_YMax_Fast(x, (y + 1) - offset, z);
|
||||
col = fullBright ? PACKEDCOL_WHITE : Lighting.Color_YMax_Fast(x, (y + 1) - offset, z);
|
||||
Drawer_YMax(count_YMax, col, loc, &part->fVertices[FACE_YMAX]);
|
||||
}
|
||||
}
|
||||
@ -795,14 +795,14 @@ static int Adv_Lit(int x, int y, int z, int cIndex) {
|
||||
|
||||
/* Use fact Light(Y.YMin) == Light((Y-1).YMax) */
|
||||
offset = (lightFlags >> FACE_YMIN) & 1;
|
||||
flags |= Lighting_IsLit_Fast(x, y - offset, z) ? LIT_M1 : 0;
|
||||
flags |= Lighting.IsLit_Fast(x, y - offset, z) ? LIT_M1 : 0;
|
||||
|
||||
/* Light is same for all the horizontal faces */
|
||||
flags |= Lighting_IsLit_Fast(x, y, z) ? LIT_CC : 0;
|
||||
flags |= Lighting.IsLit_Fast(x, y, z) ? LIT_CC : 0;
|
||||
|
||||
/* Use fact Light((Y+1).YMin) == Light(Y.YMax) */
|
||||
offset = (lightFlags >> FACE_YMAX) & 1;
|
||||
flags |= Lighting_IsLit_Fast(x, (y + 1) - offset, z) ? LIT_P1 : 0;
|
||||
flags |= Lighting.IsLit_Fast(x, (y + 1) - offset, z) ? LIT_P1 : 0;
|
||||
|
||||
/* If a block is fullbright, it should also look as if that spot is lit */
|
||||
if (Blocks.FullBright[Builder_Chunk[cIndex - 324]]) flags |= LIT_M1;
|
||||
|
@ -66,7 +66,7 @@ void LocationUpdate_MakePosAndOri(struct LocationUpdate* update, Vec3 pos, float
|
||||
static PackedCol Entity_GetCol(struct Entity* e) {
|
||||
Vec3 eyePos = Entity_GetEyePosition(e);
|
||||
IVec3 pos; IVec3_Floor(&pos, &eyePos);
|
||||
return Lighting_Color(pos.X, pos.Y, pos.Z);
|
||||
return Lighting.Color(pos.X, pos.Y, pos.Z);
|
||||
}
|
||||
|
||||
void Entity_Init(struct Entity* e) {
|
||||
|
@ -1303,7 +1303,8 @@ NBT_END,
|
||||
};
|
||||
|
||||
static cc_result Cw_WriteBockDef(struct Stream* stream, int b) {
|
||||
cc_uint8 buffer[1024], nameBuffer[10];
|
||||
cc_uint8 buffer[1024];
|
||||
char nameBuffer[10];
|
||||
cc_uint8* cur;
|
||||
cc_string name;
|
||||
cc_bool sprite = Blocks.Draw[b] == DRAW_SPRITE;
|
||||
|
@ -190,7 +190,7 @@ void Game_UpdateBlock(int x, int y, int z, BlockID block) {
|
||||
if (Weather_Heightmap) {
|
||||
EnvRenderer_OnBlockChanged(x, y, z, old, block);
|
||||
}
|
||||
Lighting_OnBlockChanged(x, y, z, old, block);
|
||||
Lighting.OnBlockChanged(x, y, z, old, block);
|
||||
MapRenderer_OnBlockChanged(x, y, z, block);
|
||||
}
|
||||
|
||||
|
186
src/Lighting.c
186
src/Lighting.c
@ -7,89 +7,94 @@
|
||||
#include "Logger.h"
|
||||
#include "Event.h"
|
||||
#include "Game.h"
|
||||
struct _Lighting Lighting;
|
||||
#define Lighting_Pack(x, z) ((x) + World.Width * (z))
|
||||
|
||||
static cc_int16* light_heightmap;
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------Classic lighting-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static cc_int16* classic_heightmap;
|
||||
#define HEIGHT_UNCALCULATED Int16_MaxValue
|
||||
|
||||
#define Lighting_CalcBody(get_block)\
|
||||
#define ClassicLighting_CalcBody(get_block)\
|
||||
for (y = maxY; y >= 0; y--, i -= World.OneY) {\
|
||||
block = get_block;\
|
||||
\
|
||||
if (Blocks.BlocksLight[block]) {\
|
||||
offset = (Blocks.LightOffset[block] >> FACE_YMAX) & 1;\
|
||||
light_heightmap[hIndex] = y - offset;\
|
||||
classic_heightmap[hIndex] = y - offset;\
|
||||
return y - offset;\
|
||||
}\
|
||||
}
|
||||
|
||||
static int Lighting_CalcHeightAt(int x, int maxY, int z, int hIndex) {
|
||||
static int ClassicLighting_CalcHeightAt(int x, int maxY, int z, int hIndex) {
|
||||
int i = World_Pack(x, maxY, z);
|
||||
BlockID block;
|
||||
int y, offset;
|
||||
|
||||
#ifndef EXTENDED_BLOCKS
|
||||
Lighting_CalcBody(World.Blocks[i]);
|
||||
ClassicLighting_CalcBody(World.Blocks[i]);
|
||||
#else
|
||||
if (World.IDMask <= 0xFF) {
|
||||
Lighting_CalcBody(World.Blocks[i]);
|
||||
ClassicLighting_CalcBody(World.Blocks[i]);
|
||||
} else {
|
||||
Lighting_CalcBody(World.Blocks[i] | (World.Blocks2[i] << 8));
|
||||
ClassicLighting_CalcBody(World.Blocks[i] | (World.Blocks2[i] << 8));
|
||||
}
|
||||
#endif
|
||||
|
||||
light_heightmap[hIndex] = -10;
|
||||
classic_heightmap[hIndex] = -10;
|
||||
return -10;
|
||||
}
|
||||
|
||||
static int Lighting_GetLightHeight(int x, int z) {
|
||||
static int ClassicLighting_GetLightHeight(int x, int z) {
|
||||
int hIndex = Lighting_Pack(x, z);
|
||||
int lightH = light_heightmap[hIndex];
|
||||
return lightH == HEIGHT_UNCALCULATED ? Lighting_CalcHeightAt(x, World.Height - 1, z, hIndex) : lightH;
|
||||
int lightH = classic_heightmap[hIndex];
|
||||
return lightH == HEIGHT_UNCALCULATED ? ClassicLighting_CalcHeightAt(x, World.Height - 1, z, hIndex) : lightH;
|
||||
}
|
||||
|
||||
/* Outside color is same as sunlight color, so we reuse when possible */
|
||||
cc_bool Lighting_IsLit(int x, int y, int z) {
|
||||
return y > Lighting_GetLightHeight(x, z);
|
||||
static cc_bool ClassicLighting_IsLit(int x, int y, int z) {
|
||||
return y > ClassicLighting_GetLightHeight(x, z);
|
||||
}
|
||||
|
||||
cc_bool Lighting_IsLit_Fast(int x, int y, int z) {
|
||||
return y > light_heightmap[Lighting_Pack(x, z)];
|
||||
static cc_bool ClassicLighting_IsLit_Fast(int x, int y, int z) {
|
||||
return y > classic_heightmap[Lighting_Pack(x, z)];
|
||||
}
|
||||
|
||||
PackedCol Lighting_Color(int x, int y, int z) {
|
||||
static PackedCol ClassicLighting_Color(int x, int y, int z) {
|
||||
if (!World_Contains(x, y, z)) return Env.SunCol;
|
||||
return y > Lighting_GetLightHeight(x, z) ? Env.SunCol : Env.ShadowCol;
|
||||
return y > ClassicLighting_GetLightHeight(x, z) ? Env.SunCol : Env.ShadowCol;
|
||||
}
|
||||
|
||||
PackedCol Lighting_Color_XSide(int x, int y, int z) {
|
||||
static PackedCol ClassicLighting_Color_XSide(int x, int y, int z) {
|
||||
if (!World_Contains(x, y, z)) return Env.SunXSide;
|
||||
return y > Lighting_GetLightHeight(x, z) ? Env.SunXSide : Env.ShadowXSide;
|
||||
return y > ClassicLighting_GetLightHeight(x, z) ? Env.SunXSide : Env.ShadowXSide;
|
||||
}
|
||||
|
||||
PackedCol Lighting_Color_Sprite_Fast(int x, int y, int z) {
|
||||
return y > light_heightmap[Lighting_Pack(x, z)] ? Env.SunCol : Env.ShadowCol;
|
||||
static PackedCol ClassicLighting_Color_Sprite_Fast(int x, int y, int z) {
|
||||
return y > classic_heightmap[Lighting_Pack(x, z)] ? Env.SunCol : Env.ShadowCol;
|
||||
}
|
||||
|
||||
PackedCol Lighting_Color_YMax_Fast(int x, int y, int z) {
|
||||
return y > light_heightmap[Lighting_Pack(x, z)] ? Env.SunCol : Env.ShadowCol;
|
||||
static PackedCol ClassicLighting_Color_YMax_Fast(int x, int y, int z) {
|
||||
return y > classic_heightmap[Lighting_Pack(x, z)] ? Env.SunCol : Env.ShadowCol;
|
||||
}
|
||||
|
||||
PackedCol Lighting_Color_YMin_Fast(int x, int y, int z) {
|
||||
return y > light_heightmap[Lighting_Pack(x, z)] ? Env.SunYMin : Env.ShadowYMin;
|
||||
static PackedCol ClassicLighting_Color_YMin_Fast(int x, int y, int z) {
|
||||
return y > classic_heightmap[Lighting_Pack(x, z)] ? Env.SunYMin : Env.ShadowYMin;
|
||||
}
|
||||
|
||||
PackedCol Lighting_Color_XSide_Fast(int x, int y, int z) {
|
||||
return y > light_heightmap[Lighting_Pack(x, z)] ? Env.SunXSide : Env.ShadowXSide;
|
||||
static PackedCol ClassicLighting_Color_XSide_Fast(int x, int y, int z) {
|
||||
return y > classic_heightmap[Lighting_Pack(x, z)] ? Env.SunXSide : Env.ShadowXSide;
|
||||
}
|
||||
|
||||
PackedCol Lighting_Color_ZSide_Fast(int x, int y, int z) {
|
||||
return y > light_heightmap[Lighting_Pack(x, z)] ? Env.SunZSide : Env.ShadowZSide;
|
||||
static PackedCol ClassicLighting_Color_ZSide_Fast(int x, int y, int z) {
|
||||
return y > classic_heightmap[Lighting_Pack(x, z)] ? Env.SunZSide : Env.ShadowZSide;
|
||||
}
|
||||
|
||||
void Lighting_Refresh(void) {
|
||||
static void ClassicLighting_Refresh(void) {
|
||||
int i;
|
||||
for (i = 0; i < World.Width * World.Length; i++) {
|
||||
light_heightmap[i] = HEIGHT_UNCALCULATED;
|
||||
classic_heightmap[i] = HEIGHT_UNCALCULATED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,7 +102,7 @@ void Lighting_Refresh(void) {
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------Lighting update------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void Lighting_UpdateLighting(int x, int y, int z, BlockID oldBlock, BlockID newBlock, int index, int lightH) {
|
||||
static void ClassicLighting_UpdateLighting(int x, int y, int z, BlockID oldBlock, BlockID newBlock, int index, int lightH) {
|
||||
cc_bool didBlock = Blocks.BlocksLight[oldBlock];
|
||||
cc_bool nowBlocks = Blocks.BlocksLight[newBlock];
|
||||
int oldOffset = (Blocks.LightOffset[oldBlock] >> FACE_YMAX) & 1;
|
||||
@ -112,11 +117,11 @@ static void Lighting_UpdateLighting(int x, int y, int z, BlockID oldBlock, Block
|
||||
|
||||
if ((y - newOffset) >= lightH) {
|
||||
if (nowBlocks) {
|
||||
light_heightmap[index] = y - newOffset;
|
||||
classic_heightmap[index] = y - newOffset;
|
||||
} else {
|
||||
/* Part of the column is now visible to light, we don't know how exactly how high it should be though. */
|
||||
/* However, we know that if the old block was above or equal to light height, then the new light height must be <= old block.y */
|
||||
Lighting_CalcHeightAt(x, y, z, index);
|
||||
ClassicLighting_CalcHeightAt(x, y, z, index);
|
||||
}
|
||||
} else if (y == lightH && oldOffset == 0) {
|
||||
/* For a solid block on top of an upside down slab, they will both have the same light height. */
|
||||
@ -125,26 +130,26 @@ static void Lighting_UpdateLighting(int x, int y, int z, BlockID oldBlock, Block
|
||||
if (Blocks.BlocksLight[above]) return;
|
||||
|
||||
if (nowBlocks) {
|
||||
light_heightmap[index] = y - newOffset;
|
||||
classic_heightmap[index] = y - newOffset;
|
||||
} else {
|
||||
Lighting_CalcHeightAt(x, y - 1, z, index);
|
||||
ClassicLighting_CalcHeightAt(x, y - 1, z, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static cc_bool Lighting_Needs(BlockID block, BlockID other) {
|
||||
static cc_bool ClassicLighting_Needs(BlockID block, BlockID other) {
|
||||
return Blocks.Draw[block] != DRAW_OPAQUE || Blocks.Draw[other] != DRAW_GAS;
|
||||
}
|
||||
|
||||
#define Lighting_NeedsNeighourBody(get_block)\
|
||||
#define ClassicLighting_NeedsNeighourBody(get_block)\
|
||||
/* Update if any blocks in the chunk are affected by light change. */ \
|
||||
for (; y >= minY; y--, i -= World.OneY) {\
|
||||
other = get_block;\
|
||||
affected = y == nY ? Lighting_Needs(block, other) : Blocks.Draw[other] != DRAW_GAS;\
|
||||
affected = y == nY ? ClassicLighting_Needs(block, other) : Blocks.Draw[other] != DRAW_GAS;\
|
||||
if (affected) return true;\
|
||||
}
|
||||
|
||||
static cc_bool Lighting_NeedsNeighour(BlockID block, int i, int minY, int y, int nY) {
|
||||
static cc_bool ClassicLighting_NeedsNeighour(BlockID block, int i, int minY, int y, int nY) {
|
||||
BlockID other;
|
||||
cc_bool affected;
|
||||
|
||||
@ -152,21 +157,21 @@ static cc_bool Lighting_NeedsNeighour(BlockID block, int i, int minY, int y, int
|
||||
Lighting_NeedsNeighourBody(World.Blocks[i]);
|
||||
#else
|
||||
if (World.IDMask <= 0xFF) {
|
||||
Lighting_NeedsNeighourBody(World.Blocks[i]);
|
||||
ClassicLighting_NeedsNeighourBody(World.Blocks[i]);
|
||||
} else {
|
||||
Lighting_NeedsNeighourBody(World.Blocks[i] | (World.Blocks2[i] << 8));
|
||||
ClassicLighting_NeedsNeighourBody(World.Blocks[i] | (World.Blocks2[i] << 8));
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Lighting_ResetNeighbour(int x, int y, int z, BlockID block, int cx, int cy, int cz, int minCy, int maxCy) {
|
||||
static void ClassicLighting_ResetNeighbour(int x, int y, int z, BlockID block, int cx, int cy, int cz, int minCy, int maxCy) {
|
||||
int minY, maxY;
|
||||
|
||||
if (minCy == maxCy) {
|
||||
minY = cy << CHUNK_SHIFT;
|
||||
|
||||
if (Lighting_NeedsNeighour(block, World_Pack(x, y, z), minY, y, y)) {
|
||||
if (ClassicLighting_NeedsNeighour(block, World_Pack(x, y, z), minY, y, y)) {
|
||||
MapRenderer_RefreshChunk(cx, cy, cz);
|
||||
}
|
||||
} else {
|
||||
@ -175,14 +180,14 @@ static void Lighting_ResetNeighbour(int x, int y, int z, BlockID block, int cx,
|
||||
maxY = (cy << CHUNK_SHIFT) + CHUNK_MAX;
|
||||
if (maxY > World.MaxY) maxY = World.MaxY;
|
||||
|
||||
if (Lighting_NeedsNeighour(block, World_Pack(x, maxY, z), minY, maxY, y)) {
|
||||
if (ClassicLighting_NeedsNeighour(block, World_Pack(x, maxY, z), minY, maxY, y)) {
|
||||
MapRenderer_RefreshChunk(cx, cy, cz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Lighting_ResetColumn(int cx, int cy, int cz, int minCy, int maxCy) {
|
||||
static void ClassicLighting_ResetColumn(int cx, int cy, int cz, int minCy, int maxCy) {
|
||||
if (minCy == maxCy) {
|
||||
MapRenderer_RefreshChunk(cx, cy, cz);
|
||||
} else {
|
||||
@ -192,7 +197,7 @@ static void Lighting_ResetColumn(int cx, int cy, int cz, int minCy, int maxCy) {
|
||||
}
|
||||
}
|
||||
|
||||
static void Lighting_RefreshAffected(int x, int y, int z, BlockID block, int oldHeight, int newHeight) {
|
||||
static void ClassicLighting_RefreshAffected(int x, int y, int z, BlockID block, int oldHeight, int newHeight) {
|
||||
int cx = x >> CHUNK_SHIFT, bX = x & CHUNK_MASK;
|
||||
int cy = y >> CHUNK_SHIFT, bY = y & CHUNK_MASK;
|
||||
int cz = z >> CHUNK_SHIFT, bZ = z & CHUNK_MASK;
|
||||
@ -201,55 +206,55 @@ static void Lighting_RefreshAffected(int x, int y, int z, BlockID block, int old
|
||||
int newCy = newHeight < 0 ? 0 : newHeight >> 4;
|
||||
int oldCy = oldHeight < 0 ? 0 : oldHeight >> 4;
|
||||
int minCy = min(oldCy, newCy), maxCy = max(oldCy, newCy);
|
||||
Lighting_ResetColumn(cx, cy, cz, minCy, maxCy);
|
||||
ClassicLighting_ResetColumn(cx, cy, cz, minCy, maxCy);
|
||||
|
||||
if (bX == 0 && cx > 0) {
|
||||
Lighting_ResetNeighbour(x - 1, y, z, block, cx - 1, cy, cz, minCy, maxCy);
|
||||
ClassicLighting_ResetNeighbour(x - 1, y, z, block, cx - 1, cy, cz, minCy, maxCy);
|
||||
}
|
||||
if (bY == 0 && cy > 0 && Lighting_Needs(block, World_GetBlock(x, y - 1, z))) {
|
||||
if (bY == 0 && cy > 0 && ClassicLighting_Needs(block, World_GetBlock(x, y - 1, z))) {
|
||||
MapRenderer_RefreshChunk(cx, cy - 1, cz);
|
||||
}
|
||||
if (bZ == 0 && cz > 0) {
|
||||
Lighting_ResetNeighbour(x, y, z - 1, block, cx, cy, cz - 1, minCy, maxCy);
|
||||
ClassicLighting_ResetNeighbour(x, y, z - 1, block, cx, cy, cz - 1, minCy, maxCy);
|
||||
}
|
||||
|
||||
if (bX == 15 && cx < MapRenderer_ChunksX - 1) {
|
||||
Lighting_ResetNeighbour(x + 1, y, z, block, cx + 1, cy, cz, minCy, maxCy);
|
||||
ClassicLighting_ResetNeighbour(x + 1, y, z, block, cx + 1, cy, cz, minCy, maxCy);
|
||||
}
|
||||
if (bY == 15 && cy < MapRenderer_ChunksY - 1 && Lighting_Needs(block, World_GetBlock(x, y + 1, z))) {
|
||||
if (bY == 15 && cy < MapRenderer_ChunksY - 1 && ClassicLighting_Needs(block, World_GetBlock(x, y + 1, z))) {
|
||||
MapRenderer_RefreshChunk(cx, cy + 1, cz);
|
||||
}
|
||||
if (bZ == 15 && cz < MapRenderer_ChunksZ - 1) {
|
||||
Lighting_ResetNeighbour(x, y, z + 1, block, cx, cy, cz + 1, minCy, maxCy);
|
||||
ClassicLighting_ResetNeighbour(x, y, z + 1, block, cx, cy, cz + 1, minCy, maxCy);
|
||||
}
|
||||
}
|
||||
|
||||
void Lighting_OnBlockChanged(int x, int y, int z, BlockID oldBlock, BlockID newBlock) {
|
||||
static void ClassicLighting_OnBlockChanged(int x, int y, int z, BlockID oldBlock, BlockID newBlock) {
|
||||
int hIndex = Lighting_Pack(x, z);
|
||||
int lightH = light_heightmap[hIndex];
|
||||
int lightH = classic_heightmap[hIndex];
|
||||
int newHeight;
|
||||
|
||||
/* Since light wasn't checked to begin with, means column never had meshes for any of its chunks built. */
|
||||
/* So we don't need to do anything. */
|
||||
if (lightH == HEIGHT_UNCALCULATED) return;
|
||||
|
||||
Lighting_UpdateLighting(x, y, z, oldBlock, newBlock, hIndex, lightH);
|
||||
newHeight = light_heightmap[hIndex] + 1;
|
||||
Lighting_RefreshAffected(x, y, z, newBlock, lightH + 1, newHeight);
|
||||
ClassicLighting_UpdateLighting(x, y, z, oldBlock, newBlock, hIndex, lightH);
|
||||
newHeight = classic_heightmap[hIndex] + 1;
|
||||
ClassicLighting_RefreshAffected(x, y, z, newBlock, lightH + 1, newHeight);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------Lighting heightmap----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static int Lighting_InitialHeightmapCoverage(int x1, int z1, int xCount, int zCount, int* skip) {
|
||||
static int Heightmap_InitialCoverage(int x1, int z1, int xCount, int zCount, int* skip) {
|
||||
int elemsLeft = 0, index = 0, curRunCount = 0;
|
||||
int x, z, hIndex, lightH;
|
||||
|
||||
for (z = 0; z < zCount; z++) {
|
||||
hIndex = Lighting_Pack(x1, z1 + z);
|
||||
for (x = 0; x < xCount; x++) {
|
||||
lightH = light_heightmap[hIndex++];
|
||||
lightH = classic_heightmap[hIndex++];
|
||||
|
||||
skip[index] = 0;
|
||||
if (lightH == HEIGHT_UNCALCULATED) {
|
||||
@ -266,7 +271,7 @@ static int Lighting_InitialHeightmapCoverage(int x1, int z1, int xCount, int zCo
|
||||
return elemsLeft;
|
||||
}
|
||||
|
||||
#define Lighting_CalculateBody(get_block)\
|
||||
#define Heightmap_CalculateBody(get_block)\
|
||||
for (y = World.Height - 1; y >= 0; y--) {\
|
||||
if (elemsLeft <= 0) { return true; } \
|
||||
mapIndex = World_Pack(x1, y, z1);\
|
||||
@ -281,7 +286,7 @@ for (y = World.Height - 1; y >= 0; y--) {\
|
||||
\
|
||||
if (x < xCount && Blocks.BlocksLight[get_block]) {\
|
||||
lightOffset = (Blocks.LightOffset[get_block] >> FACE_YMAX) & 1;\
|
||||
light_heightmap[hIndex + x] = (cc_int16)(y - lightOffset);\
|
||||
classic_heightmap[hIndex + x] = (cc_int16)(y - lightOffset);\
|
||||
elemsLeft--;\
|
||||
skip[index] = 0;\
|
||||
\
|
||||
@ -309,71 +314,92 @@ for (y = World.Height - 1; y >= 0; y--) {\
|
||||
}\
|
||||
}
|
||||
|
||||
static cc_bool Lighting_CalculateHeightmapCoverage(int x1, int z1, int xCount, int zCount, int elemsLeft, int* skip) {
|
||||
static cc_bool Heightmap_CalculateCoverage(int x1, int z1, int xCount, int zCount, int elemsLeft, int* skip) {
|
||||
int prevRunCount = 0, curRunCount, newRunCount, oldRunCount;
|
||||
int lightOffset, offset;
|
||||
int mapIndex, hIndex, baseIndex, index;
|
||||
int x, y, z;
|
||||
|
||||
#ifndef EXTENDED_BLOCKS
|
||||
Lighting_CalculateBody(World.Blocks[mapIndex]);
|
||||
Heightmap_CalculateBody(World.Blocks[mapIndex]);
|
||||
#else
|
||||
if (World.IDMask <= 0xFF) {
|
||||
Lighting_CalculateBody(World.Blocks[mapIndex]);
|
||||
Heightmap_CalculateBody(World.Blocks[mapIndex]);
|
||||
} else {
|
||||
Lighting_CalculateBody(World.Blocks[mapIndex] | (World.Blocks2[mapIndex] << 8));
|
||||
Heightmap_CalculateBody(World.Blocks[mapIndex] | (World.Blocks2[mapIndex] << 8));
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Lighting_FinishHeightmapCoverage(int x1, int z1, int xCount, int zCount) {
|
||||
static void Heightmap_FinishCoverage(int x1, int z1, int xCount, int zCount) {
|
||||
int x, z, hIndex, lightH;
|
||||
|
||||
for (z = 0; z < zCount; z++) {
|
||||
hIndex = Lighting_Pack(x1, z1 + z);
|
||||
for (x = 0; x < xCount; x++, hIndex++) {
|
||||
lightH = light_heightmap[hIndex];
|
||||
lightH = classic_heightmap[hIndex];
|
||||
|
||||
if (lightH == HEIGHT_UNCALCULATED) {
|
||||
light_heightmap[hIndex] = -10;
|
||||
classic_heightmap[hIndex] = -10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Lighting_LightHint(int startX, int startZ) {
|
||||
static void ClassicLighting_LightHint(int startX, int startZ) {
|
||||
int x1 = max(startX, 0), x2 = min(World.Width, startX + EXTCHUNK_SIZE);
|
||||
int z1 = max(startZ, 0), z2 = min(World.Length, startZ + EXTCHUNK_SIZE);
|
||||
int xCount = x2 - x1, zCount = z2 - z1;
|
||||
int skip[EXTCHUNK_SIZE * EXTCHUNK_SIZE];
|
||||
|
||||
int elemsLeft = Lighting_InitialHeightmapCoverage(x1, z1, xCount, zCount, skip);
|
||||
if (!Lighting_CalculateHeightmapCoverage(x1, z1, xCount, zCount, elemsLeft, skip)) {
|
||||
Lighting_FinishHeightmapCoverage(x1, z1, xCount, zCount);
|
||||
int elemsLeft = Heightmap_InitialCoverage(x1, z1, xCount, zCount, skip);
|
||||
if (!Heightmap_CalculateCoverage(x1, z1, xCount, zCount, elemsLeft, skip)) {
|
||||
Heightmap_FinishCoverage(x1, z1, xCount, zCount);
|
||||
}
|
||||
}
|
||||
|
||||
static void ClassicLighting_SetActive(void) {
|
||||
Lighting.LightHint = ClassicLighting_LightHint;
|
||||
Lighting.OnBlockChanged = ClassicLighting_OnBlockChanged;
|
||||
Lighting.Refresh = ClassicLighting_Refresh;
|
||||
Lighting.IsLit = ClassicLighting_IsLit;
|
||||
Lighting.Color = ClassicLighting_Color;
|
||||
Lighting.Color_XSide = ClassicLighting_Color_XSide;
|
||||
|
||||
Lighting.IsLit_Fast = ClassicLighting_IsLit_Fast;
|
||||
Lighting.Color_Sprite_Fast = ClassicLighting_Color_Sprite_Fast;
|
||||
Lighting.Color_YMax_Fast = ClassicLighting_Color_YMax_Fast;
|
||||
Lighting.Color_YMin_Fast = ClassicLighting_Color_YMin_Fast;
|
||||
Lighting.Color_XSide_Fast = ClassicLighting_Color_XSide_Fast;
|
||||
Lighting.Color_ZSide_Fast = ClassicLighting_Color_ZSide_Fast;
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------Lighting component----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
|
||||
static void OnInit(void) {
|
||||
ClassicLighting_SetActive();
|
||||
}
|
||||
|
||||
static void OnReset(void) {
|
||||
Mem_Free(light_heightmap);
|
||||
light_heightmap = NULL;
|
||||
Mem_Free(classic_heightmap);
|
||||
classic_heightmap = NULL;
|
||||
}
|
||||
|
||||
static void OnNewMapLoaded(void) {
|
||||
light_heightmap = (cc_int16*)Mem_TryAlloc(World.Width * World.Length, 2);
|
||||
if (light_heightmap) {
|
||||
Lighting_Refresh();
|
||||
classic_heightmap = (cc_int16*)Mem_TryAlloc(World.Width * World.Length, 2);
|
||||
if (classic_heightmap) {
|
||||
ClassicLighting_Refresh();
|
||||
} else {
|
||||
World_OutOfMemory();
|
||||
}
|
||||
}
|
||||
|
||||
struct IGameComponent Lighting_Component = {
|
||||
NULL, /* Init */
|
||||
OnInit, /* Init */
|
||||
OnReset, /* Free */
|
||||
OnReset, /* Reset */
|
||||
OnReset, /* OnNewMap */
|
||||
|
@ -1,41 +1,42 @@
|
||||
#ifndef CC_WORLDLIGHTING_H
|
||||
#define CC_WORLDLIGHTING_H
|
||||
#include "PackedCol.h"
|
||||
/* Manages lighting of blocks in the world.
|
||||
BasicLighting: Uses a simple heightmap, where each block is either in sun or shadow.
|
||||
/* Manages lighting of blocks in the world
|
||||
ClassicLighting: Uses a simple heightmap, where each block is either in sun or shadow.
|
||||
Copyright 2014-2021 ClassiCube | Licensed under BSD-3
|
||||
*/
|
||||
struct IGameComponent;
|
||||
extern struct IGameComponent Lighting_Component;
|
||||
|
||||
#define Lighting_Pack(x, z) ((x) + World.Width * (z))
|
||||
/* Equivalent to (but far more optimised form of)
|
||||
* for x = startX; x < startX + 18; x++
|
||||
* for z = startZ; z < startZ + 18; z++
|
||||
* CalcLight(x, maxY, z) */
|
||||
void Lighting_LightHint(int startX, int startZ);
|
||||
CC_VAR extern struct _Lighting {
|
||||
/* Equivalent to (but far more optimised form of)
|
||||
* for x = startX; x < startX + 18; x++
|
||||
* for z = startZ; z < startZ + 18; z++
|
||||
* CalcLight(x, maxY, z) */
|
||||
void (*LightHint)(int startX, int startZ);
|
||||
|
||||
/* Called when a block is changed to update internal lighting state. */
|
||||
/* NOTE: Implementations ***MUST*** mark all chunks affected by this lighting change as needing to be refreshed. */
|
||||
void Lighting_OnBlockChanged(int x, int y, int z, BlockID oldBlock, BlockID newBlock);
|
||||
void Lighting_Refresh(void);
|
||||
/* Called when a block is changed to update internal lighting state. */
|
||||
/* NOTE: Implementations ***MUST*** mark all chunks affected by this lighting change as needing to be refreshed. */
|
||||
void (*OnBlockChanged)(int x, int y, int z, BlockID oldBlock, BlockID newBlock);
|
||||
void (*Refresh)(void);
|
||||
|
||||
/* Returns whether the block at the given coordinates is fully in sunlight. */
|
||||
/* NOTE: Does ***NOT*** check that the coordinates are inside the map. */
|
||||
cc_bool Lighting_IsLit(int x, int y, int z);
|
||||
/* Returns the light colour at the given coordinates. */
|
||||
PackedCol Lighting_Color(int x, int y, int z);
|
||||
/* Returns the light colour at the given coordinates. */
|
||||
PackedCol Lighting_Color_XSide(int x, int y, int z);
|
||||
/* Returns whether the block at the given coordinates is fully in sunlight. */
|
||||
/* NOTE: Does ***NOT*** check that the coordinates are inside the map. */
|
||||
cc_bool (*IsLit)(int x, int y, int z);
|
||||
/* Returns the light colour at the given coordinates. */
|
||||
PackedCol (*Color)(int x, int y, int z);
|
||||
/* Returns the light colour at the given coordinates. */
|
||||
PackedCol (*Color_XSide)(int x, int y, int z);
|
||||
|
||||
/* _Fast functions assume Lighting_LightHint has already been called */
|
||||
/* and performed the necessary calculations for the given x/z coords */
|
||||
/* _Fast functions also do NOT check coordinates are inside the map */
|
||||
/* _Fast functions assume Lighting_LightHint has already been called */
|
||||
/* and performed the necessary calculations for the given x/z coords */
|
||||
/* _Fast functions also do NOT check coordinates are inside the map */
|
||||
|
||||
cc_bool Lighting_IsLit_Fast(int x, int y, int z);
|
||||
PackedCol Lighting_Color_Sprite_Fast(int x, int y, int z);
|
||||
PackedCol Lighting_Color_YMax_Fast(int x, int y, int z);
|
||||
PackedCol Lighting_Color_YMin_Fast(int x, int y, int z);
|
||||
PackedCol Lighting_Color_XSide_Fast(int x, int y, int z);
|
||||
PackedCol Lighting_Color_ZSide_Fast(int x, int y, int z);
|
||||
cc_bool (*IsLit_Fast)(int x, int y, int z);
|
||||
PackedCol (*Color_Sprite_Fast)(int x, int y, int z);
|
||||
PackedCol (*Color_YMax_Fast)(int x, int y, int z);
|
||||
PackedCol (*Color_YMin_Fast)(int x, int y, int z);
|
||||
PackedCol (*Color_XSide_Fast)(int x, int y, int z);
|
||||
PackedCol (*Color_ZSide_Fast)(int x, int y, int z);
|
||||
} Lighting;
|
||||
#endif
|
||||
|
@ -150,7 +150,7 @@ static void RainParticle_Render(struct Particle* p, float t, struct VertexTextur
|
||||
size.X = p->size * 0.015625f; size.Y = size.X;
|
||||
|
||||
x = Math_Floor(pos.X); y = Math_Floor(pos.Y); z = Math_Floor(pos.Z);
|
||||
col = Lighting_Color(x, y, z);
|
||||
col = Lighting.Color(x, y, z);
|
||||
Particle_DoRender(&size, &pos, &rain_rec, col, vertices);
|
||||
}
|
||||
|
||||
@ -223,7 +223,7 @@ static void TerrainParticle_Render(struct TerrainParticle* p, float t, struct Ve
|
||||
|
||||
if (!Blocks.FullBright[p->block]) {
|
||||
x = Math_Floor(pos.X); y = Math_Floor(pos.Y); z = Math_Floor(pos.Z);
|
||||
col = Lighting_Color_XSide(x, y, z);
|
||||
col = Lighting.Color_XSide(x, y, z);
|
||||
}
|
||||
|
||||
Block_Tint(col, p->block);
|
||||
@ -349,7 +349,7 @@ static void CustomParticle_Render(struct CustomParticle* p, float t, struct Vert
|
||||
size.X = p->base.size; size.Y = size.X;
|
||||
|
||||
x = Math_Floor(pos.X); y = Math_Floor(pos.Y); z = Math_Floor(pos.Z);
|
||||
col = e->fullBright ? PACKEDCOL_WHITE : Lighting_Color(x, y, z);
|
||||
col = e->fullBright ? PACKEDCOL_WHITE : Lighting.Color(x, y, z);
|
||||
col = PackedCol_Tint(col, e->tintCol);
|
||||
|
||||
Particle_DoRender(&size, &pos, &rec, col, vertices);
|
||||
|
@ -507,8 +507,7 @@ static void Classic_LevelDataChunk(cc_uint8* data) {
|
||||
struct MapState* m;
|
||||
int usedLength;
|
||||
float progress;
|
||||
cc_uint32 left, read;
|
||||
cc_uint8 value;
|
||||
cc_uint32 read;
|
||||
cc_result res;
|
||||
|
||||
/* Workaround for some servers that send LevelDataChunk before LevelInit due to their async sending behaviour */
|
||||
@ -523,7 +522,7 @@ static void Classic_LevelDataChunk(cc_uint8* data) {
|
||||
#ifndef EXTENDED_BLOCKS
|
||||
m = &map1;
|
||||
#else
|
||||
/* progress in original classic, but we ignore it */
|
||||
/* progress byte in original classic, but we ignore it */
|
||||
if (cpe_extBlocks && data[1026]) {
|
||||
m = &map2;
|
||||
} else {
|
||||
@ -1634,7 +1633,7 @@ static void CPE_Tick(void) {
|
||||
static void BlockDefs_OnBlockUpdated(BlockID block, cc_bool didBlockLight) {
|
||||
if (!World.Loaded) return;
|
||||
/* Need to refresh lighting when a block's light blocking state changes */
|
||||
if (Blocks.BlocksLight[block] != didBlockLight) Lighting_Refresh();
|
||||
if (Blocks.BlocksLight[block] != didBlockLight) Lighting.Refresh();
|
||||
}
|
||||
|
||||
static TextureLoc BlockDefs_Tex(cc_uint8** ptr) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user