Add mirror block

This commit is contained in:
Miloslav Ciz 2025-02-10 23:21:23 +01:00
parent edb7bd94fa
commit 3c903ff49f
3 changed files with 170 additions and 73 deletions

203
map.h
View file

@ -127,6 +127,13 @@
size is given by block coords */
#define LCR_BLOCK_CUBOID_HOLLOW 'h' /**< same as cuboid special block,
but makes a hollow one */
#define LCR_BLOCK_MIRROR 'm' /**< makes a mirror copy along each
major axis, starting at coords of
last added block and iterating
over a block of size given by this
block's coords */
#define LCR_BLOCK_START '*' ///< specifies start block position
#define LCR_BLOCK_QUIT 'e' /**< special block, ends reading the
@ -193,6 +200,32 @@ uint8_t LCR_mapBlockOppositeTransform(uint8_t transform)
return transform;
}
uint8_t LCR_mapBlockFlipTransformX(uint8_t transform)
{
transform ^= LCR_BLOCK_TRANSFORM_FLIP_H;
if ((transform & 0x60) == LCR_BLOCK_TRANSFORM_ROT_90)
return ((transform & (~0x60)) | LCR_BLOCK_TRANSFORM_ROT_270);
else if ((transform & 0x60) == LCR_BLOCK_TRANSFORM_ROT_270)
return ((transform & (~0x60)) | LCR_BLOCK_TRANSFORM_ROT_90);
return transform;
}
uint8_t LCR_mapBlockFlipTransformZ(uint8_t transform)
{
transform ^= LCR_BLOCK_TRANSFORM_FLIP_H;
if ((transform & 0x60) == LCR_BLOCK_TRANSFORM_ROT_180)
return transform & (~0x60);
else if ((transform & 0x60) == 0)
return transform | LCR_BLOCK_TRANSFORM_ROT_180;
return transform;
}
uint8_t LCR_mapBlockIsAccelerator(uint8_t block)
{
return block == LCR_BLOCK_FULL_ACCEL || block == LCR_BLOCK_RAMP_ACCEL ||
@ -270,7 +303,7 @@ uint8_t *LCR_getMapBlockAtCoordNumber(uint32_t coord)
/**
Adds given block to current map, including possibly deleting a block by
adding LCR_BLOCK_NONE. The function handles sorting the block to the right
position. Returns pointer to the block on success, else 0.
position.
*/
void _LCR_mapAddBlock(const uint8_t block[LCR_BLOCK_SIZE])
{
@ -380,6 +413,59 @@ void _LCR_mapComputeHash(void)
(LCR_currentMap.hash >> 13)) * 113;
}
/**
Same as LCR_mapGetBlockAt, but allows to specify start and end block of the
of the search to make it faster.
*/
int LCR_mapGetBlockAtFast(uint8_t x, uint8_t y, uint8_t z,
int start, int end)
{
// binary search (the blocks are sorted)
uint32_t n = LCR_mapBlockCoordsToCoordNumber(x,y,z);
uint8_t cacheIndex = 2 * ((x % 2) | ((y % 2) << 1) | ((z % 2) << 2));
if (_LCR_mapBlockCache[cacheIndex] == n)
return
(_LCR_mapBlockCache[cacheIndex + 1] != 0xffffffff) ?
((int) _LCR_mapBlockCache[cacheIndex + 1]) : -1;
_LCR_mapBlockCache[cacheIndex] = n;
while (start <= end)
{
int m = (start + end) / 2;
uint32_t n2 = LCR_mapBlockGetCoordNumber(
LCR_currentMap.blocks + m * LCR_BLOCK_SIZE);
if (n2 < n)
start = m + 1;
else if (n2 > n)
end = m - 1;
else
{
_LCR_mapBlockCache[cacheIndex + 1] = m;
return m;
}
}
_LCR_mapBlockCache[cacheIndex + 1] = 0xffffffff;
return -1;
}
/**
Gets an index to a map block of the currently loaded map at given
coordinates. If there is no block at given coordinates, -1 is returned.
*/
int LCR_mapGetBlockAt(uint8_t x, uint8_t y, uint8_t z)
{
if (LCR_currentMap.blockCount == 0)
return -1;
return LCR_mapGetBlockAtFast(x,y,z,0,LCR_currentMap.blockCount - 1);
}
uint8_t LCR_mapLoadFromStr(char (*getNextCharFunc)(void), const char *name)
{
LCR_LOG0("loading map string");
@ -484,6 +570,68 @@ uint8_t LCR_mapLoadFromStr(char (*getNextCharFunc)(void), const char *name)
switch (block)
{
case LCR_BLOCK_MIRROR:
{
uint8_t x, y, z, mat, transform, type;
uint8_t tmpBlock[LCR_BLOCK_SIZE];
LCR_mapBlockGetCoords(prevBlock,&x,&y,&z);
for (uint8_t k = 0; k < coords[2]; ++k)
for (uint8_t j = 0; j < coords[1]; ++j)
for (uint8_t i = 0; i < coords[0]; ++i)
{
int blockIndex = LCR_mapGetBlockAt(x + i,y + j,z + k);
if (blockIndex >= 0)
{
mat = LCR_mapBlockGetMaterial(
LCR_currentMap.blocks + blockIndex * LCR_BLOCK_SIZE);
transform = LCR_mapBlockGetTransform(
LCR_currentMap.blocks + blockIndex * LCR_BLOCK_SIZE);
type = LCR_currentMap.blocks[blockIndex * LCR_BLOCK_SIZE];
for (uint8_t l = 1; l < 8; ++l)
{
int8_t x2 = x + i, y2 = y + j, z2 = z + k;
uint8_t t2 = transform;
if (l & 0x01)
{
x2 = x - 1 - i;
t2 = LCR_mapBlockFlipTransformX(t2);
}
if (l & 0x02)
{
y2 = y - 1 - j;
t2 ^= LCR_BLOCK_TRANSFORM_FLIP_V;
}
if (l & 0x04)
{
z2 = z - 1 - k;
t2 = LCR_mapBlockFlipTransformZ(t2);
}
if (
x2 >= 0 && x2 < LCR_MAP_SIZE_BLOCKS &&
y2 >= 0 && y2 < LCR_MAP_SIZE_BLOCKS &&
z2 >= 0 && z2 < LCR_MAP_SIZE_BLOCKS)
{
LCR_makeMapBlock(type,x2,y2,z2,mat,t2,tmpBlock);
_LCR_mapAddBlock(tmpBlock);
}
}
}
}
break;
}
case LCR_BLOCK_CUBOID_FILL:
case LCR_BLOCK_CUBOID_HOLLOW:
{
@ -555,59 +703,6 @@ uint8_t LCR_mapLoadFromStr(char (*getNextCharFunc)(void), const char *name)
return 1;
}
/**
Same as LCR_mapGetBlockAt, but allows to specify start and end block of the
of the search to make it faster.
*/
int LCR_mapGetBlockAtFast(uint8_t x, uint8_t y, uint8_t z,
int start, int end)
{
// binary search (the blocks are sorted)
uint32_t n = LCR_mapBlockCoordsToCoordNumber(x,y,z);
uint8_t cacheIndex = 2 * ((x % 2) | ((y % 2) << 1) | ((z % 2) << 2));
if (_LCR_mapBlockCache[cacheIndex] == n)
return
(_LCR_mapBlockCache[cacheIndex + 1] != 0xffffffff) ?
((int) _LCR_mapBlockCache[cacheIndex + 1]) : -1;
_LCR_mapBlockCache[cacheIndex] = n;
while (start <= end)
{
int m = (start + end) / 2;
uint32_t n2 = LCR_mapBlockGetCoordNumber(
LCR_currentMap.blocks + m * LCR_BLOCK_SIZE);
if (n2 < n)
start = m + 1;
else if (n2 > n)
end = m - 1;
else
{
_LCR_mapBlockCache[cacheIndex + 1] = m;
return m;
}
}
_LCR_mapBlockCache[cacheIndex + 1] = 0xffffffff;
return -1;
}
/**
Gets an index to a map block of the currently loaded map at given
coordinates. If there is no block at given coordinates, -1 is returned.
*/
int LCR_mapGetBlockAt(uint8_t x, uint8_t y, uint8_t z)
{
if (LCR_currentMap.blockCount == 0)
return -1;
return LCR_mapGetBlockAtFast(x,y,z,0,LCR_currentMap.blockCount - 1);
}
uint8_t _LCR_encodeMapBlockCoords(uint8_t x, uint8_t y, uint8_t z)
{
return (5 * 7) * z + 7 * y + x;