Files
handmadehero/handmade_tile.cpp
T
2026-04-16 18:10:54 -07:00

173 lines
5.7 KiB
C++

#include "handmade_tile.h"
static tile_chunk *GetTileChunk(tile_map *TileMap,
U32 TileChunkX,
U32 TileChunkY,
U32 TileChunkZ)
{
tile_chunk *TileChunk = NULL;
if((TileChunkX >= 0) && (TileChunkX < TileMap->TileChunkCountX) &&
(TileChunkY >= 0) && (TileChunkY < TileMap->TileChunkCountY) &&
(TileChunkZ >= 0) && (TileChunkZ < TileMap->TileChunkCountZ))
{
TileChunk =
&TileMap->TileChunks[
(TileChunkZ*TileMap->TileChunkCountY*TileMap->TileChunkCountX) +
(TileChunkY*TileMap->TileChunkCountX) +
TileChunkX];
}
return TileChunk;
}
static void CannonicalizeCoord(tile_map *TileMap, U32 *Tile, F32 *TileRel)
{
/* NOTE: The world is assumed to be toroidal topology. If you step off
one end, you come back on the other. */
S32 Offset = RoundF32toS32(*TileRel / TileMap->TileSideInMeters);
*Tile += Offset;
*TileRel -= (F32)Offset * TileMap->TileSideInMeters;
ASSERT(*TileRel >= -0.5f*TileMap->TileSideInMeters);
ASSERT(*TileRel <= 0.5f*TileMap->TileSideInMeters);
}
static tile_map_position RecannonicalizePosition(tile_map *TileMap,
tile_map_position Pos)
{
tile_map_position Result = Pos;
CannonicalizeCoord(TileMap, &Result.AbsTileX, &Result.TileRelX);
CannonicalizeCoord(TileMap, &Result.AbsTileY, &Result.TileRelY);
return Result;
}
static tile_chunk_position GetChunkPositionFor(tile_map *TileMap,
U32 AbsTileX,
U32 AbsTileY,
U32 AbsTileZ)
{
tile_chunk_position Result;
Result.TileChunkX = AbsTileX >> TileMap->ChunkShift;
Result.TileChunkY = AbsTileY >> TileMap->ChunkShift;
Result.TileChunkZ = AbsTileZ;
Result.RelTileX = AbsTileX & TileMap->ChunkMask;
Result.RelTileY = AbsTileY & TileMap->ChunkMask;
return Result;
}
static U32 GetTileValueUnchecked(tile_map *TileMap, tile_chunk *TileChunk,
U32 TileX, U32 TileY)
{
U32 TileChunkValue;
ASSERT(TileChunk);
ASSERT(TileX < TileMap->ChunkDim);
ASSERT(TileY < TileMap->ChunkDim);
TileChunkValue = TileChunk->Tiles[TileY * TileMap->ChunkDim + TileX];
return TileChunkValue;
}
static void SetTileValueUnchecked(tile_map *TileMap, tile_chunk *TileChunk,
U32 TileX, U32 TileY, U32 TileValue)
{
ASSERT(TileChunk);
ASSERT(TileX < TileMap->ChunkDim);
ASSERT(TileY < TileMap->ChunkDim);
TileChunk->Tiles[TileY * TileMap->ChunkDim + TileX] = TileValue;
}
static U32 GetTileChunkValue(tile_map *TileMap, tile_chunk *TileChunk,
U32 TestTileX, U32 TestTileY)
{
U32 TileChunkValue = 0;
if(TileChunk && TileChunk->Tiles) {
TileChunkValue = GetTileValueUnchecked(TileMap,
TileChunk,
TestTileX,
TestTileY);
}
return TileChunkValue;
}
static void SetTileChunkValue(tile_map *TileMap, tile_chunk *TileChunk,
U32 TestTileX, U32 TestTileY,
U32 TileValue)
{
if(TileChunk && TileChunk->Tiles) {
SetTileValueUnchecked(TileMap,
TileChunk,
TestTileX, TestTileY,
TileValue);
}
}
static U32 GetTileValue(tile_map *TileMap,
U32 AbsTileX, U32 AbsTileY, U32 AbsTileZ)
{
tile_chunk_position ChunkPos = GetChunkPositionFor(TileMap,
AbsTileX,
AbsTileY,
AbsTileZ);
tile_chunk *TileChunk = GetTileChunk(TileMap,
ChunkPos.TileChunkX,
ChunkPos.TileChunkY,
ChunkPos.TileChunkZ);
U32 TileChunkValue = GetTileChunkValue(TileMap, TileChunk,
ChunkPos.RelTileX,
ChunkPos.RelTileY);
return TileChunkValue;
}
static B32 IsTileMapPointEmpty(tile_map *TileMap, tile_map_position CanPos)
{
B32 Empty;
U32 TileChunkValue = GetTileValue(TileMap,
CanPos.AbsTileX,
CanPos.AbsTileY,
CanPos.AbsTileZ);
Empty = (TileChunkValue == 1);
return Empty;
}
static void SetTileValue(memory_arena *Arena,
tile_map *TileMap,
U32 AbsTileX, U32 AbsTileY, U32 AbsTileZ,
U32 TileValue)
{
tile_chunk_position ChunkPos;
tile_chunk *TileChunk;
ChunkPos = GetChunkPositionFor(TileMap, AbsTileX, AbsTileY, AbsTileZ);
TileChunk = GetTileChunk(TileMap,
ChunkPos.TileChunkX,
ChunkPos.TileChunkY,
ChunkPos.TileChunkZ);
ASSERT(TileChunk);
if(!TileChunk->Tiles) {
U32 TileCount = TileMap->ChunkDim*TileMap->ChunkDim;
U32 TileIndex;
TileChunk->Tiles = PUSH_ARRAY(Arena, TileCount, U32);
for(TileIndex = 0; TileIndex < TileCount; TileIndex++) {
TileChunk->Tiles[TileIndex] = 1;
}
}
SetTileChunkValue(TileMap, TileChunk,
ChunkPos.RelTileX,
ChunkPos.RelTileY,
TileValue);
}