Browse Source

Further optimized model rendering by reorganizing the loaded data and precalculating & precaching often reused values.

master
Nico de Poel 3 years ago
parent
commit
02f04ef7ca
  1. 120
      main.c
  2. 8
      ps1mdl.h

120
main.c

@ -52,26 +52,31 @@ extern u_long mdl_shambler[];
extern u_long tim_shambler_f[];
extern u_long tim_shambler_b[];
// The player texture is divided into two pieces, so that each part is aligned to their own texture page
TIM_IMAGE playerFrontTex, playerBackTex;
TIM_IMAGE shamblerFrontTex, shamblerBackTex;
ps1mdl_t playerModel, shamblerModel;
void loadTexture(const u_long* tim, TIM_IMAGE* tparam)
typedef struct
{
GetTimInfo(tim, tparam);
ps1mdl_header_t* header;
ps1mdl_texcoord_t* texCoords;
ps1mdl_triangle_t* triangles;
ps1mdl_vertex_t* vertices;
// This freezes up if the TIM image has weird dimensions, such as the ones from Quake...
LoadImage(tparam->prect, tparam->paddr);
short halfSkinWidth; // Used for offsetting UVs on the back texture
} ps1mdl_t;
// Upload CLUT for palettized images
if (tparam->mode & 0x8)
typedef struct
{
LoadImage(tparam->crect, tparam->caddr);
}
RECT prect, crect;
int mode;
int uoffs, voffs;
} ps1texture_t;
DrawSync(0);
}
typedef struct
{
// Skin textures are divided into two pieces, so that each part is aligned to their own texture page
ps1texture_t front, back;
} ps1skin_t;
ps1mdl_t playerModel, shamblerModel;
ps1skin_t playerSkin, shamblerSkin;
void loadModel(const u_long* data, ps1mdl_t *mdl)
{
@ -87,6 +92,38 @@ void loadModel(const u_long* data, ps1mdl_t *mdl)
bytes += sizeof(ps1mdl_triangle_t) * mdl->header->triangleCount;
mdl->vertices = (ps1mdl_vertex_t*)bytes;
mdl->halfSkinWidth = mdl->header->skinWidth >> 1;
}
void loadTexture(const u_long* tim, ps1texture_t *texture)
{
TIM_IMAGE* tparam;
GetTimInfo(tim, tparam);
// This freezes up if the TIM image has weird dimensions, such as the ones from Quake...
LoadImage(tparam->prect, tparam->paddr);
// Upload CLUT for palettized images
if (tparam->mode & 0x8)
{
LoadImage(tparam->crect, tparam->caddr);
}
DrawSync(0);
texture->prect = *tparam->prect;
texture->crect = *tparam->crect;
texture->mode = tparam->mode;
texture->uoffs = (texture->prect.x % 64) << (2 - (texture->mode & 0x3));
texture->voffs = (texture->prect.y & 0xFF);
}
void loadSkin(const u_long* frontTim, const u_long* backTim, ps1skin_t *skin)
{
loadTexture(frontTim, &skin->front);
loadTexture(backTim, &skin->back);
}
// Init function
@ -126,12 +163,10 @@ void init(void)
nextpri = primbuff[0];
loadModel(mdl_player, &playerModel);
loadTexture(tim_player_f, &playerFrontTex);
loadTexture(tim_player_b, &playerBackTex);
loadSkin(tim_player_f, tim_player_b, &playerSkin);
loadModel(mdl_shambler, &shamblerModel);
loadTexture(tim_shambler_f, &shamblerFrontTex);
loadTexture(tim_shambler_b, &shamblerBackTex);
loadSkin(tim_shambler_f, tim_shambler_b, &shamblerSkin);
// 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);
@ -291,19 +326,14 @@ static int fakeLight(const int *norm)
return lit;
}
void drawModel(ps1mdl_t *model, TIM_IMAGE *frontTex, TIM_IMAGE *backTex, int xOffset, int frameCounter)
void drawModel(ps1mdl_t *model, ps1skin_t *skin, int xOffset, int frameCounter)
{
TIM_IMAGE *tex;
ps1texture_t *tex;
short u0, u1, u2, uoffs, voffs;
int frameNum = frameCounter % model->header->frameCount;
int vertOffs = frameNum * model->header->vertexCount;
unsigned short halfSkinWidth = model->header->skinWidth >> 1;
short frontUOffs = (frontTex->prect->x % 64) << (2 - (frontTex->mode & 0x3));
short frontVOffs = (frontTex->prect->y & 0xFF);
short backUOffs = (backTex->prect->x % 64) << (2 - (backTex->mode & 0x3));
short backVOffs = (backTex->prect->y & 0xFF);
short halfSkinWidth = model->halfSkinWidth;
for (int triIdx = 0; triIdx < model->header->triangleCount; ++triIdx)
{
@ -330,7 +360,7 @@ void drawModel(ps1mdl_t *model, TIM_IMAGE *frontTex, TIM_IMAGE *backTex, int xOf
if (tri->frontFace)
{
u0 = tc0->u, u1 = tc1->u, u2 = tc2->u;
tex = frontTex, uoffs = frontUOffs, voffs = frontVOffs;
tex = &skin->front;
}
else
{
@ -338,9 +368,11 @@ void drawModel(ps1mdl_t *model, TIM_IMAGE *frontTex, TIM_IMAGE *backTex, int xOf
u0 = tc0->onSeam ? tc0->u : tc0->u - halfSkinWidth;
u1 = tc1->onSeam ? tc1->u : tc1->u - halfSkinWidth;
u2 = tc2->onSeam ? tc2->u : tc2->u - halfSkinWidth;
tex = backTex, uoffs = backUOffs, voffs = backVOffs;
tex = &skin->back;
}
uoffs = tex->uoffs, voffs = tex->voffs;
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]);
@ -348,8 +380,8 @@ void drawModel(ps1mdl_t *model, TIM_IMAGE *frontTex, TIM_IMAGE *backTex, int xOf
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);
setClut(poly, tex->crect.x, tex->crect.y);
setTPage(poly, tex->mode & 0x3, 0, tex->prect.x, tex->prect.y);
addPrim(ot[db] + depth, poly);
nextpri += sizeof(POLY_GT3);
@ -363,29 +395,27 @@ void drawStuff(int counter)
// 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", playerFrontTex.prect->x, playerFrontTex.prect->y, playerFrontTex.prect->w, playerFrontTex.prect->h, playerFrontTex.mode);
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);
// Draw the last created text stream
FntFlush(-1);
drawModel(&playerModel, &playerFrontTex, &playerBackTex, -40, counter >> 2);
drawModel(&shamblerModel, &shamblerFrontTex, &shamblerBackTex, 80, counter >> 2);
return;
drawModel(&playerModel, &playerSkin, -40, counter >> 2);
drawModel(&shamblerModel, &shamblerSkin, 80, counter >> 2);
int r, g, b;
// 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);
// lerpcol(255, 255, 0, 255, 0, 0, (icos(counter * 32) + 4096) >> 1, &r, &g, &b);
// addTile(32, 32, 64, 64, r, g, b);
lerpcol(0, 255, 255, 0, 255, 0, (icos(counter * 24 + 512) + 4096) >> 1, &r, &g, &b);
addTile(128, 160, 48, 48, r, g, b);
// lerpcol(0, 255, 255, 0, 255, 0, (icos(counter * 24 + 512) + 4096) >> 1, &r, &g, &b);
// addTile(128, 160, 48, 48, r, g, b);
addColoredTriangle(260, 140, 220, 220, 300, 220, 0xFF0000, 0x00FF00, 0x0000FF, 0);
addTexturedTriangle(260, 40, 220, 120, 300, 120, 0, 94, 74, 124, 58, 1, &playerFrontTex);
addTexturedSprite(20, 140, 80, 80, &playerFrontTex);
addTexturedSprite(80, 40, 154, 114, &shamblerFrontTex);
// 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);
}
// Main function, program entrypoint

8
ps1mdl.h

@ -38,14 +38,6 @@ typedef struct
unsigned char normalIndex;
} ps1mdl_vertex_t;
typedef struct
{
ps1mdl_header_t* header;
ps1mdl_texcoord_t* texCoords;
ps1mdl_triangle_t* triangles;
ps1mdl_vertex_t* vertices;
} ps1mdl_t;
#ifdef __cplusplus
}
#endif

Loading…
Cancel
Save