DS GX: Automatically normalize winding culling calculations (fixes #699)
Vicki Pfau vi@endrift.com
Thu, 27 Apr 2017 02:50:23 -0700
3 files changed,
70 insertions(+),
3 deletions(-)
M
include/mgba-util/math.h
→
include/mgba-util/math.h
@@ -53,6 +53,51 @@ return table[bits] + 24;
#endif } +static inline unsigned clz64(uint64_t bits) { +#if defined(__GNUC__) || __clang__ + if (!bits) { + return 64; + } + return __builtin_clzll(bits); +#else + static const int table[256] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + if (bits & 0xFF00000000000000) { + return table[bits >> 56]; + } else if (bits & 0x00FF000000000000) { + return table[bits >> 48] + 8; + } else if (bits & 0x0000FF0000000000) { + return table[bits >> 40] + 16; + } else if (bits & 0x000000FF00000000) { + return table[bits >> 32] + 24; + } else if (bits & 0x00000000FF000000) { + return table[bits >> 24] + 32; + } else if (bits & 0x0000000000FF0000) { + return table[bits >> 16] + 40; + } else if (bits & 0x000000000000FF00) { + return table[bits >> 8] + 48; + } + return table[bits] + 56; +#endif +} + static inline uint32_t toPow2(uint32_t bits) { if (!bits) { return 0;
M
src/ds/gx.c
→
src/ds/gx.c
@@ -7,6 +7,7 @@ #include <mgba/internal/ds/gx.h>
#include <mgba/internal/ds/ds.h> #include <mgba/internal/ds/io.h> +#include <mgba-util/math.h> mLOG_DEFINE_CATEGORY(DS_GX, "DS GX", "ds.gx");@@ -237,6 +238,7 @@ int64_t nx = 0;
int64_t ny = 0; int64_t nz = 0; int64_t dot = 0; + int rank = 30; for (v = 0; v < poly->verts; ++v) { struct DSGXVertex* v0 = &gx->pendingVertices[poly->vertIds[v]]; struct DSGXVertex* v1;@@ -251,9 +253,28 @@ } else {
v1 = &gx->pendingVertices[poly->vertIds[v + 1 - poly->verts]]; v2 = &gx->pendingVertices[poly->vertIds[v + 2 - poly->verts]]; } - nx = ((int64_t) v0->viewCoord[1] * v2->viewCoord[3] - (int64_t) v0->viewCoord[3] * v2->viewCoord[1]) >> 24; - ny = ((int64_t) v0->viewCoord[3] * v2->viewCoord[0] - (int64_t) v0->viewCoord[0] * v2->viewCoord[3]) >> 24; - nz = ((int64_t) v0->viewCoord[0] * v2->viewCoord[1] - (int64_t) v0->viewCoord[1] * v2->viewCoord[0]) >> 24; + nx = ((int64_t) v0->viewCoord[1] * v2->viewCoord[3] - (int64_t) v0->viewCoord[3] * v2->viewCoord[1]); + ny = ((int64_t) v0->viewCoord[3] * v2->viewCoord[0] - (int64_t) v0->viewCoord[0] * v2->viewCoord[3]); + nz = ((int64_t) v0->viewCoord[0] * v2->viewCoord[1] - (int64_t) v0->viewCoord[1] * v2->viewCoord[0]); + int rx = 64 - clz64(nx >= 0 ? nx : -nx); + int ry = 64 - clz64(ny >= 0 ? ny : -ny); + int rz = 64 - clz64(nz >= 0 ? nz : -nz); + if (ry > rx) { + rx = ry; + } + if (rz > rx) { + rx = rz; + } + if (rx > 30) { + nx >>= rx - 30; + ny >>= rx - 30; + nz >>= rx - 30; + } + if (rx > rank) { + dot >>= rx - rank; + rank = rx; + } + dot += nx * v1->viewCoord[0] + ny * v1->viewCoord[1] + nz * v1->viewCoord[3]; } if (!DSGXPolygonAttrsIsBackFace(poly->polyParams) && dot < 0) {