#include #include "MyPad.h" #include "tmd.h" #include "fractal.h" #define TMD_DYNAMIC_START (0x80090000) #define OT_LENGTH 12 #define PACKETMAX 8192 #define PACKETMAX2 (PACKETMAX*24) #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 256 // A nice, simple macro ;-) // I know I've seen this somewhere before but I can't remember where #define LimitRange(a, b, c) ( ((a)<(b)) ? (b) : ((a)>(c) ? (c) : (a)) ) #define DotProduct(a, b) ( ((a).vx*(b).vx) + ((a).vy*(b).vy) + ((a).vz*(b).vz) ) typedef struct { int loCount, hiCount; GsDOBJ2 hiHandler[(MAP_SIZE*MAP_SIZE)>>4]; GsDOBJ2 loHandler[(MAP_SIZE*MAP_SIZE)>>4]; GsCOORDINATE2 coord; } WorldType; GsOT WorldOT[2]; GsOT_TAG OTTags[2][1<>8; view.vpz += move.vz>>8; } if (pad & PADLdown) { view.vpx -= move.vx>>8; view.vpz -= move.vz>>8; } if (pad & PADLR1) { view.vpx -= strafe.vx>>8; view.vpz -= strafe.vz>>8; } if (pad & PADLL1) { view.vpx += strafe.vx>>8; view.vpz += strafe.vz>>8; } view.vrx = view.vpx + camera.vx; view.vrz = view.vpz + camera.vz; view.vpy = Blend(view.vpx, view.vpz, map[(view.vpx>>7)][(view.vpz>>7)], map[(view.vpx>>7)+1][(view.vpz>>7)], map[(view.vpx>>7)][(view.vpz>>7)+1], map[(view.vpx>>7)+1][(view.vpz>>7)+1])*2+128; view.vry = Blend(view.vrx, view.vrz, map[(view.vrx>>7)][(view.vrz>>7)], map[(view.vrx>>7)+1][(view.vrz>>7)], map[(view.vrx>>7)][(view.vrz>>7)+1], map[(view.vrx>>7)+1][(view.vrz>>7)+1])*2+96; // It was pointed out to me by my rather clever flatmate // that a 3x3 matrix could be used to represent the corners // of the view conde and using RotMatrix() the view cone can // easily be rotated. Cunning eh? temp.m[0][0] = 0; temp.m[2][0] = -3; temp.m[0][1] = -6; temp.m[2][1] = 9; temp.m[0][2] = 6; temp.m[2][2] = 9; RotMatrixY(rot, &temp); GsSetRefView2(&view); DrawWorld(activeBuff, temp.m[0][0], temp.m[2][0], temp.m[0][1], temp.m[2][1], temp.m[0][2], temp.m[2][2], view.vpx, view.vpz); DrawSync(0); hsync = VSync(0); GsSwapDispBuff(); GsSortClear(0, 0, 0, &WorldOT[activeBuff]); GsDrawOt(&WorldOT[activeBuff]); if (hsync > maxHsync) maxHsync = hsync; FntPrint(0,"%d, %d\n",view.vpx>>7, view.vpz>>7); FntPrint(0,"%d, %d\n",hsync, maxHsync); FntFlush(-1); } while ((pad != PADLstart+PADLselect) && (pad != PADRselect+PADRstart)); } void InitGame(void) { int i, j; SetVideoMode(MODE_PAL); GsInitGraph(SCREEN_WIDTH, SCREEN_HEIGHT, GsINTER|GsOFSGPU, 1, 0); GsDefDispBuff(0, 0, 0, 256); GsInit3D(); GsDISPENV.screen.h = 255; GetPadBuf(&bb0, &bb1); lights[0].vx = 2048; lights[0].vy = 1024; lights[0].vz = 2048; lights[0].r = 255; lights[0].g = 255; lights[0].b = 255; GsSetFlatLight(0, &lights[0]); for (i = 0; i < 2; i++) { WorldOT[i].length = OT_LENGTH; WorldOT[i].org = OTTags[i]; GsClearOt(0,0,&WorldOT[i]); } for (j=-16; j<16; j++) { for (i=-16; i<16; i++) { if (i*i+j*j < 8) hiRes[i+16][j+16] = 1; else hiRes[i+16][j+16] = 0; } } } void BuildWorld(void) { u_long *pointer; int i, j, x, y; u_long address = TMD_DYNAMIC_START; VERTEX v[25]; COLOUR rgb[25]; u_char r[MAP_SIZE][MAP_SIZE], lor[4]; u_char g[MAP_SIZE][MAP_SIZE], log[4]; u_char b[MAP_SIZE][MAP_SIZE], lob[4]; u_char n; // Get Landscape colour for (j=0; j>2) + 63; g[i][j] = map[i][j]; b[i][j] = rand(); } } // Work out lighting for (j=0; j>7, 0, 255); g[i][j] = LimitRange((g[i][j] * n)>>7, 0, 255); b[i][j] = LimitRange((b[i][j] * n)>>7, 0, 255); } } // Build World world.loCount = world.hiCount = 0; for (j=2; jcoord); // Top of model data pointer += 2; GsLinkObject4((u_long )pointer, &handler[index], 0); handler[index].attribute = (1<<9); handler[index].coord2 = &world->coord; world->coord.coord.t[0] = 0; world->coord.coord.t[1] = 0; world->coord.coord.t[2] = 0; world->coord.flg = 0; (*count)++; } // Go on, take a guess... inline void swap(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } // Draw slice of the world void DrawWorld(int activeBuff, int x0, int z0, int x1, int z1, int x2, int z2, int xOffset, int zOffset) { int x, z, index; // Loop variables int lx0, lx1, dx0, dx1; // Accurate coords int *px0, *px1; // Pointers to accurate int sx, ex; // Row start & end MATRIX ls, lw; // Local screen & world x0 += xOffset>>9; x1 += xOffset>>9; x2 += xOffset>>9; z0 += zOffset>>9; z1 += zOffset>>9; z2 += zOffset>>9; xOffset = (xOffset-256)>>9; zOffset = (zOffset-256)>>9; // Sort verticies in z-order if (z0>z1) { swap(&x0, &x1); swap(&z0, &z1); } if (z1>z2) { swap(&x1, &x2); swap(&z1, &z2); } if (z0>z1) { swap(&x0, &x1); swap(&z0, &z1); } // Initialse accurate variables lx0 = lx1 = x0<<10; // Get gradients for triangle edges if (z0 != z1) dx0 = ((x1-x0)<<10) / (z1-z0); else { lx0 = x1<<10; // A bodge to fix a z0==z1 problem dx0 = (x1-x0)<<10; } if (z0 != z2) dx1 = ((x2-x0)<<10) / (z2-z0); else dx1 = (x2-x0)<<10; if (dx0 < dx1) { px0 = &lx0; px1 = &lx1; } else { px0 = &lx1; px1 = &lx0; } GsGetLws(world.hiHandler[0].coord2, &lw, &ls); // All the coord2's are the same GsSetLsMatrix(&ls); // Same goes for the ls matrix for (z=z0; z=0 && z>2) { sx = LimitRange((*px0)>>10, 0, (MAP_SIZE>>2)-1); ex = LimitRange(((*px1)>>10)+1, 0, (MAP_SIZE>>2)-1); index = sx+z*(MAP_SIZE>>2); for (x=sx; x=0 && z>2) { sx = LimitRange((*px0)>>10, 0, (MAP_SIZE>>2)-1); ex = LimitRange(((*px1)>>10)+1, 0, (MAP_SIZE>>2)-1); index = sx+z*(MAP_SIZE>>2); for (x=sx; x>14); } // Calculate landscape shading u_char GetNormal(int y0, int y1, int y2, int y3) { int nx, ny, nz, div; u_char n0, n1; long mul; nx = y0-y1; ny = 32; nz = y0-y2; div = IntSqrt(nx*nx+ny*ny+nz*nz); nx = 128*nx/div; ny = 128*ny/div; nz = 128*nz/div; mul = ((nx*lights[0].vx) + (ny*lights[0].vy) + (nz*lights[0].vz))>>11; n0 = LimitRange(mul, 32, 255); nx = y2-y3; ny = 32; nz = y1-y3; div = IntSqrt(nx*nx+ny*ny+nz*nz); nx = 128*nx/div; ny = 128*ny/div; nz = 128*nz/div; mul = ((nx*lights[0].vx) + (ny*lights[0].vy) + (nz*lights[0].vz))>>11; n1 = LimitRange(mul, 32, 255); return ((n0 + n1) >> 1); } // Make a hi-res patch void MakePatch(COLOUR *rgb, VERTEX *v, u_char r[MAP_SIZE][MAP_SIZE], u_char g[MAP_SIZE][MAP_SIZE], u_char b[MAP_SIZE][MAP_SIZE], int i, int j) { int x, y, a=0; for (y=j; y 0; i >>= 2, k0 <<= 1) ; nn <<= 2; for (;;) { k1 = (nn / k0 + k0) >> 1; if (((k0 ^ k1) & ~1) == 0) break; k0 = k1; } return (int )((k1 + 1) >> 1); } u_long ReadPad(void) { return(~(*(bb0+3) | *(bb0+2) << 8 | *(bb1+3) << 16 | *(bb1+2) << 24)); }