Improve renderer, handle textures
This commit is contained in:
parent
2b4516f408
commit
2241b4d635
5 changed files with 191 additions and 59 deletions
191
renderer.h
191
renderer.h
|
@ -28,6 +28,13 @@ struct
|
|||
S3L_Unit mapVertices[LCR_SETTING_MAX_MAP_VERTICES * 3];
|
||||
S3L_Index mapTriangles[LCR_SETTING_MAX_MAP_TRIANGLES * 3];
|
||||
|
||||
/**
|
||||
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
|
||||
texture index.
|
||||
*/
|
||||
uint8_t mapTriangleData[LCR_SETTING_MAX_MAP_TRIANGLES];
|
||||
|
||||
// pixel function precomputed values:
|
||||
int previousTriangleID;
|
||||
int triangleUVs[6];
|
||||
|
@ -45,16 +52,15 @@ void LCR_pixelFunc3D(S3L_PixelInfo *pixel)
|
|||
for (int i = 0; i < 3; ++i)
|
||||
v[i] = LCR_renderer.mapVertices + 3 * t[i];
|
||||
|
||||
uint8_t type = // 0: floor, 1: wall, 2: wall 90 degrees
|
||||
(v[0][0] == v[1][0] && v[1][0] == v[2][0]) +
|
||||
2 * (v[0][2] == v[1][2] && v[1][2] == v[2][2]);
|
||||
uint8_t type = LCR_renderer.mapTriangleData[pixel->triangleID] >> 4;
|
||||
|
||||
if (type == 0)
|
||||
LCR_loadImage(LCR_renderer.mapTriangleData[pixel->triangleID] & 0x0f);
|
||||
|
||||
if (type == 0) // floor?
|
||||
{
|
||||
LCR_loadImage(3);
|
||||
|
||||
if (v[0][1] != v[1][1] || v[1][1] != v[2][1])
|
||||
if (v[0][1] != v[1][1] || v[1][1] != v[2][1]) // angled floor?
|
||||
LCR_imageChangeBrightness(1);
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
LCR_renderer.triangleUVs[i] = ((
|
||||
(v[i / 2][(i % 2) * 2]) *
|
||||
|
@ -62,8 +68,6 @@ void LCR_pixelFunc3D(S3L_PixelInfo *pixel)
|
|||
}
|
||||
else
|
||||
{
|
||||
LCR_loadImage(1);
|
||||
|
||||
if (type == 1)
|
||||
LCR_imageChangeBrightness(0);
|
||||
|
||||
|
@ -79,6 +83,27 @@ void LCR_pixelFunc3D(S3L_PixelInfo *pixel)
|
|||
}
|
||||
}
|
||||
|
||||
// shift the UVs to the origin (prevent high values of UV coords)
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
uint8_t minCoord = LCR_renderer.triangleUVs[i] <
|
||||
LCR_renderer.triangleUVs[2 + i] ? (0 + i) : (2 + i);
|
||||
|
||||
if (LCR_renderer.triangleUVs[4 + i] < LCR_renderer.triangleUVs[minCoord])
|
||||
minCoord = 4 + i;
|
||||
|
||||
S3L_Unit shiftBy = LCR_renderer.triangleUVs[minCoord] % LCR_IMAGE_SIZE;
|
||||
|
||||
if (shiftBy < 0)
|
||||
shiftBy += LCR_IMAGE_SIZE;
|
||||
|
||||
shiftBy -= LCR_renderer.triangleUVs[minCoord];
|
||||
|
||||
LCR_renderer.triangleUVs[i] += shiftBy;
|
||||
LCR_renderer.triangleUVs[2 + i] += shiftBy;
|
||||
LCR_renderer.triangleUVs[4 + i] += shiftBy;
|
||||
}
|
||||
|
||||
LCR_renderer.previousTriangleID = pixel->triangleIndex;
|
||||
}
|
||||
|
||||
|
@ -119,10 +144,8 @@ S3L_Index _LCR_addMapVertex(S3L_Unit x, S3L_Unit y, S3L_Unit z)
|
|||
// if it doesn't exist, add it
|
||||
if (LCR_renderer.mapModel->vertexCount < LCR_SETTING_MAX_MAP_VERTICES)
|
||||
{
|
||||
*vertices = x;
|
||||
vertices++;
|
||||
*vertices = y;
|
||||
vertices++;
|
||||
*vertices = x; vertices++;
|
||||
*vertices = y; vertices++;
|
||||
*vertices = z;
|
||||
LCR_renderer.mapModel->vertexCount++;
|
||||
return LCR_renderer.mapModel->vertexCount - 1;
|
||||
|
@ -132,30 +155,42 @@ S3L_Index _LCR_addMapVertex(S3L_Unit x, S3L_Unit y, S3L_Unit z)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void _LCR_addMapTriangle(S3L_Index a, S3L_Index b, S3L_Index c)
|
||||
void _LCR_addMapTriangle(S3L_Index a, S3L_Index b, S3L_Index c, uint8_t mat)
|
||||
{
|
||||
if (LCR_renderer.mapModel->triangleCount < LCR_SETTING_MAX_MAP_TRIANGLES)
|
||||
{
|
||||
S3L_Index *t = &(LCR_renderer.mapTriangles[LCR_renderer.mapModel->triangleCount * 3]);
|
||||
S3L_Index *t =
|
||||
&(LCR_renderer.mapTriangles[LCR_renderer.mapModel->triangleCount * 3]);
|
||||
|
||||
*t = a; t++;
|
||||
*t = b; t++;
|
||||
*t = c;
|
||||
|
||||
LCR_renderer.mapTriangleData[LCR_renderer.mapModel->triangleCount] =
|
||||
mat;
|
||||
|
||||
LCR_renderer.mapModel->triangleCount++;
|
||||
}
|
||||
}
|
||||
|
||||
void _LCR_rendererSwapTriangles(S3L_Index *t1, S3L_Index *t2)
|
||||
void _LCR_rendererSwapMapTriangles(unsigned int index1, unsigned int index2)
|
||||
{
|
||||
S3L_Index tmp;
|
||||
uint8_t tmpMat;
|
||||
S3L_Index tmpIndex,
|
||||
*t1 = LCR_renderer.mapTriangles + index1 * 3,
|
||||
*t2 = LCR_renderer.mapTriangles + index2 * 3;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
tmp = t1[i];
|
||||
tmpIndex = t1[i];
|
||||
t1[i] = t2[i];
|
||||
t2[i] = tmp;
|
||||
t2[i] = tmpIndex;
|
||||
}
|
||||
|
||||
tmpMat = LCR_renderer.mapTriangleData[index1];
|
||||
LCR_renderer.mapTriangleData[index1] =
|
||||
LCR_renderer.mapTriangleData[index2];
|
||||
LCR_renderer.mapTriangleData[index2] = tmpMat;
|
||||
}
|
||||
|
||||
int _LCR_quadCoversTriangle(const S3L_Unit quad[8], const S3L_Unit tri[6])
|
||||
|
@ -288,7 +323,6 @@ uint8_t _LCR_rendererCheckMapTriangleCover(const S3L_Index *t1,
|
|||
|
||||
t3 += 3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const S3L_Index *tmp = t1;
|
||||
|
@ -332,8 +366,9 @@ void _LCR_rendererCullHiddenMapTriangles(void)
|
|||
{
|
||||
if (j < LCR_renderer.mapModel->triangleCount - n)
|
||||
{
|
||||
_LCR_rendererSwapTriangles(t2,LCR_renderer.mapTriangles +
|
||||
(LCR_renderer.mapModel->triangleCount - 1 - n) * 3);
|
||||
|
||||
_LCR_rendererSwapMapTriangles(j,
|
||||
LCR_renderer.mapModel->triangleCount - 1 - n);
|
||||
|
||||
n++;
|
||||
}
|
||||
|
@ -344,8 +379,9 @@ void _LCR_rendererCullHiddenMapTriangles(void)
|
|||
|
||||
if (t1Covered)
|
||||
{
|
||||
_LCR_rendererSwapTriangles(t1,LCR_renderer.mapTriangles +
|
||||
(LCR_renderer.mapModel->triangleCount - 1 - n) * 3);
|
||||
_LCR_rendererSwapMapTriangles(i,
|
||||
LCR_renderer.mapModel->triangleCount - 1 - n);
|
||||
|
||||
n++;
|
||||
// we stay at this position because we've swapped the triangle here
|
||||
}
|
||||
|
@ -403,45 +439,106 @@ uint8_t _LCR_rendererBuildMapModel(void)
|
|||
|
||||
for (int j = 0; j < LCR_currentMap.blockCount; ++j)
|
||||
{
|
||||
uint8_t bx, by, bz;
|
||||
LCR_mapBlockGetCoords(LCR_currentMap.blocks + j * LCR_BLOCK_SIZE,
|
||||
&bx,&by,&bz);
|
||||
|
||||
LCR_mapGetBlockShape(LCR_currentMap.blocks[j * LCR_BLOCK_SIZE],
|
||||
LCR_mapBlockGetTransform(LCR_currentMap.blocks + j * LCR_BLOCK_SIZE),
|
||||
blockShapeBytes,&blockShapeByteCount);
|
||||
|
||||
uint8_t vx, vy, vz, vi = 0,
|
||||
isAtFloor = by == 0,
|
||||
isAtCeiling = by == LCR_MAP_SIZE_BLOCKS - 1;
|
||||
S3L_Index triangleIndices[3];
|
||||
|
||||
S3L_Unit originOffset = -1 * LCR_MAP_SIZE_BLOCKS / 2 * LCR_RENDERER_UNIT;
|
||||
S3L_Index triangleIndices[3];
|
||||
const uint8_t *block = LCR_currentMap.blocks + j * LCR_BLOCK_SIZE;
|
||||
uint8_t
|
||||
blockType = block[0],
|
||||
edgeBits, // bottom, top, left, right, front, bottom
|
||||
bx, by, bz, // block coords
|
||||
vx, vy, vz, // vertex coords
|
||||
vi = 0; // vertex index (0, 1 or 2)
|
||||
|
||||
LCR_mapBlockGetCoords(block,&bx,&by,&bz);
|
||||
|
||||
LCR_mapGetBlockShape(blockType,LCR_mapBlockGetTransform(block),
|
||||
blockShapeBytes,&blockShapeByteCount);
|
||||
|
||||
for (int i = 0; i < blockShapeByteCount; ++i)
|
||||
{
|
||||
if (vi == 0)
|
||||
edgeBits = (by == 0) |
|
||||
((by == LCR_MAP_SIZE_BLOCKS - 1) << 1) |
|
||||
((bx == 0) << 2) |
|
||||
((bx == LCR_MAP_SIZE_BLOCKS - 1) << 3) |
|
||||
((bz == 0) << 4) |
|
||||
((bz == LCR_MAP_SIZE_BLOCKS - 1) << 5);
|
||||
|
||||
LCR_decodeMapBlockCoords(blockShapeBytes[i],&vx,&vy,&vz);
|
||||
|
||||
isAtFloor &= vy == 0;
|
||||
isAtCeiling &= vy == 12;
|
||||
edgeBits &= (vy == 0) | ((vy == LCR_BLOCK_SHAPE_COORD_MAX) << 1) |
|
||||
((vx == 0) << 2) | ((vx == LCR_BLOCK_SHAPE_COORD_MAX) << 3) |
|
||||
((vz == 0) << 4) | ((vz == LCR_BLOCK_SHAPE_COORD_MAX) << 5);
|
||||
|
||||
triangleIndices[vi] = _LCR_addMapVertex(
|
||||
originOffset + (((S3L_Unit) bx) * LCR_RENDERER_UNIT) + (LCR_RENDERER_UNIT * ((S3L_Unit) vx)) / 12,
|
||||
(originOffset + (((S3L_Unit) by) * LCR_RENDERER_UNIT)) / 2 + (LCR_RENDERER_UNIT / 2 * ((S3L_Unit) vy)) / 12,
|
||||
originOffset + (((S3L_Unit) bz) * LCR_RENDERER_UNIT) + (LCR_RENDERER_UNIT * ((S3L_Unit) vz)) / 12);
|
||||
originOffset + (((S3L_Unit) bx) * LCR_RENDERER_UNIT) +
|
||||
(LCR_RENDERER_UNIT * ((S3L_Unit) vx)) / LCR_BLOCK_SHAPE_COORD_MAX,
|
||||
(originOffset + (((S3L_Unit) by) * LCR_RENDERER_UNIT)) / 2 +
|
||||
(LCR_RENDERER_UNIT / 2 * ((S3L_Unit) vy)) / LCR_BLOCK_SHAPE_COORD_MAX,
|
||||
originOffset + (((S3L_Unit) bz) * LCR_RENDERER_UNIT) +
|
||||
(LCR_RENDERER_UNIT * ((S3L_Unit) vz)) / LCR_BLOCK_SHAPE_COORD_MAX);
|
||||
|
||||
if (vi < 2)
|
||||
vi++;
|
||||
else
|
||||
{
|
||||
// don't add triangles completely at the floor or ceiling of the map
|
||||
if (!isAtFloor && !isAtCeiling)
|
||||
_LCR_addMapTriangle(
|
||||
triangleIndices[0],triangleIndices[1],triangleIndices[2]);
|
||||
if (!edgeBits)
|
||||
{
|
||||
#define VERT(n,c) LCR_renderer.mapVertices[3 * n + c]
|
||||
uint8_t blockMat = LCR_mapBlockGetMaterial(block);
|
||||
uint8_t triangleData =
|
||||
(((VERT(triangleIndices[0],0) == VERT(triangleIndices[1],0)) &&
|
||||
(VERT(triangleIndices[1],0) == VERT(triangleIndices[2],0))) << 4) |
|
||||
(((VERT(triangleIndices[0],2) == VERT(triangleIndices[1],2)) &&
|
||||
(VERT(triangleIndices[1],2) == VERT(triangleIndices[2],2))) << 5);
|
||||
#undef VERT
|
||||
|
||||
if (triangleData & 0xf0) // wall?
|
||||
{
|
||||
triangleData |=
|
||||
((blockMat == LCR_BLOCK_MATERIAL_CONCRETE) ||
|
||||
(blockMat == LCR_BLOCK_MATERIAL_ICE) ||
|
||||
(blockType == LCR_BLOCK_FULL_ACCEL) ||
|
||||
(blockType == LCR_BLOCK_FULL_STICKER)) ?
|
||||
LCR_IMAGE_WALL_CONCRETE : LCR_IMAGE_WALL_WOOD;
|
||||
}
|
||||
else
|
||||
{ // TODO: tidy this mess?
|
||||
if (blockType == LCR_BLOCK_FULL_ACCEL)
|
||||
triangleData |= LCR_IMAGE_GROUND_ACCEL;
|
||||
else if (blockType == LCR_BLOCK_FULL_STICKER)
|
||||
triangleData |= LCR_IMAGE_GROUND_STICKER;
|
||||
else
|
||||
switch (blockMat)
|
||||
{
|
||||
case LCR_BLOCK_MATERIAL_CONCRETE:
|
||||
triangleData |= LCR_IMAGE_GROUND_CONCRETE;
|
||||
break;
|
||||
|
||||
case LCR_BLOCK_MATERIAL_GRASS:
|
||||
triangleData |= LCR_IMAGE_GROUND_GRASS;
|
||||
break;
|
||||
|
||||
case LCR_BLOCK_MATERIAL_DIRT:
|
||||
triangleData |= LCR_IMAGE_GROUND_DIRT;
|
||||
break;
|
||||
|
||||
case LCR_BLOCK_MATERIAL_ICE:
|
||||
triangleData |= LCR_IMAGE_GROUND_ICE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_LCR_addMapTriangle(
|
||||
triangleIndices[0],triangleIndices[1],triangleIndices[2],
|
||||
triangleData);
|
||||
}
|
||||
|
||||
vi = 0;
|
||||
isAtFloor = by == 0;
|
||||
isAtCeiling = by == LCR_MAP_SIZE_BLOCKS - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue