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_data/colormaps.h"
#include "r_triangle.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++) for (int i = 0; i < vcount / 3; i++)
{ {
TriVertex vert[3];
// Vertex shader stuff:
for (int j = 0; j < 3; j++) 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]; vert[0] = shade_vertex(objectToWorld, *(vinput++));
v = *(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: // Apply transform to get world coordinates:
v = objectToWorld * v; 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.y = (float)tr_z * 0.5f;
v.z = (float)((-tz * (farp + nearp) / (nearp - farp) + (2.0f * farp * nearp) / (nearp - farp))); v.z = (float)((-tz * (farp + nearp) / (nearp - farp) + (2.0f * farp * nearp) / (nearp - farp)));
v.w = (float)tz; 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 // Cull, clip and generate additional vertices as needed
TriVertex clippedvert[6]; TriVertex clippedvert[6];
int numclipvert = 0; int numclipvert = 0;
@ -99,47 +155,24 @@ void TriangleDrawer::draw_any(const TriMatrix &objectToWorld, const TriVertex *v
} }
// Draw screen triangles // 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) if (ccw)
{ {
for (int i = numclipvert; i > 1; i--) for (int i = numclipvert; 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];
drawfunc(&args); drawfunc(args);
} }
} }
else else
{ {
for (int i = 2; i < numclipvert; i++) for (int i = 2; i < numclipvert; i++)
{ {
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];
drawfunc(&args); drawfunc(args);
}
} }
} }
} }

View file

@ -53,14 +53,23 @@ struct TriMatrix
float matrix[16]; float matrix[16];
}; };
enum class TriangleDrawMode
{
Normal,
Fan,
Strip
};
class TriangleDrawer class TriangleDrawer
{ {
public: 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 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, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, int solidcolor); 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: 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 bool cullhalfspace(float clipdistance1, float clipdistance2, float &t1, float &t2);
static void clipedge(const TriVertex &v1, const TriVertex &v2, TriVertex *clippedvert, int &numclipvert); static void clipedge(const TriVertex &v1, const TriVertex &v2, TriVertex *clippedvert, int &numclipvert);
}; };