mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-02-27 13:41:06 +00:00
- Handle degenerate triangles either sent as input or caused by clipping
This commit is contained in:
parent
7ad61a97ed
commit
f492e92cb5
3 changed files with 43 additions and 22 deletions
|
@ -152,8 +152,28 @@ ShadedTriVertex PolyTriangleDrawer::shade_vertex(const TriMatrix &objectToClip,
|
||||||
return sv;
|
return sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PolyTriangleDrawer::is_degenerate(const ShadedTriVertex *vert)
|
||||||
|
{
|
||||||
|
// A degenerate triangle has a zero cross product for two of its sides.
|
||||||
|
float ax = vert[1].x - vert[0].x;
|
||||||
|
float ay = vert[1].y - vert[0].y;
|
||||||
|
float az = vert[1].w - vert[0].w;
|
||||||
|
float bx = vert[2].x - vert[0].x;
|
||||||
|
float by = vert[2].y - vert[0].y;
|
||||||
|
float bz = vert[2].w - vert[0].w;
|
||||||
|
float crossx = ay * bz - az * by;
|
||||||
|
float crossy = az * bx - ax * bz;
|
||||||
|
float crossz = ax * by - ay * bx;
|
||||||
|
float crosslengthsqr = crossx * crossx + crossy * crossy + crossz * crossz;
|
||||||
|
return crosslengthsqr <= 1.e-6f;
|
||||||
|
}
|
||||||
|
|
||||||
void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread)
|
void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread)
|
||||||
{
|
{
|
||||||
|
// Reject triangle if degenerate
|
||||||
|
if (is_degenerate(vert))
|
||||||
|
return;
|
||||||
|
|
||||||
// Cull, clip and generate additional vertices as needed
|
// Cull, clip and generate additional vertices as needed
|
||||||
TriVertex clippedvert[max_additional_vertices];
|
TriVertex clippedvert[max_additional_vertices];
|
||||||
int numclipvert = clipedge(vert, clippedvert);
|
int numclipvert = clipedge(vert, clippedvert);
|
||||||
|
@ -224,14 +244,13 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool
|
||||||
// Draw screen triangles
|
// Draw screen triangles
|
||||||
if (ccw)
|
if (ccw)
|
||||||
{
|
{
|
||||||
for (int i = numclipvert; i > 1; i--)
|
for (int i = numclipvert - 1; i > 1; i--)
|
||||||
{
|
{
|
||||||
args->v1 = &clippedvert[numclipvert - 1];
|
args->v1 = &clippedvert[numclipvert - 1];
|
||||||
args->v2 = &clippedvert[i - 1];
|
args->v2 = &clippedvert[i - 1];
|
||||||
args->v3 = &clippedvert[i - 2];
|
args->v3 = &clippedvert[i - 2];
|
||||||
args->CalculateGradients();
|
if (args->CalculateGradients())
|
||||||
|
ScreenTriangle::Draw(args, thread);
|
||||||
ScreenTriangle::Draw(args, thread);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -241,9 +260,8 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool
|
||||||
args->v1 = &clippedvert[0];
|
args->v1 = &clippedvert[0];
|
||||||
args->v2 = &clippedvert[i - 1];
|
args->v2 = &clippedvert[i - 1];
|
||||||
args->v3 = &clippedvert[i];
|
args->v3 = &clippedvert[i];
|
||||||
args->CalculateGradients();
|
if (args->CalculateGradients())
|
||||||
|
ScreenTriangle::Draw(args, thread);
|
||||||
ScreenTriangle::Draw(args, thread);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ private:
|
||||||
static ShadedTriVertex shade_vertex(const TriMatrix &objectToClip, const float *clipPlane, const TriVertex &v);
|
static ShadedTriVertex shade_vertex(const TriMatrix &objectToClip, const float *clipPlane, const TriVertex &v);
|
||||||
static void draw_arrays(const PolyDrawArgs &args, WorkerThreadData *thread);
|
static void draw_arrays(const PolyDrawArgs &args, WorkerThreadData *thread);
|
||||||
static void draw_shaded_triangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread);
|
static void draw_shaded_triangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread);
|
||||||
|
static bool is_degenerate(const ShadedTriVertex *vertices);
|
||||||
|
|
||||||
static int clipedge(const ShadedTriVertex *verts, TriVertex *clippedvert);
|
static int clipedge(const ShadedTriVertex *verts, TriVertex *clippedvert);
|
||||||
|
|
||||||
|
|
|
@ -66,29 +66,31 @@ struct TriDrawTriangleArgs
|
||||||
ScreenTriangleStepVariables gradientX;
|
ScreenTriangleStepVariables gradientX;
|
||||||
ScreenTriangleStepVariables gradientY;
|
ScreenTriangleStepVariables gradientY;
|
||||||
|
|
||||||
void CalculateGradients()
|
bool CalculateGradients()
|
||||||
{
|
{
|
||||||
gradientX.W = FindGradientX(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y, v1->w, v2->w, v3->w);
|
float bottomX = (v2->x - v3->x) * (v1->y - v3->y) - (v1->x - v3->x) * (v2->y - v3->y);
|
||||||
gradientY.W = FindGradientY(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y, v1->w, v2->w, v3->w);
|
float bottomY = (v1->x - v3->x) * (v2->y - v3->y) - (v2->x - v3->x) * (v1->y - v3->y);
|
||||||
gradientX.U = FindGradientX(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y, v1->u * v1->w, v2->u * v2->w, v3->u * v3->w);
|
if ((bottomX >= -FLT_EPSILON && bottomX <= FLT_EPSILON) || (bottomY >= -FLT_EPSILON && bottomY <= FLT_EPSILON))
|
||||||
gradientY.U = FindGradientY(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y, v1->u * v1->w, v2->u * v2->w, v3->u * v3->w);
|
return false;
|
||||||
gradientX.V = FindGradientX(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y, v1->v * v1->w, v2->v * v2->w, v3->v * v3->w);
|
|
||||||
gradientY.V = FindGradientY(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y, v1->v * v1->w, v2->v * v2->w, v3->v * v3->w);
|
gradientX.W = FindGradientX(bottomX, v1->w, v2->w, v3->w);
|
||||||
|
gradientY.W = FindGradientY(bottomY, v1->w, v2->w, v3->w);
|
||||||
|
gradientX.U = FindGradientX(bottomX, v1->u * v1->w, v2->u * v2->w, v3->u * v3->w);
|
||||||
|
gradientY.U = FindGradientY(bottomY, v1->u * v1->w, v2->u * v2->w, v3->u * v3->w);
|
||||||
|
gradientX.V = FindGradientX(bottomX, v1->v * v1->w, v2->v * v2->w, v3->v * v3->w);
|
||||||
|
gradientY.V = FindGradientY(bottomY, v1->v * v1->w, v2->v * v2->w, v3->v * v3->w);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static float FindGradientX(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2)
|
float FindGradientX(float bottomX, float c0, float c1, float c2)
|
||||||
{
|
{
|
||||||
float top = (c1 - c2) * (y0 - y2) - (c0 - c2) * (y1 - y2);
|
return ((c1 - c2) * (v1->y - v3->y) - (c0 - c2) * (v2->y - v3->y)) / bottomX;
|
||||||
float bottom = (x1 - x2) * (y0 - y2) - (x0 - x2) * (y1 - y2);
|
|
||||||
return top / bottom;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static float FindGradientY(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2)
|
float FindGradientY(float bottomY, float c0, float c1, float c2)
|
||||||
{
|
{
|
||||||
float top = (c1 - c2) * (x0 - x2) - (c0 - c2) * (x1 - x2);
|
return ((c1 - c2) * (v1->x - v3->x) - (c0 - c2) * (v2->x - v3->x)) / bottomY;
|
||||||
float bottom = (x0 - x2) * (y1 - y2) - (x1 - x2) * (y0 - y2);
|
|
||||||
return top / bottom;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue