mirror of
https://github.com/OpenDriver2/REDRIVER2.git
synced 2024-11-22 10:22:48 +01:00
481 lines
10 KiB
C
481 lines
10 KiB
C
#include "driver2.h"
|
|
#include "models.h"
|
|
#include "system.h"
|
|
#include "mission.h"
|
|
#include "draw.h"
|
|
#include "texture.h"
|
|
#include "tile.h"
|
|
|
|
#include "ASM/rndrasm.h"
|
|
|
|
// [D] [T] [A]
|
|
void Tile1x1(MODEL *model)
|
|
{
|
|
int opz, Z;
|
|
int ofse;
|
|
PL_POLYFT4* polys;
|
|
int i;
|
|
u_char ptype;
|
|
POLY_FT4* prims;
|
|
SVECTOR* srcVerts;
|
|
|
|
srcVerts = (SVECTOR*)model->vertices;
|
|
polys = (PL_POLYFT4*)model->poly_block;
|
|
|
|
// grass should be under pavements and other things
|
|
if ((model->shape_flags & SHAPE_FLAG_WATER) || (model->flags2 & MODEL_FLAG_GRASS))
|
|
ofse = 229;
|
|
else
|
|
ofse = 133;
|
|
|
|
#ifdef USE_PGXP
|
|
PGXP_SetZOffsetScale(0.0f, ofse > 200 ? 1.005f : 0.995f);
|
|
#endif
|
|
|
|
i = model->num_polys;
|
|
while (i-- > 0)
|
|
{
|
|
// iterate through polygons
|
|
// with skipping
|
|
ptype = polys->id & 0x1f;
|
|
|
|
// perform transform
|
|
gte_ldv3(&srcVerts[polys->v0], &srcVerts[polys->v1], &srcVerts[polys->v3]);
|
|
gte_rtpt();
|
|
|
|
// get culling value
|
|
gte_nclip();
|
|
gte_stopz(&opz);
|
|
|
|
if (opz > 0)
|
|
{
|
|
prims = (POLY_FT4*)plotContext.primptr;
|
|
|
|
setPolyFT4(prims);
|
|
*(ulong*)&prims->r0 = plotContext.colour;
|
|
|
|
// retrieve first three verts
|
|
gte_stsxy3(&prims->x0, &prims->x1, &prims->x2);
|
|
|
|
// translate 4th vert and get OT Z value
|
|
gte_ldv0(&srcVerts[polys->v2]);
|
|
gte_rtps();
|
|
gte_avsz4();
|
|
|
|
gte_stotz(&Z);
|
|
|
|
gte_stsxy(&prims->x3);
|
|
|
|
prims->tpage = (*plotContext.ptexture_pages)[polys->texture_set];
|
|
prims->clut = (*plotContext.ptexture_cluts)[polys->texture_set][polys->texture_id];
|
|
|
|
*(ushort*)&prims->u0 = *(ushort*)&polys->uv0;
|
|
*(ushort*)&prims->u1 = *(ushort*)&polys->uv1;
|
|
*(ushort*)&prims->u2 = *(ushort*)&polys->uv3;
|
|
*(ushort*)&prims->u3 = *(ushort*)&polys->uv2;
|
|
|
|
addPrim(plotContext.ot + (Z >> 1) + ofse, prims);
|
|
|
|
plotContext.primptr += sizeof(POLY_FT4);
|
|
}
|
|
|
|
polys = (PL_POLYFT4*)((char*)polys + plotContext.polySizes[ptype]);
|
|
}
|
|
|
|
#ifdef USE_PGXP
|
|
PGXP_SetZOffsetScale(0.0f, 1.0f);
|
|
#endif
|
|
|
|
// done
|
|
plotContext.current->primptr = plotContext.primptr;
|
|
}
|
|
|
|
// [D] [T]
|
|
void DrawTILES(PACKED_CELL_OBJECT** tiles, int tile_amount)
|
|
{
|
|
MODEL* pModel;
|
|
PACKED_CELL_OBJECT *ppco;
|
|
PACKED_CELL_OBJECT** tilePointers;
|
|
int previous_matrix, yang, dofse, Z;
|
|
int model_number;
|
|
|
|
if (gTimeOfDay > -1)
|
|
{
|
|
if (gTimeOfDay < 3)
|
|
{
|
|
plotContext.colour = combointensity & 0xffffffU | 0x2C000000;
|
|
}
|
|
else if (gTimeOfDay == 3)
|
|
{
|
|
plotContext.colour = ((combointensity >> 16 & 255) / 3) << 16 | ((combointensity >> 8 & 255) / 3) << 8 | (combointensity & 255) / 3 | 0x2C000000U;
|
|
}
|
|
}
|
|
|
|
previous_matrix = -1;
|
|
|
|
if (gWeather - 1U < 2)
|
|
{
|
|
u_int col;
|
|
col = plotContext.colour >> 2 & 0x3f;
|
|
plotContext.colour = col * 0x30000 | col * 0x300 | col * 3 | 0x2C000000;
|
|
}
|
|
|
|
plotContext.ot = current->ot;
|
|
plotContext.current = current;
|
|
plotContext.primptr = current->primptr;
|
|
plotContext.ptexture_pages = (ushort(*)[128])texture_pages;
|
|
plotContext.ptexture_cluts = (ushort(*)[128][32])texture_cluts;
|
|
plotContext.lastTexInfo = 0x18273472;
|
|
plotContext.flags = 0;
|
|
plotContext.polySizes = PolySizes;
|
|
|
|
tilePointers = (PACKED_CELL_OBJECT **)tiles;
|
|
|
|
while (tile_amount--)
|
|
{
|
|
ppco = *tilePointers++;
|
|
|
|
plotContext.f4colourTable[6] = ppco->pos.vx;
|
|
plotContext.f4colourTable[7] = (ppco->pos.vy << 0x10) >> 0x11;
|
|
plotContext.f4colourTable[8] = ppco->pos.vz;
|
|
|
|
yang = ppco->value & 0x3f;
|
|
model_number = (ppco->value >> 6) | (ppco->pos.vy & 1) << 10;
|
|
|
|
if (previous_matrix == yang)
|
|
{
|
|
Z = Apply_InvCameraMatrixSetTrans((VECTOR_NOPAD *)(plotContext.f4colourTable + 6));
|
|
}
|
|
else
|
|
{
|
|
Z = Apply_InvCameraMatrixAndSetMatrix((VECTOR_NOPAD *)(plotContext.f4colourTable + 6), &CompoundMatrix[previous_matrix = yang]);
|
|
}
|
|
|
|
if (Z <= DRAW_LOD_DIST_HIGH)
|
|
{
|
|
if (Low2HighDetailTable[model_number] != 0xffff)
|
|
model_number = Low2HighDetailTable[model_number];
|
|
|
|
pModel = modelpointers[model_number];
|
|
|
|
if (Z < 2000)
|
|
TileNxN(pModel, 4, 75);
|
|
else
|
|
TileNxN(pModel, 2, 35);
|
|
}
|
|
else
|
|
{
|
|
pModel = Z > DRAW_LOD_DIST_LOW ? pLodModels[model_number] : modelpointers[model_number];
|
|
|
|
Tile1x1(pModel);
|
|
}
|
|
}
|
|
current->primptr = plotContext.primptr;
|
|
}
|
|
|
|
// [A] custom implemented function
|
|
void makeMesh(MVERTEX(*VSP)[5][5], int m, int n)
|
|
{
|
|
/* vertices by index in quad:
|
|
3---------2
|
|
| |
|
|
| |
|
|
| |
|
|
0---------1
|
|
*/
|
|
|
|
// 0 3 2 1
|
|
|
|
// do subdivision
|
|
MVERTEX v1, v2, v3, v4;
|
|
MVERTEX e1, e2, e3, e4, e5;
|
|
MVERTEX p1, p2, p3, p4, p5;
|
|
|
|
if (n < 2)
|
|
return;
|
|
|
|
#if 0
|
|
// no need to subdivide!
|
|
if (g_pgxpZBuffer)
|
|
return;
|
|
#endif
|
|
|
|
v1 = (*VSP)[0][0];
|
|
v2 = (*VSP)[0][1];
|
|
v3 = (*VSP)[0][3];
|
|
v4 = (*VSP)[0][2];
|
|
|
|
VecSubtract(&e1, &v2, &v1); // plane[1] - plane[0];
|
|
e1.uv.s.u0 = (v2.uv.s.u0 - v1.uv.s.u0) / 2;
|
|
e1.uv.s.v0 = (v2.uv.s.v0 - v1.uv.s.v0) / 2;
|
|
|
|
VecSubtract(&e2, &v3, &v4); // plane[2] - plane[3];
|
|
e2.uv.s.u0 = (v3.uv.s.u0 - v4.uv.s.u0) / 2;
|
|
e2.uv.s.v0 = (v3.uv.s.v0 - v4.uv.s.v0) / 2;
|
|
|
|
VecSubtract(&e3, &v4, &v1); // plane[3] - plane[0];
|
|
e3.uv.s.u0 = (v4.uv.s.u0 - v1.uv.s.u0) / 2;
|
|
e3.uv.s.v0 = (v4.uv.s.v0 - v1.uv.s.v0) / 2;
|
|
|
|
VecSubtract(&e4, &v3, &v2); // plane[2] - plane[1];
|
|
e4.uv.s.u0 = (v3.uv.s.u0 - v2.uv.s.u0) / 2;
|
|
e4.uv.s.v0 = (v3.uv.s.v0 - v2.uv.s.v0) / 2;
|
|
|
|
//-----------
|
|
|
|
// half them all
|
|
SetVec(&e1, e1.vx / 2, e1.vy / 2, e1.vz / 2);
|
|
|
|
SetVec(&e2, e2.vx / 2, e2.vy / 2, e2.vz / 2);
|
|
|
|
SetVec(&e3, e3.vx / 2, e3.vy / 2, e3.vz / 2);
|
|
|
|
SetVec(&e4, e4.vx / 2, e4.vy / 2, e4.vz / 2);
|
|
|
|
//-----------
|
|
|
|
VecAdd(&p1, &e1, &v1); // e1 * 0.5f + plane[0];
|
|
p1.uv.s.u0 = e1.uv.s.u0 + v1.uv.s.u0;
|
|
p1.uv.s.v0 = e1.uv.s.v0 + v1.uv.s.v0;
|
|
|
|
VecAdd(&p2, &e2, &v4); // e2 * 0.5f + plane[3];
|
|
p2.uv.s.u0 = e2.uv.s.u0 + v4.uv.s.u0;
|
|
p2.uv.s.v0 = e2.uv.s.v0 + v4.uv.s.v0;
|
|
|
|
VecAdd(&p3, &e3, &v1); // e3 * 0.5f + plane[0];
|
|
p3.uv.s.u0 = e3.uv.s.u0 + v1.uv.s.u0;
|
|
p3.uv.s.v0 = e3.uv.s.v0 + v1.uv.s.v0;
|
|
|
|
VecAdd(&p4, &e4, &v2); // e4 * 0.5f + plane[1];
|
|
p4.uv.s.u0 = e4.uv.s.u0 + v2.uv.s.u0;
|
|
p4.uv.s.v0 = e4.uv.s.v0 + v2.uv.s.v0;
|
|
|
|
//-----------
|
|
|
|
VecSubtract(&e5, &p2, &p1); // p2 - p1;
|
|
e5.uv.s.u0 = (p2.uv.s.u0 - p1.uv.s.u0) / 2;
|
|
e5.uv.s.v0 = (p2.uv.s.v0 - p1.uv.s.v0) / 2;
|
|
|
|
SetVec(&e5, e5.vx / 2, e5.vy / 2, e5.vz / 2);
|
|
|
|
|
|
VecAdd(&p5, &e5, &p1); // e5 * 0.5f + p1;
|
|
p5.uv.s.u0 = e5.uv.s.u0 + p1.uv.s.u0;
|
|
p5.uv.s.v0 = e5.uv.s.v0 + p1.uv.s.v0;
|
|
|
|
//-----------
|
|
|
|
(*VSP)[0][0] = v1; // { plane[0], p1, p5, p3 },
|
|
(*VSP)[0][1] = p1;
|
|
(*VSP)[0][2] = p3;
|
|
(*VSP)[0][3] = p5;
|
|
|
|
(*VSP)[1][0] = p1; // { p1, plane[1], p4, p5 },
|
|
(*VSP)[1][1] = v2;
|
|
(*VSP)[1][2] = p5;
|
|
(*VSP)[1][3] = p4;
|
|
|
|
(*VSP)[2][0] = p5; // { p5, p4, plane[2], p2 },
|
|
(*VSP)[2][1] = p4;
|
|
(*VSP)[2][2] = p2;
|
|
(*VSP)[2][3] = v3;
|
|
|
|
(*VSP)[3][0] = p3; // { p3, p5, p2, plane[3] }
|
|
(*VSP)[3][1] = p5;
|
|
(*VSP)[3][2] = v4;
|
|
(*VSP)[3][3] = p2;
|
|
}
|
|
|
|
|
|
// [A] custom implemented function
|
|
void drawMesh(MVERTEX(*VSP)[5][5], int m, int n, _pct *pc)
|
|
{
|
|
POLY_FT4* prim;
|
|
int z, opz;
|
|
|
|
prim = (POLY_FT4*)pc->primptr;
|
|
|
|
int numPolys = 4;
|
|
|
|
if (n < 2)
|
|
numPolys = 1;
|
|
|
|
#if 0
|
|
// no need to subdivide!
|
|
if (g_pgxpZBuffer)
|
|
numPolys = 1;
|
|
#endif
|
|
|
|
for (int index = 0; index < numPolys; index++)
|
|
{
|
|
setPolyFT4(prim);
|
|
*(ulong*)&prim->r0 = pc->colour; // FIXME: semiTransparency support
|
|
|
|
// test
|
|
gte_ldv3(&(*VSP)[index][0], &(*VSP)[index][1], &(*VSP)[index][2]);
|
|
gte_rtpt();
|
|
gte_nclip();
|
|
gte_stopz(&opz);
|
|
|
|
gte_avsz3();
|
|
|
|
gte_stotz(&z);
|
|
|
|
if (pc->flags & (PLOT_NO_CULL | PLOT_INV_CULL))
|
|
{
|
|
if (pc->flags & PLOT_NO_CULL)
|
|
opz = 1; // no culling
|
|
else // PLOT_FRONT_CULL
|
|
opz = -opz; // front face
|
|
}
|
|
|
|
if (opz > 0 && z > 5)
|
|
{
|
|
gte_stsxy3(&prim->x0, &prim->x1, &prim->x2);
|
|
|
|
gte_ldv0(&(*VSP)[index][3]);
|
|
gte_rtps();
|
|
|
|
|
|
gte_stsxy(&prim->x3);
|
|
|
|
*(ushort*)&prim->u0 = (*VSP)[index][0].uv.val;
|
|
*(ushort*)&prim->u1 = (*VSP)[index][1].uv.val;
|
|
*(ushort*)&prim->u2 = (*VSP)[index][2].uv.val;
|
|
*(ushort*)&prim->u3 = (*VSP)[index][3].uv.val;
|
|
|
|
prim->clut = pc->clut >> 0x10;
|
|
prim->tpage = pc->tpage >> 0x10;
|
|
|
|
addPrim(pc->ot + (z >> 1), prim);
|
|
|
|
prim++;
|
|
}
|
|
}
|
|
|
|
pc->primptr = (char*)prim;
|
|
}
|
|
|
|
// [A] custom implemented function
|
|
void SubdivNxM(char *polys, int n, int m, int ofse)
|
|
{
|
|
MVERTEX subdivVerts[5][5];
|
|
|
|
SVECTOR* verts = plotContext.verts;
|
|
|
|
POLYFT4* pft4 = (POLYFT4*)polys;
|
|
|
|
plotContext.clut = (u_int)(*plotContext.ptexture_cluts)[pft4->texture_set][pft4->texture_id] << 0x10;
|
|
plotContext.tpage = (u_int)(*plotContext.ptexture_pages)[pft4->texture_set] << 0x10;
|
|
|
|
copyVector(&subdivVerts[0][0], &verts[pft4->v0]);
|
|
subdivVerts[0][0].uv.val = *(ushort*)&pft4->uv0;
|
|
|
|
copyVector(&subdivVerts[0][1], &verts[pft4->v1]);
|
|
subdivVerts[0][1].uv.val = *(ushort*)&pft4->uv1;
|
|
|
|
copyVector(&subdivVerts[0][2], &verts[pft4->v3]);
|
|
subdivVerts[0][2].uv.val = *(ushort*)&pft4->uv3;
|
|
|
|
copyVector(&subdivVerts[0][3], &verts[pft4->v2]);
|
|
subdivVerts[0][3].uv.val = *(ushort*)&pft4->uv2;
|
|
|
|
plotContext.ot += ofse;
|
|
|
|
makeMesh((MVERTEX(*)[5][5])subdivVerts, m, n);
|
|
drawMesh((MVERTEX(*)[5][5])subdivVerts, m, n, &plotContext);
|
|
|
|
plotContext.ot -= ofse;
|
|
}
|
|
|
|
// [D] [T]
|
|
void TileNxN(MODEL *model, int levels, int Dofse)
|
|
{
|
|
u_int ttype, tileTypes;
|
|
u_char *polys;
|
|
int i;
|
|
int ofse;
|
|
|
|
polys = (u_char *)model->poly_block;
|
|
plotContext.verts = (SVECTOR *)model->vertices;
|
|
|
|
// WEIRD: tile types comes right after model header it seems
|
|
tileTypes = *(u_int *)(model + 1) >> 2;
|
|
|
|
// grass should be under pavements and other things
|
|
if((model->shape_flags & SHAPE_FLAG_WATER) || (model->flags2 & MODEL_FLAG_GRASS))
|
|
ofse = 229;
|
|
else
|
|
ofse = 133;
|
|
|
|
int _m[5] = {
|
|
levels, levels, 0, 1, levels
|
|
};
|
|
int _ofse[5] = {
|
|
ofse, ofse, 0, Dofse, 133
|
|
};
|
|
|
|
i = model->num_polys;
|
|
ttype = 0;
|
|
while (i--)
|
|
{
|
|
#ifdef USE_PGXP
|
|
switch (ttype)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
PGXP_SetZOffsetScale(0.0f, ofse > 200 ? 1.008f : 0.995f);
|
|
break;
|
|
case 3:
|
|
PGXP_SetZOffsetScale(0.0f, ofse < 40 ? 1.0f : 0.991f);
|
|
break;
|
|
case 4:
|
|
PGXP_SetZOffsetScale(0.0f, 1.0f);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
SubdivNxM((char*)polys, levels, _m[ttype], _ofse[ttype]);
|
|
|
|
ttype = tileTypes & 7;
|
|
tileTypes >>= 3;
|
|
|
|
polys += plotContext.polySizes[*polys];
|
|
}
|
|
|
|
#ifdef USE_PGXP
|
|
PGXP_SetZOffsetScale(0.0f, 1.0f);
|
|
#endif
|
|
}
|
|
|
|
void ProcessSubDivisionLump(char *lump_ptr, int lump_size)
|
|
{
|
|
// Driver 1 leftover...
|
|
UNIMPLEMENTED();
|
|
/*
|
|
SubDivisionArrays = lump_ptr;
|
|
return;*/
|
|
}
|
|
|
|
// [D] [T]
|
|
void ProcessLowDetailTable(char *lump_ptr, int lump_size)
|
|
{
|
|
int i;
|
|
|
|
Low2HighDetailTable = (ushort *)lump_ptr;
|
|
Low2LowerDetailTable = Low2HighDetailTable + num_models_in_pack;
|
|
|
|
for (i = 0; i < num_models_in_pack; i++)
|
|
{
|
|
if (Low2LowerDetailTable[i] != 0xFFFF)
|
|
pLodModels[i] = modelpointers[Low2LowerDetailTable[i]];
|
|
else
|
|
pLodModels[i] = modelpointers[i];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|