1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - GX - demos - UnitTours/3D_Pol_Light
3   File:     main.c
4 
5   Copyright 2003-2008 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   $Date:: 2008-09-17#$
14   $Rev: 8556 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 //---------------------------------------------------------------------------
19 // A sample for lighting:
20 //
21 // Draw two cubes with a light changing in colors and direction.
22 // The left one has a normal vector for each plane,
23 // and the right one has a normal vector for each vertex.
24 //
25 // HOWTO:
26 // 1. Specify the direction of light by G3_LightVector.
27 // 2. Specify the color of light by G3_LightColor.
28 // 3. Specify the light to be enabled by G3_PolygonAttr.
29 //
30 // Note that there are four lights available.
31 //---------------------------------------------------------------------------
32 
33 #ifdef SDK_TWL
34 #include <twl.h>
35 #else
36 #include <nitro.h>
37 #endif
38 #include "DEMO.h"
39 
40 s16     gCubeGeometry[3 * 8] = {
41     FX16_ONE, FX16_ONE, FX16_ONE,
42     FX16_ONE, FX16_ONE, -FX16_ONE,
43     FX16_ONE, -FX16_ONE, FX16_ONE,
44     FX16_ONE, -FX16_ONE, -FX16_ONE,
45     -FX16_ONE, FX16_ONE, FX16_ONE,
46     -FX16_ONE, FX16_ONE, -FX16_ONE,
47     -FX16_ONE, -FX16_ONE, FX16_ONE,
48     -FX16_ONE, -FX16_ONE, -FX16_ONE
49 };
50 
51 VecFx10 gCubeNormal1[8] = {
52     GX_VECFX10(0, 0, FX32_ONE - 1),
53     GX_VECFX10(0, FX32_ONE - 1, 0),
54     GX_VECFX10(FX32_ONE - 1, 0, 0),
55     GX_VECFX10(0, 0, -FX32_ONE + 1),
56     GX_VECFX10(0, -FX32_ONE + 1, 0),
57     GX_VECFX10(-FX32_ONE + 1, 0, 0)
58 };
59 
60 VecFx10 gCubeNormal2[8] = {
61     GX_VECFX10(FX32_SQRT1_3, FX32_SQRT1_3, FX32_SQRT1_3),
62     GX_VECFX10(FX32_SQRT1_3, FX32_SQRT1_3, -FX32_SQRT1_3),
63     GX_VECFX10(FX32_SQRT1_3, -FX32_SQRT1_3, FX32_SQRT1_3),
64     GX_VECFX10(FX32_SQRT1_3, -FX32_SQRT1_3, -FX32_SQRT1_3),
65     GX_VECFX10(-FX32_SQRT1_3, FX32_SQRT1_3, FX32_SQRT1_3),
66     GX_VECFX10(-FX32_SQRT1_3, FX32_SQRT1_3, -FX32_SQRT1_3),
67     GX_VECFX10(-FX32_SQRT1_3, -FX32_SQRT1_3, FX32_SQRT1_3),
68     GX_VECFX10(-FX32_SQRT1_3, -FX32_SQRT1_3, -FX32_SQRT1_3)
69 };
70 
71 s16    *gVertexArray = NULL;
72 VecFx10 *gNormalArray = NULL;
73 
setVtxArray(s16 * array)74 inline void setVtxArray(s16 *array)
75 {
76     gVertexArray = array;
77 }
78 
setNormalArray(VecFx10 * array)79 inline void setNormalArray(VecFx10 *array)
80 {
81     gNormalArray = array;
82 }
83 
vtx(int idx)84 inline void vtx(int idx)
85 {
86     G3_Vtx(gVertexArray[idx * 3], gVertexArray[idx * 3 + 1], gVertexArray[idx * 3 + 2]);
87 }
88 
normal(int idx)89 inline void normal(int idx)
90 {
91     G3_Direct1(G3OP_NORMAL, gNormalArray[idx]);
92     // use G3_Normal(x, y, z) if not packed
93 }
94 
95 
NrmVtxQuad(int idx0,int idx1,int idx2,int idx3)96 static void NrmVtxQuad(int idx0, int idx1, int idx2, int idx3)
97 {
98     normal(idx0);
99     vtx(idx0);
100     normal(idx1);
101     vtx(idx1);
102     normal(idx2);
103     vtx(idx2);
104     normal(idx3);
105     vtx(idx3);
106 }
107 
NrmQuad(int nrm,int idx0,int idx1,int idx2,int idx3)108 static void NrmQuad(int nrm, int idx0, int idx1, int idx2, int idx3)
109 {
110     normal(nrm);
111     vtx(idx0);
112     vtx(idx1);
113     vtx(idx2);
114     vtx(idx3);
115 }
116 
drawLeftCube(u16 Rotate,u8 count)117 static void drawLeftCube(u16 Rotate, u8 count)
118 {
119     G3_PushMtx();
120 
121     // Rotate and translate the cube
122     {
123         fx16    s = FX_SinIdx(Rotate);
124         fx16    c = FX_CosIdx(Rotate);
125 
126         G3_Translate(-3 << (FX32_SHIFT - 1), 0, 0);
127 
128         G3_RotX(s, c);
129         G3_RotY(s, c);
130         G3_RotZ(s, c);
131     }
132 
133     // Set the material color( diffuse, ambient , specular ) as basic white
134     DEMO_Set3DDefaultMaterial(FALSE, TRUE);
135     DEMO_Set3DDefaultShininessTable();
136 
137     G3_PolygonAttr((GXLightMask)(count >> 4),   // lighting is varying
138                    GX_POLYGONMODE_MODULATE,     // modulation mode
139                    GX_CULL_BACK,       // cull back
140                    0,                  // polygon ID(0 - 63)
141                    31,                 // alpha(0 - 31)
142                    0                   // OR of GXPolygonAttrMisc's value
143         );
144 
145     setVtxArray(gCubeGeometry);
146     setNormalArray(gCubeNormal1);
147 
148     G3_Begin(GX_BEGIN_QUADS);
149 
150     {
151         NrmQuad(0, 2, 0, 4, 6);
152         NrmQuad(3, 7, 5, 1, 3);
153         NrmQuad(5, 6, 4, 5, 7);
154         NrmQuad(2, 3, 1, 0, 2);
155         NrmQuad(1, 5, 4, 0, 1);
156         NrmQuad(4, 6, 7, 3, 2);
157     }
158 
159     G3_End();
160 
161     G3_PopMtx(1);
162 }
163 
drawRightCube(u16 Rotate,u8 count)164 static void drawRightCube(u16 Rotate, u8 count)
165 {
166     G3_PushMtx();
167 
168     // Rotate and translate the cube
169     {
170         fx16    s = FX_SinIdx(Rotate);
171         fx16    c = FX_CosIdx(Rotate);
172 
173         G3_Translate(3 << (FX32_SHIFT - 1), 0, 0);
174 
175         G3_RotX(s, c);
176         G3_RotY(s, c);
177         G3_RotZ(s, c);
178     }
179 
180     // Set the material color( diffuse, ambient , specular ) as basic white
181     DEMO_Set3DDefaultMaterial(FALSE, TRUE);
182     DEMO_Set3DDefaultShininessTable();
183 
184     G3_PolygonAttr((GXLightMask)(count >> 4),   // lighting is varying
185                    GX_POLYGONMODE_MODULATE,     // modulation mode
186                    GX_CULL_BACK,       // cull back
187                    0,                  // polygon ID(0 - 63)
188                    31,                 // alpha(0 - 31)
189                    0                   // OR of GXPolygonAttrMisc's value
190         );
191 
192     setVtxArray(gCubeGeometry);
193     setNormalArray(gCubeNormal2);
194 
195     G3_Begin(GX_BEGIN_QUADS);
196 
197     {
198         NrmVtxQuad(2, 0, 4, 6);
199         NrmVtxQuad(7, 5, 1, 3);
200         NrmVtxQuad(6, 4, 5, 7);
201         NrmVtxQuad(3, 1, 0, 2);
202         NrmVtxQuad(5, 4, 0, 1);
203         NrmVtxQuad(6, 7, 3, 2);
204     }
205     G3_End();
206 
207     G3_PopMtx(1);
208 }
209 
210 #ifdef SDK_TWL
TwlMain(void)211 void TwlMain(void)
212 #else
213 void NitroMain(void)
214 #endif
215 {
216     u8      count = 0;
217     u16     Rotate = 0;                // for rotating cubes(0-65535)
218 
219     //---------------------------------------------------------------------------
220     // Initialize:
221     // They enable IRQ interrupts, initialize VRAM, and set BG #0 for 3D mode.
222     //---------------------------------------------------------------------------
223     DEMOInitCommon();
224     DEMOInitVRAM();
225     DEMOInitDisplay3D();
226 
227     DEMOStartDisplay();
228     while (1)
229     {
230         G3X_Reset();
231         count++;
232         Rotate += 256;
233 
234         //---------------------------------------------------------------------------
235         // Set up camera matrix
236         //---------------------------------------------------------------------------
237         {
238             VecFx32 Eye = { 0, 0, FX32_ONE * 5 };       // Eye position
239             VecFx32 at = { 0, 0, 0 };  // Viewpoint
240             VecFx32 vUp = { 0, FX32_ONE, 0 };   // Up
241 
242             G3_LookAt(&Eye, &vUp, &at, NULL);
243         }
244 
245         //---------------------------------------------------------------------------
246         // Set up light colors and direction.
247         // Notice that light vector is transformed by the current vector matrix
248         // immediately after LightVector command is issued.
249         //
250         // GX_LIGHTID_0: white, downward
251         // GX_LIGHTID_1: red, leftward
252         // GX_LIGHTID_2: green, upward
253         // GX_LIGHTID_3: blue, rightward
254         //---------------------------------------------------------------------------
255         G3_LightVector(GX_LIGHTID_0, 0, -FX16_ONE + 1, 0);
256         G3_LightColor(GX_LIGHTID_0, GX_RGB(31, 31, 31));
257 
258         G3_LightVector(GX_LIGHTID_1, -FX16_ONE + 1, 0, 0);
259         G3_LightColor(GX_LIGHTID_1, GX_RGB(31, 0, 0));
260 
261         G3_LightVector(GX_LIGHTID_2, 0, FX16_ONE - 1, 0);
262         G3_LightColor(GX_LIGHTID_2, GX_RGB(0, 31, 0));
263 
264         G3_LightVector(GX_LIGHTID_3, FX16_ONE - 1, 0, 0);
265         G3_LightColor(GX_LIGHTID_3, GX_RGB(0, 0, 31));
266 
267         G3_PushMtx();
268 
269         drawLeftCube(Rotate, count);
270         drawRightCube(Rotate, count);
271 
272         G3_PopMtx(1);
273 
274         // swapping the polygon list RAM, the vertex RAM, etc.
275         G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
276 
277 #ifdef SDK_AUTOTEST
278         GX_SetBankForLCDC(GX_VRAM_LCDC_C);
279         EXT_TestSetVRAMForScreenShot(GX_VRAM_LCDC_C);
280         EXT_TestScreenShot(100, 0xEF41160C);
281         EXT_TestTickCounter();
282 #endif //SDK_AUTOTEST
283 
284         OS_WaitVBlankIntr();           // Waiting the end of VBlank interrupt
285     }
286 }
287 
288 //---------------------------------------------------------------------------
289 // VBlank interrupt function:
290 //
291 // Interrupt handlers are registered on the interrupt table by OS_SetIRQFunction.
292 // OS_EnableIrqMask selects IRQ interrupts to enable, and
293 // OS_EnableIrq enables IRQ interrupts.
294 // Notice that you have to call 'OS_SetIrqCheckFlag' to check a VBlank interrupt.
295 //---------------------------------------------------------------------------
VBlankIntr(void)296 void VBlankIntr(void)
297 {
298     OS_SetIrqCheckFlag(OS_IE_V_BLANK); // checking VBlank interrupt
299 }
300