From 1aa0e17df7c325a41de8cf8a57f52ed853f08bf3 Mon Sep 17 00:00:00 2001 From: "John Wilbert M. Villamor" Date: Fri, 24 Apr 2020 19:01:28 +0800 Subject: Refined toolchain instructions, organized examples, added automatic retry for CdRead(), added FIOCSCAN ioctl in psxsio TTY driver, added tty and console examples. --- examples/demos/n00bdemo/lightdemo.c | 494 ++++++++++++++++++++++++++++++++++++ 1 file changed, 494 insertions(+) create mode 100644 examples/demos/n00bdemo/lightdemo.c (limited to 'examples/demos/n00bdemo/lightdemo.c') diff --git a/examples/demos/n00bdemo/lightdemo.c b/examples/demos/n00bdemo/lightdemo.c new file mode 100644 index 0000000..ff858c0 --- /dev/null +++ b/examples/demos/n00bdemo/lightdemo.c @@ -0,0 +1,494 @@ +#include +#include +#include +#include +#include "disp.h" +#include "smd.h" + +extern MATRIX lgt_colmtx; + +extern SMD *o_world; +extern SMD *o_lightbulb; + +void sort_overlay(int showlotl); + +void lightdemo() { + + /* + The point lighting demo is perhaps the most impressive part of + n00bDEMO. A more streamlined version of this demo where you control + various attributes of the light source such as position, intensity + and color might be made as a dedicated example program in the future. + + The point lighting trick is actually not that too complicated. You + basically calculate the distance and direction vector of two points + which are the light source and the vertex of a polygon. + + Calculating the normal whose result can later be used to calculate + the distance between two points is achieved with: + + vec_dir.vx = lgt_point.vx - pri_vert.vx; + vec_dir.vy = lgt_point.vy - pri_vert.vy; + vec_dir.vz = lgt_point.vz - pri_vert.vz; + + The intensity is calculated with (this might not be accurate but this + is faster than applying a square root): + + i = 4096 - ( ( + (vec_dir.vx*vec_dir.vx) + + (vec_dir.vy*vec_dir.vy) + + (vec_dir.vz*vec_dir.vz) ) >> 7 ); + + // Clip minimum intensity + if( i < 0 ) + i = 0; + + This intensity value is then used to set the color of the light source + through the light color matrix. + + col_mtx.m[0][0] = i; + col_mtx.m[1][0] = i; + col_mtx.m[2][0] = i; + gte_SetColorMatrix( &col_mtx ); + + The direction vector can then be used as the direction of the light + source. It is recommended to normalize it first to prevent possible + overflow related issues. + + VectorNormalS( &vec_dir, &vec_norm ); + + lgt_mtx.m[0][0] = vec_norm.vx; + lgt_mtx.m[0][1] = vec_norm.vy; + lgt_mtx.m[0][2] = vec_norm.vz; + + gte_SetLightMatrix( &lgt_mtx ); + + This operation is then performed for each point of a polygon to + achieve a nice smooth shaded point lighting effect. The macros used + are still the same as doing light source calculation with the GTE + the normal way. + + 3D geometry still requires normal data as with most lighting + processing operations. 'Flat' normals (faces with a single normal + vector) work best on flat surfaces while 'smooth' normals (faces with + normals on each point) work best on round or curved surfaces. + + */ + + int i,p_ang; + + SC_OT s_ot; + + SVECTOR rot; + VECTOR pos; + SMD_PRIM s_pri; + + VECTOR l_point; + SVECTOR nrm; + + MATRIX lmtx,llmtx,omtx; + + SVECTOR orot = { 0 }; + + int timeout = SCENE_TIME; + + + // Set clear color to black + setRGB0( &draw, 0, 0, 0 ); + + // Base values for the environment geometry + setVector( &pos, 0, 0, 600 ); + setVector( &rot, 512, 0, 0 ); + + // Set base tpage value for the SMD drawing routines + smdSetBaseTPage( 0x200 ); + + // Set back or ambient color to black for pure darkness + gte_SetBackColor( 0, 0, 0 ); + + memset( &llmtx, 0, sizeof(MATRIX) ); + + + // demo loop + while( 1 ) { + + char buff[32]; + + RotMatrix( &rot, &mtx ); + TransMatrix( &mtx, &pos ); + + rot.vy += 4; + + gte_SetRotMatrix( &mtx ); + gte_SetTransMatrix( &mtx ); + + + setVector( &l_point, (icos( p_ang )>>2)>>2, -350+(icos( p_ang<<1 )>>4), (isin( p_ang )>>2)>>2 ); + p_ang += 16; + + + // Begin parsing the SMD data of the environment + OpenSMD( o_world ); + + // Prototype point lighting renderer + while( ReadSMD( &s_pri ) ) { + + VECTOR v_dir; + SVECTOR v_nrm; + VECTOR v_sqr; + + int flg; + + if( s_pri.prim_id.texture ) { + + POLY_GT4 *pri; + + // Perform standard rotate, translate and perspective + // transformation of the geometry + pri = (POLY_GT4*)nextpri; + + gte_ldv3( + &o_world->p_verts[s_pri.v0], + &o_world->p_verts[s_pri.v1], + &o_world->p_verts[s_pri.v2] ); + + gte_rtpt(); + + gte_nclip(); // Backface culling + + gte_stopz( &flg ); + + if( flg < 0 ) + continue; + + gte_stsxy3( &pri->x0, &pri->x1, &pri->x2 ); + + gte_ldv0( &o_world->p_verts[s_pri.v3] ); + gte_rtps(); + + gte_avsz4(); // Depth sort + gte_stotz( &flg ); + + if( (flg>>2) >= OT_LEN ) + continue; + + gte_stsxy( &pri->x3 ); + + + // Load base color of polygon to GTE + gte_ldrgb( &s_pri.r0 ); + + // Load normal of polygon + gte_ldv0( &o_world->p_norms[s_pri.n0] ); + + // Calculate the direction between the vertex of the + // polygon and the light source + v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v0].vx; + v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v0].vy; + v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v0].vz; + + // Calculate distance and light intensity using square + i = 4096 - ( ( + (v_dir.vx*v_dir.vx) + + (v_dir.vy*v_dir.vy) + + (v_dir.vz*v_dir.vz) ) >> 7 ); + + // Clip minimum intensity + if( i < 0 ) + i = 0; + + // Set intensity to color matrix + llmtx.m[0][0] = i; + llmtx.m[1][0] = i; + llmtx.m[2][0] = i; + gte_SetColorMatrix( &llmtx ); + + // Normalize light direction and set it to light matrix + VectorNormalS( &v_dir, &v_nrm ); + lmtx.m[0][0] = v_nrm.vx; + lmtx.m[0][1] = v_nrm.vy; + lmtx.m[0][2] = v_nrm.vz; + gte_SetLightMatrix( &lmtx ); + + // Calculate (output is retrieved through gte_strgb) + gte_nccs(); + + + // Repeat process for the next 3 vertices + v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v1].vx; + v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v1].vy; + v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v1].vz; + + i = 4096 - ( ( + (v_dir.vx*v_dir.vx) + + (v_dir.vy*v_dir.vy) + + (v_dir.vz*v_dir.vz) ) >> 7 ); + + if( i < 0 ) + i = 0; + + + llmtx.m[0][0] = i; + llmtx.m[1][0] = i; + llmtx.m[2][0] = i; + + gte_strgb( &pri->r0 ); + + gte_SetColorMatrix( &llmtx ); + VectorNormalS( &v_dir, &v_nrm ); + lmtx.m[0][0] = v_nrm.vx; + lmtx.m[0][1] = v_nrm.vy; + lmtx.m[0][2] = v_nrm.vz; + gte_SetLightMatrix( &lmtx ); + gte_nccs(); + + v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v2].vx; + v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v2].vy; + v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v2].vz; + + i = 4096 - ( ( + (v_dir.vx*v_dir.vx) + + (v_dir.vy*v_dir.vy) + + (v_dir.vz*v_dir.vz) ) >> 7 ); + + if( i < 0 ) + i = 0; + + llmtx.m[0][0] = i; + llmtx.m[1][0] = i; + llmtx.m[2][0] = i; + + gte_strgb( &pri->r1 ); + + gte_SetColorMatrix( &llmtx ); + VectorNormalS( &v_dir, &v_nrm ); + lmtx.m[0][0] = v_nrm.vx; + lmtx.m[0][1] = v_nrm.vy; + lmtx.m[0][2] = v_nrm.vz; + gte_SetLightMatrix( &lmtx ); + gte_nccs(); + + v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v3].vx; + v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v3].vy; + v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v3].vz; + + i = 4096 - ( ( + (v_dir.vx*v_dir.vx) + + (v_dir.vy*v_dir.vy) + + (v_dir.vz*v_dir.vz) ) >> 7 ); + + if( i < 0 ) + i = 0; + + llmtx.m[0][0] = i; + llmtx.m[1][0] = i; + llmtx.m[2][0] = i; + + gte_strgb( &pri->r2 ); + + gte_SetColorMatrix( &llmtx ); + VectorNormalS( &v_dir, &v_nrm ); + lmtx.m[0][0] = v_nrm.vx; + lmtx.m[0][1] = v_nrm.vy; + lmtx.m[0][2] = v_nrm.vz; + gte_SetLightMatrix( &lmtx ); + gte_nccs(); + + setUV4( pri, + s_pri.tu0, s_pri.tv0, + s_pri.tu1, s_pri.tv1, + s_pri.tu2, s_pri.tv2, + s_pri.tu3, s_pri.tv3 ); + + pri->tpage = s_pri.tpage; + pri->clut = s_pri.clut; + + setPolyGT4( pri ); + addPrim( ot[db]+(flg>>2), pri ); + nextpri += sizeof(POLY_GT4); + + gte_strgb( &pri->r3 ); + + } else { + + POLY_G4 *pri; + + pri = (POLY_G4*)nextpri; + + gte_ldv3( + &o_world->p_verts[s_pri.v0], + &o_world->p_verts[s_pri.v1], + &o_world->p_verts[s_pri.v2] ); + + gte_rtpt(); + + gte_nclip(); + + gte_stopz( &flg ); + + if( flg < 0 ) + continue; + + gte_stsxy3( &pri->x0, &pri->x1, &pri->x2 ); + + gte_ldv0( &o_world->p_verts[s_pri.v3] ); + gte_rtps(); + + gte_avsz4(); + gte_stotz( &flg ); + + if( (flg>>2) >= OT_LEN ) + continue; + + gte_stsxy( &pri->x3 ); + + gte_ldrgb( &s_pri.r0 ); + gte_ldv0( &o_world->p_norms[s_pri.n0] ); + + v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v0].vx; + v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v0].vy; + v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v0].vz; + + i = 4096 - ( ( + (v_dir.vx*v_dir.vx) + + (v_dir.vy*v_dir.vy) + + (v_dir.vz*v_dir.vz) ) >> 7 ); + + if( i < 0 ) + i = 0; + + llmtx.m[0][0] = i; + llmtx.m[1][0] = i; + llmtx.m[2][0] = i; + gte_SetColorMatrix( &llmtx ); + VectorNormalS( &v_dir, &v_nrm ); + lmtx.m[0][0] = v_nrm.vx; + lmtx.m[0][1] = v_nrm.vy; + lmtx.m[0][2] = v_nrm.vz; + gte_SetLightMatrix( &lmtx ); + gte_nccs(); + + + v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v1].vx; + v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v1].vy; + v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v1].vz; + + i = 4096 - ( ( + (v_dir.vx*v_dir.vx) + + (v_dir.vy*v_dir.vy) + + (v_dir.vz*v_dir.vz) ) >> 7 ); + + if( i < 0 ) + i = 0; + + llmtx.m[0][0] = i; + llmtx.m[1][0] = i; + llmtx.m[2][0] = i; + + gte_strgb( &pri->r0 ); + + gte_SetColorMatrix( &llmtx ); + VectorNormalS( &v_dir, &v_nrm ); + lmtx.m[0][0] = v_nrm.vx; + lmtx.m[0][1] = v_nrm.vy; + lmtx.m[0][2] = v_nrm.vz; + gte_SetLightMatrix( &lmtx ); + gte_nccs(); + + v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v2].vx; + v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v2].vy; + v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v2].vz; + + i = 4096 - ( ( + (v_dir.vx*v_dir.vx) + + (v_dir.vy*v_dir.vy) + + (v_dir.vz*v_dir.vz) ) >> 7 ); + + if( i < 0 ) + i = 0; + + llmtx.m[0][0] = i; + llmtx.m[1][0] = i; + llmtx.m[2][0] = i; + + gte_strgb( &pri->r1 ); + + gte_SetColorMatrix( &llmtx ); + VectorNormalS( &v_dir, &v_nrm ); + lmtx.m[0][0] = v_nrm.vx; + lmtx.m[0][1] = v_nrm.vy; + lmtx.m[0][2] = v_nrm.vz; + gte_SetLightMatrix( &lmtx ); + gte_nccs(); + + v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v3].vx; + v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v3].vy; + v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v3].vz; + + i = 4096 - ( ( + (v_dir.vx*v_dir.vx) + + (v_dir.vy*v_dir.vy) + + (v_dir.vz*v_dir.vz) ) >> 7 ); + + if( i < 0 ) + i = 0; + + llmtx.m[0][0] = i; + llmtx.m[1][0] = i; + llmtx.m[2][0] = i; + + gte_strgb( &pri->r2 ); + + gte_SetColorMatrix( &llmtx ); + VectorNormalS( &v_dir, &v_nrm ); + lmtx.m[0][0] = v_nrm.vx; + lmtx.m[0][1] = v_nrm.vy; + lmtx.m[0][2] = v_nrm.vz; + gte_SetLightMatrix( &lmtx ); + gte_nccs(); + + setPolyG4( pri ); + addPrim( ot[db]+(flg>>2), pri ); + + nextpri += sizeof(POLY_G4); + + gte_strgb( &pri->r3 ); + + } + + } + + + // Sort the light bulb to represent the position of the light source + orot.vx += 32; + orot.vy += 32; + orot.vz += 32; + + RotMatrix( &orot, &omtx ); + TransMatrix( &omtx, &l_point ); + + CompMatrixLV( &mtx, &omtx, &mtx ); + + gte_SetRotMatrix( &mtx ); + gte_SetTransMatrix( &mtx ); + + s_ot.ot = ot[db]; + s_ot.otlen = OT_LEN; + s_ot.zdiv = 2; + s_ot.zoff = 0; + + nextpri = smdSortModel( &s_ot, nextpri, o_lightbulb ); + + + // Sort overlay and display + sort_overlay( 1 ); + + display(); + + timeout--; + if( timeout < 0 ) + break; + + } + +} \ No newline at end of file -- cgit v1.2.3