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:
parent
20ec0693a7
commit
d3a3e12f33
2 changed files with 77 additions and 13 deletions
79
s3l.h
79
s3l.h
|
@ -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
|
||||||
|
|
11
testSDL.c
11
testSDL.c
|
@ -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);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue