From 5e0641c9ffcc8581bfcb71014b77930827162d66 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Thu, 8 Sep 2022 17:46:09 +0200 Subject: [PATCH] Rewrote model rendering code using GTE acceleration. Now with 100% more perspective! --- main.c | 101 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 28 deletions(-) diff --git a/main.c b/main.c index 3eedf9e..ce7d60e 100644 --- a/main.c +++ b/main.c @@ -31,7 +31,7 @@ #define SCREENHEIGHT 240 #define NUMVERTEXNORMALS 162 -static int anorms[NUMVERTEXNORMALS][3] = { +static short anorms[NUMVERTEXNORMALS][3] = { #include "ps1anorms.h" }; @@ -78,6 +78,21 @@ typedef struct ps1mdl_t playerModel, shamblerModel; ps1skin_t playerSkin, shamblerSkin; +SVECTOR rot = { 0 }; +VECTOR pos = { -200, 128, 64 }; + +MATRIX color_mtx = { + ONE, 0, 0, + ONE, 0, 0, + ONE, 0, 0 +}; + +MATRIX light_mtx = { + ONE, 0, 0, + 0, 0, 0, + 0, 0, 0 +}; + void loadModel(const u_long* data, ps1mdl_t *mdl) { const char *bytes = (const char*)data; @@ -168,6 +183,10 @@ void init(void) loadModel(mdl_shambler, &shamblerModel); loadSkin(tim_shambler_f, tim_shambler_b, &shamblerSkin); + InitGeom(); + gte_SetGeomOffset(SCREENWIDTH >> 1, SCREENHEIGHT >> 1); + gte_SetGeomScreen(SCREENWIDTH >> 1); // Screen depth for FOV control + // Set texture page for the entire drawing environment. Nice in some cases perhaps, but not what we need. //draw[0].tpage = getTPage(playerFrontTex.mode & 0x3, 0, playerFrontTex.prect->x, playerFrontTex.prect->y); //draw[1].tpage = getTPage(playerFrontTex.mode & 0x3, 0, playerFrontTex.prect->x, playerFrontTex.prect->y); @@ -326,10 +345,13 @@ static int fakeLight(const int *norm) return lit; } +SVECTOR outPos; + void drawModel(ps1mdl_t *model, ps1skin_t *skin, int xOffset, int frameCounter) { ps1texture_t *tex; short u0, u1, u2, uoffs, voffs; + int p; int frameNum = frameCounter % model->header->frameCount; int vertOffs = frameNum * model->header->vertexCount; @@ -343,20 +365,31 @@ void drawModel(ps1mdl_t *model, ps1skin_t *skin, int xOffset, int frameCounter) ps1mdl_vertex_t *v1 = &model->vertices[tri->vertexIndex[1] + vertOffs]; ps1mdl_vertex_t *v2 = &model->vertices[tri->vertexIndex[2] + vertOffs]; - // Normally you'd have GTE do this but we're just going for a quick hack now - unsigned short depth = ((unsigned short)v0->position[1] + (unsigned short)v1->position[1] + (unsigned short)v2->position[1]) / 3; - if (depth >= OTLEN) + // Swizzle the coordinates because Quake Z is up + SVECTOR pos0 = { v0->position[0], -v0->position[2], v0->position[1] }; + SVECTOR pos1 = { v1->position[0], -v1->position[2], v1->position[1] }; + SVECTOR pos2 = { v2->position[0], -v2->position[2], v2->position[1] }; + + gte_ldv3(&pos0, &pos1, &pos2); + gte_rtpt(); // Rotation, Translation and Perspective triplet (all three vertices at once) + + // Normal clipping for backface culling + gte_nclip(); + gte_stopz(&p); + if (p < 0) + continue; + + // Average Z for depth sorting + gte_avsz3(); + gte_stotz(&p); + unsigned short depth = p;//p >> 2; + if (depth < 0 || depth >= OTLEN) continue; ps1mdl_texcoord_t *tc0 = &model->texCoords[tri->vertexIndex[0]]; ps1mdl_texcoord_t *tc1 = &model->texCoords[tri->vertexIndex[1]]; ps1mdl_texcoord_t *tc2 = &model->texCoords[tri->vertexIndex[2]]; - // Calculate some Lambert shading based on a static light vector - int lit0 = fakeLight(anorms[v0->normalIndex]); - int lit1 = fakeLight(anorms[v1->normalIndex]); - int lit2 = fakeLight(anorms[v2->normalIndex]); - if (tri->frontFace) { u0 = tc0->u, u1 = tc1->u, u2 = tc2->u; @@ -375,11 +408,25 @@ void drawModel(ps1mdl_t *model, ps1skin_t *skin, int xOffset, int frameCounter) POLY_GT3 *poly = (POLY_GT3*)nextpri; setPolyGT3(poly); - setXY3(poly, xOffset + v0->position[0], 240 - v0->position[2], xOffset + v1->position[0], 240 - v1->position[2], xOffset + v2->position[0], 240 - v2->position[2]); + + // Store transformed vertex coordinates in screen space + gte_stsxy0(&poly->x0); + gte_stsxy1(&poly->x1); + gte_stsxy2(&poly->x2); + + // Copy some values for on-screen debugging + outPos.vx = poly->x0; + outPos.vy = poly->y0; + outPos.vz = p; + + // Calculate vertex color based on normal + gte_ldrgb(&poly->r0); + gte_ldv3(anorms[v0->normalIndex], anorms[v1->normalIndex], anorms[v2->normalIndex]); + gte_nct(); + gte_strgb3(&poly->r0, &poly->r1, &poly->r2); + + // Set texture parameters setUV3(poly, uoffs + u0, voffs + tc0->v, uoffs + u1, voffs + tc1->v, uoffs + u2, voffs + tc2->v); - setRGB0(poly, lit0, lit0, lit0); - setRGB1(poly, lit1, lit1, lit1); - setRGB2(poly, lit2, lit2, lit2); setClut(poly, tex->crect.x, tex->crect.y); setTPage(poly, tex->mode & 0x3, 0, tex->prect.x, tex->prect.y); @@ -392,30 +439,28 @@ void drawStuff(int counter) { ClearOTagR(ot[db], OTLEN); - // Print the obligatory hello world and counter to show that the - // program isn't locking up to the last created text stream - FntPrint(-1, "COUNTER=%d, SIN=%d\n", counter, isin(counter)); FntPrint(-1, "Image x %d y %d w %d h %d mode 0x%x\n", playerSkin.front.prect.x, playerSkin.front.prect.y, playerSkin.front.prect.w, playerSkin.front.prect.h, playerSkin.front.mode); FntPrint(-1, "Model: %d tris, %d verts\n", playerModel.header->triangleCount, playerModel.header->vertexCount); + FntPrint(-1, "Trsf: (%d, %d, %d)\n", outPos.vx, outPos.vy, outPos.vz); // Draw the last created text stream FntFlush(-1); - drawModel(&playerModel, &playerSkin, -40, counter >> 2); - drawModel(&shamblerModel, &shamblerSkin, 80, counter >> 2); + gte_SetBackColor(48, 48, 48); // Ambient light color + gte_SetColorMatrix(&color_mtx); // Light color and direction - // int r, g, b; - - // lerpcol(255, 255, 0, 255, 0, 0, (icos(counter * 32) + 4096) >> 1, &r, &g, &b); - // addTile(32, 32, 64, 64, r, g, b); + MATRIX mtx, lmtx; + RotMatrix(&rot, &mtx); + TransMatrix(&mtx, &pos); - // lerpcol(0, 255, 255, 0, 255, 0, (icos(counter * 24 + 512) + 4096) >> 1, &r, &g, &b); - // addTile(128, 160, 48, 48, r, g, b); + MulMatrix0(&light_mtx, &mtx, &lmtx); - // addColoredTriangle(260, 140, 220, 220, 300, 220, 0xFF0000, 0x00FF00, 0x0000FF, 0); - // addTexturedTriangle(260, 40, 220, 120, 300, 120, 0, 94, 74, 124, 58, 1, &playerSkin.front); - // addTexturedSprite(20, 140, 80, 80, &playerSkin.front); - // addTexturedSprite(80, 40, 154, 114, &shamblerSkin.front); + gte_SetRotMatrix(&mtx); + gte_SetTransMatrix(&mtx); + gte_SetLightMatrix(&lmtx); + + drawModel(&playerModel, &playerSkin, -40, counter >> 2); + //drawModel(&shamblerModel, &shamblerSkin, 80, counter >> 2); } // Main function, program entrypoint