diff --git a/map.h b/map.h index 6657ae8..ba8645f 100644 --- a/map.h +++ b/map.h @@ -81,7 +81,7 @@ #define LCR_BLOCK_RAMP_12 0x07 ///< plain ramp, 1/2 size #define LCR_BLOCK_RAMP_14 0x08 ///< plain ramp, 1/4 size #define LCR_BLOCK_RAMP_CURVED_PLAT 0x09 ///< curved ramp with top platgform -#define LCR_BLOCK_RAMP_CURVED 0x0a ///< curv. ramp without top platf. +#define LCR_BLOCK_RAMP_CURVED 0x0a ///< curv. ramp without top platf. #define LCR_BLOCK_RAMP_CURVED_WALL 0x0b ///< curved ramp plus small wall #define LCR_BLOCK_RAMP_STEEP 0x0c ///< extremely steep ramp #define LCR_BLOCK_CORNER 0x0d ///< diagonal corner @@ -112,6 +112,17 @@ but makes a hollow one */ #define LCR_BLOCK_START 0x83 ///< specifies start block position +#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]; + struct { uint16_t blockCount; @@ -390,7 +401,12 @@ uint8_t LCR_mapLoad(const uint8_t *map) map += LCR_BLOCK_SIZE; } - + + LCR_LOG2("clearing map block cache") + + for (int i = 0; i < LCR_MAP_BLOCK_CACHE_SIZE; ++i) + _LCR_mapBlockCache[i] = 0xffffffff; + LCR_LOG2("map loaded") return 1; @@ -406,6 +422,14 @@ int LCR_mapGetBlockAtFast(uint8_t x, uint8_t y, uint8_t z, // 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) { @@ -419,9 +443,13 @@ int LCR_mapGetBlockAtFast(uint8_t x, uint8_t y, uint8_t z, else if (n2 > n) end = m - 1; else + { + _LCR_mapBlockCache[cacheIndex + 1] = m; return m; + } } + _LCR_mapBlockCache[cacheIndex + 1] = 0xffffffff; return -1; } diff --git a/racing.h b/racing.h index 2d653f9..3fd02b5 100644 --- a/racing.h +++ b/racing.h @@ -9,10 +9,15 @@ typedef int32_t LCR_GameUnit; ///< abstract game unit #define LCR_GAME_UNIT 1024 ///< length of map square in LCR_GameUnits -#define LCR_RACING_INPUT_FORW 0x01 -#define LCR_RACING_INPUT_RIGHT 0x02 -#define LCR_RACING_INPUT_BACK 0x04 -#define LCR_RACING_INPUT_LEFT 0x08 +#define LCR_RACING_INPUT_FORW 0x01 +#define LCR_RACING_INPUT_RIGHT 0x02 +#define LCR_RACING_INPUT_BACK 0x04 +#define LCR_RACING_INPUT_LEFT 0x08 + +#define LCR_RACING_EVENT_CP_TAKEN 0x0001 +#define LCR_RACING_EVENT_FINISHED 0x0002 +#define LCR_RACING_EVENT_CRASH_SMALL 0x0004 +#define LCR_RACING_EVENT_CRASH_BIG 0x0008 #define LCR_PHYSICS_UNIT 2048 ///< length of map square for physics engine @@ -571,11 +576,14 @@ int _LCR_racingCarShapeOK(void) /** Updates the racing physics world, call every LCR_RACING_TICK_MS milliseconds. + Returns a set of events (logically ORed) that occured during this step. */ -void LCR_racingStep(unsigned int input) +uint32_t LCR_racingStep(unsigned int input) { +printf("---------\n"); LCR_LOG2("racing step start"); + uint32_t result = 0; TPE_Vec3 carForw, carRight, carUp; uint8_t groundMat = LCR_BLOCK_MATERIAL_CONCRETE; // material under wheels int groundBlockIndex = -1; @@ -870,6 +878,8 @@ void LCR_racingStep(unsigned int input) LCR_racing.tick++; LCR_LOG2("racing step end"); + + return result; } void LCR_physicsDebugDraw(LCR_GameUnit camPos[3], LCR_GameUnit camRot[2], diff --git a/renderer.h b/renderer.h index 1b25c7f..a257385 100644 --- a/renderer.h +++ b/renderer.h @@ -776,8 +776,6 @@ uint8_t _LCR_buildMapModel(void) } } - // TODO: also cull the triangles in the loop by some N steps - _LCR_cullHiddenMapTris(); LCR_LOG1("map model built"); @@ -806,6 +804,47 @@ void _LCR_rendererComputeLOD(void) } } +void LCR_rendererMarkTakenCP(int x, int y, int z) +{ + for (int i = 0; i < LCR_renderer.mapModel.triangleCount; ++i) + if ((LCR_renderer.mapTriangleData[i] & 0x0f) == LCR_RENDERER_MAT_CP0) + { + S3L_Unit point[3]; + + point[0] = 0; + point[1] = 0; + point[2] = 0; + + for (int j = 0; j < 2; ++j) + for (int k = 0; k < 3; ++k) + point[k] += LCR_renderer.mapModel.vertices[ + 3 * LCR_renderer.mapModel.triangles[3 * i + j] + k] + + (LCR_MAP_SIZE_BLOCKS / 2) * + (k == 1 ? LCR_RENDERER_UNIT / 2 : LCR_RENDERER_UNIT); + + point[0] /= 2; + point[1] /= 2; + point[2] /= 2; + + if (point[0] / LCR_RENDERER_UNIT == x && + point[1] / (LCR_RENDERER_UNIT / 2) == y && + point[2] / LCR_RENDERER_UNIT == z) + LCR_renderer.mapTriangleData[i] = (LCR_renderer.mapTriangleData[i] + & 0xf0) | LCR_RENDERER_MAT_CP1; + } +} + +/** + Call to reset currently loaded map, i.e. mark all checkpoints as untaken etc. +*/ +void LCR_rendererRestart(void) +{ + for (int i = 0; i < LCR_renderer.mapModel.triangleCount; ++i) + if ((LCR_renderer.mapTriangleData[i] & 0x0f) == LCR_RENDERER_MAT_CP1) + LCR_renderer.mapTriangleData[i] = (LCR_renderer.mapTriangleData[i] & 0xf0) + | LCR_RENDERER_MAT_CP0; +} + uint8_t LCR_rendererInit(void) { LCR_LOG0("initializing renderer");