Add mirror block
This commit is contained in:
parent
edb7bd94fa
commit
3c903ff49f
3 changed files with 170 additions and 73 deletions
203
map.h
203
map.h
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue