diff --git a/constants.h b/constants.h index d16ef5e..900b5a0 100644 --- a/constants.h +++ b/constants.h @@ -16,6 +16,6 @@ (LCR_SETTING_FREE_CAMERA_TURN_SPEED / LCR_SETTING_FPS) /** Maximum number of triangles of a block shape. */ -#define LCR_MAP_BLOCK_SHAPE_MAX_BYTES 64 +#define LCR_MAP_BLOCK_SHAPE_MAX_BYTES 80 #endif diff --git a/map.h b/map.h index 340d19c..1eaea34 100644 --- a/map.h +++ b/map.h @@ -274,13 +274,38 @@ const uint8_t *LCR_mapGetBlockAt(uint8_t x, uint8_t y, uint8_t z) return 0; } +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); +} + +/** + 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; +} + void _LCR_addBlockShapeByte(uint8_t *bytes, uint8_t *byteCount, int x, int y, int z) { if (*byteCount >= LCR_MAP_BLOCK_SHAPE_MAX_BYTES) return; - bytes[*byteCount] = (5 * 7) * z + 7 * y + x; + bytes[*byteCount] = _LCR_encodeMapBlockCoords(x,y,z); *byteCount += 1; } @@ -295,36 +320,104 @@ void LCR_mapGetBlockShape(uint8_t blockType, uint8_t transform, { /* The coordinate format is following: byte B specifies coordinates X (0 to 6) - = B % 7, Y (vertical, 0 to 4) = (B / 7) % 5, Z (0 to 6) = B % 35. + = 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 */ *byteCount = 0; + #define ADD(a,b,c) _LCR_addBlockShapeByte(bytes,byteCount,a,b,c); + switch (blockType) { case LCR_BLOCK_FULL: default: - _LCR_addBlockShapeByte(bytes,byteCount,0,0,1); - _LCR_addBlockShapeByte(bytes,byteCount,5,0,1); - _LCR_addBlockShapeByte(bytes,byteCount,0,1,3); + 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) break; } -} -/** - 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) -{ - *x = (byte % 7) * 2; - *y = ((byte / 7) % 5) * 3; - *z = (byte % 35) * 2; + if (transform) + { + for (int i = 0; i < *byteCount; ++i) + { + uint8_t x, y, z, tmp; + + _LCR_decodeMapBlockCoords(bytes[i],&x,&y,&z); + + if (transform & LCR_BLOCK_TRANSFORM_FLIP_H) + x = 6 - x; + + if (transform & 0x20) // for both 90 and 270 + { + tmp = z; + z = x; + x = 6 - tmp; + } + + if (transform & 0x40) // for both 180 and 270 + { + x = 6 - x; + z = 6 - z; + } + + if (transform & LCR_BLOCK_TRANSFORM_FLIP_V) + y = 4 - y; + + 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 } #endif // guard diff --git a/renderer.h b/renderer.h index 8d4f7dc..15b8218 100644 --- a/renderer.h +++ b/renderer.h @@ -13,6 +13,11 @@ #include "small3dlib.h" +/** + Renderer specific unit, length of one map square. +*/ +#define LCR_RENDERER_UNIT S3L_FRACTIONS_PER_UNIT + struct LCR_Renderer { // TODO @@ -29,7 +34,7 @@ S3L_Index LCR_mapTriangles[LCR_SETTING_MAX_MAP_TRIANGLES * 3]; void LCR_pixelFunc3D(S3L_PixelInfo *pixel) { - LCR_drawPixelXYSafe(pixel->x,pixel->y,0xff00); + LCR_drawPixelXYSafe(pixel->x,pixel->y, 0xff00 + (pixel->triangleID % 16) * 16 ); } S3L_Index _LCR_addMapVertex(S3L_Unit x, S3L_Unit y, S3L_Unit z) @@ -88,7 +93,10 @@ uint8_t _LCR_rendererBuildMapModel(void) S3L_model3DInit(LCR_mapVertices,0,LCR_mapTriangles,0,LCR_mapModel); - LCR_mapGetBlockShape(0,0,blockShapeBytes,&blockShapeByteCount); + LCR_mapGetBlockShape(0, + +LCR_BLOCK_TRANSFORM_ROT_270 +,blockShapeBytes,&blockShapeByteCount); uint8_t vx, vy, vz, vi = 0; uint8_t *bytes = blockShapeBytes; @@ -98,12 +106,10 @@ for (int i = 0; i < blockShapeByteCount; ++i) { LCR_decodeMapBlockCoords(blockShapeBytes[i],&vx,&vy,&vz); -printf("%d: %d %d %d\n",blockShapeBytes[i],vx,vy,vz); - - triangleIndices[vi] = _LCR_addMapVertex( - (LCR_SQUARE_SIDE_LEN * ((LCR_SpaceUnit) vx)) / 12, - (LCR_SQUARE_SIDE_LEN / 2 * ((LCR_SpaceUnit) vy)) / 12, - (LCR_SQUARE_SIDE_LEN * ((LCR_SpaceUnit) vz)) / 12); + triangleIndices[vi] = _LCR_addMapVertex( + (LCR_RENDERER_UNIT * ((S3L_Unit) vx)) / 12, + (LCR_RENDERER_UNIT / 2 * ((S3L_Unit) vy)) / 12, + (LCR_RENDERER_UNIT * ((S3L_Unit) vz)) / 12); if (vi < 2) vi++;