0.9.6: line hack

This commit is contained in:
gocha 2010-12-24 13:59:19 +00:00
parent 6f7d169123
commit 776968e0f5
4 changed files with 91 additions and 93 deletions

View File

@ -813,64 +813,6 @@ static void GL_ReadFramebuffer()
} }
// "Workaround" for line poly
static bool isLinePoly(POLY *poly)
{
int type = poly->type;
VERT *vert1, *vert2;
if (type <= 2)
return true;
else if (type > 4)
return false;
// Method 1:
// Castlevania Portrait of Ruin - trajectory of ricochet
bool duplicatedVert[4] = { false, false, false, false };
for(int i = 0; i < type - 1; i++)
{
vert1 = &gfx3d.vertlist->list[poly->vertIndexes[i]];
for(int j = i + 1; j < type; j++)
{
vert2 = &gfx3d.vertlist->list[poly->vertIndexes[j]];
if (vert1->x == vert2->x && vert1->y == vert2->y)
{
duplicatedVert[j] = true;
}
}
}
int vertCount = type;
for(int i = 0; i < type; i++)
{
if (duplicatedVert[i])
vertCount--;
}
if (vertCount <= 2)
return true;
// Method 2:
// Castlevania Portrait of Ruin - warp stone
bool horizontalLine = true;
bool verticalLine = true;
vert1 = &gfx3d.vertlist->list[poly->vertIndexes[0]];
for(int i = 1; i < type && (horizontalLine || verticalLine); i++)
{
vert2 = &gfx3d.vertlist->list[poly->vertIndexes[i]];
if (vert1->coord[0] != vert2->coord[0])
{
verticalLine = false;
}
if (vert1->coord[1] != vert2->coord[1])
{
horizontalLine = false;
}
}
if (horizontalLine || verticalLine)
return true;
return false;
}
static void OGLRender() static void OGLRender()
{ {
if(!BEGINGL()) return; if(!BEGINGL()) return;
@ -971,7 +913,7 @@ static void OGLRender()
lastViewport = poly->viewport; lastViewport = poly->viewport;
} }
if (isLinePoly(poly)) if (gfx3d_IsLinePoly(poly))
glBegin(GL_LINE_LOOP); glBegin(GL_LINE_LOOP);
else else
glBegin(GL_TRIANGLES); glBegin(GL_TRIANGLES);

View File

@ -2760,3 +2760,60 @@ void GFX3D_Clipper::clipPoly(POLY* poly, VERT** verts)
} }
#endif #endif
// "Workaround" for line poly
bool gfx3d_IsLinePoly(POLY *poly)
{
int type = poly->type;
VERT *vert1, *vert2;
if (type <= 2)
return true;
else if (type > 4)
return false;
// Method 1:
// Castlevania Portrait of Ruin - trajectory of ricochet
bool duplicatedVert[4] = { false, false, false, false };
for(int i = 0; i < type - 1; i++)
{
vert1 = &gfx3d.vertlist->list[poly->vertIndexes[i]];
for(int j = i + 1; j < type; j++)
{
vert2 = &gfx3d.vertlist->list[poly->vertIndexes[j]];
if (vert1->x == vert2->x && vert1->y == vert2->y)
{
duplicatedVert[j] = true;
}
}
}
int vertCount = type;
for(int i = 0; i < type; i++)
{
if (duplicatedVert[i])
vertCount--;
}
if (vertCount <= 2)
return true;
// Method 2:
// Castlevania Portrait of Ruin - warp stone
bool horizontalLine = true;
bool verticalLine = true;
vert1 = &gfx3d.vertlist->list[poly->vertIndexes[0]];
for(int i = 1; i < type && (horizontalLine || verticalLine); i++)
{
vert2 = &gfx3d.vertlist->list[poly->vertIndexes[i]];
if (vert1->coord[0] != vert2->coord[0])
{
verticalLine = false;
}
if (vert1->coord[1] != vert2->coord[1])
{
horizontalLine = false;
}
}
if (horizontalLine || verticalLine)
return true;
return false;
}

View File

@ -446,4 +446,6 @@ bool gfx3d_loadstate(EMUFILE* is, int size);
void gfx3d_ClearStack(); void gfx3d_ClearStack();
bool gfx3d_IsLinePoly(POLY *poly);
#endif //_GFX3D_H_ #endif //_GFX3D_H_

View File

