aboutsummaryrefslogtreecommitdiff
path: root/src/graphics33.c
diff options
context:
space:
mode:
authorpk33 <pk33@pk33.space>2024-11-14 15:06:07 +0100
committerpk33 <pk33@pk33.space>2024-11-14 15:06:07 +0100
commited2a4bc4400c38ecd11baccac5db328b797b5d68 (patch)
treeb703749d0639f933edca4c3a78209159aa735c25 /src/graphics33.c
parent5a54774474f43ae29716751d6415563a59b92c7d (diff)
downloadengine33-master.tar.gz
begin 3D rendering, basic camera controlsHEADmaster
Diffstat (limited to 'src/graphics33.c')
-rw-r--r--src/graphics33.c214
1 files changed, 214 insertions, 0 deletions
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;
+ }
+ }
+}