diff options
| author | John Wilbert M. Villamor <lameguy64@gmail.com> | 2019-07-18 09:19:44 +0800 |
|---|---|---|
| committer | John Wilbert M. Villamor <lameguy64@gmail.com> | 2019-07-18 09:19:44 +0800 |
| commit | c2a6d21dcb8067599f710b349067488f7d00e4b5 (patch) | |
| tree | 79c3e72364f69107bc76e4f7c22743aab8b65d1f | |
| parent | 0d4345a9bf2623df079c50a3bc73cbb7deca1176 (diff) | |
| download | psn00bsdk-c2a6d21dcb8067599f710b349067488f7d00e4b5.tar.gz | |
Added fpscam example, added small descriptions to examples, minor readme changes
| -rw-r--r-- | README.md | 31 | ||||
| -rw-r--r-- | changelog.txt | 9 | ||||
| -rw-r--r-- | examples/balls/main.c | 4 | ||||
| -rw-r--r-- | examples/fpscam/clip.c | 108 | ||||
| -rw-r--r-- | examples/fpscam/clip.h | 27 | ||||
| -rw-r--r-- | examples/fpscam/lookat.c | 40 | ||||
| -rw-r--r-- | examples/fpscam/lookat.h | 19 | ||||
| -rw-r--r-- | examples/fpscam/main.c | 654 | ||||
| -rw-r--r-- | examples/fpscam/makefile | 39 | ||||
| -rw-r--r-- | examples/gte/main.c | 4 |
10 files changed, 920 insertions, 15 deletions
@@ -28,7 +28,7 @@ performance reasons. ## Notable features -As of libpsn00b run-time library v0.11b +As of libpsn00b run-time library v0.12b * Extensive GPU support with polygon primitives, high-speed DMA VRAM transfers and DMA ordering table processing. All video modes for both NTSC @@ -66,7 +66,7 @@ As of libpsn00b run-time library v0.11b ## Obtaining PSn00bSDK Because PSn00bSDK is updated semi-regularly due to this project being in -a work-in-progress state, it is better to obtain this SDK from source by +a work-in-progress state, it is better to obtain this SDK from source and building it yourself in the long run. Prepared packages containing precompiled libpsn00b libraries, the toolchain and additional utilities not included in this repository for Windows users are planned, though some @@ -77,7 +77,7 @@ A precompiled copy of the GCC 7.4.0 toolchain for Windows is available in the PSn00bSDK page of Lameguy64's website ( http://lameguy64.tk/?page=psn00bsdk ). This should make building PSn00bSDK under Windows a bit easier as building the toolchain is the hardest part -of building PSn00bSDK as its more difficult to get it to compile correctly +of building PSn00bSDK, as its more difficult to get it to compile correctly under Windows than on Linux and BSDs. @@ -92,10 +92,10 @@ under Windows than on Linux and BSDs. following packages: * git * make - * mingw-w64-i686-gcc (for 32-bit) or mingw-w64-x86_64-gcc (64-bit) + * mingw-w64-i686-gcc (32-bit) or mingw-w64-x86_64-gcc (64-bit) + You will need to close and reopen MSys2 for the PATH environment to + update for MinGW. * mingw-w64-i686-tinyxml2 (32-bit) or mingw-w64-x86_64-tinyxml2 (64-bit) - You will need to close and reopen MSys2 for the PATH environment to - update for MinGW. 3. Extract GCC 7.4.0 for mipsel-unknown-elf to the root of your C drive. 4. Edit `mipsel-unknown-elf/mipsel-unknown-elf/lib/ldscripts/elf32elmip.x` and update the .text definitions as explained in toolchain.txt. @@ -150,22 +150,27 @@ and contributed example programs are welcome. ## To-do List -* psxgpu: VRAM move function, some primitives and macros yet to be +* psxgpu: VRAM move function, few more primitives and macros yet to be implemented. -* psxgte: Higher level GTE rotate translate and perspective functions - yet to be implemented. +* psxgte: Higher level GTE rotate translate and perspective functions, + and many matrix transformation functions yet to be implemented. * psxspu: Plenty of work to be done. -* psxapi: BIOS function calls intended for stdio may need to be in - libc instead. +* psxapi: BIOS function calls intended for stdio may need to be moved + to libc instead. * psxetc: Text stream stuff (FntOpen(), FntPrint(), FndFlush()) for debug purposes yet to be implemented. -* Libraries yet to be made: psxcd (for better CD-ROM support) and - psxmdec (MDEC support). +* And many more. + +There's been some working prototype CD-ROM code in the works for PSn00bSDK +that is functional enough to play CD Audio tracks. The prototype code can +be found in the SVN repo of PSn00bSDK which can be found in the PSn00bSDK +page of Lameguy64's website, if you're interested to work on the CD-ROM +implementation yourself. ## Usage terms diff --git a/changelog.txt b/changelog.txt index 8c50718..20f77a3 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,15 @@ PSn00bSDK changelog Items that are lower in the log are more recently implemented. +07-18-2019 by Lameguy64: + +* Added fpscam example. + +* Gave examples small descriptions. + +* Updated readme a little. + + 07-17-2019 by Lameguy64: * LibPSn00b run-time library is officially version 1.12b. diff --git a/examples/balls/main.c b/examples/balls/main.c index 1be49e0..4f3ab14 100644 --- a/examples/balls/main.c +++ b/examples/balls/main.c @@ -4,7 +4,9 @@ * Balls Example * 2019 Meido-Tek Productions / PSn00bSDK Project * - * To build, simply run make. + * Draws a bunch of ball sprites that bounce around the screen, + * along with a ball snake that might be difficult to see. + * * * Example by Lameguy64 * diff --git a/examples/fpscam/clip.c b/examples/fpscam/clip.c new file mode 100644 index 0000000..7f2b780 --- /dev/null +++ b/examples/fpscam/clip.c @@ -0,0 +1,108 @@ +/* Polygon clip detection code + * + * The polygon clipping logic is based on the Cohen-Sutherland algorithm, but + * only the off-screen detection logic is used to determine which polygon edges + * are off-screen. + * + * In tri_clip, the following edges are checked as follows: + * + * |\ + * | \ + * | \ + * | \ + * |-------- + * + * In quad_clip, the following edges are checked as follows: + * + * |---------| + * | \ / | + * | \ / | + * | / \ | + * | / \ | + * |---------| + * + * The inner portion of the quad is checked, otherwise the quad will be + * culled out if the camera faces right into it, where all four edges + * are off-screen at once. + * + */ + +#include "clip.h" + +#define CLIP_LEFT 1 +#define CLIP_RIGHT 2 +#define CLIP_TOP 4 +#define CLIP_BOTTOM 8 + +int test_clip(RECT *clip, short x, short y) { + + // Tests which corners of the screen a point lies outside of + + int result = 0; + + if ( x < clip->x ) { + result |= CLIP_LEFT; + } + + if ( x >= (clip->x+(clip->w-1)) ) { + result |= CLIP_RIGHT; + } + + if ( y < clip->y ) { + result |= CLIP_TOP; + } + + if ( y >= (clip->y+(clip->h-1)) ) { + result |= CLIP_BOTTOM; + } + + return result; + +} + +int tri_clip(RECT *clip, DVECTOR *v0, DVECTOR *v1, DVECTOR *v2) { + + // Returns non-zero if a triangle is outside the screen boundaries + + short c[3]; + + c[0] = test_clip(clip, v0->vx, v0->vy); + c[1] = test_clip(clip, v1->vx, v1->vy); + c[2] = test_clip(clip, v2->vx, v2->vy); + + if ( ( c[0] & c[1] ) == 0 ) + return 0; + if ( ( c[1] & c[2] ) == 0 ) + return 0; + if ( ( c[2] & c[0] ) == 0 ) + return 0; + + return 1; +} + +int quad_clip(RECT *clip, DVECTOR *v0, DVECTOR *v1, DVECTOR *v2, DVECTOR *v3) { + + // Returns non-zero if a quad is outside the screen boundaries + + short c[4]; + + c[0] = test_clip(clip, v0->vx, v0->vy); + c[1] = test_clip(clip, v1->vx, v1->vy); + c[2] = test_clip(clip, v2->vx, v2->vy); + c[3] = test_clip(clip, v3->vx, v3->vy); + + if ( ( c[0] & c[1] ) == 0 ) + return 0; + if ( ( c[1] & c[2] ) == 0 ) + return 0; + if ( ( c[2] & c[3] ) == 0 ) + return 0; + if ( ( c[3] & c[0] ) == 0 ) + return 0; + if ( ( c[0] & c[2] ) == 0 ) + return 0; + if ( ( c[1] & c[3] ) == 0 ) + return 0; + + return 1; +}
\ No newline at end of file diff --git a/examples/fpscam/clip.h b/examples/fpscam/clip.h new file mode 100644 index 0000000..3b428bb --- /dev/null +++ b/examples/fpscam/clip.h @@ -0,0 +1,27 @@ +#ifndef _CLIP_H +#define _CLIP_H + +#include <psxgte.h> +#include <psxgpu.h> + +/* tri_clip + * + * Returns non-zero if a triangle (v0, v1, v2) is outside 'clip'. + * + * clip - Clipping area + * v0,v1,v2 - Triangle coordinates + * + */ +int tri_clip(RECT *clip, DVECTOR *v0, DVECTOR *v1, DVECTOR *v2); + +/* quad_clip + * + * Returns non-zero if a quad (v0, v1, v2, v3) is outside 'clip'. + * + * clip - Clipping area + * v0,v1,v2,v3 - Quad coordinates + * + */ +int quad_clip(RECT *clip, DVECTOR *v0, DVECTOR *v1, DVECTOR *v2, DVECTOR *v3); + +#endif // _CLIP_H
\ No newline at end of file diff --git a/examples/fpscam/lookat.c b/examples/fpscam/lookat.c new file mode 100644 index 0000000..d7c9ce4 --- /dev/null +++ b/examples/fpscam/lookat.c @@ -0,0 +1,40 @@ +// LookAt matrix code (may be implemented into libpsxgte soon) + +#include "lookat.h" + +void crossProduct(SVECTOR *v0, SVECTOR *v1, VECTOR *out) { + + out->vx = ((v0->vy*v1->vz)-(v0->vz*v1->vy))>>12; + out->vy = ((v0->vz*v1->vx)-(v0->vx*v1->vz))>>12; + out->vz = ((v0->vx*v1->vy)-(v0->vy*v1->vx))>>12; + +} + +void LookAt(VECTOR *eye, VECTOR *at, SVECTOR *up, MATRIX *mtx) { + + VECTOR taxis; + SVECTOR zaxis; + SVECTOR xaxis; + SVECTOR yaxis; + VECTOR pos; + VECTOR vec; + + setVector(&taxis, at->vx-eye->vx, at->vy-eye->vy, at->vz-eye->vz); + VectorNormalS(&taxis, &zaxis); + crossProduct(&zaxis, up, &taxis); + VectorNormalS(&taxis, &xaxis); + crossProduct(&zaxis, &xaxis, &taxis); + VectorNormalS(&taxis, &yaxis); + + mtx->m[0][0] = xaxis.vx; mtx->m[1][0] = yaxis.vx; mtx->m[2][0] = zaxis.vx; + mtx->m[0][1] = xaxis.vy; mtx->m[1][1] = yaxis.vy; mtx->m[2][1] = zaxis.vy; + mtx->m[0][2] = xaxis.vz; mtx->m[1][2] = yaxis.vz; mtx->m[2][2] = zaxis.vz; + + pos.vx = -eye->vx;; + pos.vy = -eye->vy;; + pos.vz = -eye->vz;; + + ApplyMatrixLV(mtx, &pos, &vec); + TransMatrix(mtx, &vec); + +}
\ No newline at end of file diff --git a/examples/fpscam/lookat.h b/examples/fpscam/lookat.h new file mode 100644 index 0000000..c57e50a --- /dev/null +++ b/examples/fpscam/lookat.h @@ -0,0 +1,19 @@ +#ifndef _LOOKAT_H +#define _LOOKAT_H + +#include <psxgte.h> +#include <psxgpu.h> + +/* LookAt + * + * Generates a matrix that looks from 'eye' to 'at'. + * + * eye - Position of viewpoint + * at - Position to 'look at' from viewpoint + * up - Vector that defines the 'up' direction + * mtx - Matrix output + * + */ +void LookAt(VECTOR *eye, VECTOR *at, SVECTOR *up, MATRIX *mtx); + +#endif // _LOOKAT_H
\ No newline at end of file diff --git a/examples/fpscam/main.c b/examples/fpscam/main.c new file mode 100644 index 0000000..0cde9f5 --- /dev/null +++ b/examples/fpscam/main.c @@ -0,0 +1,654 @@ +/* + * LibPSn00b Example Programs + * + * First-Person and Look-At Camera Example + * 2019 Meido-Tek Productions / PSn00bSDK Project + * + * Demonstrates both a first person perspective camera implementation with + * full six degrees of movement using fixed point integer math and a look-at + * tracking perspective. This example also shows how to use BIOS controller + * functions and how to parse analog controller input. + * + * Controls: + * Up - Look up + * Down - Look down + * Left - Look left + * Right - Look right + * Triangle - Move forward + * Cross - Move backward + * Square - Strafe left + * Circle - Strafe right + * R1 - Slide up + * R2 - Slide down + * L1 - Look at cube + * + * + * Example by Lameguy64 + * + * Changelog: + * + * July 18, 2019 - Initial version. + * + */ + +#include <stdio.h> +#include <psxgpu.h> +#include <psxgte.h> +#include <psxpad.h> +#include <psxapi.h> +#include <inline_c.h> + +#include "clip.h" +#include "lookat.h" + +// OT and Packet Buffer sizes +#define OT_LEN 1024 +#define PACKET_LEN 8192 + +// Screen resolution +#define SCREEN_XRES 320 +#define SCREEN_YRES 240 + +// Screen center position +#define CENTERX SCREEN_XRES>>1 +#define CENTERY SCREEN_YRES>>1 + + +// Double buffer structure +typedef struct { + DISPENV disp; // Display environment + DRAWENV draw; // Drawing environment + int ot[OT_LEN]; // Ordering table + char p[PACKET_LEN]; // Packet buffer +} DB; + +// Double buffer variables +DB db[2]; +int db_active = 0; +char *db_nextpri; +RECT screen_clip; + +// Pad data buffer +char pad_buff[2][34]; + + +// For easier handling of vertex indexes +typedef struct { + short v0,v1,v2,v3; +} INDEX; + +// Cube vertices +SVECTOR cube_verts[] = { + { -100, -100, -100, 0 }, + { 100, -100, -100, 0 }, + { -100, 100, -100, 0 }, + { 100, 100, -100, 0 }, + { 100, -100, 100, 0 }, + { -100, -100, 100, 0 }, + { 100, 100, 100, 0 }, + { -100, 100, 100, 0 } +}; + +// Cube face normals +SVECTOR cube_norms[] = { + { 0, 0, -ONE, 0 }, + { 0, 0, ONE, 0 }, + { 0, -ONE, 0, 0 }, + { 0, ONE, 0, 0 }, + { -ONE, 0, 0, 0 }, + { ONE, 0, 0, 0 } +}; + +// Cube vertex indices +INDEX cube_indices[] = { + { 0, 1, 2, 3 }, + { 4, 5, 6, 7 }, + { 5, 4, 0, 1 }, + { 6, 7, 3, 2 }, + { 0, 2, 5, 7 }, + { 3, 1, 6, 4 } +}; + +// Number of faces of cube +#define CUBE_FACES 6 + + +// Light color matrix +// Each column represents the color matrix of each light source and is +// used as material color when using gte_ncs() or multiplied by a +// source color when using gte_nccs(). 4096 is 1.0 in this matrix +// A column of zeroes effectively disables the light source. +MATRIX color_mtx = { + ONE, 0, 0, // Red + 0, 0, 0, // Green + ONE, 0, 0 // Blue +}; + +// Light matrix +// Each row represents a vector direction of each light source. +// An entire row of zeroes effectively disables the light source. +MATRIX light_mtx = { + /* X, Y, Z */ + -2048 , -2048 , -2048, + 0 , 0 , 0, + 0 , 0 , 0 +}; + + +// Function declarations +void init(); +void display(); +void sort_cube(MATRIX *mtx, VECTOR *pos, SVECTOR *rot); + + +// Main function +int main() { + + int i,p,xy_temp; + int px,py; + + SVECTOR rot; // Rotation vector for cube + VECTOR pos; // Position vector for cube + + SVECTOR verts[17][17]; // Vertex array for floor + + VECTOR cam_pos; // Camera position (in fixed point integers) + VECTOR cam_rot; // Camera view angle (in fixed point integers) + int cam_mode; // Camera mode (between first-person and look-at) + + VECTOR tpos; // Translation value for matrix calculations + SVECTOR trot; // Rotation value for matrix calculations + MATRIX mtx,lmtx; // Rotation matrices for geometry and lighting + + PADTYPE *pad; // Pad structure pointer for parsing controller + + POLY_F4 *pol4; // Flat shaded quad primitive pointer + + + // Init graphics and GTE + init(); + + + // Set coordinates to the vertex array for the floor + for( py=0; py<17; py++ ) { + for( px=0; px<17; px++ ) { + + setVector( &verts[py][px], + (100*(px-8))-50, + 0, + (100*(py-8))-50 ); + + } + } + + + // Camera default coordinates + setVector( &cam_pos, 0, ONE*-200, 0 ); + setVector( &cam_rot, 0, 0, 0 ); + + + // Main loop + while( 1 ) { + + // Set pad buffer data to pad pointer + pad = (PADTYPE*)&pad_buff[0][0]; + + // Parse controller input + cam_mode = 0; + + // Divide out fractions of camera rotation + trot.vx = cam_rot.vx >> 12; + trot.vy = cam_rot.vy >> 12; + trot.vz = cam_rot.vz >> 12; + + if( pad->stat == 0 ) { + + // For digital pad, dual-analog and dual-shock + if( ( pad->type == 0x4 ) || ( pad->type == 0x5 ) || ( pad->type == 0x7 ) ) { + + // The button status bits are inverted, + // so 0 means pressed in this case + + // Look controls + if( !(pad->btn&PAD_UP) ) { + + // Look up + cam_rot.vx -= ONE*8; + + } else if( !(pad->btn&PAD_DOWN) ) { + + // Look down + cam_rot.vx += ONE*8; + + } + + if( !(pad->btn&PAD_LEFT) ) { + + // Look left + cam_rot.vy += ONE*8; + + } else if( !(pad->btn&PAD_RIGHT) ) { + + // Look right + cam_rot.vy -= ONE*8; + + } + + // Movement controls + if( !(pad->btn&PAD_TRIANGLE) ) { + + // Move forward + cam_pos.vx -= (( isin( trot.vy )*icos( trot.vx ) )>>12)<<2; + cam_pos.vy += isin( trot.vx )<<2; + cam_pos.vz += (( icos( trot.vy )*icos( trot.vx ) )>>12)<<2; + + } else if( !(pad->btn&PAD_CROSS) ) { + + // Move backward + cam_pos.vx += (( isin( trot.vy )*icos( trot.vx ) )>>12)<<2; + cam_pos.vy -= isin( trot.vx )<<2; + cam_pos.vz -= (( icos( trot.vy )*icos( trot.vx ) )>>12)<<2; + + } + + if( !(pad->btn&PAD_SQUARE ) ) { + + // Slide left + cam_pos.vx -= icos( trot.vy )<<2; + cam_pos.vz -= isin( trot.vy )<<2; + + } else if( !(pad->btn&PAD_CIRCLE ) ) { + + // Slide right + cam_pos.vx += icos( trot.vy )<<2; + cam_pos.vz += isin( trot.vy )<<2; + + } + + if( !(pad->btn&PAD_R1) ) { + + // Slide up + cam_pos.vx -= (( isin( trot.vy )*isin( trot.vx ) )>>12)<<2; + cam_pos.vy -= icos( trot.vx )<<2; + cam_pos.vz += (( icos( trot.vy )*isin( trot.vx ) )>>12)<<2; + + } + + if( !(pad->btn&PAD_R2) ) { + + // Slide down + cam_pos.vx += (( isin( trot.vy )*isin( trot.vx ) )>>12)<<2; + cam_pos.vy += icos( trot.vx )<<2; + cam_pos.vz -= (( icos( trot.vy )*isin( trot.vx ) )>>12)<<2; + + } + + // Look at cube + if( !(pad->btn&PAD_L1) ) { + + cam_mode = 1; + + } + + } + + // For dual-analog and dual-shock (analog input) + if( ( pad->type == 0x5 ) || ( pad->type == 0x7 ) ) { + + // Moving forwards and backwards + if( ( (pad->ls_y-128) < -16 ) || ( (pad->ls_y-128) > 16 ) ) { + + cam_pos.vx += ((( isin( trot.vy )*icos( trot.vx ) )>>12)*(pad->ls_y-128))>>5; + cam_pos.vy -= (isin( trot.vx )*(pad->ls_y-128))>>5; + cam_pos.vz -= ((( icos( trot.vy )*icos( trot.vx ) )>>12)*(pad->ls_y-128))>>5; + + } + + // Strafing left and right + if( ( (pad->ls_x-128) < -16 ) || ( (pad->ls_x-128) > 16 ) ) { + cam_pos.vx += (icos( trot.vy )*(pad->ls_x-128))>>5; + cam_pos.vz += (isin( trot.vy )*(pad->ls_x-128))>>5; + } + + // Look up and down + if( ( (pad->rs_y-128) < -16 ) || ( (pad->rs_y-128) > 16 ) ) { + cam_rot.vx += (pad->rs_y-128)<<9; + } + + // Look left and right + if( ( (pad->rs_x-128) < -16 ) || ( (pad->rs_x-128) > 16 ) ) { + cam_rot.vy -= (pad->rs_x-128)<<9; + } + + } + + } + + + // First-person camera mode + if( cam_mode == 0 ) { + + // Set rotation to the matrix + RotMatrix( &trot, &mtx ); + + // Divide out the fractions of camera coordinates and invert + // the sign, so camera coordinates will line up to world + // (or geometry) coordinates + tpos.vx = -cam_pos.vx >> 12; + tpos.vy = -cam_pos.vy >> 12; + tpos.vz = -cam_pos.vz >> 12; + + // Apply rotation of matrix to translation value to achieve a + // first person perspective + ApplyMatrixLV( &mtx, &tpos, &tpos ); + + // Set translation matrix + TransMatrix( &mtx, &tpos ); + + // Tracking mode + } else { + + // Vector that defines the 'up' direction of the camera + SVECTOR up = { 0, -ONE, 0 }; + + // Divide out fractions of camera coordinates + tpos.vx = cam_pos.vx >> 12; + tpos.vy = cam_pos.vy >> 12; + tpos.vz = cam_pos.vz >> 12; + + // Look at the cube + LookAt(&tpos, &pos, &up, &mtx); + + } + + // Set rotation and translation matrix + gte_SetRotMatrix( &mtx ); + gte_SetTransMatrix( &mtx ); + + // Draw the floor + pol4 = (POLY_F4*)db_nextpri; + + for( py=0; py<16; py++ ) { + for( px=0; px<16; px++ ) { + + // Load first three vertices to GTE + gte_ldv3( + &verts[py][px], + &verts[py][px+1], + &verts[py+1][px] ); + + gte_rtpt(); + + gte_avsz3(); + gte_stotz( &p ); + + if( ( (p>>2) >= OT_LEN ) || ( (p>>2) <= 0 ) ) + continue; + + setPolyF4( pol4 ); + + // Set the projected vertices to the primitive + gte_stsxy0( &pol4->x0 ); + gte_stsxy1( &pol4->x1 ); + gte_stsxy2( &pol4->x2 ); + + // Compute the last vertex and set the result + gte_ldv0( &verts[py+1][px+1] ); + gte_rtps(); + gte_stsxy( &pol4->x3 ); + + // Test if quad is off-screen, discard if so + // Clipping is important as it not only prevents primitive + // overflows (tends to happen on textured polys) but also + // saves packet buffer space and speeds up rendering. + if( quad_clip( &screen_clip, + (DVECTOR*)&pol4->x0, (DVECTOR*)&pol4->x1, + (DVECTOR*)&pol4->x2, (DVECTOR*)&pol4->x3 ) ) + continue; + + gte_avsz4(); + gte_stotz( &p ); + + if((px+py)&0x1) { + setRGB0( pol4, 128, 128, 128 ); + } else { + setRGB0( pol4, 255, 255, 255 ); + } + + addPrim( db[db_active].ot+(p>>2), pol4 ); + pol4++; + + } + } + + // Update nextpri variable (very important) + db_nextpri = (char*)pol4; + + + // Position the cube going around the floor bouncily + setVector( &pos, + isin( rot.vy )>>4, + -300+(isin( rot.vy<<2 )>>5), + icos( rot.vy )>>3 ); + + // Sort cube + sort_cube( &mtx, &pos, &rot ); + + // Make the cube SPEEN + rot.vx += 8; + rot.vy += 8; + + + // Swap buffers and draw the primitives + display(); + + } + + return 0; + +} + +void sort_cube(MATRIX *mtx, VECTOR *pos, SVECTOR *rot) { + + int i,p; + POLY_F4 *pol4; + + // Object and light matrix for object + MATRIX omtx,lmtx; + + // Set object rotation and position + RotMatrix( rot, &omtx ); + TransMatrix( &omtx, pos ); + + // Multiply light matrix to object matrix + MulMatrix0( &light_mtx, &omtx, &lmtx ); + + // Set result to GTE light matrix + gte_SetLightMatrix( &lmtx ); + + // Composite coordinate matrix transform, so object will be rotated and + // positioned relative to camera matrix (mtx), so it'll appear as + // world-space relative. + CompMatrixLV( mtx, &omtx, &omtx ); + + // Save matrix + PushMatrix(); + + // Set matrices + gte_SetRotMatrix( &omtx ); + gte_SetTransMatrix( &omtx ); + + // Sort the cube + pol4 = (POLY_F4*)db_nextpri; + + for( i=0; i<CUBE_FACES; i++ ) { + + // Load the first 3 vertices of a quad to the GTE + gte_ldv3( + &cube_verts[cube_indices[i].v0], + &cube_verts[cube_indices[i].v1], + &cube_verts[cube_indices[i].v2] ); + + // Rotation, Translation and Perspective Triple + gte_rtpt(); + + // Compute normal clip for backface culling + gte_nclip(); + + // Get result + gte_stopz( &p ); + + // Skip this face if backfaced + if( p < 0 ) + continue; + + // Calculate average Z for depth sorting + gte_avsz3(); + gte_stotz( &p ); + + // Skip if clipping off + // (the shift right operator is to scale the depth precision) + if( ((p>>2) <= 0) || ((p>>2) >= OT_LEN) ) + continue; + + // Initialize a quad primitive + setPolyF4( pol4 ); + + // Set the projected vertices to the primitive + gte_stsxy0( &pol4->x0 ); + gte_stsxy1( &pol4->x1 ); + gte_stsxy2( &pol4->x2 ); + + // Compute the last vertex and set the result + gte_ldv0( &cube_verts[cube_indices[i].v3] ); + gte_rtps(); + gte_stsxy( &pol4->x3 ); + + // Test if quad is off-screen, discard if so + if( quad_clip( &screen_clip, + (DVECTOR*)&pol4->x0, (DVECTOR*)&pol4->x1, + (DVECTOR*)&pol4->x2, (DVECTOR*)&pol4->x3 ) ) + continue; + + // Load primitive color even though gte_ncs() doesn't use it. + // This is so the GTE will output a color result with the + // correct primitive code. + gte_ldrgb( &pol4->r0 ); + + // Load the face normal + gte_ldv0( &cube_norms[i] ); + + // Normal Color Single + gte_ncs(); + + // Store result to the primitive + gte_strgb( &pol4->r0 ); + + gte_avsz4(); + gte_stotz( &p ); + + // Sort primitive to the ordering table + addPrim( db[db_active].ot+(p>>2), pol4 ); + + // Advance to make another primitive + pol4++; + + } + + // Update nextpri + db_nextpri = (char*)pol4; + + // Restore matrix + PopMatrix(); + +} + +void init() { + + // Reset the GPU, also installs a VSync event handler + ResetGraph( 0 ); + + // Set display and draw environment areas + // (display and draw areas must be separate, otherwise hello flicker) + SetDefDispEnv( &db[0].disp, 0, 0, SCREEN_XRES, SCREEN_YRES ); + SetDefDrawEnv( &db[0].draw, SCREEN_XRES, 0, SCREEN_XRES, SCREEN_YRES ); + + // Enable draw area clear and dither processing + setRGB0( &db[0].draw, 63, 0, 127 ); + db[0].draw.isbg = 1; + db[0].draw.dtd = 1; + + + // Define the second set of display/draw environments + SetDefDispEnv( &db[1].disp, SCREEN_XRES, 0, SCREEN_XRES, SCREEN_YRES ); + SetDefDrawEnv( &db[1].draw, 0, 0, SCREEN_XRES, SCREEN_YRES ); + + setRGB0( &db[1].draw, 63, 0, 127 ); + db[1].draw.isbg = 1; + db[1].draw.dtd = 1; + + // Apply the drawing environment of the first double buffer + PutDrawEnv( &db[0].draw ); + + // Clear both ordering tables to make sure they are clean at the start + ClearOTagR( db[0].ot, OT_LEN ); + ClearOTagR( db[1].ot, OT_LEN ); + + // Set primitive pointer address + db_nextpri = db[0].p; + + // Set clip region + setRECT( &screen_clip, 0, 0, SCREEN_XRES, SCREEN_YRES ); + + + // Initialize the GTE + InitGeom(); + + // Set GTE offset (recommended method of centering) + gte_SetGeomOffset( CENTERX, CENTERY ); + + // Set screen depth (basically FOV control, W/2 works best) + gte_SetGeomScreen( CENTERX ); + + // Set light ambient color and light color matrix + gte_SetBackColor( 63, 63, 63 ); + gte_SetColorMatrix( &color_mtx ); + + + // Init BIOS pad driver and set pad buffers (buffers are updated + // automatically on every V-Blank) + _InitPad(&pad_buff[0][0], 34, &pad_buff[1][0], 34); + + // Start pad + _StartPad(); + + // Don't make pad driver acknowledge V-Blank IRQ (recommended) + ChangeClearPAD(0); + +} + +void display() { + + // Wait for GPU to finish drawing and vertical retrace + DrawSync( 0 ); + VSync( 0 ); + + // Swap buffers + db_active ^= 1; + db_nextpri = db[db_active].p; + + // Clear the OT of the next frame + ClearOTagR( db[db_active].ot, OT_LEN ); + + // Apply display/drawing environments + PutDrawEnv( &db[db_active].draw ); + PutDispEnv( &db[db_active].disp ); + + // Enable display + SetDispMask( 1 ); + + // Start drawing the OT of the last buffer + DrawOTag( db[1-db_active].ot+(OT_LEN-1) ); + +} + diff --git a/examples/fpscam/makefile b/examples/fpscam/makefile new file mode 100644 index 0000000..7175c98 --- /dev/null +++ b/examples/fpscam/makefile @@ -0,0 +1,39 @@ +include ../sdk-common.mk + +TARGET = fpscam.elf + +CFILES = $(notdir $(wildcard *.c)) +CPPFILES = $(notdir $(wildcard *.cpp)) +AFILES = $(notdir $(wildcard *.s)) + +OFILES = $(addprefix build/,$(CFILES:.c=.o) $(CPPFILES:.cpp=.o) $(AFILES:.s=.o)) + +INCLUDE += +LIBDIRS += + +LIBS = -lc -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lgcc + +CFLAGS = -g -O2 -fno-builtin -fdata-sections -ffunction-sections +CPPFLAGS = $(CFLAGS) -fno-exceptions +AFLAGS = -g -msoft-float +LDFLAGS = -g -Ttext=0x80010000 -gc-sections -T $(GCC_BASE)/mipsel-unknown-elf/lib/ldscripts/elf32elmip.x + +CC = $(PREFIX)gcc +CXX = $(PREFIX)g++ +AS = $(PREFIX)as +LD = $(PREFIX)ld + +all: $(OFILES) + $(LD) $(LDFLAGS) $(LIBDIRS) $(OFILES) $(LIBS) -o $(TARGET) + elf2x -q $(TARGET) + +build/%.o: %.c + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +build/%.o: %.s + @mkdir -p $(dir $@) + $(CC) $(AFLAGS) $(INCLUDE) -c $< -o $@ + +clean: + rm -rf build $(TARGET) $(TARGET:.elf=.exe) diff --git a/examples/gte/main.c b/examples/gte/main.c index 3fec9d7..432ef95 100644 --- a/examples/gte/main.c +++ b/examples/gte/main.c @@ -4,7 +4,9 @@ * GTE Graphics Example * 2019 Meido-Tek Productions / PSn00bSDK Project * - * To build, simply run make. + * Renders a spinning 3D cube with light source calculation + * using GTE macros. + * * * Example by Lameguy64 * |