@ -245,7 +245,6 @@ FORCEINLINE edge_fx_fl::edge_fx_fl(int Top, int Bottom, VERT** verts, bool& fail
Numerator = 0; Numerator = 0;
ErrorTerm = 0; ErrorTerm = 0;
Denominator = 1; Denominator = 1;
failure = false;
} }
float YPrestep = Fixed28_4ToFloat((fixed28_4)(Y*16 - verts[Top]->y)); float YPrestep = Fixed28_4ToFloat((fixed28_4)(Y*16 - verts[Top]->y));
@ -691,26 +690,22 @@ public:
} }
//draws a single scanline //draws a single scanline
FORCEINLINE void drawscanline(edge_fx_fl *pLeft, edge_fx_fl *pRight) FORCEINLINE void drawscanline(edge_fx_fl *pLeft, edge_fx_fl *pRight, bool lineHack)
{ {
int XStart = pLeft->X; int XStart = pLeft->X;
int width = pRight->X - XStart; int width = pRight->X - XStart;
// workaround for vertical/slant line poly // HACK: workaround for vertical/slant line poly
// it seems to cause another issue though if (lineHack && width == 0)
//if (width == 0) {
//{ int leftWidth = pLeft->XStep;
// int leftWidth = pLeft->XStep; if (pLeft->ErrorTerm + pLeft->Numerator >= pLeft->Denominator)
// if (pLeft->ErrorTerm + pLeft->Numerator >= pLeft->Denominator) leftWidth++;
// leftWidth++; int rightWidth = pRight->XStep;
// int rightWidth = pRight->XStep; if (pRight->ErrorTerm + pRight->Numerator >= pRight->Denominator)
// if (pRight->ErrorTerm + pRight->Numerator >= pRight->Denominator) rightWidth++;
// rightWidth++; width = max(1, max(abs(leftWidth), abs(rightWidth)));
// width = max(1, min(abs(leftWidth), abs(rightWidth))); }
//
// if (XStart + width > 256)
// width = max(0, 256 - XStart);
//}
//these are the starting values, taken from the left edge //these are the starting values, taken from the left edge
float invw = pLeft->invw.curr; float invw = pLeft->invw.curr;
@ -750,15 +745,18 @@ public:
while(width-- > 0) while(width-- > 0)
{ {
if(RENDERER && (x<0 || x>255)) { bool outOfRange = false;
if(RENDERER && (x<0 || x>255))
outOfRange = true;
if(!RENDERER && (x<0 || x>=engine->width))
outOfRange = true;
if(!lineHack && outOfRange)
{
printf("rasterizer rendering at x=%d! oops!\n",x); printf("rasterizer rendering at x=%d! oops!\n",x);
return; return;
} }
if(!RENDERER && (x<0 || x>=engine->width)) { if(!outOfRange)
printf("rasterizer rendering at x=%d! oops!\n",x); pixel(adr,color[0],color[1],color[2],u,v,1.0f/invw,z);
return;
}
pixel(adr,color[0],color[1],color[2],u,v,1.0f/invw,z);
adr++; adr++;
x++; x++;
@ -774,7 +772,7 @@ public:
//runs several scanlines, until an edge is finished //runs several scanlines, until an edge is finished
template<bool SLI> template<bool SLI>
void runscanlines(edge_fx_fl *left, edge_fx_fl *right,bool horizontal) void runscanlines(edge_fx_fl *left, edge_fx_fl *right, bool horizontal, bool lineHack)
{ {
//oh lord, hack city for edge drawing //oh lord, hack city for edge drawing
@ -785,16 +783,15 @@ public:
runctr++; runctr++;
//HACK: special handling for horizontal line poly //HACK: special handling for horizontal line poly
//Instead of line, this will cause other notable issue. if (lineHack && left->Height == 0 && right->Height == 0)
//if (left->Height == 0 && right->Height == 0) {
//{ bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE);
// bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE); if(draw) drawscanline(left,right,lineHack);
// if(draw) drawscanline(left,right); }
//}
while(Height--) { while(Height--) {
bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE); bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE);
if(draw) drawscanline(left,right); if(draw) drawscanline(left,right,lineHack);
const int xl = left->X; const int xl = left->X;
const int xr = right->X; const int xr = right->X;
const int y = left->Y; const int y = left->Y;
@ -897,7 +894,7 @@ public:
//I didnt reference anything for this algorithm but it seems like I've seen it somewhere before. //I didnt reference anything for this algorithm but it seems like I've seen it somewhere before.
//Maybe it is like crow's algorithm //Maybe it is like crow's algorithm
template<bool SLI> template<bool SLI>
void shape_engine(int type, bool backwards) void shape_engine(int type, bool backwards, bool lineHack)
{ {
bool failure = false; bool failure = false;
@ -935,7 +932,7 @@ public:
return; return;
bool horizontal = left.Y == right.Y; bool horizontal = left.Y == right.Y;
runscanlines<SLI>(&left,&right,horizontal); runscanlines<SLI>(&left,&right,horizontal,lineHack);
//if we ran out of an edge, step to the next one //if we ran out of an edge, step to the next one
if(right.Height == 0) { if(right.Height == 0) {
@ -1005,7 +1002,7 @@ public:
polyAttr.backfacing = engine->polyBackfacing[i]; polyAttr.backfacing = engine->polyBackfacing[i];
shape_engine<SLI>(type,!polyAttr.backfacing); shape_engine<SLI>(type,!polyAttr.backfacing, gfx3d_IsLinePoly(poly));
} }
} }