1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin
3   File:     gd-light-gc.c
4 
5   Copyright 2001 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: gd-light-gc.c,v $
14   Revision 1.2  02/20/2006 04:13:09  mitu
15   changed include path from dolphin/ to revolution/.
16 
17   Revision 1.1  02/08/2006 11:19:43  mitu
18   1st version.
19 
20 
21     3     02/09/06 11:25 Hirose
22     Resolved future time stamp problem.
23 
24     3     10/19/02 6:53p Hirose
25     Changed location of data file.
26 
27     2     10/03/01 11:37a Hirose
28     Deleted redundant ifdef.
29 
30     1     9/24/01 2:17p Hirose
31     Initial check-in.
32 
33   $NoKeywords: $
34  *---------------------------------------------------------------------------*/
35 /*---------------------------------------------------------------------------*
36    gd-light
37      Displaylist demo with lighting commands
38      [Main source code for GAMECUBE executable]
39  *---------------------------------------------------------------------------*/
40 
41 
42 /*---------------------------------------------------------------------------*
43    Header files
44  *---------------------------------------------------------------------------*/
45 #include <demo.h>
46 #include <math.h>
47 #include <revolution/gd.h>
48 
49 #include "gd-light.h"
50 
51 /*---------------------------------------------------------------------------*
52    Macro definitions
53  *---------------------------------------------------------------------------*/
54 #define PI          3.14159265358979323846F
55 #define PI_2        (PI*2)
56 
57 #define Clamp(val,min,max) \
58     ((val) = (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val)))
59 
60 /*---------------------------------------------------------------------------*
61    Forward references
62  *---------------------------------------------------------------------------*/
63 void        main                ( void );
64 
65 static void CreateModelVtxArray ( void );
66 static void PatchLightStatus    ( void );
67 static void PrepareDL           ( void );
68 
69 static void CameraInit          ( Mtx v );
70 static void DrawInit            ( void );
71 static void DrawTick            ( void );
72 static void AnimTick            ( void );
73 static void PrintIntro          ( void );
74 
75 /*---------------------------------------------------------------------------*
76    Global variables
77  *---------------------------------------------------------------------------*/
78 
79 // Model display list
80 static u8*      ModelDL;
81 static u32      ModelDLSize;
82 static u32*     ModelDLPatchList;
83 // Model geometry
84 static s16*     VtxPosArray = NULL;
85 static s16*     VtxNrmArray = NULL;
86 
87 // Model/Camera matrices
88 static Mtx      ViewMtx;
89 static Mtx      ModelMtx;
90 
91 // Light position control
92 static Vec      Light0Pos;
93 static Vec      Light1Dir;
94 static s32      LightTheta, LightPhi;
95 
96 
97 /*---------------------------------------------------------------------------*
98    Application main loop
99  *---------------------------------------------------------------------------*/
main(void)100 void main ( void )
101 {
102     DEMOInit(NULL); // Init the OS, game pad, graphics and video.
103     DrawInit();     // Initialize vertex formats and array pointers.
104 
105     PrintIntro();   // Print demo directions
106 
107     while(!( DEMOPadGetButton(0) & PAD_BUTTON_MENU ))
108     {
109 		DEMOBeforeRender();
110 
111         DrawTick();  // Draw the model.
112 
113         DEMODoneRender();
114 
115         DEMOPadRead();
116         AnimTick();
117     }
118 
119     OSHalt("End of demo");
120 }
121 
122 /*---------------------------------------------------------------------------*
123    Functions
124  *---------------------------------------------------------------------------*/
125 /*---------------------------------------------------------------------------*
126     Name:           CreateModelVtxArray
127 
128     Description:    Create indexed data array for the model
129 
130     Arguments:      none
131 
132     Returns:        none
133  *---------------------------------------------------------------------------*/
CreateModelVtxArray(void)134 static void CreateModelVtxArray( void )
135 {
136     u32  size, cnt_p, cnt_n;
137     s32  i, j;
138     f32  fs, ft, fr;
139 
140     // allocate necessary array memories
141     if ( VtxPosArray != NULL )
142         OSFree(VtxPosArray);
143     if ( VtxNrmArray != NULL )
144         OSFree(VtxNrmArray);
145 
146     size = MODEL_N0 * MODEL_N1 * 3;
147 
148     VtxPosArray = (s16*)OSAlloc(size * sizeof(s16));
149     VtxNrmArray = (s16*)OSAlloc(size * sizeof(s16));
150 
151     // make array data
152     cnt_p = cnt_n = 0;
153     for ( i = 0 ; i < MODEL_N0 ; ++i )
154     {
155         for ( j = 0 ; j < MODEL_N1; ++j )
156         {
157             // Position
158             fs = i * PI_2 / MODEL_N0;
159             ft = j * PI_2 / MODEL_N1;
160             fr = 1.0F + MODEL_R * cosf(fs);
161 
162             VtxPosArray[cnt_p++] = (s16)(fr * cosf(ft) * SCALE_Q);
163             VtxPosArray[cnt_p++] = (s16)(fr * sinf(ft) * SCALE_Q);
164             VtxPosArray[cnt_p++] = (s16)(MODEL_R * sinf(fs) * SCALE_Q);
165 
166             // Normal
167             VtxNrmArray[cnt_n++] = (s16)(cosf(ft) * cosf(fs) * SCALE_Q);
168             VtxNrmArray[cnt_n++] = (s16)(sinf(ft) * cosf(fs) * SCALE_Q);
169             VtxNrmArray[cnt_n++] = (s16)(sinf(fs) * SCALE_Q);
170         }
171     }
172 
173     // make sure data is written to main memory
174     DCFlushRange(VtxPosArray, size * sizeof(s16));
175     DCFlushRange(VtxNrmArray, size * sizeof(s16));
176 
177 }
178 
179 /*---------------------------------------------------------------------------*
180     Name:           PrepareDL
181 
182     Description:    [create mode] Allocate memory for display list and call
183                     the function CreateModelDL to create the display list.
184                     [load mode] Load GDL file from the disc.
185 
186     Arguments:      none
187 
188     Returns:        none
189  *---------------------------------------------------------------------------*/
PrepareDL(void)190 static void PrepareDL ( void )
191 {
192 #ifdef  LOAD_DL_FROM_FILE
193     //---------------------------------------------------------
194     // File mode : Read pre-generated GDL file from file
195     //---------------------------------------------------------
196     s32         err;
197     GDGList*    dlArray;
198     GDGList*    plArray;
199     u32         nDls, nPls;
200 
201     err = GDReadDLFile("gddemo/gdLight.gdl", &nDls, &nPls, &dlArray, &plArray);
202 
203     // This demo only expects 1DL/1PL.
204     ASSERTMSG( ( nDls == 1 && nPls == 1 ),
205                "This data doesn't match requirement of this demo.\n" );
206 
207     ModelDL     = dlArray[0].ptr;
208     ModelDLSize = dlArray[0].byteLength;
209 
210     // Check length of the patch list.
211     ASSERTMSG( ( plArray[0].byteLength == MODELDL_NUM_PATCHES * sizeof(u32) ),
212                "Length of the patch list doesn't match requirement of this demo.\n" );
213 
214     ModelDLPatchList = plArray[0].ptr;
215 
216 #else
217     //---------------------------------------------------------
218     // Create mode : Create display list in this application
219     //---------------------------------------------------------
220 
221     // Allocate memory for the DL.
222     ModelDL = OSAlloc(MODELDL_SIZE_MAX);
223     ASSERTMSG(ModelDL, "Memory allocation failed.\n");
224     ModelDLPatchList = (u32*)OSAlloc(MODELDL_NUM_PATCHES * sizeof(u32));
225     ASSERTMSG(ModelDLPatchList, "Memory allocation failed.\n");
226 
227     ModelDLSize = CreateModelDL(ModelDL, ModelDLPatchList);
228     OSReport("Size = %d\n", ModelDLSize);
229 
230 #endif
231 }
232 
233 /*---------------------------------------------------------------------------*
234     Name:           PatchLightStatus
235 
236     Description:    Patches lighting status in the model display list.
237                     Position and direction information is overridden in run-time.
238                     Locations are given by the patch list.
239 
240     Arguments:      none
241 
242     Returns:        none
243  *---------------------------------------------------------------------------*/
PatchLightStatus(void)244 static void PatchLightStatus( void )
245 {
246     Vec         lpos;
247     GDLObj      dlObj;
248 
249     // Prepare DL object for patching.
250     GDInitGDLObj(&dlObj, ModelDL, ModelDLSize);
251     GDSetCurrent(&dlObj);
252 
253     // Patch LIGHT0(Pos)
254     lpos = Light0Pos;
255     MTXMultVec(ViewMtx, &lpos, &lpos);
256     GDSetCurrOffset(ModelDLPatchList[MODELDL_PATCH_LIGHT0POS]);
257     GDSetLightPos(GX_LIGHT0, lpos.x, lpos.y, lpos.z);
258 
259     // Patch LIGHT1(Dir)
260     lpos = Light1Dir;
261     MTXMultVecSR(ViewMtx, &lpos, &lpos);
262     GDSetCurrOffset(ModelDLPatchList[MODELDL_PATCH_LIGHT1DIR]);
263     GDSetSpecularDir(GX_LIGHT1, lpos.x, lpos.y, lpos.z);
264 
265     GDFlushCurrToMem();
266     GDSetCurrent(NULL); // release DL object
267 }
268 
269 /*---------------------------------------------------------------------------*
270     Name:           CameraInit
271 
272     Description:    Initialize the projection matrix and load into hardware.
273                     Initialize the view matrix.
274 
275     Arguments:      v       view matrix
276 
277     Returns:        none
278  *---------------------------------------------------------------------------*/
CameraInit(Mtx v)279 static void CameraInit ( Mtx v )
280 {
281     Mtx44   p;      // projection matrix
282     Vec     up      = { 0.0F, 1.0F, 0.0F };
283     Vec     camLoc  = { 0.0F, 0.0F, 6.0F };
284     Vec     objPt   = { 0.0F, 0.0F, 0.0F };
285     f32     left    = -0.050F;
286     f32     top     = 0.0375F;
287     f32     znear   = 0.1F;
288     f32     zfar    = 10.0F;
289 
290     MTXFrustum(p, top, -top, left, -left, znear, zfar);
291     GXSetProjection(p, GX_PERSPECTIVE);
292 
293     MTXLookAt(v, &camLoc, &up, &objPt);
294 }
295 
296 /*---------------------------------------------------------------------------*
297     Name:           DrawInit
298 
299     Description:    Initializes the vertex attribute format and
300                     array pointers.
301 
302     Arguments:      none
303 
304     Returns:        none
305  *---------------------------------------------------------------------------*/
DrawInit(void)306 static void DrawInit( void )
307 {
308     // prepare display list
309     PrepareDL();
310     // create model data geometries
311     CreateModelVtxArray();
312 
313     // model rotation and light location
314     MTXIdentity(ModelMtx);
315     LightTheta = 30;
316     LightPhi   = 30;
317 
318     // camera
319     CameraInit(ViewMtx);
320 
321     // set up vertex attributes
322     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, QUANTIZE);
323     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_S16, QUANTIZE);
324 
325     // set up array pointers for indexed lookup
326     GXSetArray(GX_VA_POS, VtxPosArray, 3*sizeof(s16));
327     GXSetArray(GX_VA_NRM, VtxNrmArray, 3*sizeof(s16));
328 
329     //--------------------------------------------------
330     //  Rendering pipe setting
331     //--------------------------------------------------
332     GXSetNumTexGens(0);
333     GXSetNumTevStages(2);
334     GXSetNumChans(2);
335 
336     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
337     GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR1A1);
338 
339     // Output = Color channel 0 + Color channel 1
340     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
341     GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_RASC,
342                                   GX_CC_ONE,  GX_CC_CPREV);
343     GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO,
344                     GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
345 }
346 
347 /*---------------------------------------------------------------------------*
348     Name:           DrawTick
349 
350     Description:    Draws the lit model
351 
352     Arguments:      none
353 
354     Returns:        none
355  *---------------------------------------------------------------------------*/
DrawTick(void)356 static void DrawTick( void )
357 {
358     Mtx     mv, mvi;
359 
360     //--------------------------------------------------
361     //  Lighting parameters
362     //--------------------------------------------------
363     PatchLightStatus();
364 
365     //--------------------------------------------------
366     //  Geometry transformation
367     //--------------------------------------------------
368     // model has a rotation about y axis
369     MTXConcat(ViewMtx, ModelMtx, mv);
370     GXLoadPosMtxImm(mv, GX_PNMTX0);
371     MTXInvXpose(mv, mvi);
372     GXLoadNrmMtxImm(mvi, GX_PNMTX0);
373 
374     //--------------------------------------------------
375     //  Draw the model
376     //--------------------------------------------------
377 
378     // Call the display list
379     GXCallDisplayList(ModelDL, ModelDLSize);
380 }
381 
382 /*---------------------------------------------------------------------------*
383     Name:           AnimTick
384 
385     Description:    Controls model rotation.
386 
387     Arguments:      none
388 
389     Returns:        none
390  *---------------------------------------------------------------------------*/
AnimTick(void)391 static void AnimTick( void )
392 {
393     Mtx  mrx, mry;
394     f32  f_theta, f_phi;
395 
396     // Model Rotation Calculation
397     MTXRotDeg(mry, 'x', -(DEMOPadGetStickY(0) / 24));
398     MTXRotDeg(mrx, 'y',  (DEMOPadGetStickX(0) / 24));
399     MTXConcat(mry, ModelMtx, ModelMtx);
400     MTXConcat(mrx, ModelMtx, ModelMtx);
401 
402     // Light Position Calculation
403     LightTheta += (DEMOPadGetSubStickX(0) / 24);
404     Clamp(LightTheta, -90, 90);
405     LightPhi   += (DEMOPadGetSubStickY(0) / 24);
406     Clamp(LightPhi,   -90, 90);
407 
408     f_theta = (f32)LightTheta * PI / 180.0F;
409     f_phi   = (f32)LightPhi   * PI / 180.0F;
410 
411     Light1Dir.x = - cosf(f_phi) * sinf(f_theta);
412     Light1Dir.y = - sinf(f_phi);
413     Light1Dir.z = - cosf(f_phi) * cosf(f_theta);
414     Light0Pos.x = - Light1Dir.x * 1000;
415     Light0Pos.y = - Light1Dir.y * 1000;
416     Light0Pos.z = - Light1Dir.z * 1000;
417 }
418 
419 /*---------------------------------------------------------------------------*
420     Name:           PrintIntro
421 
422     Description:    Prints the directions on how to use this demo.
423 
424     Arguments:      none
425 
426     Returns:        none
427  *---------------------------------------------------------------------------*/
PrintIntro(void)428 static void PrintIntro( void )
429 {
430     OSReport("\n\n");
431     OSReport("********************************\n");
432     OSReport("    Lighting demo on GD\n");
433     OSReport("********************************\n");
434     OSReport("START      : Quit.\n");
435     OSReport("Main Stick : Rotate the model.\n");
436     OSReport("Sub  Stick : Move light.\n");
437     OSReport("********************************\n");
438 }
439 
440 /*============================================================================*/
441