#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 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) { ASSERT(TileChunk); ASSERT(TileX < TileMap->ChunkDim); ASSERT(TileY < TileMap->ChunkDim); U32 TileChunkValue = TileChunk->Tiles[TileY * TileMap->ChunkDim + TileX]; return TileChunkValue; } 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 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 U32 GetTileValueByPos(tile_map *TileMap, tile_map_position Pos) { U32 TileChunkValue = GetTileValue(TileMap, Pos.AbsTileX, Pos.AbsTileY, Pos.AbsTileZ); 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 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 B32 IsTileMapPointEmpty(tile_map *TileMap, tile_map_position Pos) { U32 TileChunkValue = GetTileValueByPos(TileMap, Pos); B32 Empty = ((TileChunkValue == 1) || (TileChunkValue == 3) || (TileChunkValue == 4)); return Empty; } static void SetTileValue(memory_arena *Arena, tile_map *TileMap, U32 AbsTileX, U32 AbsTileY, U32 AbsTileZ, U32 TileValue) { tile_chunk_position ChunkPos = GetChunkPositionFor(TileMap, AbsTileX, AbsTileY, AbsTileZ); tile_chunk *TileChunk = GetTileChunk(TileMap, ChunkPos.TileChunkX, ChunkPos.TileChunkY, ChunkPos.TileChunkZ); ASSERT(TileChunk); if(!TileChunk->Tiles) { U32 TileCount = TileMap->ChunkDim*TileMap->ChunkDim; TileChunk->Tiles = PUSH_ARRAY(Arena, TileCount, U32); for(U32 TileIndex = 0; TileIndex < TileCount; TileIndex++) { TileChunk->Tiles[TileIndex] = 1; } } SetTileChunkValue(TileMap, TileChunk, ChunkPos.RelTileX, ChunkPos.RelTileY, TileValue); } // // TODO: Do these belong more in a "positioning" or "geometry" file? // 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.OffsetX); CannonicalizeCoord(TileMap, &Result.AbsTileY, &Result.OffsetY); return Result; } static B32 AreOnSameTile(tile_map_position *A, tile_map_position *B) { B32 Result = ((A->AbsTileX == B->AbsTileX) && (A->AbsTileY == B->AbsTileY) && (A->AbsTileZ == B->AbsTileZ)); return Result; } static tile_map_difference SubtractInF32(tile_map *TileMap, tile_map_position *A, tile_map_position *B) { tile_map_difference Result; F32 dTileX = (F32)A->AbsTileX - (F32)B->AbsTileX; F32 dTileY = (F32)A->AbsTileY - (F32)B->AbsTileY; F32 dTileZ = (F32)A->AbsTileZ - (F32)B->AbsTileZ; Result.dX = TileMap->TileSideInMeters*dTileX + (A->OffsetX - B->OffsetX); Result.dY = TileMap->TileSideInMeters*dTileY + (A->OffsetY - B->OffsetY); // TODO: Incomplete . . . Result.dZ = TileMap->TileSideInMeters*dTileZ; return Result; }