diff --git a/TODO.txt b/TODO.txt index 87daf73..dcb3c8f 100644 --- a/TODO.txt +++ b/TODO.txt @@ -4,8 +4,6 @@ fuck issue trackers :D - try to prevent car getting stuck at extreme speed by may just hard stopping it if it ends up unresolved? -- car shadow idea: have shadow model, during rendering check each new triangle - agains car XY, record height, then set maimum height to shadow - Managed to get the car stuck in non-rotating state, then after a while get it back by crashing. MAY BE FIXED NOW, watch if it still happens - press forward map??? :-D @@ -51,6 +49,8 @@ fuck issue trackers :D =========== HANDLED ============== - should drifting make a sound? NO NEED +- car shadow idea: have shadow model, during rendering check each new triangle + agains car XY, record height, then set maimum height to shadow - seems like there might be a bug in physics env function, despite it being impossible in theory, car gets stuck after fast drive into a wall, with its shape staying OK, but wheel being inside a block somehow, maybe there are diff --git a/assets.h b/assets.h index b528c19..65c6a97 100644 --- a/assets.h +++ b/assets.h @@ -7083,6 +7083,23 @@ uint16_t LCR_getNextImagePixel(void) return r; } +#if LCR_SETTING_CAR_SHADOW + +#define LCR_SHADOW_VERTEX_COUNT 4 +#define LCR_SHADOW_TRIANGLE_COUNT 2 + +static const int32_t LCR_shadowVertices[] = +{ + -130,16,-175, 130,16,-175, -130,16, 155, 130,16, 155 +}; + +static const uint16_t LCR_shadowTriangles[] = +{ + 0,1,2,2,1,3 +}; + +#endif + #define LCR_CAR_VERTEX_COUNT 124 #define LCR_CAR_TRIANGLE_COUNT 228 diff --git a/data b/data index f9dd2f7..855d526 100644 --- a/data +++ b/data @@ -164,3 +164,5 @@ details #RLCtiny4;00LCtiny4;343017ba 0000137:0013:0131:0019:0191:0093:0041:0129:0011:0319 #RLCtiny4;00LCtiny4;343017ba 0000120:0011:00f9:0051:0029:0091:0059:0041:0049:0031:00b9:0031:02e9 #RLCtiny4;00LCtiny4;343017ba 0000118:0011:0099:0021:0039:00c1:00d9:0061:0049:0031:0383 +#RLCtiny2;00LCtiny2;833ee4b2 0000257:0464:00b0:0051:0100:0054:0070:0141:0050:0042:00c0:0094:0030:0194:00a0:0121 +#RLCtiny2;00LCtiny2;833ee4b2 0000257:0464:00b0:0051:0100:0054:0070:0141:0050:0042:00c0:0094:0030:0194:00a0:0121 diff --git a/renderer.h b/renderer.h index b3d2eda..2892a42 100644 --- a/renderer.h +++ b/renderer.h @@ -57,7 +57,8 @@ #define LCR_RENDERER_CHUNKS_TOTAL (LCR_RENDERER_CHUNK_RESOLUTION * \ LCR_RENDERER_CHUNK_RESOLUTION * LCR_RENDERER_CHUNK_RESOLUTION) -#define LCR_RENDERER_MODEL_COUNT 10 +#define LCR_RENDERER_MODEL_COUNT 11 + #define LCR_RENDERER_CAR_SCALE (LCR_RENDERER_UNIT / 4) #define LCR_RENDERER_FONT_SEGMENT_SIZE (2 + LCR_EFFECTIVE_RESOLUTION_X / 512) @@ -76,12 +77,14 @@ struct S3L_Model3D mapModel; ///< Whole map model. S3L_Model3D *carModel; ///< Shortcut ptr to the car model in the scene. S3L_Model3D *ghostModel; ///< Shortcut ptr to the ghost model in the scene. + S3L_Model3D *shadowModel; /** The scene model array. 0, 1, 2, 3, 4, 5, 6, 7: nearest map chunk models 8: car model 9: ghost model + 10: shadow model */ S3L_Model3D models[LCR_RENDERER_MODEL_COUNT]; @@ -356,12 +359,7 @@ void _LCR_pixelFunc3D(S3L_PixelInfo *pixel) LCR_renderer.texSubsampleCount = 0; #endif - if (pixel->modelIndex == 9) - { - // car ghost model - LCR_renderer.flatAndTransparent = LCR_SETTING_GHOST_COLOR; - } - else if (pixel->modelIndex == 8) + if (pixel->modelIndex == 8) { // car model @@ -398,6 +396,16 @@ void _LCR_pixelFunc3D(S3L_PixelInfo *pixel) } #endif } + else if (pixel->modelIndex == 9) + { + // car ghost model + LCR_renderer.flatAndTransparent = LCR_SETTING_GHOST_COLOR; + } + else if (pixel->modelIndex == 10) + { + // shadow model + LCR_renderer.flatAndTransparent = 0x0001; + } else { // map model @@ -408,12 +416,44 @@ void _LCR_pixelFunc3D(S3L_PixelInfo *pixel) for (int i = 0; i < 3; ++i) v[i] = LCR_renderer.mapVerts + 3 * t[i]; + + + + const uint8_t *triData = LCR_renderer.mapTriangleData + LCR_renderer.chunkStarts[LCR_renderer.loadedChunks[pixel->modelIndex]]; uint8_t type = triData[pixel->triangleIndex] >> 4; uint8_t mat = triData[pixel->triangleIndex] & 0x0f; +#if LCR_SETTING_CAR_SHADOW + if (type == 0 && (S3L_abs((2 * v[0][0] + v[1][0] + v[2][0]) / 4 - + LCR_renderer.carModel->transform.translation.x) + + S3L_abs((2 * v[0][2] + v[1][2] + v[2][2]) / 4 - + LCR_renderer.carModel->transform.translation.z)) < LCR_RENDERER_UNIT) + { + S3L_Unit groundH = (2 * v[0][1] + v[1][1] + v[2][1]) / 4; + + if (groundH < LCR_renderer.carModel->transform.translation.y && + groundH > LCR_renderer.shadowModel->transform.translation.y) + { + LCR_renderer.shadowModel->transform.translation.y = S3L_min(groundH, + LCR_renderer.carModel->transform.translation.y + - LCR_RENDERER_UNIT / 8); + + LCR_renderer.shadowModel->transform.scale.x = S3L_max(0, + LCR_RENDERER_UNIT - (LCR_renderer.carModel->transform.translation.y + - groundH) / 4); + + LCR_renderer.shadowModel->transform.scale.y = + LCR_renderer.shadowModel->transform.scale.x; + + LCR_renderer.shadowModel->transform.scale.z = + LCR_renderer.shadowModel->transform.scale.x; + } + } +#endif + switch (mat) { #define CL (type ? 0x8210 : 0x0000) @@ -1203,9 +1243,21 @@ uint8_t LCR_rendererInit(void) LCR_LOG0("initializing renderer"); LCR_renderer.frame = 0; - LCR_renderer.carModel = LCR_renderer.models + 8; + LCR_renderer.carModel = LCR_renderer.models + 8; LCR_renderer.ghostModel = LCR_renderer.models + 9; + LCR_renderer.shadowModel = LCR_renderer.models + 10; + +#if LCR_SETTING_CAR_SHADOW + S3L_model3DInit( + LCR_shadowVertices, + LCR_SHADOW_VERTEX_COUNT, + LCR_shadowTriangles,LCR_SHADOW_TRIANGLE_COUNT, + LCR_renderer.shadowModel); +#else + S3L_model3DInit(0,0,0,0,LCR_renderer.shadowModel); + LCR_renderer.shadowModel->config.visible = 0; +#endif S3L_model3DInit( #if LCR_ANIMATE_CAR @@ -2049,6 +2101,21 @@ void LCR_rendererDraw3D(void) { LCR_LOG2("rendering frame (start)"); +#if LCR_SETTING_CAR_SHADOW + LCR_renderer.shadowModel->transform.translation = + LCR_renderer.carModel->transform.translation; + + LCR_renderer.shadowModel->transform.translation.y = + -1 * (LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / 4; + + S3L_vec4Set(&(LCR_renderer.shadowModel->transform.scale), + LCR_RENDERER_UNIT,LCR_RENDERER_UNIT,LCR_RENDERER_UNIT, + LCR_RENDERER_UNIT); + + LCR_renderer.shadowModel->transform.rotation.y = + LCR_renderer.carModel->transform.rotation.y; +#endif + // first make sure rotations are in correct range: LCR_renderer.scene.camera.transform.rotation.y = S3L_wrap( LCR_renderer.scene.camera.transform.rotation.y, S3L_F); diff --git a/settings.h b/settings.h index 9235122..0c94b00 100644 --- a/settings.h +++ b/settings.h @@ -273,6 +273,11 @@ #define LCR_SETTING_PARTICLE_COLOR_DIRT 0x8b84 #endif +#ifndef LCR_SETTING_CAR_SHADOW + /** Turns on/off a simple car shadow. */ + #define LCR_SETTING_CAR_SHADOW 1 +#endif + #ifndef LCR_SETTING_FOG /** Turns distance fog on/off. Turning this off may increase performance. */ #define LCR_SETTING_FOG 0