#include "driver2.h" #include "draw.h" #include "main.h" #include "map.h" #include "models.h" #include "system.h" #include "camera.h" #include "mission.h" #include "cell.h" #include "tile.h" #include "objanim.h" #include "texture.h" #include "cars.h" #include "debris.h" #include "ASM/rndrasm.h" #include "INLINE_C.H" #include MATRIX aspect = { { { 6553, 0, 0 }, { 0, 4096, 0 }, { 0, 0, 4096 } }, { 0, 0, 0 } }; MATRIX identity = { { { 4096, 0, 0 }, { 0, 4096, 0 }, { 0, 0, 4096 } }, { 0, 0, 0 } }; int PolySizes[56] = { 8, 12, 16, 24, 20, 20, 28, 32, 8, 12, 16, 16, 0, 0, 0, 0, 12, 12, 12, 16, 20, 20, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 8, 12, 16, 24, 20, 24, 28, 32, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 16, 20, 20, 24, 24, }; SVECTOR day_vectors[4] = { { 62404, 2520, 783, 0 }, { 62404, 2520, 783, 0 }, { 63172, 2364, 2364, 0 }, { 62404, 2520, 783, 0 } }; SVECTOR night_vectors[4] = { { 3132, 2520, 783, 0 }, { 3132, 2520, 783, 0 }, { 63172, 2364, 63172, 0 }, { 3132, 2520, 783, 0 } }; SVECTOR day_colours[4] = { { 3200, 3200, 3200, 0 }, { 3200, 3200, 3200, 0 }, { 3200, 3200, 3200, 0 }, { 3200, 3200, 3200, 0 } }; SVECTOR night_colours[4] = { { 880, 880, 905, 0 }, { 880, 880, 905, 0 }, { 880, 880, 905, 0 }, { 880, 880, 905, 0 } }; void* model_object_ptrs[MAX_DRAWN_BUILDINGS]; void* model_tile_ptrs[MAX_DRAWN_TILES]; void* anim_obj_buffer[MAX_DRAWN_ANIMATING]; void* spriteList[MAX_DRAWN_SPRITES]; u_int planeColours[8]; MATRIX inv_camera_matrix; MATRIX face_camera; MATRIX2 CompoundMatrix[64]; uint farClip2Player = 36000; int goFaster = 0; // [A] was 1 int fasterToggle = 0; //int current_object_computed_value = 0; int combointensity; char CurrentPVS[444]; // 20*20+4 MATRIX2 matrixtable[64]; int setupYet = 0; int gDrawDistance = 441; // offset: 0x1f800020 _pct plotContext; // [D] [T] [A] void addSubdivSpriteShadow(POLYFT4* src, SVECTOR* verts, int z) { int m; m = 4; MVERTEX subdiVerts[5][5]; plotContext.colour = 0x2E000000; plotContext.flags = PLOT_INV_CULL; plotContext.clut = texture_cluts[src->texture_set][src->texture_id] << 0x10; plotContext.tpage = texture_pages[src->texture_set] << 0x10; if (z > 3200) m = 1; //2; plotContext.ot += 28; copyVector(&subdiVerts[0][0], &verts[src->v0]); subdiVerts[0][0].uv.val = *(ushort*)&src->uv0; copyVector(&subdiVerts[0][1], &verts[src->v1]); subdiVerts[0][1].uv.val = *(ushort*)&src->uv1; copyVector(&subdiVerts[0][2], &verts[src->v3]); subdiVerts[0][2].uv.val = *(ushort*)&src->uv3; copyVector(&subdiVerts[0][3], &verts[src->v2]); subdiVerts[0][3].uv.val = *(ushort*)&src->uv2; makeMesh((MVERTEX(*)[5][5])subdiVerts, m, m); drawMesh((MVERTEX(*)[5][5])subdiVerts, m, m, &plotContext); plotContext.ot -= 28; } MATRIX shadowMatrix; // [D] [T] [A] void DrawSprites(PACKED_CELL_OBJECT** sprites, int numFound) { int i; int z; uint spriteColour; uint lightdd; unsigned char lightLevel; MODEL* model; PACKED_CELL_OBJECT* pco; PACKED_CELL_OBJECT** list; int numShadows; int count; MVERTEX subdiVerts[5][5]; lightdd = FIXEDH(camera_matrix.m[2][0] * day_vectors[GameLevel].vx) + FIXEDH(camera_matrix.m[2][1] * day_vectors[GameLevel].vy) + FIXEDH(camera_matrix.m[2][2] * day_vectors[GameLevel].vz) + 0x1000 * 0xc00; lightLevel = (lightdd >> 0x12) + 0x20U & 0xff; if (gWeather > 0 && gTimeOfDay == 1) { lightLevel = (lightLevel * 2 * NightAmbient) >> 8 & 0xff; } if (gTimeOfDay == 0) { lightLevel = (lightLevel * 2 * NightAmbient) >> 8; } else if (gTimeOfDay == 2) { lightLevel = (lightLevel * 2 * NightAmbient) >> 8; } else if (gTimeOfDay == 3) { if (GameLevel == 0) lightLevel *= 2; // [A] level bug - Chicago trees lit wrong else lightLevel /= 3; } spriteColour = lightLevel << 0x10 | lightLevel << 8 | 0x2c000000 | lightLevel; i = 2; do { shadowMatrix.m[i][0] = inv_camera_matrix.m[i][2]; shadowMatrix.m[i][1] = -inv_camera_matrix.m[i][0]; shadowMatrix.m[i][2] = inv_camera_matrix.m[i][0]; i--; } while (i >= 0); plotContext.primptr = current->primptr; plotContext.ptexture_pages = (ushort(*)[128])texture_pages; plotContext.ptexture_cluts = (ushort(*)[128][32])texture_cluts; plotContext.polySizes = PolySizes; plotContext.ot = current->ot; list = sprites; plotContext.colour = spriteColour; plotContext.current = current; numShadows = 0; count = numFound - 1; while (count != -1) { pco = *list; list++; int modelnumber = (pco->value >> 6) | (pco->pos.vy & 1) << 10; model = modelpointers[modelnumber]; plotContext.colour = spriteColour; if ((pco->value & 0x3f) == 63 || (gTimeOfDay == 3 && modelnumber == 945)) // [A] Vegas tree fix plotContext.colour = 0x2c808080; plotContext.scribble[0] = pco->pos.vx; plotContext.scribble[1] = (pco->pos.vy << 0x10) >> 0x11; plotContext.scribble[2] = pco->pos.vz; z = Apply_InvCameraMatrixAndSetMatrix((VECTOR_NOPAD*)plotContext.scribble, (MATRIX2*)&face_camera); if (z < 1000) { POLYFT4* src; SVECTOR* verts; int numPolys; numPolys = (uint)model->num_polys; src = (POLYFT4*)model->poly_block; verts = (SVECTOR*)model->vertices; plotContext.flags |= 4; while (numPolys--, numPolys >= 0) { plotContext.clut = texture_cluts[src->texture_set][src->texture_id] << 0x10; plotContext.tpage = texture_pages[src->texture_set] << 0x10; copyVector(&subdiVerts[0][0], &verts[src->v0]); subdiVerts[0][0].uv.val = *(ushort*)&src->uv0; copyVector(&subdiVerts[0][1], &verts[src->v1]); subdiVerts[0][1].uv.val = *(ushort*)&src->uv1; copyVector(&subdiVerts[0][2], &verts[src->v3]); subdiVerts[0][2].uv.val = *(ushort*)&src->uv3; copyVector(&subdiVerts[0][3], &verts[src->v2]); subdiVerts[0][3].uv.val = *(ushort*)&src->uv2; makeMesh((MVERTEX(*)[5][5])subdiVerts, 4, 4); drawMesh((MVERTEX(*)[5][5])subdiVerts, 4, 4, &plotContext); src++; } plotContext.flags &= ~4; } else { plotContext.ot -= 133; Tile1x1(model); plotContext.ot += 133; } count--; #ifdef PSX #define MAX_TREE_SHADOW_DISTANCE 7000 #else #define MAX_TREE_SHADOW_DISTANCE 14000 #endif if (wetness == 0 && gTimeOfDay != 3 && (pco->value & 0x20) == 0 && z < MAX_TREE_SHADOW_DISTANCE && numShadows < 40) { gte_SetRotMatrix(&shadowMatrix); addSubdivSpriteShadow((POLYFT4*)model->poly_block, (SVECTOR*)model->vertices, z); if (model->num_polys == 2) addSubdivSpriteShadow((POLYFT4*)(model->poly_block + sizeof(POLYFT4)), (SVECTOR*)model->vertices, z); gte_SetRotMatrix(&face_camera); numShadows++; } } current->primptr = plotContext.primptr; } // [D] [T] void SetupPlaneColours(uint ambient) { uint r; uint g; uint b; if ((gWeather - 1U > 1) && gTimeOfDay != 0 && gTimeOfDay != 2) { if (gTimeOfDay == 1) { b = ambient & 0xff; g = ambient >> 8 & 0xff; r = ambient >> 0x10 & 0xff; planeColours[1] = (r * 0x78 >> 7) << 0x10 | (g * 0x78 >> 7) << 8 | b * 0x78 >> 7; planeColours[2] = (r * 0x67 >> 7) << 0x10 | (g * 0x67 >> 7) << 8 | b * 0x67 >> 7; planeColours[3] = (r * 0xd >> 5) << 0x10 | (g * 0xd >> 5) << 8 | b * 0xd >> 5; planeColours[0] = r << 0x10 | g << 8 | b; planeColours[4] = (r * 3 >> 3) << 0x10 | (g * 3 >> 3) << 8 | b * 3 >> 3; planeColours[5] = planeColours[3]; planeColours[6] = planeColours[2]; planeColours[7] = planeColours[1]; return; } planeColours[0] = ambient; planeColours[1] = ambient; planeColours[2] = ambient; planeColours[3] = ambient; planeColours[4] = ambient; planeColours[5] = ambient; planeColours[6] = ambient; planeColours[7] = ambient; return; } planeColours[0] = ambient; planeColours[1] = ambient + 0x10101; planeColours[2] = ambient + 0x30303; planeColours[3] = ambient + 0x80808; planeColours[4] = ambient + 0xa0a0a; planeColours[5] = ambient + 0x80808; planeColours[6] = ambient + 0x30303; planeColours[7] = ambient + 0x10101; } // [D] [T] void SetupDrawMapPSX(void) { int region_x1; int region_z1; int current_barrel_region_x1; int current_barrel_region_z1; int theta; current_cell_x = (camera_position.vx + units_across_halved) / MAP_CELL_SIZE; current_cell_z = (camera_position.vz + units_down_halved) / MAP_CELL_SIZE; region_x1 = current_cell_x / MAP_REGION_SIZE; region_z1 = current_cell_z / MAP_REGION_SIZE; current_barrel_region_x1 = (region_x1 & 1); current_barrel_region_z1 = (region_z1 & 1); GetPVSRegionCell2( current_barrel_region_x1 + current_barrel_region_z1 * 2, region_x1 + region_z1 * cells_across / MAP_REGION_SIZE, (current_cell_z % MAP_REGION_SIZE) * MAP_REGION_SIZE + (current_cell_x % MAP_REGION_SIZE), CurrentPVS); for (theta = 0; theta < 64; theta++) MulMatrix0(&inv_camera_matrix, (MATRIX*)&matrixtable[theta], (MATRIX*)&CompoundMatrix[theta]); InitFrustrumMatrix(); SetFrustrumMatrix(); setupYet = 1; } MATRIX frustrum_matrix; // [D] [T] void InitFrustrumMatrix(void) { int a; a = -camera_angle.vy; frustrum_matrix.m[0][1] = 0; frustrum_matrix.m[0][0] = rcossin_tbl[(a & 0xfffU) * 2]; frustrum_matrix.m[0][2] = rcossin_tbl[(a & 0xfffU) * 2 + 1]; a = (FrAng - 1024) - camera_angle.vy; frustrum_matrix.m[1][1] = 0; frustrum_matrix.m[1][0] = rcossin_tbl[(a & 0xfff) * 2]; frustrum_matrix.m[1][2] = rcossin_tbl[(a & 0xfff) * 2 + 1]; a = -(FrAng - 1024) - camera_angle.vy; frustrum_matrix.m[2][1] = 0; frustrum_matrix.m[2][0] = rcossin_tbl[(a & 0xfff) * 2]; frustrum_matrix.m[2][2] = rcossin_tbl[(a & 0xfff) * 2 + 1]; frustrum_matrix.t[0] = -80; } // [D] [T] void SetFrustrumMatrix(void) { gte_SetLightMatrix(&frustrum_matrix); } // [D] [T] void Set_Inv_CameraMatrix(void) { gte_SetColorMatrix(&inv_camera_matrix); } // [D] [T] [A] void CalcObjectRotationMatrices(void) { int i; int angle; MATRIX* m; angle = 0; for (i = 0; i < 64; i++) { // simpler and faster method m = (MATRIX*)&matrixtable[i]; m->m[0][0] = ONE; m->m[0][1] = 0; m->m[0][2] = 0; m->m[1][0] = 0; m->m[1][1] = ONE; m->m[1][2] = 0; m->m[2][0] = 0; m->m[2][1] = 0; m->m[2][2] = ONE; RotMatrixY(angle, m); angle += 64; } } // [D] [T] void PlotMDL_less_than_128(MODEL* model) { RenderModel(model, (MATRIX*)0x0, (VECTOR*)0x0, 0, 0, 0, 0); } int gForceLowDetailCars = 0; int num_cars_drawn = 0; // [D] [T] void DrawAllTheCars(int view) { static int car_distance[MAX_CARS]; // offset 0x0 CAR_DATA* cars_to_draw[MAX_CARS]; int dx, dz; int dist; int i, j; CAR_DATA* cp; int num_cars_to_draw; int spacefree; num_cars_drawn = 0; num_cars_to_draw = 0; cp = &car_data[MAX_CARS - 1]; do { if (cp->controlType != CONTROL_TYPE_NONE && PositionVisible((VECTOR*)cp->hd.where.t)) { // XZ distance estimation dx = ABS(camera_position.vx - cp->hd.where.t[0]); dz = ABS(camera_position.vz - cp->hd.where.t[2]); if (dx < dz) dist = dz + dx / 2; else dist = dx + dz / 2; if (dist < 16000) { car_distance[num_cars_to_draw] = dx + dz; cars_to_draw[num_cars_to_draw] = cp; num_cars_to_draw++; } } cp--; } while (cp >= car_data); if (num_cars_to_draw != 0) { gForceLowDetailCars = 0; // sort cars by distance i = 1; while (i < num_cars_to_draw) { cp = cars_to_draw[i]; dist = car_distance[i]; j = i - 1; while (dist < car_distance[j]) { car_distance[i] = car_distance[j]; cars_to_draw[i] = cars_to_draw[j]; if (j == 0) break; j--; } cars_to_draw[i] = cp; car_distance[i] = dist; i++; } i = 0; spacefree = (num_cars_to_draw - 1) * 2000; while (i < num_cars_to_draw) { // Don't exceed draw buffers if ((int)(current->primtab + (-3000 - (int)(current->primptr - PRIMTAB_SIZE))) < 5800) return; // make cars look uglier if ((int)(current->primtab + (-3000 - (int)(current->primptr - PRIMTAB_SIZE)) - spacefree) < 5800) gForceLowDetailCars = 1; if (cars_to_draw[i]->controlType == CONTROL_TYPE_PLAYER) gForceLowDetailCars = 0; DrawCar(cars_to_draw[i], view); spacefree -= 2000; i++; } } } // [D] [T] u_int normalIndex(SVECTOR* verts, uint vidx) { SVECTOR* v0; SVECTOR* v1; SVECTOR* v2; int ny; int y; int th23; int x; int nz; int nx; SVECTOR p; SVECTOR q; v0 = verts + (vidx & 0xff); v1 = verts + (vidx >> 8 & 0xff); v2 = verts + (vidx >> 16 & 0xff); p.vz = v1->vz - v0->vz; q.vz = v2->vz - v0->vz; p.vy = v1->vy - v0->vy; q.vy = v2->vy - v0->vy; p.vx = v1->vx - v0->vx; q.vx = v2->vx - v0->vx; nx = p.vy * q.vz - p.vz * q.vy; nz = p.vx * q.vy - p.vy * q.vx; x = nx + (nz >> 3); y = nz - (x >> 2); x += (y >> 3); if (x < y) { if (x + y < 1) th23 = y < 0 ? 5 : 4; else th23 = x < 0 ? 3 : 2; } else { if (x + y < 1) th23 = x < 0 ? 6 : 7; else th23 = 0 < y ? 1 : 0; } th23 *= 4; ny = p.vz * q.vx - p.vx * q.vz; nx = ABS(nx); nz = ABS(nz); if (nx + nz < ny) th23 += 1; if (nx + nz < -ny) th23 = th23 & 0x1f | 2; else th23 = th23 & 0x1f; return th23 | 0x80; } // [D] [T] [A] custom void PlotBuildingModelSubdivNxN(MODEL* model, int rot, _pct* pc, int n) { int opz; int diff, minZ, maxZ; int Z; PL_POLYFT4* polys; int i; int r; u_char temp; u_char ptype; POLY_FT4* prims; SVECTOR* srcVerts; MVERTEX subdiVerts[5][5]; int combo; srcVerts = (SVECTOR*)model->vertices; polys = (PL_POLYFT4*)model->poly_block; combo = combointensity; // transparent object flag if (pc->flags & PLOT_TRANSPARENT) combo |= 0x2000000; i = model->num_polys; while (i > 0) { // iterate through polygons // with skipping ptype = polys->id & 0x1f; if ((ptype & 0x1) == 0 && ptype != 8) // is FT3 triangle? { temp = polys->uv2.v; polys->uv3.u = polys->uv2.u; polys->uv3.v = temp; polys->v3 = polys->v2; polys->id |= 1; ptype |= 1; } if (ptype != 11 && ptype != 21 && ptype != 23) { polys = (PL_POLYFT4*)((char*)polys + pc->polySizes[ptype]); i--; continue; } // perform transform gte_ldv3(&srcVerts[polys->v0], &srcVerts[polys->v1], &srcVerts[polys->v3]); gte_rtpt(); // get culling value gte_nclip(); gte_stopz(&opz); r = rot; if (pc->flags & (PLOT_INV_CULL | PLOT_NO_CULL)) { if (opz < 0) r = rot + 32 & 63; if (pc->flags & PLOT_NO_CULL) opz = 1; // no culling else // PLOT_FRONT_CULL opz = -opz; // front face } if (ptype == 21 || (pc->flags & PLOT_NO_SHADE)) { pc->colour = combo & 0x2ffffffU | 0x2c000000; } else { temp = polys->th; if ((polys->th & 0x80) == 0) // cache normal index if it were not temp = polys->th = normalIndex(srcVerts, *(uint*)&polys->v0); pc->colour = pc->f4colourTable[(r >> 3) * 4 - temp & 31]; } if (opz > 0) { gte_stsz3(&pc->scribble[0], &pc->scribble[1], &pc->scribble[2]); pc->tpage = (*pc->ptexture_pages)[polys->texture_set] << 0x10; if ((pc->flags & PLOT_CUSTOM_PALETTE) == 0) // [A] custom palette flag - for pedestrian heads pc->clut = (*pc->ptexture_cluts)[polys->texture_set][polys->texture_id] << 0x10; minZ = pc->scribble[2]; if (pc->scribble[1] < minZ) minZ = pc->scribble[1]; if (pc->scribble[0] < minZ) minZ = pc->scribble[0]; maxZ = pc->scribble[2]; if (maxZ < pc->scribble[1]) maxZ = pc->scribble[1]; diff = maxZ - minZ; if (maxZ < pc->scribble[0]) diff = pc->scribble[0] - minZ; ushort uv0, uv1, uv2, uv3; // [A] special case if(ptype == 23) { POLYGT4* pgt4 = (POLYGT4*)polys; uv0 = *(ushort*)&pgt4->uv0; uv1 = *(ushort*)&pgt4->uv1; uv2 = *(ushort*)&pgt4->uv2; uv3 = *(ushort*)&pgt4->uv3; } else { uv0 = *(ushort*)&polys->uv0; uv1 = *(ushort*)&polys->uv1; uv2 = *(ushort*)&polys->uv2; uv3 = *(ushort*)&polys->uv3; } if (n == 0 || diff << 2 <= minZ - 350) { prims = (POLY_FT4*)pc->primptr; setPolyFT4(prims); *(uint*)&prims->r0 = pc->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 = pc->tpage >> 0x10; prims->clut = pc->clut >> 0x10; *(ushort*)&prims->u0 = uv0; *(ushort*)&prims->u1 = uv1; *(ushort*)&prims->u2 = uv3; *(ushort*)&prims->u3 = uv2; addPrim(pc->ot + (Z >> 1), prims); pc->primptr += sizeof(POLY_FT4); } else { r = n; if (n == 1) { if (minZ - 150 < (diff << 1)) r = 4; else r = 2; } copyVector(&subdiVerts[0][0], &srcVerts[polys->v0]); subdiVerts[0][0].uv.val = uv0; copyVector(&subdiVerts[0][1], &srcVerts[polys->v1]); subdiVerts[0][1].uv.val = uv1; copyVector(&subdiVerts[0][2], &srcVerts[polys->v3]); subdiVerts[0][2].uv.val = uv3; copyVector(&subdiVerts[0][3], &srcVerts[polys->v2]); subdiVerts[0][3].uv.val = uv2; makeMesh((MVERTEX(*)[5][5])subdiVerts, r, r); drawMesh((MVERTEX(*)[5][5])subdiVerts, r, r, pc); } } polys = (PL_POLYFT4*)((char*)polys + pc->polySizes[ptype]); i--; } } // [D] [T] int DrawAllBuildings(CELL_OBJECT** objects, int num_buildings) { int mat; int zbias; int drawlimit; MODEL* model; OTTYPE* ot; CELL_OBJECT* cop; int i; int prev_mat; prev_mat = -1; for (i = 0; i < 8; i++) { plotContext.f4colourTable[i * 4 + 0] = planeColours[i] | 0x2C000000; plotContext.f4colourTable[i * 4 + 1] = planeColours[0] | 0x2C000000; plotContext.f4colourTable[i * 4 + 2] = planeColours[5] | 0x2C000000; plotContext.f4colourTable[i * 4 + 3] = planeColours[0] | 0x2C000000; // default: 0x2C00F0F0 } plotContext.current = current; plotContext.ptexture_pages = &texture_pages; plotContext.ptexture_cluts = &texture_cluts; plotContext.polySizes = PolySizes; plotContext.flags = 0; plotContext.primptr = plotContext.current->primptr; ot = plotContext.current->ot + 8; i = 0; while (i < num_buildings) { cop = (CELL_OBJECT*)*objects; mat = cop->yang; if (prev_mat == mat) { Apply_InvCameraMatrixSetTrans(&cop->pos); } else { Apply_InvCameraMatrixAndSetMatrix(&cop->pos, &CompoundMatrix[mat]); prev_mat = mat; } model = modelpointers[cop->type]; zbias = model->zBias - 64; if (zbias < 0) zbias = 0; plotContext.ot = ot + zbias * 4; PlotBuildingModelSubdivNxN(model, cop->yang, &plotContext, 1); drawlimit = (int)current->primptr - (int)current->primtab; if (PRIMTAB_SIZE - drawlimit < 60000) break; i++; objects++; } // advance primitive buffer current->primptr = plotContext.primptr; return 0; } // [D] [T] void RenderModel(MODEL* model, MATRIX* matrix, VECTOR* pos, int zBias, int flags, int subdiv, int nrot) { int i; if (matrix != NULL) { MATRIX comb; gte_SetTransVector(pos); MulMatrix0(&inv_camera_matrix, matrix, &comb); SetRotMatrix(&comb); } zBias /= 8; zBias += (model->zBias - 64); plotContext.ot = current->ot; if (zBias > 0) plotContext.ot += (zBias * 4); for (i = 0; i < 8; i++) { plotContext.f4colourTable[i * 4 + 0] = planeColours[i] | 0x2C000000; plotContext.f4colourTable[i * 4 + 1] = planeColours[0] | 0x2C000000; plotContext.f4colourTable[i * 4 + 2] = planeColours[5] | 0x2C000000; plotContext.f4colourTable[i * 4 + 3] = planeColours[0] | 0x2C000000; // default: 0x2C00F0F0 } plotContext.ptexture_pages = &texture_pages; plotContext.ptexture_cluts = &texture_cluts; plotContext.polySizes = PolySizes; plotContext.flags = flags; plotContext.current = current; plotContext.primptr = plotContext.current->primptr; if ((current->primtab - (current->primptr - PRIMTAB_SIZE)) > 56000) PlotBuildingModelSubdivNxN(model, nrot, &plotContext, subdiv); // advance primitive buffer current->primptr = plotContext.primptr; } // [D] [T] void DrawMapPSX(int* comp_val) { int dir; PACKED_CELL_OBJECT* ppco; int distScale; int cellx; int cellz; CELL_OBJECT* cop; MODEL* model; int hloop; int vloop; int backPlane; CELL_ITERATOR ci; MATRIX mRotStore; int cellxpos; int cellzpos; char* PVS_ptr; int tiles_found; int other_models_found; int sprites_found; int anim_objs_found; static int treecount = 0; static int alleycount = 0; int rightcos; int rightsin; int leftcos; int leftsin; int backcos; int backsin; int rightPlane; int leftPlane; int farClipLimit; int backAng; int leftAng; int rightAng; int i; int current_object_computed_value; backPlane = 6144; rightPlane = -6144; leftPlane = 6144; farClipLimit = 80000; // setup planes rightAng = camera_angle.vy - FrAng & 0xfff; leftAng = camera_angle.vy + FrAng & 0xfff; backAng = camera_angle.vy + 0x400U & 0xfff; rightcos = rcossin_tbl[rightAng * 2 + 1]; rightsin = rcossin_tbl[rightAng * 2]; leftcos = rcossin_tbl[leftAng * 2 + 1]; leftsin = rcossin_tbl[leftAng * 2]; backcos = rcossin_tbl[backAng * 2 + 1]; backsin = rcossin_tbl[backAng * 2]; if (NumPlayers == 2) { farClipLimit = farClip2Player; } tiles_found = 0; sprites_found = 0; goFaster = goFaster ^ fasterToggle; current_object_computed_value = *comp_val; other_models_found = 0; anim_objs_found = 0; if (setupYet == 0) { SetupDrawMapPSX(); setupYet = 0; } cellzpos = current_cell_z; cellxpos = current_cell_x; // clean cell cache ClearCopUsage(); PVS_ptr = CurrentPVS + 220; vloop = 0; hloop = 0; dir = 0; if (NumPlayers == 2) distScale = goFaster & 31 | 1; else distScale = goFaster & 31; i = (gDrawDistance >> distScale) - 1; // [A] // walk through all cells while (i >= 0) { if (ABS(hloop) + ABS(vloop) < 21) { // clamped vis values int vis_h = MIN(MAX(hloop, -9), 10); int vis_v = MIN(MAX(vloop, -9), 10); cellx = cellxpos + hloop; cellz = cellzpos + vloop; if (rightPlane < 0 && leftPlane > 0 && backPlane < farClipLimit && // check planes cellx > -1 && cellx < cells_across && // check cell ranges cellz > -1 && cellz < cells_down && PVS_ptr[vis_v * pvs_square + vis_h]) // check PVS table { ppco = GetFirstPackedCop(cellx, cellz, &ci, 1); // walk each cell object in cell while (ppco != NULL) { model = modelpointers[(ppco->value >> 6) | ((ppco->pos).vy & 1) << 10]; if (FrustrumCheck16(ppco, model->bounding_sphere) != -1) { // sprity type if (model->shape_flags & SHAPE_FLAG_SMASH_SPRITE) { if (sprites_found < MAX_DRAWN_SPRITES) spriteList[sprites_found++] = ppco; if ((model->flags2 & MODEL_FLAG_ANIMOBJ) && anim_objs_found < 20) { cop = UnpackCellObject(ppco, &ci.nearCell); anim_obj_buffer[anim_objs_found++] = cop; } if (model->flags2 & MODEL_FLAG_TREE) { if (treecount == 0) { cop = UnpackCellObject(ppco, &ci.nearCell); ground_debris[groundDebrisIndex] = *cop; if (groundDebrisIndex < MAX_GROUND_DEBRIS - 1) groundDebrisIndex++; else groundDebrisIndex = 0; } if (treecount < 15) treecount++; else treecount = 0; } } else { int modelNumber; modelNumber = ppco->value & 0x3f; if (modelNumber > 0) { MATRIX2* cmat; cmat = &CompoundMatrix[modelNumber]; if (cmat->computed != current_object_computed_value) { cmat->computed = current_object_computed_value; gte_ReadRotMatrix(&mRotStore); gte_sttr(mRotStore.t); MulMatrix0(&inv_camera_matrix, (MATRIX*)&matrixtable[modelNumber], (MATRIX*)cmat); gte_SetRotMatrix(&mRotStore); } } if ((model->shape_flags & (SHAPE_FLAG_SUBSURFACE | SHAPE_FLAG_ALLEYWAY)) || (model->flags2 & (MODEL_FLAG_SIDEWALK | MODEL_FLAG_GRASS))) { if (model->flags2 & MODEL_FLAG_ALLEY) { alleycount++; if (alleycount == 13) { cop = UnpackCellObject(ppco, &ci.nearCell); ground_debris[groundDebrisIndex] = *cop; if (groundDebrisIndex < MAX_GROUND_DEBRIS - 1) groundDebrisIndex++; else groundDebrisIndex = 0; alleycount = 0; } } if (tiles_found < MAX_DRAWN_TILES) model_tile_ptrs[tiles_found++] = ppco; } else { cop = UnpackCellObject(ppco, &ci.nearCell); if (other_models_found < MAX_DRAWN_BUILDINGS) model_object_ptrs[other_models_found++] = cop; if ((model->flags2 & MODEL_FLAG_ANIMOBJ) && anim_objs_found < MAX_DRAWN_ANIMATING) anim_obj_buffer[anim_objs_found++] = cop; } } } ppco = GetNextPackedCop(&ci); } } } if (dir == 0) { leftPlane += leftcos; backPlane += backcos; rightPlane += rightcos; hloop++; if (hloop + vloop == 1) dir = 1; } else if (dir == 1) { leftPlane += leftsin; backPlane += backsin; rightPlane += rightsin; vloop++; //PVS_ptr += pvs_square; if (hloop == vloop) dir = 2; } else if (dir == 2) { hloop--; leftPlane -= leftcos; backPlane -= backcos; rightPlane -= rightcos; if (hloop + vloop == 0) dir = 3; } else { leftPlane -= leftsin; backPlane -= backsin; rightPlane -= rightsin; vloop--; //PVS_ptr -= pvs_square; if (hloop == vloop) dir = 0; } i--; } #if 0 char tempBuf[512]; SetTextColour(255, 255, 0); sprintf(tempBuf, "Buildings: %d", other_models_found); PrintString(tempBuf, 10, 60); sprintf(tempBuf, "Sprites: %d", sprites_found); PrintString(tempBuf, 10, 75); sprintf(tempBuf, "Tiles: %d", tiles_found); PrintString(tempBuf, 10, 90); sprintf(tempBuf, "Anims: %d", anim_objs_found); PrintString(tempBuf, 10, 105); sprintf(tempBuf, "TOTAL: %d", other_models_found + sprites_found + tiles_found + anim_objs_found); PrintString(tempBuf, 10, 120); #endif SetupPlaneColours(combointensity); if (sprites_found) DrawSprites((PACKED_CELL_OBJECT**)spriteList, sprites_found); if (tiles_found) DrawTILES((PACKED_CELL_OBJECT**)model_tile_ptrs, tiles_found); if (other_models_found) DrawAllBuildings((CELL_OBJECT**)model_object_ptrs, other_models_found); if (anim_objs_found) DrawAllAnimatingObjects((CELL_OBJECT**)anim_obj_buffer, anim_objs_found); }