mirror of
https://git.coom.tech/drummyfish/small3dlib.git
synced 2024-11-23 20:59:58 +01:00
Fix discontinities in long triangles
This commit is contained in:
parent
e0467330e9
commit
c0a0270c96
2 changed files with 32 additions and 11 deletions
40
s3l.h
40
s3l.h
|
@ -85,6 +85,9 @@ typedef int32_t S3L_Unit; /**< Units of measurement in 3D space. There is
|
||||||
it will overflow. Also other things
|
it will overflow. Also other things
|
||||||
may overflow, so rather don't do it. */
|
may overflow, so rather don't do it. */
|
||||||
|
|
||||||
|
#define S3L_NONZERO(value) ((value) != 0 ? (value) : 1) /**< prevents division
|
||||||
|
by zero */
|
||||||
|
|
||||||
#define S3L_SIN_TABLE_LENGTH 128
|
#define S3L_SIN_TABLE_LENGTH 128
|
||||||
static const S3L_Unit S3L_sinTable[S3L_SIN_TABLE_LENGTH] =
|
static const S3L_Unit S3L_sinTable[S3L_SIN_TABLE_LENGTH] =
|
||||||
{
|
{
|
||||||
|
@ -722,9 +725,9 @@ void S3L_drawTriangle(
|
||||||
|
|
||||||
#undef handleLR
|
#undef handleLR
|
||||||
|
|
||||||
S3L_ScreenCoord splitY; // Y at which one side (L or R) changes
|
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 split happens on L or R
|
int splitOnLeft; // whether splitY happens on L or R side
|
||||||
|
|
||||||
if (rPointY <= lPointY)
|
if (rPointY <= lPointY)
|
||||||
{
|
{
|
||||||
|
@ -761,7 +764,12 @@ void S3L_drawTriangle(
|
||||||
|
|
||||||
int16_t helperDxAbs;
|
int16_t helperDxAbs;
|
||||||
|
|
||||||
#define initSide(v,p1,p2, down)\
|
/* init side for the algorithm, params:
|
||||||
|
v - which side (l or r)
|
||||||
|
p1 - point from (t, l or r)
|
||||||
|
p2 - point to (t, l or r)
|
||||||
|
down - whether going top-down or bottom-up */
|
||||||
|
#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;\
|
||||||
|
@ -791,10 +799,14 @@ void S3L_drawTriangle(
|
||||||
initSide(r,t,r,1)
|
initSide(r,t,r,1)
|
||||||
initSide(l,t,l,1)
|
initSide(l,t,l,1)
|
||||||
|
|
||||||
while (currentY <= endY)
|
S3L_Unit xFrom_prev = tPointX; // helper vars, hold previous values of xFrom
|
||||||
{
|
S3L_Unit xTo_prev = tPointX; // and xTo (declared later) to prevent
|
||||||
if (currentY == splitY)
|
// discontinuities
|
||||||
|
|
||||||
|
while (currentY <= endY) // draw the triangle from top to bottom
|
||||||
{
|
{
|
||||||
|
if (currentY == splitY) // reached a vertical split of the triangle?
|
||||||
|
{ // then reinit one side
|
||||||
if (splitOnLeft)
|
if (splitOnLeft)
|
||||||
{
|
{
|
||||||
initSide(l,l,r,0);
|
initSide(l,l,r,0);
|
||||||
|
@ -821,15 +833,20 @@ void S3L_drawTriangle(
|
||||||
|
|
||||||
p.y = currentY;
|
p.y = currentY;
|
||||||
|
|
||||||
// draw the line
|
// draw the horizontal line
|
||||||
|
|
||||||
S3L_Unit tMax = rX - lX;
|
S3L_Unit xFrom = lX < (xTo_prev + 1) ? lX : (xTo_prev + 1);
|
||||||
tMax = tMax != 0 ? tMax : 1; // prevent division by zero
|
S3L_Unit xTo = rX > (xFrom_prev - 1) ? rX : (xFrom_prev - 1);
|
||||||
|
/* ^ these conditions prevent discontinuities when drawing
|
||||||
|
"long" triangles (thinner than 1 px) */
|
||||||
|
|
||||||
|
S3L_Unit tMax = xTo - xFrom;
|
||||||
|
tMax = S3L_NONZERO(tMax); // prevent division by zero
|
||||||
|
|
||||||
S3L_Unit t1 = 0;
|
S3L_Unit t1 = 0;
|
||||||
S3L_Unit t2 = tMax;
|
S3L_Unit t2 = tMax;
|
||||||
|
|
||||||
for (S3L_ScreenCoord x = lX; x <= rX; ++x)
|
for (S3L_ScreenCoord x = xFrom; x <= xTo; ++x)
|
||||||
{
|
{
|
||||||
*barycentric0 = S3L_interpolateFrom0(rSideUnitPos,t1,tMax);
|
*barycentric0 = S3L_interpolateFrom0(rSideUnitPos,t1,tMax);
|
||||||
*barycentric1 = S3L_interpolateFrom0(lSideUnitPos,t2,tMax);
|
*barycentric1 = S3L_interpolateFrom0(lSideUnitPos,t2,tMax);
|
||||||
|
@ -848,6 +865,9 @@ void S3L_drawTriangle(
|
||||||
lSideUnitPos += lSideUnitStep;
|
lSideUnitPos += lSideUnitStep;
|
||||||
rSideUnitPos += rSideUnitStep;
|
rSideUnitPos += rSideUnitStep;
|
||||||
|
|
||||||
|
xFrom_prev = xFrom;
|
||||||
|
xTo_prev = xTo;
|
||||||
|
|
||||||
++currentY;
|
++currentY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,8 @@ conf.mode = S3L_MODE_TRIANGLES;
|
||||||
y2 = test_coords[6 * c + 5];
|
y2 = test_coords[6 * c + 5];
|
||||||
|
|
||||||
int cent = (x0 + x1 + x2) / 3.0;
|
int cent = (x0 + x1 + x2) / 3.0;
|
||||||
x2 = cent + (x2 - cent) * sin(frame * 0.01) * 2;
|
x2 = cent + (x2 - cent) * sin(frame * 0.001) * 2;
|
||||||
|
//x2 = cent + (x2 - cent) * sin(600 * 0.001) * 2;
|
||||||
|
|
||||||
S3L_drawTriangle(x0,y0,x1,y1,x2,y2,conf,0);
|
S3L_drawTriangle(x0,y0,x1,y1,x2,y2,conf,0);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue