1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     DL-geom.c
4 
5   Copyright 1998-2006 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 
14 #include <demo.h>
15 #include <math.h>
16 #include <string.h> // needed for memcpy()
17 
18 /*---------------------------------------------------------------------------*
19    Forward references
20  *---------------------------------------------------------------------------*/
21 
22 void        main            ( void );
23 
24 static void CameraInit      ( void );
25 static void DrawInit        ( void );
26 static void PrintIntro      ( void );
27 static void DrawTick        ( void );
28 static void VertexLightInit ( void );
29 
30 static void AnimTick        ( void );
31 
32 static void SendVertex ( u8 posIndex, u8 normalIndex,
33                          u8 colorIndex, u8 texCoordIndex );
34 
35 void MyCreateSphere(u8 numMajor, u8 numMinor);
36 void MyDrawSphere(u8 numMajor, u8 numMinor);
37 void MyDrawCube(void);
38 
39 /*---------------------------------------------------------------------------*
40    Defines
41  *---------------------------------------------------------------------------*/
42 #define PI           3.14159265358979323846F
43 #define SIDE         50
44 #define WOOD1_TEX_ID 5
45 #define TMP_SIZE     65536
46 #define SPHERE_PTS   100
47 #define NUM_LISTDL   14
48 
49 /*---------------------------------------------------------------------------*
50    Global variables
51  *---------------------------------------------------------------------------*/
52 Mtx v;
53 
54 TPLPalettePtr tpl = 0;
55 
56 u32 rot = 0;
57 
58 // display list stuff goes here.
59 u8* cubeDL;
60 u8* sphereDL;
61 u8* listDL[NUM_LISTDL];
62 u32 cubeSize;
63 u32 sphereSize;
64 u32 listSize[NUM_LISTDL];
65 
66 /*---*/
67 
68 GXVtxDescList    vcd[3][GX_MAX_VTXDESCLIST_SZ];
69 
70 float SFloatVert[SPHERE_PTS][3] ATTRIBUTE_ALIGN(32);
71 
72 float CFloatVert[] ATTRIBUTE_ALIGN(32) =
73                      {  -SIDE, SIDE, -SIDE,
74                         -SIDE, SIDE, SIDE,
75                         -SIDE, -SIDE, SIDE,
76                         -SIDE, -SIDE, -SIDE,
77                         SIDE, SIDE, -SIDE,
78                         SIDE, -SIDE, -SIDE,
79                         SIDE, -SIDE, SIDE,
80                         SIDE, SIDE, SIDE
81                     };
82 
83 float CFloatNorm[] ATTRIBUTE_ALIGN(32) =
84                     {   -1.0F, 0.0F, 0.0F,
85                         1.0F, 0.0F, 0.0F,
86                         0.0F, -1.0F, 0.0F,
87                         0.0F, 1.0F, 0.0F,
88                         0.0F, 0.0F, -1.0F,
89                         0.0F, 0.0F, 1.0F
90                     };
91 
92 u8  CColorRGBA8[] ATTRIBUTE_ALIGN(32) =
93                         {   255, 0, 0, 255,
94                             255, 0, 0, 192,
95                             255, 0, 0, 128,
96                             255, 0, 0, 64,
97                             255, 0, 0, 0};      //GX_RGBA8
98 
99 float CFloatTex[] ATTRIBUTE_ALIGN(32) =
100                     {   0.0F, 0.0F,
101                         1.0F, 0.0F,
102                         1.0F, 1.0F,
103                         0.0F, 1.0F
104                     };
105 
106 /*---------------------------------------------------------------------------*
107    Application main loop
108  *---------------------------------------------------------------------------*/
main(void)109 void main ( void )
110 {
111     DEMOInit(NULL);
112 
113     DrawInit();         // Define my vertex formats and set array pointers.
114 
115     PrintIntro();  // Print demo directions
116 
117     VertexLightInit();
118 
119     DEMOPadRead();     // Read the joystick for this frame
120 
121     // While the quit button is not pressed
122     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
123     {
124         DEMOPadRead();  // Read the joystick for this frame
125 
126         AnimTick();     // Do animation based on input
127 
128         DEMOBeforeRender();
129 
130         DrawTick();     // Draw the model.
131 
132         DEMODoneRender();
133     }
134 
135     OSHalt("End of demo");
136 }
137 
138 /*---------------------------------------------------------------------------*
139    Functions
140  *---------------------------------------------------------------------------*/
141 
142 
143 /*---------------------------------------------------------------------------*
144     Name:           CameraInit
145 
146     Description:    Initialize the projection matrix and load into hardware.
147 
148     Arguments:      v   view matrix to be passed to ViewInit
149                     cameraLocScale  scale for the camera's distance from the
150                                     object - to be passed to ViewInit
151 
152     Returns:        none
153  *---------------------------------------------------------------------------*/
CameraInit(void)154 static void CameraInit      ( void )
155 {
156     Mtx44 p;
157     Vec camPt = {0.0F, 0.0F, 650.0F};
158     Vec up = {0.0F, 1.0F, 0.0F};
159     Vec origin = {0.0F, 0.0F, 0.0F};
160 
161     MTXFrustum(p, 240, -240, -320, 320, 500, 2000);
162 
163     GXSetProjection(p, GX_PERSPECTIVE);
164 
165     MTXLookAt(v, &camPt, &up, &origin);
166 }
167 
168 /*---------------------------------------------------------------------------*
169     Name:           DrawInit
170 
171     Description:    Calls the correct initialization function for the current
172                     model.
173 
174     Arguments:      none
175 
176     Returns:        none
177  *---------------------------------------------------------------------------*/
DrawInit(void)178 static void DrawInit( void )
179 {
180     u8* tmpDL;
181     GXTexObj to;
182     u16 i;
183 
184     CameraInit();   // Initialize the camera.
185 
186     GXClearVtxDesc();
187 
188     // set position params
189     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
190     GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
191     GXSetArray(GX_VA_POS, CFloatVert, 12);
192 
193     // set color params
194     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
195     GXSetVtxDesc(GX_VA_CLR0, GX_INDEX8);
196     GXSetArray(GX_VA_CLR0, CColorRGBA8, 4);
197 
198     // set normal params
199     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
200     GXSetVtxDesc(GX_VA_NRM, GX_INDEX8);
201     GXSetArray(GX_VA_NRM, CFloatNorm, 12);
202 
203     // set tex coord params
204     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
205     GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
206     GXSetArray(GX_VA_TEX0, CFloatTex, 8);
207 
208     // save the current VCD
209     GXGetVtxDescv(vcd[0]);
210 
211     // make cube display list
212     // note that the display-list buffer area must be forced out of
213     // the CPU cache since it will be written using the write-gather pipe
214     tmpDL = MEMAllocFromAllocator(&DemoAllocator1, TMP_SIZE);
215     ASSERTMSG(tmpDL != NULL, "error allocating tmpDL");
216     DCInvalidateRange( (void *) tmpDL, TMP_SIZE);
217 
218     GXBeginDisplayList( (void *) tmpDL, (u32) TMP_SIZE);
219     MyDrawCube();
220     cubeSize = GXEndDisplayList();
221     cubeDL = MEMAllocFromAllocator(&DemoAllocator1, cubeSize);
222     ASSERTMSG(cubeDL != NULL, "error allocating cubeDL");
223     memcpy( (void *) cubeDL, (void *) tmpDL, cubeSize);
224     DCFlushRange( (void *) cubeDL, cubeSize);
225 
226     // set up VCD/VAT for sphere drawing
227     GXClearVtxDesc();
228 
229     // set position params
230     GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
231     GXSetVtxDesc(GX_VA_POS, GX_INDEX16);
232     GXSetArray(GX_VA_POS, SFloatVert, 12);
233 
234     // set normal params
235     GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
236     GXSetVtxDesc(GX_VA_NRM, GX_INDEX16);
237     GXSetArray(GX_VA_NRM, SFloatVert, 12);
238 
239     // save the current VCD
240     GXGetVtxDescv(vcd[1]);
241 
242     // generate sphere coordinates
243     MyCreateSphere(8, 12);
244     DCFlushRange( (void *) SFloatVert, sizeof(SFloatVert) );
245 
246     // make sphere display list
247     // Note: must get tmpDL out of the cpu cache again
248     // (it got back into the cache because of the memcpy)
249     DCInvalidateRange( (void *) tmpDL, TMP_SIZE);
250     GXBeginDisplayList( (void *) tmpDL, (u32) TMP_SIZE);
251     MyDrawSphere(8, 12);
252     sphereSize = GXEndDisplayList();
253     sphereDL = MEMAllocFromAllocator(&DemoAllocator1, sphereSize);
254     ASSERTMSG(sphereDL != NULL, "error allocating sphereDL");
255     memcpy( (void *) sphereDL, (void *) tmpDL, sphereSize);
256     DCFlushRange( (void *) sphereDL, sphereSize);
257 
258     // set up VCD/VAT for misc. object drawing
259     GXClearVtxDesc();
260 
261     // set position params
262     GXSetVtxAttrFmt(GX_VTXFMT2, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
263     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
264 
265     // set normal params
266     GXSetVtxAttrFmt(GX_VTXFMT2, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
267     GXSetVtxDesc(GX_VA_NRM, GX_DIRECT);
268 
269     // save the current VCD
270     GXGetVtxDescv(vcd[2]);
271 
272     // make misc. object display lists
273 
274     for(i=0; i<NUM_LISTDL; i++)
275     {
276         DCInvalidateRange( (void *) tmpDL, TMP_SIZE);
277         GXBeginDisplayList( (void *) tmpDL, (u32) TMP_SIZE);
278         switch(i % 7)
279         {
280           case 0: GXDrawCylinder(20); break;
281           case 1: GXDrawTorus((f32) 0.5, 12, 16);  break;
282           case 2: GXDrawSphere(12, 16); break;
283           case 3: GXDrawCube(); break;
284           case 4: GXDrawDodeca(); break;
285           case 5: GXDrawOctahedron(); break;
286           case 6: GXDrawIcosahedron(); break;
287         }
288         listSize[i] = GXEndDisplayList();
289         listDL[i] = MEMAllocFromAllocator(&DemoAllocator1, listSize[i]);
290         ASSERTMSG(listDL[i] != NULL, "error allocating listDL");
291         memcpy( (void *) listDL[i], (void *) tmpDL, listSize[i]);
292         DCFlushRange( (void *) listDL[i], listSize[i]);
293     }
294 
295     // technically, tmpDL should be freed at this point...
296 
297     // Pixel processing setup
298     GXSetChanCtrl(
299         GX_ALPHA0,
300         GX_FALSE,   // enable channel
301         GX_SRC_REG, // amb source
302         GX_SRC_VTX, // mat source
303         GX_LIGHT0,  // light mask
304         GX_DF_CLAMP,// diffuse function
305         GX_AF_NONE);
306 
307     // cube texture setup
308     GXSetNumTevStages(1);
309     TPLGetPalette(&tpl, "gxTextrs.tpl");
310     TPLGetGXTexObjFromPalette(tpl, &to, WOOD1_TEX_ID);
311     GXLoadTexObj(&to, GX_TEXMAP0);
312 
313     // set blend op
314     GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA,
315                    GX_LO_CLEAR /* ignored for blend */);
316 }
317 
318 /*---------------------------------------------------------------------------*
319     Name:           PrintIntro
320 
321     Description:    Prints the directions on how to use this demo.
322 
323     Arguments:      none
324 
325     Returns:        none
326  *---------------------------------------------------------------------------*/
PrintIntro(void)327 static void PrintIntro( void )
328 {
329     OSReport("\n\n");
330     OSReport("************************************************\n");
331     OSReport("DL-geom: display list test with geometry\n");
332     OSReport("************************************************\n");
333     OSReport("The top two objects are drawn using display lists.\n");
334     OSReport("The bottom two objects are drawn normally.\n");
335     OSReport("\n");
336     OSReport("To quit hit the start button.\n");
337     OSReport("\n");
338     OSReport("A Button     : Hold to pause the animation\n");
339     OSReport("************************************************\n");
340     OSReport("\n");
341 }
342 
343 /*---------------------------------------------------------------------------*
344     Name:           DrawTick
345 
346     Description:    Draw the current model once.
347 
348     Arguments:      v       view matrix
349                     m       model matrix
350 
351     Returns:        none
352  *---------------------------------------------------------------------------*/
DrawTick(void)353 static void DrawTick( void )
354 {
355     u16 i;
356     Mtx mv, r1, r2, mr, ms, mt;
357     GXColor other  = {  0,   0,   0, 255};
358     GXColor yellow = {255, 255,   0, 255};
359     GXColor cyan   = {  0, 255, 255, 255};
360 
361     // cube setup
362 
363     GXSetVtxDescv(vcd[0]);
364     GXSetArray(GX_VA_POS, CFloatVert, 12);
365     GXSetArray(GX_VA_NRM, CFloatNorm, 12);
366 
367     GXSetNumChans(1);
368     GXSetChanCtrl(
369         GX_COLOR0,
370         GX_TRUE,    // enable channel
371         GX_SRC_REG, // amb source
372         GX_SRC_VTX, // mat source
373         GX_LIGHT0,  // light mask
374         GX_DF_CLAMP,// diffuse function
375         GX_AF_NONE);
376     GXSetNumTexGens(1);
377     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
378     GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE);
379 
380     // Draw regular cube
381 
382     MTXTrans(mt, -250, -200, 0);
383     MTXRotDeg(r1, 'X', (float)rot);
384     MTXRotDeg(r2, 'y', (float)rot/2.0F);
385     MTXConcat(r2, r1, mr);
386     MTXConcat(mt, mr, mv);
387     MTXConcat(v, mv, mv);
388     GXLoadPosMtxImm(mv, GX_PNMTX0);
389     MTXInverse(mv, mv);
390     MTXTranspose(mv, mv);
391     GXLoadNrmMtxImm(mv, GX_PNMTX0);
392 
393     MyDrawCube();
394 
395     // Draw DL cube
396 
397     MTXTrans(mt, -250, 200, 0);
398     MTXConcat(mt, mr, mv);
399     MTXConcat(v, mv, mv);
400     GXLoadPosMtxImm(mv, GX_PNMTX0);
401 
402     GXCallDisplayList(cubeDL, cubeSize);
403 
404     // sphere setup
405 
406     GXSetVtxDescv(vcd[1]);
407     GXSetArray(GX_VA_POS, SFloatVert, 12);
408     GXSetArray(GX_VA_NRM, SFloatVert, 12);
409 
410     GXSetNumChans(1);
411     GXSetChanCtrl(
412         GX_COLOR0,
413         GX_TRUE,    // enable channel
414         GX_SRC_REG, // amb source
415         GX_SRC_REG, // mat source
416         GX_LIGHT0,  // light mask
417         GX_DF_CLAMP,// diffuse function
418         GX_AF_NONE);
419     GXSetNumTexGens(0);
420     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
421     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
422 
423     // Draw regular sphere
424 
425     GXSetChanMatColor(GX_COLOR0A0, yellow);
426 
427     MTXTrans(mt, 250, -200, 0);
428     MTXScale(ms, 60, 60, 60);
429     MTXConcat(mr, ms, mv);
430     MTXConcat(mt, mv, mv);
431     MTXConcat(v, mv, mv);
432     GXLoadPosMtxImm(mv, GX_PNMTX0);
433 
434     MyDrawSphere(8, 12);
435 
436     // Draw DL sphere
437 
438     GXSetChanMatColor(GX_COLOR0A0, cyan);
439 
440     MTXTrans(mt, 250, 200, 0);
441     MTXConcat(mr, ms, mv);
442     MTXConcat(mt, mv, mv);
443     MTXConcat(v, mv, mv);
444     GXLoadPosMtxImm(mv, GX_PNMTX0);
445 
446     GXCallDisplayList(sphereDL, sphereSize);
447 
448     // Draw list objects
449 
450     GXSetVtxDescv(vcd[2]);
451 
452     for(i=0; i<NUM_LISTDL; i++)
453     {
454         other.r = (u8) (i*255/NUM_LISTDL);
455         other.g = (u8) (i*127/NUM_LISTDL);
456         other.b = (u8) (255-other.g);
457 
458         GXSetChanMatColor(GX_COLOR0A0, other);
459 
460         MTXTrans(mt, (f32) (-275.0+550.0*i/(NUM_LISTDL-1)), 80*(i&1)-40, 0);
461         MTXScale(ms, 30, 30, 30);
462         MTXConcat(mr, ms, mv);
463         MTXConcat(mt, mv, mv);
464         MTXConcat(v, mv, mv);
465         GXLoadPosMtxImm(mv, GX_PNMTX0);
466 
467         GXCallDisplayList(listDL[i], listSize[i]);
468     }
469 }
470 
471 /*---------------------------------------------------------------------------*/
VertexLightInit(void)472 static void VertexLightInit ( void )
473 {
474     GXLightObj MyLight;
475     GXColor litcolor = {255, 255, 255, 255}; // white
476 
477     GXInitLightPos(&MyLight, 0.0F, 0.0F, 0.0F);
478     GXInitLightColor(&MyLight, litcolor);
479     GXLoadLightObjImm(&MyLight, GX_LIGHT0);
480 }
481 
482 /*---------------------------------------------------------------------------*
483     Name:           AnimTick
484 
485     Description:    Animates the camera and object based on the joystick's
486                     state.
487 
488     Arguments:      none
489 
490     Returns:        none
491  *---------------------------------------------------------------------------*/
AnimTick(void)492 static void AnimTick ( void )
493 {
494     u16 buttons = DEMOPadGetButton(0);
495     s8 stickX = DEMOPadGetStickX(0);
496     s8 stickY = DEMOPadGetStickY(0);
497 
498     if(!(buttons & PAD_BUTTON_A))
499     {
500         rot ++;
501         if(rot > 719)
502         {
503             rot = 0;
504         }
505     }
506 }
507 
508 /*---------------------------------------------------------------------------*
509     Name:           MyCreateSphere
510 
511     Description:    Creates a matrix containing sphere coordinates.
512 
513     Arguments:      numMajor - number of major steps
514                     numMinor - number of minor steps
515 
516     Returns:        none
517  *---------------------------------------------------------------------------*/
MyCreateSphere(u8 numMajor,u8 numMinor)518 void MyCreateSphere(u8 numMajor, u8 numMinor)
519 {
520   f32 majorStep = (PI / numMajor);
521   f32 minorStep = (2.0F * PI / numMinor);
522   s32 i, j, v=0;
523 
524   // top point
525   SFloatVert[v][0] = (f32) 0.0;
526   SFloatVert[v][1] = (f32) 0.0;
527   SFloatVert[v][2] = (f32) 1.0;
528   v++;
529   for (i = 1; i < numMajor; i++)
530   {
531     f32 a = i * majorStep;
532     f32 r0 = sinf(a);
533     f32 z0 = cosf(a);
534 
535     for (j = 0; j < numMinor; j++)
536     {
537       f32 c = j * minorStep;
538       f32 x = cosf(c);
539       f32 y = sinf(c);
540 
541       SFloatVert[v][0] = x * r0;
542       SFloatVert[v][1] = y * r0;
543       SFloatVert[v][2] = z0;
544       v++;
545     }
546   }
547 
548   SFloatVert[v][0] = (f32)  0.0;
549   SFloatVert[v][1] = (f32)  0.0;
550   SFloatVert[v][2] = (f32) -1.0;
551 }
552 
553 /*---------------------------------------------------------------------------*
554     Name:           MyDrawSphere
555 
556     Description:    Draw a sphere.  Sends indices to sphere matrix.
557 
558     Arguments:      numMajor - number of major steps
559                     numMinor - number of minor steps
560 
561     Returns:        none
562  *---------------------------------------------------------------------------*/
MyDrawSphere(u8 numMajor,u8 numMinor)563 void MyDrawSphere(u8 numMajor, u8 numMinor)
564 {
565   s32 i, j, v=0;
566   s32 n;
567 
568   // top hat
569   GXBegin(GX_TRIANGLEFAN, GX_VTXFMT1, (u16) (numMinor+2));
570   GXPosition1x16((u16) 0);
571   GXNormal1x16((u16) 0);
572   for (j = numMinor; j >= 0; j--)
573   {
574       GXPosition1x16((u16) (j % numMinor + 1));
575       GXNormal1x16((u16) (j % numMinor + 1));
576   }
577   GXEnd();
578 
579   // central portion
580   for (i = 1; i < numMajor-1; i++)
581   {
582     n = (i-1) * numMinor + 1;
583     GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, (u16) ((numMinor+1)*2));
584     for (j = 0; j <= numMinor; j++)
585     {
586       GXPosition1x16((u16) (n + numMinor + j % numMinor));
587       GXNormal1x16((u16) (n + numMinor + j % numMinor));
588       GXPosition1x16((u16) (n + j % numMinor));
589       GXNormal1x16((u16) (n + j % numMinor));
590     }
591     GXEnd();
592   }
593 
594   // bottom cup
595   n = (numMajor-1) * numMinor;
596 
597   GXBegin(GX_TRIANGLEFAN, GX_VTXFMT1, (u16) (numMinor+2));
598   GXPosition1x16((u16) (n+1));
599   GXNormal1x16((u16) (n+1));
600   for (j = numMinor; j >= 0; j--)
601   {
602       GXPosition1x16((u16) (n - j % numMinor));
603       GXNormal1x16((u16) (n - j % numMinor));
604   }
605   GXEnd();
606 }
607 
608 /*---------------------------------------------------------------------------*/
609 
SendVertex(u8 posIndex,u8 normalIndex,u8 colorIndex,u8 texCoordIndex)610 static void SendVertex ( u8 posIndex, u8 normalIndex,
611                          u8 colorIndex, u8 texCoordIndex )
612 {
613     GXPosition1x8(posIndex);
614     GXNormal1x8(normalIndex);
615     GXColor1x8(colorIndex);
616     GXTexCoord1x8(texCoordIndex);
617 }
618 
619 /*---------------------------------------------------------------------------*
620     Name:           MyDrawCube
621 
622     Description:    Draws a cube.  Position, normal, etc. are indirect
623 
624     Arguments:      none
625 
626     Returns:        none
627  *---------------------------------------------------------------------------*/
MyDrawCube(void)628 void MyDrawCube(void)
629 {
630     GXBegin(GX_TRIANGLES, GX_VTXFMT0, 6*6);
631 
632         SendVertex(0, 0, 1, 0);
633         SendVertex(1, 0, 2, 1);
634         SendVertex(2, 0, 3, 2);
635         SendVertex(2, 0, 3, 2);
636         SendVertex(3, 0, 4, 3);
637         SendVertex(0, 0, 1, 0);
638 
639         SendVertex(4, 1, 0, 0);
640         SendVertex(5, 1, 0, 1);
641         SendVertex(6, 1, 0, 2);
642         SendVertex(6, 1, 0, 2);
643         SendVertex(7, 1, 0, 3);
644         SendVertex(4, 1, 0, 0);
645 
646         SendVertex(2, 2, 0, 0);
647         SendVertex(6, 2, 0, 1);
648         SendVertex(5, 2, 0, 2);
649         SendVertex(5, 2, 0, 2);
650         SendVertex(3, 2, 0, 3);
651         SendVertex(2, 2, 0, 0);
652 
653         SendVertex(1, 3, 0, 0);
654         SendVertex(0, 3, 0, 1);
655         SendVertex(4, 3, 0, 2);
656         SendVertex(4, 3, 0, 2);
657         SendVertex(7, 3, 0, 3);
658         SendVertex(1, 3, 0, 0);
659 
660         SendVertex(5, 4, 0, 0);
661         SendVertex(4, 4, 0, 1);
662         SendVertex(0, 4, 0, 2);
663         SendVertex(0, 4, 0, 2);
664         SendVertex(3, 4, 0, 3);
665         SendVertex(5, 4, 0, 0);
666 
667         SendVertex(6, 5, 0, 0);
668         SendVertex(2, 5, 0, 1);
669         SendVertex(1, 5, 0, 2);
670         SendVertex(1, 5, 0, 2);
671         SendVertex(7, 5, 0, 3);
672         SendVertex(6, 5, 0, 0);
673 
674     GXEnd();
675 }
676 
677 /****************************************************************************/
678 /****************************************************************************/
679