Start LOD

This commit is contained in:
Miloslav Ciz 2024-08-13 00:53:04 +02:00
parent 672c17eec1
commit 5d9592bcd6
3 changed files with 168 additions and 24 deletions

View file

@ -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),

View file

@ -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;
camChunk[0] = (cp.x + (LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / 2)
/ LCR_RENDERER_CHUNK_SIZE_HORIZONTAL;
S3L_rotationToDirections(LCR_renderer.scene.camera.transform.rotation,
LCR_RENDERER_CHUNK_SIZE_HORIZONTAL / 2,&cf,0,0);
camChunk[1] = (cp.y + (LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / 4)
/ (LCR_RENDERER_CHUNK_SIZE_HORIZONTAL / 2);
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[2] = ((cp.z + (LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / 2)
/ LCR_RENDERER_CHUNK_SIZE_HORIZONTAL);
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;
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);
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 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);
}

View file

@ -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