Browse Source

Added texture mapping for the character model using a split front/back texture approach.

master
Nico de Poel 3 years ago
parent
commit
5f54a4f3b8
  1. 3
      CMakeLists.txt
  2. 68
      main.c
  3. BIN
      player.ps1mdl
  4. BIN
      player.tim
  5. BIN
      player_b.tim
  6. BIN
      player_f.tim
  7. 16
      ps1mdl.h

3
CMakeLists.txt

@ -13,7 +13,8 @@ project(
psn00bsdk_add_executable(template STATIC main.c) psn00bsdk_add_executable(template STATIC main.c)
psn00bsdk_target_incbin(template PRIVATE tim_player128 player128.tim)
psn00bsdk_target_incbin(template PRIVATE tim_player_f player_f.tim)
psn00bsdk_target_incbin(template PRIVATE tim_player_b player_b.tim)
psn00bsdk_target_incbin(template PRIVATE tim_player16bpp player128-16.tim) psn00bsdk_target_incbin(template PRIVATE tim_player16bpp player128-16.tim)
psn00bsdk_target_incbin(template PRIVATE tim_shambler shambler128.tim) psn00bsdk_target_incbin(template PRIVATE tim_shambler shambler128.tim)
psn00bsdk_target_incbin(template PRIVATE mdl_player player.ps1mdl) psn00bsdk_target_incbin(template PRIVATE mdl_player player.ps1mdl)

68
main.c

@ -42,12 +42,14 @@ u_long ot[2][OTLEN]; // Ordering tables, two arrays for double buffering. These
char primbuff[2][32768]; // Primitive buffer, just a raw buffer of bytes to use as a pool for primitives char primbuff[2][32768]; // Primitive buffer, just a raw buffer of bytes to use as a pool for primitives
char *nextpri; char *nextpri;
extern u_long tim_player128[];
extern u_long tim_player_f[];
extern u_long tim_player_b[];
extern u_long tim_player16bpp[]; extern u_long tim_player16bpp[];
extern u_long tim_shambler[]; extern u_long tim_shambler[];
extern u_long mdl_player[]; extern u_long mdl_player[];
TIM_IMAGE playerTex;
// 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 shamblerTex; TIM_IMAGE shamblerTex;
ps1mdl_t model; ps1mdl_t model;
@ -119,15 +121,16 @@ void init(void)
nextpri = primbuff[0]; nextpri = primbuff[0];
loadTexture(tim_player128, &playerTex);
loadTexture(tim_player16bpp, &playerTex);
loadTexture(tim_player_f, &playerFrontTex);
loadTexture(tim_player_b, &playerBackTex);
//loadTexture(tim_player16bpp, &playerFrontTex);
loadTexture(tim_shambler, &shamblerTex); loadTexture(tim_shambler, &shamblerTex);
loadModel(mdl_player, &model); loadModel(mdl_player, &model);
// Set texture page for the entire drawing environment. Nice in some cases perhaps, but not what we need. // Set texture page for the entire drawing environment. Nice in some cases perhaps, but not what we need.
//draw[0].tpage = getTPage(playerTex.mode & 0x3, 0, playerTex.prect->x, playerTex.prect->y);
//draw[1].tpage = getTPage(playerTex.mode & 0x3, 0, playerTex.prect->x, playerTex.prect->y);
//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);
} }
// Display function // Display function
@ -208,6 +211,34 @@ void addTexturedTriangle(int x0, int y0, int x1, int y1, int x2, int y2, short u
nextpri += sizeof(POLY_FT3); nextpri += sizeof(POLY_FT3);
} }
void addGouraudTexturedTriangle(
int x0, int y0, int x1, int y1, int x2, int y2, unsigned char depth,
unsigned int rgb0, unsigned int rgb1, unsigned int rgb2,
short u0, short v0, short u1, short v1, short u2, short v2, TIM_IMAGE *img)
{
if (img == NULL)
{
addColoredTriangle(x0, y0, x1, y1, x2, y2, rgb0, rgb1, rgb2, depth);
return;
}
short uoffs = (img->prect->x % 64) << (2 - (img->mode & 0x3));
short voffs = (img->prect->y & 0xFF);
POLY_GT3 *poly = (POLY_GT3*)nextpri;
setPolyGT3(poly);
setXY3(poly, x0, y0, x1, y1, x2, y2);
setUV3(poly, uoffs + u0, voffs + v0, uoffs + u1, voffs + v1, uoffs + u2, voffs + v2);
setRGB0(poly, (rgb0 >> 16) & 0xFF, (rgb0 >> 8) & 0xFF, rgb0 & 0xFF);
setRGB1(poly, (rgb1 >> 16) & 0xFF, (rgb1 >> 8) & 0xFF, rgb1 & 0xFF);
setRGB2(poly, (rgb2 >> 16) & 0xFF, (rgb2 >> 8) & 0xFF, rgb2 & 0xFF);
setClut(poly, img->crect->x, img->crect->y);
setTPage(poly, img->mode & 0x3, 0, img->prect->x, img->prect->y);
addPrim(ot[db] + depth, poly);
nextpri += sizeof(POLY_GT3);
}
void addTexturedSprite(int x, int y, int w, int h, TIM_IMAGE *img) void addTexturedSprite(int x, int y, int w, int h, TIM_IMAGE *img)
{ {
short uoffs = (img->prect->x % 64) << (2 - (img->mode & 0x3)); short uoffs = (img->prect->x % 64) << (2 - (img->mode & 0x3));
@ -250,7 +281,7 @@ static int fakeLight(const int *norm)
const int light[3] = { ONE, 0, 0 }; const int light[3] = { ONE, 0, 0 };
int lit = dot(norm, light) >> 4; // Calculate light intensity and normalize to [-256..255] int lit = dot(norm, light) >> 4; // Calculate light intensity and normalize to [-256..255]
lit = lit < 0 ? 0 : lit; // Clamp to [0..255] lit = lit < 0 ? 0 : lit; // Clamp to [0..255]
lit += 32; // Add some ambient light
lit += 48; // Add some ambient light
lit = lit > 255 ? 255 : lit; // Clamp to [0..255] again lit = lit > 255 ? 255 : lit; // Clamp to [0..255] again
return lit << 16 | lit << 8 | lit; return lit << 16 | lit << 8 | lit;
} }
@ -262,7 +293,7 @@ void drawStuff(int counter)
// Print the obligatory hello world and counter to show that the // Print the obligatory hello world and counter to show that the
// program isn't locking up to the last created text stream // program isn't locking up to the last created text stream
FntPrint(-1, "COUNTER=%d, SIN=%d\n", counter, isin(counter)); 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", playerTex.prect->x, playerTex.prect->y, playerTex.prect->w, playerTex.prect->h, playerTex.mode);
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, "Model: %d tris, %d verts\n", model.header->triangleCount, model.header->vertexCount); FntPrint(-1, "Model: %d tris, %d verts\n", model.header->triangleCount, model.header->vertexCount);
// Draw the last created text stream // Draw the last created text stream
@ -279,6 +310,10 @@ void drawStuff(int counter)
ps1mdl_vertex_t *v1 = &model.vertices[tri->vertexIndex[1] + vertOffs]; ps1mdl_vertex_t *v1 = &model.vertices[tri->vertexIndex[1] + vertOffs];
ps1mdl_vertex_t *v2 = &model.vertices[tri->vertexIndex[2] + vertOffs]; ps1mdl_vertex_t *v2 = &model.vertices[tri->vertexIndex[2] + vertOffs];
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]];
// Use normal indices to generate a greyscale value. Good for just giving the polygons some gradients. // Use normal indices to generate a greyscale value. Good for just giving the polygons some gradients.
unsigned int n0 = v0->normalIndex, n1 = v1->normalIndex, n2 = v2->normalIndex; unsigned int n0 = v0->normalIndex, n1 = v1->normalIndex, n2 = v2->normalIndex;
unsigned int rgb0 = (n0 << 16) | (n0 << 8) | n0; unsigned int rgb0 = (n0 << 16) | (n0 << 8) | n0;
@ -298,7 +333,18 @@ void drawStuff(int counter)
// Normally you'd have GTE do this but we're just going for a quick hack now // 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; unsigned short depth = ((unsigned short)v0->position[1] + (unsigned short)v1->position[1] + (unsigned short)v2->position[1]) / 3;
addColoredTriangle(v0->position[0], 240 - v0->position[2], v1->position[0], 240 - v1->position[2], v2->position[0], 240 - v2->position[2], rgb0, rgb1, rgb2, (unsigned char)depth);
// Since we have the texture split into two parts, we need to correct the UVs that are *not* on the seam, instead of the other way round
short u0 = !tri->frontFace && !tc0->onSeam ? tc0->u - (model.header->skinWidth >> 1) : tc0->u;
short u1 = !tri->frontFace && !tc1->onSeam ? tc1->u - (model.header->skinWidth >> 1) : tc1->u;
short u2 = !tri->frontFace && !tc2->onSeam ? tc2->u - (model.header->skinWidth >> 1) : tc2->u;
addGouraudTexturedTriangle(
v0->position[0], 240 - v0->position[2],
v1->position[0], 240 - v1->position[2],
v2->position[0], 240 - v2->position[2],
(unsigned char)depth,
rgb0, rgb1, rgb2,
u0, tc0->v, u1, tc1->v, u2, tc2->v, tri->frontFace ? &playerFrontTex : &playerBackTex);
} }
return; return;
@ -312,8 +358,8 @@ void drawStuff(int counter)
addTile(128, 160, 48, 48, r, g, b); addTile(128, 160, 48, 48, r, g, b);
addColoredTriangle(260, 140, 220, 220, 300, 220, 0xFF0000, 0x00FF00, 0x0000FF, 0); addColoredTriangle(260, 140, 220, 220, 300, 220, 0xFF0000, 0x00FF00, 0x0000FF, 0);
addTexturedTriangle(260, 40, 220, 120, 300, 120, 0, 94, 74, 124, 58, 1, &playerTex);
addTexturedSprite(20, 140, 80, 80, &playerTex);
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, &shamblerTex); addTexturedSprite(80, 40, 154, 114, &shamblerTex);
} }

