From 5d9592bcd678207493335eeb1f4d0caf3458ddbc Mon Sep 17 00:00:00 2001 From: Miloslav Ciz Date: Tue, 13 Aug 2024 00:53:04 +0200 Subject: [PATCH] Start LOD --- assets.h | 14 +++-- renderer.h | 171 ++++++++++++++++++++++++++++++++++++++++++++++------- settings.h | 7 +++ 3 files changed, 168 insertions(+), 24 deletions(-) diff --git a/assets.h b/assets.h index 29bd7d2..4ac9229 100644 --- a/assets.h +++ b/assets.h @@ -26,11 +26,11 @@ static const uint8_t map1[] = 10, 0, - LCR_MAP_BLOCK(LCR_BLOCK_FULL_ACCEL,32,32,32,LCR_BLOCK_MATERIAL_CONCRETE,0), - LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,3,4,4,0,0), + LCR_MAP_BLOCK(LCR_BLOCK_FULL_ACCEL,32,2,32,LCR_BLOCK_MATERIAL_CONCRETE,0), + LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,1,40,1,0,0), - LCR_MAP_BLOCK(LCR_BLOCK_FULL_ACCEL,40,34,33,LCR_BLOCK_MATERIAL_CONCRETE,0), - LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,4,3,2,0,0), + LCR_MAP_BLOCK(LCR_BLOCK_FULL_ACCEL,32,32,32,LCR_BLOCK_MATERIAL_CONCRETE,0), + LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,4,4,4,0,0), LCR_MAP_BLOCK(LCR_BLOCK_FULL,50,20,20,LCR_BLOCK_MATERIAL_GRASS,0), LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,5,5,5,0,0), @@ -41,6 +41,12 @@ static const uint8_t map1[] = LCR_MAP_BLOCK(LCR_BLOCK_FULL,2,25,50,LCR_BLOCK_MATERIAL_GRASS,0), LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,3,3,3,0,0), + LCR_MAP_BLOCK(LCR_BLOCK_FULL,0,0,0,LCR_BLOCK_MATERIAL_GRASS,0), + LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,40,1,1,0,0), + + LCR_MAP_BLOCK(LCR_BLOCK_FULL,63,63,0,LCR_BLOCK_MATERIAL_GRASS,0), + LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,1,1,40,0,0), + /* LCR_MAP_BLOCK(LCR_BLOCK_FULL,0,15,0,LCR_BLOCK_MATERIAL_GRASS,0), LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,7,4,8,0,0), diff --git a/renderer.h b/renderer.h index 1e3e9f0..47dec36 100644 --- a/renderer.h +++ b/renderer.h @@ -17,9 +17,10 @@ #include "small3dlib.h" /// Renderer specific unit, length of one map square. -#define LCR_RENDERER_UNIT S3L_FRACTIONS_PER_UNIT +#define LCR_RENDERER_UNIT (S3L_FRACTIONS_PER_UNIT / 2) + // ^ just S3L_FRACTIONS_PER_UNIT leaves some tris bugging -#define LCR_RENDERER_CHUNK_RESOLUTION 4 +#define LCR_RENDERER_CHUNK_RESOLUTION 4 // do not change #define LCR_RENDERER_CHUNK_SIZE_HORIZONTAL \ ((LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / LCR_RENDERER_CHUNK_RESOLUTION) @@ -27,6 +28,8 @@ #define LCR_RENDERER_CHUNKS_TOTAL (LCR_RENDERER_CHUNK_RESOLUTION * \ LCR_RENDERER_CHUNK_RESOLUTION * LCR_RENDERER_CHUNK_RESOLUTION) +#define LCR_RENDERER_LOD_BLOCKS 64 + struct { S3L_Scene scene; @@ -42,7 +45,6 @@ struct S3L_Unit mapVerts[LCR_SETTING_MAX_MAP_VERTICES * 3]; S3L_Index mapTris[LCR_SETTING_MAX_MAP_TRIANGLES * 3]; - S3L_Index chunkStarts[LCR_RENDERER_CHUNKS_TOTAL]; /** @@ -52,6 +54,10 @@ struct */ uint8_t mapTriangleData[LCR_SETTING_MAX_MAP_TRIANGLES]; + +uint8_t gridLOD[LCR_RENDERER_LOD_BLOCKS]; + + // pixel function precomputed values: int previousTriID; int triUVs[6]; @@ -660,6 +666,27 @@ uint8_t _LCR_buildMapModel(void) return 1; } +void _LCR_computeLOD(void) +{ + LCR_log("computing LOD"); + + for (int i = 0; i < LCR_RENDERER_LOD_BLOCKS; ++i) + LCR_renderer.gridLOD[i] = 0; + + for (int i = 0; i < LCR_currentMap.blockCount; ++i) + { + uint8_t x, y, z; + + LCR_mapBlockGetCoords(LCR_currentMap.blocks + i * LCR_BLOCK_SIZE,&x,&y,&z); + + x /= 8; + y /= 8; + z /= 8; + + LCR_renderer.gridLOD[z * 8 + y] |= (0x01 << x); + } +} + uint8_t LCR_rendererInit(void) { LCR_log("initializing renderer"); @@ -671,6 +698,8 @@ uint8_t LCR_rendererInit(void) _LCR_makeMapChunks(); + _LCR_computeLOD(); + S3L_sceneInit( LCR_renderer.models + 1,8,&LCR_renderer.scene); @@ -722,6 +751,80 @@ chk(>,z,LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT / 2) } +/** + Fast and safe rect drawing function (handles out of screen coords). +*/ +void LCR_rendererDrawRect(int x, int y, unsigned int w, unsigned int h, + uint16_t color) +{ + if (x >= LCR_EFFECTIVE_RESOLUTION_X || y >= LCR_EFFECTIVE_RESOLUTION_Y) + return; + + if (x < 0) + { + if (-1 * x > ((int) w)) + return; + + w += x; + x = 0; + } + + if (x + w > LCR_EFFECTIVE_RESOLUTION_X) + w = LCR_EFFECTIVE_RESOLUTION_X - x; + + if (y < 0) + { + if (-1 * y > ((int) h)) + return; + + y += h; + y = 0; + } + + if (y + h > LCR_EFFECTIVE_RESOLUTION_X) + h = LCR_EFFECTIVE_RESOLUTION_Y - y; + + unsigned long index = y * LCR_EFFECTIVE_RESOLUTION_X + x; + + for (unsigned int i = 0; i < h; ++i) + { + for (unsigned int j = 0; j < w; ++j) + { + LCR_drawPixel(index,color); + index++; + } + + index += LCR_EFFECTIVE_RESOLUTION_X - w; + } +} + +void _LCR_drawLOD(int blockX, int blockY, int blockZ, unsigned int size, + uint16_t color) +{ + S3L_Vec4 p, r; + + p.x = (blockX - LCR_MAP_SIZE_BLOCKS / 2) * LCR_RENDERER_UNIT + + LCR_RENDERER_UNIT / 2; + + p.y = (blockY - LCR_MAP_SIZE_BLOCKS / 2) * (LCR_RENDERER_UNIT / 2) + + LCR_RENDERER_UNIT / 4; + + p.z = (blockZ - LCR_MAP_SIZE_BLOCKS / 2) * LCR_RENDERER_UNIT + + LCR_RENDERER_UNIT / 2; + + p.w = size; + + S3L_project3DPointToScreen(p,LCR_renderer.scene.camera,&r); + + if (r.w > 0 && r.z > LCR_SETTING_LOD_DISTANCE * LCR_RENDERER_UNIT && + r.w < LCR_EFFECTIVE_RESOLUTION_X) + { + LCR_rendererDrawRect(r.x - r.w / 2,r.y - r.w / 2, + r.w,r.w,color); + } +} + + /** Draws background sky, offsets are in multiples of screen dimensions (e.g. S3L_FRACTIONS_PER_UNIT / 2 for offsetH means half the screen width). @@ -887,29 +990,31 @@ void _LCR_loadMapChunks(void) { int8_t camChunk[3], chunkOffsets[3]; S3L_Vec4 cp = LCR_renderer.scene.camera.transform.translation; + S3L_Vec4 cf; + + S3L_rotationToDirections(LCR_renderer.scene.camera.transform.rotation, + LCR_RENDERER_CHUNK_SIZE_HORIZONTAL / 2,&cf,0,0); - camChunk[0] = (cp.x + (LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / 2) - / LCR_RENDERER_CHUNK_SIZE_HORIZONTAL; + cp.x += (LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / 2; + cp.y += (LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / 4; + cp.z += (LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / 2; - camChunk[1] = (cp.y + (LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / 4) - / (LCR_RENDERER_CHUNK_SIZE_HORIZONTAL / 2); + cf.x += cp.x % LCR_RENDERER_CHUNK_SIZE_HORIZONTAL; + cf.y += cp.y % (LCR_RENDERER_CHUNK_SIZE_HORIZONTAL / 2); + cf.z += cp.z % LCR_RENDERER_CHUNK_SIZE_HORIZONTAL; - camChunk[2] = ((cp.z + (LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / 2) - / LCR_RENDERER_CHUNK_SIZE_HORIZONTAL); + camChunk[0] = cp.x / LCR_RENDERER_CHUNK_SIZE_HORIZONTAL; + camChunk[1] = cp.y / (LCR_RENDERER_CHUNK_SIZE_HORIZONTAL / 2); + camChunk[2] = cp.z / LCR_RENDERER_CHUNK_SIZE_HORIZONTAL; - uint8_t camRot = S3L_wrap(LCR_renderer.scene.camera.transform.rotation.y - + S3L_FRACTIONS_PER_UNIT / 8,S3L_FRACTIONS_PER_UNIT) / - (S3L_FRACTIONS_PER_UNIT / 4); - - uint8_t camSide = (((camRot % 2) ? cp.x : cp.z) % - LCR_RENDERER_CHUNK_SIZE_HORIZONTAL) >= - LCR_RENDERER_CHUNK_SIZE_HORIZONTAL / 2; - - chunkOffsets[(camRot % 2) ? 0 : 2] = (camRot == 1 || camRot == 2) ? -1 : 1; - chunkOffsets[(camRot % 2) ? 2 : 0] = (camSide == (camRot < 2)) ? 1 : -1; + chunkOffsets[0] = + (cf.x >= (LCR_RENDERER_CHUNK_SIZE_HORIZONTAL / 2)) ? 1 : -1; chunkOffsets[1] = - LCR_renderer.scene.camera.transform.rotation.x <= 0 ? -1 : 1; + (cf.y >= (LCR_RENDERER_CHUNK_SIZE_HORIZONTAL / 4)) ? 1 : -1; + + chunkOffsets[2] = + (cf.z >= (LCR_RENDERER_CHUNK_SIZE_HORIZONTAL / 2)) ? 1 : -1; for (uint8_t i = 0; i < 8; ++i) _LCR_loadMapChunk(i, @@ -918,6 +1023,30 @@ void _LCR_loadMapChunks(void) camChunk[2] + ((i & 0x04) ? chunkOffsets[2] : 0)); } +void LCR_rendererDrawLOD(void) +{ + for (unsigned int i = 0; i < LCR_RENDERER_LOD_BLOCKS; ++i) + if (LCR_renderer.gridLOD[i]) + { + uint8_t byte = LCR_renderer.gridLOD[i]; + unsigned int bx, by, bz; + + bz = (i / 8) * 8 + 4; + by = (i % 8) * 8 + 4; + + for (unsigned int j = 0; j < 8; ++j) + { + if (byte & 0x01) + { + bx = j * 8 + 4; + _LCR_drawLOD(bx,by,bz,LCR_EFFECTIVE_RESOLUTION_X,0); + } // TODO: this ^ + + byte >>= 1; + } + } +} + void LCR_rendererDraw(void) { LCR_renderer.previousTriID = -1; @@ -929,6 +1058,8 @@ void LCR_rendererDraw(void) LCR_renderer.scene.camera.transform.rotation.y, -4 * LCR_renderer.scene.camera.transform.rotation.x); + LCR_rendererDrawLOD(); + S3L_drawScene(LCR_renderer.scene); } diff --git a/settings.h b/settings.h index 556c4aa..a38d4ef 100644 --- a/settings.h +++ b/settings.h @@ -70,4 +70,11 @@ #define LCR_SETTING_TEXTURE_SUBSAMPLE 4 #endif +#ifndef LCR_SETTING_LOD_DISTANCE + /** Distance in game squares from which LOD will be drawn. Value 64 or higher + turns off LOD completely. Note that this doesn't affect rendering distance + of 3D models. */ + #define LCR_SETTING_LOD_DISTANCE 25 +#endif + #endif // guard