Reformat all the things. Have fun with merge conflicts.

This commit is contained in:
Pierre Bourdon
2016-06-24 10:43:46 +02:00
parent 2115e8a4a6
commit 3570c7f03a
1116 changed files with 187405 additions and 180344 deletions

View File

@ -35,8 +35,8 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Common/ChunkFile.h"
#include "VideoBackends/Software/Clipper.h"
#include "Common/ChunkFile.h"
#include "VideoBackends/Software/NativeVertexFormat.h"
#include "VideoBackends/Software/Rasterizer.h"
@ -46,399 +46,412 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Clipper
{
enum
{
NUM_CLIPPED_VERTICES = 33,
NUM_INDICES = NUM_CLIPPED_VERTICES + 3
};
static OutputVertexData ClippedVertices[NUM_CLIPPED_VERTICES];
static OutputVertexData *Vertices[NUM_INDICES];
void Init()
{
for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i)
Vertices[i+3] = &ClippedVertices[i];
}
enum
{
SKIP_FLAG = -1,
CLIP_POS_X_BIT = 0x01,
CLIP_NEG_X_BIT = 0x02,
CLIP_POS_Y_BIT = 0x04,
CLIP_NEG_Y_BIT = 0x08,
CLIP_POS_Z_BIT = 0x10,
CLIP_NEG_Z_BIT = 0x20
};
static inline int CalcClipMask(OutputVertexData *v)
{
int cmask = 0;
Vec4 pos = v->projectedPosition;
if (pos.w - pos.x < 0)
cmask |= CLIP_POS_X_BIT;
if (pos.x + pos.w < 0)
cmask |= CLIP_NEG_X_BIT;
if (pos.w - pos.y < 0)
cmask |= CLIP_POS_Y_BIT;
if (pos.y + pos.w < 0)
cmask |= CLIP_NEG_Y_BIT;
if (pos.w * pos.z > 0)
cmask |= CLIP_POS_Z_BIT;
if (pos.z + pos.w < 0)
cmask |= CLIP_NEG_Z_BIT;
return cmask;
}
static inline void AddInterpolatedVertex(float t, int out, int in, int* numVertices)
{
Vertices[(*numVertices)++]->Lerp(t, Vertices[out], Vertices[in]);
}
#define DIFFERENT_SIGNS(x,y) ((x <= 0 && y > 0) || (x > 0 && y <= 0))
#define CLIP_DOTPROD(I, A, B, C, D) \
(Vertices[I]->projectedPosition.x * A + Vertices[I]->projectedPosition.y * B + Vertices[I]->projectedPosition.z * C + Vertices[I]->projectedPosition.w * D)
#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
{ \
if (mask & PLANE_BIT) { \
int idxPrev = inlist[0]; \
float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
int outcount = 0; \
\
inlist[n] = inlist[0]; \
for (int j = 1; j <= n; j++) { \
int idx = inlist[j]; \
float dp = CLIP_DOTPROD(idx, A, B, C, D ); \
if (dpPrev >= 0) { \
outlist[outcount++] = idxPrev; \
} \
\
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
if (dp < 0) { \
float t = dp / (dp - dpPrev); \
AddInterpolatedVertex(t, idx, idxPrev, &numVertices); \
} else { \
float t = dpPrev / (dpPrev - dp); \
AddInterpolatedVertex(t, idxPrev, idx, &numVertices); \
} \
outlist[outcount++] = numVertices - 1; \
} \
\
idxPrev = idx; \
dpPrev = dp; \
} \
\
if (outcount < 3) \
continue; \
\
{ \
int *tmp = inlist; \
inlist = outlist; \
outlist = tmp; \
n = outcount; \
} \
} \
}
#define LINE_CLIP(PLANE_BIT, A, B, C, D ) \
{ \
if (mask & PLANE_BIT) { \
const float dp0 = CLIP_DOTPROD( 0, A, B, C, D ); \
const float dp1 = CLIP_DOTPROD( 1, A, B, C, D ); \
const bool neg_dp0 = dp0 < 0; \
const bool neg_dp1 = dp1 < 0; \
\
if (neg_dp0 && neg_dp1) \
return; \
\
if (neg_dp1) { \
float t = dp1 / (dp1 - dp0); \
if (t > t1) t1 = t; \
} else if (neg_dp0) { \
float t = dp0 / (dp0 - dp1); \
if (t > t0) t0 = t; \
} \
} \
}
static void ClipTriangle(int *indices, int* numIndices)
{
int mask = 0;
mask |= CalcClipMask(Vertices[0]);
mask |= CalcClipMask(Vertices[1]);
mask |= CalcClipMask(Vertices[2]);
if (mask != 0)
{
for (int i = 0; i < 3; i += 3)
{
int vlist[2][2*6+1];
int *inlist = vlist[0], *outlist = vlist[1];
int n = 3;
int numVertices = 3;
inlist[0] = 0;
inlist[1] = 1;
inlist[2] = 2;
// mark this triangle as unused in case it should be completely
// clipped
indices[0] = SKIP_FLAG;
indices[1] = SKIP_FLAG;
indices[2] = SKIP_FLAG;
POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1);
POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
INCSTAT(stats.thisFrame.numTrianglesClipped);
// transform the poly in inlist into triangles
indices[0] = inlist[0];
indices[1] = inlist[1];
indices[2] = inlist[2];
for (int j = 3; j < n; ++j)
{
indices[(*numIndices)++] = inlist[0];
indices[(*numIndices)++] = inlist[j - 1];
indices[(*numIndices)++] = inlist[j];
}
}
}
}
static void ClipLine(int *indices)
{
int mask = 0;
int clip_mask[2] = { 0, 0 };
for (int i = 0; i < 2; ++i)
{
clip_mask[i] = CalcClipMask(Vertices[i]);
mask |= clip_mask[i];
}
if (mask == 0)
return;
float t0 = 0;
float t1 = 0;
// Mark unused in case of early termination
// of the macros below. (When fully clipped)
indices[0] = SKIP_FLAG;
indices[1] = SKIP_FLAG;
LINE_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
LINE_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
LINE_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
LINE_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
LINE_CLIP(CLIP_POS_Z_BIT, 0, 0, -1, 1);
LINE_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
// Restore the old values as this line
// was not fully clipped.
indices[0] = 0;
indices[1] = 1;
int numVertices = 2;
if (clip_mask[0])
{
indices[0] = numVertices;
AddInterpolatedVertex(t0, 0, 1, &numVertices);
}
if (clip_mask[1])
{
indices[1] = numVertices;
AddInterpolatedVertex(t1, 1, 0, &numVertices);
}
}
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
{
INCSTAT(stats.thisFrame.numTrianglesIn)
bool backface;
if (!CullTest(v0, v1, v2, backface))
return;
int indices[NUM_INDICES] = {
0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG
};
int numIndices = 3;
if (backface)
{
Vertices[0] = v0;
Vertices[1] = v2;
Vertices[2] = v1;
}
else
{
Vertices[0] = v0;
Vertices[1] = v1;
Vertices[2] = v2;
}
ClipTriangle(indices, &numIndices);
for (int i = 0; i+3 <= numIndices; i+=3)
{
_assert_(i < NUM_INDICES);
if (indices[i] != SKIP_FLAG)
{
PerspectiveDivide(Vertices[indices[i]]);
PerspectiveDivide(Vertices[indices[i+1]]);
PerspectiveDivide(Vertices[indices[i+2]]);
Rasterizer::DrawTriangleFrontFace(Vertices[indices[i]], Vertices[indices[i+1]], Vertices[indices[i+2]]);
}
}
}
static void CopyVertex(OutputVertexData *dst, OutputVertexData *src, float dx, float dy, unsigned int sOffset)
{
dst->screenPosition.x = src->screenPosition.x + dx;
dst->screenPosition.y = src->screenPosition.y + dy;
dst->screenPosition.z = src->screenPosition.z;
for (int i = 0; i < 3; ++i)
dst->normal[i] = src->normal[i];
for (int i = 0; i < 4; ++i)
dst->color[0][i] = src->color[0][i];
// todo - s offset
for (int i = 0; i < 8; ++i)
dst->texCoords[i] = src->texCoords[i];
}
void ProcessLine(OutputVertexData *lineV0, OutputVertexData *lineV1)
{
int indices[4] = { 0, 1, SKIP_FLAG, SKIP_FLAG };
Vertices[0] = lineV0;
Vertices[1] = lineV1;
// point to a valid vertex to store to when clipping
Vertices[2] = &ClippedVertices[17];
ClipLine(indices);
if (indices[0] != SKIP_FLAG)
{
OutputVertexData *v0 = Vertices[indices[0]];
OutputVertexData *v1 = Vertices[indices[1]];
PerspectiveDivide(v0);
PerspectiveDivide(v1);
float dx = v1->screenPosition.x - v0->screenPosition.x;
float dy = v1->screenPosition.y - v0->screenPosition.y;
float screenDx = 0;
float screenDy = 0;
if (fabsf(dx) > fabsf(dy))
{
if (dx > 0)
screenDy = bpmem.lineptwidth.linesize / -12.0f;
else
screenDy = bpmem.lineptwidth.linesize / 12.0f;
}
else
{
if (dy > 0)
screenDx = bpmem.lineptwidth.linesize / 12.0f;
else
screenDx = bpmem.lineptwidth.linesize / -12.0f;
}
OutputVertexData triangle[3];
CopyVertex(&triangle[0], v0, screenDx, screenDy, 0);
CopyVertex(&triangle[1], v1, screenDx, screenDy, 0);
CopyVertex(&triangle[2], v1, -screenDx, -screenDy, bpmem.lineptwidth.lineoff);
// ccw winding
Rasterizer::DrawTriangleFrontFace(&triangle[2], &triangle[1], &triangle[0]);
CopyVertex(&triangle[1], v0, -screenDx, -screenDy, bpmem.lineptwidth.lineoff);
Rasterizer::DrawTriangleFrontFace(&triangle[0], &triangle[1], &triangle[2]);
}
}
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface)
{
int mask = CalcClipMask(v0);
mask &= CalcClipMask(v1);
mask &= CalcClipMask(v2);
if (mask)
{
INCSTAT(stats.thisFrame.numTrianglesRejected)
return false;
}
float x0 = v0->projectedPosition.x;
float x1 = v1->projectedPosition.x;
float x2 = v2->projectedPosition.x;
float y1 = v1->projectedPosition.y;
float y0 = v0->projectedPosition.y;
float y2 = v2->projectedPosition.y;
float w0 = v0->projectedPosition.w;
float w1 = v1->projectedPosition.w;
float w2 = v2->projectedPosition.w;
float normalZDir = (x0*w2 - x2*w0)*y1 + (x2*y0 - x0*y2)*w1 + (y2*w0 - y0*w2)*x1;
backface = normalZDir <= 0.0f;
if ((bpmem.genMode.cullmode & 1) && !backface) // cull frontfacing
{
INCSTAT(stats.thisFrame.numTrianglesCulled)
return false;
}
if ((bpmem.genMode.cullmode & 2) && backface) // cull backfacing
{
INCSTAT(stats.thisFrame.numTrianglesCulled)
return false;
}
return true;
}
void PerspectiveDivide(OutputVertexData *vertex)
{
Vec4 &projected = vertex->projectedPosition;
Vec3 &screen = vertex->screenPosition;
float wInverse = 1.0f/projected.w;
screen.x = projected.x * wInverse * xfmem.viewport.wd + xfmem.viewport.xOrig - 342;
screen.y = projected.y * wInverse * xfmem.viewport.ht + xfmem.viewport.yOrig - 342;
screen.z = projected.z * wInverse * xfmem.viewport.zRange + xfmem.viewport.farZ;
}
enum
{
NUM_CLIPPED_VERTICES = 33,
NUM_INDICES = NUM_CLIPPED_VERTICES + 3
};
static OutputVertexData ClippedVertices[NUM_CLIPPED_VERTICES];
static OutputVertexData* Vertices[NUM_INDICES];
void Init()
{
for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i)
Vertices[i + 3] = &ClippedVertices[i];
}
enum
{
SKIP_FLAG = -1,
CLIP_POS_X_BIT = 0x01,
CLIP_NEG_X_BIT = 0x02,
CLIP_POS_Y_BIT = 0x04,
CLIP_NEG_Y_BIT = 0x08,
CLIP_POS_Z_BIT = 0x10,
CLIP_NEG_Z_BIT = 0x20
};
static inline int CalcClipMask(OutputVertexData* v)
{
int cmask = 0;
Vec4 pos = v->projectedPosition;
if (pos.w - pos.x < 0)
cmask |= CLIP_POS_X_BIT;
if (pos.x + pos.w < 0)
cmask |= CLIP_NEG_X_BIT;
if (pos.w - pos.y < 0)
cmask |= CLIP_POS_Y_BIT;
if (pos.y + pos.w < 0)
cmask |= CLIP_NEG_Y_BIT;
if (pos.w * pos.z > 0)
cmask |= CLIP_POS_Z_BIT;
if (pos.z + pos.w < 0)
cmask |= CLIP_NEG_Z_BIT;
return cmask;
}
static inline void AddInterpolatedVertex(float t, int out, int in, int* numVertices)
{
Vertices[(*numVertices)++]->Lerp(t, Vertices[out], Vertices[in]);
}
#define DIFFERENT_SIGNS(x, y) ((x <= 0 && y > 0) || (x > 0 && y <= 0))
#define CLIP_DOTPROD(I, A, B, C, D) \
(Vertices[I]->projectedPosition.x * A + Vertices[I]->projectedPosition.y * B + \
Vertices[I]->projectedPosition.z * C + Vertices[I]->projectedPosition.w * D)
#define POLY_CLIP(PLANE_BIT, A, B, C, D) \
{ \
if (mask & PLANE_BIT) \
{ \
int idxPrev = inlist[0]; \
float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D); \
int outcount = 0; \
\
inlist[n] = inlist[0]; \
for (int j = 1; j <= n; j++) \
{ \
int idx = inlist[j]; \
float dp = CLIP_DOTPROD(idx, A, B, C, D); \
if (dpPrev >= 0) \
{ \
outlist[outcount++] = idxPrev; \
} \
\
if (DIFFERENT_SIGNS(dp, dpPrev)) \
{ \
if (dp < 0) \
{ \
float t = dp / (dp - dpPrev); \
AddInterpolatedVertex(t, idx, idxPrev, &numVertices); \
} \
else \
{ \
float t = dpPrev / (dpPrev - dp); \
AddInterpolatedVertex(t, idxPrev, idx, &numVertices); \
} \
outlist[outcount++] = numVertices - 1; \
} \
\
idxPrev = idx; \
dpPrev = dp; \
} \
\
if (outcount < 3) \
continue; \
\
{ \
int* tmp = inlist; \
inlist = outlist; \
outlist = tmp; \
n = outcount; \
} \
} \
}
#define LINE_CLIP(PLANE_BIT, A, B, C, D) \
{ \
if (mask & PLANE_BIT) \
{ \
const float dp0 = CLIP_DOTPROD(0, A, B, C, D); \
const float dp1 = CLIP_DOTPROD(1, A, B, C, D); \
const bool neg_dp0 = dp0 < 0; \
const bool neg_dp1 = dp1 < 0; \
\
if (neg_dp0 && neg_dp1) \
return; \
\
if (neg_dp1) \
{ \
float t = dp1 / (dp1 - dp0); \
if (t > t1) \
t1 = t; \
} \
else if (neg_dp0) \
{ \
float t = dp0 / (dp0 - dp1); \
if (t > t0) \
t0 = t; \
} \
} \
}
static void ClipTriangle(int* indices, int* numIndices)
{
int mask = 0;
mask |= CalcClipMask(Vertices[0]);
mask |= CalcClipMask(Vertices[1]);
mask |= CalcClipMask(Vertices[2]);
if (mask != 0)
{
for (int i = 0; i < 3; i += 3)
{
int vlist[2][2 * 6 + 1];
int *inlist = vlist[0], *outlist = vlist[1];
int n = 3;
int numVertices = 3;
inlist[0] = 0;
inlist[1] = 1;
inlist[2] = 2;
// mark this triangle as unused in case it should be completely
// clipped
indices[0] = SKIP_FLAG;
indices[1] = SKIP_FLAG;
indices[2] = SKIP_FLAG;
POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1);
POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
INCSTAT(stats.thisFrame.numTrianglesClipped);
// transform the poly in inlist into triangles
indices[0] = inlist[0];
indices[1] = inlist[1];
indices[2] = inlist[2];
for (int j = 3; j < n; ++j)
{
indices[(*numIndices)++] = inlist[0];
indices[(*numIndices)++] = inlist[j - 1];
indices[(*numIndices)++] = inlist[j];
}
}
}
}
static void ClipLine(int* indices)
{
int mask = 0;
int clip_mask[2] = {0, 0};
for (int i = 0; i < 2; ++i)
{
clip_mask[i] = CalcClipMask(Vertices[i]);
mask |= clip_mask[i];
}
if (mask == 0)
return;
float t0 = 0;
float t1 = 0;
// Mark unused in case of early termination
// of the macros below. (When fully clipped)
indices[0] = SKIP_FLAG;
indices[1] = SKIP_FLAG;
LINE_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
LINE_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
LINE_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
LINE_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
LINE_CLIP(CLIP_POS_Z_BIT, 0, 0, -1, 1);
LINE_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
// Restore the old values as this line
// was not fully clipped.
indices[0] = 0;
indices[1] = 1;
int numVertices = 2;
if (clip_mask[0])
{
indices[0] = numVertices;
AddInterpolatedVertex(t0, 0, 1, &numVertices);
}
if (clip_mask[1])
{
indices[1] = numVertices;
AddInterpolatedVertex(t1, 1, 0, &numVertices);
}
}
void ProcessTriangle(OutputVertexData* v0, OutputVertexData* v1, OutputVertexData* v2)
{
INCSTAT(stats.thisFrame.numTrianglesIn)
bool backface;
if (!CullTest(v0, v1, v2, backface))
return;
int indices[NUM_INDICES] = {0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG};
int numIndices = 3;
if (backface)
{
Vertices[0] = v0;
Vertices[1] = v2;
Vertices[2] = v1;
}
else
{
Vertices[0] = v0;
Vertices[1] = v1;
Vertices[2] = v2;
}
ClipTriangle(indices, &numIndices);
for (int i = 0; i + 3 <= numIndices; i += 3)
{
_assert_(i < NUM_INDICES);
if (indices[i] != SKIP_FLAG)
{
PerspectiveDivide(Vertices[indices[i]]);
PerspectiveDivide(Vertices[indices[i + 1]]);
PerspectiveDivide(Vertices[indices[i + 2]]);
Rasterizer::DrawTriangleFrontFace(Vertices[indices[i]], Vertices[indices[i + 1]],
Vertices[indices[i + 2]]);
}
}
}
static void CopyVertex(OutputVertexData* dst, OutputVertexData* src, float dx, float dy,
unsigned int sOffset)
{
dst->screenPosition.x = src->screenPosition.x + dx;
dst->screenPosition.y = src->screenPosition.y + dy;
dst->screenPosition.z = src->screenPosition.z;
for (int i = 0; i < 3; ++i)
dst->normal[i] = src->normal[i];
for (int i = 0; i < 4; ++i)
dst->color[0][i] = src->color[0][i];
// todo - s offset
for (int i = 0; i < 8; ++i)
dst->texCoords[i] = src->texCoords[i];
}
void ProcessLine(OutputVertexData* lineV0, OutputVertexData* lineV1)
{
int indices[4] = {0, 1, SKIP_FLAG, SKIP_FLAG};
Vertices[0] = lineV0;
Vertices[1] = lineV1;
// point to a valid vertex to store to when clipping
Vertices[2] = &ClippedVertices[17];
ClipLine(indices);
if (indices[0] != SKIP_FLAG)
{
OutputVertexData* v0 = Vertices[indices[0]];
OutputVertexData* v1 = Vertices[indices[1]];
PerspectiveDivide(v0);
PerspectiveDivide(v1);
float dx = v1->screenPosition.x - v0->screenPosition.x;
float dy = v1->screenPosition.y - v0->screenPosition.y;
float screenDx = 0;
float screenDy = 0;
if (fabsf(dx) > fabsf(dy))
{
if (dx > 0)
screenDy = bpmem.lineptwidth.linesize / -12.0f;
else
screenDy = bpmem.lineptwidth.linesize / 12.0f;
}
else
{
if (dy > 0)
screenDx = bpmem.lineptwidth.linesize / 12.0f;
else
screenDx = bpmem.lineptwidth.linesize / -12.0f;
}
OutputVertexData triangle[3];
CopyVertex(&triangle[0], v0, screenDx, screenDy, 0);
CopyVertex(&triangle[1], v1, screenDx, screenDy, 0);
CopyVertex(&triangle[2], v1, -screenDx, -screenDy, bpmem.lineptwidth.lineoff);
// ccw winding
Rasterizer::DrawTriangleFrontFace(&triangle[2], &triangle[1], &triangle[0]);
CopyVertex(&triangle[1], v0, -screenDx, -screenDy, bpmem.lineptwidth.lineoff);
Rasterizer::DrawTriangleFrontFace(&triangle[0], &triangle[1], &triangle[2]);
}
}
bool CullTest(OutputVertexData* v0, OutputVertexData* v1, OutputVertexData* v2, bool& backface)
{
int mask = CalcClipMask(v0);
mask &= CalcClipMask(v1);
mask &= CalcClipMask(v2);
if (mask)
{
INCSTAT(stats.thisFrame.numTrianglesRejected)
return false;
}
float x0 = v0->projectedPosition.x;
float x1 = v1->projectedPosition.x;
float x2 = v2->projectedPosition.x;
float y1 = v1->projectedPosition.y;
float y0 = v0->projectedPosition.y;
float y2 = v2->projectedPosition.y;
float w0 = v0->projectedPosition.w;
float w1 = v1->projectedPosition.w;
float w2 = v2->projectedPosition.w;
float normalZDir = (x0 * w2 - x2 * w0) * y1 + (x2 * y0 - x0 * y2) * w1 + (y2 * w0 - y0 * w2) * x1;
backface = normalZDir <= 0.0f;
if ((bpmem.genMode.cullmode & 1) && !backface) // cull frontfacing
{
INCSTAT(stats.thisFrame.numTrianglesCulled)
return false;
}
if ((bpmem.genMode.cullmode & 2) && backface) // cull backfacing
{
INCSTAT(stats.thisFrame.numTrianglesCulled)
return false;
}
return true;
}
void PerspectiveDivide(OutputVertexData* vertex)
{
Vec4& projected = vertex->projectedPosition;
Vec3& screen = vertex->screenPosition;
float wInverse = 1.0f / projected.w;
screen.x = projected.x * wInverse * xfmem.viewport.wd + xfmem.viewport.xOrig - 342;
screen.y = projected.y * wInverse * xfmem.viewport.ht + xfmem.viewport.yOrig - 342;
screen.z = projected.z * wInverse * xfmem.viewport.zRange + xfmem.viewport.farZ;
}
}