BIN
player.ps1mdl

BIN
player.tim

BIN
player_b.tim

BIN
player_f.tim

16
ps1mdl.h

@ -10,19 +10,25 @@ typedef struct
int ident; int ident;
int version; int version;
unsigned short skinWidth;
unsigned short skinHeight;
unsigned short vertexCount; unsigned short vertexCount;
unsigned short triangleCount; unsigned short triangleCount;
unsigned short frameCount; unsigned short frameCount;
unsigned short pad;
} ps1mdl_header_t; } ps1mdl_header_t;
typedef struct typedef struct
{ {
char onSeam;
short onSeam;
short u, v; short u, v;
} ps1mdl_texcoord_t; } ps1mdl_texcoord_t;
typedef struct typedef struct
{ {
short frontFace;
unsigned short vertexIndex[3]; unsigned short vertexIndex[3];
} ps1mdl_triangle_t; } ps1mdl_triangle_t;
@ -34,10 +40,10 @@ typedef struct
typedef struct typedef struct
{ {
ps1mdl_header_t *header;
ps1mdl_texcoord_t *texCoords;
ps1mdl_triangle_t *triangles;
ps1mdl_vertex_t *vertices;
ps1mdl_header_t* header;
ps1mdl_texcoord_t* texCoords;
ps1mdl_triangle_t* triangles;
ps1mdl_vertex_t* vertices;
} ps1mdl_t; } ps1mdl_t;
#ifdef __cplusplus #ifdef __cplusplus

Loading…
Cancel
Save