#include "handmade_tile.h" static struct tile_chunk * GetTileChunk(struct tile_map *TileMap, unsigned int TileChunkX, unsigned int TileChunkY, unsigned int TileChunkZ) { struct 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 struct tile_chunk_position GetChunkPositionFor(struct tile_map *TileMap, unsigned int AbsTileX, unsigned int AbsTileY, unsigned int AbsTileZ) { struct 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 unsigned int GetTileValueUnchecked(struct tile_map *TileMap, struct tile_chunk *TileChunk, unsigned int TileX, unsigned int TileY) { ASSERT(TileChunk); ASSERT(TileX < TileMap->ChunkDim); ASSERT(TileY < TileMap->ChunkDim); unsigned int TileChunkValue = TileChunk->Tiles[TileY * TileMap->ChunkDim + TileX]; return TileChunkValue; } static unsigned int GetTileChunkValue(struct tile_map *TileMap, struct tile_chunk *TileChunk, unsigned int TestTileX, unsigned int TestTileY) { unsigned int TileChunkValue = 0; if(TileChunk && TileChunk->Tiles) { TileChunkValue = GetTileValueUnchecked(TileMap, TileChunk, TestTileX, TestTileY); } return TileChunkValue; } static unsigned int GetTileValue(struct tile_map *TileMap, unsigned int AbsTileX, unsigned int AbsTileY, unsigned int AbsTileZ) { struct tile_chunk_position ChunkPos = GetChunkPositionFor(TileMap, AbsTileX, AbsTileY, AbsTileZ); struct tile_chunk *TileChunk = GetTileChunk(TileMap, ChunkPos.TileChunkX, ChunkPos.TileChunkY, ChunkPos.TileChunkZ); unsigned int TileChunkValue = GetTileChunkValue(TileMap, TileChunk, ChunkPos.RelTileX, ChunkPos.RelTileY); return TileChunkValue; } static int IsTileValueEmpty(unsigned int TileValue) { int Empty = ((TileValue == 1) || (TileValue == 3) || (TileValue == 4)); return Empty; } static unsigned int GetTileValueByPos(struct tile_map *TileMap, struct tile_map_position Pos) { unsigned int TileChunkValue = GetTileValue(TileMap, Pos.AbsTileX, Pos.AbsTileY, Pos.AbsTileZ); return TileChunkValue; } static void SetTileValueUnchecked(struct tile_map *TileMap, struct tile_chunk *TileChunk, unsigned int TileX, unsigned int TileY, unsigned int TileValue) { ASSERT(TileChunk); ASSERT(TileX < TileMap->ChunkDim); ASSERT(TileY < TileMap->ChunkDim); TileChunk->Tiles[TileY * TileMap->ChunkDim + TileX] = TileValue; } static void SetTileChunkValue(struct tile_map *TileMap, struct tile_chunk *TileChunk, unsigned int TestTileX, unsigned int TestTileY, unsigned int TileValue) { if(TileChunk && TileChunk->Tiles) { SetTileValueUnchecked(TileMap, TileChunk, TestTileX, TestTileY, TileValue); } } static int IsTileMapPointEmpty(struct tile_map *TileMap, struct tile_map_position Pos) { unsigned int TileChunkValue = GetTileValueByPos(TileMap, Pos); int Empty = IsTileValueEmpty(TileChunkValue); return Empty; } static void SetTileValue(struct memory_arena *Arena, struct tile_map *TileMap, unsigned int AbsTileX, unsigned int AbsTileY, unsigned int AbsTileZ, unsigned int TileValue) { struct tile_chunk_position ChunkPos = GetChunkPositionFor(TileMap, AbsTileX, AbsTileY, AbsTileZ); struct tile_chunk *TileChunk = GetTileChunk(TileMap, ChunkPos.TileChunkX, ChunkPos.TileChunkY, ChunkPos.TileChunkZ); ASSERT(TileChunk); if(!TileChunk->Tiles) { unsigned int TileCount = TileMap->ChunkDim*TileMap->ChunkDim; TileChunk->Tiles = PUSH_ARRAY(Arena, TileCount, unsigned int); for(unsigned int 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(struct tile_map *TileMap, unsigned int *Tile, float *TileRel) { // NOTE: The world is assumed to be toroidal topology. If you step off // one end, you come back on the other. int Offset = RoundFloatToInt(*TileRel / TileMap->TileSideInMeters); *Tile += Offset; *TileRel -= (float)Offset * TileMap->TileSideInMeters; ASSERT(*TileRel >= -0.5f*TileMap->TileSideInMeters); ASSERT(*TileRel <= 0.5f*TileMap->TileSideInMeters); } static struct tile_map_position RecannonicalizePosition(struct tile_map *TileMap, struct tile_map_position Pos) { struct tile_map_position Result = Pos; CannonicalizeCoord(TileMap, &Result.AbsTileX, &Result.Offset.X); CannonicalizeCoord(TileMap, &Result.AbsTileY, &Result.Offset.Y); return Result; } static int AreOnSameTile(struct tile_map_position *A, struct tile_map_position *B) { int Result = ((A->AbsTileX == B->AbsTileX) && (A->AbsTileY == B->AbsTileY) && (A->AbsTileZ == B->AbsTileZ)); return Result; } static struct tile_map_difference SubtractInFloat(struct tile_map *TileMap, struct tile_map_position *A, struct tile_map_position *B) { struct tile_map_difference Result; struct v2 dTileXY = { ((float)A->AbsTileX - (float)B->AbsTileX), ((float)A->AbsTileY - (float)B->AbsTileY) }; float dTileZ = (float)A->AbsTileZ - (float)B->AbsTileZ; Result.dXY = V2Add(V2Multiply(TileMap->TileSideInMeters, dTileXY), V2Subtract(A->Offset, B->Offset)); // TODO: Incomplete . . . Result.dZ = TileMap->TileSideInMeters*dTileZ; return Result; } static struct tile_map_position CenteredTilePoint(unsigned int AbsTileX, unsigned int AbsTileY, unsigned int AbsTileZ) { struct tile_map_position Result; memset(&Result, 0, sizeof(Result)); Result.AbsTileX = AbsTileX; Result.AbsTileY = AbsTileY; Result.AbsTileZ = AbsTileZ; return Result; }