From ed2a4bc4400c38ecd11baccac5db328b797b5d68 Mon Sep 17 00:00:00 2001 From: pk33 Date: Thu, 14 Nov 2024 15:06:07 +0100 Subject: begin 3D rendering, basic camera controls --- src/graphics33.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 src/graphics33.c (limited to 'src/graphics33.c') diff --git a/src/graphics33.c b/src/graphics33.c new file mode 100644 index 0000000..686aa86 --- /dev/null +++ b/src/graphics33.c @@ -0,0 +1,214 @@ +#include "math.h" + +#include "options33.h" +#include "types33.h" +#include "display33.h" +#include "scene33.h" +#include "strings33.h" +#include "logger33.h" + + +#define _FOV_HALF (0.78539816339744830962/2.0) +#define _NEAR 1.0 +#define _FAR 24.0 + + +static Mat4 _projectionMatrix = {0,}; +static Mat4 _viewMatrix; +static Mat4 _worldMatrix; +static f64 _preXformedModelVertices[ E33_VERTICES_PER_MODEL_MAX ][4]; + + +static void _draw_line( Vec2 v0, Vec2 v1, u32 colour ); + + +Error graphics33_init( void ) +{ + f64 ar, cot; + f64 displayW = (f64)__display.surface.w; + f64 displayH = (f64)__display.surface.h; + + ar = displayW / displayH; + cot = 1.0 / tan( _FOV_HALF ); + + _projectionMatrix[ 0] = cot / ar; + _projectionMatrix[ 5] = cot; + _projectionMatrix[10] = _FAR / (_FAR - _NEAR); + _projectionMatrix[11] = 1.0; + _projectionMatrix[14] = -_NEAR * (_FAR / (_FAR - _NEAR)); + + + return E33_EXIT_SUCCESS; +} + +Error graphics33_term( void ) +{ + return E33_EXIT_SUCCESS; +} + +void graphics33_update( void ) +{ + math33_create_view_matrix(__scene.camera.t, __scene.camera.r, _viewMatrix ); + VxP( _viewMatrix, _projectionMatrix ); +} + +void graphics33_decompose_scene( void ) +{ + extern Scene33 __scene; + + Size i, j; + Size displayW = __display.surface.w; + Size displayH = __display.surface.h; + Model33 *model = &__scene.cube; + + ModelEdge33 *medges = model->medges; + Size *sedges = model->sedges; + + Size modelVertexCount = model->vertexCount; + Size modelSurfaceCount = model->surfaceCount; + + + math33_create_world_matrix( model->t, model->r, model->s, _worldMatrix ); + MxM4( _worldMatrix, _viewMatrix ); + + #define pV _preXformedModelVertices + for( i = 0; i < modelVertexCount; ++i ) { + f64 iw; + + V4xMt( pV[i], model->vertices[i], _worldMatrix ); + + iw = 1.0 / pV[i][3]; + pV[i][0] = ( ((pV[i][0] * iw) + 1.0) * 0.5 ); + pV[i][1] = ( ((pV[i][1] * iw) + 1.0) * 0.5 ); + } + + for( i = 0; i < modelSurfaceCount; ++i ) + { + Vec4 v[16]; + Size a[2], b[2], c[2]; + Boolean needsClippage = 0; + + a[0] = medges[ sedges[i*3 ] ].vertices[0]; + a[1] = medges[ sedges[i*3 ] ].vertices[1]; + b[0] = medges[ sedges[i*3+1] ].vertices[0]; + b[1] = medges[ sedges[i*3+1] ].vertices[1]; + c[0] = medges[ sedges[i*3+2] ].vertices[0]; + c[1] = medges[ sedges[i*3+2] ].vertices[1]; + + if( a[0] == b[0] ) + { + Size tmp = a[0]; + a[0] = a[1]; + a[1] = tmp; + } + else if( a[1] == b[1] ) + { + Size tmp = b[0]; + b[0] = b[1]; + b[1] = tmp; + } + + if( c[1] != a[0] ) { + Size tmp = c[0]; + c[0] = c[1]; + c[1] = tmp; + } + + if( ( (pV[a[0]][0] - pV[b[0]][0]) * (pV[c[0]][1] - pV[b[0]][1]) - + (pV[a[0]][1] - pV[b[0]][1]) * (pV[c[0]][0] - pV[b[0]][0]) ) <= 0 ) { + continue; + } + + v[0][3] = pV[a[0]][3]; + if( v[0][3] <= _NEAR ) continue; + if( v[0][3] > _FAR ) continue; + v[0][0] = pV[a[0]][0]; + v[0][1] = pV[a[0]][1]; + v[0][2] = pV[a[0]][2]; + + v[1][3] = pV[b[0]][3]; + if( v[1][3] <= _NEAR ) continue; + if( v[1][3] > _FAR ) continue; + v[1][0] = pV[b[0]][0]; + v[1][1] = pV[b[0]][1]; + v[1][2] = pV[b[0]][2]; + + v[2][3] = pV[c[0]][3]; + if( v[2][3] <= _NEAR ) continue; + if( v[2][3] > _FAR ) continue; + v[2][0] = pV[c[0]][0]; + v[2][1] = pV[c[0]][1]; + v[2][2] = pV[c[0]][2]; + + v[0][0] *= (f64)(displayW - 1); + v[0][1] *= (f64)(displayH - 1); + v[1][0] *= (f64)(displayW - 1); + v[1][1] *= (f64)(displayH - 1); + v[2][0] *= (f64)(displayW - 1); + v[2][1] *= (f64)(displayH - 1); + + _draw_line( v[0], v[1], CYAN ); + _draw_line( v[1], v[2], CYAN ); + _draw_line( v[2], v[0], CYAN ); + } + #undef pV +} + + +static void _draw_line( Vec2 v0, Vec2 v1, u32 colour ) +{ + u32 *dest = __display.surface.data; + Size w = __display.surface.w; + Size h = __display.surface.h; + Size x0 = (Size)(v0[0] + 0.5 ); + Size y0 = (Size)(v0[1] + 0.5 ); + Size x1 = (Size)(v1[0] + 0.5 ); + Size y1 = (Size)(v1[1] + 0.5 ); + + Size sx, sy; + Size dx, dy, error; + + + dx = (x1 - x0); + if( dx < 0 ) { dx = -dx; } + sx = -1; if( x0 < x1 ) sx = 1; + + dy = -(y1 - y0); + if( dy > 0 ) { dy = -dy; } + sy = -1; if( y0 < y1 ) sy = 1; + + error = dx + dy; + + while( 1 ) + { + Size e2; + + dest[ x0 + y0 * w ] = colour; + + if( (x0 == x1) && (y0 == y1) ) { + break; + } + + e2 = error << 1; + + if( e2 >= dy ) + { + if( x0 == x1 ) { + break; + } + + error += dy; + x0 += sx; + } + + if( e2 <= dx ) + { + if( y0 == y1 ) { + break; + } + + error += dx; + y0 += sy; + } + } +} -- cgit v1.2.3