aboutsummaryrefslogtreecommitdiff
path: root/examples/demos/n00bdemo/lightdemo.c
diff options
context:
space:
mode:
authorspicyjpeg <thatspicyjpeg@gmail.com>2023-06-20 15:13:11 +0200
committerspicyjpeg <thatspicyjpeg@gmail.com>2023-06-20 15:13:11 +0200
commitd23024ceeb8e7f04b0a3bde7a0db41ae5e4fd06d (patch)
tree03342eb22041fb7343c034e376489295e2a78a19 /examples/demos/n00bdemo/lightdemo.c
parent79a966486615e60be3a37d278945dc3dd0fd933b (diff)
Split off libsmd from n00bdemo into separate library
Diffstat (limited to 'examples/demos/n00bdemo/lightdemo.c')
-rw-r--r--examples/demos/n00bdemo/lightdemo.c326
1 files changed, 163 insertions, 163 deletions
diff --git a/examples/demos/n00bdemo/lightdemo.c b/examples/demos/n00bdemo/lightdemo.c
index 5afd5c8..26da9ef 100644
--- a/examples/demos/n00bdemo/lightdemo.c
+++ b/examples/demos/n00bdemo/lightdemo.c
@@ -3,8 +3,8 @@
#include <psxgte.h>
#include <psxgpu.h>
#include <inline_c.h>
+#include <smd/smd.h>
#include "disp.h"
-#include "smd.h"
extern MATRIX lgt_colmtx;
@@ -14,227 +14,227 @@ 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.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(
+
+ 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.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.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;
@@ -242,25 +242,25 @@ void lightdemo() {
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.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;
@@ -268,25 +268,25 @@ void lightdemo() {
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.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;
@@ -294,70 +294,70 @@ void lightdemo() {
lmtx.m[0][2] = v_nrm.vz;
gte_SetLightMatrix( &lmtx );
gte_nccs();
-
- setUV4( pri,
+
+ setUV4( pri,
s_pri.tu0, s_pri.tv0,
- s_pri.tu1, s_pri.tv1,
+ 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(
+
+ 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.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;
@@ -368,26 +368,26 @@ void lightdemo() {
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.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;
@@ -395,25 +395,25 @@ void lightdemo() {
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.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;
@@ -421,25 +421,25 @@ void lightdemo() {
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.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;
@@ -447,49 +447,49 @@ void lightdemo() {
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