DS GX: Partial polygon clipping

This commit is contained in:
Vicki Pfau 2017-03-03 18:16:35 -08:00
parent 30cac2e24b
commit c29dd3c1d3
1 changed files with 46 additions and 1 deletions

View File

@ -23,6 +23,8 @@ static void DSGXDummyRendererGetScanline(struct DSGXRenderer* renderer, int y, c
static void DSGXWriteFIFO(struct DSGX* gx, struct DSGXEntry entry); static void DSGXWriteFIFO(struct DSGX* gx, struct DSGXEntry entry);
static bool _boxTestVertex(struct DSGX* gx, struct DSGXVertex* vertex);
static const int32_t _gxCommandCycleBase[DS_GX_CMD_MAX] = { static const int32_t _gxCommandCycleBase[DS_GX_CMD_MAX] = {
[DS_GX_CMD_NOP] = 0, [DS_GX_CMD_NOP] = 0,
[DS_GX_CMD_MTX_MODE] = 2, [DS_GX_CMD_MTX_MODE] = 2,
@ -176,6 +178,46 @@ static void _updateClipMatrix(struct DSGX* gx) {
gx->p->memory.io9[DS9_REG_CLIPMTX_RESULT_1F >> 1] = gx->clipMatrix.m[15] >> 16; gx->p->memory.io9[DS9_REG_CLIPMTX_RESULT_1F >> 1] = gx->clipMatrix.m[15] >> 16;
} }
static bool _clipPolygon(struct DSGX* gx, struct DSGXPolygon* poly) {
struct DSGXVertex* vbuf = gx->vertexBuffer[gx->bufferIndex];
int nOffscreen = 0;
unsigned offscreenVerts[4] = {};
int v;
// Collect offscreen vertices
for (v = 0; v < poly->verts; ++v) {
if (!_boxTestVertex(gx, &vbuf[gx->currentPoly.vertIds[v]])) {
offscreenVerts[nOffscreen] = gx->currentPoly.vertIds[v];
++nOffscreen;
}
}
if (!nOffscreen) {
return true;
}
// All of the vertices are offscreen
// TODO: clip vertices instead of discarding them
if (nOffscreen == poly->verts) {
// Remove all vertices before remaking them
gx->vertexIndex -= poly->verts;
// Put back the ones that are on the strip
for (v = 0; v < gx->currentPoly.verts; ++v) {
unsigned vid = gx->currentPoly.vertIds[v];
int ov;
for (ov = 0; ov < nOffscreen; ++ov) {
if (vid != offscreenVerts[ov]) {
continue;
}
vbuf[gx->vertexIndex] = vbuf[vid];
gx->currentPoly.vertIds[v] = gx->vertexIndex;
++gx->vertexIndex;
break;
}
}
return false;
}
return true;
}
static int32_t _dotViewport(struct DSGXVertex* vertex, int32_t* col) { static int32_t _dotViewport(struct DSGXVertex* vertex, int32_t* col) {
int64_t a; int64_t a;
int64_t b; int64_t b;
@ -308,7 +350,10 @@ static void _emitVertex(struct DSGX* gx, uint16_t x, uint16_t y, uint16_t z) {
gx->currentPoly.verts = 2; gx->currentPoly.verts = 2;
break; break;
} }
++gx->polygonIndex;
if (_clipPolygon(gx, &pbuf[gx->polygonIndex])) {
++gx->polygonIndex;
}
} }
} }