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 Číž 2019-05-10 16:52:20 +02:00
parent 8392d88763
commit 01e523aff0
2 changed files with 73 additions and 128 deletions

197
s3l.h
View file

@ -832,16 +832,16 @@ void _S3L_drawFilledTriangle(
S3L_PixelInfo *p) S3L_PixelInfo *p)
{ {
S3L_ScreenCoord x0, y0, x1, y1, x2, y2; S3L_ScreenCoord x0, y0, x1, y1, x2, y2;
S3L_Vec4 *pointTop, *pointLeft, *pointRight; S3L_Vec4 *tPointPP, *lPointPP, *rPointPP; // points in projction plane space
S3L_mapProjectionPlaneToScreen(point0,&x0,&y0); S3L_mapProjectionPlaneToScreen(point0,&x0,&y0);
S3L_mapProjectionPlaneToScreen(point1,&x1,&y1); S3L_mapProjectionPlaneToScreen(point1,&x1,&y1);
S3L_mapProjectionPlaneToScreen(point2,&x2,&y2); S3L_mapProjectionPlaneToScreen(point2,&x2,&y2);
S3L_ScreenCoord S3L_ScreenCoord
tPointX, tPointY, // top triangle point coords tPointSx, tPointSy, // top point coords, in screen space
lPointX, lPointY, // left triangle point coords lPointSx, lPointSy, // left point coords, in screen space
rPointX, rPointY; // right triangle point coords rPointSx, rPointSy; // right point coords, in screen space
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
@ -849,90 +849,72 @@ void _S3L_drawFilledTriangle(
// Sort the points. // Sort the points.
#define handleLR(t,a,b)\ #define assignPoints(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;\ tPointSx = x##t;\
rPointX = x##b; rPointY = y##b;\ tPointSy = y##t;\
pointLeft = &point##a; pointRight = &point##b;\ tPointPP = &point##t;\
barycentric0 = &(p->barycentric##b);\ barycentric2 = &(p->barycentric##t);\
barycentric1 = &(p->barycentric##a);\ int16_t aDx = x##a - x##t;\
}\ int16_t bDx = x##b - x##t;\
else\ int16_t aDy = S3L_nonZero(y##a - y##t);\
{\ int16_t bDy = S3L_nonZero(y##b - y##t);\
lPointX = x##b; lPointY = y##b;\ if ((aDx << 4) / aDy < (bDx << 4) / bDy)\
rPointX = x##a; rPointY = y##a;\ /*if (x##a <= x##b)*/\
pointLeft = &point##b; pointRight = &point##a;\ {\
barycentric0 = &(p->barycentric##a);\ lPointSx = x##a; lPointSy = y##a;\
barycentric1 = &(p->barycentric##b);\ rPointSx = x##b; rPointSy = y##b;\
lPointPP = &point##a; rPointPP = &point##b;\
barycentric0 = &(p->barycentric##b);\
barycentric1 = &(p->barycentric##a);\
}\
else\
{\
lPointSx = x##b; lPointSy = y##b;\
rPointSx = x##a; rPointSy = y##a;\
lPointPP = &point##b; rPointPP = &point##a;\
barycentric0 = &(p->barycentric##a);\
barycentric1 = &(p->barycentric##b);\
}\
} }
if (y0 <= y1) if (y0 <= y1)
{ {
if (y0 <= y2) if (y0 <= y2)
{ assignPoints(0,1,2)
tPointX = x0;
tPointY = y0;
pointTop = &point0;
barycentric2 = &(p->barycentric0);
handleLR(0,1,2)
}
else else
{ assignPoints(2,0,1)
tPointX = x2;
tPointY = y2;
pointTop = &point2;
barycentric2 = &(p->barycentric2);
handleLR(2,0,1)
}
} }
else else
{ {
if (y1 <= y2) if (y1 <= y2)
{ assignPoints(1,0,2)
tPointX = x1;
tPointY = y1;
pointTop = &point1;
barycentric2 = &(p->barycentric1);
handleLR(1,0,2)
}
else else
{ assignPoints(2,0,1)
tPointX = x2;
tPointY = y2;
pointTop = &point2;
barycentric2 = &(p->barycentric2);
handleLR(2,0,1)
}
} }
// Now draw the triangle line by line. // Now draw the triangle line by line.
#undef handleLR #undef assignPoints
S3L_ScreenCoord splitY; // Y of the vertically middle point of the triangle S3L_ScreenCoord splitY; // Y of the vertically middle point of the triangle
S3L_ScreenCoord endY; // bottom Y of the whole triangle S3L_ScreenCoord endY; // bottom Y of the whole triangle
int splitOnLeft; // whether splitY happens on L or R side int splitOnLeft; // whether splitY happens on L or R side
if (rPointY <= lPointY) if (rPointSy <= lPointSy)
{ {
splitY = rPointY; splitY = rPointSy;
splitOnLeft = 0; splitOnLeft = 0;
endY = lPointY; endY = lPointSy;
} }
else else
{ {
splitY = lPointY; splitY = lPointSy;
splitOnLeft = 1; splitOnLeft = 1;
endY = rPointY; endY = rPointSy;
} }
S3L_ScreenCoord currentY = tPointY; S3L_ScreenCoord currentY = tPointSy;
/* We'll be using an algorithm similar to Bresenham line algorithm. The /* We'll be using an algorithm similar to Bresenham line algorithm. The
specifics of this algorithm are among others: specifics of this algorithm are among others:
@ -956,7 +938,7 @@ void _S3L_drawFilledTriangle(
int16_t int16_t
/* triangle side: /* triangle side:
left right */ left right */
lX, rX, // current x position lX, rX, // current x position on the screen
lDx, rDx, // dx (end point - start point) lDx, rDx, // dx (end point - start point)
lDy, rDy, // dy (end point - start point) lDy, rDy, // dy (end point - start point)
lInc, rInc, // direction in which to increment (1 or -1) lInc, rInc, // direction in which to increment (1 or -1)
@ -976,9 +958,9 @@ void _S3L_drawFilledTriangle(
down - whether the side coordinate goes top-down or vice versa down - whether the side coordinate goes top-down or vice versa
*/ */
#define initSide(s,p1,p2,down)\ #define initSide(s,p1,p2,down)\
s##X = p1##PointX;\ s##X = p1##PointSx;\
s##Dx = p2##PointX - p1##PointX;\ s##Dx = p2##PointSx - p1##PointSx;\
s##Dy = p2##PointY - p1##PointY;\ s##Dy = p2##PointSy - p1##PointSy;\
s##SideUnitStep = (S3L_FRACTIONS_PER_UNIT << S3L_LERP_QUALITY)\ s##SideUnitStep = (S3L_FRACTIONS_PER_UNIT << S3L_LERP_QUALITY)\
/ (s##Dy != 0 ? s##Dy : 1);\ / (s##Dy != 0 ? s##Dy : 1);\
s##SideUnitPos = 0;\ s##SideUnitPos = 0;\
@ -1007,34 +989,21 @@ void _S3L_drawFilledTriangle(
initSide(r,t,r,1) initSide(r,t,r,1)
initSide(l,t,l,1) initSide(l,t,l,1)
#define initPC(f,t,pc)\
S3L_initPerspectiveCorrectionState(\
f##PointPP->x,\
f##PointPP->y,\
f##PointPP->z,\
t##PointPP->x,\
t##PointPP->y,\
t##PointPP->z,\
camera->focalLength,\
&pc##PC);
#if S3L_PERSPECTIVE_CORRECTION == 1 #if S3L_PERSPECTIVE_CORRECTION == 1
S3L_PerspectiveCorrectionState lPC, rPC, rowPC; S3L_PerspectiveCorrectionState lPC, rPC, rowPC;
initPC(t,l,l)
S3L_Unit initPC(t,r,r)
lDepthFrom = pointTop->z,
lDepthTo = pointLeft->z,
rDepthFrom = pointTop->z,
rDepthTo = pointRight->z;
S3L_initPerspectiveCorrectionState(
pointTop->x,
pointTop->y,
pointTop->z,
pointLeft->x,
pointLeft->y,
pointLeft->z,
camera->focalLength,
&lPC);
S3L_initPerspectiveCorrectionState(
pointTop->x,
pointTop->y,
pointTop->z,
pointRight->x,
pointRight->y,
pointRight->z,
camera->focalLength,
&rPC);
#endif #endif
while (currentY < endY) /* draw the triangle from top to bottom -- the while (currentY < endY) /* draw the triangle from top to bottom -- the
@ -1058,18 +1027,7 @@ void _S3L_drawFilledTriangle(
rSideUnitStep *= -1; rSideUnitStep *= -1;
#if S3L_PERSPECTIVE_CORRECTION == 1 #if S3L_PERSPECTIVE_CORRECTION == 1
S3L_initPerspectiveCorrectionState( initPC(l,r,l)
pointLeft->x,
pointLeft->y,
pointLeft->z,
pointRight->x,
pointRight->y,
pointRight->z,
camera->focalLength,
&lPC);
lDepthFrom = pointLeft->z;
lDepthTo = pointRight->z;
#endif #endif
} }
else else
@ -1086,18 +1044,7 @@ void _S3L_drawFilledTriangle(
lSideUnitStep *= -1; lSideUnitStep *= -1;
#if S3L_PERSPECTIVE_CORRECTION == 1 #if S3L_PERSPECTIVE_CORRECTION == 1
S3L_initPerspectiveCorrectionState( initPC(r,l,r)
pointRight->x,
pointRight->y,
pointRight->z,
pointLeft->x,
pointLeft->y,
pointLeft->z,
camera->focalLength,
&rPC);
rDepthFrom = pointRight->z;
rDepthTo = pointLeft->z;
#endif #endif
} }
} }
@ -1120,27 +1067,24 @@ void _S3L_drawFilledTriangle(
#if S3L_PERSPECTIVE_CORRECTION == 1 #if S3L_PERSPECTIVE_CORRECTION == 1
S3L_Unit lDepth, rDepth, lT, rT; S3L_Unit lDepth, rDepth, lT, rT;
lT = lSideUnitPos >> S3L_LERP_QUALITY; lT = lSideUnitPos >> S3L_LERP_QUALITY; // CHANGEEEE
rT = rSideUnitPos >> S3L_LERP_QUALITY; rT = rSideUnitPos >> S3L_LERP_QUALITY; // CHANGEEEE
printf("%d %d\n",lDepth,rDepth); rT = S3L_correctPerspective(rT,&rPC);
lDepth = S3L_interpolateByUnit(lPC.p0[2],lPC.p1[2],lT);
rDepth = S3L_interpolateByUnit(rPC.p0[2],rPC.p1[2],rT);
S3L_initPerspectiveCorrectionState( S3L_initPerspectiveCorrectionState(
S3L_interpolateByUnit(pointTop->x,pointLeft->x,lT), S3L_interpolateByUnit(lPC.a[0],lPC.b[0],lT),
S3L_interpolateByUnit(pointTop->y,pointLeft->y,lT), S3L_interpolateByUnit(lPC.a[1],lPC.b[1],lT),
lDepth, lDepth,
S3L_interpolateByUnit(pointTop->x,pointRight->x,rT), S3L_interpolateByUnit(rPC.a[0],rPC.b[0],rT),
S3L_interpolateByUnit(pointTop->y,pointRight->y,rT), S3L_interpolateByUnit(rPC.a[1],rPC.b[1],rT),
rDepth, rDepth,
camera->focalLength, camera->focalLength,
&rowPC &rowPC
); );
lT = S3L_correctPerspective(lT,&lPC);
rT = S3L_correctPerspective(rT,&rPC);
lDepth = S3L_interpolateByUnit(lDepthFrom,lDepthTo,lT);
rDepth = S3L_interpolateByUnit(rDepthFrom,rDepthTo,rT);
#endif #endif
for (S3L_ScreenCoord x = lX; x < rX; ++x) for (S3L_ScreenCoord x = lX; x < rX; ++x)
@ -1170,6 +1114,7 @@ printf("%d %d\n",lDepth,rDepth);
++currentY; ++currentY;
} }
#undef initPC
#undef initSide #undef initSide
#undef stepSide #undef stepSide
} }

View file

@ -119,8 +119,8 @@ void draw()
//frame = 853; //frame = 853;
// modelTransform.rotation.z = frame * 0.1; modelTransform.rotation.z = frame * 0.1;
modelTransform.rotation.x = 60;//frame * 0.3; modelTransform.rotation.x = frame * 0.3;
S3L_drawModelIndexed(ver,tri,12,modelTransform,&camera,&conf); S3L_drawModelIndexed(ver,tri,12,modelTransform,&camera,&conf);
// S3L_drawModelIndexed(ver,tri + 3,1,modelTransform,&camera,&conf); // S3L_drawModelIndexed(ver,tri + 3,1,modelTransform,&camera,&conf);