1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - GX - demos - UnitTours/3D_Shininess
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 that uses the shininess table:
20 //
21 // There are nine spheres displayed. Each of them displayed with different shininess adjustment
22 // by the shininess table.
23 //
24 // HOWTO:
25 // 1. Set up the shininess table by G3_Shininess().
26 // 2. Prepare to use the shininess table by G3_MaterialColorSpecEmi(..., TRUE).
27 //---------------------------------------------------------------------------
28
29 #ifdef SDK_TWL
30 #include <twl.h>
31 #else
32 #include <nitro.h>
33 #endif
34 #include "DEMO.h"
35 #include "commandList.h"
36
37 #define NUM_SHININESS_TYPES 9
38 static u32 shininess_table[NUM_SHININESS_TYPES][32];
39
40
drawSphere(BOOL shininess)41 static void drawSphere(BOOL shininess)
42 {
43 //---------------------------------------------------------------------------
44 // GX_RGB(0, 0, 0) set except specular color for comparison
45 //---------------------------------------------------------------------------
46 G3_MaterialColorDiffAmb(GX_RGB(23, 0, 0), // diffuse
47 GX_RGB(8, 0, 0), // ambient
48 FALSE // use diffuse as vtx color if TRUE
49 );
50
51 G3_MaterialColorSpecEmi(GX_RGB(31, 31, 31), // specular
52 GX_RGB(0, 0, 0), // emission
53 shininess // use shininess table if TRUE
54 );
55
56
57 G3_PolygonAttr(GX_LIGHTMASK_0, // lighting
58 GX_POLYGONMODE_MODULATE, // modulation mode
59 GX_CULL_BACK, // cull back
60 0, // polygon ID(0 - 63)
61 31, // alpha(0 - 31)
62 0 // OR of GXPolygonAttrMisc's value
63 );
64
65 // Transfer by DMA
66 G3_Begin(GX_BEGIN_TRIANGLES);
67 MI_SendGXCommand(3, sphere1, sphere_size);
68 G3_End();
69
70 }
71
72 // Power fixed point format( 0.8 ) number
powFixedPoint8_(u8 base,u8 exponent)73 static inline u8 powFixedPoint8_(u8 base, u8 exponent)
74 {
75 u16 result = (u16)base;
76 const u16 LIGHTING_L_DOT_H_SHIFT = 8;
77
78 if (exponent == 0)
79 return base;
80
81 while (exponent - 1 > 0)
82 {
83 result *= (u16)base;
84 result = (u16)(result >> LIGHTING_L_DOT_H_SHIFT);
85 exponent--;
86 }
87
88 return (u8)result;
89 }
90
91 #include <nitro/code32.h> // avoid byte access problems
92 // Initialize the shininess table.
InitShininessTables_()93 static void InitShininessTables_()
94 {
95 u8 i, j;
96 u8 *pShininess = NULL;
97 const u8 tableLength = 32 * sizeof(u32);
98
99 for (i = 0; i < NUM_SHININESS_TYPES; i++)
100 {
101 pShininess = (u8 *)&shininess_table[i][0];
102
103 for (j = 0; j < tableLength - 1; j++)
104 {
105 pShininess[j] = powFixedPoint8_((u8)(j * 2 + 1), i);
106 }
107
108 // set the max value specially
109 pShininess[tableLength - 1] = 0xFF;
110 }
111 }
112
113
114 #ifdef SDK_TWL
TwlMain(void)115 void TwlMain(void)
116 #else
117 void NitroMain(void)
118 #endif
119 {
120 u8 count = 0;
121 u16 Rotate = 0; // for rotating cubes(0-65535)
122
123 //---------------------------------------------------------------------------
124 // Initialize:
125 // They enable IRQ interrupts, initialize VRAM, and set BG #0 for 3D mode.
126 //---------------------------------------------------------------------------
127 DEMOInitCommon();
128 DEMOInitVRAM();
129 DEMOInitDisplay3D();
130
131 // Initialize shininess tables
132 InitShininessTables_();
133
134 DEMOStartDisplay();
135 while (1)
136 {
137 G3X_Reset();
138 count++;
139 Rotate += 256;
140
141 //---------------------------------------------------------------------------
142 // Set up the camera matrix
143 //---------------------------------------------------------------------------
144 {
145 VecFx32 Eye = { 0, 0, FX32_ONE }; // Eye position
146 VecFx32 at = { 0, 0, 0 }; // Viewpoint
147 VecFx32 vUp = { 0, FX32_ONE, 0 }; // Up
148
149 G3_LookAt(&Eye, &vUp, &at, NULL);
150 }
151
152 //---------------------------------------------------------------------------
153 // Set up light colors and direction.
154 // Notice that light vector is transformed by the current vector matrix
155 // immediately after LightVector command is issued.
156 //---------------------------------------------------------------------------
157 {
158 const fx32 XY_R = FX_Mul(FX32_SQRT1_3, FX32_SQRT2);
159
160 G3_LightVector(GX_LIGHTID_0,
161 (fx16)FX_Mul(XY_R, FX_SinIdx(Rotate)),
162 (fx16)FX_Mul(XY_R, FX_CosIdx(Rotate)), (fx16)(FX32_SQRT1_3 * -1));
163
164 G3_LightColor(GX_LIGHTID_0, GX_RGB(31, 31, 31));
165 }
166
167 G3_PushMtx();
168
169 //---------------------------------------------------------------------------
170 // Draw spheres , changing its shininess table.
171 //---------------------------------------------------------------------------
172 G3_Translate(0, 0, -15 * FX32_ONE);
173 {
174 u8 i = 0;
175 const fx32 step = FX32_ONE * 5;
176 const u8 num_row = 3;
177 const u8 num_cor = NUM_SHININESS_TYPES / num_row;
178 for (i = 0; i < NUM_SHININESS_TYPES; i++)
179 {
180 int ix = i % num_row;
181 int iy = i / num_row;
182 //---------------------------------------------------------------------------
183 // Set up the shininess table
184 //---------------------------------------------------------------------------
185 G3_Shininess(&shininess_table[i][0]);
186
187
188 G3_PushMtx();
189 G3_Translate(step * ix - step * (num_row / 2), -step * iy + step * (num_cor / 2),
190 0);
191 drawSphere(TRUE);
192 G3_PopMtx(1);
193 }
194 }
195
196 G3_PopMtx(1);
197
198 // swapping the polygon list RAM, the vertex RAM, etc.
199 G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
200
201 #ifdef SDK_AUTOTEST
202 GX_SetBankForLCDC(GX_VRAM_LCDC_C);
203 EXT_TestSetVRAMForScreenShot(GX_VRAM_LCDC_C);
204 EXT_TestScreenShot(100, 0x445FBD00);
205 EXT_TestTickCounter();
206 #endif //SDK_AUTOTEST
207
208 OS_WaitVBlankIntr(); // Waiting the end of VBlank interrupt
209 }
210 }
211
212 #include <nitro/codereset.h>
213
214 //---------------------------------------------------------------------------
215 // VBlank interrupt function:
216 //
217 // Interrupt handlers are registered on the interrupt table by OS_SetIRQFunction.
218 // OS_EnableIrqMask selects IRQ interrupts to enable, and
219 // OS_EnableIrq enables IRQ interrupts.
220 // Notice that you have to call 'OS_SetIrqCheckFlag' to check a VBlank interrupt.
221 //---------------------------------------------------------------------------
VBlankIntr(void)222 void VBlankIntr(void)
223 {
224 OS_SetIrqCheckFlag(OS_IE_V_BLANK); // checking VBlank interrupt
225 }
226