1
0
Fork 0
mirror of https://git.coom.tech/drummyfish/small3dlib.git synced 2024-11-21 20:39:57 +01:00
This commit is contained in:
Miloslav Číž 2018-11-18 13:40:51 +01:00
parent 1d52e3b516
commit 182ee3b65d
3 changed files with 70 additions and 33 deletions

View file

@ -1,5 +1,9 @@
#!/bin/bash #!/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

66
s3l.h
View file

@ -3,7 +3,7 @@
#include <stdint.h> #include <stdint.h>
typedef int16_t S3L_UNIT; typedef int16_t S3L_Unit;
#define S3L_FRACTIONS_PER_UNIT 1024 #define S3L_FRACTIONS_PER_UNIT 1024
typedef int16_t S3L_COORD; typedef int16_t S3L_COORD;
@ -12,16 +12,27 @@ typedef struct
S3L_COORD x; ///< Screen X coordinate. S3L_COORD x; ///< Screen X coordinate.
S3L_COORD y; ///< Screen Y 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 Together with B and C coords these serve to
locate the pixel on a triangle and interpolate locate the pixel on a triangle and interpolate
values between it's three points. The sum of the values between it's three points. The sum of the
three coordinates will always be exactly three coordinates will always be exactly
S3L_FRACTIONS_PER_UNIT. */ S3L_FRACTIONS_PER_UNIT. */
S3L_UNIT barycentric1; ///< Baryc. coord B (corresponds to 2nd vertex). S3L_Unit barycentric1; ///< Baryc. coord B (corresponds to 2nd vertex).
S3L_UNIT barycentric2; ///< Baryc. coord C (corresponds to 3rd vertex). S3L_Unit barycentric2; ///< Baryc. coord C (corresponds to 3rd vertex).
} S3L_PixelInfo; } 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 typedef struct
{ {
int16_t steps; int16_t steps;
@ -52,6 +63,16 @@ static inline int16_t S3L_max(int16_t v1, int16_t v2)
return v1 >= v2 ? v1 : 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 Interpolated between two values, v1 and v2, in the same ratio as t is to
tMax. Does NOT prevent zero division. tMax. Does NOT prevent zero division.
@ -130,7 +151,7 @@ int S3L_bresenhamStep(S3L_BresenhamState *state)
return state->steps >= 0; 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 S3L_COORD
tPointX, tPointY, // top triangle point coords 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.barycentric1 = 0;
p.barycentric2 = 0; p.barycentric2 = 0;
S3L_UNIT *barycentric0; // bar. coord that gets higher from L to R 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 *barycentric1; // bar. coord that gets higher from R to L
S3L_UNIT *barycentric2; // bar. coord that gets higher from bottom up S3L_Unit *barycentric2; // bar. coord that gets higher from bottom up
// Sort the points. // Sort the points.
#define handleLR(a,b)\ #define handleLR(t,a,b)\
if (x##a <= x##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;\ lPointX = x##a; lPointY = y##a;\
rPointX = x##b; rPointY = y##b;\ 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; tPointX = x0;
tPointY = y0; tPointY = y0;
barycentric2 = &p.barycentric0; barycentric2 = &p.barycentric0;
handleLR(1,2) handleLR(0,1,2)
} }
else else
{ {
tPointX = x2; tPointX = x2;
tPointY = y2; tPointY = y2;
barycentric2 = &p.barycentric2; barycentric2 = &p.barycentric2;
handleLR(0,1) handleLR(2,0,1)
} }
} }
else 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; tPointX = x1;
tPointY = y1; tPointY = y1;
barycentric2 = &p.barycentric1; barycentric2 = &p.barycentric1;
handleLR(0,2) handleLR(1,0,2)
} }
else else
{ {
tPointX = x2; tPointX = x2;
tPointY = y2; tPointY = y2;
barycentric2 = &p.barycentric2; 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 lErrAdd, rErrAdd, // error value to add in each Bresenham cycle
lErrSub, rErrSub; // error value to substract when moving in x direction lErrSub, rErrSub; // error value to substract when moving in x direction
S3L_UNIT S3L_Unit
lSideUnitStep, rSideUnitStep, lSideUnitStep, rSideUnitStep,
lSideUnitPos, rSideUnitPos; 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); initSide(l,l,r,0);
S3L_UNIT *tmp = barycentric0; S3L_Unit *tmp = barycentric0;
barycentric0 = barycentric2; barycentric0 = barycentric2;
barycentric2 = tmp; 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); initSide(r,r,l,0);
S3L_UNIT *tmp = barycentric1; S3L_Unit *tmp = barycentric1;
barycentric1 = barycentric2; barycentric1 = barycentric2;
barycentric2 = tmp; 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 // draw the line
S3L_UNIT tMax = rX - lX; S3L_Unit tMax = rX - lX;
tMax = tMax != 0 ? tMax : 1; // prevent division by zero tMax = tMax != 0 ? tMax : 1; // prevent division by zero
S3L_UNIT t1 = 0; S3L_Unit t1 = 0;
S3L_UNIT t2 = tMax; S3L_Unit t2 = tMax;
for (S3L_COORD x = lX; x <= rX; ++x) for (S3L_COORD x = lX; x <= rX; ++x)
{ {

View file

@ -47,7 +47,7 @@ const int16_t test_coords[] =
{ {
100,100, 99,101, 101,101, // 0, small triangle 100,100, 99,101, 101,101, // 0, small triangle
190,50, 200,10, 400,80, // 1, arbitrary 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 350,270, 440,200, 490,220, // 3, arbitrary
150,300, 290,400, 450,400, // 4, regular 150,300, 290,400, 450,400, // 4, regular
105,200, 120,200, 201,200, // 5, horizontal line 105,200, 120,200, 201,200, // 5, horizontal line
@ -58,7 +58,11 @@ void draw()
{ {
clearScreen(); clearScreen();
/* S3L_DrawConfig conf;
conf.backfaceCulling = S3L_BACKFACE_CULLING_NONE;
for (int c = 0; c < 7; ++c) for (int c = 0; c < 7; ++c)
{ {
int int
@ -69,26 +73,29 @@ void draw()
x2 = test_coords[6 * c + 4], x2 = test_coords[6 * c + 4],
y2 = test_coords[6 * c + 5]; 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(x0,y0,255,0,0);
setPixel(x1,y1,255,0,0); setPixel(x1,y1,255,0,0);
setPixel(x2,y2,255,0,0); setPixel(x2,y2,255,0,0);
} }
*/
int16_t rotX0 = 200 + sin(frame * 0.01) * 50; int16_t rotX0 = 200 + sin(frame * 0.01) * 50;
int16_t rotY0 = 200 + cos(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 rotX1 = 200 + sin((frame + 500) * 0.01) * 50;
int16_t rotY1 = 200 + cos((frame + 300) * 0.01) * 50; int16_t rotY1 = 200 + cos((frame + 500) * 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 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);
} }