2023-09-16 22:52:03 +02:00
|
|
|
/**
|
|
|
|
3D renderer: implements 3D rendering.
|
|
|
|
*/
|
|
|
|
|
2023-09-13 20:51:07 +02:00
|
|
|
#ifndef _LCR_RENDERER_H
|
|
|
|
#define _LCR_RENDERER_H
|
|
|
|
|
2023-09-16 20:35:01 +02:00
|
|
|
#define S3L_RESOLUTION_X LCR_SETTING_RESOLUTION_X
|
|
|
|
#define S3L_RESOLUTION_Y LCR_SETTING_RESOLUTION_Y
|
|
|
|
#define S3L_PIXEL_FUNCTION LCR_pixelFunc3D
|
|
|
|
|
|
|
|
#include "small3dlib.h"
|
|
|
|
|
2023-09-13 20:51:07 +02:00
|
|
|
struct LCR_Renderer
|
|
|
|
{
|
|
|
|
// TODO
|
2023-09-16 22:52:03 +02:00
|
|
|
|
|
|
|
|
2023-09-13 20:51:07 +02:00
|
|
|
};
|
|
|
|
|
2023-09-16 20:35:01 +02:00
|
|
|
S3L_Scene LCR_scene3D;
|
|
|
|
S3L_Model3D LCR_models3D[3]; // TODO
|
|
|
|
|
|
|
|
S3L_Unit LCR_vertices3D[LCR_SETTING_MAX_VERTICES * 3];
|
|
|
|
S3L_Index LCR_triangles3D[LCR_SETTING_MAX_TRIANGLES * 3];
|
|
|
|
|
|
|
|
void LCR_pixelFunc3D(S3L_PixelInfo *pixel)
|
|
|
|
{
|
|
|
|
LCR_drawPixelSafe(pixel->x,pixel->y,0xff00);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Builds an internal 3D model of the currently loaded map. Returns 1 on
|
|
|
|
success, otherwise 0 (e.g. not enough space). */
|
|
|
|
uint8_t LCR_buildMapModel(void)
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
|
|
|
|
LCR_vertices3D[0] = -400;
|
|
|
|
LCR_vertices3D[1] = -100;
|
|
|
|
LCR_vertices3D[2] = 1000;
|
|
|
|
|
|
|
|
LCR_vertices3D[3] = 400;
|
|
|
|
LCR_vertices3D[4] = -100;
|
|
|
|
LCR_vertices3D[5] = 1000;
|
|
|
|
|
|
|
|
LCR_vertices3D[6] = 0;
|
|
|
|
LCR_vertices3D[7] = 400;
|
|
|
|
LCR_vertices3D[8] = 1000;
|
|
|
|
|
|
|
|
LCR_triangles3D[0] = 0;
|
|
|
|
LCR_triangles3D[1] = 1;
|
|
|
|
LCR_triangles3D[2] = 2;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t LCR_rendererInit(void)
|
|
|
|
{
|
|
|
|
if (!LCR_buildMapModel())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
S3L_model3DInit(LCR_vertices3D,3,LCR_triangles3D,1,LCR_models3D);
|
|
|
|
S3L_sceneInit(LCR_models3D,1,&LCR_scene3D);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-09-17 13:21:19 +02:00
|
|
|
void LCR_rendererMoveCamera(LCR_SpaceUnit forwRightUpOffset[3],
|
|
|
|
LCR_SpaceUnit yawPitchOffset[2])
|
|
|
|
{
|
|
|
|
S3L_Vec4 f, r, u;
|
|
|
|
|
|
|
|
S3L_rotationToDirections(LCR_scene3D.camera.transform.rotation,
|
|
|
|
S3L_FRACTIONS_PER_UNIT,&f,&r,&u);
|
|
|
|
|
|
|
|
LCR_scene3D.camera.transform.translation.x +=
|
|
|
|
((f.x * forwRightUpOffset[0] + r.x * forwRightUpOffset[1] +
|
|
|
|
u.x * forwRightUpOffset[2]) * S3L_FRACTIONS_PER_UNIT) / LCR_SQUARE_SIDE_LEN;
|
|
|
|
|
|
|
|
LCR_scene3D.camera.transform.translation.y +=
|
|
|
|
((f.y * forwRightUpOffset[0] + r.y * forwRightUpOffset[1] +
|
|
|
|
u.y * forwRightUpOffset[2]) * S3L_FRACTIONS_PER_UNIT) / LCR_SQUARE_SIDE_LEN;
|
|
|
|
|
|
|
|
LCR_scene3D.camera.transform.translation.z +=
|
|
|
|
((f.z * forwRightUpOffset[0] + r.z * forwRightUpOffset[1] +
|
|
|
|
u.z * forwRightUpOffset[2]) * S3L_FRACTIONS_PER_UNIT) / LCR_SQUARE_SIDE_LEN;
|
|
|
|
|
|
|
|
LCR_scene3D.camera.transform.rotation.y +=
|
|
|
|
(yawPitchOffset[0] * S3L_FRACTIONS_PER_UNIT) / LCR_SQUARE_SIDE_LEN;
|
|
|
|
|
|
|
|
LCR_scene3D.camera.transform.rotation.x +=
|
|
|
|
(yawPitchOffset[1] * S3L_FRACTIONS_PER_UNIT) / LCR_SQUARE_SIDE_LEN;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2023-09-16 22:52:03 +02:00
|
|
|
void LCR_getCameraPos(LCR_SpaceUnit pos[3])
|
|
|
|
{
|
|
|
|
pos[0] = (LCR_scene3D.camera.transform.translation.x *
|
|
|
|
LCR_SQUARE_SIDE_LEN) / S3L_FRACTIONS_PER_UNIT;
|
|
|
|
pos[1] = (LCR_scene3D.camera.transform.translation.y *
|
|
|
|
LCR_SQUARE_SIDE_LEN) / S3L_FRACTIONS_PER_UNIT;
|
|
|
|
pos[2] = (LCR_scene3D.camera.transform.translation.z *
|
|
|
|
LCR_SQUARE_SIDE_LEN) / S3L_FRACTIONS_PER_UNIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LCR_setCameraPos(LCR_SpaceUnit pos[3])
|
|
|
|
{
|
|
|
|
LCR_scene3D.camera.transform.translation.x =
|
|
|
|
(pos[0] * S3L_FRACTIONS_PER_UNIT) / LCR_SQUARE_SIDE_LEN;
|
|
|
|
LCR_scene3D.camera.transform.translation.y =
|
|
|
|
(pos[1] * S3L_FRACTIONS_PER_UNIT) / LCR_SQUARE_SIDE_LEN;
|
|
|
|
LCR_scene3D.camera.transform.translation.z =
|
|
|
|
(pos[2] * S3L_FRACTIONS_PER_UNIT) / LCR_SQUARE_SIDE_LEN;
|
|
|
|
}
|
2023-09-17 13:21:19 +02:00
|
|
|
*/
|
2023-09-16 22:52:03 +02:00
|
|
|
|
2023-09-17 13:21:19 +02:00
|
|
|
void LCR_rendererDraw(void)
|
2023-09-16 20:35:01 +02:00
|
|
|
{
|
|
|
|
S3L_newFrame();
|
|
|
|
S3L_drawScene(LCR_scene3D);
|
|
|
|
}
|
|
|
|
|
2023-09-13 20:51:07 +02:00
|
|
|
void LCR_drawBackground(int verticalOffset)
|
|
|
|
{
|
|
|
|
uint16_t color = LCR_skyImages[LCR_skyImages[256] & 0x00ff] ; // TODO
|
|
|
|
int limit = verticalOffset - LCR_SETTING_SKY_SIZE * LCR_SKY_IMAGE_SIZE / 2;
|
|
|
|
|
|
|
|
if (limit >= LCR_EFFECTIVE_RESOLUTION_Y)
|
|
|
|
limit = LCR_EFFECTIVE_RESOLUTION_Y - 1;
|
|
|
|
|
|
|
|
for (int y = 0; y <= limit; ++y)
|
|
|
|
for (int x = 0; x < LCR_EFFECTIVE_RESOLUTION_X; ++x)
|
|
|
|
LCR_drawPixelUnsafe(x,y,color);
|
|
|
|
|
|
|
|
color = LCR_skyImages[LCR_skyImages[255 + (128 * 128) / 2] >> 8]; // TODO
|
|
|
|
limit = verticalOffset + LCR_SETTING_SKY_SIZE * LCR_SKY_IMAGE_SIZE / 2 -
|
|
|
|
LCR_SETTING_SKY_SIZE;
|
|
|
|
|
|
|
|
if (limit < 0)
|
|
|
|
limit = 0;
|
|
|
|
|
|
|
|
for (int y = LCR_EFFECTIVE_RESOLUTION_Y - 1; y >= limit; --y)
|
|
|
|
for (int x = 0; x < LCR_EFFECTIVE_RESOLUTION_X; ++x)
|
|
|
|
LCR_drawPixelUnsafe(x,y,color);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LCR_drawSkyStrip(int verticalOffset, uint8_t horizontalOffset)
|
|
|
|
{
|
|
|
|
#if LCR_SETTING_SKY_SIZE != 0
|
|
|
|
verticalOffset -= (LCR_SETTING_SKY_SIZE * LCR_SKY_IMAGE_SIZE) / 2;
|
|
|
|
|
|
|
|
int finalY = verticalOffset + LCR_SETTING_SKY_SIZE * LCR_SKY_IMAGE_SIZE;
|
|
|
|
|
|
|
|
finalY = (finalY / LCR_SETTING_SKY_SIZE) * LCR_SETTING_SKY_SIZE;
|
|
|
|
|
|
|
|
if (finalY >= LCR_EFFECTIVE_RESOLUTION_Y)
|
|
|
|
finalY = LCR_EFFECTIVE_RESOLUTION_Y - 1;
|
|
|
|
|
|
|
|
const uint16_t *skyLine = LCR_skyImages + 256;
|
|
|
|
|
|
|
|
if (verticalOffset < 0)
|
|
|
|
{
|
|
|
|
skyLine += (-1 * verticalOffset / LCR_SETTING_SKY_SIZE) * (LCR_SKY_IMAGE_SIZE / 2);
|
|
|
|
verticalOffset = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (verticalOffset < finalY)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < LCR_EFFECTIVE_RESOLUTION_X; ++i)
|
|
|
|
{
|
|
|
|
// TODO: check z-buffer
|
|
|
|
|
|
|
|
int offsetX = (i / LCR_SETTING_SKY_SIZE + horizontalOffset)
|
|
|
|
% LCR_SKY_IMAGE_SIZE;
|
|
|
|
|
|
|
|
uint16_t pixel = *(skyLine + offsetX / 2);
|
|
|
|
|
|
|
|
pixel = offsetX % 2 ? (pixel >> 8) : (pixel & 0x00ff);
|
|
|
|
|
|
|
|
LCR_drawPixelUnsafe(i,verticalOffset,LCR_skyImages[pixel]);
|
|
|
|
}
|
|
|
|
|
|
|
|
verticalOffset++;
|
|
|
|
|
|
|
|
if (verticalOffset % LCR_SETTING_SKY_SIZE == 0)
|
|
|
|
skyLine += LCR_SKY_IMAGE_SIZE / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // guard
|