5
* 3d board drawing code
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of version 2 of the GNU General Public License as
10
* published by the Free Software Foundation.
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.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
* $Id: drawboard3d.c,v 1.46 2006/09/21 22:24:45 Superfly_Jon Exp $
36
#include "drawboard.h"
39
/* Used to calculate correct viewarea for board/fov angles */
40
typedef struct _viewArea
47
/* My logcube - more than 32 then return 0 (show 64) */
48
static int LogCube( const int n )
57
/* Helper functions in misc3d */
58
void cylinder(float radius, float height, int accuracy, Texture* texture);
59
void circle(float radius, float height, int accuracy);
60
void circleRev(float radius, float height, int accuracy);
61
void circleTex(float radius, float height, int accuracy, Texture* texture);
62
void circleRevTex(float radius, float height, int accuracy, Texture* texture);
63
void circleOutlineOutward(float radius, float height, int accuracy);
64
void circleOutline(float radius, float height, int accuracy);
65
void drawBox(boxType type, float x, float y, float z, float w, float h, float d, Texture* texture);
66
void drawCube(float size);
67
void drawRect(float x, float y, float z, float w, float h, Texture* texture);
68
void drawSplitRect(float x, float y, float z, float w, float h, Texture* texture);
69
void drawChequeredRect(float x, float y, float z, float w, float h, int across, int down, Texture* texture);
70
void QuarterCylinder(float radius, float len, int accuracy, Texture* texture);
71
void QuarterCylinderSplayed(float radius, float len, int accuracy, Texture* texture);
72
void QuarterCylinderSplayedRev(float radius, float len, int accuracy, Texture* texture);
73
void drawCornerEigth(float ***boardPoints, float radius, int accuracy);
74
void calculateEigthPoints(float ****boardPoints, float radius, int accuracy);
77
void initPath(Path* p, float start[3]);
78
void addPathSegment(Path* p, PathType type, float point[3]);
79
void initDT(diceTest* dt, int x, int y, int z);
81
/* All the board element sizes - based on base_unit size */
85
/* Side edge width of bearoff trays */
86
#define EDGE_WIDTH base_unit
88
#define TRAY_WIDTH (EDGE_WIDTH * 2.0f + PIECE_HOLE)
89
#define BOARD_WIDTH (PIECE_HOLE * 6.0f)
90
#define BAR_WIDTH (PIECE_HOLE * 1.7f)
91
#define DICE_AREA_CLICK_WIDTH BOARD_WIDTH
93
#define TAKI_WIDTH .9f
95
#define TOTAL_WIDTH ((TRAY_WIDTH + BOARD_WIDTH) * 2.0f + BAR_WIDTH)
99
/* Bottom + top edge */
100
#define EDGE_HEIGHT (base_unit * 1.5f)
102
#define POINT_HEIGHT (PIECE_HOLE * 6)
103
#define TRAY_HEIGHT (EDGE_HEIGHT + POINT_HEIGHT)
104
#define MID_SIDE_GAP_HEIGHT (base_unit * 3.5f)
105
#define DICE_AREA_HEIGHT MID_SIDE_GAP_HEIGHT
106
/* Vertical gap between pieces */
107
#define PIECE_GAP_HEIGHT (base_unit / 5.0f)
109
#define TOTAL_HEIGHT (TRAY_HEIGHT * 2.0f + MID_SIDE_GAP_HEIGHT)
113
#define EDGE_DEPTH (base_unit * 1.95f)
114
#define BASE_DEPTH base_unit
118
#define BOARD_FILLET (base_unit / 3.0f)
120
#define DOUBLECUBE_SIZE (base_unit * 3.4f)
122
/* Dice animation step size */
123
#define DICE_STEP_SIZE0 (base_unit * 1.3f)
124
#define DICE_STEP_SIZE1 (base_unit * 1.7f)
126
#define HINGE_GAP (base_unit / 12.0f)
127
#define HINGE_WIDTH (base_unit / 2.0f)
128
#define HINGE_HEIGHT (base_unit * 7.0f)
131
#define ARROW_SIZE (EDGE_HEIGHT * .8f)
133
#define FLAG_HEIGHT (base_unit * 3)
134
#define FLAG_WIDTH (FLAG_HEIGHT * 1.4f)
135
#define FLAG_WAG (FLAG_HEIGHT * .3f)
136
#define FLAGPOLE_WIDTH (base_unit * .2f)
137
#define FLAGPOLE_HEIGHT (FLAG_HEIGHT * 2.05f)
139
/* Slight offset from surface - avoid using unless necessary */
140
#define LIFT_OFF (base_unit / 50.0f)
142
float getBoardWidth() {return TOTAL_WIDTH;}
143
float getBoardHeight() {return TOTAL_HEIGHT;}
144
float getDiceSize(renderdata* prd) {return prd->diceSize * base_unit;}
146
extern list textures;
148
void TidyShadows(BoardData3d* bd3d)
150
freeOccluder(&bd3d->Occluders[OCC_BOARD]);
151
freeOccluder(&bd3d->Occluders[OCC_CUBE]);
152
freeOccluder(&bd3d->Occluders[OCC_DICE1]);
153
freeOccluder(&bd3d->Occluders[OCC_FLAG]);
154
freeOccluder(&bd3d->Occluders[OCC_HINGE1]);
155
freeOccluder(&bd3d->Occluders[OCC_PIECE]);
158
void Tidy3dObjects(BoardData3d* bd3d, renderdata *prd)
160
glDeleteLists(bd3d->pieceList, 1);
161
glDeleteLists(bd3d->diceList, 1);
162
glDeleteLists(bd3d->DCList, 1);
164
gluDeleteQuadric(bd3d->qobjTex);
165
gluDeleteQuadric(bd3d->qobj);
167
gluDeleteNurbsRenderer(bd3d->flagNurb);
169
if (bd3d->boardPoints)
170
freeEigthPoints(&bd3d->boardPoints, prd->curveAccuracy);
174
ListDeleteAll(&textures);
177
void preDrawPiece0(renderdata* prd)
180
float angle, angle2, step;
185
float radius = PIECE_HOLE / 2.0f;
186
float discradius = radius * 0.8f;
187
float lip = radius - discradius;
188
float height = PIECE_DEPTH - 2 * lip;
189
float ***p = Alloc3d(prd->curveAccuracy + 1, prd->curveAccuracy / 4 + 1, 3);
190
float ***n = Alloc3d(prd->curveAccuracy + 1, prd->curveAccuracy / 4 + 1, 3);
192
step = (2 * (float)PI) / prd->curveAccuracy;
194
/* Draw top/bottom of piece */
195
circleTex(discradius, PIECE_DEPTH, prd->curveAccuracy, prd->ChequerMat[0].pTexture);
197
if (prd->ChequerMat[0].pTexture && prd->pieceTextureType == PTT_TOP)
198
glDisable(GL_TEXTURE_2D);
200
circleRevTex(discradius, 0, prd->curveAccuracy, prd->ChequerMat[0].pTexture);
202
/* Draw side of piece */
204
glTranslatef(0, 0, lip);
205
cylinder(radius, height, prd->curveAccuracy, prd->ChequerMat[0].pTexture);
208
/* Draw edges of piece */
210
for (j = 0; j <= prd->curveAccuracy / 4; j++)
212
latitude = (float)sin(angle2) * lip;
213
new_radius = Dist2d(lip, latitude);
216
for (i = 0; i < prd->curveAccuracy; i++)
218
n[i][j][0] = (float)sin(angle) * new_radius;
219
p[i][j][0] = (float)sin(angle) * (discradius + new_radius);
220
n[i][j][1] = (float)cos(angle) * new_radius;
221
p[i][j][1] = (float)cos(angle) * (discradius + new_radius);
222
p[i][j][2] = latitude + lip + height;
223
n[i][j][2] = latitude;
227
p[i][j][0] = p[0][j][0];
228
p[i][j][1] = p[0][j][1];
229
p[i][j][2] = p[0][j][2];
230
n[i][j][0] = n[0][j][0];
231
n[i][j][1] = n[0][j][1];
232
n[i][j][2] = n[0][j][2];
237
for (j = 0; j < prd->curveAccuracy / 4; j++)
239
glBegin(GL_QUAD_STRIP);
240
for (i = 0; i < prd->curveAccuracy + 1; i++)
242
glNormal3f((n[i][j][0]) / lip, (n[i][j][1]) / lip, n[i][j][2] / lip);
243
if (prd->ChequerMat[0].pTexture)
244
glTexCoord2f((p[i][j][0] + discradius) / (discradius * 2), (p[i][j][1] + discradius) / (discradius * 2));
245
glVertex3f(p[i][j][0], p[i][j][1], p[i][j][2]);
247
glNormal3f((n[i][j + 1][0]) / lip, (n[i][j + 1][1]) / lip, n[i][j + 1][2] / lip);
248
if (prd->ChequerMat[0].pTexture)
249
glTexCoord2f((p[i][j + 1][0] + discradius) / (discradius * 2), (p[i][j + 1][1] + discradius) / (discradius * 2));
250
glVertex3f(p[i][j + 1][0], p[i][j + 1][1], p[i][j + 1][2]);
254
glBegin(GL_QUAD_STRIP);
255
for (i = 0; i < prd->curveAccuracy + 1; i++)
257
glNormal3f((n[i][j + 1][0]) / lip, (n[i][j + 1][1]) / lip, n[i][j + 1][2] / lip);
258
if (prd->ChequerMat[0].pTexture)
259
glTexCoord2f((p[i][j + 1][0] + discradius) / (discradius * 2), (p[i][j + 1][1] + discradius) / (discradius * 2));
260
glVertex3f(p[i][j + 1][0], p[i][j + 1][1], PIECE_DEPTH - p[i][j + 1][2]);
262
glNormal3f((n[i][j][0]) / lip, (n[i][j][1]) / lip, n[i][j][2] / lip);
263
if (prd->ChequerMat[0].pTexture)
264
glTexCoord2f((p[i][j][0] + discradius) / (discradius * 2), (p[i][j][1] + discradius) / (discradius * 2));
265
glVertex3f(p[i][j][0], p[i][j][1], PIECE_DEPTH - p[i][j][2]);
270
/* Anti-alias piece edges */
272
glEnable(GL_LINE_SMOOTH);
274
glDepthMask(GL_FALSE);
276
circleOutlineOutward(radius, PIECE_DEPTH - lip, prd->curveAccuracy);
277
circleOutlineOutward(radius, lip, prd->curveAccuracy);
280
glDisable(GL_LINE_SMOOTH);
281
glDepthMask(GL_TRUE);
283
if (prd->ChequerMat[0].pTexture && prd->pieceTextureType == PTT_TOP)
284
glEnable(GL_TEXTURE_2D); /* Re-enable texturing */
286
Free3d(p, prd->curveAccuracy + 1, prd->curveAccuracy / 4 + 1);
287
Free3d(n, prd->curveAccuracy + 1, prd->curveAccuracy / 4 + 1);
290
void preDrawPiece1(renderdata* prd)
292
float pieceRad, pieceBorder;
294
pieceRad = PIECE_HOLE / 2.0f;
295
pieceBorder = pieceRad * .9f;
297
/* Draw top/bottom of piece */
298
circleTex(pieceRad, PIECE_DEPTH, prd->curveAccuracy, prd->ChequerMat[0].pTexture);
300
if (prd->ChequerMat[0].pTexture && prd->pieceTextureType == PTT_TOP)
301
glDisable(GL_TEXTURE_2D);
303
circleRevTex(pieceRad, 0, prd->curveAccuracy, prd->ChequerMat[0].pTexture);
306
cylinder(pieceRad, PIECE_DEPTH, prd->curveAccuracy, prd->ChequerMat[0].pTexture);
308
/* Anti-alias piece edges */
310
glEnable(GL_LINE_SMOOTH);
312
glDepthMask(GL_FALSE);
314
circleOutlineOutward(pieceRad, PIECE_DEPTH, prd->curveAccuracy);
315
circleOutlineOutward(pieceRad, 0, prd->curveAccuracy);
318
glDisable(GL_LINE_SMOOTH);
319
glDepthMask(GL_TRUE);
321
if (prd->ChequerMat[0].pTexture && prd->pieceTextureType == PTT_TOP)
322
glEnable(GL_TEXTURE_2D); /* Re-enable texturing */
325
void preDrawPiece(BoardData* bd)
327
if (bd->bd3d.pieceList)
328
glDeleteLists(bd->bd3d.pieceList, 1);
330
bd->bd3d.pieceList = glGenLists(1);
331
glNewList(bd->bd3d.pieceList, GL_COMPILE);
333
switch(bd->rd->pieceType)
336
preDrawPiece0(bd->rd);
339
preDrawPiece1(bd->rd);
342
g_print("Error: Unhandled piece type\n");
348
void UnitNormal(float x, float y, float z)
350
/* Calculate the length of the vector */
351
float length = (float)sqrt((x * x) + (y * y) + (z * z));
353
/* Dividing each element by the length will result in a unit normal vector */
354
glNormal3f(x / length, y / length, z / length);
357
void renderDice(renderdata* prd)
368
float size = getDiceSize(prd);
370
int corner_steps = (prd->curveAccuracy / 4) + 1;
371
float ***corner_points = Alloc3d(corner_steps, corner_steps, 3);
373
radius = size / 2.0f;
374
step = (2 * (float)PI) / prd->curveAccuracy;
379
for (c = 0; c < 6; c++)
381
circle(radius, radius, prd->curveAccuracy);
384
glRotatef(-90, 0, 1, 0);
386
glRotatef(90, 1, 0, 0);
390
lns = (prd->curveAccuracy / 4);
391
lat_step = ((float)PI / 2) / lns;
393
/* Calculate corner points */
394
for (i = 0; i < lns + 1; i++)
396
latitude = (float)sin(lat_angle) * radius;
397
new_radius = Dist2d(radius, latitude);
399
ns = (prd->curveAccuracy / 4) - i;
401
step = ((float)PI / 2 - lat_angle) / (ns);
404
for (j = 0; j <= ns; j++)
406
corner_points[i][j][0] = (float)cos(lat_angle) * radius;
407
corner_points[i][j][1] = (float)cos(angle) * radius;
408
corner_points[i][j][2] = (float)sin(angle + lat_angle) * radius;
412
lat_angle += lat_step;
416
for (c = 0; c < 8; c++)
420
glRotatef((float)(c * 90), 0, 0, 1);
422
for (i = 0; i < prd->curveAccuracy / 4; i++)
424
ns = (prd->curveAccuracy / 4) - i - 1;
426
glBegin(GL_TRIANGLE_STRIP);
427
UnitNormal(corner_points[i][0][0], corner_points[i][0][1], corner_points[i][0][2]);
428
glVertex3f(corner_points[i][0][0], corner_points[i][0][1], corner_points[i][0][2]);
429
for (j = 0; j <= ns; j++)
431
UnitNormal(corner_points[i + 1][j][0], corner_points[i + 1][j][1], corner_points[i + 1][j][2]);
432
glVertex3f(corner_points[i + 1][j][0], corner_points[i + 1][j][1], corner_points[i + 1][j][2]);
433
UnitNormal(corner_points[i][j + 1][0], corner_points[i][j + 1][1], corner_points[i][j + 1][2]);
434
glVertex3f(corner_points[i][j + 1][0], corner_points[i][j + 1][1], corner_points[i][j + 1][2]);
441
glRotatef(180, 1, 0, 0);
444
/* Anti-alias dice edges */
446
glEnable(GL_LINE_SMOOTH);
448
glDepthMask(GL_FALSE);
450
for (c = 0; c < 6; c++)
452
circleOutline(radius, radius + LIFT_OFF, prd->curveAccuracy);
455
glRotatef(-90, 0, 1, 0);
457
glRotatef(90, 1, 0, 0);
460
glDisable(GL_LINE_SMOOTH);
461
glDepthMask(GL_TRUE);
465
Free3d(corner_points, corner_steps, corner_steps);
468
void renderCube(renderdata* prd, float size)
471
float ***corner_points;
472
float radius = size / 7.0f;
473
float ds = (size * 5.0f / 7.0f);
474
float hds = (ds / 2);
479
for (c = 0; c < 6; c++)
482
glTranslatef(0, 0, hds + radius);
487
glVertex3f(-hds, -hds, 0);
488
glVertex3f(hds, -hds, 0);
489
glVertex3f(hds, hds, 0);
490
glVertex3f(-hds, hds, 0);
494
for (i = 0; i < 2; i++)
497
glRotatef((float)(i * 90), 0, 0, 1);
499
glTranslatef(hds, -hds, -radius);
500
QuarterCylinder(radius, ds, prd->curveAccuracy, 0);
505
glRotatef(-90, 0, 1, 0);
507
glRotatef(90, 1, 0, 0);
510
calculateEigthPoints(&corner_points, radius, prd->curveAccuracy);
513
for (c = 0; c < 8; c++)
516
glTranslatef(0, 0, hds + radius);
518
glRotatef((float)(c * 90), 0, 0, 1);
520
glTranslatef(hds, -hds, -radius);
521
glRotatef(-90, 0, 0, 1);
523
drawCornerEigth(corner_points, radius, prd->curveAccuracy);
527
glRotatef(180, 1, 0, 0);
531
freeEigthPoints(&corner_points, prd->curveAccuracy);
534
void preDrawDice(BoardData3d* bd3d, renderdata* prd)
537
glDeleteLists(bd3d->diceList, 1);
539
bd3d->diceList = glGenLists(1);
540
glNewList(bd3d->diceList, GL_COMPILE);
545
glDeleteLists(bd3d->DCList, 1);
547
bd3d->DCList = glGenLists(1);
548
glNewList(bd3d->DCList, GL_COMPILE);
549
renderCube(prd, DOUBLECUBE_SIZE);
553
void getDoubleCubePos(BoardData* bd, float v[3])
555
if (bd->doubled != 0)
557
v[0] = TRAY_WIDTH + BOARD_WIDTH / 2;
558
if (bd->doubled != 1)
559
v[0] = TOTAL_WIDTH - v[0];
561
v[1] = TOTAL_HEIGHT / 2.0f;
562
v[2] = BASE_DEPTH + DOUBLECUBE_SIZE / 2.0f;
566
v[0] = TOTAL_WIDTH / 2.0f;
567
switch(bd->cube_owner)
570
v[1] = TOTAL_HEIGHT / 2.0f;
573
v[1] = EDGE_HEIGHT + DOUBLECUBE_SIZE / 2.0f;
576
v[1] = TOTAL_HEIGHT - EDGE_HEIGHT - DOUBLECUBE_SIZE / 2.0f;
579
v[1] = 0; /* error */
581
v[2] = BASE_DEPTH + EDGE_DEPTH + DOUBLECUBE_SIZE / 2.0f;
585
void moveToDoubleCubePos(BoardData* bd)
588
getDoubleCubePos(bd, v);
589
glTranslatef(v[0], v[1], v[2]);
592
void drawDCNumbers(BoardData* bd, diceTest* dt)
595
float radius = DOUBLECUBE_SIZE / 7.0f;
596
float ds = (DOUBLECUBE_SIZE * 5.0f / 7.0f);
597
float hds = (ds / 2);
598
float depth = hds + radius;
600
char* sides[] = {"4", "16", "32", "64", "8", "2"};
605
for (c = 0; c < 6; c++)
611
/* Nicer top numbers */
612
nice = (side == dt->top);
614
/* Don't draw bottom number or back number */
615
if (side == dt->top || side == dt->side[2] ||
616
(bd->doubled && (side == dt->side[1] || side == dt->side[3]))
617
|| (bd->cube_owner == -1 && side == dt->side[0]))
620
glDisable(GL_DEPTH_TEST);
623
glTranslatef(0, 0, depth + !nice * LIFT_OFF);
625
glPrintCube(&bd->bd3d, sides[side]);
629
glEnable(GL_DEPTH_TEST);
632
glRotatef(-90, 0, 1, 0);
634
glRotatef(90, 1, 0, 0);
639
void DrawDCNumbers(BoardData* bd)
643
int rotDC[6][3] = {{1, 0, 0}, {2, 0, 3}, {0, 0, 0}, {0, 3, 1}, {0, 1, 0}, {3, 0, 3}};
646
/* Rotate to correct number + rotation */
649
cubeIndex = LogCube(bd->cube);
650
extraRot = bd->cube_owner + 1;
654
cubeIndex = LogCube(bd->cube * 2); /* Show offered cube value */
655
extraRot = bd->turn + 1;
658
glRotatef((rotDC[cubeIndex][2] + extraRot) * 90.0f, 0, 0, 1);
659
glRotatef(rotDC[cubeIndex][0] * 90.0f, 1, 0, 0);
660
glRotatef(rotDC[cubeIndex][1] * 90.0f, 0, 1, 0);
662
initDT(&dt, rotDC[cubeIndex][0], rotDC[cubeIndex][1], rotDC[cubeIndex][2] + extraRot);
664
setMaterial(&bd->rd->CubeNumberMat);
667
drawDCNumbers(bd, &dt);
670
void drawDC(BoardData* bd, BoardData3d* bd3d, renderdata* prd)
673
moveToDoubleCubePos(bd);
675
setMaterial(&prd->CubeMat);
676
glCallList(bd3d->DCList);
683
/* Define position of dots on dice */
684
int dots1[] = {2, 2, 0};
685
int dots2[] = {1, 1, 3, 3, 0};
686
int dots3[] = {1, 3, 2, 2, 3, 1, 0};
687
int dots4[] = {1, 1, 1, 3, 3, 1, 3, 3, 0};
688
int dots5[] = {1, 1, 1, 3, 2, 2, 3, 1, 3, 3, 0};
689
int dots6[] = {1, 1, 1, 3, 2, 1, 2, 3, 3, 1, 3, 3, 0};
690
int *dots[6] = {dots1, dots2, dots3, dots4, dots5, dots6};
691
int dot_pos[] = {0, 20, 50, 80}; /* percentages across face */
693
void drawDots(BoardData3d *bd3d, float diceSize, float dotOffset, diceTest* dt, int showFront, int drawOutline)
699
float ds = (diceSize * 5.0f / 7.0f);
700
float hds = (ds / 2);
702
float dotSize = diceSize / 10.0f;
703
/* Remove specular effects */
704
float zero[4] = {0, 0, 0, 0};
705
glMaterialfv(GL_FRONT, GL_SPECULAR, zero);
707
radius = diceSize / 7.0f;
710
for (c = 0; c < 6; c++)
717
/* Make sure top dot looks nice */
718
nd = !bd3d->shakingDice && (dot == dt->top);
720
if (bd3d->shakingDice
721
|| (showFront && dot != dt->bottom && dot != dt->side[0])
722
|| (!showFront && dot != dt->top && dot != dt->side[2]))
725
glDisable(GL_DEPTH_TEST);
727
glTranslatef(0, 0, hds + radius);
731
/* Show all the dots for this number */
735
x = (dot_pos[dp[0]] * ds) / 100;
736
y = (dot_pos[dp[1]] * ds) / 100;
739
glTranslatef(x - hds, y - hds, 0);
741
glEnable(GL_TEXTURE_2D);
742
glBindTexture(GL_TEXTURE_2D, bd3d->dotTexture);
745
glTexCoord2f(0, 1); glVertex3f(dotSize, dotSize, dotOffset);
746
glTexCoord2f(1, 1); glVertex3f(-dotSize, dotSize, dotOffset);
747
glTexCoord2f(1, 0); glVertex3f(-dotSize, -dotSize, dotOffset);
748
glTexCoord2f(0, 0); glVertex3f(dotSize, -dotSize, dotOffset);
758
glEnable(GL_DEPTH_TEST);
762
glRotatef(-90, 0, 1, 0);
764
glRotatef(90, 1, 0, 0);
769
void getDicePos(BoardData* bd, int num, float v[3])
771
float size = getDiceSize(bd->rd);
772
if (bd->diceShown == DICE_BELOW_BOARD)
773
{ /* Show below board */
779
v[0] += TOTAL_WIDTH - size * 4;
781
v[0] += size; /* Place 2nd dice by 1st */
785
v[0] = bd->bd3d.dicePos[num][0];
787
v[0] = TOTAL_WIDTH - v[0]; /* Dice on right side */
789
v[1] = (TOTAL_HEIGHT - DICE_AREA_HEIGHT) / 2.0f + bd->bd3d.dicePos[num][1];
790
v[2] = BASE_DEPTH + LIFT_OFF + size / 2.0f;
794
void moveToDicePos(BoardData* bd, int num)
797
getDicePos(bd, num, v);
798
glTranslatef(v[0], v[1], v[2]);
800
if (bd->diceShown == DICE_ON_BOARD)
801
{ /* Spin dice to required rotation if on board */
802
glRotatef(bd->bd3d.dicePos[num][2], 0, 0, 1);
806
void drawDice(BoardData* bd, int num)
809
int rotDice[6][2] = {{0, 0}, {0, 1}, {3, 0}, {1, 0}, {0, 3}, {2, 0}};
810
int diceCol = (bd->turn == 1);
812
float diceSize = getDiceSize(bd->rd);
814
Material* pDiceMat = &bd->rd->DiceMat[diceCol];
816
SetupSimpleMat(&whiteMat, 1, 1, 1);
818
value = bd->diceRoll[num];
819
value--; /* Zero based for array access */
821
/* Get dice rotation */
822
if (bd->diceShown == DICE_BELOW_BOARD)
825
z = ((int)bd->bd3d.dicePos[num][2] + 45) / 90;
827
/* Orientate dice correctly */
828
glRotatef(90.0f * rotDice[value][0], 1, 0, 0);
829
glRotatef(90.0f * rotDice[value][1], 0, 1, 0);
831
/* DT = dice test, use to work out which way up the dice is */
832
initDT(&dt, rotDice[value][0], rotDice[value][1], z);
834
if (pDiceMat->alphaBlend)
835
{ /* Draw back of dice separately */
836
glCullFace(GL_FRONT);
840
setMaterial(pDiceMat);
841
glCallList(bd->bd3d.diceList);
843
/* Place back dots inside dice */
844
setMaterial(&bd->rd->DiceDotMat[diceCol]);
845
glEnable(GL_BLEND); /* NB. Disabled in diceList */
846
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);
847
drawDots(&bd->bd3d, diceSize, -LIFT_OFF, &dt, 0, 0);
848
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
853
setMaterial(&bd->rd->DiceMat[diceCol]);
854
glCallList(bd->bd3d.diceList);
856
/* Draw (front) dots */
858
/* First blank out space for dots */
859
setMaterial(&whiteMat);
860
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
861
drawDots(&bd->bd3d, diceSize, LIFT_OFF, &dt, 1, 0);
863
/* Now fill space with coloured dots */
864
setMaterial(&bd->rd->DiceDotMat[diceCol]);
865
glBlendFunc(GL_ONE, GL_ONE);
866
drawDots(&bd->bd3d, diceSize, LIFT_OFF, &dt, 1, 0);
868
/* Restore blending defaults */
870
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
873
void getPiecePos(int point, int pos, int swap, float v[3])
875
if (point == 0 || point == 25)
877
v[0] = TOTAL_WIDTH / 2.0f;
878
v[1] = TOTAL_HEIGHT / 2.0f;
879
v[2] = BASE_DEPTH + EDGE_DEPTH + ((pos - 1) / 3) * PIECE_DEPTH;
880
pos = ((pos - 1) % 3) + 1;
884
v[1] -= DOUBLECUBE_SIZE / 2.0f + (PIECE_HOLE + PIECE_GAP_HEIGHT) * (pos + .5f);
888
v[1] += DOUBLECUBE_SIZE / 2.0f + (PIECE_HOLE + PIECE_GAP_HEIGHT) * (pos + .5f);
890
v[1] -= PIECE_HOLE / 2.0f;
892
else if (point >= 26)
896
v[0] = TRAY_WIDTH / 2.0f;
898
v[0] = TOTAL_WIDTH - TRAY_WIDTH / 2.0f;
901
v[1] = EDGE_HEIGHT + (PIECE_DEPTH * 1.2f * (pos - 1)); /* 1.3 gives a gap between pieces */
903
v[1] = TOTAL_HEIGHT - EDGE_HEIGHT - PIECE_DEPTH - (PIECE_DEPTH * 1.2f * (pos - 1));
907
v[2] = BASE_DEPTH + ((pos - 1) / 5) * PIECE_DEPTH;
918
v[1] = EDGE_HEIGHT + (PIECE_HOLE / 2.0f) + (PIECE_HOLE + PIECE_GAP_HEIGHT) * (pos - 5 - 1);
920
v[1] = EDGE_HEIGHT + (PIECE_HOLE + PIECE_GAP_HEIGHT) * (pos - 1);
922
v[0] = TRAY_WIDTH + PIECE_HOLE * (12 - point);
929
point = (24 + 13) - point;
935
v[1] = TOTAL_HEIGHT - EDGE_HEIGHT - (PIECE_HOLE / 2.0f) - PIECE_HOLE - (PIECE_HOLE + PIECE_GAP_HEIGHT) * (pos - 5 - 1);
937
v[1] = TOTAL_HEIGHT - EDGE_HEIGHT - PIECE_HOLE - (PIECE_HOLE + PIECE_GAP_HEIGHT) * (pos - 1);
939
v[0] = TRAY_WIDTH + PIECE_HOLE * (point - 13);
943
v[0] += PIECE_HOLE / 2.0f;
945
v[2] += LIFT_OFF * 2;
947
/* Move to centre of piece */
950
v[1] += PIECE_HOLE / 2.0f;
953
{ /* Home pieces are sideways */
956
v[2] += PIECE_HOLE / 2.0f;
960
void renderSpecialPieces(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
962
if (bd->drag_point >= 0)
965
glTranslated(bd3d->dragPos[0], bd3d->dragPos[1], bd3d->dragPos[2]);
966
glRotatef((float)bd3d->movingPieceRotation, 0, 0, 1);
967
setMaterial(&prd->ChequerMat[bd->drag_colour == 1]);
968
glCallList(bd3d->pieceList);
975
glTranslatef(bd3d->movingPos[0], bd3d->movingPos[1], bd3d->movingPos[2]);
976
if (bd3d->rotateMovingPiece > 0)
977
glRotatef(-90 * bd3d->rotateMovingPiece * bd->turn, 1, 0, 0);
978
glRotatef((float)bd3d->movingPieceRotation, 0, 0, 1);
979
setMaterial(&prd->ChequerMat[bd->turn == 1]);
980
glCallList(bd3d->pieceList);
985
void drawSpecialPieces(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
986
{ /* Draw animated or dragged pieces */
987
int blend = (prd->ChequerMat[0].alphaBlend) || (prd->ChequerMat[1].alphaBlend);
990
{ /* Draw back of piece separately */
991
glCullFace(GL_FRONT);
993
renderSpecialPieces(bd, bd3d, prd);
997
renderSpecialPieces(bd, bd3d, prd);
1000
glDisable(GL_BLEND);
1003
void drawPiece(BoardData3d* bd3d, int point, int pos)
1008
getPiecePos(point, pos, fClockwise, v);
1009
glTranslatef(v[0], v[1], v[2]);
1011
/* Home pieces are sideways */
1013
glRotatef(-90, 1, 0, 0);
1015
glRotatef(90, 1, 0, 0);
1017
glRotatef((float)bd3d->pieceRotation[point][pos - 1], 0, 0, 1);
1018
glCallList(bd3d->pieceList);
1023
void drawPieces(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
1026
int blend = (prd->ChequerMat[0].alphaBlend) || (prd->ChequerMat[1].alphaBlend);
1029
{ /* Draw back of piece separately */
1030
glCullFace(GL_FRONT);
1032
setMaterial(&prd->ChequerMat[0]);
1033
for (i = 0; i < 28; i++)
1035
for (j = 1; j <= -bd->points[i]; j++)
1038
drawPiece(bd3d, i, j);
1041
setMaterial(&prd->ChequerMat[1]);
1042
for (i = 0; i < 28; i++)
1044
for (j = 1; j <= bd->points[i]; j++)
1047
drawPiece(bd3d, i, j);
1050
glCullFace(GL_BACK);
1053
setMaterial(&prd->ChequerMat[0]);
1054
for (i = 0; i < 28; i++)
1056
for (j = 1; j <= -bd->points[i]; j++)
1060
drawPiece(bd3d, i, j);
1063
setMaterial(&prd->ChequerMat[1]);
1064
for (i = 0; i < 28; i++)
1066
for (j = 1; j <= bd->points[i]; j++)
1070
drawPiece(bd3d, i, j);
1074
glDisable(GL_BLEND);
1076
if (bd->DragTargetHelp)
1077
{ /* highlight target points */
1078
glPolygonMode(GL_FRONT, GL_LINE);
1079
SetColour3d(0, 1, 0, 0); /* Nice bright green... */
1081
for (i = 0; i <= 3; i++)
1083
int target = bd->iTargetHelpPoints[i];
1085
{ /* Make sure texturing is disabled */
1086
if (prd->ChequerMat[0].pTexture)
1087
glDisable(GL_TEXTURE_2D);
1088
drawPiece(bd3d, target, abs(bd->points[target]) + 1);
1091
glPolygonMode(GL_FRONT, GL_FILL);
1095
void DrawNumbers(BoardData* bd, int sides)
1100
float textHeight = bd->bd3d.numberFont.height;
1104
glTranslatef(0, (EDGE_HEIGHT - textHeight) / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1105
x = TRAY_WIDTH - PIECE_HOLE / 2.0f;
1107
for (i = 0; i < 12; i++)
1113
if ((i < 6 && (sides & 1)) || (i >= 6 && (sides & 2)))
1116
glTranslatef(x, 0, 0);
1122
if (bd->turn == -1 && bd->rd->fDynamicLabels)
1125
sprintf(num, "%d", n);
1126
glPrintPointNumbers(&bd->bd3d, num);
1133
glTranslatef(0, TOTAL_HEIGHT - textHeight - (EDGE_HEIGHT - textHeight) / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1134
x = TRAY_WIDTH - PIECE_HOLE / 2.0f;
1136
for (i = 0; i < 12; i++)
1141
if ((i < 6 && (sides & 1)) || (i >= 6 && (sides & 2)))
1144
glTranslatef(x, 0, 0);
1150
if (bd->turn == -1 && bd->rd->fDynamicLabels)
1153
sprintf(num, "%d", n);
1154
glPrintPointNumbers(&bd->bd3d, num);
1161
void drawNumbers(BoardData* bd, int sides)
1163
/* No need to depth test as on top of board (depth test could cause alias problems too) */
1164
glDisable(GL_DEPTH_TEST);
1165
/* Draw inside then anti-aliased outline of numbers */
1166
setMaterial(&bd->rd->PointNumberMat);
1167
glNormal3f(0, 0, 1);
1170
DrawNumbers(bd, sides);
1171
glEnable(GL_DEPTH_TEST);
1174
void drawPoint(renderdata* prd, float tuv, int i, int p, int outline)
1175
{ /* Draw point with correct texture co-ords */
1176
float w = PIECE_HOLE;
1177
float h = POINT_HEIGHT;
1182
x = TRAY_WIDTH - EDGE_WIDTH + PIECE_HOLE * i;
1187
x = TRAY_WIDTH - EDGE_WIDTH + BOARD_WIDTH - (PIECE_HOLE * i);
1188
y = TOTAL_HEIGHT - EDGE_HEIGHT * 2 + LIFT_OFF;
1195
glTranslatef(EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH);
1198
x -= TRAY_WIDTH - EDGE_WIDTH;
1199
glTranslatef(TRAY_WIDTH, EDGE_HEIGHT, BASE_DEPTH);
1202
if (prd->roundedPoints)
1203
{ /* Draw rounded point ends */
1211
xoff = x + (PIECE_HOLE / 2.0f);
1213
xoff = x - (PIECE_HOLE / 2.0f);
1215
/* Draw rounded semi-circle end of point (with correct texture co-ords) */
1219
float radius = w / 2.0f;
1221
step = (2 * (float)PI) / prd->curveAccuracy;
1222
angle = -step * (prd->curveAccuracy / 4);
1223
glNormal3f(0, 0, 1);
1224
glBegin(outline ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1225
glTexCoord2f(xoff* tuv, y* tuv);
1227
glVertex3f(xoff, y, 0);
1228
for (i = 0; i <= prd->curveAccuracy / 2; i++)
1230
glTexCoord2f((xoff + (float)sin(angle) * radius) * tuv, (y + (float)cos(angle) * radius) * tuv);
1231
glVertex3f(xoff + (float)sin(angle) * radius, y + (float)cos(angle) * radius, 0);
1236
/* Move rest of point in slighlty */
1238
x -= -((PIECE_HOLE * (1 - TAKI_WIDTH)) / 2.0f);
1240
x -= ((PIECE_HOLE * (1 - TAKI_WIDTH)) / 2.0f);
1243
glBegin(outline ? GL_LINE_STRIP : GL_TRIANGLES);
1244
glNormal3f(0, 0, 1);
1245
glTexCoord2f((x + w) * tuv, y * tuv);
1246
glVertex3f(x + w, y, 0);
1247
glTexCoord2f((x + w / 2) * tuv, (y + h) * tuv);
1248
glVertex3f(x + w / 2, y + h, 0);
1249
glTexCoord2f(x * tuv, y * tuv);
1250
glVertex3f(x, y, 0);
1256
void drawPoints(renderdata* prd)
1258
/* texture unit value */
1261
/* Don't worry about depth testing (but set depth values) */
1262
glDepthFunc(GL_ALWAYS);
1264
setMaterial(&prd->BaseMat);
1266
drawChequeredRect(EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH, BOARD_WIDTH + TRAY_WIDTH - EDGE_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT * 2, prd->acrossCheq, prd->downCheq, prd->BaseMat.pTexture);
1268
drawChequeredRect(TRAY_WIDTH, EDGE_HEIGHT, BASE_DEPTH, BOARD_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT * 2, prd->acrossCheq, prd->downCheq, prd->BaseMat.pTexture);
1270
/* Ignore depth values when drawing points */
1271
glDepthMask(GL_FALSE);
1273
if (prd->PointMat[0].pTexture)
1274
tuv = (TEXTURE_SCALE) / prd->PointMat[0].pTexture->width;
1277
setMaterial(&prd->PointMat[0]);
1278
drawPoint(prd, tuv, 0, 0, 0);
1279
drawPoint(prd, tuv, 0, 1, 0);
1280
drawPoint(prd, tuv, 2, 0, 0);
1281
drawPoint(prd, tuv, 2, 1, 0);
1282
drawPoint(prd, tuv, 4, 0, 0);
1283
drawPoint(prd, tuv, 4, 1, 0);
1286
glEnable(GL_LINE_SMOOTH);
1289
drawPoint(prd, tuv, 0, 0, 1);
1290
drawPoint(prd, tuv, 0, 1, 1);
1291
drawPoint(prd, tuv, 2, 0, 1);
1292
drawPoint(prd, tuv, 2, 1, 1);
1293
drawPoint(prd, tuv, 4, 0, 1);
1294
drawPoint(prd, tuv, 4, 1, 1);
1296
glDisable(GL_BLEND);
1297
glDisable(GL_LINE_SMOOTH);
1299
if (prd->PointMat[1].pTexture)
1300
tuv = (TEXTURE_SCALE) / prd->PointMat[1].pTexture->width;
1303
setMaterial(&prd->PointMat[1]);
1304
drawPoint(prd, tuv, 1, 0, 0);
1305
drawPoint(prd, tuv, 1, 1, 0);
1306
drawPoint(prd, tuv, 3, 0, 0);
1307
drawPoint(prd, tuv, 3, 1, 0);
1308
drawPoint(prd, tuv, 5, 0, 0);
1309
drawPoint(prd, tuv, 5, 1, 0);
1311
glEnable(GL_LINE_SMOOTH);
1314
drawPoint(prd, tuv, 1, 0, 1);
1315
drawPoint(prd, tuv, 1, 1, 1);
1316
drawPoint(prd, tuv, 3, 0, 1);
1317
drawPoint(prd, tuv, 3, 1, 1);
1318
drawPoint(prd, tuv, 5, 0, 1);
1319
drawPoint(prd, tuv, 5, 1, 1);
1321
glDisable(GL_BLEND);
1322
glDisable(GL_LINE_SMOOTH);
1324
/* Restore depth buffer settings */
1325
glDepthFunc(GL_LEQUAL);
1326
glDepthMask(GL_TRUE);
1329
void drawBase(renderdata* prd, int sides)
1336
/* Rotate right board around */
1338
glTranslatef(TOTAL_WIDTH, TOTAL_HEIGHT, 0);
1339
glRotatef(180, 0, 0, 1);
1345
void drawHinge(BoardData3d *bd3d, renderdata *prd, float height)
1347
setMaterial(&prd->HingeMat);
1349
glMatrixMode(GL_TEXTURE);
1351
glScalef(1, HINGE_SEGMENTS, 1);
1352
glMatrixMode(GL_MODELVIEW);
1355
glTranslatef((TOTAL_WIDTH) / 2.0f, height, BASE_DEPTH + EDGE_DEPTH);
1356
glRotatef(-90, 1, 0, 0);
1357
gluCylinder(bd3d->qobjTex, HINGE_WIDTH, HINGE_WIDTH, HINGE_HEIGHT, prd->curveAccuracy, 1);
1359
glMatrixMode(GL_TEXTURE);
1361
glMatrixMode(GL_MODELVIEW);
1363
glRotatef(180, 1, 0, 0);
1364
gluDisk(bd3d->qobjTex, 0, HINGE_WIDTH, prd->curveAccuracy, 1);
1369
void tidyEdges(renderdata* prd)
1370
{ /* Anti-alias board edges */
1371
setMaterial(&prd->BoxMat);
1375
glEnable(GL_LINE_SMOOTH);
1376
glDepthMask(GL_FALSE);
1378
glNormal3f(0, 0, 1);
1381
if (prd->roundedEdges)
1384
glNormal3f(-1, 0, 0);
1385
glVertex3f(TRAY_WIDTH + BOARD_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1386
glVertex3f(TRAY_WIDTH + BOARD_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1388
glNormal3f(1, 0, 0);
1389
glVertex3f(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1390
glVertex3f(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1392
/* left bear off tray */
1393
glNormal3f(-1, 0, 0);
1394
glVertex3f(0, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1395
glVertex3f(0, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1397
glVertex3f(TRAY_WIDTH - EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1398
glVertex3f(TRAY_WIDTH - EDGE_WIDTH, TRAY_HEIGHT, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1399
glVertex3f(TRAY_WIDTH - EDGE_WIDTH, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1400
glVertex3f(TRAY_WIDTH - EDGE_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1402
/* right bear off tray */
1403
glNormal3f(1, 0, 0);
1404
glVertex3f(TOTAL_WIDTH, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1405
glVertex3f(TOTAL_WIDTH, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1407
glVertex3f(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1408
glVertex3f(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH, TRAY_HEIGHT, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1409
glVertex3f(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1410
glVertex3f(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1416
glVertex3f(TRAY_WIDTH + BOARD_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1417
glVertex3f(TRAY_WIDTH + BOARD_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1419
glVertex3f(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1420
glVertex3f(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1422
/* left bear off tray */
1423
glVertex3f(0, 0, BASE_DEPTH + EDGE_DEPTH);
1424
glVertex3f(0, TOTAL_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1426
glVertex3f(EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1427
glVertex3f(EDGE_WIDTH, TRAY_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1428
glVertex3f(EDGE_WIDTH, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1429
glVertex3f(EDGE_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1431
glVertex3f(TRAY_WIDTH - EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1432
glVertex3f(TRAY_WIDTH - EDGE_WIDTH, TRAY_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1433
glVertex3f(TRAY_WIDTH - EDGE_WIDTH, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1434
glVertex3f(TRAY_WIDTH - EDGE_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1436
glVertex3f(TRAY_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1437
glVertex3f(TRAY_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1439
/* right bear off tray */
1440
glVertex3f(TOTAL_WIDTH, 0, BASE_DEPTH + EDGE_DEPTH);
1441
glVertex3f(TOTAL_WIDTH, TOTAL_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1443
glVertex3f(TOTAL_WIDTH - EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1444
glVertex3f(TOTAL_WIDTH - EDGE_WIDTH, TRAY_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1445
glVertex3f(TOTAL_WIDTH - EDGE_WIDTH, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1446
glVertex3f(TOTAL_WIDTH - EDGE_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1448
glVertex3f(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1449
glVertex3f(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH, TRAY_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1450
glVertex3f(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1451
glVertex3f(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1453
glVertex3f(TOTAL_WIDTH - TRAY_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1454
glVertex3f(TOTAL_WIDTH - TRAY_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1457
/* inner edges (sides) */
1458
glNormal3f(1, 0, 0);
1459
glVertex3f(EDGE_WIDTH + LIFT_OFF, EDGE_HEIGHT, BASE_DEPTH + LIFT_OFF);
1460
glVertex3f(EDGE_WIDTH + LIFT_OFF, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + LIFT_OFF);
1461
glVertex3f(TRAY_WIDTH + LIFT_OFF, EDGE_HEIGHT, BASE_DEPTH + LIFT_OFF);
1462
glVertex3f(TRAY_WIDTH + LIFT_OFF, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + LIFT_OFF);
1464
glNormal3f(-1, 0, 0);
1465
glVertex3f(TOTAL_WIDTH - EDGE_WIDTH + LIFT_OFF, EDGE_HEIGHT, BASE_DEPTH + LIFT_OFF);
1466
glVertex3f(TOTAL_WIDTH - EDGE_WIDTH + LIFT_OFF, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + LIFT_OFF);
1467
glVertex3f(TOTAL_WIDTH - TRAY_WIDTH + LIFT_OFF, EDGE_HEIGHT, BASE_DEPTH + LIFT_OFF);
1468
glVertex3f(TOTAL_WIDTH - TRAY_WIDTH + LIFT_OFF, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + LIFT_OFF);
1470
glDepthMask(GL_TRUE);
1471
glDisable(GL_BLEND);
1472
glDisable(GL_LINE_SMOOTH);
1475
void getMoveIndicatorPos(BoardData* bd, float pos[3])
1478
pos[0] = TOTAL_WIDTH - TRAY_WIDTH + ARROW_SIZE / 2.0f;
1480
pos[0] = TRAY_WIDTH - ARROW_SIZE / 2.0f;
1483
pos[1] = EDGE_HEIGHT / 2.0f;
1485
pos[1] = TOTAL_HEIGHT - EDGE_HEIGHT / 2.0f;
1487
pos[2] = BASE_DEPTH + EDGE_DEPTH;
1490
void showMoveIndicator(BoardData* bd)
1493
/* ARROW_UNIT used to draw sub-bits of arrow */
1494
#define ARROW_UNIT (ARROW_SIZE / 4.0f)
1496
setMaterial(&bd->rd->ChequerMat[(bd->turn == 1)]);
1498
glDisable(GL_DEPTH_TEST);
1499
glDisable(GL_TEXTURE_2D);
1500
glNormal3f(0, 0, 1);
1503
getMoveIndicatorPos(bd, pos);
1504
glTranslatef(pos[0], pos[1], pos[2]);
1506
glRotatef(180, 0, 0, 1);
1509
glVertex2f(-ARROW_UNIT * 2, -ARROW_UNIT);
1510
glVertex2f(LIFT_OFF, -ARROW_UNIT);
1511
glVertex2f(LIFT_OFF, ARROW_UNIT);
1512
glVertex2f(-ARROW_UNIT * 2, ARROW_UNIT);
1514
glBegin(GL_TRIANGLES);
1515
glVertex2f(0, ARROW_UNIT * 2);
1516
glVertex2f(0, -ARROW_UNIT * 2);
1517
glVertex2f(ARROW_UNIT * 2, 0);
1521
SetColour3d(0, 0, 0, 1); /* Black outline */
1525
glEnable(GL_LINE_SMOOTH);
1527
glBegin(GL_LINE_LOOP);
1528
glVertex2f(-ARROW_UNIT * 2, -ARROW_UNIT);
1529
glVertex2f(-ARROW_UNIT * 2, ARROW_UNIT);
1530
glVertex2f(0, ARROW_UNIT);
1531
glVertex2f(0, ARROW_UNIT * 2);
1532
glVertex2f(ARROW_UNIT * 2, 0);
1533
glVertex2f(0, -ARROW_UNIT * 2);
1534
glVertex2f(0, -ARROW_UNIT);
1537
glDisable(GL_BLEND);
1538
glDisable(GL_LINE_SMOOTH);
1541
glEnable(GL_DEPTH_TEST);
1544
void ClearScreen(renderdata *prd)
1546
glClearColor(prd->BackGroundMat.ambientColour[0], prd->BackGroundMat.ambientColour[1], prd->BackGroundMat.ambientColour[2], 0);
1547
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1550
void RotateClosingBoard(BoardData3d* bd3d, renderdata *prd)
1552
float rotAngle = 90;
1553
float trans = getBoardHeight() * .4f;
1560
if ((bd3d->State == BOARD_OPENING) || (bd3d->State == BOARD_CLOSING))
1562
rotAngle *= bd3d->perOpen;
1563
trans *= bd3d->perOpen;
1564
zoom *= bd3d->perOpen;
1567
glTranslatef(0, -trans, zoom);
1568
glTranslatef(getBoardWidth() / 2.0f, getBoardHeight() / 2.0f, 0);
1569
glRotatef(rotAngle, 0, 0, 1);
1570
glTranslatef(-getBoardWidth() / 2.0f, -getBoardHeight() / 2.0f, 0);
1573
/* Macros to make texture specification easier */
1574
#define M_X(x, y, z) if (tuv) glTexCoord2f((z) * tuv, (y) * tuv); glVertex3f(x, y, z);
1575
#define M_Z(x, y, z) if (tuv) glTexCoord2f((x) * tuv, (y) * tuv); glVertex3f(x, y, z);
1577
#define DrawBottom(x, y, z, w, h)\
1578
glNormal3f(0, -1, 0);\
1580
if (tuv) glTexCoord2f((x) * tuv, (y + BOARD_FILLET - curveTextOff - (h)) * tuv);\
1581
glVertex3f(x, y, z);\
1582
if (tuv) glTexCoord2f((x + w) * tuv, (y + BOARD_FILLET - curveTextOff - (h)) * tuv);\
1583
glVertex3f(x + w, y, z);\
1584
if (tuv) glTexCoord2f((x + w) * tuv, (y + BOARD_FILLET - curveTextOff) * tuv);\
1585
glVertex3f(x + w, y, z + h);\
1586
if (tuv) glTexCoord2f((x) * tuv, (y + BOARD_FILLET - curveTextOff) * tuv);\
1587
glVertex3f(x, y, z + h);\
1590
#define DrawTop(x, y, z, w, h)\
1591
glNormal3f(0, 1, 0);\
1593
if (tuv) glTexCoord2f((x) * tuv, (y - (BOARD_FILLET - curveTextOff) + (h)) * tuv);\
1594
glVertex3f(x, y, z);\
1595
if (tuv) glTexCoord2f((x) * tuv, (y - (BOARD_FILLET - curveTextOff)) * tuv);\
1596
glVertex3f(x, y, z + h);\
1597
if (tuv) glTexCoord2f((x + w) * tuv, (y - (BOARD_FILLET - curveTextOff)) * tuv);\
1598
glVertex3f(x + w, y, z + h);\
1599
if (tuv) glTexCoord2f((x + w) * tuv, (y - (BOARD_FILLET - curveTextOff) + (h)) * tuv);\
1600
glVertex3f(x + w, y, z);\
1603
#define DrawLeft(x, y, z, w, h)\
1604
glNormal3f(-1, 0, 0);\
1606
if (tuv) glTexCoord2f((x + BOARD_FILLET - curveTextOff - (h)) * tuv, (y) * tuv);\
1607
glVertex3f(x, y, z);\
1608
if (tuv) glTexCoord2f((x + BOARD_FILLET - curveTextOff) * tuv, (y) * tuv);\
1609
glVertex3f(x, y, z + h);\
1610
if (tuv) glTexCoord2f((x + BOARD_FILLET - curveTextOff) * tuv, (y + w) * tuv);\
1611
glVertex3f(x, y + w, z + h);\
1612
if (tuv) glTexCoord2f((x + BOARD_FILLET - curveTextOff - (h)) * tuv, (y + w) * tuv);\
1613
glVertex3f(x, y + w, z);\
1616
#define DrawRight(x, y, z, w, h)\
1617
glNormal3f(1, 0, 0);\
1619
if (tuv) glTexCoord2f((x - (BOARD_FILLET - curveTextOff) + (h)) * tuv, (y) * tuv);\
1620
glVertex3f(x, y, z);\
1621
if (tuv) glTexCoord2f((x - (BOARD_FILLET - curveTextOff) + (h)) * tuv, (y + w) * tuv);\
1622
glVertex3f(x, y + w, z);\
1623
if (tuv) glTexCoord2f((x - (BOARD_FILLET - curveTextOff)) * tuv, (y + w) * tuv);\
1624
glVertex3f(x, y + w, z + h);\
1625
if (tuv) glTexCoord2f((x - (BOARD_FILLET - curveTextOff)) * tuv, (y) * tuv);\
1626
glVertex3f(x, y, z + h);\
1629
#define TextureOffset(s, t) if (tuv)\
1631
glMatrixMode(GL_TEXTURE);\
1633
glTranslatef(s, t, 0);\
1634
glMatrixMode(GL_MODELVIEW);\
1637
#define TextureReset if (tuv)\
1639
glMatrixMode(GL_TEXTURE);\
1641
glMatrixMode(GL_MODELVIEW);\
1644
/* texture unit value */
1647
void InsideFillet(float x, float y, float z, float w, float h, float radius, int accuracy, Texture* texture, float curveTextOff)
1650
DrawRight(x + BOARD_FILLET, y + BOARD_FILLET, BASE_DEPTH, h, EDGE_DEPTH - BOARD_FILLET);
1652
DrawBottom(x + BOARD_FILLET, y + h + BOARD_FILLET, BASE_DEPTH, w, EDGE_DEPTH - BOARD_FILLET + LIFT_OFF);
1654
DrawTop(x + BOARD_FILLET, y + BOARD_FILLET, BASE_DEPTH, w, EDGE_DEPTH - BOARD_FILLET)
1656
DrawLeft(x + w + BOARD_FILLET, y + BOARD_FILLET, BASE_DEPTH + LIFT_OFF, h, EDGE_DEPTH - BOARD_FILLET);
1660
glMatrixMode(GL_TEXTURE);
1662
glTranslatef((x + curveTextOff) * tuv, (y + h + radius * 2) * tuv, 0);
1663
glRotatef(-90, 0, 0, 1);
1664
glMatrixMode(GL_MODELVIEW);
1667
glTranslatef(x, y + h + radius * 2, z - radius);
1668
glRotatef(-180, 1, 0, 0);
1669
glRotatef(90, 0, 1, 0);
1670
QuarterCylinderSplayed(radius, h + radius * 2, accuracy, texture);
1674
TextureOffset(x * tuv, (y + curveTextOff) * tuv);
1676
glTranslatef(x, y, z - radius);
1677
glRotatef(-90, 1, 0, 0);
1678
glRotatef(-90, 0, 0, 1);
1679
QuarterCylinderSplayed(radius, w + radius * 2, accuracy, texture);
1685
glMatrixMode(GL_TEXTURE);
1687
glTranslatef((x + w + radius * 2 - curveTextOff) * tuv, y * tuv, 0);
1688
glRotatef(90, 0, 0, 1);
1689
glMatrixMode(GL_MODELVIEW);
1692
glTranslatef(x + w + radius * 2, y, z - radius);
1693
glRotatef(-90, 0, 1, 0);
1694
QuarterCylinderSplayed(radius, h + radius * 2, accuracy, texture);
1698
TextureOffset((x + radius) * tuv, (y + h + radius * 2) * tuv);
1700
glTranslatef(x + radius, y + h + radius * 2, z - radius);
1701
glRotatef(-90, 0, 0, 1);
1702
QuarterCylinderSplayedRev(radius, w, accuracy, texture);
1707
void drawTable(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
1709
float st, ct, dInc, curveTextOff = 0;
1712
if (bd3d->State != BOARD_OPEN)
1713
RotateClosingBoard(bd3d, prd);
1715
/* Draw background */
1716
setMaterial(&prd->BackGroundMat);
1718
/* Set depth and default pixel values (as background covers entire screen) */
1719
glDepthFunc(GL_ALWAYS);
1720
drawRect(bd3d->backGroundPos[0], bd3d->backGroundPos[1], 0, bd3d->backGroundSize[0], bd3d->backGroundSize[1], prd->BackGroundMat.pTexture);
1721
glDepthFunc(GL_LEQUAL);
1723
/* Right side of board */
1724
if (!prd->fHinges3d)
1725
drawBase(prd, 1 | 2);
1728
setMaterial(&prd->BoxMat);
1730
if (!prd->bgInTrays)
1731
drawSplitRect(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH, PIECE_HOLE + LIFT_OFF, TOTAL_HEIGHT - EDGE_HEIGHT * 2, prd->BoxMat.pTexture);
1733
if (prd->roundedEdges)
1735
if (prd->BoxMat.pTexture)
1737
tuv = (TEXTURE_SCALE) / prd->BoxMat.pTexture->width;
1738
st = (float)sin((2 * PI) / prd->curveAccuracy) * BOARD_FILLET;
1739
ct = ((float)cos((2 * PI) / prd->curveAccuracy) - 1) * BOARD_FILLET;
1740
dInc = (float)sqrt(st * st + ct * ct);
1741
curveTextOff = (prd->curveAccuracy / 4) * dInc;
1747
glNormal3f(0, 0, 1);
1749
M_Z(TOTAL_WIDTH - EDGE_WIDTH + BOARD_FILLET - LIFT_OFF, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1750
M_Z(TOTAL_WIDTH - BOARD_FILLET + LIFT_OFF, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1751
M_Z(TOTAL_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1752
M_Z(TOTAL_WIDTH - EDGE_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1754
M_Z(TOTAL_WIDTH - EDGE_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1755
M_Z(TOTAL_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1756
M_Z(TOTAL_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1757
M_Z(TOTAL_WIDTH - EDGE_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1761
DrawRight(TOTAL_WIDTH, BOARD_FILLET, 0, TOTAL_HEIGHT - BOARD_FILLET * 2, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1765
glMatrixMode(GL_TEXTURE);
1767
glTranslatef((TOTAL_WIDTH - BOARD_FILLET) * tuv, (BOARD_FILLET - curveTextOff - (BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET)) * tuv, 0);
1768
glRotatef(90, 0, 0, 1);
1769
glMatrixMode(GL_MODELVIEW);
1772
glTranslatef(TOTAL_WIDTH - BOARD_FILLET, BOARD_FILLET, 0);
1773
glRotatef(90, 1, 0, 0);
1774
QuarterCylinder(BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET, prd->curveAccuracy, prd->BoxMat.pTexture);
1780
glMatrixMode(GL_TEXTURE);
1782
glTranslatef((TOTAL_WIDTH - BOARD_FILLET) * tuv, (TOTAL_HEIGHT - (BOARD_FILLET - curveTextOff)) * tuv, 0);
1783
glRotatef(90, 0, 0, 1);
1784
glMatrixMode(GL_MODELVIEW);
1787
glTranslatef(TOTAL_WIDTH - BOARD_FILLET, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1788
glRotatef(-90, 1, 0, 0);
1789
QuarterCylinder(BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET, prd->curveAccuracy, prd->BoxMat.pTexture);
1795
glMatrixMode(GL_TEXTURE);
1797
glTranslatef((TOTAL_WIDTH - BOARD_FILLET + curveTextOff) * tuv, (TOTAL_HEIGHT - BOARD_FILLET) * tuv, 0);
1798
glRotatef(-90, 0, 0, 1);
1799
glMatrixMode(GL_MODELVIEW);
1802
glTranslatef(TOTAL_WIDTH - BOARD_FILLET, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1803
glRotatef(-180, 1, 0, 0);
1804
glRotatef(90, 0, 1, 0);
1805
QuarterCylinder(BOARD_FILLET, TOTAL_HEIGHT - BOARD_FILLET * 2, prd->curveAccuracy, prd->BoxMat.pTexture);
1810
glTranslatef(TOTAL_WIDTH - BOARD_FILLET, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1811
glRotatef(-90, 0, 0, 1);
1812
drawCornerEigth(bd3d->boardPoints, BOARD_FILLET, prd->curveAccuracy);
1816
glTranslatef(TOTAL_WIDTH - BOARD_FILLET, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1817
drawCornerEigth(bd3d->boardPoints, BOARD_FILLET, prd->curveAccuracy);
1820
/* Top + bottom edges */
1821
if (!prd->fHinges3d)
1825
glNormal3f(0, 0, 1);
1826
M_Z(EDGE_WIDTH - BOARD_FILLET, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1827
M_Z(TOTAL_WIDTH / 2.0f, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1828
M_Z(TOTAL_WIDTH / 2.0f, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1829
M_Z(EDGE_WIDTH - BOARD_FILLET, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1831
M_Z(TOTAL_WIDTH / 2.0f, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1832
M_Z(TOTAL_WIDTH - EDGE_WIDTH + BOARD_FILLET, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1833
M_Z(TOTAL_WIDTH - EDGE_WIDTH + BOARD_FILLET, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1834
M_Z(TOTAL_WIDTH / 2.0f, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1837
DrawBottom(BOARD_FILLET, 0, 0, TOTAL_WIDTH - BOARD_FILLET * 2, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1841
glNormal3f(0, 0, 1);
1842
M_Z(EDGE_WIDTH - BOARD_FILLET, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1843
M_Z(TOTAL_WIDTH / 2.0f, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1844
M_Z(TOTAL_WIDTH / 2.0f, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1845
M_Z(EDGE_WIDTH - BOARD_FILLET, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1847
M_Z(TOTAL_WIDTH / 2.0f, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1848
M_Z(TOTAL_WIDTH - EDGE_WIDTH + BOARD_FILLET, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1849
M_Z(TOTAL_WIDTH - EDGE_WIDTH + BOARD_FILLET, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1850
M_Z(TOTAL_WIDTH / 2.0f, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1853
DrawTop(BOARD_FILLET, TOTAL_HEIGHT, 0, TOTAL_WIDTH - BOARD_FILLET * 2, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1855
TextureOffset(BOARD_FILLET * tuv, BOARD_FILLET * tuv);
1857
glTranslatef(BOARD_FILLET, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1858
glRotatef(-90, 0, 0, 1);
1859
QuarterCylinder(BOARD_FILLET, TOTAL_WIDTH - BOARD_FILLET * 2, prd->curveAccuracy, prd->BoxMat.pTexture);
1863
TextureOffset(BOARD_FILLET * tuv, (TOTAL_HEIGHT - (BOARD_FILLET - curveTextOff)) * tuv);
1865
glTranslatef(BOARD_FILLET, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1866
glRotatef(-90, 1, 0, 0);
1867
glRotatef(-90, 0, 0, 1);
1868
QuarterCylinder(BOARD_FILLET, TOTAL_WIDTH - BOARD_FILLET * 2, prd->curveAccuracy, prd->BoxMat.pTexture);
1876
glNormal3f(0, 0, 1);
1877
M_Z((TOTAL_WIDTH + HINGE_GAP) / 2.0f, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1878
M_Z(TOTAL_WIDTH - EDGE_WIDTH + BOARD_FILLET, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1879
M_Z(TOTAL_WIDTH - EDGE_WIDTH + BOARD_FILLET, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1880
M_Z((TOTAL_WIDTH + HINGE_GAP) / 2.0f, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1883
DrawBottom((TOTAL_WIDTH + HINGE_GAP) / 2.0f, 0, 0, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1887
glNormal3f(0, 0, 1);
1888
M_Z((TOTAL_WIDTH + HINGE_GAP) / 2.0f, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1889
M_Z(TOTAL_WIDTH - EDGE_WIDTH + BOARD_FILLET, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1890
M_Z(TOTAL_WIDTH - EDGE_WIDTH + BOARD_FILLET, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1891
M_Z((TOTAL_WIDTH + HINGE_GAP) / 2.0f, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1894
DrawTop((TOTAL_WIDTH + HINGE_GAP) / 2.0f, TOTAL_HEIGHT, 0, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET)
1898
if (bd3d->State != BOARD_OPEN)
1900
/* Cover up back when closing */
1901
glNormal3f(-1, 0, 0);
1902
M_X(TRAY_WIDTH + BOARD_WIDTH + (BAR_WIDTH + HINGE_GAP) / 2.0f, 0, 0);
1903
M_X(TRAY_WIDTH + BOARD_WIDTH + (BAR_WIDTH + HINGE_GAP) / 2.0f, 0, BASE_DEPTH + EDGE_DEPTH);
1904
M_X(TRAY_WIDTH + BOARD_WIDTH + (BAR_WIDTH + HINGE_GAP) / 2.0f, TOTAL_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
1905
M_X(TRAY_WIDTH + BOARD_WIDTH + (BAR_WIDTH + HINGE_GAP) / 2.0f, TOTAL_HEIGHT, 0);
1909
TextureOffset(((TOTAL_WIDTH + HINGE_GAP) / 2.0f) * tuv, BOARD_FILLET * tuv);
1911
glTranslatef((TOTAL_WIDTH + HINGE_GAP) / 2.0f, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1912
glRotatef(-90, 0, 0, 1);
1913
QuarterCylinder(BOARD_FILLET, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - BOARD_FILLET, prd->curveAccuracy, prd->BoxMat.pTexture);
1917
TextureOffset(((TOTAL_WIDTH + HINGE_GAP) / 2.0f) * tuv, (TOTAL_HEIGHT - (BOARD_FILLET - curveTextOff)) * tuv);
1919
glTranslatef((TOTAL_WIDTH + HINGE_GAP) / 2.0f, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
1920
glRotatef(-90, 1, 0, 0);
1921
glRotatef(-90, 0, 0, 1);
1922
QuarterCylinder(BOARD_FILLET, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - BOARD_FILLET, prd->curveAccuracy, prd->BoxMat.pTexture);
1927
if (!prd->fHinges3d)
1931
glNormal3f(0, 0, 1);
1932
M_Z(TRAY_WIDTH + BOARD_WIDTH + BOARD_FILLET - LIFT_OFF, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1933
M_Z(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH - BOARD_FILLET + LIFT_OFF, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1934
M_Z(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1935
M_Z(TRAY_WIDTH + BOARD_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1937
M_Z(TRAY_WIDTH + BOARD_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1938
M_Z(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1939
M_Z(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1940
M_Z(TRAY_WIDTH + BOARD_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1947
glNormal3f(0, 0, 1);
1948
M_Z(TRAY_WIDTH + BOARD_WIDTH + (BAR_WIDTH + HINGE_GAP) / 2.0f, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1949
M_Z(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH - BOARD_FILLET + LIFT_OFF, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1950
M_Z(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1951
M_Z(TRAY_WIDTH + BOARD_WIDTH + (BAR_WIDTH + HINGE_GAP) / 2.0f, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1953
M_Z(TRAY_WIDTH + BOARD_WIDTH + (BAR_WIDTH + HINGE_GAP) / 2.0f, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1954
M_Z(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1955
M_Z(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1956
M_Z(TRAY_WIDTH + BOARD_WIDTH + (BAR_WIDTH + HINGE_GAP) / 2.0f, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1962
glNormal3f(0, 0, 1);
1963
M_Z(TOTAL_WIDTH - TRAY_WIDTH + BOARD_FILLET - LIFT_OFF, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1964
M_Z(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH - BOARD_FILLET + LIFT_OFF, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1965
M_Z(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1966
M_Z(TOTAL_WIDTH - TRAY_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1968
M_Z(TOTAL_WIDTH - TRAY_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1969
M_Z(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
1970
M_Z(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1971
M_Z(TOTAL_WIDTH - TRAY_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1976
glNormal3f(0, 0, 1);
1977
M_Z(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH - LIFT_OFF - BOARD_FILLET, TRAY_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1978
M_Z(TOTAL_WIDTH - EDGE_WIDTH + BOARD_FILLET, TRAY_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1979
M_Z(TOTAL_WIDTH - EDGE_WIDTH + BOARD_FILLET, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1980
M_Z(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH - LIFT_OFF - BOARD_FILLET, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
1983
InsideFillet(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH - BOARD_FILLET, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2, TRAY_HEIGHT - EDGE_HEIGHT, BOARD_FILLET, prd->curveAccuracy, prd->BoxMat.pTexture, curveTextOff);
1984
InsideFillet(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH - BOARD_FILLET, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2, TRAY_HEIGHT - EDGE_HEIGHT, BOARD_FILLET, prd->curveAccuracy, prd->BoxMat.pTexture, curveTextOff);
1986
InsideFillet(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH - BOARD_FILLET, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH, BOARD_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT * 2, BOARD_FILLET, prd->curveAccuracy, prd->BoxMat.pTexture, curveTextOff);
1991
drawBox(BOX_SPLITTOP, TOTAL_WIDTH - EDGE_WIDTH, 0, 0, EDGE_WIDTH, TOTAL_HEIGHT, BASE_DEPTH + EDGE_DEPTH, prd->BoxMat.pTexture);
1993
/* Top + bottom edges */
1994
if (!prd->fHinges3d)
1996
drawBox(BOX_NOSIDES | BOX_SPLITWIDTH, EDGE_WIDTH, 0, 0, TOTAL_WIDTH - EDGE_WIDTH * 2, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH, prd->BoxMat.pTexture);
1997
drawBox(BOX_NOSIDES | BOX_SPLITWIDTH, EDGE_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, 0, TOTAL_WIDTH - EDGE_WIDTH * 2, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH, prd->BoxMat.pTexture);
2001
drawBox(BOX_ALL, (TOTAL_WIDTH + HINGE_GAP) / 2.0f, 0, 0, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH, prd->BoxMat.pTexture);
2002
drawBox(BOX_ALL, (TOTAL_WIDTH + HINGE_GAP) / 2.0f, TOTAL_HEIGHT - EDGE_HEIGHT, 0, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH, prd->BoxMat.pTexture);
2006
if (!prd->fHinges3d)
2007
drawBox(BOX_NOENDS | BOX_SPLITTOP, TRAY_WIDTH + BOARD_WIDTH, EDGE_HEIGHT, BASE_DEPTH, BAR_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT * 2, EDGE_DEPTH, prd->BoxMat.pTexture);
2009
drawBox(BOX_NOENDS | BOX_SPLITTOP, TRAY_WIDTH + BOARD_WIDTH + (BAR_WIDTH + HINGE_GAP) / 2.0f, EDGE_HEIGHT, 0, (BAR_WIDTH - HINGE_GAP) / 2.0f, TOTAL_HEIGHT - EDGE_HEIGHT * 2, BASE_DEPTH + EDGE_DEPTH, prd->BoxMat.pTexture);
2012
drawBox(BOX_NOENDS | BOX_SPLITTOP, TOTAL_WIDTH - TRAY_WIDTH, EDGE_HEIGHT, BASE_DEPTH, EDGE_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT * 2, EDGE_DEPTH, prd->BoxMat.pTexture);
2013
drawBox(BOX_NOSIDES, TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH - LIFT_OFF, TRAY_HEIGHT, BASE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2 + LIFT_OFF * 2, MID_SIDE_GAP_HEIGHT, EDGE_DEPTH, prd->BoxMat.pTexture);
2019
/* Left side of board*/
2022
if (bd3d->State != BOARD_OPEN)
2024
float boardAngle = 180;
2025
if ((bd3d->State == BOARD_OPENING) || (bd3d->State == BOARD_CLOSING))
2026
boardAngle *= bd3d->perOpen;
2028
glTranslatef(TOTAL_WIDTH / 2.0f, 0, BASE_DEPTH + EDGE_DEPTH);
2029
glRotatef(boardAngle, 0, 1, 0);
2030
glTranslatef(-TOTAL_WIDTH / 2.0f, 0, -(BASE_DEPTH + EDGE_DEPTH));
2036
setMaterial(&prd->BoxMat);
2038
if (!prd->bgInTrays)
2039
drawSplitRect(EDGE_WIDTH - LIFT_OFF, EDGE_HEIGHT, BASE_DEPTH, PIECE_HOLE, TOTAL_HEIGHT - EDGE_HEIGHT * 2, prd->BoxMat.pTexture);
2041
if (bd3d->State != BOARD_OPEN)
2042
{ /* Back of board */
2043
float logoSize = (TOTAL_WIDTH * .3f) / 2.0f;
2044
drawRect(TOTAL_WIDTH / 2.0f, 0, 0, -(TOTAL_WIDTH / 2.0f), TOTAL_HEIGHT, prd->BoxMat.pTexture);
2047
glTranslatef(TOTAL_WIDTH / 4.0f, TOTAL_HEIGHT / 2.0f, -LIFT_OFF);
2048
glRotatef(90, 0, 0, 1);
2049
setMaterial(&bd3d->logoMat);
2050
glNormal3f(0, 0, 1);
2052
glTexCoord2f(0, 0); glVertex3f(logoSize, -logoSize, 0);
2053
glTexCoord2f(1, 0); glVertex3f(-logoSize, -logoSize, 0);
2054
glTexCoord2f(1, 1); glVertex3f(-logoSize, logoSize, 0);
2055
glTexCoord2f(0, 1); glVertex3f(logoSize, logoSize, 0);
2058
setMaterial(&prd->BoxMat);
2061
if (prd->roundedEdges)
2066
glNormal3f(0, 0, 1);
2067
M_Z(BOARD_FILLET - LIFT_OFF, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2068
M_Z(EDGE_WIDTH - BOARD_FILLET + LIFT_OFF, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2069
M_Z(EDGE_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
2070
M_Z(BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
2072
M_Z(BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
2073
M_Z(EDGE_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
2074
M_Z(EDGE_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2075
M_Z(BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2078
DrawLeft(0, BOARD_FILLET, 0, TOTAL_HEIGHT - BOARD_FILLET * 2, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
2082
glMatrixMode(GL_TEXTURE);
2084
glTranslatef(BOARD_FILLET * tuv, (BOARD_FILLET - curveTextOff) * tuv, 0);
2085
glRotatef(-90, 0, 0, 1);
2086
glMatrixMode(GL_MODELVIEW);
2089
glTranslatef(BOARD_FILLET, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
2090
glRotatef(-90, 1, 0, 0);
2091
glRotatef(180, 0, 1, 0);
2092
QuarterCylinder(BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET, prd->curveAccuracy, prd->BoxMat.pTexture);
2098
glMatrixMode(GL_TEXTURE);
2100
glTranslatef((BOARD_FILLET - curveTextOff) * tuv, (TOTAL_HEIGHT - (BOARD_FILLET - curveTextOff)) * tuv, 0);
2101
glRotatef(90, 0, 0, 1);
2102
glMatrixMode(GL_MODELVIEW);
2105
glTranslatef(BOARD_FILLET, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
2106
glRotatef(-90, 1, 0, 0);
2107
glRotatef(-90, 0, 1, 0);
2108
QuarterCylinder(BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET, prd->curveAccuracy, prd->BoxMat.pTexture);
2114
glMatrixMode(GL_TEXTURE);
2116
glTranslatef((BOARD_FILLET - curveTextOff) * tuv, BOARD_FILLET * tuv, 0);
2117
glRotatef(90, 0, 0, 1);
2119
glMatrixMode(GL_MODELVIEW);
2121
glTranslatef(BOARD_FILLET, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
2122
glRotatef(-90, 0, 1, 0);
2123
QuarterCylinder(BOARD_FILLET, TOTAL_HEIGHT - BOARD_FILLET * 2, prd->curveAccuracy, prd->BoxMat.pTexture);
2128
glTranslatef(BOARD_FILLET, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
2129
glRotatef(180, 0, 0, 1);
2130
drawCornerEigth(bd3d->boardPoints, BOARD_FILLET, prd->curveAccuracy);
2134
glTranslatef(BOARD_FILLET, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
2135
glRotatef(90, 0, 0, 1);
2136
drawCornerEigth(bd3d->boardPoints, BOARD_FILLET, prd->curveAccuracy);
2140
{ /* Top + bottom edges and bar */
2143
glNormal3f(0, 0, 1);
2144
M_Z(EDGE_WIDTH - BOARD_FILLET, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2145
M_Z((TOTAL_WIDTH - HINGE_GAP) / 2.0f, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2146
M_Z((TOTAL_WIDTH - HINGE_GAP) / 2.0f, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2147
M_Z(EDGE_WIDTH - BOARD_FILLET, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2150
DrawBottom(BOARD_FILLET, 0, 0, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
2154
glNormal3f(0, 0, 1);
2155
M_Z(EDGE_WIDTH - BOARD_FILLET, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2156
M_Z((TOTAL_WIDTH - HINGE_GAP) / 2.0f, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2157
M_Z((TOTAL_WIDTH - HINGE_GAP) / 2.0f, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2158
M_Z(EDGE_WIDTH - BOARD_FILLET, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2162
DrawTop(BOARD_FILLET, TOTAL_HEIGHT, 0, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET)
2165
if (bd3d->State != BOARD_OPEN)
2167
/* Cover up back when closing */
2168
glNormal3f(1, 0, 0);
2169
M_X((TOTAL_WIDTH - HINGE_GAP) / 2.0f, 0, 0);
2170
M_X((TOTAL_WIDTH - HINGE_GAP) / 2.0f, TOTAL_HEIGHT, 0);
2171
M_X((TOTAL_WIDTH - HINGE_GAP) / 2.0f, TOTAL_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
2172
M_X((TOTAL_WIDTH - HINGE_GAP) / 2.0f, 0, BASE_DEPTH + EDGE_DEPTH);
2176
TextureOffset(BOARD_FILLET * tuv, BOARD_FILLET * tuv);
2178
glTranslatef(BOARD_FILLET, BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
2179
glRotatef(-90, 0, 0, 1);
2180
QuarterCylinder(BOARD_FILLET, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - BOARD_FILLET, prd->curveAccuracy, prd->BoxMat.pTexture);
2184
TextureOffset(BOARD_FILLET * tuv, (TOTAL_HEIGHT - (BOARD_FILLET - curveTextOff)) * tuv);
2186
glTranslatef(BOARD_FILLET, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
2187
glRotatef(-90, 1, 0, 0);
2188
glRotatef(-90, 0, 0, 1);
2189
QuarterCylinder(BOARD_FILLET, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - BOARD_FILLET, prd->curveAccuracy, prd->BoxMat.pTexture);
2195
glNormal3f(0, 0, 1);
2196
M_Z(TRAY_WIDTH + BOARD_WIDTH + BOARD_FILLET - LIFT_OFF, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2197
M_Z(TRAY_WIDTH + BOARD_WIDTH + (BAR_WIDTH - HINGE_GAP) / 2.0f, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2198
M_Z(TRAY_WIDTH + BOARD_WIDTH + (BAR_WIDTH - HINGE_GAP) / 2.0f, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
2199
M_Z(TRAY_WIDTH + BOARD_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
2201
M_Z(TRAY_WIDTH + BOARD_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
2202
M_Z(TRAY_WIDTH + BOARD_WIDTH + (BAR_WIDTH - HINGE_GAP) / 2.0f, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
2203
M_Z(TRAY_WIDTH + BOARD_WIDTH + (BAR_WIDTH - HINGE_GAP) / 2.0f, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2204
M_Z(TRAY_WIDTH + BOARD_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2211
glNormal3f(0, 0, 1);
2212
M_Z(TRAY_WIDTH - EDGE_WIDTH + BOARD_FILLET - LIFT_OFF, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2213
M_Z(TRAY_WIDTH - BOARD_FILLET + LIFT_OFF, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2214
M_Z(TRAY_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
2215
M_Z(TRAY_WIDTH - EDGE_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
2217
M_Z(TRAY_WIDTH - EDGE_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
2218
M_Z(TRAY_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT / 2.0f, BASE_DEPTH + EDGE_DEPTH);
2219
M_Z(TRAY_WIDTH - BOARD_FILLET + LIFT_OFF, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2220
M_Z(TRAY_WIDTH - EDGE_WIDTH + BOARD_FILLET - LIFT_OFF, TOTAL_HEIGHT - EDGE_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2225
glNormal3f(0, 0, 1);
2226
M_Z(EDGE_WIDTH - LIFT_OFF - BOARD_FILLET, TRAY_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2227
M_Z(TRAY_WIDTH - EDGE_WIDTH + BOARD_FILLET + LIFT_OFF * 2, TRAY_HEIGHT + BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2228
M_Z(TRAY_WIDTH - EDGE_WIDTH + BOARD_FILLET + LIFT_OFF * 2, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2229
M_Z(EDGE_WIDTH - LIFT_OFF - BOARD_FILLET, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH);
2232
InsideFillet(EDGE_WIDTH - BOARD_FILLET, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2, TRAY_HEIGHT - EDGE_HEIGHT, BOARD_FILLET, prd->curveAccuracy, prd->BoxMat.pTexture, curveTextOff);
2233
InsideFillet(EDGE_WIDTH - BOARD_FILLET, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2, TRAY_HEIGHT - EDGE_HEIGHT, BOARD_FILLET, prd->curveAccuracy, prd->BoxMat.pTexture, curveTextOff);
2235
InsideFillet(TRAY_WIDTH - BOARD_FILLET, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH, BOARD_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT * 2, BOARD_FILLET, prd->curveAccuracy, prd->BoxMat.pTexture, curveTextOff);
2240
drawBox(BOX_SPLITTOP, 0, 0, 0, EDGE_WIDTH, TOTAL_HEIGHT, BASE_DEPTH + EDGE_DEPTH, prd->BoxMat.pTexture);
2243
{ /* Top + bottom edges and bar */
2244
drawBox(BOX_ALL, EDGE_WIDTH, 0, 0, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH, prd->BoxMat.pTexture);
2245
drawBox(BOX_ALL, EDGE_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, 0, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH, prd->BoxMat.pTexture);
2249
drawBox(BOX_NOENDS | BOX_SPLITTOP, TRAY_WIDTH + BOARD_WIDTH, EDGE_HEIGHT, 0, (BAR_WIDTH - HINGE_GAP) / 2.0f, TOTAL_HEIGHT - EDGE_HEIGHT * 2, BASE_DEPTH + EDGE_DEPTH, prd->BoxMat.pTexture);
2252
drawBox(BOX_NOENDS | BOX_SPLITTOP, TRAY_WIDTH - EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH, EDGE_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT * 2, EDGE_DEPTH, prd->BoxMat.pTexture);
2253
drawBox(BOX_NOSIDES, EDGE_WIDTH - LIFT_OFF, TRAY_HEIGHT, BASE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2 + LIFT_OFF * 2, MID_SIDE_GAP_HEIGHT, EDGE_DEPTH, prd->BoxMat.pTexture);
2258
drawHinge(bd3d, prd, ((TOTAL_HEIGHT / 2.0f) - HINGE_HEIGHT) / 2.0f);
2259
drawHinge(bd3d, prd, ((TOTAL_HEIGHT / 2.0f) - HINGE_HEIGHT + TOTAL_HEIGHT) / 2.0f);
2261
if (bd3d->State == BOARD_OPEN)
2262
{ /* Shadow in gap between boards */
2263
setMaterial(&bd3d->gapColour);
2264
drawRect((TOTAL_WIDTH - HINGE_GAP * 1.5f) / 2.0f, 0, LIFT_OFF, HINGE_GAP * 2, TOTAL_HEIGHT + LIFT_OFF, 0);
2273
if (prd->showMoveIndicator)
2274
showMoveIndicator(bd);
2277
int DiceShowing(BoardData* bd)
2279
return ((bd->diceShown == DICE_ON_BOARD && bd->diceRoll[0]) ||
2280
(bd->rd->fDiceArea && bd->diceShown == DICE_BELOW_BOARD));
2283
void drawPick(BoardData* bd)
2284
{ /* Draw all the objects on the board to see if any have been selected */
2289
for (i = 0; i < 28; i++)
2292
for (j = 1; j <= abs(bd->points[i]); j++)
2293
drawPiece(&bd->bd3d, i, j);
2297
for (i = 0; i < 6; i++)
2299
glLoadName(fClockwise ? i + 1 : 12 - i);
2300
drawRect(TRAY_WIDTH + PIECE_HOLE * i, EDGE_HEIGHT, BASE_DEPTH, PIECE_HOLE, POINT_HEIGHT, 0);
2302
glLoadName(fClockwise ? i + 7 : 6 - i);
2303
drawRect(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH + PIECE_HOLE * i, EDGE_HEIGHT, BASE_DEPTH, PIECE_HOLE, POINT_HEIGHT, 0);
2305
glLoadName(fClockwise ? i + 13 : 24 - i);
2306
drawRect(TOTAL_WIDTH - TRAY_WIDTH - (PIECE_HOLE * i), TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH, -PIECE_HOLE, -POINT_HEIGHT, 0);
2308
glLoadName(fClockwise ? i + 19 : 18 - i);
2309
drawRect(TRAY_WIDTH + BOARD_WIDTH - (PIECE_HOLE * i), TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH, -PIECE_HOLE, -POINT_HEIGHT, 0);
2312
barHeight = (PIECE_HOLE + PIECE_GAP_HEIGHT) * 4;
2314
drawRect(TOTAL_WIDTH / 2.0f - PIECE_HOLE / 2.0f, TOTAL_HEIGHT / 2.0f - (DOUBLECUBE_SIZE / 2.0f + barHeight + PIECE_HOLE / 2.0f),
2315
BASE_DEPTH + EDGE_DEPTH, PIECE_HOLE, barHeight, 0);
2317
drawRect(TOTAL_WIDTH / 2.0f - PIECE_HOLE / 2.0f, TOTAL_HEIGHT / 2.0f + (DOUBLECUBE_SIZE / 2.0f + PIECE_HOLE / 2.0f),
2318
BASE_DEPTH + EDGE_DEPTH, PIECE_HOLE, barHeight, 0);
2320
/* Home/unused trays depend on direction */
2321
glLoadName((!fClockwise) ? 26 : POINT_UNUSED0);
2322
drawRect(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2, TRAY_HEIGHT - EDGE_HEIGHT, 0);
2323
glLoadName((fClockwise) ? 26 : POINT_UNUSED0);
2324
drawRect(EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2, TRAY_HEIGHT - EDGE_HEIGHT, 0);
2326
glLoadName((!fClockwise) ? 27 : POINT_UNUSED1);
2327
drawRect(TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT - POINT_HEIGHT, BASE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2, POINT_HEIGHT, 0);
2328
glLoadName((fClockwise) ? 27 : POINT_UNUSED1);
2329
drawRect(EDGE_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT - POINT_HEIGHT, BASE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2, POINT_HEIGHT, 0);
2332
glLoadName(POINT_LEFT);
2333
drawRect(TRAY_WIDTH, (TOTAL_HEIGHT - DICE_AREA_HEIGHT) / 2.0f, BASE_DEPTH, DICE_AREA_CLICK_WIDTH, DICE_AREA_HEIGHT, 0);
2334
glLoadName(POINT_RIGHT);
2335
drawRect(TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH, (TOTAL_HEIGHT - DICE_AREA_HEIGHT) / 2.0f, BASE_DEPTH, DICE_AREA_CLICK_WIDTH, DICE_AREA_HEIGHT, 0);
2338
if (DiceShowing(bd))
2340
glLoadName(POINT_DICE);
2342
moveToDicePos(bd, 0);
2343
drawCube(getDiceSize(bd->rd) * .95f);
2346
moveToDicePos(bd, 1);
2347
drawCube(getDiceSize(bd->rd) * .95f);
2353
glLoadName(POINT_CUBE);
2354
moveToDoubleCubePos(bd);
2355
drawCube(DOUBLECUBE_SIZE * .95f);
2359
int NearestHit(int hits, GLuint* ptr)
2363
float minDepth = 0, depth;
2365
for (i = 0; i < hits; i++)
2366
{ /* for each hit */
2368
depth = (float) *ptr++/0x7fffffff;
2369
ptr++; /* Skip max depth */
2370
if (i == 0 || depth < minDepth)
2380
void getProjectedPos(int x, int y, float atDepth, float pos[3])
2381
{ /* Work out where point (x, y) projects to at depth atDepth */
2383
GLdouble mvmatrix[16], projmatrix[16];
2384
double nX, nY, nZ, fX, fY, fZ, zRange;
2386
glGetIntegerv (GL_VIEWPORT, viewport);
2387
glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
2388
glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);
2390
gluUnProject ((GLdouble)x, (GLdouble)y, 0.0, mvmatrix, projmatrix, viewport, &nX, &nY, &nZ);
2391
gluUnProject ((GLdouble)x, (GLdouble)y, 1.0, mvmatrix, projmatrix, viewport, &fX, &fY, &fZ);
2393
zRange = (fabs(nZ) - atDepth) / (fabs(fZ) + fabs(nZ));
2394
pos[0] = (float)(nX - (-fX + nX) * zRange);
2395
pos[1] = (float)(nY - (-fY + nY) * zRange);
2396
pos[2] = (float)(nZ - (-fZ + nZ) * zRange);
2399
void getProjectedPieceDragPos(int x, int y, float pos[3])
2401
getProjectedPos(x, y, BASE_DEPTH + EDGE_DEPTH + DOUBLECUBE_SIZE + LIFT_OFF * 3, pos);
2404
void calculateBackgroundSize(BoardData3d *bd3d, int viewport[4])
2406
float pos1[3], pos2[3], pos3[3];
2408
getProjectedPos(0, viewport[1] + viewport[3], 0, pos1);
2409
getProjectedPos(viewport[2], viewport[1] + viewport[3], 0, pos2);
2410
getProjectedPos(0, viewport[1], 0, pos3);
2412
bd3d->backGroundPos[0] = pos1[0];
2413
bd3d->backGroundPos[1] = pos3[1];
2414
bd3d->backGroundSize[0] = pos2[0] - pos1[0];
2415
bd3d->backGroundSize[1] = pos1[1] - pos3[1];
2418
void getFlagPos(BoardData* bd, float v[3])
2420
v[0] = (TRAY_WIDTH + BOARD_WIDTH) / 2.0f;
2421
v[1] = TOTAL_HEIGHT / 2.0f;
2422
v[2] = BASE_DEPTH + EDGE_DEPTH;
2424
if (bd->turn == -1) /* Move to other side of board */
2425
v[0] += BOARD_WIDTH + BAR_WIDTH;
2428
void waveFlag(float ctlpoints[S_NUMPOINTS][T_NUMPOINTS][3], float wag)
2432
/* wave the flag by rotating Z coords though a sine wave */
2433
for (i = 1; i < S_NUMPOINTS; i++)
2434
for (j = 0; j < T_NUMPOINTS; j++)
2435
ctlpoints[i][j][2] = (float)sin((GLfloat)i + wag) * FLAG_WAG;
2438
void drawFlagPick(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
2443
waveFlag(bd3d->ctlpoints, bd3d->flagWaved);
2445
glLoadName(POINT_RESIGN);
2450
glTranslatef(v[0], v[1], v[2]);
2452
/* Draw flag surface (approximation) */
2453
glBegin(GL_QUAD_STRIP);
2454
for (s = 0; s < S_NUMPOINTS; s++)
2456
glVertex3fv(bd3d->ctlpoints[s][1]);
2457
glVertex3fv(bd3d->ctlpoints[s][0]);
2461
/* Draw flag pole */
2462
glTranslatef(0, -FLAG_HEIGHT, 0);
2464
glRotatef(-90, 1, 0, 0);
2465
gluCylinder(bd3d->qobj, FLAGPOLE_WIDTH, FLAGPOLE_WIDTH, FLAGPOLE_HEIGHT, prd->curveAccuracy, 1);
2467
circleRev(FLAGPOLE_WIDTH, 0, prd->curveAccuracy);
2468
circleRev(FLAGPOLE_WIDTH * 2, FLAGPOLE_HEIGHT, prd->curveAccuracy);
2473
static void drawPointPick(int point)
2474
{ /* Draw sub parts of point to work out which part of point clicked */
2478
if (point >= 0 && point <= 25)
2479
{ /* Split first point into 2 parts for zero and one selection */
2480
#define SPLIT_PERCENT .40f
2481
#define SPLIT_HEIGHT (PIECE_HOLE * SPLIT_PERCENT)
2483
getPiecePos(point, 1, fClockwise, pos);
2487
drawRect(pos[0] - (PIECE_HOLE / 2.0f), pos[1] + (PIECE_HOLE / 2.0f) + PIECE_GAP_HEIGHT - SPLIT_HEIGHT, pos[2], PIECE_HOLE, SPLIT_HEIGHT, 0);
2489
drawRect(pos[0] - (PIECE_HOLE / 2.0f), pos[1] - (PIECE_HOLE / 2.0f), pos[2], PIECE_HOLE, SPLIT_HEIGHT, 0);
2493
drawRect(pos[0] - (PIECE_HOLE / 2.0f), pos[1] - (PIECE_HOLE / 2.0f), pos[2], PIECE_HOLE, PIECE_HOLE + PIECE_GAP_HEIGHT - SPLIT_HEIGHT, 0);
2495
drawRect(pos[0] - (PIECE_HOLE / 2.0f), pos[1] - (PIECE_HOLE / 2.0f) + SPLIT_HEIGHT, pos[2], PIECE_HOLE, PIECE_HOLE + PIECE_GAP_HEIGHT - SPLIT_HEIGHT, 0);
2497
for (i = 2; i < 6; i++)
2499
/* Only 3 places for bar */
2500
if ((point == 0 || point == 25) && i == 4)
2502
getPiecePos(point, i, fClockwise, pos);
2504
drawRect(pos[0] - (PIECE_HOLE / 2.0f), pos[1] - (PIECE_HOLE / 2.0f), pos[2], PIECE_HOLE, PIECE_HOLE + PIECE_GAP_HEIGHT, 0);
2510
pos[1] = pos[1] - (PIECE_HOLE / 2.0f);
2511
drawRect(pos[0] - (PIECE_HOLE / 2.0f), TOTAL_HEIGHT - EDGE_HEIGHT - POINT_HEIGHT, pos[2], PIECE_HOLE, pos[1] - (TOTAL_HEIGHT - EDGE_HEIGHT - POINT_HEIGHT), 0);
2515
pos[1] = pos[1] + (PIECE_HOLE / 2.0f) + PIECE_GAP_HEIGHT;
2516
drawRect(pos[0] - (PIECE_HOLE / 2.0f), pos[1], pos[2], PIECE_HOLE, EDGE_HEIGHT + POINT_HEIGHT - pos[1], 0);
2521
/* 20 allows for 5 hit records (more than enough) */
2524
int BoardPoint3d(BoardData* bd, BoardData3d* bd3d, renderdata* prd, int x, int y, int point)
2525
{ /* Identify if anything is below point (x,y) */
2526
GLuint selectBuf[BUFSIZE];
2530
glSelectBuffer(BUFSIZE, selectBuf);
2531
glRenderMode(GL_SELECT);
2535
glGetIntegerv (GL_VIEWPORT, viewport);
2537
glMatrixMode(GL_PROJECTION);
2541
gluPickMatrix(x, y, 1, 1, viewport);
2543
/* Setup projection matrix - using saved values */
2545
glOrtho(-bd3d->horFrustrum, bd3d->horFrustrum, -bd3d->vertFrustrum, bd3d->vertFrustrum, 0, 5);
2547
glFrustum(-bd3d->horFrustrum, bd3d->horFrustrum, -bd3d->vertFrustrum, bd3d->vertFrustrum, zNear, zFar);
2549
glMatrixMode(GL_MODELVIEW);
2550
glLoadMatrixf(bd3d->modelMatrix);
2553
{ /* Flag showing - just pick this */
2554
drawFlagPick(bd, &bd->bd3d, bd->rd);
2558
/* Either draw all the objects of just a single point */
2562
drawPointPick(point);
2567
hits = glRenderMode(GL_RENDER);
2569
glMatrixMode(GL_PROJECTION);
2571
glMatrixMode(GL_MODELVIEW);
2573
return NearestHit(hits, (GLuint*)selectBuf);
2576
void setupPath(BoardData *bd, Path* p, float* pRotate, int fClockwise, int fromPoint, int fromDepth, int toPoint, int toDepth)
2577
{ /* Work out the animation path for a moving piece */
2579
float w, h, xDist, yDist;
2581
float bar1Dist, bar1Ratio;
2582
float bar2Dist, bar2Ratio;
2583
float start[3], end[3], obj1, obj2, objHeight;
2584
int fromBoard = (fromPoint + 5) / 6;
2585
int toBoard = (toPoint - 1) / 6 + 1;
2588
/* First work out were piece has to move */
2589
/* Get start and end points */
2590
getPiecePos(fromPoint, fromDepth, fClockwise, start);
2591
getPiecePos(toPoint, toDepth, fClockwise, end);
2593
/* Only rotate piece going home */
2596
/* Swap boards if displaying other way around */
2599
int swap[] = {0, 2, 1, 4, 3, 5};
2600
fromBoard = swap[fromBoard];
2601
toBoard = swap[toBoard];
2604
/* Work out what obstacle needs to be avoided */
2605
if ((fromBoard == 2 || fromBoard == 3) && (toBoard == 1 || toBoard == 4))
2606
{ /* left side to right side */
2607
obj1 = TRAY_WIDTH + BOARD_WIDTH;
2608
obj2 = obj1 + BAR_WIDTH;
2609
objHeight = BASE_DEPTH + EDGE_DEPTH + DOUBLECUBE_SIZE;
2611
else if ((fromBoard == 1 || fromBoard == 4) && (toBoard == 2 || toBoard == 3))
2612
{ /* right side to left side */
2613
obj2 = TRAY_WIDTH + BOARD_WIDTH;
2614
obj1 = obj2 + BAR_WIDTH;
2615
objHeight = BASE_DEPTH + EDGE_DEPTH + DOUBLECUBE_SIZE;
2617
else if ((fromBoard == 1 && toBoard == 4) || (fromBoard == 2 && toBoard == 3))
2618
{ /* up same side */
2619
obj1 = (TOTAL_HEIGHT - DICE_AREA_HEIGHT) / 2.0f;
2620
obj2 = (TOTAL_HEIGHT + DICE_AREA_HEIGHT) / 2.0f;
2621
objHeight = BASE_DEPTH + getDiceSize(bd->rd);
2624
else if ((fromBoard == 4 && toBoard == 1) || (fromBoard == 3 && toBoard == 2))
2625
{ /* down same side */
2626
obj1 = (TOTAL_HEIGHT + DICE_AREA_HEIGHT) / 2.0f;
2627
obj2 = (TOTAL_HEIGHT - DICE_AREA_HEIGHT) / 2.0f;
2628
objHeight = BASE_DEPTH + getDiceSize(bd->rd);
2631
else if (fromBoard == toBoard)
2637
fromPoint = 13 - fromPoint;
2638
toPoint = 13 - toPoint;
2641
if (fromPoint < toPoint)
2646
fromPoint = 12 - fromPoint;
2647
toPoint = 12 - toPoint;
2653
fromPoint = 24 + 13 - fromPoint;
2654
toPoint = 24 + 13 - toPoint;
2657
if (fromPoint < toPoint)
2661
fromPoint = fromPoint - 13;
2662
toPoint = toPoint - 13;
2664
obj1 = TRAY_WIDTH + PIECE_HOLE * fromPoint;
2665
obj2 = TRAY_WIDTH + PIECE_HOLE * toPoint;
2666
if ((fromBoard == 1) || (fromBoard == 4))
2672
objHeight = BASE_DEPTH + PIECE_DEPTH * 3;
2676
if (fromPoint == 0 || fromPoint == 25)
2677
{ /* Move from bar */
2680
obj1 = TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH;
2683
obj2 = TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH;
2685
obj2 += PIECE_HOLE * (toPoint - 20);
2689
obj2 = TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH;
2691
obj2 += PIECE_HOLE * (5 - toPoint);
2696
obj1 = TRAY_WIDTH + BOARD_WIDTH;
2699
obj2 = TRAY_WIDTH + PIECE_HOLE * (25 - toPoint);
2705
obj2 = TRAY_WIDTH + PIECE_HOLE * toPoint;
2710
objHeight = BASE_DEPTH + EDGE_DEPTH + DOUBLECUBE_SIZE;
2717
obj1 = TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH + PIECE_HOLE * (7 - fromPoint);
2718
else /* (toPoint == 27) */
2719
obj1 = TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH + PIECE_HOLE * (fromPoint - 18);
2724
obj1 = TRAY_WIDTH + PIECE_HOLE * (fromPoint - 1);
2725
else /* (toPoint == 27) */
2726
obj1 = TRAY_WIDTH + PIECE_HOLE * (24 - fromPoint);
2730
obj2 = TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH;
2732
obj2 = TRAY_WIDTH - EDGE_WIDTH;
2735
objHeight = BASE_DEPTH + EDGE_DEPTH + getDiceSize(bd->rd);
2738
if ((fromBoard == 3 && toBoard == 4) || (fromBoard == 4 && toBoard == 3))
2739
{ /* Special case when moving along top of board */
2740
if ((bd->cube_owner != 1) && (fromDepth <= 2) && (toDepth <= 2))
2741
objHeight = BASE_DEPTH + EDGE_DEPTH + PIECE_DEPTH;
2744
/* Now setup path object */
2748
/* obstacle height */
2749
point[2] = objHeight;
2752
{ /* barriers are along y axis */
2753
xDiff = end[0] - start[0];
2754
yDiff = end[1] - start[1];
2755
bar1Dist = obj1 - start[1];
2756
bar1Ratio = bar1Dist / yDiff;
2757
bar2Dist = obj2 - start[1];
2758
bar2Ratio = bar2Dist / yDiff;
2760
/* 2nd point - moved up from 1st one */
2761
/* Work out whether 2nd point is further away than height required */
2762
xDist = xDiff * bar1Ratio;
2763
yDist = obj1 - start[1];
2764
h = objHeight - start[2];
2765
w = (float)sqrt(xDist * xDist + yDist * yDist);
2769
point[0] = start[0] + xDiff * bar1Ratio;
2774
point[0] = start[0] + xDist * (h / w);
2775
point[1] = start[1] + yDist * (h / w);
2777
addPathSegment(p, PATH_CURVE_9TO12, point);
2779
/* Work out whether 3rd point is further away than height required */
2780
yDist = end[1] - obj2;
2781
xDist = xDiff * (yDist / yDiff);
2782
w = (float)sqrt(xDist * xDist + yDist * yDist);
2783
h = objHeight - end[2];
2785
/* 3rd point - moved along from 2nd one */
2788
point[0] = start[0] + xDiff * bar2Ratio;
2793
point[0] = end[0] - xDist * (h / w);
2794
point[1] = end[1] - yDist * (h / w);
2796
addPathSegment(p, PATH_LINE, point);
2799
{ /* barriers are along x axis */
2800
xDiff = end[0] - start[0];
2801
yDiff = end[1] - start[1];
2802
bar1Dist = obj1 - start[0];
2803
bar1Ratio = bar1Dist / xDiff;
2804
bar2Dist = obj2 - start[0];
2805
bar2Ratio = bar2Dist / xDiff;
2807
/* Work out whether 2nd point is further away than height required */
2808
xDist = obj1 - start[0];
2809
yDist = yDiff * bar1Ratio;
2810
h = objHeight - start[2];
2811
w = (float)sqrt(xDist * xDist + yDist * yDist);
2813
/* 2nd point - moved up from 1st one */
2817
point[1] = start[1] + yDiff * bar1Ratio;
2821
point[0] = start[0] + xDist * (h / w);
2822
point[1] = start[1] + yDist * (h / w);
2824
addPathSegment(p, PATH_CURVE_9TO12, point);
2826
/* Work out whether 3rd point is further away than height required */
2827
xDist = end[0] - obj2;
2828
yDist = yDiff * (xDist / xDiff);
2829
w = (float)sqrt(xDist * xDist + yDist * yDist);
2830
h = objHeight - end[2];
2832
/* 3rd point - moved along from 2nd one */
2836
point[1] = start[1] + yDiff * bar2Ratio;
2840
point[0] = end[0] - xDist * (h / w);
2841
point[1] = end[1] - yDist * (h / w);
2843
addPathSegment(p, PATH_LINE, point);
2846
addPathSegment(p, PATH_CURVE_12TO3, end);
2849
void setupDicePath(int num, float stepSize, Path* p, BoardData* bd)
2852
getDicePos(bd, num, point);
2854
point[0] -= stepSize * 5;
2857
point[0] += stepSize * 2;
2858
addPathSegment(p, PATH_PARABOLA_12TO3, point);
2860
point[0] += stepSize * 2;
2861
addPathSegment(p, PATH_PARABOLA, point);
2863
point[0] += stepSize;
2864
addPathSegment(p, PATH_PARABOLA, point);
2867
void randomDiceRotation(Path* p, DiceRotation* diceRotation, int dir)
2869
/* Dice rotation range values */
2871
#define XROT_RANGE 1.5f
2873
#define YROT_MIN -.5f
2874
#define YROT_RANGE 1
2876
diceRotation->xRotFactor = XROT_MIN + randRange(XROT_RANGE);
2877
diceRotation->xRotStart = 1 - (p->pts[p->numSegments][0] - p->pts[0][0]) * diceRotation->xRotFactor;
2878
diceRotation->xRot = diceRotation->xRotStart * 360;
2880
diceRotation->yRotFactor = YROT_MIN + randRange(YROT_RANGE);
2881
diceRotation->yRotStart = 1 - (p->pts[p->numSegments][0] - p->pts[0][0]) * diceRotation->yRotFactor;
2882
diceRotation->yRot = diceRotation->yRotStart * 360;
2886
diceRotation->xRotFactor = -diceRotation->xRotFactor;
2887
diceRotation->yRotFactor = -diceRotation->yRotFactor;
2891
void setupDicePaths(BoardData* bd, Path dicePaths[2], float diceMovingPos[2][3], DiceRotation diceRotation[2])
2893
int firstDie = (bd->turn == 1);
2894
int dir = (bd->turn == 1) ? -1 : 1;
2896
setupDicePath(firstDie, dir * DICE_STEP_SIZE0, &dicePaths[firstDie], bd);
2897
setupDicePath(!firstDie, dir * DICE_STEP_SIZE1, &dicePaths[!firstDie], bd);
2899
randomDiceRotation(&dicePaths[firstDie], &diceRotation[firstDie], dir);
2900
randomDiceRotation(&dicePaths[!firstDie], &diceRotation[!firstDie], dir);
2902
copyPoint(diceMovingPos[0], dicePaths[0].pts[0]);
2903
copyPoint(diceMovingPos[1], dicePaths[1].pts[0]);
2906
int DiceTooClose(BoardData3d *bd3d, renderdata *prd)
2910
int firstDie = bd3d->dicePos[0][0] > bd3d->dicePos[1][0];
2912
orgX[0] = bd3d->dicePos[firstDie][0] - DICE_STEP_SIZE0 * 5;
2913
orgX[1] = bd3d->dicePos[!firstDie][0] - DICE_STEP_SIZE1 * 5;
2914
dist = (float)sqrt((orgX[1] - orgX[0]) * (orgX[1] - orgX[0])
2915
+ (bd3d->dicePos[!firstDie][1] - bd3d->dicePos[firstDie][1]) * (bd3d->dicePos[!firstDie][1] - bd3d->dicePos[firstDie][1]));
2916
return (dist < getDiceSize(prd) * 1.1f);
2919
void setDicePos(BoardData *bd, BoardData3d *bd3d)
2922
float diceSize = getDiceSize(bd->rd);
2923
float firstX = TRAY_WIDTH + DICE_STEP_SIZE0 * 3 + diceSize * .75f;
2924
int firstDie = (bd->turn == 1);
2926
bd3d->dicePos[firstDie][0] = firstX + randRange(BOARD_WIDTH + TRAY_WIDTH - firstX - diceSize * 2);
2927
bd3d->dicePos[firstDie][1] = randRange(DICE_AREA_HEIGHT);
2929
do /* insure dice are not too close together */
2932
{ /* Trouble placing 2nd dice - replace 1st dice */
2933
setDicePos(bd, bd3d);
2937
firstX = bd3d->dicePos[firstDie][0] + diceSize;
2938
bd3d->dicePos[!firstDie][0] = firstX + randRange(BOARD_WIDTH + TRAY_WIDTH - firstX - diceSize * .7f);
2939
bd3d->dicePos[!firstDie][1] = randRange(DICE_AREA_HEIGHT);
2941
while (DiceTooClose(bd3d, bd->rd));
2943
bd3d->dicePos[firstDie][2] = (float)(rand() % 360);
2944
bd3d->dicePos[!firstDie][2] = (float)(rand() % 360);
2946
updateDiceOccPos(bd, bd3d);
2949
void drawDie(BoardData* bd, BoardData3d *bd3d, int num)
2952
/* Move to correct position for die */
2953
if (bd3d->shakingDice)
2955
glTranslatef(bd3d->diceMovingPos[num][0], bd3d->diceMovingPos[num][1], bd3d->diceMovingPos[num][2]);
2956
glRotatef(bd3d->diceRotation[num].xRot, 0, 1, 0);
2957
glRotatef(bd3d->diceRotation[num].yRot, 1, 0, 0);
2958
glRotatef(bd3d->dicePos[num][2], 0, 0, 1);
2961
moveToDicePos(bd, num);
2968
void initViewArea(viewArea* pva)
2969
{ /* Initialize values to extremes */
2970
pva->top = -base_unit * 1000;
2971
pva->bottom = base_unit * 1000;
2975
float getViewAreaHeight(viewArea* pva)
2977
return pva->top - pva->bottom;
2980
float getViewAreaWidth(viewArea* pva)
2985
float getAreaRatio(viewArea* pva)
2987
return getViewAreaWidth(pva) / getViewAreaHeight(pva);
2990
void addViewAreaHeightPoint(viewArea* pva, float halfRadianFOV, float boardRadAngle, float inY, float inZ)
2991
{ /* Rotate points by board angle */
2995
y = inY * (float)cos(boardRadAngle) - inZ * (float)sin(boardRadAngle);
2996
z = inZ * (float)cos(boardRadAngle) + inY * (float)sin(boardRadAngle);
2998
/* Project height to zero depth */
2999
adj = z * (float)tan(halfRadianFOV);
3005
/* Store max / min heights */
3008
if (pva->bottom > y)
3012
void workOutWidth(viewArea* pva, float halfRadianFOV, float boardRadAngle, float aspectRatio, float ip[3])
3014
float halfRadianXFOV;
3015
float w = getViewAreaHeight(pva) * aspectRatio;
3020
/* Work out X-FOV from Y-FOV */
3021
float halfViewHeight = getViewAreaHeight(pva) / 2;
3022
l = halfViewHeight / (float)tan(halfRadianFOV);
3023
halfRadianXFOV = (float)atan((halfViewHeight * aspectRatio) / l);
3025
/* Rotate z coord by board angle */
3027
p[2] = ip[2] * (float)cos(boardRadAngle) + ip[1] * (float)sin(boardRadAngle);
3029
/* Adjust x coord by projected z value at relevant X-FOV */
3030
w2 = w / 2 - p[2] * (float)tan(halfRadianXFOV);
3031
l = w2 / (float)tan(halfRadianXFOV);
3032
p[0] += p[2] * (p[0] / l);
3034
if (pva->width < p[0] * 2)
3035
pva->width = p[0] * 2;
3038
float GetFOVAngle(BoardData* bd)
3040
float temp = bd->rd->boardAngle / 20.0f;
3041
float skewFactor = (bd->rd->skewFactor / 100.0f) * (4 - .6f) + .6f;
3042
/* Magic numbers to normalize viewing distance */
3043
return (47 - 2.3f * temp * temp) / skewFactor;
3046
void WorkOutViewArea(BoardData* bd, viewArea *pva, float *pHalfRadianFOV, float aspectRatio, int AssumeCubeAtTop)
3049
float boardRadAngle;
3052
boardRadAngle = (bd->rd->boardAngle * (float)PI) / 180.0f;
3053
*pHalfRadianFOV = ((GetFOVAngle(bd) * (float)PI) / 180.0f) / 2.0f;
3055
/* Sort out viewing area */
3056
addViewAreaHeightPoint(pva, *pHalfRadianFOV, boardRadAngle, -getBoardHeight() / 2, 0);
3057
addViewAreaHeightPoint(pva, *pHalfRadianFOV, boardRadAngle, -getBoardHeight() / 2, BASE_DEPTH + EDGE_DEPTH);
3059
if (bd->rd->fDiceArea)
3061
float diceSize = getDiceSize(bd->rd);
3062
addViewAreaHeightPoint(pva, *pHalfRadianFOV, boardRadAngle, getBoardHeight() / 2 + diceSize, 0);
3063
addViewAreaHeightPoint(pva, *pHalfRadianFOV, boardRadAngle, getBoardHeight() / 2 + diceSize, BASE_DEPTH + diceSize);
3066
{ /* Bottom edge is defined by board */
3067
addViewAreaHeightPoint(pva, *pHalfRadianFOV, boardRadAngle, getBoardHeight() / 2, 0);
3068
addViewAreaHeightPoint(pva, *pHalfRadianFOV, boardRadAngle, getBoardHeight() / 2, BASE_DEPTH + EDGE_DEPTH);
3071
if (AssumeCubeAtTop)
3072
addViewAreaHeightPoint(pva, *pHalfRadianFOV, boardRadAngle, -(getBoardHeight() / 2 - EDGE_HEIGHT), BASE_DEPTH + EDGE_DEPTH + DOUBLECUBE_SIZE);
3076
if (bd->cube_owner == 1)
3077
addViewAreaHeightPoint(pva, *pHalfRadianFOV, boardRadAngle, -(getBoardHeight() / 2 - EDGE_HEIGHT), BASE_DEPTH + EDGE_DEPTH + DOUBLECUBE_SIZE);
3078
if (bd->cube_owner == -1)
3079
addViewAreaHeightPoint(pva, *pHalfRadianFOV, boardRadAngle, getBoardHeight() / 2 - EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH + DOUBLECUBE_SIZE);
3081
p[0] = getBoardWidth() / 2;
3082
p[1] = getBoardHeight() / 2;
3083
p[2] = BASE_DEPTH + EDGE_DEPTH;
3084
workOutWidth(pva, *pHalfRadianFOV, boardRadAngle, aspectRatio, p);
3087
void SetupPerspVolume(BoardData* bd, BoardData3d* bd3d, renderdata* prd, int viewport[4])
3089
float aspectRatio = (float)viewport[2]/(float)(viewport[3]);
3093
float halfRadianFOV;
3097
if (aspectRatio < .5f)
3098
{ /* Viewing area to high - cut down so board rendered correctly */
3099
int newHeight = viewport[2] * 2;
3100
viewport[1] = (viewport[3] - newHeight) / 2;
3101
viewport[3] = newHeight;
3102
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
3104
/* Clear screen so top + bottom outside board shown ok */
3108
/* Workout how big the board is (in 3d space) */
3109
WorkOutViewArea(bd, &va, &halfRadianFOV, aspectRatio, FALSE);
3111
/* If the cube not at top of board and some spare vertical space,
3112
see if adding cube at top would fit without changing the board size */
3113
if ((bd->doubled || bd->cube_owner != 1) && (aspectRatio <= getAreaRatio(&va)))
3115
WorkOutViewArea(bd, &va, &halfRadianFOV, aspectRatio, TRUE);
3116
if (aspectRatio > getAreaRatio(&va))
3117
{ /* Didn't fit - go back to original values */
3118
WorkOutViewArea(bd, &va, &halfRadianFOV, aspectRatio, FALSE);
3122
fovScale = zNear * (float)tan(halfRadianFOV);
3124
if (aspectRatio > getAreaRatio(&va))
3126
bd3d->vertFrustrum = fovScale;
3127
bd3d->horFrustrum = bd3d->vertFrustrum * aspectRatio;
3131
bd3d->horFrustrum = fovScale * getAreaRatio(&va);
3132
bd3d->vertFrustrum = bd3d->horFrustrum / aspectRatio;
3134
/* Setup projection matrix */
3135
glFrustum(-bd3d->horFrustrum, bd3d->horFrustrum, -bd3d->vertFrustrum, bd3d->vertFrustrum, zNear, zFar);
3137
/* Setup modelview matrix */
3138
glMatrixMode(GL_MODELVIEW);
3141
/* Zoom back so image fills window */
3142
zoom = (getViewAreaHeight(&va) / 2) / (float)tan(halfRadianFOV);
3143
glTranslatef(0, 0, -zoom);
3145
/* Offset from centre because of perspective */
3146
glTranslatef(0, getViewAreaHeight(&va) / 2 + va.bottom, 0);
3149
glRotatef((float)prd->boardAngle, -1, 0, 0);
3151
/* Origin is bottom left, so move from centre */
3152
glTranslatef(-(getBoardWidth() / 2.0f), -((getBoardHeight()) / 2.0f), 0);
3158
if (aspectRatio > getBoardWidth() / getBoardHeight())
3160
size = (getBoardHeight() / 2);
3161
bd3d->horFrustrum = size * aspectRatio;
3162
bd3d->vertFrustrum = size;
3166
size = (getBoardWidth() / 2);
3167
bd3d->horFrustrum = size;
3168
bd3d->vertFrustrum = size / aspectRatio;
3170
glOrtho(-bd3d->horFrustrum, bd3d->horFrustrum, -bd3d->vertFrustrum, bd3d->vertFrustrum, 0, 5);
3172
glMatrixMode(GL_MODELVIEW);
3175
glTranslatef(-(getBoardWidth() / 2.0f), -(getBoardHeight() / 2.0f), -3);
3178
/* Save matrix for later */
3179
glGetFloatv(GL_MODELVIEW_MATRIX, bd3d->modelMatrix);
3182
void setupFlag(BoardData3d *bd3d)
3185
float width = FLAG_WIDTH;
3186
float height = FLAG_HEIGHT;
3189
gluDeleteNurbsRenderer(bd3d->flagNurb);
3190
bd3d->flagNurb = gluNewNurbsRenderer();
3192
for (i = 0; i < S_NUMPOINTS; i++)
3194
bd3d->ctlpoints[i][0][0] = width / (S_NUMPOINTS - 1) * i;
3195
bd3d->ctlpoints[i][1][0] = width / (S_NUMPOINTS - 1) * i;
3196
bd3d->ctlpoints[i][0][1] = 0;
3197
bd3d->ctlpoints[i][1][1] = height;
3198
bd3d->ctlpoints[i][0][2] = 0;
3199
bd3d->ctlpoints[i][1][2] = 0;
3203
void renderFlag(BoardData *bd, BoardData3d *bd3d, int curveAccuracy)
3205
/* Simple knots i.e. no weighting */
3206
float s_knots[S_NUMKNOTS] = {0, 0, 0, 0, 1, 1, 1, 1};
3207
float t_knots[T_NUMKNOTS] = {0, 0, 1, 1};
3209
/* Draw flag surface */
3210
setMaterial(&bd3d->flagMat);
3212
/* Set size of polygons */
3213
gluNurbsProperty(bd3d->flagNurb, GLU_SAMPLING_TOLERANCE, 500.0f / curveAccuracy);
3215
gluBeginSurface(bd3d->flagNurb);
3216
gluNurbsSurface(bd3d->flagNurb, S_NUMKNOTS, s_knots, T_NUMKNOTS, t_knots, 3 * T_NUMPOINTS, 3,
3217
(float*)bd3d->ctlpoints, S_NUMPOINTS, T_NUMPOINTS, GL_MAP2_VERTEX_3);
3218
gluEndSurface(bd3d->flagNurb);
3220
/* Draw flag pole */
3223
glTranslatef(-FLAGPOLE_WIDTH, -FLAG_HEIGHT, 0);
3225
glRotatef(-90, 1, 0, 0);
3226
SetColour3d(.2f, .2f, .4f, 0); /* Blue pole */
3227
gluCylinder(bd3d->qobj, FLAGPOLE_WIDTH, FLAGPOLE_WIDTH, FLAGPOLE_HEIGHT, curveAccuracy, 1);
3229
circleRev(FLAGPOLE_WIDTH, 0, curveAccuracy);
3230
circleRev(FLAGPOLE_WIDTH * 2, FLAGPOLE_HEIGHT, curveAccuracy);
3234
/* Draw number on flag */
3235
glDisable(GL_DEPTH_TEST);
3237
setMaterial(&bd3d->flagNumberMat);
3241
/* Move to middle of flag */
3243
v[0] = (bd3d->ctlpoints[1][0][0] + bd3d->ctlpoints[2][0][0]) / 2.0f;
3244
v[1] = (bd3d->ctlpoints[1][0][0] + bd3d->ctlpoints[1][1][0]) / 2.0f;
3245
v[2] = (bd3d->ctlpoints[1][0][2] + bd3d->ctlpoints[2][0][2]) / 2.0f;
3246
glTranslatef(v[0], v[1], v[2]);
3249
/* Work out approx angle of number based on control points */
3250
float ang = (float)atan(-(bd3d->ctlpoints[2][0][2] - bd3d->ctlpoints[1][0][2]) / (bd3d->ctlpoints[2][0][0] - bd3d->ctlpoints[1][0][0]));
3251
float degAng = (ang) * 180 / (float)PI;
3253
glRotatef(degAng, 0, 1, 0);
3258
char flagValue[2] = "x";
3259
/* No specular light */
3261
float zero[4] = {0,0,0,0};
3262
glGetLightfv(GL_LIGHT0, GL_SPECULAR, specular);
3263
glLightfv(GL_LIGHT0, GL_SPECULAR, zero);
3265
flagValue[0] = '0' + (char)abs(bd->resigned);
3266
glScalef(1.3f, 1.3f, 1);
3269
glPrintCube(&bd->bd3d, flagValue);
3271
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
3275
glEnable(GL_DEPTH_TEST);
3278
void drawFlag(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
3281
int isStencil = glIsEnabled(GL_STENCIL_TEST);
3284
glDisable(GL_STENCIL_TEST);
3286
waveFlag(bd3d->ctlpoints, bd3d->flagWaved);
3291
glTranslatef(v[0], v[1], v[2]);
3293
renderFlag(bd, bd3d, prd->curveAccuracy);
3297
glEnable(GL_STENCIL_TEST);
3300
void updateDieOccPos(BoardData* bd, BoardData3d* bd3d, Occluder* pOcc, int num)
3304
if (bd3d->shakingDice)
3306
copyPoint(pOcc->trans, bd3d->diceMovingPos[num]);
3308
pOcc->rot[0] = bd3d->diceRotation[num].xRot;
3309
pOcc->rot[1] = bd3d->diceRotation[num].yRot;
3310
pOcc->rot[2] = bd3d->dicePos[num][2];
3312
makeInverseRotateMatrixZ(pOcc->invMat, pOcc->rot[2]);
3314
makeInverseRotateMatrixX(id, pOcc->rot[1]);
3315
matrixmult(pOcc->invMat, id);
3317
makeInverseRotateMatrixY(id, pOcc->rot[0]);
3318
matrixmult(pOcc->invMat, id);
3320
makeInverseTransposeMatrix(id, pOcc->trans);
3321
matrixmult(pOcc->invMat, id);
3325
getDicePos(bd, num, pOcc->trans);
3327
makeInverseTransposeMatrix(id, pOcc->trans);
3329
if (bd->diceShown == DICE_ON_BOARD)
3331
pOcc->rot[0] = pOcc->rot[1] = 0;
3332
pOcc->rot[2] = bd3d->dicePos[num][2];
3334
makeInverseRotateMatrixZ(pOcc->invMat, pOcc->rot[2]);
3335
matrixmult(pOcc->invMat, id);
3339
pOcc->rot[0] = pOcc->rot[1] = pOcc->rot[2] = 0;
3340
copyMatrix(pOcc->invMat, id);
3345
void updateDiceOccPos(BoardData* bd, BoardData3d* bd3d)
3347
int show = DiceShowing(bd);
3349
bd3d->Occluders[OCC_DICE1].show = bd3d->Occluders[OCC_DICE2].show = show;
3352
updateDieOccPos(bd, bd3d, &bd3d->Occluders[OCC_DICE1], 0);
3353
updateDieOccPos(bd, bd3d, &bd3d->Occluders[OCC_DICE2], 1);
3357
void updateCubeOccPos(BoardData* bd, BoardData3d* bd3d)
3359
getDoubleCubePos(bd, bd3d->Occluders[OCC_CUBE].trans);
3360
makeInverseTransposeMatrix(bd3d->Occluders[OCC_CUBE].invMat, bd3d->Occluders[OCC_CUBE].trans);
3362
bd3d->Occluders[OCC_CUBE].show = (bd->cube_use && !bd->crawford_game);
3365
void updateMovingPieceOccPos(BoardData* bd, BoardData3d* bd3d)
3367
if (bd->drag_point >= 0)
3369
copyPoint(bd3d->Occluders[LAST_PIECE].trans, bd3d->dragPos);
3370
makeInverseTransposeMatrix(bd3d->Occluders[LAST_PIECE].invMat, bd3d->Occluders[LAST_PIECE].trans);
3372
else /* if (bd3d->moving) */
3374
copyPoint(bd3d->Occluders[LAST_PIECE].trans, bd3d->movingPos);
3376
if (bd3d->rotateMovingPiece > 0)
3377
{ /* rotate shadow as piece is put in bear off tray */
3380
bd3d->Occluders[LAST_PIECE].rotator = 1;
3381
bd3d->Occluders[LAST_PIECE].rot[1] = -90 * bd3d->rotateMovingPiece * bd->turn;
3382
makeInverseTransposeMatrix(id, bd3d->Occluders[LAST_PIECE].trans);
3383
makeInverseRotateMatrixX(bd3d->Occluders[LAST_PIECE].invMat, bd3d->Occluders[LAST_PIECE].rot[1]);
3384
matrixmult(bd3d->Occluders[LAST_PIECE].invMat, id);
3387
makeInverseTransposeMatrix(bd3d->Occluders[LAST_PIECE].invMat, bd3d->Occluders[LAST_PIECE].trans);
3391
void updatePieceOccPos(BoardData* bd, BoardData3d* bd3d)
3393
int i, j, p = OCC_PIECE;
3395
for (i = 0; i < 28; i++)
3397
for (j = 1; j <= abs(bd->points[i]); j++)
3400
break; /* Found all pieces */
3401
getPiecePos(i, j, fClockwise, bd3d->Occluders[p].trans);
3403
if (i == 26 || i == 27)
3407
bd3d->Occluders[p].rotator = 1;
3409
bd3d->Occluders[p].rot[1] = -90;
3411
bd3d->Occluders[p].rot[1] = 90;
3412
makeInverseTransposeMatrix(id, bd3d->Occluders[p].trans);
3413
makeInverseRotateMatrixX(bd3d->Occluders[p].invMat, bd3d->Occluders[p].rot[1]);
3414
matrixmult(bd3d->Occluders[p].invMat, id);
3418
makeInverseTransposeMatrix(bd3d->Occluders[p].invMat, bd3d->Occluders[p].trans);
3419
bd3d->Occluders[p].rotator = 0;
3424
if (p == LAST_PIECE)
3426
updateMovingPieceOccPos(bd, bd3d);
3427
bd3d->Occluders[p].rotator = 0;
3431
void updateFlagOccPos(BoardData* bd, BoardData3d* bd3d)
3435
freeOccluder(&bd3d->Occluders[OCC_FLAG]);
3436
initOccluder(&bd3d->Occluders[OCC_FLAG]);
3438
bd3d->Occluders[OCC_FLAG].show = 1;
3440
getFlagPos(bd, bd3d->Occluders[OCC_FLAG].trans);
3441
makeInverseTransposeMatrix(bd3d->Occluders[OCC_FLAG].invMat, bd3d->Occluders[OCC_FLAG].trans);
3444
addCube(&bd3d->Occluders[OCC_FLAG], -FLAGPOLE_WIDTH * 1.95f, -FLAG_HEIGHT, -LIFT_OFF,
3445
FLAGPOLE_WIDTH * 1.95f, FLAGPOLE_HEIGHT, LIFT_OFF * 2);
3447
/* Flag surface (approximation) */
3450
/* Change first ctlpoint to better match flag shape */
3451
float p1x = bd3d->ctlpoints[1][0][2];
3452
bd3d->ctlpoints[1][0][2] *= .7f;
3454
for (s = 0; s < S_NUMPOINTS - 1; s++)
3455
{ /* Reduce shadow size a bit to remove artifacts */
3456
float h = (bd3d->ctlpoints[s][1][1] - bd3d->ctlpoints[s][0][1]) * .92f - (FLAG_HEIGHT * .05f);
3457
float y = bd3d->ctlpoints[s][0][1] + FLAG_HEIGHT * .05f;
3458
float w = bd3d->ctlpoints[s + 1][0][0] - bd3d->ctlpoints[s][0][0];
3461
addWonkyCube(&bd3d->Occluders[OCC_FLAG], bd3d->ctlpoints[s][0][0], y, bd3d->ctlpoints[s][0][2],
3462
w, h, base_unit / 10.0f,
3463
bd3d->ctlpoints[s + 1][0][2] - bd3d->ctlpoints[s][0][2], s);
3465
bd3d->ctlpoints[1][0][2] = p1x;
3470
bd3d->Occluders[OCC_FLAG].show = 0;
3474
void updateHingeOccPos(BoardData3d* bd3d, int show3dHinges)
3476
bd3d->Occluders[OCC_HINGE1].show = bd3d->Occluders[OCC_HINGE2].show = show3dHinges;
3479
void updateOccPos(BoardData* bd)
3480
{ /* Make sure shadows are in correct place */
3481
updateCubeOccPos(bd, &bd->bd3d);
3482
updateDiceOccPos(bd, &bd->bd3d);
3483
updatePieceOccPos(bd, &bd->bd3d);
3486
void MakeShadowModel(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
3491
initOccluder(&bd3d->Occluders[OCC_BOARD]);
3493
if (prd->roundedEdges)
3495
addClosedSquare(&bd3d->Occluders[OCC_BOARD], EDGE_WIDTH - BOARD_FILLET, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2 + BOARD_FILLET * 2, TRAY_HEIGHT - EDGE_HEIGHT + BOARD_FILLET * 2, EDGE_DEPTH - LIFT_OFF);
3496
addClosedSquare(&bd3d->Occluders[OCC_BOARD], EDGE_WIDTH - BOARD_FILLET, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT - BOARD_FILLET, BASE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2 + BOARD_FILLET * 2, TRAY_HEIGHT - EDGE_HEIGHT + BOARD_FILLET * 2, EDGE_DEPTH - LIFT_OFF);
3497
addClosedSquare(&bd3d->Occluders[OCC_BOARD], TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH - BOARD_FILLET, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2 + BOARD_FILLET * 2, TRAY_HEIGHT - EDGE_HEIGHT + BOARD_FILLET * 2, EDGE_DEPTH - LIFT_OFF);
3498
addClosedSquare(&bd3d->Occluders[OCC_BOARD], TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH - BOARD_FILLET, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT - BOARD_FILLET, BASE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2 + BOARD_FILLET * 2, TRAY_HEIGHT - EDGE_HEIGHT + BOARD_FILLET * 2, EDGE_DEPTH - LIFT_OFF);
3499
addClosedSquare(&bd3d->Occluders[OCC_BOARD], TRAY_WIDTH - BOARD_FILLET, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH, BOARD_WIDTH + BOARD_FILLET * 2, TOTAL_HEIGHT - EDGE_HEIGHT * 2 + BOARD_FILLET * 2, EDGE_DEPTH - LIFT_OFF);
3500
addClosedSquare(&bd3d->Occluders[OCC_BOARD], TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH - BOARD_FILLET, EDGE_HEIGHT - BOARD_FILLET, BASE_DEPTH, BOARD_WIDTH + BOARD_FILLET * 2, TOTAL_HEIGHT - EDGE_HEIGHT * 2 + BOARD_FILLET * 2, EDGE_DEPTH - LIFT_OFF);
3501
addSquare(&bd3d->Occluders[OCC_BOARD], BOARD_FILLET, BOARD_FILLET, 0, TOTAL_WIDTH - BOARD_FILLET * 2, TOTAL_HEIGHT - BOARD_FILLET * 2, BASE_DEPTH + EDGE_DEPTH - LIFT_OFF);
3505
addClosedSquare(&bd3d->Occluders[OCC_BOARD], EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2, TRAY_HEIGHT - EDGE_HEIGHT, EDGE_DEPTH);
3506
addClosedSquare(&bd3d->Occluders[OCC_BOARD], EDGE_WIDTH, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT, BASE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2, TRAY_HEIGHT - EDGE_HEIGHT, EDGE_DEPTH);
3507
addClosedSquare(&bd3d->Occluders[OCC_BOARD], TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2, TRAY_HEIGHT - EDGE_HEIGHT, EDGE_DEPTH);
3508
addClosedSquare(&bd3d->Occluders[OCC_BOARD], TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH, TRAY_HEIGHT + MID_SIDE_GAP_HEIGHT, BASE_DEPTH, TRAY_WIDTH - EDGE_WIDTH * 2, TRAY_HEIGHT - EDGE_HEIGHT, EDGE_DEPTH);
3509
addClosedSquare(&bd3d->Occluders[OCC_BOARD], TRAY_WIDTH, EDGE_HEIGHT, BASE_DEPTH, BOARD_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT * 2, EDGE_DEPTH);
3510
addClosedSquare(&bd3d->Occluders[OCC_BOARD], TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH, EDGE_HEIGHT, BASE_DEPTH, BOARD_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT * 2, EDGE_DEPTH);
3511
addSquare(&bd3d->Occluders[OCC_BOARD], 0, 0, 0, TOTAL_WIDTH, TOTAL_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
3513
setIdMatrix(bd3d->Occluders[OCC_BOARD].invMat);
3514
bd3d->Occluders[OCC_BOARD].trans[0] = bd3d->Occluders[OCC_BOARD].trans[1] = bd3d->Occluders[OCC_BOARD].trans[2] = 0;
3516
initOccluder(&bd3d->Occluders[OCC_HINGE1]);
3517
copyOccluder(&bd3d->Occluders[OCC_HINGE1], &bd3d->Occluders[OCC_HINGE2]);
3519
addHalfTube(&bd3d->Occluders[OCC_HINGE1], HINGE_WIDTH, HINGE_HEIGHT, prd->curveAccuracy / 2);
3521
bd3d->Occluders[OCC_HINGE1].trans[0] = bd3d->Occluders[OCC_HINGE2].trans[0] = (TOTAL_WIDTH) / 2.0f;
3522
bd3d->Occluders[OCC_HINGE1].trans[2] = bd3d->Occluders[OCC_HINGE2].trans[2] = BASE_DEPTH + EDGE_DEPTH;
3523
bd3d->Occluders[OCC_HINGE1].trans[1] = ((TOTAL_HEIGHT / 2.0f) - HINGE_HEIGHT) / 2.0f;
3524
bd3d->Occluders[OCC_HINGE2].trans[1] = ((TOTAL_HEIGHT / 2.0f) - HINGE_HEIGHT + TOTAL_HEIGHT) / 2.0f;
3526
makeInverseTransposeMatrix(bd3d->Occluders[OCC_HINGE1].invMat, bd3d->Occluders[OCC_HINGE1].trans);
3527
makeInverseTransposeMatrix(bd3d->Occluders[OCC_HINGE2].invMat, bd3d->Occluders[OCC_HINGE2].trans);
3529
updateHingeOccPos(bd3d, prd->fHinges3d);
3531
initOccluder(&bd3d->Occluders[OCC_CUBE]);
3532
addSquareCentered(&bd3d->Occluders[OCC_CUBE], 0, 0, 0, DOUBLECUBE_SIZE * .88f, DOUBLECUBE_SIZE * .88f, DOUBLECUBE_SIZE * .88f);
3534
updateCubeOccPos(bd, bd3d);
3536
initOccluder(&bd3d->Occluders[OCC_DICE1]);
3537
addDice(&bd3d->Occluders[OCC_DICE1], getDiceSize(prd) / 2.0f);
3538
copyOccluder(&bd3d->Occluders[OCC_DICE1], &bd3d->Occluders[OCC_DICE2]);
3539
bd3d->Occluders[OCC_DICE1].rotator = bd3d->Occluders[OCC_DICE2].rotator = 1;
3540
updateDiceOccPos(bd, bd3d);
3542
initOccluder(&bd3d->Occluders[OCC_PIECE]);
3544
float radius = PIECE_HOLE / 2.0f;
3545
float discradius = radius * 0.8f;
3546
float lip = radius - discradius;
3547
float height = PIECE_DEPTH - 2 * lip;
3549
addCylinder(&bd3d->Occluders[OCC_PIECE], 0, 0, lip, PIECE_HOLE / 2.0f - LIFT_OFF, height, prd->curveAccuracy);
3551
for (i = OCC_PIECE; i < OCC_PIECE + 30; i++)
3553
bd3d->Occluders[i].rot[0] = 0;
3554
bd3d->Occluders[i].rot[2] = 0;
3556
copyOccluder(&bd3d->Occluders[OCC_PIECE], &bd3d->Occluders[i]);
3559
updatePieceOccPos(bd, bd3d);
3560
updateFlagOccPos(bd, bd3d);
3563
void getCheqSize(renderdata* prd)
3565
int accuracy = (prd->curveAccuracy / 4) - 1;
3567
prd->acrossCheq = prd->downCheq = 1;
3568
for (i = 1; i < accuracy; i++)
3570
if (((float)prd->acrossCheq) / prd->downCheq > .5)
3577
void preDraw3d(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
3581
bd3d->qobjTex = gluNewQuadric();
3582
gluQuadricDrawStyle(bd3d->qobjTex, GLU_FILL);
3583
gluQuadricNormals(bd3d->qobjTex, GLU_FLAT);
3584
gluQuadricTexture(bd3d->qobjTex, GL_TRUE);
3588
bd3d->qobj = gluNewQuadric();
3589
gluQuadricDrawStyle(bd3d->qobj, GLU_FILL);
3590
gluQuadricNormals(bd3d->qobj, GLU_FLAT);
3591
gluQuadricTexture(bd3d->qobj, GL_FALSE);
3594
if (bd3d->boardPoints)
3595
freeEigthPoints(&bd3d->boardPoints, prd->curveAccuracy);
3596
calculateEigthPoints(&bd3d->boardPoints, BOARD_FILLET, prd->curveAccuracy);
3599
preDrawDice(bd3d, prd);
3601
MakeShadowModel(bd, bd3d, prd);
3606
void RestrictiveDrawPiece(int pos, int depth)
3609
getPiecePos(pos, depth, fClockwise, newPos);
3610
RestrictiveDrawFrame(newPos, PIECE_HOLE, PIECE_HOLE, PIECE_DEPTH);
3613
static void RestrictiveDoDrawDice(BoardData* bd, DiceShown dicePos)
3616
float diceSize = getDiceSize(bd->rd);
3617
float overSize = diceSize * 1.5f;
3619
DiceShown tempDiceShown;
3621
tempDiceShown = bd->diceShown;
3622
bd->diceShown = dicePos;
3624
getDicePos(bd, 0, pos);
3625
pos[2] -= diceSize / 2.0f;
3626
RestrictiveDrawFrame(pos, overSize, overSize, overSize);
3628
getDicePos(bd, 1, pos);
3629
pos[2] -= diceSize / 2.0f;
3630
RestrictiveDraw(&temp, pos, overSize, overSize, overSize);
3631
EnlargeCurrentToBox(&temp);
3633
bd->diceShown = tempDiceShown;
3636
void RestrictiveDrawDice(BoardData* bd)
3640
if (numRestrictFrames == -1)
3643
if (bd->rd->fDiceArea)
3644
RestrictiveDoDrawDice(bd, DICE_BELOW_BOARD);
3646
if (bd->diceShown != DICE_ON_BOARD)
3648
tempTurn = bd->turn;
3651
RestrictiveDoDrawDice(bd, DICE_ON_BOARD);
3654
bd->turn = tempTurn;
3657
void RestrictiveDrawCube(BoardData* bd, int old_doubled, int old_cube_owner)
3660
int temp_dob = bd->doubled, temp_cow = bd->cube_owner;
3661
bd->doubled = old_doubled;
3662
bd->cube_owner = old_cube_owner;
3663
getDoubleCubePos(bd, pos);
3664
pos[2] -= DOUBLECUBE_SIZE / 2.0f;
3665
RestrictiveDrawFrame(pos, DOUBLECUBE_SIZE, DOUBLECUBE_SIZE, DOUBLECUBE_SIZE);
3666
bd->doubled = temp_dob;
3667
bd->cube_owner = temp_cow;
3668
getDoubleCubePos(bd, pos);
3669
pos[2] -= DOUBLECUBE_SIZE / 2.0f;
3670
RestrictiveDrawFrame(pos, DOUBLECUBE_SIZE, DOUBLECUBE_SIZE, DOUBLECUBE_SIZE);
3673
void RestrictiveDrawMoveIndicator(BoardData* bd)
3674
{ /* Need to redraw both indicators */
3678
getMoveIndicatorPos(bd, pos);
3679
RestrictiveDrawFrame(pos, ARROW_SIZE, ARROW_SIZE, LIFT_OFF);
3682
getMoveIndicatorPos(bd, pos);
3683
RestrictiveDrawFrame(pos, ARROW_SIZE, ARROW_SIZE, LIFT_OFF);
3686
void RestrictiveDrawBoardNumbers(BoardData3d *bd3d)
3688
#define NUMBER_WIDTH (TOTAL_WIDTH - (2 * TRAY_WIDTH))
3689
float pos[3] = {TRAY_WIDTH + (NUMBER_WIDTH / 2.0f), TOTAL_HEIGHT - EDGE_HEIGHT + (EDGE_HEIGHT / 2.0f), BASE_DEPTH + EDGE_DEPTH};
3690
float textHeight = bd3d->numberFont.height;;
3692
RestrictiveDrawFrame(pos, NUMBER_WIDTH, textHeight, LIFT_OFF);
3693
pos[1] = EDGE_HEIGHT / 2.0f;
3694
RestrictiveDrawFrame(pos, NUMBER_WIDTH, textHeight, LIFT_OFF);
3697
void RestrictiveDrawFlag(BoardData* bd)
3701
v[0] += FLAG_WIDTH / 2.0f - FLAGPOLE_WIDTH;
3702
v[2] -= FLAG_WIDTH / 2.0f;
3703
RestrictiveDrawFrame(v, FLAG_WIDTH, FLAGPOLE_HEIGHT, FLAG_WIDTH);
3706
void drawBoard(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
3708
drawTable(bd, bd3d, prd);
3710
if (bd->cube_use && !bd->crawford_game)
3711
drawDC(bd, bd3d, prd);
3713
/* Draw things in correct order so transparency works correctly */
3714
/* First pieces, then dice, then moving pieces */
3715
drawPieces(bd, bd3d, prd);
3717
if (bd3d->State == BOARD_OPEN)
3720
if (DiceShowing(bd))
3722
drawDie(bd, bd3d, 0);
3723
drawDie(bd, bd3d, 1);
3726
if (bd3d->moving || bd->drag_point >= 0)
3727
drawSpecialPieces(bd, bd3d, prd);
3730
drawFlag(bd, bd3d, prd);