1 /*
2   File:        MenuGraphics.cpp
3   Description: Menu graphics management
4   Program:     BlockOut
5   Author:      Jean-Luc PONS
6 
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2 of the License, or
10   (at your option) any later version.
11 
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16 */
17 
18 #include "Menu.h"
19 
20 // ---------------------------------------------------------------------
21 
InitGraphics()22 void Menu::InitGraphics() {
23 
24   startMenuTime = 0.0f;
25 
26   // Intitial rotation matrix of "BLOCKOUT" letters (Startup demo)
27 
28   blOrgMatrix.Init33( 1.0f , 0.0f , 0.0f ,
29                       0.0f ,-1.0f , 0.0f ,
30                       0.0f , 0.0f ,-1.0f );
31 
32   // Origin and end position of "BLOCKOUT" letters (Startup demo)
33 
34   // B
35   startPos[0] = v(0.7f,-0.5f,0.0f);
36   endPos[0] = v(0.65f,0.9f ,3.0f);
37 
38   // L
39   startPos[1] =  v(0.25f,-0.5f,0.0f);
40   endPos[1] =  v(0.25f,1.1f,3.0f);
41 
42   // O
43   startPos[2] =  v(0.0f,-0.5f,0.0f);
44   endPos[2] =  v(-0.15f,1.1f,3.0f);
45 
46   // C
47   startPos[3] =  v(-0.25f,-0.5f,0.0f);
48   endPos[3] =  v(-0.55f,1.1f,3.0f);
49 
50   // K
51   startPos[4] =  v(-0.7f,-0.5f,0.0f);
52   endPos[4]= v(-1.25f,0.9f,3.0f);
53 
54   // O
55   startPos[5] =  v(0.25f,-0.5f,0.0f);
56   endPos[5] =  v(0.25f,0.4f,3.0f);
57 
58   // U
59   startPos[6] =  v(0.0f,-0.5f,0.0f);
60   endPos[6] =  v(-0.15f,0.4f,3.0f);
61 
62   // T
63   startPos[7] =  v( -0.25f,-0.5f,0.0f);
64   endPos[7] =  v(-0.55f,0.4f,3.0f);
65 
66   // II
67   startPos[8] =  v( -0.5f,-0.5f,0.0f);
68   endPos[8] =  v(-1.35f,0.4f,3.0f);
69 
70   for(int i=0;i<BLLETTER_NB;i++) {
71     isAdded[i] = FALSE;
72     isStarted[i] = FALSE;
73   }
74   animEnded = FALSE;
75   menuEscaped = FALSE;
76 
77 }
78 
79 // ---------------------------------------------------------------------
80 
SetViewMatrix(GLfloat * mView)81 void Menu::SetViewMatrix(GLfloat *mView) {
82    memcpy(matView , mView , 16*sizeof(GLfloat));
83 }
84 
GetViewMatrix()85 GLfloat *Menu::GetViewMatrix() {
86    return matView;
87 }
88 
89 // ---------------------------------------------------------------------
90 
FullRepaint()91 void Menu::FullRepaint() {
92   // For the 2 back buffers
93   fullRepaint = 2;
94 }
95 
96 // ---------------------------------------------------------------------
97 
Create(int width,int height)98 int Menu::Create(int width,int height) {
99 
100   scrWidth = width;
101   scrHeight = height;
102 
103   // Menu viewport
104   menuView.x      = 0;
105   menuView.y      = 0;
106   menuView.width  = width;
107   menuView.height = height;
108 
109   // Projection matrix
110   double fAspectRatio = (double)width / (double)height;
111   glMatrixMode( GL_PROJECTION );
112   glLoadIdentity();
113   gluPerspective(60.0,fAspectRatio,0.1,10.0);
114   glGetFloatv( GL_PROJECTION_MATRIX , matProj );
115 
116   // Initialiase letters
117   if( !InitBlLetters() )
118     return GL_FAIL;
119 
120   // Initialiase grid
121   if( !theGrid.Create() )
122     return GL_FAIL;
123 
124   // Background
125   int x1 = fround( (float)width  * 0.13f );
126   int y1 = fround( (float)height * 0.41f );
127   int x2 = fround( (float)width  * 0.87f );
128   int y2 = fround( (float)height * 0.985f );
129   if( !background.RestoreDeviceObjects(STR("images/menuback.png"),STR("none"),width,height) )
130     return GL_FAIL;
131   background.UpdateSprite(x1,y1,x2,y2,0.0f,0.0f,1.0f,1.0f);
132 
133   if(!background2.RestoreDeviceObjects(STR("images/menucredits.png"),STR("none"),width,height) )
134     return GL_FAIL;
135   background2.UpdateSprite(x1,y1,x2,y2,0.0f,0.0f,1.0f,1.0f);
136 
137   // Font
138   wFont = fround( (float)width  * 0.0205f );
139   hFont = fround( (float)height * 0.0449f );
140   if( !font.RestoreDeviceObjects(STR("images/menufont.png"),STR("none"),width,height) )
141     return GL_FAIL;
142 
143   if(!font2.RestoreDeviceObjects(STR("images/menufont2.png"),STR("none"),width,height))
144     return GL_FAIL;
145 
146   // onLine logo
147   if( !onlineLogo.RestoreDeviceObjects(STR("images/online.png"),STR("images/onlinea.png"),width,height) )
148     return GL_FAIL;
149 
150   x1 = fround( 0.148f * (float)width );
151   y1 = fround( 0.413f * (float)height );
152   x2 = fround( 0.232f * (float)width );
153   y2 = fround( 0.524f * (float)height );
154   onlineLogo.UpdateSprite(x1,y1,x2,y2,0.0f,0.0f,1.0f,1.0f);
155 
156   // Controls menu page
157   if( !controlsPage.Create(width,height) )
158     return GL_FAIL;
159 
160   // Credits page
161   if( !creditsPage.Create(width,height) )
162     return GL_FAIL;
163 
164   FullRepaint();
165 
166   return GL_OK;
167 }
168 
169 // ---------------------------------------------------------------------
170 
RenderChar(int x,int y,int w,int h,BOOL selected,char c)171 void Menu::RenderChar(int x,int y,int w,int h,BOOL selected,char c) {
172 
173   BOOL ok = FALSE;
174   int  fnt = 1;
175 
176   float sX = 0.0f;
177   float sY = 0.0f;
178   float eX = 0.0f;
179   float eY = 0.0f;
180 
181   if( !selected && c==' ' ) {
182     // Do not render unselected space
183     return;
184   }
185 
186   // Space
187   if( c==' ' ) {
188     sX = 12.0f * 0.0638f + 0.005f;
189     sY = 0.2930f;
190     eX = 13.0f * 0.0638f + 0.003f;
191     eY = 0.3828f;
192     ok = TRUE;
193   }
194 
195   // Mapping
196   if( c>='A' && c<='O' ) {
197     sX = (float)(c-'A')   * 0.0638f + 0.005f;
198     sY = 0.0f;
199     eX = (float)(c-'A'+1) * 0.0638f + 0.003f;
200     eY = 0.0898f;
201     ok = TRUE;
202   }
203 
204   if( c>='P' && c<='Z' ) {
205     sX = (float)(c-'P')   * 0.0638f + 0.005f;
206     sY = 0.0977f;
207     eX = (float)(c-'P'+1) * 0.0638f + 0.003f;
208     eY = 0.1875f;
209     ok = TRUE;
210   }
211 
212   if( c>='a' && c<='o' ) {
213     sX = (float)(c-'a')   * 0.0638f + 0.005f;
214     sY = 0.1953f;
215     eX = (float)(c-'a'+1) * 0.0638f + 0.003f;
216     eY = 0.2852f;
217     ok = TRUE;
218   }
219 
220   if( c>='p' && c<='z' ) {
221     sX = (float)(c-'p')   * 0.0638f + 0.005f;
222     sY = 0.2930f;
223     eX = (float)(c-'p'+1) * 0.0638f + 0.003f;
224     eY = 0.3828f;
225     ok = TRUE;
226   }
227 
228   if( c>='0' && c<='9' ) {
229     sX = (float)(c-'0')   * 0.0638f + 0.005f;
230     sY = 0.3906f;
231     eX = (float)(c-'0'+1) * 0.0638f + 0.003f;
232     eY = 0.4805f;
233     ok = TRUE;
234   }
235 
236   if( c=='[' ) {
237     sX = 10.0f   * 0.0638f + 0.005f;
238     sY = 0.3906f;
239     eX = 11.0f * 0.0638f + 0.003f;
240     eY = 0.4805f;
241     ok = TRUE;
242   }
243 
244   if( c==']' ) {
245     sX = 11.0f   * 0.0638f + 0.005f;
246     sY = 0.3906f;
247     eX = 12.0f * 0.0638f + 0.003f;
248     eY = 0.4805f;
249     ok = TRUE;
250   }
251 
252   if( c==':' ) {
253     sX = 12.0f   * 0.0638f + 0.005f;
254     sY = 0.3906f;
255     eX = 13.0f * 0.0638f + 0.003f;
256     eY = 0.4805f;
257     ok = TRUE;
258   }
259 
260   if( c=='.' ) {
261     sX = 13.0f   * 0.0638f + 0.005f;
262     sY = 0.3906f;
263     eX = 14.0f * 0.0638f + 0.003f;
264     eY = 0.4805f;
265     ok = TRUE;
266   }
267 
268   if( c==',' ) {
269     sX = 14.0f   * 0.0638f + 0.005f;
270     sY = 0.3906f;
271     eX = 15.0f * 0.0638f + 0.003f;
272     eY = 0.4805f;
273     ok = TRUE;
274   }
275 
276   if( c=='-' ) {
277     sX = 11.0f   * 0.0638f + 0.005f;
278     sY = 0.2930f;
279     eX = 12.0f * 0.0638f + 0.003f;
280     eY = 0.3828f;
281     ok = TRUE;
282   }
283 
284   if( c=='+' ) {
285     sX = 11.0f   * 0.0638f + 0.005f;
286     sY = 0.0977f;
287     eX = 12.0f * 0.0638f + 0.003f;
288     eY = 0.1875f;
289     ok = TRUE;
290   }
291 
292   if( c=='/' ) {
293     sX = 12.0f   * 0.0638f + 0.005f;
294     sY = 0.0977f;
295     eX = 13.0f * 0.0638f + 0.003f;
296     eY = 0.1875f;
297     ok = TRUE;
298   }
299 
300   if( c=='{' ) {
301     sX = 13.0f   * 0.0638f + 0.005f;
302     sY = 0.0977f;
303     eX = 14.0f * 0.0638f + 0.003f;
304     eY = 0.1875f;
305     ok = TRUE;
306   }
307 
308   if( c=='@' ) {
309     sX = 14.0f   * 0.0638f + 0.005f;
310     sY = 0.0977f;
311     eX = 15.0f * 0.0638f + 0.003f;
312     eY = 0.1875f;
313     ok = TRUE;
314   }
315 
316   if( c=='\'' ) {
317     sX = 14.0f   * 0.0638f + 0.005f;
318     sY = 0.2930f;
319     eX = 15.0f * 0.0638f + 0.003f;
320     eY = 0.3828f;
321     ok = TRUE;
322   }
323 
324   if( c=='#' ) {
325     sX = 12.0f * 0.0638f + 0.005f;
326     sY = 0.2930f;
327     eX = 13.7f * 0.0638f + 0.003f;
328     eY = 0.3828f;
329     ok = TRUE;
330   }
331 
332   if( c=='!' ) {
333     sX = 0.0f   * 0.0638f + 0.005f;
334     sY = 0.0f;
335     eX = 1.0f * 0.0638f + 0.003f;
336     eY = 0.0898f;
337     ok = TRUE;
338     fnt = 2;
339   }
340 
341   if( c=='$' ) {
342     sX = 1.0f   * 0.0638f + 0.005f;
343     sY = 0.0f;
344     eX = 2.0f * 0.0638f + 0.003f;
345     eY = 0.0898f;
346     ok = TRUE;
347     fnt = 2;
348   }
349 
350   if( c=='%' ) {
351     sX = 2.0f   * 0.0638f + 0.005f;
352     sY = 0.0f;
353     eX = 3.0f * 0.0638f + 0.003f;
354     eY = 0.0898f;
355     ok = TRUE;
356     fnt = 2;
357   }
358 
359   if( c=='&' ) {
360     sX = 3.0f   * 0.0638f + 0.005f;
361     sY = 0.0f;
362     eX = 4.0f * 0.0638f + 0.003f;
363     eY = 0.0898f;
364     ok = TRUE;
365     fnt = 2;
366   }
367 
368   if( c=='*' ) {
369     sX = 4.0f   * 0.0638f + 0.005f;
370     sY = 0.0f;
371     eX = 5.0f * 0.0638f + 0.003f;
372     eY = 0.0898f;
373     ok = TRUE;
374     fnt = 2;
375   }
376 
377   if( c=='(' ) {
378     sX = 5.0f   * 0.0638f + 0.005f;
379     sY = 0.0f;
380     eX = 6.0f * 0.0638f + 0.003f;
381     eY = 0.0898f;
382     ok = TRUE;
383     fnt = 2;
384   }
385 
386   if( c==')' ) {
387     sX = 6.0f   * 0.0638f + 0.005f;
388     sY = 0.0f;
389     eX = 7.0f * 0.0638f + 0.003f;
390     eY = 0.0898f;
391     ok = TRUE;
392     fnt = 2;
393   }
394 
395   if( c=='_' ) {
396     sX = 7.0f   * 0.0638f + 0.005f;
397     sY = 0.0f;
398     eX = 8.0f * 0.0638f + 0.003f;
399     eY = 0.0898f;
400     ok = TRUE;
401     fnt = 2;
402   }
403 
404   if( c=='?' ) {
405     sX = 8.0f   * 0.0638f + 0.005f;
406     sY = 0.0f;
407     eX = 9.0f * 0.0638f + 0.003f;
408     eY = 0.0898f;
409     ok = TRUE;
410     fnt = 2;
411   }
412 
413   if( c==';' ) {
414     sX = 9.0f   * 0.0638f + 0.005f;
415     sY = 0.0f;
416     eX = 10.0f * 0.0638f + 0.003f;
417     eY = 0.0898f;
418     ok = TRUE;
419     fnt = 2;
420   }
421 
422   if( !ok ) return;
423 
424   if(selected) {
425     sY += 0.508f;
426     eY += 0.508f;
427   }
428 
429   if( fnt==1 ) {
430     font.UpdateSprite(x,y,x+w,y+h,sX,sY,eX,eY);
431     font.Render();
432   } else {
433     font2.UpdateSprite(x,y,x+w,y+h,sX,sY,eX,eY);
434     font2.Render();
435   }
436 
437 }
438 
439 // ---------------------------------------------------------------------
440 
RenderTitle(char * title)441 void Menu::RenderTitle(char *title) {
442 
443   int  lgth = (int)strlen(title);
444   int  nwFont = fround((float)wFont*1.1f);
445   int  nhFont = fround((float)hFont*1.1f);
446   int  x1 = (scrWidth - (nwFont * lgth))/2;
447   int  y1 = fround( 0.43f * (float)scrHeight );
448 
449   for(int i=0;i<lgth;i++,x1+=nwFont) {
450     RenderChar(x1,y1,nwFont,nhFont,FALSE,title[i]);
451   }
452 
453 }
454 
455 // ---------------------------------------------------------------------
456 
RenderText(int x,int y,BOOL selected,char * text)457 void Menu::RenderText(int x,int y,BOOL selected,char *text) {
458 
459   float startLine   = 0.515f;
460   float startColumn = 0.15f;
461   float lineHeight  = 0.045f;
462 
463   int   lgth = (int)strlen(text);
464   int   x1 = fround( startColumn*(float)scrWidth ) + x*wFont;
465   int   y1 = fround( (startLine+y*lineHeight)*(float)scrHeight );
466 
467   for(int i=0;i<lgth;i++,x1+=wFont) {
468     RenderChar(x1,y1,wFont,hFont,selected,text[i]);
469   }
470 
471 }
472 
473 // ---------------------------------------------------------------------
474 
Render()475 void Menu::Render() {
476 
477   // Disable texture, alpha and z buff
478   glDisable(GL_TEXTURE_2D);
479   glDisable(GL_DEPTH_TEST);
480   glDisable(GL_BLEND);
481 
482   // Set Projection and viewport
483   glMatrixMode(GL_PROJECTION);
484   glLoadMatrixf(matProj);
485   glMatrixMode(GL_MODELVIEW);
486   glLoadMatrixf(matView);
487   glViewport(menuView.x,menuView.y,menuView.width,menuView.height);
488 
489   // Clear and render the background
490   if( fullRepaint>0 || !animEnded ) {
491 
492     // Menu startup demo
493     glClear( GL_COLOR_BUFFER_BIT );
494     theGrid.Render();
495 
496     for(int i=0;i<BLLETTER_NB;i++) {
497       if( !isAdded[i] ) {
498         glMatrixMode(GL_MODELVIEW);
499         glLoadMatrixf(matView);
500         glMultMatrixf(blMatrix[i].GetGL());
501         blLetters[i]->Render(FALSE);
502       }
503     }
504 
505     fullRepaint--;
506 
507   }
508 
509   if( animEnded ) {
510     if( selPage != &creditsPage )
511       background.Render();
512     else
513       background2.Render();
514     selPage->Render();
515     // Restore full viewport
516     glViewport(menuView.x,menuView.y,menuView.width,menuView.height);
517   }
518 
519 }
520 
521 // ---------------------------------------------------------------------
522 
InvalidateDeviceObjects()523 void Menu::InvalidateDeviceObjects() {
524   controlsPage.InvalidateDeviceObjects();
525   creditsPage.InvalidateDeviceObjects();
526   theGrid.InvalidateDeviceObjects();
527   background.InvalidateDeviceObjects();
528   background2.InvalidateDeviceObjects();
529   font.InvalidateDeviceObjects();
530   font2.InvalidateDeviceObjects();
531   onlineLogo.InvalidateDeviceObjects();
532   for(int i=0;i<BLLETTER_NB;i++)
533     blLetters[i]->InvalidateDeviceObjects();
534 }
535 
536 // ---------------------------------------------------------------------
537 
ResetAnim(float fTime)538 void Menu::ResetAnim(float fTime) {
539 
540   startMenuTime = fTime;
541   for(int i=0;i<BLLETTER_NB;i++) {
542     isAdded[i] = FALSE;
543     isStarted[i] = FALSE;
544   }
545   theGrid.Clear();
546   animEnded = FALSE;
547 
548 }
549 
550 // ---------------------------------------------------------------------
551 
ProcessAnim(float fTime)552 void Menu::ProcessAnim(float fTime) {
553 
554   if( startMenuTime==0.0f ) {
555     // Menu startup
556     startMenuTime = fTime;
557   }
558 
559   // Compute letters transformation matrix
560   float angle = 0.0f;
561   float xPos = 0.0f;
562   float yPos = 0.0f;
563   float zPos = 0.0f;
564   GLMatrix t;
565   GLMatrix r;
566   float mTime = (fTime - startMenuTime);
567 
568   for(int i=0;i<BLLETTER_NB;i++) {
569 
570     float delay = (float)i * 0.25f; // 250ms delay between letters
571 
572     if( mTime < delay ) {
573       angle =  0.0f;
574       xPos  =  startPos[i].x;
575       yPos  =  startPos[i].y;
576       zPos  =  startPos[i].z;
577     } else if( mTime > ANIMTIME+delay ) {
578 
579       animEnded = (i==BLLETTER_NB-1);
580       if( animEnded ) FullRepaint();
581 
582       // Add the letter to the grid
583       if( !isAdded[i] ) {
584 
585         BLOCKITEM c[MAX_CUBE];
586         int nbCube;
587 
588         isAdded[i] = TRUE;
589         int ox = fround( endPos[i].x*10.0f + 0.5f ) + GRID_WIDTH/2;
590         int oy = fround( endPos[i].y*10.0f ) + GRID_HEIGHT/2;
591         blLetters[i]->CopyCube(c,&nbCube);
592         for(int j=0;j<nbCube;j++) {
593           theGrid.SetValue( ox + c[j].x , oy + c[j].y , 1);
594         }
595         if(!menuEscaped)
596           soundManager->PlayTchh();
597 
598       }
599 
600     } else {
601 
602       if( (i==1 || i==5) && !isStarted[i] ) {
603         soundManager->PlayWozz();
604         isStarted[i] = TRUE;
605       }
606 
607       float ratio = (mTime-delay)/ANIMTIME;
608       angle = PI * ratio;
609       xPos  = startPos[i].x + (endPos[i].x-startPos[i].x) * ratio;
610       yPos  = startPos[i].y + (endPos[i].y-startPos[i].y) * ratio;
611       zPos  = startPos[i].z + (endPos[i].z-startPos[i].z) * ratio;
612 
613     }
614 
615     t.Translate(xPos,yPos,zPos);
616     r.RotateX(angle);
617     blMatrix[i].Identity();
618     blMatrix[i].Multiply(&t);
619     blMatrix[i].Multiply(&r);
620     blMatrix[i].Multiply(&blOrgMatrix);
621 
622   }
623 
624 
625 }
626 
627 // ---------------------------------------------------------------------
628 
InitBlLetters()629 int Menu::InitBlLetters() {
630 
631   int hr;
632 
633   VERTEX org = v(0.0f,0.0f,0.0f);
634 
635   // "B" letter
636   blLetters[0] = new PolyCube();
637   blLetters[0]->AddCube(0,0,0);
638   blLetters[0]->AddCube(1,0,0);
639   blLetters[0]->AddCube(2,0,0);
640   blLetters[0]->AddCube(3,0,0);
641   blLetters[0]->AddCube(4,0,0);
642   blLetters[0]->AddCube(5,0,0);
643   blLetters[0]->AddCube(0,1,0);
644   blLetters[0]->AddCube(4,1,0);
645   blLetters[0]->AddCube(0,2,0);
646   blLetters[0]->AddCube(4,2,0);
647   blLetters[0]->AddCube(0,3,0);
648   blLetters[0]->AddCube(1,3,0);
649   blLetters[0]->AddCube(2,3,0);
650   blLetters[0]->AddCube(3,3,0);
651   blLetters[0]->AddCube(4,3,0);
652   blLetters[0]->AddCube(1,4,0);
653   blLetters[0]->AddCube(4,4,0);
654   blLetters[0]->AddCube(1,5,0);
655   blLetters[0]->AddCube(4,5,0);
656   blLetters[0]->AddCube(1,6,0);
657   blLetters[0]->AddCube(2,6,0);
658   blLetters[0]->AddCube(3,6,0);
659   blLetters[0]->AddCube(4,6,0);
660   blLetters[0]->AddCube(5,6,0);
661   hr = blLetters[0]->Create(0.1f,org,FALSE);
662   if(!hr) return GL_FAIL;
663 
664   // "L" letter
665   blLetters[1] = new PolyCube();
666   blLetters[1]->AddCube(0,0,0);
667   blLetters[1]->AddCube(1,0,0);
668   blLetters[1]->AddCube(2,0,0);
669   blLetters[1]->AddCube(2,1,0);
670   blLetters[1]->AddCube(2,2,0);
671   blLetters[1]->AddCube(2,3,0);
672   blLetters[1]->AddCube(2,4,0);
673   hr = blLetters[1]->Create(0.1f,org,FALSE);
674   if(!hr) return GL_FAIL;
675 
676   // "O" letter
677   blLetters[2] = new PolyCube();
678   blLetters[2]->AddCube(0,0,0);
679   blLetters[2]->AddCube(1,0,0);
680   blLetters[2]->AddCube(2,0,0);
681   blLetters[2]->AddCube(0,1,0);
682   blLetters[2]->AddCube(2,1,0);
683   blLetters[2]->AddCube(0,2,0);
684   blLetters[2]->AddCube(2,2,0);
685   blLetters[2]->AddCube(0,3,0);
686   blLetters[2]->AddCube(2,3,0);
687   blLetters[2]->AddCube(0,4,0);
688   blLetters[2]->AddCube(1,4,0);
689   blLetters[2]->AddCube(2,4,0);
690   hr = blLetters[2]->Create(0.1f,org,FALSE);
691   if(!hr) return GL_FAIL;
692 
693   // "C" letter
694   blLetters[3] = new PolyCube();
695   blLetters[3]->AddCube(0,0,0);
696   blLetters[3]->AddCube(1,0,0);
697   blLetters[3]->AddCube(2,0,0);
698   blLetters[3]->AddCube(0,1,0);
699   blLetters[3]->AddCube(2,1,0);
700   blLetters[3]->AddCube(2,2,0);
701   blLetters[3]->AddCube(0,3,0);
702   blLetters[3]->AddCube(2,3,0);
703   blLetters[3]->AddCube(0,4,0);
704   blLetters[3]->AddCube(1,4,0);
705   blLetters[3]->AddCube(2,4,0);
706   hr = blLetters[3]->Create(0.1f,org,FALSE);
707   if(!hr) return GL_FAIL;
708 
709 
710   // "K" letter
711   blLetters[4] = new PolyCube();
712   blLetters[4]->AddCube(0,0,0);
713   blLetters[4]->AddCube(1,0,0);
714   blLetters[4]->AddCube(4,0,0);
715   blLetters[4]->AddCube(5,0,0);
716   blLetters[4]->AddCube(1,1,0);
717   blLetters[4]->AddCube(4,1,0);
718   blLetters[4]->AddCube(2,2,0);
719   blLetters[4]->AddCube(4,2,0);
720   blLetters[4]->AddCube(3,3,0);
721   blLetters[4]->AddCube(4,3,0);
722   blLetters[4]->AddCube(2,4,0);
723   blLetters[4]->AddCube(4,4,0);
724   blLetters[4]->AddCube(1,5,0);
725   blLetters[4]->AddCube(4,5,0);
726   blLetters[4]->AddCube(0,6,0);
727   blLetters[4]->AddCube(1,6,0);
728   blLetters[4]->AddCube(4,6,0);
729   blLetters[4]->AddCube(5,6,0);
730   hr = blLetters[4]->Create(0.1f,org,FALSE);
731   if(!hr) return GL_FAIL;
732 
733   // "O" letter
734   blLetters[5] = new PolyCube();
735   blLetters[5]->AddCube(0,0,0);
736   blLetters[5]->AddCube(1,0,0);
737   blLetters[5]->AddCube(2,0,0);
738   blLetters[5]->AddCube(0,1,0);
739   blLetters[5]->AddCube(2,1,0);
740   blLetters[5]->AddCube(0,2,0);
741   blLetters[5]->AddCube(2,2,0);
742   blLetters[5]->AddCube(0,3,0);
743   blLetters[5]->AddCube(2,3,0);
744   blLetters[5]->AddCube(0,4,0);
745   blLetters[5]->AddCube(1,4,0);
746   blLetters[5]->AddCube(2,4,0);
747   hr = blLetters[5]->Create(0.1f,org,FALSE);
748   if(!hr) return GL_FAIL;
749 
750   // "U" letter
751   blLetters[6] = new PolyCube();
752   blLetters[6]->AddCube(0,0,0);
753   blLetters[6]->AddCube(1,0,0);
754   blLetters[6]->AddCube(2,0,0);
755   blLetters[6]->AddCube(0,1,0);
756   blLetters[6]->AddCube(2,1,0);
757   blLetters[6]->AddCube(0,2,0);
758   blLetters[6]->AddCube(2,2,0);
759   blLetters[6]->AddCube(0,3,0);
760   blLetters[6]->AddCube(2,3,0);
761   blLetters[6]->AddCube(0,4,0);
762   blLetters[6]->AddCube(2,4,0);
763   hr = blLetters[6]->Create(0.1f,org,FALSE);
764   if(!hr) return GL_FAIL;
765 
766   // "T" letter
767   blLetters[7] = new PolyCube();
768   blLetters[7]->AddCube(1,0,0);
769   blLetters[7]->AddCube(1,1,0);
770   blLetters[7]->AddCube(1,2,0);
771   blLetters[7]->AddCube(1,3,0);
772   blLetters[7]->AddCube(0,4,0);
773   blLetters[7]->AddCube(1,4,0);
774   blLetters[7]->AddCube(2,4,0);
775   hr = blLetters[7]->Create(0.1f,org,FALSE);
776   if(!hr) return GL_FAIL;
777 
778   // "II" letter
779   blLetters[8] = new PolyCube();
780   blLetters[8]->AddCube(0,0,0);
781   blLetters[8]->AddCube(1,0,0);
782   blLetters[8]->AddCube(2,0,0);
783   blLetters[8]->AddCube(3,0,0);
784   blLetters[8]->AddCube(4,0,0);
785   blLetters[8]->AddCube(1,1,0);
786   blLetters[8]->AddCube(1,2,0);
787   blLetters[8]->AddCube(3,1,0);
788   blLetters[8]->AddCube(3,2,0);
789   blLetters[8]->AddCube(0,3,0);
790   blLetters[8]->AddCube(1,3,0);
791   blLetters[8]->AddCube(2,3,0);
792   blLetters[8]->AddCube(3,3,0);
793   blLetters[8]->AddCube(4,3,0);
794   hr = blLetters[8]->Create(0.1f,org,FALSE);
795   if(!hr) return GL_FAIL;
796 
797   return GL_OK;
798 }
799