From 182ee3b65dabb5db4eabacfe0fb5094eb594cbbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Sun, 18 Nov 2018 13:40:51 +0100 Subject: [PATCH] Fix L/R --- make.sh | 8 +++++-- s3l.h | 66 ++++++++++++++++++++++++++++++++++++++----------------- testSDL.c | 29 ++++++++++++++---------- 3 files changed, 70 insertions(+), 33 deletions(-) diff --git a/make.sh b/make.sh index 6e5b564..ce62687 100755 --- a/make.sh +++ b/make.sh @@ -1,5 +1,9 @@ #!/bin/bash -PROGRAM=testSDL +clear; clear -clear; clear; g++ -x c -g -fmax-errors=5 -pedantic -Wall -Wextra -o $PROGRAM $PROGRAM.c -lSDL2 2>&1 >/dev/null && ./$PROGRAM +make + +if [ $? -eq 0 ]; then + ./PokittoEmu ./BUILD/firmware.bin $1 +fi diff --git a/s3l.h b/s3l.h index 22ca5f8..e22673e 100644 --- a/s3l.h +++ b/s3l.h @@ -3,7 +3,7 @@ #include -typedef int16_t S3L_UNIT; +typedef int16_t S3L_Unit; #define S3L_FRACTIONS_PER_UNIT 1024 typedef int16_t S3L_COORD; @@ -12,16 +12,27 @@ typedef struct S3L_COORD x; ///< Screen X coordinate. S3L_COORD y; ///< Screen Y coordinate. - S3L_UNIT barycentric0; /**< Barycentric coord A (corresponds to 1st vertex). + S3L_Unit barycentric0; /**< Barycentric coord A (corresponds to 1st vertex). Together with B and C coords these serve to locate the pixel on a triangle and interpolate values between it's three points. The sum of the three coordinates will always be exactly S3L_FRACTIONS_PER_UNIT. */ - S3L_UNIT barycentric1; ///< Baryc. coord B (corresponds to 2nd vertex). - S3L_UNIT barycentric2; ///< Baryc. coord C (corresponds to 3rd vertex). + S3L_Unit barycentric1; ///< Baryc. coord B (corresponds to 2nd vertex). + S3L_Unit barycentric2; ///< Baryc. coord C (corresponds to 3rd vertex). } S3L_PixelInfo; +#define S3L_BACKFACE_CULLING_NONE 0 +#define S3L_BACKFACE_CULLING_CW 1 +#define S3L_BACKFACE_CULLING_CCW 2 + +typedef struct +{ + int backfaceCulling; +} S3L_DrawConfig; + +void S3L_PIXEL_FUNCTION(S3L_PixelInfo *pixel); // forward decl + typedef struct { int16_t steps; @@ -52,6 +63,16 @@ static inline int16_t S3L_max(int16_t v1, int16_t v2) return v1 >= v2 ? v1 : v2; } +static inline S3L_Unit S3L_wrap(S3L_Unit value, S3L_Unit mod) +{ + return value >= 0 ? (value % mod) : (mod + (value % mod) - 1); +} + +static inline S3L_nonZero(S3L_Unit value) +{ + return value != 0 ? value : 1; +} + /** Interpolated between two values, v1 and v2, in the same ratio as t is to tMax. Does NOT prevent zero division. @@ -130,7 +151,7 @@ int S3L_bresenhamStep(S3L_BresenhamState *state) return state->steps >= 0; } -void S3L_drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2) +void S3L_drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, S3L_DrawConfig config) { S3L_COORD tPointX, tPointY, // top triangle point coords @@ -143,14 +164,19 @@ void S3L_drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2 p.barycentric1 = 0; p.barycentric2 = 0; - S3L_UNIT *barycentric0; // bar. coord that gets higher from L to R - S3L_UNIT *barycentric1; // bar. coord that gets higher from R to L - S3L_UNIT *barycentric2; // bar. coord that gets higher from bottom up + S3L_Unit *barycentric0; // bar. coord that gets higher from L to R + S3L_Unit *barycentric1; // bar. coord that gets higher from R to L + S3L_Unit *barycentric2; // bar. coord that gets higher from bottom up // Sort the points. - #define handleLR(a,b)\ - if (x##a <= x##b)\ + #define handleLR(t,a,b)\ + int16_t aDx = x##a - x##t;\ + int16_t bDx = x##b - x##t;\ + int16_t aDy = S3L_nonZero(y##a - y##t);\ + int16_t bDy = S3L_nonZero(y##b - y##t);\ + if ((aDx << 4) / aDy < (bDx << 4) / bDy)\ + /*if (x##a <= x##b)*/\ {\ lPointX = x##a; lPointY = y##a;\ rPointX = x##b; rPointY = y##b;\ @@ -172,14 +198,14 @@ void S3L_drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2 tPointX = x0; tPointY = y0; barycentric2 = &p.barycentric0; - handleLR(1,2) + handleLR(0,1,2) } else { tPointX = x2; tPointY = y2; barycentric2 = &p.barycentric2; - handleLR(0,1) + handleLR(2,0,1) } } else @@ -189,14 +215,14 @@ void S3L_drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2 tPointX = x1; tPointY = y1; barycentric2 = &p.barycentric1; - handleLR(0,2) + handleLR(1,0,2) } else { tPointX = x2; tPointY = y2; barycentric2 = &p.barycentric2; - handleLR(0,1) + handleLR(2,0,1) } } @@ -237,7 +263,7 @@ void S3L_drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2 lErrAdd, rErrAdd, // error value to add in each Bresenham cycle lErrSub, rErrSub; // error value to substract when moving in x direction - S3L_UNIT + S3L_Unit lSideUnitStep, rSideUnitStep, lSideUnitPos, rSideUnitPos; @@ -281,7 +307,7 @@ void S3L_drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2 { initSide(l,l,r,0); - S3L_UNIT *tmp = barycentric0; + S3L_Unit *tmp = barycentric0; barycentric0 = barycentric2; barycentric2 = tmp; @@ -292,7 +318,7 @@ void S3L_drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2 { initSide(r,r,l,0); - S3L_UNIT *tmp = barycentric1; + S3L_Unit *tmp = barycentric1; barycentric1 = barycentric2; barycentric2 = tmp; @@ -305,11 +331,11 @@ void S3L_drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2 // draw the line - S3L_UNIT tMax = rX - lX; + S3L_Unit tMax = rX - lX; tMax = tMax != 0 ? tMax : 1; // prevent division by zero - S3L_UNIT t1 = 0; - S3L_UNIT t2 = tMax; + S3L_Unit t1 = 0; + S3L_Unit t2 = tMax; for (S3L_COORD x = lX; x <= rX; ++x) { diff --git a/testSDL.c b/testSDL.c index 482f37c..95c5a50 100644 --- a/testSDL.c +++ b/testSDL.c @@ -47,7 +47,7 @@ const int16_t test_coords[] = { 100,100, 99,101, 101,101, // 0, small triangle 190,50, 200,10, 400,80, // 1, arbitrary - 40,80, 20,50, 100,30, // 2, arbitrary + 40,80, 60,50, 100,30, // 2, arbitrary 350,270, 440,200, 490,220, // 3, arbitrary 150,300, 290,400, 450,400, // 4, regular 105,200, 120,200, 201,200, // 5, horizontal line @@ -58,7 +58,11 @@ void draw() { clearScreen(); -/* +S3L_DrawConfig conf; + +conf.backfaceCulling = S3L_BACKFACE_CULLING_NONE; + + for (int c = 0; c < 7; ++c) { int @@ -69,26 +73,29 @@ void draw() x2 = test_coords[6 * c + 4], y2 = test_coords[6 * c + 5]; - S3L_drawTriangle(x0,y0,x1,y1,x2,y2); +//int cent = (x0 + x1 + x2) / 3.0; +//x1 = cent + (x1 - cent) * sin(frame * 0.01); + + S3L_drawTriangle(x0,y0,x1,y1,x2,y2,conf); + setPixel(x0,y0,255,0,0); setPixel(x1,y1,255,0,0); setPixel(x2,y2,255,0,0); + } -*/ + int16_t rotX0 = 200 + sin(frame * 0.01) * 50; int16_t rotY0 = 200 + cos(frame * 0.01) * 50; -int16_t rotX1 = 200 + sin((frame + 300) * 0.01) * 50; -int16_t rotY1 = 200 + cos((frame + 300) * 0.01) * 50; - -int16_t rotX2 = 200 + sin((frame + 500) * 0.01) * 50; -int16_t rotY2 = 200 + cos((frame + 500) * 0.01) * 50; - -S3L_drawTriangle(rotX0,rotY0,rotX1,rotY1,rotX2,rotY2); +int16_t rotX1 = 200 + sin((frame + 500) * 0.01) * 50; +int16_t rotY1 = 200 + cos((frame + 500) * 0.01) * 50; +int16_t rotX2 = 200 + sin((frame + 300) * 0.01) * 50; +int16_t rotY2 = 200 + cos((frame + 300) * 0.01) * 50; +S3L_drawTriangle(rotX0,rotY0,rotX1,rotY1,rotX2,rotY2,conf); }