Start map chunks

This commit is contained in:
Miloslav Ciz 2024-08-06 01:34:38 +02:00
parent 22a10b6451
commit 672c17eec1
4 changed files with 224 additions and 40 deletions

View file

@ -27,23 +27,24 @@ static const uint8_t map1[] =
0, 0,
LCR_MAP_BLOCK(LCR_BLOCK_FULL_ACCEL,32,32,32,LCR_BLOCK_MATERIAL_CONCRETE,0), LCR_MAP_BLOCK(LCR_BLOCK_FULL_ACCEL,32,32,32,LCR_BLOCK_MATERIAL_CONCRETE,0),
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_FILL,3,4,5,0,0), LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,3,4,4,0,0),
LCR_MAP_BLOCK(LCR_BLOCK_FULL_ACCEL,40,34,33,LCR_BLOCK_MATERIAL_CONCRETE,0), LCR_MAP_BLOCK(LCR_BLOCK_FULL_ACCEL,40,34,33,LCR_BLOCK_MATERIAL_CONCRETE,0),
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_FILL,6,7,2,0,0), LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,4,3,2,0,0),
/*
LCR_MAP_BLOCK(LCR_BLOCK_FULL,50,20,20,LCR_BLOCK_MATERIAL_GRASS,0), LCR_MAP_BLOCK(LCR_BLOCK_FULL,50,20,20,LCR_BLOCK_MATERIAL_GRASS,0),
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_FILL,5,5,5,0,0), LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,5,5,5,0,0),
LCR_MAP_BLOCK(LCR_BLOCK_FULL,10,10,10,LCR_BLOCK_MATERIAL_GRASS,0), LCR_MAP_BLOCK(LCR_BLOCK_FULL,10,10,10,LCR_BLOCK_MATERIAL_GRASS,0),
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_FILL,7,3,8,0,0), LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,3,3,3,0,0),
LCR_MAP_BLOCK(LCR_BLOCK_FULL,0,15,30,LCR_BLOCK_MATERIAL_GRASS,0), LCR_MAP_BLOCK(LCR_BLOCK_FULL,2,25,50,LCR_BLOCK_MATERIAL_GRASS,0),
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_FILL,7,4,8,0,0), LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,3,3,3,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),
LCR_MAP_BLOCK(LCR_BLOCK_FULL,32,32,32,LCR_BLOCK_MATERIAL_CONCRETE,0), LCR_MAP_BLOCK(LCR_BLOCK_FULL,32,32,32,LCR_BLOCK_MATERIAL_CONCRETE,0),
LCR_MAP_BLOCK(LCR_BLOCK_FULL,33,32,32,LCR_BLOCK_MATERIAL_GRASS,0), LCR_MAP_BLOCK(LCR_BLOCK_FULL,33,32,32,LCR_BLOCK_MATERIAL_GRASS,0),
LCR_MAP_BLOCK(LCR_BLOCK_RAMP_CURVED_WALL,34,32,32,LCR_BLOCK_MATERIAL_GRASS,0), LCR_MAP_BLOCK(LCR_BLOCK_RAMP_CURVED_WALL,34,32,32,LCR_BLOCK_MATERIAL_GRASS,0),
@ -84,7 +85,7 @@ const uint8_t *_LCR_currentImage;
#define LCR_IMAGE_GROUND_DIRT 4 #define LCR_IMAGE_GROUND_DIRT 4
#define LCR_IMAGE_GROUND_ICE 5 #define LCR_IMAGE_GROUND_ICE 5
#define LCR_IMAGE_GROUND_ACCEL 6 #define LCR_IMAGE_GROUND_ACCEL 6
#define LCR_IMAGE_GROUND_STICKER 7 #define LCR_IMAGE_GROUND_FAN 7
static const uint8_t LCR_images[] = static const uint8_t LCR_images[] =
{ {

9
map.h
View file

@ -83,7 +83,7 @@
#define LCR_BLOCK_RAMP_CURVED_WALL 0x09 #define LCR_BLOCK_RAMP_CURVED_WALL 0x09
#define LCR_BLOCK_FULL_ACCEL 0x20 #define LCR_BLOCK_FULL_ACCEL 0x20
#define LCR_BLOCK_FULL_STICKER 0x30 #define LCR_BLOCK_FULL_FAN 0x30
#define LCR_BLOCK_CHECKPOINT_0 0x40 ///< checkpoint, not taken #define LCR_BLOCK_CHECKPOINT_0 0x40 ///< checkpoint, not taken
#define LCR_BLOCK_CHECKPOINT_1 0x41 ///< checkpoint, taken #define LCR_BLOCK_CHECKPOINT_1 0x41 ///< checkpoint, taken
@ -285,6 +285,7 @@ uint8_t LCR_mapLoad(const uint8_t *map)
switch (*map) switch (*map)
{ {
case LCR_BLOCK_CUBOID_FILL: case LCR_BLOCK_CUBOID_FILL:
case LCR_BLOCK_CUBOID_HOLLOW:
{ {
const uint8_t *prevBlock = map - LCR_BLOCK_SIZE; const uint8_t *prevBlock = map - LCR_BLOCK_SIZE;
uint8_t x, y, z, w, h, d, mat, transform; uint8_t x, y, z, w, h, d, mat, transform;
@ -301,6 +302,10 @@ uint8_t LCR_mapLoad(const uint8_t *map)
for (uint8_t k = 0; k < d; ++k) for (uint8_t k = 0; k < d; ++k)
for (uint8_t j = 0; j < h; ++j) for (uint8_t j = 0; j < h; ++j)
for (uint8_t i = 0; i < w; ++i) for (uint8_t i = 0; i < w; ++i)
if (*map == LCR_BLOCK_CUBOID_FILL ||
k == 0 || k == d - 1 ||
j == 0 || j == h - 1 ||
i == 0 || i == w - 1)
{ {
LCR_makeMapBlock(prevBlock[0],x + i,y + j,z + k,mat,transform, LCR_makeMapBlock(prevBlock[0],x + i,y + j,z + k,mat,transform,
tmpBlock); tmpBlock);
@ -413,7 +418,7 @@ void LCR_mapGetBlockShape(uint8_t blockType, uint8_t transform,
case LCR_BLOCK_BOTTOM_LEFT: case LCR_BLOCK_BOTTOM_LEFT:
case LCR_BLOCK_BOTTOM_LEFT_FRONT: case LCR_BLOCK_BOTTOM_LEFT_FRONT:
case LCR_BLOCK_FULL_ACCEL: case LCR_BLOCK_FULL_ACCEL:
case LCR_BLOCK_FULL_STICKER: case LCR_BLOCK_FULL_FAN:
{ {
uint8_t xRight = 6, yTop = 4, uint8_t xRight = 6, yTop = 4,
zBack = 6 >> (blockType == LCR_BLOCK_BOTTOM_LEFT_FRONT); zBack = 6 >> (blockType == LCR_BLOCK_BOTTOM_LEFT_FRONT);

View file

@ -10,7 +10,7 @@
#define S3L_PIXEL_FUNCTION LCR_pixelFunc3D #define S3L_PIXEL_FUNCTION LCR_pixelFunc3D
#define S3L_PERSPECTIVE_CORRECTION 2 #define S3L_PERSPECTIVE_CORRECTION 2
#define S3L_NEAR_CROSS_STRATEGY 0 #define S3L_NEAR_CROSS_STRATEGY 1
#define S3L_Z_BUFFER 1 #define S3L_Z_BUFFER 1
@ -19,15 +19,32 @@
/// Renderer specific unit, length of one map square. /// Renderer specific unit, length of one map square.
#define LCR_RENDERER_UNIT S3L_FRACTIONS_PER_UNIT #define LCR_RENDERER_UNIT S3L_FRACTIONS_PER_UNIT
#define LCR_RENDERER_CHUNK_RESOLUTION 4
#define LCR_RENDERER_CHUNK_SIZE_HORIZONTAL \
((LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / LCR_RENDERER_CHUNK_RESOLUTION)
#define LCR_RENDERER_CHUNKS_TOTAL (LCR_RENDERER_CHUNK_RESOLUTION * \
LCR_RENDERER_CHUNK_RESOLUTION * LCR_RENDERER_CHUNK_RESOLUTION)
struct struct
{ {
S3L_Scene scene; S3L_Scene scene;
S3L_Model3D models[3]; // TODO S3L_Model3D models[9]; /**< 0: whole map model,
1, 2, 3, 4, 5, 6, 7, 8: nearest map chunks
models */
/* TODO: separate the whole model from the array? it's confusing if it's
in the array and then doesn't get rendered? */
uint8_t loadedChunks[8];
S3L_Model3D *mapModel; S3L_Model3D *mapModel;
S3L_Unit mapVerts[LCR_SETTING_MAX_MAP_VERTICES * 3]; S3L_Unit mapVerts[LCR_SETTING_MAX_MAP_VERTICES * 3];
S3L_Index mapTris[LCR_SETTING_MAX_MAP_TRIANGLES * 3]; S3L_Index mapTris[LCR_SETTING_MAX_MAP_TRIANGLES * 3];
S3L_Index chunkStarts[LCR_RENDERER_CHUNKS_TOTAL];
/** /**
Additional data for triangles. 4 higher bits hold direction (for lighting): Additional data for triangles. 4 higher bits hold direction (for lighting):
0 is floor, 1 is wall, 2 is wall (90 degrees). 4 lower bits hold the 0 is floor, 1 is wall, 2 is wall (90 degrees). 4 lower bits hold the
@ -38,22 +55,37 @@ struct
// pixel function precomputed values: // pixel function precomputed values:
int previousTriID; int previousTriID;
int triUVs[6]; int triUVs[6];
uint8_t texSubsampleCount;
} LCR_renderer; } LCR_renderer;
uint16_t ccc;
int cnt = 0;
void LCR_pixelFunc3D(S3L_PixelInfo *pixel) void LCR_pixelFunc3D(S3L_PixelInfo *pixel)
{ {
// once we get a new triangle, we precompute things for it: // once we get a new triangle, we precompute things for it:
if (pixel->triangleIndex != LCR_renderer.previousTriID) if (pixel->triangleIndex != LCR_renderer.previousTriID)
{ {
S3L_Index *t = LCR_renderer.mapTris + 3 * pixel->triangleIndex; const S3L_Index *t =
LCR_renderer.models[1 + pixel->modelIndex].triangles +
3 * pixel->triangleIndex;
S3L_Unit *v[3]; S3L_Unit *v[3];
#if LCR_SETTING_TEXTURE_SUBSAMPLE != 0
LCR_renderer.texSubsampleCount = 0;
#endif
for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
v[i] = LCR_renderer.mapVerts + 3 * t[i]; v[i] = LCR_renderer.mapVerts + 3 * t[i];
uint8_t type = LCR_renderer.mapTriangleData[pixel->triangleID] >> 4; const uint8_t *triData =
LCR_renderer.mapTriangleData +
LCR_renderer.chunkStarts[LCR_renderer.loadedChunks[
pixel->modelIndex]];
LCR_loadImage(LCR_renderer.mapTriangleData[pixel->triangleID] & 0x0f); uint8_t type = triData[pixel->triangleIndex] >> 4;
LCR_loadImage(triData[pixel->triangleIndex] & 0x0f);
if (type == 0) // floor? if (type == 0) // floor?
{ {
@ -106,13 +138,19 @@ void LCR_pixelFunc3D(S3L_PixelInfo *pixel)
LCR_renderer.previousTriID = pixel->triangleIndex; LCR_renderer.previousTriID = pixel->triangleIndex;
} }
uint16_t color;
#if LCR_SETTING_TEXTURE_SUBSAMPLE != 0
if (LCR_renderer.texSubsampleCount == 0)
{
#endif
int barycentric[3]; int barycentric[3];
barycentric[0] = pixel->barycentric[0] / 8; barycentric[0] = pixel->barycentric[0] / 8;
barycentric[1] = pixel->barycentric[1] / 8; barycentric[1] = pixel->barycentric[1] / 8;
barycentric[2] = pixel->barycentric[2] / 8; barycentric[2] = pixel->barycentric[2] / 8;
uint16_t color = LCR_sampleImage( color = LCR_sampleImage(
(barycentric[0] * LCR_renderer.triUVs[0] + (barycentric[0] * LCR_renderer.triUVs[0] +
barycentric[1] * LCR_renderer.triUVs[2] + barycentric[1] * LCR_renderer.triUVs[2] +
barycentric[2] * LCR_renderer.triUVs[4]) barycentric[2] * LCR_renderer.triUVs[4])
@ -122,6 +160,13 @@ void LCR_pixelFunc3D(S3L_PixelInfo *pixel)
barycentric[2] * LCR_renderer.triUVs[5]) barycentric[2] * LCR_renderer.triUVs[5])
/ (S3L_FRACTIONS_PER_UNIT / 8)); / (S3L_FRACTIONS_PER_UNIT / 8));
#if LCR_SETTING_TEXTURE_SUBSAMPLE != 0
LCR_renderer.texSubsampleCount = LCR_SETTING_TEXTURE_SUBSAMPLE;
}
LCR_renderer.texSubsampleCount--;
#endif
LCR_drawPixelXYUnsafe(pixel->x,pixel->y,color); LCR_drawPixelXYUnsafe(pixel->x,pixel->y,color);
} }
@ -445,6 +490,47 @@ void _LCR_cullHiddenMapTris(void)
} }
} }
void _LCR_makeMapChunks(void)
{
LCR_log("making map chunks");
S3L_Index start = 0;
for (int chunkNo = 0; chunkNo < LCR_RENDERER_CHUNKS_TOTAL; ++chunkNo)
{
S3L_Unit chunkCorner[3];
const S3L_Index *tri = LCR_renderer.mapTris + 3 * start;
LCR_renderer.chunkStarts[chunkNo] = start;
chunkCorner[0] = (chunkNo & 0x03) * LCR_RENDERER_CHUNK_SIZE_HORIZONTAL;
chunkCorner[1] = ((chunkNo >> 2) & 0x03) * (LCR_RENDERER_CHUNK_SIZE_HORIZONTAL / 2);
chunkCorner[2] = ((chunkNo >> 4) & 0x03) * LCR_RENDERER_CHUNK_SIZE_HORIZONTAL;
chunkCorner[0] -= LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT / 2;
chunkCorner[1] -= LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT / 4;
chunkCorner[2] -= LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT / 2;
for (int i = start; i < LCR_renderer.mapModel->triangleCount; ++i)
{
const S3L_Unit *v = LCR_renderer.mapVerts + 3 * tri[0];
if (v[0] >= chunkCorner[0] &&
v[0] < chunkCorner[0] + LCR_RENDERER_CHUNK_SIZE_HORIZONTAL &&
v[1] >= chunkCorner[1] &&
v[1] < chunkCorner[1] + (LCR_RENDERER_CHUNK_SIZE_HORIZONTAL / 2) &&
v[2] >= chunkCorner[2] &&
v[2] < chunkCorner[2] + LCR_RENDERER_CHUNK_SIZE_HORIZONTAL)
{
_LCR_swapMapTris(i,start);
start++;
}
tri += 3;
}
}
}
/** /**
Builds the internal 3D model of the currently loaded map. Returns 1 on Builds the internal 3D model of the currently loaded map. Returns 1 on
success, 0 otherwise (e.g. not enough space). success, 0 otherwise (e.g. not enough space).
@ -524,15 +610,15 @@ uint8_t _LCR_buildMapModel(void)
((blockMat == LCR_BLOCK_MATERIAL_CONCRETE) || ((blockMat == LCR_BLOCK_MATERIAL_CONCRETE) ||
(blockMat == LCR_BLOCK_MATERIAL_ICE) || (blockMat == LCR_BLOCK_MATERIAL_ICE) ||
(blockType == LCR_BLOCK_FULL_ACCEL) || (blockType == LCR_BLOCK_FULL_ACCEL) ||
(blockType == LCR_BLOCK_FULL_STICKER)) ? (blockType == LCR_BLOCK_FULL_FAN)) ?
LCR_IMAGE_WALL_CONCRETE : LCR_IMAGE_WALL_WOOD; LCR_IMAGE_WALL_CONCRETE : LCR_IMAGE_WALL_WOOD;
} }
else else
{ // TODO: tidy this mess? { // TODO: tidy this mess?
if (blockType == LCR_BLOCK_FULL_ACCEL) if (blockType == LCR_BLOCK_FULL_ACCEL)
triData |= LCR_IMAGE_GROUND_ACCEL; triData |= LCR_IMAGE_GROUND_ACCEL;
else if (blockType == LCR_BLOCK_FULL_STICKER) else if (blockType == LCR_BLOCK_FULL_FAN)
triData |= LCR_IMAGE_GROUND_STICKER; triData |= LCR_IMAGE_GROUND_FAN;
else else
switch (blockMat) switch (blockMat)
{ {
@ -583,7 +669,10 @@ uint8_t LCR_rendererInit(void)
if (!_LCR_buildMapModel()) if (!_LCR_buildMapModel())
return 0; return 0;
S3L_sceneInit(LCR_renderer.models,1,&LCR_renderer.scene); _LCR_makeMapChunks();
S3L_sceneInit(
LCR_renderer.models + 1,8,&LCR_renderer.scene);
return 1; return 1;
} }
@ -619,6 +708,18 @@ void LCR_rendererMoveCamera(LCR_SpaceUnit forwRightUpOffset[3],
if (LCR_renderer.scene.camera.transform.rotation.x < -1 * S3L_FRACTIONS_PER_UNIT / 4) if (LCR_renderer.scene.camera.transform.rotation.x < -1 * S3L_FRACTIONS_PER_UNIT / 4)
LCR_renderer.scene.camera.transform.rotation.x = -1 * S3L_FRACTIONS_PER_UNIT / 4; LCR_renderer.scene.camera.transform.rotation.x = -1 * S3L_FRACTIONS_PER_UNIT / 4;
#define chk(o,c,l) \
if (LCR_renderer.scene.camera.transform.translation.c o l) \
LCR_renderer.scene.camera.transform.translation.c = l;
chk(<,x,-1 * LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT / 2)
chk(>,x,LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT / 2)
chk(<,y,-1 * LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT / 4)
chk(>,y,LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT / 4)
chk(<,z,-1 * LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT / 2)
chk(>,z,LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT / 2)
} }
/** /**
@ -749,11 +850,81 @@ void LCR_rendererDrawSky(int sky, S3L_Unit offsetH, S3L_Unit offsetV)
} }
} }
void _LCR_loadMapChunk(uint8_t chunk, int8_t x, int8_t y, int8_t z)
{
LCR_renderer.models[chunk + 1] = LCR_renderer.models[0];
if (x < 0 || x >= LCR_RENDERER_CHUNK_RESOLUTION ||
y < 0 || y >= LCR_RENDERER_CHUNK_RESOLUTION ||
z < 0 || z >= LCR_RENDERER_CHUNK_RESOLUTION)
{
LCR_renderer.models[chunk + 1].triangleCount = 0;
LCR_renderer.loadedChunks[chunk] = 0;
}
else
{
int blockNum = x | (y << 2) | (z << 4);
LCR_renderer.loadedChunks[chunk] = blockNum;
int triCount =
(blockNum == LCR_RENDERER_CHUNKS_TOTAL - 1 ?
(LCR_renderer.mapModel->triangleCount - 1) :
LCR_renderer.chunkStarts[blockNum + 1])
- LCR_renderer.chunkStarts[blockNum];
if (triCount < 0)
triCount = 0;
LCR_renderer.models[chunk + 1].triangles =
LCR_renderer.mapTris + LCR_renderer.chunkStarts[blockNum] * 3;
LCR_renderer.models[chunk + 1].triangleCount = triCount;
}
}
void _LCR_loadMapChunks(void)
{
int8_t camChunk[3], chunkOffsets[3];
S3L_Vec4 cp = LCR_renderer.scene.camera.transform.translation;
camChunk[0] = (cp.x + (LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / 2)
/ LCR_RENDERER_CHUNK_SIZE_HORIZONTAL;
camChunk[1] = (cp.y + (LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / 4)
/ (LCR_RENDERER_CHUNK_SIZE_HORIZONTAL / 2);
camChunk[2] = ((cp.z + (LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / 2)
/ 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[1] =
LCR_renderer.scene.camera.transform.rotation.x <= 0 ? -1 : 1;
for (uint8_t i = 0; i < 8; ++i)
_LCR_loadMapChunk(i,
camChunk[0] + ((i & 0x01) ? chunkOffsets[0] : 0),
camChunk[1] + ((i & 0x02) ? chunkOffsets[1] : 0),
camChunk[2] + ((i & 0x04) ? chunkOffsets[2] : 0));
}
void LCR_rendererDraw(void) void LCR_rendererDraw(void)
{ {
LCR_renderer.previousTriID = -1; LCR_renderer.previousTriID = -1;
S3L_newFrame(); S3L_newFrame();
_LCR_loadMapChunks();
LCR_rendererDrawSky(2, LCR_rendererDrawSky(2,
LCR_renderer.scene.camera.transform.rotation.y, LCR_renderer.scene.camera.transform.rotation.y,
-4 * LCR_renderer.scene.camera.transform.rotation.x); -4 * LCR_renderer.scene.camera.transform.rotation.x);

View file

@ -63,4 +63,11 @@
#define LCR_SETTING_TRIANGLE_CULLING_PERIOD 64 #define LCR_SETTING_TRIANGLE_CULLING_PERIOD 64
#endif #endif
#ifndef LCR_SETTING_TEXTURE_SUBSAMPLE
/** Sets texture subsampling: 0 means no subsampling, higher value N means a
texture will be sampled once per N rasterized pixels. Higher value can
increase performance. */
#define LCR_SETTING_TEXTURE_SUBSAMPLE 4
#endif
#endif // guard #endif // guard