|
|
|
@ -331,6 +331,195 @@ static INLINE void draw_quadstrip_textured(const ps1bsp_vertex_t *vertices, cons |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
typedef struct _TMPVERT |
|
|
|
{ |
|
|
|
int16_t vx, vy, vz, vpad; |
|
|
|
uint8_t r, g, b, cpad; |
|
|
|
uint8_t u, v; |
|
|
|
uint16_t pad; |
|
|
|
} TMPVERT; |
|
|
|
|
|
|
|
#define copyVertFast(dst, pv, v) \ |
|
|
|
setColorFast(&(dst)->r, &(pv)->r); \ |
|
|
|
setColorFast(&(dst)->vx, &(v)->vx); \ |
|
|
|
setColorFast(&(dst)->vz, &(v)->vz); \ |
|
|
|
setUVFast(&(dst)->u, &(pv)->u); |
|
|
|
|
|
|
|
#define lerpVert(dst, src0, src1) \ |
|
|
|
(dst)->vx = (int16_t)(((int32_t)(src0)->vx + (int32_t)(src1)->vx) >> 1); \ |
|
|
|
(dst)->vy = (int16_t)(((int32_t)(src0)->vy + (int32_t)(src1)->vy) >> 1); \ |
|
|
|
(dst)->vz = (int16_t)(((int32_t)(src0)->vz + (int32_t)(src1)->vz) >> 1); \ |
|
|
|
(dst)->r = (uint8_t)(((uint16_t)(src0)->r + (uint16_t)(src1)->r) >> 1); \ |
|
|
|
(dst)->g = (uint8_t)(((uint16_t)(src0)->g + (uint16_t)(src1)->g) >> 1); \ |
|
|
|
(dst)->b = (uint8_t)(((uint16_t)(src0)->b + (uint16_t)(src1)->b) >> 1); \ |
|
|
|
(dst)->u = (uint8_t)(((uint16_t)(src0)->u + (uint16_t)(src1)->u) >> 1); \ |
|
|
|
(dst)->v = (uint8_t)(((uint16_t)(src0)->v + (uint16_t)(src1)->v) >> 1); |
|
|
|
|
|
|
|
#define blitVert(dst, src) \ |
|
|
|
setColorFast(&(dst)->x, &(src)->vx); \ |
|
|
|
setColorFast(&(dst)->r, &(src)->r); \ |
|
|
|
setUVFast(&(dst)->u, &(src)->u); |
|
|
|
|
|
|
|
static INLINE void draw_quadstrip_tess2(const ps1bsp_vertex_t *vertices, const ps1bsp_polyvertex_t *polyVerts, u_char numVerts, u_short tpage, u_long *ot) |
|
|
|
{ |
|
|
|
const ps1bsp_polyvertex_t *pv0, *pv1, *pv2, *pv3; |
|
|
|
const ps1bsp_vertex_t *v0, *v1, *v2, *v3; |
|
|
|
u_char i0, i1, i2, i3; |
|
|
|
u_char head = 0; |
|
|
|
u_char tail = numVerts; |
|
|
|
|
|
|
|
// Initialize the first two vertices |
|
|
|
i2 = --tail; |
|
|
|
i3 = head++; |
|
|
|
|
|
|
|
TMPVERT *tmp = (TMPVERT*)(scratchpad); |
|
|
|
|
|
|
|
// Normally a quad strip would have (N-2)/2 quads, but we might end up with a sole triangle at the end which will be drawn as a collapsed quad |
|
|
|
// NOTE: testing has shown that the PS1 is faster just rendering quads and accepting the odd collapsed quad, rather than being clever with pointer comparisons and drawing a single triangle at the end. |
|
|
|
u_char numQuads = (numVerts - 1) >> 1; |
|
|
|
for (u_char quadIdx = 0; quadIdx < numQuads; ++quadIdx) |
|
|
|
{ |
|
|
|
i0 = i2; |
|
|
|
i1 = i3; |
|
|
|
i2 = --tail; |
|
|
|
i3 = head++; |
|
|
|
|
|
|
|
pv0 = &polyVerts[i0]; |
|
|
|
pv1 = &polyVerts[i1]; |
|
|
|
pv2 = &polyVerts[i2]; |
|
|
|
pv3 = &polyVerts[i3]; |
|
|
|
|
|
|
|
v0 = &vertices[pv0->index]; |
|
|
|
v1 = &vertices[pv1->index]; |
|
|
|
v2 = &vertices[pv2->index]; |
|
|
|
v3 = &vertices[pv3->index]; |
|
|
|
|
|
|
|
copyVertFast(&tmp[0], pv0, v0); |
|
|
|
copyVertFast(&tmp[2], pv1, v1); |
|
|
|
copyVertFast(&tmp[6], pv2, v2); |
|
|
|
copyVertFast(&tmp[8], pv3, v3); |
|
|
|
|
|
|
|
lerpVert(&tmp[1], &tmp[0], &tmp[2]); |
|
|
|
lerpVert(&tmp[3], &tmp[0], &tmp[6]); |
|
|
|
lerpVert(&tmp[5], &tmp[2], &tmp[8]); |
|
|
|
lerpVert(&tmp[7], &tmp[6], &tmp[8]); |
|
|
|
lerpVert(&tmp[4], &tmp[3], &tmp[5]); |
|
|
|
|
|
|
|
// Transform the vertices in groups of three |
|
|
|
gte_ldv3(&tmp[0], &tmp[1], &tmp[2]); |
|
|
|
gte_rtpt(); |
|
|
|
gte_stsxy0(&tmp[0].vx); |
|
|
|
gte_stsxy1(&tmp[1].vx); |
|
|
|
gte_stsxy2(&tmp[2].vx); |
|
|
|
|
|
|
|
gte_ldv3(&tmp[3], &tmp[4], &tmp[5]); |
|
|
|
gte_rtpt(); |
|
|
|
gte_stsxy0(&tmp[3].vx); |
|
|
|
gte_stsxy1(&tmp[4].vx); |
|
|
|
gte_stsxy2(&tmp[5].vx); |
|
|
|
|
|
|
|
gte_ldv3(&tmp[6], &tmp[7], &tmp[8]); |
|
|
|
gte_rtpt(); |
|
|
|
gte_stsxy0(&tmp[6].vx); |
|
|
|
gte_stsxy1(&tmp[7].vx); |
|
|
|
gte_stsxy2(&tmp[8].vx); |
|
|
|
|
|
|
|
// Draw the first quad |
|
|
|
POLY_GT4 *poly = (POLY_GT4*)mem_prim(sizeof(POLY_GT4)); |
|
|
|
setColorFast(&poly->x0, &tmp[0].vx); |
|
|
|
setColorFast(&poly->r0, &tmp[0].r); |
|
|
|
setUVFast(&poly->u0, &tmp[0].u); |
|
|
|
poly->clut = quake_clut; |
|
|
|
|
|
|
|
setColorFast(&poly->x1, &tmp[3].vx); |
|
|
|
setColorFast(&poly->r1, &tmp[3].r); |
|
|
|
setUVFast(&poly->u1, &tmp[3].u); |
|
|
|
poly->tpage = tpage; |
|
|
|
|
|
|
|
setColorFast(&poly->x2, &tmp[1].vx); |
|
|
|
setColorFast(&poly->r2, &tmp[1].r); |
|
|
|
setUVFast(&poly->u2, &tmp[1].u); |
|
|
|
|
|
|
|
setColorFast(&poly->x3, &tmp[4].vx); |
|
|
|
setColorFast(&poly->r3, &tmp[4].r); |
|
|
|
setUVFast(&poly->u3, &tmp[4].u); |
|
|
|
|
|
|
|
setPolyGT4(poly); |
|
|
|
addPrim(ot, poly); |
|
|
|
|
|
|
|
// Second quad |
|
|
|
poly = (POLY_GT4*)mem_prim(sizeof(POLY_GT4)); |
|
|
|
setColorFast(&poly->x0, &tmp[1].vx); |
|
|
|
setColorFast(&poly->r0, &tmp[1].r); |
|
|
|
setUVFast(&poly->u0, &tmp[1].u); |
|
|
|
poly->clut = quake_clut; |
|
|
|
|
|
|
|
setColorFast(&poly->x1, &tmp[4].vx); |
|
|
|
setColorFast(&poly->r1, &tmp[4].r); |
|
|
|
setUVFast(&poly->u1, &tmp[4].u); |
|
|
|
poly->tpage = tpage; |
|
|
|
|
|
|
|
setColorFast(&poly->x2, &tmp[2].vx); |
|
|
|
setColorFast(&poly->r2, &tmp[2].r); |
|
|
|
setUVFast(&poly->u2, &tmp[2].u); |
|
|
|
|
|
|
|
setColorFast(&poly->x3, &tmp[5].vx); |
|
|
|
setColorFast(&poly->r3, &tmp[5].r); |
|
|
|
setUVFast(&poly->u3, &tmp[5].u); |
|
|
|
|
|
|
|
setPolyGT4(poly); |
|
|
|
addPrim(ot, poly); |
|
|
|
|
|
|
|
// Third quad |
|
|
|
poly = (POLY_GT4*)mem_prim(sizeof(POLY_GT4)); |
|
|
|
setColorFast(&poly->x0, &tmp[3].vx); |
|
|
|
setColorFast(&poly->r0, &tmp[3].r); |
|
|
|
setUVFast(&poly->u0, &tmp[3].u); |
|
|
|
poly->clut = quake_clut; |
|
|
|
|
|
|
|
setColorFast(&poly->x1, &tmp[6].vx); |
|
|
|
setColorFast(&poly->r1, &tmp[6].r); |
|
|
|
setUVFast(&poly->u1, &tmp[6].u); |
|
|
|
poly->tpage = tpage; |
|
|
|
|
|
|
|
setColorFast(&poly->x2, &tmp[4].vx); |
|
|
|
setColorFast(&poly->r2, &tmp[4].r); |
|
|
|
setUVFast(&poly->u2, &tmp[4].u); |
|
|
|
|
|
|
|
setColorFast(&poly->x3, &tmp[7].vx); |
|
|
|
setColorFast(&poly->r3, &tmp[7].r); |
|
|
|
setUVFast(&poly->u3, &tmp[7].u); |
|
|
|
|
|
|
|
setPolyGT4(poly); |
|
|
|
addPrim(ot, poly); |
|
|
|
|
|
|
|
// Fourth quad |
|
|
|
poly = (POLY_GT4*)mem_prim(sizeof(POLY_GT4)); |
|
|
|
setColorFast(&poly->x0, &tmp[4].vx); |
|
|
|
setColorFast(&poly->r0, &tmp[4].r); |
|
|
|
setUVFast(&poly->u0, &tmp[4].u); |
|
|
|
poly->clut = quake_clut; |
|
|
|
|
|
|
|
setColorFast(&poly->x1, &tmp[7].vx); |
|
|
|
setColorFast(&poly->r1, &tmp[7].r); |
|
|
|
setUVFast(&poly->u1, &tmp[7].u); |
|
|
|
poly->tpage = tpage; |
|
|
|
|
|
|
|
setColorFast(&poly->x2, &tmp[5].vx); |
|
|
|
setColorFast(&poly->r2, &tmp[5].r); |
|
|
|
setUVFast(&poly->u2, &tmp[5].u); |
|
|
|
|
|
|
|
setColorFast(&poly->x3, &tmp[8].vx); |
|
|
|
setColorFast(&poly->r3, &tmp[8].r); |
|
|
|
setUVFast(&poly->u3, &tmp[8].u); |
|
|
|
|
|
|
|
setPolyGT4(poly); |
|
|
|
addPrim(ot, poly); |
|
|
|
|
|
|
|
polyCount += 4; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static INLINE void draw_quadstrip_water(const ps1bsp_vertex_t *vertices, const ps1bsp_polyvertex_t *polyVerts, u_char numVerts, u_short tpage, u_char semiTrans, u_long *ot) |
|
|
|
{ |
|
|
|
// Draw the face as a quad strip |
|
|
|
|