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