| 
									
										
										
										
											2023-07-21 21:17:49 +02:00
										 |  |  | #ifndef _LCR_MAP
 | 
					
						
							|  |  |  | #define _LCR_MAP
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdint.h>
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | #include "constants.h"
 | 
					
						
							|  |  |  | #include "settings.h"
 | 
					
						
							| 
									
										
										
										
											2023-07-21 21:17:49 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |   The map (track) module for Licar. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-23 16:51:09 +02:00
										 |  |  |   Map coordinates/size: | 
					
						
							|  |  |  |     - map size is 64x64x64 blocks | 
					
						
							|  |  |  |     - [0,0,0] is is bottom-left-front-most | 
					
						
							|  |  |  |     - x goes right, y goes up, z goes forward | 
					
						
							|  |  |  |     - coordinate number is a single number obtained as x + 64 * y + 64 * 64 * z | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |   The STORAGE map format is binary and consists of the following values: | 
					
						
							| 
									
										
										
										
											2023-07-23 16:51:09 +02:00
										 |  |  |     - 76, 77 (for "LM", magic number) | 
					
						
							| 
									
										
										
										
											2023-08-08 16:17:51 +02:00
										 |  |  |     - one byte recording the map environment | 
					
						
							| 
									
										
										
										
											2023-07-23 16:51:09 +02:00
										 |  |  |     - ASCII map name | 
					
						
							|  |  |  |     - 10 (separator) | 
					
						
							|  |  |  |     - ASCII comment | 
					
						
							|  |  |  |     - 10 (separator) | 
					
						
							|  |  |  |     - block values, each one in the format: | 
					
						
							|  |  |  |       - 1 byte type: says the type of block. If the highest bit is 0, the block | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |         is normal, otherwise it is a special block (will be preprocessed) | 
					
						
							| 
									
										
										
										
											2023-07-23 16:51:09 +02:00
										 |  |  |       - 3 bytes: A, B, C, such that: | 
					
						
							|  |  |  |         - A, B and lowest 2 bits of C form the block coordinate number (A being | 
					
						
							|  |  |  |           the lowest part etc.) | 
					
						
							|  |  |  |         - bits C2 and C3 say the block material | 
					
						
							|  |  |  |         - highest 4 bits of C (C4, C5, C6, C7) say the block's transform: | 
					
						
							|  |  |  |           - first if C4 is set, the block is flipped in the X direction | 
					
						
							|  |  |  |           - then the block is rotated around vertical axis by 0, 90, 180 or 270 | 
					
						
							|  |  |  |             degrees if C5C6 is 00, 01, 10 or 11. | 
					
						
							|  |  |  |           - last if C7 is set, the block is flipped vertically | 
					
						
							|  |  |  |     - 255 (terminator) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   In this format order of blocks matters, latter blocks will replace previous | 
					
						
							|  |  |  |   blocks placed on the same coordinate. Internally the map will be preprocessed | 
					
						
							|  |  |  |   to RAM when loaded so that thing like the magic number and special blocks are | 
					
						
							|  |  |  |   removed and the remaining blocks will be sorted for fast block searching. | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   The PREPROCESSED map format is similar, but only consists of block values but | 
					
						
							|  |  |  |   there are only normal blocks (no special blocks) and they are sorted by their | 
					
						
							|  |  |  |   coordinate number. | 
					
						
							| 
									
										
										
										
											2023-07-21 21:17:49 +02:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-23 16:51:09 +02:00
										 |  |  | #define LCR_BLOCK_TRANSFORM_FLIP_H    0x10
 | 
					
						
							|  |  |  | #define LCR_BLOCK_TRANSFORM_ROT_90    0x20
 | 
					
						
							|  |  |  | #define LCR_BLOCK_TRANSFORM_ROT_180   0x40
 | 
					
						
							|  |  |  | #define LCR_BLOCK_TRANSFORM_ROT_270   0x60
 | 
					
						
							|  |  |  | #define LCR_BLOCK_TRANSFORM_FLIP_V    0x80
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  | #define LCR_BLOCK_XYZ_TO_COORD(x,y,z) // ??? 
 | 
					
						
							| 
									
										
										
										
											2023-07-23 16:51:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | #define LCR_MAP_MAGIC_NUMBER1         'L'
 | 
					
						
							|  |  |  | #define LCR_MAP_MAGIC_NUMBER2         'M'
 | 
					
						
							|  |  |  | #define LCR_MAP_MAGIC_NUMBER          LCR_MAP_MAGIC_NUMBER1, LCR_MAP_MAGIC_NUMBER2
 | 
					
						
							| 
									
										
										
										
											2023-07-23 16:51:09 +02:00
										 |  |  | #define LCR_MAP_TERMINATOR            0xff
 | 
					
						
							| 
									
										
										
										
											2024-07-24 23:16:13 +02:00
										 |  |  | #define LCR_MAP_BLOCK(t,x,y,z,m,r)    t,(uint8_t) (x | (y << 6)), \
 | 
					
						
							|  |  |  |                                       (uint8_t) ((y >> 2) | (z << 4)), \ | 
					
						
							|  |  |  |                                       (uint8_t) ((z >> 4) | (m << 2) | (r)) | 
					
						
							| 
									
										
										
										
											2023-07-23 16:51:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  | #define LCR_BLOCK_SIZE                4 ///< size of map block, in bytes
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-23 16:51:09 +02:00
										 |  |  | #define LCR_BLOCK_MATERIAL_CONCRETE   0x00
 | 
					
						
							| 
									
										
										
										
											2024-08-01 21:41:21 +02:00
										 |  |  | #define LCR_BLOCK_MATERIAL_GRASS      0x01
 | 
					
						
							|  |  |  | #define LCR_BLOCK_MATERIAL_DIRT       0x02
 | 
					
						
							|  |  |  | #define LCR_BLOCK_MATERIAL_ICE        0x03
 | 
					
						
							| 
									
										
										
										
											2023-07-21 21:17:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-23 16:51:09 +02:00
										 |  |  | #define LCR_MAP_COUNT                 1
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | // normal blocks:
 | 
					
						
							| 
									
										
										
										
											2024-09-23 23:31:30 +02:00
										 |  |  | #define LCR_BLOCK_FULL                0x00 ///< completely filled block
 | 
					
						
							|  |  |  | #define LCR_BLOCK_BOTTOM              0x01 ///< filled bottom half
 | 
					
						
							|  |  |  | #define LCR_BLOCK_LEFT                0x02 ///< filled left half
 | 
					
						
							|  |  |  | #define LCR_BLOCK_BOTTOM_LEFT         0x03 ///< filled bottom left quarter
 | 
					
						
							|  |  |  | #define LCR_BLOCK_BOTTOM_LEFT_FRONT   0x04 ///< filled bottom left front eigth
 | 
					
						
							|  |  |  | #define LCR_BLOCK_RAMP                0x05 ///< plain ramp
 | 
					
						
							|  |  |  | #define LCR_BLOCK_RAMP_34             0x06 ///< plain ramp, 3/4 size
 | 
					
						
							|  |  |  | #define LCR_BLOCK_RAMP_12             0x07 ///< plain ramp, 1/2 size
 | 
					
						
							|  |  |  | #define LCR_BLOCK_RAMP_14             0x08 ///< plain ramp, 1/4 size
 | 
					
						
							| 
									
										
										
										
											2024-10-03 00:24:28 +02:00
										 |  |  | #define LCR_BLOCK_RAMP_CURVED_PLAT    0x09 ///< curved ramp with top platgform
 | 
					
						
							| 
									
										
										
										
											2024-11-21 00:16:00 +01:00
										 |  |  | #define LCR_BLOCK_RAMP_CURVED         0x0a ///< curv. ramp without top platf.
 | 
					
						
							| 
									
										
										
										
											2024-10-03 00:24:28 +02:00
										 |  |  | #define LCR_BLOCK_RAMP_CURVED_WALL    0x0b ///< curved ramp plus small wall
 | 
					
						
							| 
									
										
										
										
											2024-10-01 22:38:49 +02:00
										 |  |  | #define LCR_BLOCK_RAMP_STEEP          0x0c ///< extremely steep ramp
 | 
					
						
							|  |  |  | #define LCR_BLOCK_CORNER              0x0d ///< diagonal corner
 | 
					
						
							|  |  |  | #define LCR_BLOCK_CORNER_12           0x0e ///< diagonal corner (1/2 wide)
 | 
					
						
							| 
									
										
										
										
											2024-09-23 23:31:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-03 00:24:28 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |   TODO: | 
					
						
							|  |  |  |   - ramp corner??? | 
					
						
							|  |  |  |   - curved corner? | 
					
						
							|  |  |  |   - curved out corner? | 
					
						
							|  |  |  |   - curved "hill" | 
					
						
							|  |  |  |   - bumpy road | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-23 23:31:30 +02:00
										 |  |  | #define LCR_BLOCK_FULL_ACCEL          0x20
 | 
					
						
							|  |  |  | #define LCR_BLOCK_FULL_FAN            0x30
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define LCR_BLOCK_CHECKPOINT_0        0x40 ///< checkpoint, not taken
 | 
					
						
							|  |  |  | #define LCR_BLOCK_CHECKPOINT_1        0x41 ///< checkpoint, taken
 | 
					
						
							|  |  |  | #define LCR_BLOCK_FINISH              0x42 ///< finish
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // special blocks:
 | 
					
						
							| 
									
										
										
										
											2024-09-23 23:31:30 +02:00
										 |  |  | #define LCR_BLOCK_NONE                0x80 ///< no block, e.g to make holes
 | 
					
						
							|  |  |  | #define LCR_BLOCK_CUBOID_FILL         0x81 /**< makes a cuboid from the
 | 
					
						
							|  |  |  |                                              previously specified block, the | 
					
						
							|  |  |  |                                              size is given by block coords */ | 
					
						
							|  |  |  | #define LCR_BLOCK_CUBOID_HOLLOW       0x82 /**< same as cuboid special block,
 | 
					
						
							|  |  |  |                                              but makes a hollow one */ | 
					
						
							|  |  |  | #define LCR_BLOCK_START               0x83 ///< specifies start block position
 | 
					
						
							| 
									
										
										
										
											2023-07-21 21:17:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-21 00:16:00 +01:00
										 |  |  | #define LCR_MAP_BLOCK_CACHE_SIZE (8 * 2)   /// do not change
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |   Cache for accelerating LCR_mapGetBlockAtFast, consists of 8 2-item records, | 
					
						
							|  |  |  |   the first record item stores block coord number, the second one stores the | 
					
						
							|  |  |  |   value returned by LCR_mapGetBlockAtFast (-1 is 0xffffffff). The record index | 
					
						
							|  |  |  |   depends on the block coords: lowest bit is x % 2, middle bit y % 2, highest | 
					
						
							|  |  |  |   one z % 2. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | uint32_t _LCR_mapBlockCache[LCR_MAP_BLOCK_CACHE_SIZE]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | struct | 
					
						
							| 
									
										
										
										
											2023-07-21 21:17:49 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |   uint16_t blockCount; | 
					
						
							| 
									
										
										
										
											2024-09-23 23:31:30 +02:00
										 |  |  |   uint8_t blocks[LCR_SETTING_MAP_MAX_BLOCKS * LCR_BLOCK_SIZE]; | 
					
						
							| 
									
										
										
										
											2024-09-29 20:52:52 +02:00
										 |  |  |   uint8_t startPos[4]; ///< Initial position and rotation.
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-08 16:17:51 +02:00
										 |  |  |   uint8_t environment; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |   // TODO: name, desc? possibly as a single '\n' separated string?
 | 
					
						
							|  |  |  | } LCR_currentMap; | 
					
						
							| 
									
										
										
										
											2023-07-21 21:17:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-23 16:51:09 +02:00
										 |  |  | static const uint8_t LCR_map0[] = | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   LCR_MAP_MAGIC_NUMBER, | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |   77, 48, 10,   // map name: M0
 | 
					
						
							| 
									
										
										
										
											2023-07-23 16:51:09 +02:00
										 |  |  |   10,           // map comment:
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |   LCR_MAP_BLOCK( LCR_BLOCK_NONE, 3, 0, 0, LCR_BLOCK_MATERIAL_CONCRETE, 0), | 
					
						
							|  |  |  |   LCR_MAP_BLOCK( LCR_BLOCK_FULL, 3, 0, 0, LCR_BLOCK_MATERIAL_CONCRETE, 0), | 
					
						
							|  |  |  |   LCR_MAP_BLOCK( LCR_BLOCK_FULL, 0, 1, 0, LCR_BLOCK_MATERIAL_CONCRETE, 0), | 
					
						
							|  |  |  |   LCR_MAP_BLOCK( LCR_BLOCK_FULL, 2, 0, 0, LCR_BLOCK_MATERIAL_CONCRETE, 0), | 
					
						
							|  |  |  |   LCR_MAP_BLOCK( LCR_BLOCK_FULL, 0, 1, 0, LCR_BLOCK_MATERIAL_CONCRETE, 0), | 
					
						
							|  |  |  |   LCR_MAP_BLOCK( LCR_BLOCK_FULL, 3, 0, 0, LCR_BLOCK_MATERIAL_CONCRETE, 0), | 
					
						
							| 
									
										
										
										
											2023-07-23 16:51:09 +02:00
										 |  |  |   LCR_MAP_TERMINATOR | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const uint8_t *LCR_maps[LCR_MAP_COUNT] = | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   LCR_map0 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-02 00:05:03 +02:00
										 |  |  | void LCR_makeMapBlock(uint8_t type, uint8_t x, uint8_t y, uint8_t z, | 
					
						
							|  |  |  |   uint8_t material, uint8_t transform, uint8_t block[LCR_BLOCK_SIZE]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   block[0] = type; | 
					
						
							|  |  |  |   block[1] = x | (y << 6); | 
					
						
							|  |  |  |   block[2] = (y >> 2) | (z << 4); | 
					
						
							|  |  |  |   block[3] = (z >> 4) | (material << 2) | transform; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  | void LCR_mapBlockGetCoords(const uint8_t block[LCR_BLOCK_SIZE], | 
					
						
							|  |  |  |   uint8_t *x, uint8_t *y, uint8_t *z) | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   *x = block[1] & 0x3f; | 
					
						
							|  |  |  |   *y = (block[1] >> 6) | ((block[2] & 0x0f)  << 2); | 
					
						
							|  |  |  |   *z = (block[2] >> 4) | ((block[3] & 0x03) << 4); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-26 14:56:39 +02:00
										 |  |  | uint8_t LCR_mapBlockOppositeTransform(uint8_t transform) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!(transform & LCR_BLOCK_TRANSFORM_FLIP_H)) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if ((transform & 0x60) == LCR_BLOCK_TRANSFORM_ROT_90) | 
					
						
							|  |  |  |       return ((transform & (~0x60)) | LCR_BLOCK_TRANSFORM_ROT_270); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((transform & 0x60) == LCR_BLOCK_TRANSFORM_ROT_270) | 
					
						
							|  |  |  |       return ((transform & (~0x60)) | LCR_BLOCK_TRANSFORM_ROT_90); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return transform; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 23:16:13 +02:00
										 |  |  | uint8_t LCR_mapBlockGetTransform(const uint8_t block[LCR_BLOCK_SIZE]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return block[3] & 0xf0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 21:41:21 +02:00
										 |  |  | uint8_t LCR_mapBlockGetMaterial(const uint8_t block[LCR_BLOCK_SIZE]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (block[3] >> 2) & 0x03; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  | uint32_t LCR_mapBlockGetCoordNumber(const uint8_t block[LCR_BLOCK_SIZE]) | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   return block[1] | (((uint32_t) block[2]) << 8) | | 
					
						
							|  |  |  |     ((((uint32_t) block[3]) & 0x3) << 16); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-23 20:21:08 +02:00
										 |  |  | uint32_t LCR_mapBlockCoordsToCoordNumber(uint8_t x, uint8_t y, uint8_t z) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   uint8_t b[LCR_BLOCK_SIZE]; | 
					
						
							|  |  |  |   LCR_makeMapBlock(0,x,y,z,0,0,b); | 
					
						
							|  |  |  |   return LCR_mapBlockGetCoordNumber(b); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-03 00:24:28 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |   Gets dimensions of a non-curved ramp. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | void LCR_rampGetDimensions(uint8_t rampType, uint8_t *height4ths, | 
					
						
							| 
									
										
										
										
											2024-10-01 22:08:03 +02:00
										 |  |  |   uint8_t *length6ths) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   *height4ths = | 
					
						
							|  |  |  |     (rampType == LCR_BLOCK_RAMP_14) + | 
					
						
							|  |  |  |     (rampType == LCR_BLOCK_RAMP || rampType == LCR_BLOCK_RAMP_STEEP) * 4 + | 
					
						
							|  |  |  |     (rampType == LCR_BLOCK_RAMP_12 || rampType == LCR_BLOCK_RAMP_34) * 2 + | 
					
						
							|  |  |  |     (rampType == LCR_BLOCK_RAMP_34); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *length6ths = rampType != LCR_BLOCK_RAMP_STEEP ? 6 : 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-08 16:17:51 +02:00
										 |  |  | uint8_t *LCR_getMapBlockAtCoordNumber(uint32_t coord) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   // binary search the block:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uint16_t a = 0, b = LCR_currentMap.blockCount - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (b >= a) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     uint16_t mid = (a + b) / 2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  |     uint8_t *block = LCR_currentMap.blocks + mid * LCR_BLOCK_SIZE; | 
					
						
							| 
									
										
										
										
											2023-08-08 16:17:51 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     uint32_t coord2 = | 
					
						
							|  |  |  |       LCR_mapBlockGetCoordNumber(block); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (coord2 == coord) | 
					
						
							|  |  |  |       return block; | 
					
						
							|  |  |  |     else if (coord2 > coord) | 
					
						
							|  |  |  |       b = mid - 1; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       a = mid + 1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |   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 1 on success, else 0. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  | uint8_t _LCR_mapAddBlock(const uint8_t block[LCR_BLOCK_SIZE]) | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-09-29 20:52:52 +02:00
										 |  |  |   LCR_LOG2("adding map block"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-23 23:31:30 +02:00
										 |  |  |   if (LCR_currentMap.blockCount >= LCR_SETTING_MAP_MAX_BLOCKS) | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uint32_t coord = LCR_mapBlockGetCoordNumber(block); | 
					
						
							|  |  |  |   uint16_t insertAt = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (insertAt < LCR_currentMap.blockCount && | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  |     coord > LCR_mapBlockGetCoordNumber(LCR_currentMap.blocks + | 
					
						
							|  |  |  |     insertAt * LCR_BLOCK_SIZE)) | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |     insertAt++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (block[0] == LCR_BLOCK_NONE) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (insertAt < LCR_currentMap.blockCount && | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  |       coord == LCR_mapBlockGetCoordNumber(LCR_currentMap.blocks + | 
					
						
							|  |  |  |       insertAt * LCR_BLOCK_SIZE)) | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |       // shift all left (remove the block):
 | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  |       for (uint16_t i = insertAt * LCR_BLOCK_SIZE; | 
					
						
							|  |  |  |         i < LCR_currentMap.blockCount * LCR_BLOCK_SIZE - 1; ++i) | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |         LCR_currentMap.blocks[i] = LCR_currentMap.blocks[i + 1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       LCR_currentMap.blockCount--; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (insertAt == LCR_currentMap.blockCount || | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  |     coord != LCR_mapBlockGetCoordNumber(LCR_currentMap.blocks + | 
					
						
							|  |  |  |     insertAt * LCR_BLOCK_SIZE)) | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     // shift from here to the right, make room for the new block
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     LCR_currentMap.blockCount++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  |     for (int16_t i = ((int16_t) LCR_currentMap.blockCount) - 1; | 
					
						
							|  |  |  |       i > insertAt; i--) | 
					
						
							|  |  |  |       for (uint8_t j = 0; j < LCR_BLOCK_SIZE; ++j) | 
					
						
							|  |  |  |         LCR_currentMap.blocks[i * LCR_BLOCK_SIZE + j] = | 
					
						
							|  |  |  |           LCR_currentMap.blocks[(i - 1) * LCR_BLOCK_SIZE + j]; | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  |   insertAt *= LCR_BLOCK_SIZE; | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  |   for (uint8_t j = 0; j < LCR_BLOCK_SIZE; ++j) | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |     LCR_currentMap.blocks[insertAt + j] = block[j];  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |   Loads and preprocesses given map. Returns 1 on success, otherwise 0. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | uint8_t LCR_mapLoad(const uint8_t *map) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-09-29 20:52:52 +02:00
										 |  |  |   LCR_LOG0("loading map") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (int i = 0; i < 4; ++i) | 
					
						
							|  |  |  |     LCR_currentMap.startPos[i] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |   LCR_currentMap.blockCount = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (map[0] != LCR_MAP_MAGIC_NUMBER1 || map[1] != LCR_MAP_MAGIC_NUMBER2) | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   map += 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (*map != 10) // read map name
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // TODO
 | 
					
						
							|  |  |  |     map++; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   map++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (*map != 10) // read map description
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // TODO
 | 
					
						
							|  |  |  |     map++; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   map++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-08 16:17:51 +02:00
										 |  |  |   LCR_currentMap.environment = *map; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   map++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |   while (*map != LCR_MAP_TERMINATOR) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2024-08-02 00:05:03 +02:00
										 |  |  |     switch (*map) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       case LCR_BLOCK_CUBOID_FILL: | 
					
						
							| 
									
										
										
										
											2024-08-06 01:34:38 +02:00
										 |  |  |       case LCR_BLOCK_CUBOID_HOLLOW: | 
					
						
							| 
									
										
										
										
											2024-08-02 00:05:03 +02:00
										 |  |  |       { | 
					
						
							|  |  |  |         const uint8_t *prevBlock = map - LCR_BLOCK_SIZE; | 
					
						
							|  |  |  |         uint8_t x, y, z, w, h, d, mat, transform; | 
					
						
							|  |  |  |         uint8_t tmpBlock[LCR_BLOCK_SIZE]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (LCR_currentMap.blockCount == 0 || (prevBlock[0] & 0x80)) | 
					
						
							|  |  |  |           return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         mat = LCR_mapBlockGetMaterial(prevBlock); | 
					
						
							|  |  |  |         transform = LCR_mapBlockGetTransform(prevBlock); | 
					
						
							|  |  |  |         LCR_mapBlockGetCoords(prevBlock,&x,&y,&z); | 
					
						
							|  |  |  |         LCR_mapBlockGetCoords(map,&w,&h,&d); | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         for (uint8_t k = 0; k < d; ++k) | 
					
						
							|  |  |  |           for (uint8_t j = 0; j < h; ++j) | 
					
						
							|  |  |  |             for (uint8_t i = 0; i < w; ++i) | 
					
						
							| 
									
										
										
										
											2024-08-06 01:34:38 +02:00
										 |  |  |               if (*map == LCR_BLOCK_CUBOID_FILL || | 
					
						
							|  |  |  |                   k == 0 || k == d - 1 || | 
					
						
							|  |  |  |                   j == 0 || j == h - 1 || | 
					
						
							|  |  |  |                   i == 0 || i == w - 1) | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 LCR_makeMapBlock(prevBlock[0],x + i,y + j,z + k,mat,transform, | 
					
						
							|  |  |  |                   tmpBlock); | 
					
						
							| 
									
										
										
										
											2024-08-02 00:05:03 +02:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2024-08-06 01:34:38 +02:00
										 |  |  |                 if (!_LCR_mapAddBlock(tmpBlock)) | 
					
						
							|  |  |  |                   return 0; | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2024-08-02 00:05:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-29 20:52:52 +02:00
										 |  |  |       case LCR_BLOCK_START: | 
					
						
							|  |  |  |         LCR_mapBlockGetCoords(map, | 
					
						
							|  |  |  |           LCR_currentMap.startPos, | 
					
						
							|  |  |  |           LCR_currentMap.startPos + 1, | 
					
						
							|  |  |  |           LCR_currentMap.startPos + 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         LCR_currentMap.startPos[3] = LCR_mapBlockGetTransform(map) & 0x60; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-02 00:05:03 +02:00
										 |  |  |       default: | 
					
						
							|  |  |  |         if (!_LCR_mapAddBlock(map)) // normal block
 | 
					
						
							|  |  |  |           return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2024-09-29 20:52:52 +02:00
										 |  |  |     map += LCR_BLOCK_SIZE; | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2024-11-21 00:16:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   LCR_LOG2("clearing map block cache") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (int i = 0; i < LCR_MAP_BLOCK_CACHE_SIZE; ++i) | 
					
						
							|  |  |  |     _LCR_mapBlockCache[i] = 0xffffffff; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-29 20:52:52 +02:00
										 |  |  |   LCR_LOG2("map loaded") | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2024-09-23 20:21:08 +02:00
										 |  |  |   Same as LCR_mapGetBlockAt, but allows to specify start and end block of the | 
					
						
							|  |  |  |   of the search to make it faster. | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2024-09-23 20:21:08 +02:00
										 |  |  | int LCR_mapGetBlockAtFast(uint8_t x, uint8_t y, uint8_t z, | 
					
						
							|  |  |  |   int start, int end) | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-09-23 20:21:08 +02:00
										 |  |  |   // binary search (the blocks are sorted)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uint32_t n = LCR_mapBlockCoordsToCoordNumber(x,y,z); | 
					
						
							| 
									
										
										
										
											2024-11-21 00:16:00 +01:00
										 |  |  |   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; | 
					
						
							| 
									
										
										
										
											2024-09-23 20:21:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   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 | 
					
						
							| 
									
										
										
										
											2024-11-21 00:16:00 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |       _LCR_mapBlockCache[cacheIndex + 1] = m; | 
					
						
							| 
									
										
										
										
											2024-09-23 20:21:08 +02:00
										 |  |  |       return m; | 
					
						
							| 
									
										
										
										
											2024-11-21 00:16:00 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-09-23 20:21:08 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-21 00:16:00 +01:00
										 |  |  |   _LCR_mapBlockCache[cacheIndex + 1] = 0xffffffff; | 
					
						
							| 
									
										
										
										
											2024-09-23 20:21:08 +02:00
										 |  |  |   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); | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 19:57:29 +02:00
										 |  |  | uint8_t _LCR_encodeMapBlockCoords(uint8_t x, uint8_t y, uint8_t z) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (5 * 7) * z + 7 * y + x; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void _LCR_decodeMapBlockCoords(uint8_t byte, uint8_t *x, uint8_t *y, uint8_t *z) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   *x = (byte % 7); | 
					
						
							|  |  |  |   *y = ((byte / 7) % 5); | 
					
						
							|  |  |  |   *z = (byte / 35); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 21:41:21 +02:00
										 |  |  | #define LCR_BLOCK_SHAPE_COORD_MAX 12
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 19:57:29 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |   Decodes XYZ coordinates encoded in a byte returned by LCR_mapGetBlockShape. | 
					
						
							|  |  |  |   Each coordinate will be in range 0 to 12 (including both). This unusual range | 
					
						
							|  |  |  |   is intentional as it for example has an exact mid value. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | void LCR_decodeMapBlockCoords(uint8_t byte, uint8_t *x, uint8_t *y, uint8_t *z) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   _LCR_decodeMapBlockCoords(byte,x,y,z); | 
					
						
							|  |  |  |   *x *= 2; | 
					
						
							|  |  |  |   *y *= 3; | 
					
						
							|  |  |  |   *z *= 2; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-22 01:16:16 +02:00
										 |  |  | void _LCR_addBlockShapeByte(uint8_t *bytes, uint8_t *byteCount, | 
					
						
							|  |  |  |   int x, int y, int z) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (*byteCount >= LCR_MAP_BLOCK_SHAPE_MAX_BYTES) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 19:57:29 +02:00
										 |  |  |   bytes[*byteCount] = _LCR_encodeMapBlockCoords(x,y,z); | 
					
						
							| 
									
										
										
										
											2024-07-22 01:16:16 +02:00
										 |  |  |   *byteCount += 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-29 20:52:52 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |   Macro that transforms coordinates according to block transformation. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2024-09-26 14:56:39 +02:00
										 |  |  | #define LCR_TRANSFORM_COORDS(trans,cx,cy,cz,maxXZ,maxY)\
 | 
					
						
							|  |  |  |   if (trans & LCR_BLOCK_TRANSFORM_FLIP_H) cx = maxXZ - cx;\ | 
					
						
							|  |  |  |   if (trans & 0x20) {         /* for both 90 and 270 */ \ | 
					
						
							|  |  |  |     cx ^= cz; cz ^= cx; cx ^= cz; /* swap */ \ | 
					
						
							|  |  |  |     cx = maxXZ - cx; } \ | 
					
						
							|  |  |  |   if (trans & 0x40) {         /* for both 180 and 270 */ \ | 
					
						
							|  |  |  |     cx = maxXZ - cx; \ | 
					
						
							|  |  |  |     cz = maxXZ - cz; } \ | 
					
						
							|  |  |  |   if (trans & LCR_BLOCK_TRANSFORM_FLIP_V) \ | 
					
						
							|  |  |  |     cy = maxY - cy;  | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |   Gets a shape of given map block type as a 3D model composed of triangles. The | 
					
						
							| 
									
										
										
										
											2024-07-22 01:16:16 +02:00
										 |  |  |   model is returned as an array of byte triplets (triangles), with each byte | 
					
						
							|  |  |  |   representing one coordinate. These coordinates can be decoded with | 
					
						
							|  |  |  |   LCR_decodeMapBlockCoords function. | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | */ | 
					
						
							|  |  |  | void LCR_mapGetBlockShape(uint8_t blockType, uint8_t transform, | 
					
						
							| 
									
										
										
										
											2024-07-22 01:16:16 +02:00
										 |  |  |   uint8_t bytes[LCR_MAP_BLOCK_SHAPE_MAX_BYTES], uint8_t *byteCount) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /*
 | 
					
						
							|  |  |  |     The coordinate format is following: byte B specifies coordinates X (0 to 6) | 
					
						
							| 
									
										
										
										
											2024-07-23 19:57:29 +02:00
										 |  |  |     = B % 7, Y (vertical, 0 to 4) = (B / 7) % 5, Z (0 to 6) = B % 35. Helper | 
					
						
							|  |  |  |     side view grid: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     4 . . . . . . . ^ | 
					
						
							|  |  |  |     3 . . . . . . . | y | 
					
						
							|  |  |  |     2 . . . . . . . | 
					
						
							|  |  |  |     1 . . . . . . . | 
					
						
							|  |  |  |     0 . . . . . . . | 
					
						
							|  |  |  |       0 1 2 3 4 5 6 -> x/z | 
					
						
							| 
									
										
										
										
											2024-07-22 01:16:16 +02:00
										 |  |  |   */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *byteCount = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 19:57:29 +02:00
										 |  |  |   #define ADD(a,b,c) _LCR_addBlockShapeByte(bytes,byteCount,a,b,c);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-22 01:16:16 +02:00
										 |  |  |   switch (blockType) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2024-10-07 22:07:58 +02:00
										 |  |  |     case LCR_BLOCK_CHECKPOINT_0: | 
					
						
							|  |  |  |     case LCR_BLOCK_CHECKPOINT_1: | 
					
						
							|  |  |  |     case LCR_BLOCK_FINISH: | 
					
						
							|  |  |  |       ADD(3,0,3) ADD(0,2,6) ADD(6,2,6) | 
					
						
							|  |  |  |       ADD(3,0,3) ADD(0,2,0) ADD(0,2,6) | 
					
						
							|  |  |  |       ADD(3,0,3) ADD(6,2,0) ADD(0,2,0) | 
					
						
							|  |  |  |       ADD(3,0,3) ADD(6,2,6) ADD(6,2,0) | 
					
						
							|  |  |  |       ADD(3,4,3) ADD(0,2,6) ADD(0,2,0) | 
					
						
							|  |  |  |       ADD(3,4,3) ADD(0,2,0) ADD(6,2,0) | 
					
						
							|  |  |  |       ADD(3,4,3) ADD(6,2,0) ADD(6,2,6) | 
					
						
							|  |  |  |       ADD(3,4,3) ADD(6,2,6) ADD(0,2,6) | 
					
						
							|  |  |  |       break; | 
					
						
							| 
									
										
										
										
											2024-10-07 15:52:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-22 01:16:16 +02:00
										 |  |  |     case LCR_BLOCK_FULL: | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  |     case LCR_BLOCK_BOTTOM: | 
					
						
							|  |  |  |     case LCR_BLOCK_LEFT: | 
					
						
							|  |  |  |     case LCR_BLOCK_BOTTOM_LEFT: | 
					
						
							|  |  |  |     case LCR_BLOCK_BOTTOM_LEFT_FRONT: | 
					
						
							| 
									
										
										
										
											2024-08-01 21:41:21 +02:00
										 |  |  |     case LCR_BLOCK_FULL_ACCEL: | 
					
						
							| 
									
										
										
										
											2024-08-06 01:34:38 +02:00
										 |  |  |     case LCR_BLOCK_FULL_FAN: | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |       uint8_t xRight = 6, yTop = 4, | 
					
						
							|  |  |  |         zBack = 6 >> (blockType == LCR_BLOCK_BOTTOM_LEFT_FRONT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (blockType == LCR_BLOCK_BOTTOM || blockType == LCR_BLOCK_BOTTOM_LEFT || | 
					
						
							|  |  |  |         blockType == LCR_BLOCK_BOTTOM_LEFT_FRONT) | 
					
						
							|  |  |  |         yTop /= 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (blockType == LCR_BLOCK_LEFT || | 
					
						
							|  |  |  |         blockType == LCR_BLOCK_BOTTOM_LEFT || | 
					
						
							|  |  |  |         blockType == LCR_BLOCK_BOTTOM_LEFT_FRONT) | 
					
						
							|  |  |  |         xRight /= 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       ADD(0,0,0)      ADD(xRight,0,0)        ADD(xRight,yTop,0)     // front
 | 
					
						
							|  |  |  |       ADD(0,0,0)      ADD(xRight,yTop,0)     ADD(0,yTop,0) | 
					
						
							|  |  |  |       ADD(xRight,0,0) ADD(xRight,0,zBack)    ADD(xRight,yTop,zBack) // right
 | 
					
						
							|  |  |  |       ADD(xRight,0,0) ADD(xRight,yTop,zBack) ADD(xRight,yTop,0) | 
					
						
							|  |  |  |       ADD(0,0,0)      ADD(0,yTop,0)          ADD(0,yTop,zBack)      // left
 | 
					
						
							|  |  |  |       ADD(0,0,0)      ADD(0,yTop,zBack)      ADD(0,0,zBack) | 
					
						
							|  |  |  |       ADD(0,0,zBack)  ADD(0,yTop,zBack)      ADD(xRight,yTop,zBack) // back
 | 
					
						
							|  |  |  |       ADD(0,0,zBack)  ADD(xRight,yTop,zBack) ADD(xRight,0,zBack) | 
					
						
							|  |  |  |       ADD(0,yTop,0)   ADD(xRight,yTop,0)     ADD(xRight,yTop,zBack) // top
 | 
					
						
							|  |  |  |       ADD(0,yTop,0)   ADD(xRight,yTop,zBack) ADD(0,yTop,zBack) | 
					
						
							|  |  |  |       ADD(0,0,0)      ADD(xRight,0,zBack)    ADD(xRight,0,0)        // bottom
 | 
					
						
							|  |  |  |       ADD(0,0,0)      ADD(0,0,zBack)         ADD(xRight,0,zBack) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-04 00:59:15 +02:00
										 |  |  |     case LCR_BLOCK_RAMP_CURVED_PLAT: | 
					
						
							|  |  |  |       ADD(0,0,6) ADD(0,4,5) ADD(0,4,6) // left
 | 
					
						
							|  |  |  |       ADD(6,0,6) ADD(6,4,6) ADD(6,4,5) // right
 | 
					
						
							|  |  |  |       ADD(0,4,5) ADD(6,4,5) ADD(0,4,6) // top
 | 
					
						
							|  |  |  |       ADD(0,4,6) ADD(6,4,5) ADD(6,4,6) | 
					
						
							| 
									
										
										
										
											2024-10-06 21:53:11 +02:00
										 |  |  |       // fall through
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-03 00:24:28 +02:00
										 |  |  |     case LCR_BLOCK_RAMP_CURVED: | 
					
						
							| 
									
										
										
										
											2024-10-04 00:59:15 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |       uint8_t plusZ = blockType == LCR_BLOCK_RAMP_CURVED; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       ADD(0,0,0)         ADD(6,0,0)         ADD(0,1,3 + plusZ) // ramp
 | 
					
						
							|  |  |  |       ADD(0,1,3 + plusZ) ADD(6,0,0)         ADD(6,1,3 + plusZ) | 
					
						
							|  |  |  |       ADD(0,1,3 + plusZ) ADD(6,1,3 + plusZ) ADD(0,2,4 + plusZ) // ramp
 | 
					
						
							|  |  |  |       ADD(0,2,4 + plusZ) ADD(6,1,3 + plusZ) ADD(6,2,4 + plusZ) | 
					
						
							|  |  |  |       ADD(0,2,4 + plusZ) ADD(6,2,4 + plusZ) ADD(0,4,5 + plusZ) // ramp
 | 
					
						
							|  |  |  |       ADD(0,4,5 + plusZ) ADD(6,2,4 + plusZ) ADD(6,4,5 + plusZ) | 
					
						
							|  |  |  |       ADD(0,0,0)         ADD(0,1,3 + plusZ) ADD(0,0,6)         // left
 | 
					
						
							|  |  |  |       ADD(0,0,6)         ADD(0,1,3 + plusZ) ADD(0,2,4 + plusZ) | 
					
						
							|  |  |  |       ADD(0,0,6)         ADD(0,2,4 + plusZ) ADD(0,4,5 + plusZ) | 
					
						
							|  |  |  |       ADD(6,0,0)         ADD(6,0,6)         ADD(6,1,3 + plusZ) // right
 | 
					
						
							|  |  |  |       ADD(6,0,6)         ADD(6,2,4 + plusZ) ADD(6,1,3 + plusZ) | 
					
						
							|  |  |  |       ADD(6,0,6)         ADD(6,4,5 + plusZ) ADD(6,2,4 + plusZ) | 
					
						
							|  |  |  |       ADD(0,0,6)         ADD(0,4,6)         ADD(6,0,6)         // back
 | 
					
						
							|  |  |  |       ADD(6,0,6)         ADD(0,4,6)         ADD(6,4,6) | 
					
						
							|  |  |  |       ADD(0,0,0)         ADD(6,0,6)         ADD(6,0,0)         // bottom
 | 
					
						
							|  |  |  |       ADD(0,0,0)         ADD(0,0,6)         ADD(6,0,6) | 
					
						
							| 
									
										
										
										
											2024-10-03 00:24:28 +02:00
										 |  |  |       break; | 
					
						
							| 
									
										
										
										
											2024-10-04 00:59:15 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-10-03 00:24:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  |     case LCR_BLOCK_RAMP_CURVED_WALL: | 
					
						
							| 
									
										
										
										
											2024-07-23 19:57:29 +02:00
										 |  |  |       ADD(0,0,0) ADD(5,0,0) ADD(0,1,3) // ramp
 | 
					
						
							|  |  |  |       ADD(0,1,3) ADD(5,0,0) ADD(5,1,3) | 
					
						
							|  |  |  |       ADD(0,1,3) ADD(5,1,3) ADD(0,2,4) // ramp
 | 
					
						
							|  |  |  |       ADD(0,2,4) ADD(5,1,3) ADD(5,2,4) | 
					
						
							|  |  |  |       ADD(0,2,4) ADD(5,2,4) ADD(0,4,5) // ramp
 | 
					
						
							|  |  |  |       ADD(0,4,5) ADD(5,2,4) ADD(5,4,5) | 
					
						
							|  |  |  |       ADD(0,4,5) ADD(5,4,5) ADD(0,4,6) // top
 | 
					
						
							|  |  |  |       ADD(0,4,6) ADD(5,4,5) ADD(6,4,6) | 
					
						
							|  |  |  |       ADD(5,4,5) ADD(6,4,0) ADD(6,4,6) // top
 | 
					
						
							|  |  |  |       ADD(5,4,5) ADD(5,4,0) ADD(6,4,0) | 
					
						
							|  |  |  |       ADD(5,4,0) ADD(5,4,5) ADD(5,2,4) // inner side
 | 
					
						
							|  |  |  |       ADD(5,4,0) ADD(5,2,4) ADD(5,1,3) | 
					
						
							|  |  |  |       ADD(5,4,0) ADD(5,1,3) ADD(5,0,0) | 
					
						
							|  |  |  |       ADD(5,4,0) ADD(5,0,0) ADD(6,4,0) // front
 | 
					
						
							|  |  |  |       ADD(6,4,0) ADD(5,0,0) ADD(6,0,0) | 
					
						
							|  |  |  |       ADD(6,4,0) ADD(6,0,0) ADD(6,4,6) // right
 | 
					
						
							|  |  |  |       ADD(6,4,6) ADD(6,0,0) ADD(6,0,6) | 
					
						
							|  |  |  |       ADD(0,0,6) ADD(0,4,5) ADD(0,4,6) // left
 | 
					
						
							|  |  |  |       ADD(0,0,6) ADD(0,2,4) ADD(0,4,5) | 
					
						
							|  |  |  |       ADD(0,0,6) ADD(0,1,3) ADD(0,2,4) | 
					
						
							|  |  |  |       ADD(0,0,6) ADD(0,0,0) ADD(0,1,3) | 
					
						
							|  |  |  |       ADD(0,0,6) ADD(0,4,6) ADD(6,0,6) // back
 | 
					
						
							|  |  |  |       ADD(6,0,6) ADD(0,4,6) ADD(6,4,6) | 
					
						
							|  |  |  |       ADD(0,0,0) ADD(6,0,6) ADD(6,0,0) // bottom
 | 
					
						
							|  |  |  |       ADD(0,0,0) ADD(0,0,6) ADD(6,0,6) | 
					
						
							| 
									
										
										
										
											2024-07-22 01:16:16 +02:00
										 |  |  |       break; | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-23 23:31:30 +02:00
										 |  |  |     case LCR_BLOCK_RAMP: | 
					
						
							|  |  |  |     case LCR_BLOCK_RAMP_12: | 
					
						
							|  |  |  |     case LCR_BLOCK_RAMP_14: | 
					
						
							|  |  |  |     case LCR_BLOCK_RAMP_34: | 
					
						
							| 
									
										
										
										
											2024-10-01 22:08:03 +02:00
										 |  |  |     case LCR_BLOCK_RAMP_STEEP: | 
					
						
							| 
									
										
										
										
											2024-09-23 23:31:30 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-10-01 22:08:03 +02:00
										 |  |  |       uint8_t front, top; | 
					
						
							|  |  |  |       LCR_rampGetDimensions(blockType,&top,&front); | 
					
						
							|  |  |  |       front = 6 - front; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       ADD(0,0,front) ADD(0,top,6)   ADD(0,0,6)     // side
 | 
					
						
							|  |  |  |       ADD(6,0,front) ADD(6,0,6)     ADD(6,top,6)   // side
 | 
					
						
							|  |  |  |       ADD(0,0,front) ADD(6,0,front) ADD(0,top,6)   // top
 | 
					
						
							|  |  |  |       ADD(6,0,front) ADD(6,top,6)   ADD(0,top,6)   // top
 | 
					
						
							|  |  |  |       ADD(0,0,6)     ADD(6,top,6)   ADD(6,0,6)     // back
 | 
					
						
							|  |  |  |       ADD(0,0,6)     ADD(0,top,6)   ADD(6,top,6)   // back
 | 
					
						
							|  |  |  |       ADD(0,0,front) ADD(0,0,6)     ADD(6,0,6)     // bottom
 | 
					
						
							|  |  |  |       ADD(0,0,front) ADD(6,0,6)     ADD(6,0,front) // bottom
 | 
					
						
							| 
									
										
										
										
											2024-09-23 23:31:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-01 22:38:49 +02:00
										 |  |  |     case LCR_BLOCK_CORNER: | 
					
						
							|  |  |  |     case LCR_BLOCK_CORNER_12: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       uint8_t right = blockType == LCR_BLOCK_CORNER ? 6 : 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       ADD(0,0,0)     ADD(right,0,6) ADD(right,4,6)   // front/right
 | 
					
						
							|  |  |  |       ADD(0,0,0)     ADD(right,4,6) ADD(0,4,0)       // front/right
 | 
					
						
							|  |  |  |       ADD(0,0,0)     ADD(0,4,6)     ADD(0,0,6)       // left
 | 
					
						
							|  |  |  |       ADD(0,0,0)     ADD(0,4,0)     ADD(0,4,6)       // left
 | 
					
						
							|  |  |  |       ADD(right,0,6) ADD(0,0,6)     ADD(0,4,6)       // back
 | 
					
						
							|  |  |  |       ADD(0,4,6)     ADD(right,4,6) ADD(right,0,6)   // back
 | 
					
						
							|  |  |  |       ADD(0,4,0)     ADD(right,4,6) ADD(0,4,6)       // top
 | 
					
						
							|  |  |  |       ADD(0,0,6)     ADD(right,0,6) ADD(0,0,0)       // bottom
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 20:28:57 +02:00
										 |  |  |     default: break; | 
					
						
							| 
									
										
										
										
											2024-07-22 01:16:16 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 19:57:29 +02:00
										 |  |  |   if (transform) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     for (int i = 0; i < *byteCount; ++i) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       uint8_t x, y, z, tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       _LCR_decodeMapBlockCoords(bytes[i],&x,&y,&z); | 
					
						
							| 
									
										
										
										
											2024-09-26 14:56:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-29 20:52:52 +02:00
										 |  |  |       LCR_TRANSFORM_COORDS(transform,x,y,z,6,4) | 
					
						
							| 
									
										
										
										
											2024-07-23 19:57:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       bytes[i] = _LCR_encodeMapBlockCoords(x,y,z); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (((transform & LCR_BLOCK_TRANSFORM_FLIP_H) == 0) != | 
					
						
							|  |  |  |       ((transform & LCR_BLOCK_TRANSFORM_FLIP_V) == 0)) // flip triangles
 | 
					
						
							|  |  |  |       for (int i = 0; i < *byteCount; i += 3) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         uint8_t tmp = bytes[i]; | 
					
						
							|  |  |  |         bytes[i] = bytes[i + 1]; | 
					
						
							|  |  |  |         bytes[i + 1] = tmp; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   #undef ADD
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:12:23 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-21 21:17:49 +02:00
										 |  |  | #endif // guard
 |