1
0
Fork 0
mirror of https://git.coom.tech/drummyfish/small3dlib.git synced 2024-11-21 20:39:57 +01:00

Start barycentric

This commit is contained in:
Miloslav Číž 2018-11-17 19:57:30 +01:00
parent 20ec0693a7
commit d3a3e12f33
2 changed files with 77 additions and 13 deletions

79
s3l.h
View file

@ -51,6 +51,26 @@ static inline int16_t S3L_max(int16_t v1, int16_t v2)
return v1 >= v2 ? v1 : v2; return v1 >= v2 ? v1 : v2;
} }
/**
Interpolated between two values, v1 and v2, in the same ratio as t is to
tMax. Does NOT prevent zero division.
*/
static inline int16_t S3L_interpolate(int16_t v1, int16_t v2, int16_t t,
int16_t tMax)
{
return v1 + ((v2 - v1) * t) / tMax;
}
/**
Same as S3L_interpolate but with v1 = 0. Should be faster.
*/
static inline int16_t S3L_interpolateFrom0(int16_t v2, int16_t t, int16_t tMax)
{
return (v2 * t) / tMax;
}
void S3L_bresenhamInit(S3L_BresenhamState *state, int16_t x0, int16_t y0, int16_t x1, int16_t y1) void S3L_bresenhamInit(S3L_BresenhamState *state, int16_t x0, int16_t y0, int16_t x1, int16_t y1)
{ {
int16_t dx = x1 - x0; int16_t dx = x1 - x0;
@ -165,9 +185,9 @@ void S3L_drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2
#undef handleLR #undef handleLR
S3L_COORD splitY; S3L_COORD splitY; // Y at which one side (L or R) changes
S3L_COORD endY; S3L_COORD endY; // bottom Y of the whole triangle
int splitOnLeft; int splitOnLeft; // whether split happens on L or R
if (rPointY <= lPointY) if (rPointY <= lPointY)
{ {
@ -198,12 +218,23 @@ 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
lSideUnitStep, rSideUnitStep,
lSideUnitPos, rSideUnitPos;
int16_t helperDxAbs; int16_t helperDxAbs;
#define initSide(v,p1,p2)\ #define initSide(v,p1,p2, down)\
v##X = p1##PointX;\ v##X = p1##PointX;\
v##Dx = p2##PointX - p1##PointX;\ v##Dx = p2##PointX - p1##PointX;\
v##Dy = p2##PointY - p1##PointY;\ v##Dy = p2##PointY - p1##PointY;\
v##SideUnitStep = S3L_FRACTIONS_PER_UNIT / (v##Dy != 0 ? v##Dy : 1);\
v##SideUnitPos = 0;\
if (!down)\
{\
v##SideUnitPos = S3L_FRACTIONS_PER_UNIT;\
v##SideUnitStep *= -1;\
}\
helperDxAbs = S3L_abs(v##Dx);\ helperDxAbs = S3L_abs(v##Dx);\
v##Inc = v##Dx >= 0 ? 1 : -1;\ v##Inc = v##Dx >= 0 ? 1 : -1;\
v##Err = 2 * helperDxAbs - v##Dy;\ v##Err = 2 * helperDxAbs - v##Dy;\
@ -220,8 +251,8 @@ void S3L_drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2
}\ }\
s##Err += s##ErrAdd; s##Err += s##ErrAdd;
initSide(r,t,r) initSide(r,t,r,1)
initSide(l,t,l) initSide(l,t,l,1)
S3L_PixelInfo p; S3L_PixelInfo p;
@ -229,8 +260,9 @@ void S3L_drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2
p.barycentricB = 0; p.barycentricB = 0;
p.barycentricC = 0; p.barycentricC = 0;
//lBarStep = S3L_FRACTIONS_PER_UNIT S3L_UNIT *barycentric1 = &p.barycentricA;
//rBarStep = S3L_FRACTIONS_PER_UNIT S3L_UNIT *barycentric2 = &p.barycentricB;
S3L_UNIT *barycentric3 = &p.barycentricC;
while (currentY <= endY) while (currentY <= endY)
{ {
@ -238,11 +270,20 @@ void S3L_drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2
{ {
if (splitOnLeft) if (splitOnLeft)
{ {
initSide(l,l,r); initSide(l,l,r,0);
barycentric1 = &p.barycentricC;
barycentric2 = &p.barycentricB;
barycentric3 = &p.barycentricA;
rSideUnitPos = S3L_FRACTIONS_PER_UNIT - rSideUnitPos;
rSideUnitStep *= -1;
} }
else else
{ {
initSide(r,r,l); initSide(r,r,l,0);
// TODO
} }
} }
@ -250,20 +291,36 @@ 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;
tMax = tMax != 0 ? tMax : 1; // prevent division by zero
S3L_UNIT t1 = 0;
S3L_UNIT t2 = tMax;
for (S3L_COORD x = lX; x <= rX; ++x) for (S3L_COORD x = lX; x <= rX; ++x)
{ {
*barycentric1 = S3L_interpolateFrom0(rSideUnitPos,t1,tMax);
*barycentric2 = S3L_interpolateFrom0(lSideUnitPos,t2,tMax);
*barycentric3 = S3L_FRACTIONS_PER_UNIT - *barycentric1 - *barycentric2;
p.x = x; p.x = x;
S3L_PIXEL_FUNCTION(&p); S3L_PIXEL_FUNCTION(&p);
++t1;
--t2;
} }
stepSide(r) stepSide(r)
stepSide(l) stepSide(l)
lSideUnitPos += lSideUnitStep;
rSideUnitPos += rSideUnitStep;
++currentY; ++currentY;
} }
#undef initSide #undef initSide
#undef stepSide #undef stepSide
} }
#endif #endif

View file

@ -34,7 +34,13 @@ static inline void setPixel(int x, int y, uint8_t red, uint8_t green, uint8_t bl
void drawPixel(S3L_PixelInfo *p) void drawPixel(S3L_PixelInfo *p)
{ {
setPixel(p->x,p->y,255,255,255);
setPixel(p->x,p->y,
p->barycentricA / ((float) S3L_FRACTIONS_PER_UNIT) * 255,
p->barycentricB / ((float) S3L_FRACTIONS_PER_UNIT) * 255,
p->barycentricC / ((float) S3L_FRACTIONS_PER_UNIT) * 255);
} }
const int16_t test_coords[] = const int16_t test_coords[] =
@ -62,10 +68,11 @@ void draw()
y2 = test_coords[6 * c + 5]; y2 = test_coords[6 * c + 5];
S3L_drawTriangle(x0,y0,x1,y1,x2,y2); S3L_drawTriangle(x0,y0,x1,y1,x2,y2);
/*
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);
*/
} }
} }