diff --git a/TODO.txt b/TODO.txt index 7bdfba9..fefc843 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,5 +1,6 @@ =========== GENERAL ============== +- car shadow? - sound engine: probably all SFX will be procedurally generated, ok? - allow slowing down in air like in TM? - music? @@ -7,10 +8,6 @@ that be played by the frontend just ALL the time (maybe with the option in menu to just turn music off) -- simple frontends can just ignore music - allow car to be flipped upside down on start? with start block transform -- make a simple rendering setting: - - will exclude images and only draw solid colors, let's say only 16, so that - memory usage is reduced, CPU rendering is relieved, executable is smaller - AND frontend doesn't have to use RGB565 (it can basically choose any mode). - camera behavior? what if car is riding upside down (on magnet) etc? - compile time option to choose how many maps to include (for platforms with lower memory) @@ -33,6 +30,10 @@ =========== HANDLED ============== - allow stopping car rotation in air like in Trackmania +- make a simple rendering setting: + - will exclude images and only draw solid colors, let's say only 16, so that + memory usage is reduced, CPU rendering is relieved, executable is smaller + AND frontend doesn't have to use RGB565 (it can basically choose any mode). - drifting: passing some upper threshold on steering force should reduce steering friction until reaching some some lower threshold again probably - maybe allow some more air control, like slowing down with brakes, like in TM diff --git a/assets.h b/assets.h index b52b14d..4d1c2ee 100644 --- a/assets.h +++ b/assets.h @@ -36,8 +36,8 @@ static const char *LCR_maps[] = "#;p0w0L #f5130" // bugs - "#=f0s0 #fd110" // small labyrinth - "#=c0p0 #fd110" + "#>f0s0 #fd110" // small labyrinth + "#oc0p0 #fd110" "#=f0s0 #f11d0" "#=c0p0 #f11d0" @@ -153,6 +153,7 @@ uint16_t LCR_getFontChar(char c) #define LCR_IMAGE_GROUND_FAN 7 #define LCR_IMAGE_CAR 20 +#if !LCR_SETTING_POTATO_GRAPHICS static const uint8_t LCR_images[] = { // 0: wall concrete @@ -2178,7 +2179,7 @@ static const uint8_t LCR_images[] = 0xe6,0xed,0xf1,0xfc,0xae,0xfa,0x89,0xf7,0x6b,0xc2,0xc2,0xe9,0xee,0xa7,0xa7,0xb5, 0xb5,0xb5,0xa7,0xa7,0xf9,0xee,0xf9,0xe9,0xf7,0x89,0xf6,0xae,0xd2,0xf1,0xff,0xe6, 0xff,0xfe,0xfd,0xed,0xfb,0xed,0xf1,0xf8,0xeb,0xf6,0xf5,0xf4,0xf3,0xf2,0xed,0xf0, - // 7: ground sticker + // 7: ground fan 0x2c,0x63,0x4d,0x6b,0x08,0x42,0x00,0x00,0x08,0x00,0x10,0x00,0x18,0x00,0x00,0x01, 0x08,0x01,0x10,0x01,0x18,0x01,0x00,0x02,0x08,0x02,0x10,0x02,0x18,0x02,0x00,0x03, 0x08,0x03,0x10,0x03,0x18,0x03,0x00,0x04,0x08,0x04,0x10,0x04,0x18,0x04,0x00,0x05, @@ -6225,9 +6226,11 @@ static const uint8_t LCR_images[] = 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0xa5,0xf7,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xfb, 0x00,0xec,0xb6,0xb6,0xce,0x00,0xa5,0xa5,0x00,0x00,0xec,0xa5,0x01,0xcc,0xc1,0xc1 }; +#endif // LCR_SETTING_POTATO_GRAPHICS void LCR_loadImage(unsigned int index) { +#if !LCR_SETTING_POTATO_GRAPHICS LCR_currentImage.image = LCR_images + index * LCR_IMAGE_STORE_SIZE; for (int i = 0; i < 256; ++i) @@ -6239,6 +6242,7 @@ void LCR_loadImage(unsigned int index) } LCR_currentImage.pixel = LCR_currentImage.image; +#endif } /** diff --git a/renderer.h b/renderer.h index 6095838..af0c76b 100644 --- a/renderer.h +++ b/renderer.h @@ -12,6 +12,12 @@ #define S3L_NEAR_CROSS_STRATEGY 1 #define S3L_Z_BUFFER 1 +#if LCR_SETTING_POTATO_GRAPHICS + #define S3L_PERSPECTIVE_CORRECTION 0 + #define S3L_NEAR_CROSS_STRATEGY 1 + #define S3L_FLAT 1 +#endif + #include "small3dlib.h" /// Renderer specific unit, length of one map square. @@ -190,6 +196,47 @@ void LCR_rendererDrawText(const char *text, int x, int y, uint16_t color, void _LCR_pixelFunc3D(S3L_PixelInfo *pixel) { +#if LCR_SETTING_POTATO_GRAPHICS + // simple shader for simplified graphics + + if (pixel->triangleID != LCR_renderer.previousTriID) + { + LCR_renderer.previousTriID = pixel->triangleID; + LCR_renderer.flatAndTransparent = 0x630c; // base gray + + if (pixel->modelIndex < 8) + { + uint8_t tData = + (LCR_renderer.mapTriangleData + + LCR_renderer.chunkStarts[LCR_renderer.loadedChunks[ + pixel->modelIndex]])[pixel->triangleIndex]; + + switch (tData & 0x0f) + { + case 3: LCR_renderer.flatAndTransparent &= ~(0x3008); break; // grass + case 4: LCR_renderer.flatAndTransparent &= ~(0x0408); break; // mud + case 5: LCR_renderer.flatAndTransparent |= 0x0010; break; // ice + case 6: LCR_renderer.flatAndTransparent |= 0x8080; break; // acc + case 7: LCR_renderer.flatAndTransparent &= ~(0x4208); break; // fan + default: break; + } + + tData &= 0x30; + + LCR_renderer.flatAndTransparent |= + (((uint16_t) (tData)) >> 4) | + (((uint16_t) (tData)) << 2) | + (((uint16_t) (tData)) << 7); + } + else + LCR_renderer.flatAndTransparent >>= 1; // car, darken + + LCR_renderer.flatAndTransparent += pixel->triangleIndex % 4; + } + + LCR_drawPixelXYUnsafe(pixel->x,pixel->y,LCR_renderer.flatAndTransparent); + +#else // LCR_SETTING_POTATO_GRAPHICS // once we get a new triangle, we precompute things for it: if (pixel->triangleID != LCR_renderer.previousTriID) { @@ -352,6 +399,7 @@ void _LCR_pixelFunc3D(S3L_PixelInfo *pixel) #endif LCR_drawPixelXYUnsafe(pixel->x,pixel->y,color); +#endif // LCR_SETTING_POTATO_GRAPHICS } S3L_Index _LCR_rendererAddMapVert(S3L_Unit x, S3L_Unit y, S3L_Unit z) @@ -1199,6 +1247,10 @@ void LCR_rendererDrawSky(int sky, S3L_Unit offsetH, S3L_Unit offsetV) { LCR_LOG2("drawing sky"); +#if LCR_SETTING_POTATO_GRAPHICS + LCR_rendererDrawRect(0,0,LCR_EFFECTIVE_RESOLUTION_X, + LCR_EFFECTIVE_RESOLUTION_Y,0x7bfd,0); +#else int anchorPoint[2], y; unsigned long pixelIndex; unsigned int topColor, bottomColor; @@ -1319,6 +1371,7 @@ void LCR_rendererDrawSky(int sky, S3L_Unit offsetH, S3L_Unit offsetV) y++; } +#endif } void _LCR_rendererLoadMapChunk(uint8_t chunk, int8_t x, int8_t y, int8_t z) @@ -1672,7 +1725,31 @@ void LCR_rendererDraw(void) LCR_rendererDrawLOD(); LCR_LOG2("gonna render 3D scene"); + +#if LCR_SETTING_POTATO_GRAPHICS + /* in potato mode we render twice so that car is always in front of the + level model (lack of precise depth causes artifacts otherwise) */ + + LCR_renderer.carModel->config.visible = 0; + LCR_renderer.ghostModel->config.visible = 0; + S3L_drawScene(LCR_renderer.scene); + + for (int i = 0; i < LCR_renderer.scene.modelCount; ++i) + LCR_renderer.scene.models[i].config.visible = 0; + + LCR_renderer.carModel->config.visible = 1; + LCR_renderer.ghostModel->config.visible = 1; + + S3L_newFrame(); + S3L_drawScene(LCR_renderer.scene); + + for (int i = 0; i < LCR_renderer.scene.modelCount; ++i) + LCR_renderer.scene.models[i].config.visible = 1; +#else + S3L_drawScene(LCR_renderer.scene); +#endif + LCR_LOG2("rendering 3D scene done"); LCR_renderer.frame++; diff --git a/settings.h b/settings.h index ed2b1e5..3a3b9c1 100644 --- a/settings.h +++ b/settings.h @@ -164,4 +164,10 @@ #define LCR_SETTING_DEBUG_PHYSICS_DRAW 0 #endif +#ifndef LCR_SETTING_POTATO_GRAPHICS + /** Setting this will turn on very simple graphics without textures and etc., + can be good for very weak devices. */ + #define LCR_SETTING_POTATO_GRAPHICS 0 +#endif + #endif // guard