1 /*
2   File:        PolyCube.cpp
3   Description: PolyCube 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 "PolyCube.h"
19 #include <math.h>
20 
21 #define SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }
22 
23 #define DIR_OX 1
24 #define DIR_OY 2
25 #define DIR_OZ 3
26 
27 const EDGE edgeOrg[] = {
28 
29   {{0,1,0} , {1,1,0} , DIR_OX} , // 0
30   {{1,1,0} , {1,0,0} , DIR_OY} , // 1
31   {{0,0,0} , {1,0,0} , DIR_OX} , // 2
32   {{0,1,0} , {0,0,0} , DIR_OY} , // 3
33 
34   {{0,1,0} , {0,1,1} , DIR_OZ} , // 4
35   {{1,1,0} , {1,1,1} , DIR_OZ} , // 5
36   {{1,0,0} , {1,0,1} , DIR_OZ} , // 6
37   {{0,0,0} , {0,0,1} , DIR_OZ} , // 7
38 
39   {{0,1,1} , {1,1,1} , DIR_OX} , // 8
40   {{1,1,1} , {1,0,1} , DIR_OY} , // 9
41   {{0,0,1} , {1,0,1} , DIR_OX} , // 10
42   {{0,1,1} , {0,0,1} , DIR_OY}   // 11
43 
44 };
45 
46 //-----------------------------------------------------------------------------
47 
PolyCube()48 PolyCube::PolyCube() {
49 
50   lineList  = 0;
51   ghostList = 0;
52   bigEdgeList = 0;
53   nbCube = 0;
54   hScore = 0;
55   lScore = 0;
56   isFlat = FALSE;
57   isBasic = FALSE;
58   hasGhost = FALSE;
59   nbOrientation = 0;
60   hasGhost = FALSE;
61   edges = (EDGE *)malloc(MAX_CUBE*12*sizeof(EDGE));
62   allRot = (ORIENTATION *)malloc(24*sizeof(ORIENTATION));
63 
64 }
65 
66 //-----------------------------------------------------------------------------
67 
~PolyCube()68 PolyCube::~PolyCube() {
69   free(edges);
70   free(allRot);
71 }
72 
73 //-----------------------------------------------------------------------------
74 
SetInfo(int highScore,int lowScore,BOOL flat,BOOL basic)75 void PolyCube::SetInfo(int highScore,int lowScore,BOOL flat,BOOL basic) {
76 
77   hScore = highScore;
78   lScore = lowScore;
79   isFlat = flat;
80   isBasic = basic;
81 
82 }
83 
84 //-----------------------------------------------------------------------------
85 
AddCube(int x,int y,int z)86 void PolyCube::AddCube(int x,int y,int z) {
87 
88   if( nbCube<MAX_CUBE ) {
89     cubes[nbCube].x = x;
90     cubes[nbCube].y = y;
91     cubes[nbCube].z = z;
92     nbCube++;
93   }
94 
95 }
96 
97 //-----------------------------------------------------------------------------
98 
AddOrientation(int r0,int r1,int r2)99 void PolyCube::AddOrientation(int r0,int r1,int r2) {
100   allRot[nbOrientation].r0 = r0;
101   allRot[nbOrientation].r1 = r1;
102   allRot[nbOrientation].r2 = r2;
103   nbOrientation++;
104 }
105 
106 //-----------------------------------------------------------------------------
107 
GetOrientationAt(int idx)108 ORIENTATION *PolyCube::GetOrientationAt(int idx) {
109   return &(allRot[idx]);
110 }
111 
112 //-----------------------------------------------------------------------------
GetNbOrientation()113 int PolyCube::GetNbOrientation() {
114   return nbOrientation;
115 }
116 
117 //-----------------------------------------------------------------------------
118 
GetHighScore()119 int PolyCube::GetHighScore() {
120 
121   return hScore;
122 
123 }
124 
125 //-----------------------------------------------------------------------------
126 
GetLowScore()127 int PolyCube::GetLowScore() {
128 
129   return lScore;
130 
131 }
132 
133 //-----------------------------------------------------------------------------
134 
IsInSet(int set)135 BOOL PolyCube::IsInSet(int set) {
136 
137   switch(set) {
138     case BLOCKSET_EXTENDED:
139       return TRUE;
140     case BLOCKSET_BASIC:
141       return isBasic;
142     case BLOCKSET_FLAT:
143       return isFlat;
144   }
145 
146   return FALSE;
147 
148 }
149 
150 //-----------------------------------------------------------------------------
151 
GetNbCube()152 int PolyCube::GetNbCube() {
153 
154   return nbCube;
155 
156 }
157 
158 //-----------------------------------------------------------------------------
159 
GetWidth()160 int PolyCube::GetWidth() {
161   int maxW = 0;
162   for(int i=0;i<nbCube;i++)
163     if(cubes[i].x > maxW) maxW = cubes[i].x;
164   return maxW + 1;
165 }
166 
167 //-----------------------------------------------------------------------------
168 
GetHeight()169 int PolyCube::GetHeight() {
170   int maxH = 0;
171   for(int i=0;i<nbCube;i++)
172     if(cubes[i].y > maxH) maxH = cubes[i].y;
173   return maxH + 1;
174 }
175 
176 //-----------------------------------------------------------------------------
177 
GetDepth()178 int PolyCube::GetDepth() {
179   int maxD = 0;
180   for(int i=0;i<nbCube;i++)
181     if(cubes[i].z > maxD) maxD = cubes[i].z;
182   return maxD + 1;
183 }
184 
185 //-----------------------------------------------------------------------------
186 
GetMaxDim()187 int PolyCube::GetMaxDim() {
188   int w = GetWidth();
189   int h = GetHeight();
190   int d = GetDepth();
191   int maxDim = w;
192   if( h > maxDim ) maxDim = h;
193   if( d > maxDim ) maxDim = d;
194   return maxDim;
195 }
196 
197 //-----------------------------------------------------------------------------
198 
InitRotationCenter()199 void PolyCube::InitRotationCenter() {
200 
201   // Emulate "BlockOut original" rotation center
202   iCenter.x = GetWidth() - 1;
203   iCenter.y = 1;
204   iCenter.z = GetDepth() - 1;
205 
206   center.x = iCenter.x * cubeSide + origin.x;
207   center.y = iCenter.y * cubeSide + origin.y;
208   center.z = iCenter.z * cubeSide + origin.z;
209 
210 }
211 //-----------------------------------------------------------------------------
212 
EdgeExist(EDGE e)213 BOOL PolyCube::EdgeExist(EDGE e) {
214 
215   BOOL found = FALSE;
216   int i = 0;
217   while(i<nbEdge && !found) {
218     found = EdgeEqual(edges[i],e);
219     if(!found) i++;
220   }
221   return found;
222 
223 }
224 
225 //-----------------------------------------------------------------------------
226 
GetEdgesAtCorner(int x,int y,int z,int * nb,int * direction)227 void PolyCube::GetEdgesAtCorner(int x,int y,int z,int *nb,int *direction) {
228 
229   int vx,vy,vz;
230 
231   for(int i=0;i<nbEdge;i++) {
232 
233     EDGE e = edges[i];
234     vx=0; vy=0; vz=0;
235 
236     if( (e.p1.x == x && e.p1.y == y && e.p1.z == z) ) {
237       vx = e.p1.x - e.p2.x;
238       vy = e.p1.y - e.p2.y;
239       vz = e.p1.z - e.p2.z;
240     }
241 
242     if( (e.p2.x == x && e.p2.y == y && e.p2.z == z) ) {
243       vx = e.p2.x - e.p1.x;
244       vy = e.p2.y - e.p1.y;
245       vz = e.p2.z - e.p1.z;
246     }
247 
248     if( vx ) {
249       if( vx<0 ) direction[*nb] = -DIR_OX;
250       else       direction[*nb] =  DIR_OX;
251       *nb=*nb+1;
252     } else if( vy ) {
253       if( vy<0 ) direction[*nb] = -DIR_OY;
254       else       direction[*nb] =  DIR_OY;
255       *nb=*nb+1;
256     } else if( vz ) {
257       if( vz<0 ) direction[*nb] = -DIR_OZ;
258       else       direction[*nb] =  DIR_OZ;
259       *nb=*nb+1;
260     }
261 
262   }
263 
264 }
265 
266 //-----------------------------------------------------------------------------
267 
IsPermut(int d1,int d2,int d3,int * dir)268 BOOL PolyCube::IsPermut(int d1,int d2,int d3,int *dir) {
269 
270   return (d1==dir[0] && d2==dir[1] && d3==dir[2]) ||
271          (d1==dir[0] && d2==dir[2] && d3==dir[1]) ||
272          (d1==dir[1] && d2==dir[0] && d3==dir[2]) ||
273          (d1==dir[1] && d2==dir[2] && d3==dir[0]) ||
274          (d1==dir[2] && d2==dir[1] && d3==dir[0]) ||
275          (d1==dir[2] && d2==dir[0] && d3==dir[1]);
276 
277 }
278 
279 //-----------------------------------------------------------------------------
280 
GetCornerAt(int x,int y,int z,VERTEX * o)281 BOOL PolyCube::GetCornerAt(int x,int y,int z,VERTEX *o) {
282 
283     int direction[8];  // 4 should be the max
284     int nbDir=0;
285 
286     GetEdgesAtCorner(x,y,z,&nbDir,direction);
287     if( nbDir==3 ) {
288       if( IsPermut(-DIR_OX,+DIR_OY,-DIR_OZ,direction) ) {
289         o->x = -1.0f; o->y = 1.0f; o->z = -1.0f;
290         return TRUE;
291       } else if( IsPermut(+DIR_OX,+DIR_OY,-DIR_OZ,direction) ) {
292         o->x = 1.0f; o->y = 1.0f; o->z = -1.0f;
293         return TRUE;
294       } else if( IsPermut(+DIR_OX,-DIR_OY,-DIR_OZ,direction) ) {
295         o->x = 1.0f; o->y = -1.0f; o->z = -1.0f;
296         return TRUE;
297       } else if( IsPermut(-DIR_OX,-DIR_OY,-DIR_OZ,direction) ) {
298         o->x = -1.0f; o->y = -1.0f; o->z = -1.0f;
299         return TRUE;
300       } else if( IsPermut(-DIR_OX,+DIR_OY,+DIR_OZ,direction) ) {
301         o->x = -1.0f; o->y = 1.0f; o->z = 1.0f;
302         return TRUE;
303       } else if( IsPermut(+DIR_OX,+DIR_OY,+DIR_OZ,direction) ) {
304         o->x = 1.0f; o->y = 1.0f; o->z = 1.0f;
305         return TRUE;
306       } else if( IsPermut(+DIR_OX,-DIR_OY,+DIR_OZ,direction) ) {
307         o->x = 1.0f; o->y = -1.0f; o->z = 1.0f;
308         return TRUE;
309       } else if( IsPermut(-DIR_OX,-DIR_OY,+DIR_OZ,direction) ) {
310         o->x = -1.0f; o->y = -1.0f; o->z = 1.0f;
311         return TRUE;
312       }
313     }
314 
315     return FALSE;
316 
317 }
318 
319 //-----------------------------------------------------------------------------
320 
EdgeEqual(EDGE e1,EDGE e2)321 BOOL PolyCube::EdgeEqual(EDGE e1,EDGE e2) {
322 
323   return ((e1.p1.x == e2.p1.x && e1.p1.y == e2.p1.y && e1.p1.z == e2.p1.z) &&
324           (e1.p2.x == e2.p2.x && e1.p2.y == e2.p2.y && e1.p2.z == e2.p2.z) ) ||
325          ((e1.p1.x == e2.p2.x && e1.p1.y == e2.p2.y && e1.p1.z == e2.p2.z) &&
326           (e1.p2.x == e2.p1.x && e1.p2.y == e2.p1.y && e1.p2.z == e2.p1.z) );
327 
328 }
329 
330 //-----------------------------------------------------------------------------
331 
Create(float cSide,VERTEX org,int ghost,float wEdge)332 int PolyCube::Create(float cSide,VERTEX org,int ghost,float wEdge) {
333 
334   int hr;
335 
336   cubeSide = cSide;
337   origin = org;
338   hasBigEdge = (wEdge!=0.0f);
339 
340   // Create edge
341 
342   nbEdge = 0;
343   for(int i=0;i<nbCube;i++) {
344     for(int j=0;j<12;j++) {
345       if( IsEdgeVisible(i,j) ) {
346 
347         EDGE e;
348         e.p1.x = cubes[i].x + edgeOrg[j].p1.x;
349         e.p1.y = cubes[i].y + edgeOrg[j].p1.y;
350         e.p1.z = cubes[i].z + edgeOrg[j].p1.z;
351 
352         e.p2.x = cubes[i].x + edgeOrg[j].p2.x;
353         e.p2.y = cubes[i].y + edgeOrg[j].p2.y;
354         e.p2.z = cubes[i].z + edgeOrg[j].p2.z;
355 
356         e.orientation = edgeOrg[j].orientation;
357 
358         if(!EdgeExist(e)) edges[nbEdge++] = e;
359 
360       }
361     }
362   }
363 
364   if(!hasBigEdge) {
365     hr = CreateLineEdge();
366     if(!hr) return GL_FAIL;
367   } else {
368     hr = CreateCylinderEdges(wEdge*cubeSide);
369     if(!hr) return GL_FAIL;
370   }
371 
372 
373   // Init material
374   memset (&whiteMaterial, 0, sizeof (GLMATERIAL));
375   whiteMaterial.Diffuse.r = 1.0f;
376   whiteMaterial.Diffuse.g = 1.0f;
377   whiteMaterial.Diffuse.b = 1.0f;
378   whiteMaterial.Ambient.r = 1.0f;
379   whiteMaterial.Ambient.g = 1.0f;
380   whiteMaterial.Ambient.b = 1.0f;
381 
382   memset (&redMaterial, 0, sizeof (GLMATERIAL));
383   redMaterial.Diffuse.r = 1.0f;
384   redMaterial.Diffuse.g = 0.0f;
385   redMaterial.Diffuse.b = 0.0f;
386   redMaterial.Ambient.r = 1.0f;
387   redMaterial.Ambient.g = 0.0f;
388   redMaterial.Ambient.b = 0.0f;
389 
390   memset (&ghostMaterial, 0, sizeof (GLMATERIAL));
391 
392   memset (&grayMaterial, 0, sizeof (GLMATERIAL));
393   grayMaterial.Diffuse.r = 0.8f;
394   grayMaterial.Diffuse.g = 0.8f;
395   grayMaterial.Diffuse.b = 0.8f;
396   grayMaterial.Ambient.r = 0.5f;
397   grayMaterial.Ambient.g = 0.5f;
398   grayMaterial.Ambient.b = 0.5f;
399   grayMaterial.Specular.r = 1.0f;
400   grayMaterial.Specular.g = 1.0f;
401   grayMaterial.Specular.b = 1.0f;
402   grayMaterial.Power = 20.0f;
403 
404   InitRotationCenter();
405 
406   // Ghost
407   hasGhost = (ghost!=0);
408   if( hasGhost ) {
409     if( !CreateGhost(ghost) ) return GL_FAIL;
410   }
411 
412   return GL_OK;
413 }
414 
415 //-----------------------------------------------------------------------------
416 
CreateLineEdge()417 int PolyCube::CreateLineEdge() {
418 
419   lineList = glGenLists(1);
420   glNewList(lineList,GL_COMPILE);
421   glBegin(GL_LINES);
422 
423   for(int i=0;i<nbEdge;i++) {
424 
425     glVertex3f( (float)(edges[i].p1.x) * cubeSide + origin.x,
426                 (float)(edges[i].p1.y) * cubeSide + origin.y,
427                 (float)(edges[i].p1.z) * cubeSide + origin.z);
428 
429     glVertex3f( (float)(edges[i].p2.x) * cubeSide + origin.x,
430                 (float)(edges[i].p2.y) * cubeSide + origin.y,
431                 (float)(edges[i].p2.z) * cubeSide + origin.z);
432 
433   }
434 
435   glEnd();
436   glEndList();
437 
438   return GL_OK;
439 }
440 
441 //-----------------------------------------------------------------------------
442 
CreateCylinderEdges(float wEdge)443 int PolyCube::CreateCylinderEdges(float wEdge) {
444 
445   CORNER       corner[40];
446   int          nbCorner=0;
447   int          nbDiv = 6;
448   VERTEX       oV;
449 
450   // Compute corner, node where 3 edges intersect
451   for(int i=0;i<=GetWidth();i++) {
452     for(int j=0;j<=GetHeight();j++) {
453       for(int k=0;k<=GetDepth();k++) {
454         if( GetCornerAt(i,j,k,&oV) ) {
455           corner[nbCorner].p.x = (float)i * cubeSide + origin.x;
456           corner[nbCorner].p.y = (float)j * cubeSide + origin.y;
457           corner[nbCorner].p.z = (float)k * cubeSide + origin.z;
458           corner[nbCorner].o = oV;
459           nbCorner++;
460         }
461       }
462     }
463   }
464 
465   bigEdgeList = glGenLists(1);
466   glNewList(bigEdgeList,GL_COMPILE);
467 
468   // Edge cylinder
469   glBegin(GL_QUADS);
470 
471   for(int i=0;i<nbEdge;i++) {
472 
473     float x1c = (float)(edges[i].p1.x) * cubeSide + origin.x;
474     float y1c = (float)(edges[i].p1.y) * cubeSide + origin.y;
475     float z1c = (float)(edges[i].p1.z) * cubeSide + origin.z;
476 
477     float x2c = (float)(edges[i].p2.x) * cubeSide + origin.x;
478     float y2c = (float)(edges[i].p2.y) * cubeSide + origin.y;
479     float z2c = (float)(edges[i].p2.z) * cubeSide + origin.z;
480 
481     for(int j=0;j<nbDiv;j++) {
482 
483       float x,y,z,nx,ny,nz;
484       float x2,y2,z2,nx2,ny2,nz2;
485       float angle = (float)j/(float)nbDiv * 2.0f * PI;
486       float angle2 = (float)(j+1)/(float)nbDiv * 2.0f * PI;
487 
488       // Create vertex
489       switch(edges[i].orientation) {
490 
491       case DIR_OX:
492         nx = 0.0;
493         ny = cosf(angle);
494         nz = sinf(angle);
495         nx2 = 0.0;
496         ny2 = cosf(angle2);
497         nz2 = sinf(angle2);
498         break;
499 
500       case DIR_OY:
501         nx = cosf(angle);
502         ny = 0.0;
503         nz = sinf(angle);
504         nx2 = cosf(angle2);
505         ny2 = 0.0;
506         nz2 = sinf(angle2);
507         break;
508 
509       case DIR_OZ:
510         nx = cosf(angle);
511         ny = sinf(angle);
512         nz = 0.0;
513         nx2 = cosf(angle2);
514         ny2 = sinf(angle2);
515         nz2 = 0.0;
516         break;
517 
518       }
519 
520       x = wEdge * nx;
521       y = wEdge * ny;
522       z = wEdge * nz;
523       x2 = wEdge * nx2;
524       y2 = wEdge * ny2;
525       z2 = wEdge * nz2;
526 
527       glNormal3f(nx,ny,nz);
528       glVertex3f(x1c + x,y1c + y,z1c + z);
529 
530       glNormal3f(nx,ny,nz);
531       glVertex3f(x2c + x,y2c + y,z2c + z);
532 
533       glNormal3f(nx2,ny2,nz2);
534       glVertex3f(x2c + x2,y2c + y2,z2c + z2);
535 
536       glNormal3f(nx2,ny2,nz2);
537       glVertex3f(x1c + x2,y1c + y2,z1c + z2);
538 
539    }
540 
541   }
542 
543   glEnd();
544 
545   // Corner
546 
547   glBegin(GL_TRIANGLES);
548 
549   for(int i=0;i<nbCorner;i++) {
550 
551     glNormal3f(0.0f,0.0f,corner[i].o.z);
552     glVertex3f(corner[i].p.x,corner[i].p.y,corner[i].p.z+wEdge*corner[i].o.z);
553 
554     glNormal3f(corner[i].o.x,0.0f,0.0f);
555     glVertex3f(corner[i].p.x+wEdge*corner[i].o.x,corner[i].p.y,corner[i].p.z);
556 
557     glNormal3f(0.0f,corner[i].o.y,0.0f);
558     glVertex3f(corner[i].p.x,corner[i].p.y+wEdge*corner[i].o.y,corner[i].p.z);
559 
560     //--
561 
562     glNormal3f(0.0f,0.0f,corner[i].o.z);
563     glVertex3f(corner[i].p.x,corner[i].p.y,corner[i].p.z+wEdge*corner[i].o.z);
564 
565     glNormal3f(0.0f,corner[i].o.y,0.0f);
566     glVertex3f(corner[i].p.x,corner[i].p.y+wEdge*corner[i].o.y,corner[i].p.z);
567 
568     glNormal3f(corner[i].o.x,0.0f,0.0f);
569     glVertex3f(corner[i].p.x+wEdge*corner[i].o.x,corner[i].p.y,corner[i].p.z);
570 
571   }
572 
573   glEnd();
574   glEndList();
575 
576   return GL_OK;
577 
578 }
579 
580 
581 //-----------------------------------------------------------------------------
582 
gV(int cubeIdx,int x,int y,int z,float nx,float ny,float nz)583 void PolyCube::gV(int cubeIdx,int x,int y,int z,float nx,float ny,float nz) {
584 
585   glNormal3f(nx,ny,nz);
586   glVertex3f((cubes[cubeIdx].x+x) * cubeSide + origin.x,
587              (cubes[cubeIdx].y+y) * cubeSide + origin.y,
588              (cubes[cubeIdx].z+z) * cubeSide + origin.z);
589 
590 }
591 
592 //-----------------------------------------------------------------------------
593 
CreateGhost(int value)594 int PolyCube::CreateGhost(int value) {
595 
596   // Create face
597 
598   ghostList = glGenLists(1);
599   glNewList(ghostList,GL_COMPILE);
600   glBegin(GL_QUADS);
601 
602   for(int i=0;i<nbCube;i++) {
603 
604     // Face 0
605     if( IsFaceVisible(i,0) ) {
606       gV(i,0,0,0, 0.0f,0.0f,-1.0f);
607       gV(i,0,1,0, 0.0f,0.0f,-1.0f);
608       gV(i,1,1,0, 0.0f,0.0f,-1.0f);
609       gV(i,1,0,0, 0.0f,0.0f,-1.0f);
610     }
611 
612     // Face 1
613     if( IsFaceVisible(i,1) ) {
614       gV(i,0,0,1, -1.0f,0.0f,0.0f);
615       gV(i,0,1,1, -1.0f,0.0f,0.0f);
616       gV(i,0,1,0, -1.0f,0.0f,0.0f);
617       gV(i,0,0,0, -1.0f,0.0f,0.0f);
618     }
619 
620     // Face 2
621     if( IsFaceVisible(i,2) ) {
622       gV(i,1,0,1, 0.0f,0.0f,1.0f);
623       gV(i,1,1,1, 0.0f,0.0f,1.0f);
624       gV(i,0,1,1, 0.0f,0.0f,1.0f);
625       gV(i,0,0,1, 0.0f,0.0f,1.0f);
626     }
627 
628     // Face 3
629     if( IsFaceVisible(i,3) ) {
630       gV(i,1,0,0, 1.0f,0.0f,0.0f);
631       gV(i,1,1,0, 1.0f,0.0f,0.0f);
632       gV(i,1,1,1, 1.0f,0.0f,0.0f);
633       gV(i,1,0,1, 1.0f,0.0f,0.0f);
634     }
635 
636     // Face 4
637     if( IsFaceVisible(i,4) ) {
638       gV(i,0,1,0, 0.0f,1.0f,0.0f);
639       gV(i,0,1,1, 0.0f,1.0f,0.0f);
640       gV(i,1,1,1, 0.0f,1.0f,0.0f);
641       gV(i,1,1,0, 0.0f,1.0f,0.0f);
642     }
643 
644     // Face 5
645     if( IsFaceVisible(i,5) ) {
646       gV(i,1,0,0, 0.0f,-1.0f,0.0f);
647       gV(i,1,0,1, 0.0f,-1.0f,0.0f);
648       gV(i,0,0,1, 0.0f,-1.0f,0.0f);
649       gV(i,0,0,0, 0.0f,-1.0f,0.0f);
650     }
651 
652   }
653 
654   glEnd();
655   glEndList();
656 
657   // Ghost material
658   float trans = ((float)value / (float)FTRANS_MAX) * 0.4f;
659 
660   ghostMaterial.Diffuse.r = 0.5f;
661   ghostMaterial.Diffuse.g = 0.5f;
662   ghostMaterial.Diffuse.b = 0.5f;
663   ghostMaterial.Diffuse.a = trans;
664   ghostMaterial.Ambient.r = 0.5f;
665   ghostMaterial.Ambient.g = 0.5f;
666   ghostMaterial.Ambient.b = 0.5f;
667   ghostMaterial.Ambient.a = trans;
668 
669   return GL_OK;
670 
671 }
672 
673 //-----------------------------------------------------------------------------
674 
CopyCube(BLOCKITEM * c,int * nb)675 void PolyCube::CopyCube(BLOCKITEM *c,int *nb) {
676 
677   for(int i=0;i<nbCube;i++) {
678     c[i] = cubes[i];
679   }
680   *nb = nbCube;
681 
682 }
683 
684 //-----------------------------------------------------------------------------
685 
GetRCenter()686 VERTEX PolyCube::GetRCenter() {
687 
688   return center;
689 
690 }
691 
692 //-----------------------------------------------------------------------------
693 
GetICenter()694 BLOCKITEM PolyCube::GetICenter() {
695 
696   return iCenter;
697 
698 }
699 
700 //-----------------------------------------------------------------------------
701 
FindCube(int x,int y,int z)702 BOOL PolyCube::FindCube(int x,int y,int z) {
703 
704   BOOL found = FALSE;
705   int i = 0;
706   while(i<nbCube && !found) {
707     found = (cubes[i].x == x) && (cubes[i].y == y) && (cubes[i].z == z);
708     if(!found) i++;
709   }
710 
711   return found;
712 
713 }
714 
715 //-----------------------------------------------------------------------------
716 
IsFaceVisible(int cubeIdx,int face)717 BOOL PolyCube::IsFaceVisible(int cubeIdx,int face) {
718 
719   int x = cubes[cubeIdx].x;
720   int y = cubes[cubeIdx].y;
721   int z = cubes[cubeIdx].z;
722 
723   switch(face) {
724     case 0:
725       return !FindCube(x,y,z-1);
726       break;
727     case 1:
728       return !FindCube(x-1,y,z);
729       break;
730     case 2:
731       return !FindCube(x,y,z+1);
732       break;
733     case 3:
734       return !FindCube(x+1,y,z);
735       break;
736     case 4:
737       return !FindCube(x,y+1,z);
738       break;
739     case 5:
740       return !FindCube(x,y-1,z);
741       break;
742   }
743 
744   return FALSE;
745 
746 }
747 
748 //-----------------------------------------------------------------------------
749 
IsEdgeVisible(int cubeIdx,int edge)750 BOOL PolyCube::IsEdgeVisible(int cubeIdx,int edge) {
751 
752   int nb = 0;
753   BOOL e1,e2,e3;
754 
755   int x = cubes[cubeIdx].x;
756   int y = cubes[cubeIdx].y;
757   int z = cubes[cubeIdx].z;
758 
759   switch(edge) {
760 
761     case 0:
762       e1 = FindCube(x,y,z-1);e2 = FindCube(x,y+1,z-1);e3 = FindCube(x,y+1,z);
763       break;
764     case 1:
765       e1 = FindCube(x,y,z-1);e2 = FindCube(x+1,y,z-1);e3 = FindCube(x+1,y,z);
766       break;
767     case 2:
768       e1 = FindCube(x,y,z-1);e2 = FindCube(x,y-1,z-1);e3 = FindCube(x,y-1,z);
769       break;
770     case 3:
771       e1 = FindCube(x,y,z-1);e2 = FindCube(x-1,y,z-1);e3 = FindCube(x-1,y,z);
772       break;
773 
774     case 4:
775       e1 = FindCube(x,y+1,z);e2 = FindCube(x-1,y+1,z);e3 = FindCube(x-1,y,z);
776       break;
777     case 5:
778       e1 = FindCube(x,y+1,z);e2 = FindCube(x+1,y+1,z);e3 = FindCube(x+1,y,z);
779       break;
780     case 6:
781       e1 = FindCube(x+1,y,z);e2 = FindCube(x+1,y-1,z);e3 = FindCube(x,y-1,z);
782       break;
783     case 7:
784       e1 = FindCube(x,y-1,z);e2 = FindCube(x-1,y-1,z);e3 = FindCube(x-1,y,z);
785       break;
786 
787     case 8:
788       e1 = FindCube(x,y+1,z);e2 = FindCube(x,y+1,z+1);e3 = FindCube(x,y,z+1);
789       break;
790     case 9:
791       e1 = FindCube(x+1,y,z);e2 = FindCube(x+1,y,z+1);e3 = FindCube(x,y,z+1);
792       break;
793     case 10:
794       e1 = FindCube(x,y-1,z);e2 = FindCube(x,y-1,z+1);e3 = FindCube(x,y,z+1);
795       break;
796     case 11:
797       e1 = FindCube(x-1,y,z);e2 = FindCube(x-1,y,z+1);e3 = FindCube(x,y,z+1);
798       break;
799 
800   }
801 
802   return !( (!e1 && !e2 && e3) || (e1 && !e2 && !e3) || (e1 && e2 && e3) );
803 
804 }
805 
806 //-----------------------------------------------------------------------------
807 
Render(BOOL redMode)808 void PolyCube::Render(BOOL redMode) {
809 
810   glEnable(GL_LIGHTING);
811   glDisable(GL_DEPTH_TEST);
812   glDisable(GL_TEXTURE_2D);
813 
814   if( hasGhost ) {
815 
816     // Alpha texture
817     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
818     glEnable(GL_BLEND);
819     GLApplication::SetMaterial(&ghostMaterial);
820 
821     // Draw back face first
822     glEnable(GL_CULL_FACE);
823     glCullFace(GL_FRONT);
824     glCallList(ghostList);
825 
826     // Draw front face
827     glCullFace(GL_BACK);
828     glCallList(ghostList);
829 
830   }
831 
832   glDisable(GL_TEXTURE_2D);
833   glDisable(GL_LIGHTING);
834   glDisable(GL_BLEND);
835   glDisable(GL_CULL_FACE);
836 
837   // Draw the polycube
838   if( hasBigEdge ) {
839 
840     if(redMode)
841       GLApplication::SetMaterial (&redMaterial);
842     else
843       GLApplication::SetMaterial (&grayMaterial);
844 
845     glEnable(GL_DEPTH_TEST);
846     glEnable(GL_LIGHTING);
847     glCallList(bigEdgeList);
848     glDisable(GL_LIGHTING);
849     glDisable(GL_DEPTH_TEST);
850 
851   } else {
852 
853     if(redMode)
854       GLApplication::SetMaterial (&redMaterial);
855     else
856       GLApplication::SetMaterial (&whiteMaterial);
857 
858     glCallList(lineList);
859 
860   }
861 
862 }
863 
864 //-----------------------------------------------------------------------------
865 
InvalidateDeviceObjects()866 void PolyCube::InvalidateDeviceObjects() {
867 
868   DELETE_LIST(lineList);
869   DELETE_LIST(ghostList);
870   DELETE_LIST(bigEdgeList);
871   nbCube = 0;
872   nbOrientation = 0;
873 
874 }
875