Add triangle fan and strip

This commit is contained in:
Magnus Norddahl 2016-10-31 08:30:08 +01:00
parent a1ba371eed
commit 7a9c674f83
2 changed files with 130 additions and 88 deletions

View file

@ -36,28 +36,80 @@
#include "r_data/colormaps.h"
#include "r_triangle.h"
void TriangleDrawer::draw(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture)
void TriangleDrawer::draw(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture)
{
draw_any(objectToWorld, vinput, vcount, ccw, clipleft, clipright, cliptop, clipbottom, texture, 0, &ScreenTriangleDrawer::draw);
draw_arrays(objectToWorld, vinput, vcount, mode, ccw, clipleft, clipright, cliptop, clipbottom, texture, 0, &ScreenTriangleDrawer::draw);
}
void TriangleDrawer::fill(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, int solidcolor)
void TriangleDrawer::fill(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, int solidcolor)
{
draw_any(objectToWorld, vinput, vcount, ccw, clipleft, clipright, cliptop, clipbottom, nullptr, solidcolor, &ScreenTriangleDrawer::fill);
draw_arrays(objectToWorld, vinput, vcount, mode, ccw, clipleft, clipright, cliptop, clipbottom, nullptr, solidcolor, &ScreenTriangleDrawer::fill);
}
void TriangleDrawer::draw_any(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture, int solidcolor, void(*drawfunc)(const ScreenTriangleDrawerArgs *))
void TriangleDrawer::draw_arrays(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture, int solidcolor, void(*drawfunc)(const ScreenTriangleDrawerArgs *))
{
if (vcount < 3)
return;
ScreenTriangleDrawerArgs args;
args.dest = dc_destorg;
args.pitch = dc_pitch;
args.clipleft = clipleft;
args.clipright = clipright;
args.cliptop = cliptop;
args.clipbottom = clipbottom;
if (texture)
{
args.textureWidth = texture->GetWidth();
args.textureHeight = texture->GetHeight();
args.texturePixels = texture->GetPixels();
}
else
{
args.textureWidth = 0;
args.textureHeight = 0;
args.texturePixels = nullptr;
}
args.solidcolor = solidcolor;
TriVertex vert[3];
if (mode == TriangleDrawMode::Normal)
{
for (int i = 0; i < vcount / 3; i++)
{
TriVertex vert[3];
// Vertex shader stuff:
for (int j = 0; j < 3; j++)
vert[j] = shade_vertex(objectToWorld, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, drawfunc);
}
}
else if (mode == TriangleDrawMode::Fan)
{
auto &v = vert[j];
v = *(vinput++);
vert[0] = shade_vertex(objectToWorld, *(vinput++));
vert[1] = shade_vertex(objectToWorld, *(vinput++));
for (int i = 2; i < vcount; i++)
{
vert[2] = shade_vertex(objectToWorld, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, drawfunc);
vert[1] = vert[2];
}
}
else // TriangleDrawMode::Strip
{
vert[0] = shade_vertex(objectToWorld, *(vinput++));
vert[1] = shade_vertex(objectToWorld, *(vinput++));
for (int i = 2; i < vcount; i++)
{
vert[2] = shade_vertex(objectToWorld, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, drawfunc);
vert[0] = vert[1];
vert[1] = vert[2];
ccw = !ccw;
}
}
}
TriVertex TriangleDrawer::shade_vertex(const TriMatrix &objectToWorld, TriVertex v)
{
// Apply transform to get world coordinates:
v = objectToWorld * v;
@ -73,8 +125,12 @@ void TriangleDrawer::draw_any(const TriMatrix &objectToWorld, const TriVertex *v
v.y = (float)tr_z * 0.5f;
v.z = (float)((-tz * (farp + nearp) / (nearp - farp) + (2.0f * farp * nearp) / (nearp - farp)));
v.w = (float)tz;
return v;
}
void TriangleDrawer::draw_shaded_triangle(const TriVertex *vert, bool ccw, ScreenTriangleDrawerArgs *args, void(*drawfunc)(const ScreenTriangleDrawerArgs *))
{
// Cull, clip and generate additional vertices as needed
TriVertex clippedvert[6];
int numclipvert = 0;
@ -99,47 +155,24 @@ void TriangleDrawer::draw_any(const TriMatrix &objectToWorld, const TriVertex *v
}
// Draw screen triangles
ScreenTriangleDrawerArgs args;
args.dest = dc_destorg;
args.pitch = dc_pitch;
args.clipleft = clipleft;
args.clipright = clipright;
args.cliptop = cliptop;
args.clipbottom = clipbottom;
if (texture)
{
args.textureWidth = texture->GetWidth();
args.textureHeight = texture->GetHeight();
args.texturePixels = texture->GetPixels();
}
else
{
args.textureWidth = 0;
args.textureHeight = 0;
args.texturePixels = nullptr;
}
args.solidcolor = solidcolor;
if (ccw)
{
for (int i = numclipvert; i > 1; i--)
{
args.v1 = &clippedvert[numclipvert - 1];
args.v2 = &clippedvert[i - 1];
args.v3 = &clippedvert[i - 2];
drawfunc(&args);
args->v1 = &clippedvert[numclipvert - 1];
args->v2 = &clippedvert[i - 1];
args->v3 = &clippedvert[i - 2];
drawfunc(args);
}
}
else
{
for (int i = 2; i < numclipvert; i++)
{
args.v1 = &clippedvert[0];
args.v2 = &clippedvert[i - 1];
args.v3 = &clippedvert[i];
drawfunc(&args);
}
args->v1 = &clippedvert[0];
args->v2 = &clippedvert[i - 1];
args->v3 = &clippedvert[i];
drawfunc(args);
}
}
}

View file

@ -53,14 +53,23 @@ struct TriMatrix
float matrix[16];
};
enum class TriangleDrawMode
{
Normal,
Fan,
Strip
};
class TriangleDrawer
{
public:
static void draw(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture);
static void fill(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, int solidcolor);
static void draw(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture);
static void fill(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, int solidcolor);
private:
static void draw_any(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture, int solidcolor, void(*drawfunc)(const ScreenTriangleDrawerArgs *));
static TriVertex shade_vertex(const TriMatrix &objectToWorld, TriVertex v);
static void draw_arrays(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture, int solidcolor, void(*drawfunc)(const ScreenTriangleDrawerArgs *));
static void draw_shaded_triangle(const TriVertex *vertices, bool ccw, ScreenTriangleDrawerArgs *args, void(*drawfunc)(const ScreenTriangleDrawerArgs *));
static bool cullhalfspace(float clipdistance1, float clipdistance2, float &t1, float &t2);
static void clipedge(const TriVertex &v1, const TriVertex &v2, TriVertex *clippedvert, int &numclipvert);
};