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