~ubuntu-branches/debian/sid/gnubg/sid

« back to all changes in this revision

Viewing changes to board3d/drawboard3d.c

  • Committer: Bazaar Package Importer
  • Author(s): Russ Allbery
  • Date: 2006-12-28 10:45:05 UTC
  • mfrom: (2.1.5 feisty)
  • Revision ID: james.westby@ubuntu.com-20061228104505-4p6sxxdosrlvhgpr
Tags: 0.14.3+20060923-4
* Translation updates:
  - French, thanks Thomas Huriaux.  (Closes: #404254)
  - Spanish, thanks Javier Ruano.  (Closes: #404613)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
* drawboard3d.c
 
3
* by Jon Kinsey, 2003
 
4
*
 
5
* 3d board drawing code
 
6
*
 
7
*
 
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.
 
11
*
 
12
* This program is distributed in the hope that it will be useful,
 
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
* GNU General Public License for more details.
 
16
*
 
17
* 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
 
20
*
 
21
* $Id: drawboard3d.c,v 1.46 2006/09/21 22:24:45 Superfly_Jon Exp $
 
22
*/
 
23
 
 
24
#include "config.h"
 
25
 
 
26
#include <math.h>
 
27
#include <stdlib.h>
 
28
#include <stdio.h>
 
29
#include <memory.h>
 
30
 
 
31
#include "inc3d.h"
 
32
#include "matrix.h"
 
33
#include "shadow.h"
 
34
#include "font3d.h"
 
35
#include "gtkboard.h"
 
36
#include "drawboard.h"
 
37
#include "boardpos.h"
 
38
 
 
39
/* Used to calculate correct viewarea for board/fov angles */
 
40
typedef struct _viewArea
 
41
{
 
42
        float top;
 
43
        float bottom;
 
44
        float width;
 
45
} viewArea;
 
46
 
 
47
/* My logcube - more than 32 then return 0 (show 64) */
 
48
static int LogCube( const int n )
 
49
{
 
50
        int i;
 
51
 
 
52
        for( i = 0; ; i++ )
 
53
        if( n <= ( 1 << i ) )
 
54
                return i < 6 ? i : 0;
 
55
}
 
56
 
 
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);
 
75
 
 
76
/* Other functions */
 
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);
 
80
 
 
81
/* All the board element sizes - based on base_unit size */
 
82
 
 
83
/* Widths */
 
84
 
 
85
/* Side edge width of bearoff trays */
 
86
#define EDGE_WIDTH base_unit
 
87
 
 
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
 
92
 
 
93
#define TAKI_WIDTH .9f
 
94
 
 
95
#define TOTAL_WIDTH ((TRAY_WIDTH + BOARD_WIDTH) * 2.0f + BAR_WIDTH)
 
96
 
 
97
/* Heights */
 
98
 
 
99
/* Bottom + top edge */
 
100
#define EDGE_HEIGHT (base_unit * 1.5f)
 
101
 
 
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)
 
108
 
 
109
#define TOTAL_HEIGHT (TRAY_HEIGHT * 2.0f + MID_SIDE_GAP_HEIGHT)
 
110
 
 
111
/* Depths */
 
112
 
 
113
#define EDGE_DEPTH (base_unit * 1.95f)
 
114
#define BASE_DEPTH base_unit
 
115
 
 
116
/* Other objects */
 
117
 
 
118
#define BOARD_FILLET (base_unit / 3.0f)
 
119
 
 
120
#define DOUBLECUBE_SIZE (base_unit * 3.4f)
 
121
 
 
122
/* Dice animation step size */
 
123
#define DICE_STEP_SIZE0 (base_unit * 1.3f)
 
124
#define DICE_STEP_SIZE1 (base_unit * 1.7f)
 
125
 
 
126
#define HINGE_GAP (base_unit / 12.0f)
 
127
#define HINGE_WIDTH (base_unit / 2.0f)
 
128
#define HINGE_HEIGHT (base_unit * 7.0f)
 
129
 
 
130
#undef ARROW_SIZE
 
131
#define ARROW_SIZE (EDGE_HEIGHT * .8f)
 
132
 
 
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)
 
138
 
 
139
/* Slight offset from surface - avoid using unless necessary */
 
140
#define LIFT_OFF (base_unit / 50.0f)
 
141
 
 
142
float getBoardWidth() {return TOTAL_WIDTH;}
 
143
float getBoardHeight() {return TOTAL_HEIGHT;}
 
144
float getDiceSize(renderdata* prd) {return prd->diceSize * base_unit;}
 
145
 
 
146
extern list textures;
 
147
 
 
148
void TidyShadows(BoardData3d* bd3d)
 
149
{
 
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]);
 
156
}
 
157
 
 
158
void Tidy3dObjects(BoardData3d* bd3d, renderdata *prd)
 
159
{
 
160
        glDeleteLists(bd3d->pieceList, 1);
 
161
        glDeleteLists(bd3d->diceList, 1);
 
162
        glDeleteLists(bd3d->DCList, 1);
 
163
 
 
164
        gluDeleteQuadric(bd3d->qobjTex);
 
165
        gluDeleteQuadric(bd3d->qobj);
 
166
 
 
167
        gluDeleteNurbsRenderer(bd3d->flagNurb);
 
168
 
 
169
        if (bd3d->boardPoints)
 
170
                freeEigthPoints(&bd3d->boardPoints, prd->curveAccuracy);
 
171
 
 
172
        TidyShadows(bd3d);
 
173
        ClearTextures(bd3d);
 
174
        ListDeleteAll(&textures);
 
175
}
 
176
 
 
177
void preDrawPiece0(renderdata* prd)
 
178
{
 
179
        int i, j;
 
180
        float angle, angle2, step;
 
181
 
 
182
        float latitude;
 
183
        float new_radius;
 
184
 
 
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);
 
191
 
 
192
        step = (2 * (float)PI) / prd->curveAccuracy;
 
193
 
 
194
        /* Draw top/bottom of piece */
 
195
        circleTex(discradius, PIECE_DEPTH, prd->curveAccuracy, prd->ChequerMat[0].pTexture);
 
196
 
 
197
        if (prd->ChequerMat[0].pTexture && prd->pieceTextureType == PTT_TOP)
 
198
                glDisable(GL_TEXTURE_2D);
 
199
 
 
200
        circleRevTex(discradius, 0, prd->curveAccuracy, prd->ChequerMat[0].pTexture);
 
201
 
 
202
        /* Draw side of piece */
 
203
        glPushMatrix();
 
204
        glTranslatef(0, 0, lip);
 
205
        cylinder(radius, height, prd->curveAccuracy, prd->ChequerMat[0].pTexture);
 
206
        glPopMatrix();
 
207
 
 
208
        /* Draw edges of piece */
 
209
        angle2 = 0;
 
210
        for (j = 0; j <= prd->curveAccuracy / 4; j++)
 
211
        {
 
212
                latitude = (float)sin(angle2) * lip;
 
213
                new_radius = Dist2d(lip, latitude);
 
214
 
 
215
                angle = 0;
 
216
                for (i = 0; i < prd->curveAccuracy; i++)
 
217
                {
 
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;
 
224
 
 
225
                        angle += step;
 
226
                }
 
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];
 
233
 
 
234
                angle2 += step;
 
235
        }
 
236
 
 
237
        for (j = 0; j < prd->curveAccuracy / 4; j++)
 
238
        {
 
239
                glBegin(GL_QUAD_STRIP);
 
240
                for (i = 0; i < prd->curveAccuracy + 1; i++)
 
241
                {
 
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]);
 
246
 
 
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]);
 
251
                }
 
252
                glEnd();
 
253
                        
 
254
                glBegin(GL_QUAD_STRIP);
 
255
                for (i = 0; i < prd->curveAccuracy + 1; i++)
 
256
                {
 
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]);
 
261
 
 
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]);
 
266
                }
 
267
                glEnd();
 
268
        }
 
269
 
 
270
        /* Anti-alias piece edges */
 
271
        glLineWidth(1);
 
272
        glEnable(GL_LINE_SMOOTH);
 
273
        glEnable(GL_BLEND);
 
274
        glDepthMask(GL_FALSE);
 
275
 
 
276
        circleOutlineOutward(radius, PIECE_DEPTH - lip, prd->curveAccuracy);
 
277
        circleOutlineOutward(radius, lip, prd->curveAccuracy);
 
278
 
 
279
        glDisable(GL_BLEND);
 
280
        glDisable(GL_LINE_SMOOTH);
 
281
        glDepthMask(GL_TRUE);
 
282
 
 
283
        if (prd->ChequerMat[0].pTexture && prd->pieceTextureType == PTT_TOP)
 
284
                glEnable(GL_TEXTURE_2D);        /* Re-enable texturing */
 
285
 
 
286
        Free3d(p, prd->curveAccuracy + 1, prd->curveAccuracy / 4 + 1);
 
287
        Free3d(n, prd->curveAccuracy + 1, prd->curveAccuracy / 4 + 1);
 
288
}
 
289
 
 
290
void preDrawPiece1(renderdata* prd)
 
291
{
 
292
        float pieceRad, pieceBorder;
 
293
 
 
294
        pieceRad = PIECE_HOLE / 2.0f;
 
295
        pieceBorder = pieceRad * .9f;
 
296
 
 
297
        /* Draw top/bottom of piece */
 
298
        circleTex(pieceRad, PIECE_DEPTH, prd->curveAccuracy, prd->ChequerMat[0].pTexture);
 
299
 
 
300
        if (prd->ChequerMat[0].pTexture && prd->pieceTextureType == PTT_TOP)
 
301
                glDisable(GL_TEXTURE_2D);
 
302
 
 
303
        circleRevTex(pieceRad, 0, prd->curveAccuracy, prd->ChequerMat[0].pTexture);
 
304
 
 
305
        /* Edge of piece */
 
306
        cylinder(pieceRad, PIECE_DEPTH, prd->curveAccuracy, prd->ChequerMat[0].pTexture);
 
307
 
 
308
        /* Anti-alias piece edges */
 
309
        glLineWidth(1);
 
310
        glEnable(GL_LINE_SMOOTH);
 
311
        glEnable(GL_BLEND);
 
312
        glDepthMask(GL_FALSE);
 
313
 
 
314
        circleOutlineOutward(pieceRad, PIECE_DEPTH, prd->curveAccuracy);
 
315
        circleOutlineOutward(pieceRad, 0, prd->curveAccuracy);
 
316
 
 
317
        glDisable(GL_BLEND);
 
318
        glDisable(GL_LINE_SMOOTH);
 
319
        glDepthMask(GL_TRUE);
 
320
 
 
321
        if (prd->ChequerMat[0].pTexture && prd->pieceTextureType == PTT_TOP)
 
322
                glEnable(GL_TEXTURE_2D);        /* Re-enable texturing */
 
323
}
 
324
 
 
325
void preDrawPiece(BoardData* bd)
 
326
{
 
327
        if (bd->bd3d.pieceList)
 
328
                glDeleteLists(bd->bd3d.pieceList, 1);
 
329
 
 
330
        bd->bd3d.pieceList = glGenLists(1);
 
331
        glNewList(bd->bd3d.pieceList, GL_COMPILE);
 
332
 
 
333
        switch(bd->rd->pieceType)
 
334
        {
 
335
        case PT_ROUNDED:
 
336
                preDrawPiece0(bd->rd);
 
337
                break;
 
338
        case PT_FLAT:
 
339
                preDrawPiece1(bd->rd);
 
340
                break;
 
341
        default:
 
342
                g_print("Error: Unhandled piece type\n");
 
343
        }
 
344
 
 
345
        glEndList();
 
346
}
 
347
 
 
348
void UnitNormal(float x, float y, float z)
 
349
{
 
350
        /* Calculate the length of the vector */
 
351
        float length = (float)sqrt((x * x) + (y * y) + (z * z));
 
352
 
 
353
        /* Dividing each element by the length will result in a unit normal vector */
 
354
        glNormal3f(x / length, y / length, z / length);
 
355
}
 
356
 
 
357
void renderDice(renderdata* prd)
 
358
{
 
359
        int ns, lns;
 
360
        int i, j;
 
361
        int c;
 
362
        float lat_angle;
 
363
        float lat_step;
 
364
        float latitude;
 
365
        float new_radius;
 
366
        float radius;
 
367
        float angle, step;
 
368
        float size = getDiceSize(prd);
 
369
 
 
370
        int corner_steps = (prd->curveAccuracy / 4) + 1;
 
371
        float ***corner_points = Alloc3d(corner_steps, corner_steps, 3);
 
372
 
 
373
        radius = size / 2.0f;
 
374
        step = (2 * (float)PI) / prd->curveAccuracy;
 
375
 
 
376
        glPushMatrix();
 
377
 
 
378
        /* Draw 6 faces */
 
379
        for (c = 0; c < 6; c++)
 
380
        {
 
381
                circle(radius, radius, prd->curveAccuracy);
 
382
 
 
383
                if (c % 2 == 0)
 
384
                        glRotatef(-90, 0, 1, 0);
 
385
                else
 
386
                        glRotatef(90, 1, 0, 0);
 
387
        }
 
388
 
 
389
        lat_angle = 0;
 
390
        lns = (prd->curveAccuracy / 4);
 
391
        lat_step = ((float)PI / 2) / lns;
 
392
 
 
393
        /* Calculate corner points */
 
394
        for (i = 0; i < lns + 1; i++)
 
395
        {
 
396
                latitude = (float)sin(lat_angle) * radius;
 
397
                new_radius = Dist2d(radius, latitude);
 
398
 
 
399
                ns = (prd->curveAccuracy / 4) - i;
 
400
 
 
401
                step = ((float)PI / 2 - lat_angle) / (ns);
 
402
                angle = 0;
 
403
 
 
404
                for (j = 0; j <= ns; j++)
 
405
                {
 
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;
 
409
 
 
410
                        angle += step;
 
411
                }
 
412
                lat_angle += lat_step;
 
413
        }
 
414
 
 
415
        /* Draw 8 corners */
 
416
        for (c = 0; c < 8; c++)
 
417
        {
 
418
                glPushMatrix();
 
419
 
 
420
                glRotatef((float)(c * 90), 0, 0, 1);
 
421
 
 
422
                for (i = 0; i < prd->curveAccuracy / 4; i++)
 
423
                {
 
424
                        ns = (prd->curveAccuracy / 4) - i - 1;
 
425
 
 
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++)
 
430
                                {
 
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]);
 
435
                                }
 
436
                        glEnd();
 
437
                }
 
438
 
 
439
                glPopMatrix();
 
440
                if (c == 3)
 
441
                        glRotatef(180, 1, 0, 0);
 
442
        }
 
443
 
 
444
        /* Anti-alias dice edges */
 
445
        glLineWidth(1);
 
446
        glEnable(GL_LINE_SMOOTH);
 
447
        glEnable(GL_BLEND);
 
448
        glDepthMask(GL_FALSE);
 
449
 
 
450
        for (c = 0; c < 6; c++)
 
451
        {
 
452
                circleOutline(radius, radius + LIFT_OFF, prd->curveAccuracy);
 
453
 
 
454
                if (c % 2 == 0)
 
455
                        glRotatef(-90, 0, 1, 0);
 
456
                else
 
457
                        glRotatef(90, 1, 0, 0);
 
458
        }
 
459
        glDisable(GL_BLEND);
 
460
        glDisable(GL_LINE_SMOOTH);
 
461
        glDepthMask(GL_TRUE);
 
462
 
 
463
        glPopMatrix();
 
464
 
 
465
        Free3d(corner_points, corner_steps, corner_steps);
 
466
}
 
467
 
 
468
void renderCube(renderdata* prd, float size)
 
469
{
 
470
        int i, c;
 
471
        float ***corner_points;
 
472
        float radius = size / 7.0f;
 
473
        float ds = (size * 5.0f / 7.0f);
 
474
        float hds = (ds / 2);
 
475
 
 
476
        glPushMatrix();
 
477
 
 
478
        /* Draw 6 faces */
 
479
        for (c = 0; c < 6; c++)
 
480
        {
 
481
                glPushMatrix();
 
482
                glTranslatef(0, 0, hds + radius);
 
483
 
 
484
                glNormal3f(0, 0, 1);
 
485
 
 
486
                glBegin(GL_QUADS);
 
487
                        glVertex3f(-hds, -hds, 0);
 
488
                        glVertex3f(hds, -hds, 0);
 
489
                        glVertex3f(hds, hds, 0);
 
490
                        glVertex3f(-hds, hds, 0);
 
491
                glEnd();
 
492
 
 
493
                /* Draw 12 edges */
 
494
                for (i = 0; i < 2; i++)
 
495
                {
 
496
                        glPushMatrix();
 
497
                        glRotatef((float)(i * 90), 0, 0, 1);
 
498
 
 
499
                        glTranslatef(hds, -hds, -radius);
 
500
                        QuarterCylinder(radius, ds, prd->curveAccuracy, 0);
 
501
                        glPopMatrix();
 
502
                }
 
503
                glPopMatrix();
 
504
                if (c % 2 == 0)
 
505
                        glRotatef(-90, 0, 1, 0);
 
506
                else
 
507
                        glRotatef(90, 1, 0, 0);
 
508
        }
 
509
 
 
510
        calculateEigthPoints(&corner_points, radius, prd->curveAccuracy);
 
511
 
 
512
        /* Draw 8 corners */
 
513
        for (c = 0; c < 8; c++)
 
514
        {
 
515
                glPushMatrix();
 
516
                glTranslatef(0, 0, hds + radius);
 
517
 
 
518
                glRotatef((float)(c * 90), 0, 0, 1);
 
519
 
 
520
                glTranslatef(hds, -hds, -radius);
 
521
                glRotatef(-90, 0, 0, 1);
 
522
 
 
523
                drawCornerEigth(corner_points, radius, prd->curveAccuracy);
 
524
 
 
525
                glPopMatrix();
 
526
                if (c == 3)
 
527
                        glRotatef(180, 1, 0, 0);
 
528
        }
 
529
        glPopMatrix();
 
530
 
 
531
        freeEigthPoints(&corner_points, prd->curveAccuracy);
 
532
}
 
533
 
 
534
void preDrawDice(BoardData3d* bd3d, renderdata* prd)
 
535
{
 
536
        if (bd3d->diceList)
 
537
                glDeleteLists(bd3d->diceList, 1);
 
538
 
 
539
        bd3d->diceList = glGenLists(1);
 
540
        glNewList(bd3d->diceList, GL_COMPILE);
 
541
                renderDice(prd);
 
542
        glEndList();
 
543
 
 
544
        if (bd3d->DCList)
 
545
                glDeleteLists(bd3d->DCList, 1);
 
546
 
 
547
        bd3d->DCList = glGenLists(1);
 
548
        glNewList(bd3d->DCList, GL_COMPILE);
 
549
                renderCube(prd, DOUBLECUBE_SIZE);
 
550
        glEndList();
 
551
}
 
552
 
 
553
void getDoubleCubePos(BoardData* bd, float v[3])
 
554
{
 
555
        if (bd->doubled != 0)
 
556
        {
 
557
                v[0] = TRAY_WIDTH + BOARD_WIDTH / 2;
 
558
                if (bd->doubled != 1)
 
559
                        v[0] = TOTAL_WIDTH - v[0];
 
560
 
 
561
                v[1] = TOTAL_HEIGHT / 2.0f;
 
562
                v[2] = BASE_DEPTH + DOUBLECUBE_SIZE / 2.0f;
 
563
        }
 
564
        else
 
565
        {
 
566
                v[0] = TOTAL_WIDTH / 2.0f;
 
567
                switch(bd->cube_owner)
 
568
                {
 
569
                case 0:
 
570
                        v[1] = TOTAL_HEIGHT / 2.0f;
 
571
                        break;
 
572
                case -1:
 
573
                        v[1] = EDGE_HEIGHT + DOUBLECUBE_SIZE / 2.0f;
 
574
                        break;
 
575
                case 1:
 
576
                        v[1] = TOTAL_HEIGHT - EDGE_HEIGHT - DOUBLECUBE_SIZE / 2.0f;
 
577
                        break;
 
578
                default:
 
579
                  v[1] = 0;     /* error */
 
580
                }
 
581
                v[2] = BASE_DEPTH + EDGE_DEPTH + DOUBLECUBE_SIZE / 2.0f;
 
582
        }
 
583
}
 
584
 
 
585
void moveToDoubleCubePos(BoardData* bd)
 
586
{
 
587
        float v[3];
 
588
        getDoubleCubePos(bd, v);
 
589
        glTranslatef(v[0], v[1], v[2]);
 
590
}
 
591
 
 
592
void drawDCNumbers(BoardData* bd, diceTest* dt)
 
593
{
 
594
        int c, nice;
 
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;
 
599
 
 
600
        char* sides[] = {"4", "16", "32", "64", "8", "2"};
 
601
        int side;
 
602
 
 
603
        glLineWidth(1);
 
604
        glPushMatrix();
 
605
        for (c = 0; c < 6; c++)
 
606
        {
 
607
                if (c < 3)
 
608
                        side = c;
 
609
                else
 
610
                        side = 8 - c;
 
611
                /* Nicer top numbers */
 
612
                nice = (side == dt->top);
 
613
 
 
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]))
 
618
                {
 
619
                        if (nice)
 
620
                                glDisable(GL_DEPTH_TEST);
 
621
 
 
622
                        glPushMatrix();
 
623
                        glTranslatef(0, 0, depth + !nice * LIFT_OFF);
 
624
 
 
625
                        glPrintCube(&bd->bd3d, sides[side]);
 
626
 
 
627
                        glPopMatrix();
 
628
                        if (nice)
 
629
                                glEnable(GL_DEPTH_TEST);
 
630
                }
 
631
                if (c % 2 == 0)
 
632
                        glRotatef(-90, 0, 1, 0);
 
633
                else
 
634
                        glRotatef(90, 1, 0, 0);
 
635
        }
 
636
        glPopMatrix();
 
637
}
 
638
 
 
639
void DrawDCNumbers(BoardData* bd)
 
640
{
 
641
        diceTest dt;
 
642
        int extraRot = 0;
 
643
        int rotDC[6][3] = {{1, 0, 0}, {2, 0, 3}, {0, 0, 0}, {0, 3, 1}, {0, 1, 0}, {3, 0, 3}};
 
644
 
 
645
        int cubeIndex;
 
646
        /* Rotate to correct number + rotation */
 
647
        if (!bd->doubled)
 
648
        {
 
649
                cubeIndex = LogCube(bd->cube);
 
650
                extraRot = bd->cube_owner + 1;
 
651
        }
 
652
        else
 
653
        {
 
654
                cubeIndex = LogCube(bd->cube * 2);      /* Show offered cube value */
 
655
                extraRot = bd->turn + 1;
 
656
        }
 
657
 
 
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);
 
661
 
 
662
        initDT(&dt, rotDC[cubeIndex][0], rotDC[cubeIndex][1], rotDC[cubeIndex][2] + extraRot);
 
663
 
 
664
        setMaterial(&bd->rd->CubeNumberMat);
 
665
        glNormal3f(0, 0, 1);
 
666
 
 
667
        drawDCNumbers(bd, &dt);
 
668
}
 
669
 
 
670
void drawDC(BoardData* bd, BoardData3d* bd3d, renderdata* prd)
 
671
{
 
672
        glPushMatrix();
 
673
        moveToDoubleCubePos(bd);
 
674
 
 
675
        setMaterial(&prd->CubeMat);
 
676
        glCallList(bd3d->DCList);
 
677
 
 
678
        DrawDCNumbers(bd);
 
679
 
 
680
        glPopMatrix();
 
681
}
 
682
 
 
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 */
 
692
 
 
693
void drawDots(BoardData3d *bd3d, float diceSize, float dotOffset, diceTest* dt, int showFront, int drawOutline)
 
694
{
 
695
        int dot;
 
696
        int c, nd;
 
697
        int* dp;
 
698
        float radius;
 
699
        float ds = (diceSize * 5.0f / 7.0f);
 
700
        float hds = (ds / 2);
 
701
        float x, y;
 
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);
 
706
 
 
707
        radius = diceSize / 7.0f;
 
708
 
 
709
        glPushMatrix();
 
710
        for (c = 0; c < 6; c++)
 
711
        {
 
712
                if (c < 3)
 
713
                        dot = c;
 
714
                else
 
715
                        dot = 8 - c;
 
716
 
 
717
                /* Make sure top dot looks nice */
 
718
                nd = !bd3d->shakingDice && (dot == dt->top);
 
719
 
 
720
                if (bd3d->shakingDice
 
721
                        || (showFront && dot != dt->bottom && dot != dt->side[0])
 
722
                        || (!showFront && dot != dt->top && dot != dt->side[2]))
 
723
                {
 
724
                        if (nd)
 
725
                                glDisable(GL_DEPTH_TEST);
 
726
                        glPushMatrix();
 
727
                        glTranslatef(0, 0, hds + radius);
 
728
 
 
729
                        glNormal3f(0, 0, 1);
 
730
 
 
731
                        /* Show all the dots for this number */
 
732
                        dp = dots[dot];
 
733
                        do
 
734
                        {
 
735
                                x = (dot_pos[dp[0]] * ds) / 100;
 
736
                                y = (dot_pos[dp[1]] * ds) / 100;
 
737
 
 
738
                                glPushMatrix();
 
739
                                glTranslatef(x - hds, y - hds, 0);
 
740
 
 
741
                                glEnable(GL_TEXTURE_2D);
 
742
                                glBindTexture(GL_TEXTURE_2D, bd3d->dotTexture);
 
743
 
 
744
                                glBegin(GL_QUADS);
 
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);
 
749
                                glEnd();
 
750
 
 
751
                                glPopMatrix();
 
752
 
 
753
                                dp += 2;
 
754
                        } while (*dp);
 
755
 
 
756
                        glPopMatrix();
 
757
                        if (nd)
 
758
                                glEnable(GL_DEPTH_TEST);
 
759
                }
 
760
 
 
761
                if (c % 2 == 0)
 
762
                        glRotatef(-90, 0, 1, 0);
 
763
                else
 
764
                        glRotatef(90, 1, 0, 0);
 
765
        }
 
766
        glPopMatrix();
 
767
}
 
768
 
 
769
void getDicePos(BoardData* bd, int num, float v[3])
 
770
{
 
771
        float size = getDiceSize(bd->rd);
 
772
        if (bd->diceShown == DICE_BELOW_BOARD)
 
773
        {       /* Show below board */
 
774
                v[0] = size * 1.5f;
 
775
                v[1] = -size / 2.0f;
 
776
                v[2] = size / 2.0f;
 
777
 
 
778
                if (bd->turn == 1)
 
779
                        v[0] += TOTAL_WIDTH - size * 4;
 
780
                if (num == 1)
 
781
                        v[0] += size;   /* Place 2nd dice by 1st */
 
782
        }
 
783
        else
 
784
        {
 
785
                v[0] = bd->bd3d.dicePos[num][0];
 
786
                if (bd->turn == 1)
 
787
                        v[0] = TOTAL_WIDTH - v[0];      /* Dice on right side */
 
788
 
 
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;
 
791
        }
 
792
}
 
793
 
 
794
void moveToDicePos(BoardData* bd, int num)
 
795
{
 
796
        float v[3];
 
797
        getDicePos(bd, num, v);
 
798
        glTranslatef(v[0], v[1], v[2]);
 
799
 
 
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);
 
803
        }
 
804
}
 
805
 
 
806
void drawDice(BoardData* bd, int num)
 
807
{
 
808
        int value;
 
809
        int rotDice[6][2] = {{0, 0}, {0, 1}, {3, 0}, {1, 0}, {0, 3}, {2, 0}};
 
810
        int diceCol = (bd->turn == 1);
 
811
        int z;
 
812
        float diceSize = getDiceSize(bd->rd);
 
813
        diceTest dt;
 
814
        Material* pDiceMat = &bd->rd->DiceMat[diceCol];
 
815
        Material whiteMat;
 
816
        SetupSimpleMat(&whiteMat, 1, 1, 1);
 
817
 
 
818
        value = bd->diceRoll[num];
 
819
        value--;        /* Zero based for array access */
 
820
 
 
821
        /* Get dice rotation */
 
822
        if (bd->diceShown == DICE_BELOW_BOARD)
 
823
                z = 0;
 
824
        else
 
825
                z = ((int)bd->bd3d.dicePos[num][2] + 45) / 90;
 
826
 
 
827
        /* Orientate dice correctly */
 
828
        glRotatef(90.0f * rotDice[value][0], 1, 0, 0);
 
829
        glRotatef(90.0f * rotDice[value][1], 0, 1, 0);
 
830
 
 
831
        /* DT = dice test, use to work out which way up the dice is */
 
832
        initDT(&dt, rotDice[value][0], rotDice[value][1], z);
 
833
 
 
834
        if (pDiceMat->alphaBlend)
 
835
        {       /* Draw back of dice separately */
 
836
                glCullFace(GL_FRONT);
 
837
                glEnable(GL_BLEND);
 
838
 
 
839
                /* Draw dice */
 
840
                setMaterial(pDiceMat);
 
841
                glCallList(bd->bd3d.diceList);
 
842
 
 
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);
 
849
 
 
850
                glCullFace(GL_BACK);
 
851
        }
 
852
        /* Draw dice */
 
853
        setMaterial(&bd->rd->DiceMat[diceCol]);
 
854
        glCallList(bd->bd3d.diceList);
 
855
 
 
856
        /* Draw (front) dots */
 
857
        glEnable(GL_BLEND);
 
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);
 
862
 
 
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);
 
867
 
 
868
        /* Restore blending defaults */
 
869
        glDisable(GL_BLEND);
 
870
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
871
}
 
872
 
 
873
void getPiecePos(int point, int pos, int swap, float v[3])
 
874
{
 
875
        if (point == 0 || point == 25)
 
876
        {       /* bars */
 
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;
 
881
 
 
882
                if (point == 25)
 
883
                {
 
884
                        v[1] -= DOUBLECUBE_SIZE / 2.0f + (PIECE_HOLE + PIECE_GAP_HEIGHT) * (pos + .5f);
 
885
                }
 
886
                else
 
887
                {
 
888
                        v[1] += DOUBLECUBE_SIZE / 2.0f + (PIECE_HOLE + PIECE_GAP_HEIGHT) * (pos + .5f);
 
889
                }
 
890
                v[1] -= PIECE_HOLE / 2.0f;
 
891
        }
 
892
        else if (point >= 26)
 
893
        {       /* homes */
 
894
                v[2] = BASE_DEPTH;
 
895
                if (swap)
 
896
                        v[0] = TRAY_WIDTH / 2.0f;
 
897
                else
 
898
                        v[0] = TOTAL_WIDTH - TRAY_WIDTH / 2.0f;
 
899
 
 
900
                if (point == 26)
 
901
                        v[1] = EDGE_HEIGHT + (PIECE_DEPTH * 1.2f * (pos - 1));  /* 1.3 gives a gap between pieces */
 
902
                else
 
903
                        v[1] = TOTAL_HEIGHT - EDGE_HEIGHT - PIECE_DEPTH - (PIECE_DEPTH * 1.2f * (pos - 1));
 
904
        }
 
905
        else
 
906
        {
 
907
                v[2] = BASE_DEPTH + ((pos - 1) / 5) * PIECE_DEPTH;
 
908
 
 
909
                if (point < 13)
 
910
                {
 
911
                        if (swap)
 
912
                                point = 13 - point;
 
913
 
 
914
                        if (pos > 10)
 
915
                                pos -= 10;
 
916
 
 
917
                        if (pos > 5)
 
918
                                v[1] = EDGE_HEIGHT + (PIECE_HOLE / 2.0f) + (PIECE_HOLE + PIECE_GAP_HEIGHT) * (pos - 5 - 1);
 
919
                        else
 
920
                                v[1] = EDGE_HEIGHT + (PIECE_HOLE + PIECE_GAP_HEIGHT) * (pos - 1);
 
921
 
 
922
                        v[0] = TRAY_WIDTH + PIECE_HOLE * (12 - point);
 
923
                        if (point < 7)
 
924
                                v[0] += BAR_WIDTH;
 
925
                }
 
926
                else
 
927
                {
 
928
                        if (swap)
 
929
                                point = (24 + 13) - point;
 
930
 
 
931
                        if (pos > 10)
 
932
                                pos -= 10;
 
933
 
 
934
                        if (pos > 5)
 
935
                                v[1] = TOTAL_HEIGHT - EDGE_HEIGHT - (PIECE_HOLE / 2.0f) - PIECE_HOLE - (PIECE_HOLE + PIECE_GAP_HEIGHT) * (pos - 5 - 1);
 
936
                        else
 
937
                                v[1] = TOTAL_HEIGHT - EDGE_HEIGHT - PIECE_HOLE - (PIECE_HOLE + PIECE_GAP_HEIGHT) * (pos - 1);
 
938
 
 
939
                        v[0] = TRAY_WIDTH + PIECE_HOLE * (point - 13);
 
940
                        if (point > 18)
 
941
                                v[0] += BAR_WIDTH;
 
942
                }
 
943
                v[0] += PIECE_HOLE / 2.0f;
 
944
        }
 
945
        v[2] += LIFT_OFF * 2;
 
946
 
 
947
        /* Move to centre of piece */
 
948
        if (point < 26)
 
949
        {
 
950
                v[1] += PIECE_HOLE / 2.0f;
 
951
        }
 
952
        else
 
953
        {       /* Home pieces are sideways */
 
954
                if (point == 27)
 
955
                        v[1] += PIECE_DEPTH;
 
956
                v[2] += PIECE_HOLE / 2.0f;
 
957
        }
 
958
}
 
959
 
 
960
void renderSpecialPieces(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
 
961
{
 
962
        if (bd->drag_point >= 0)
 
963
        {
 
964
                glPushMatrix();
 
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);
 
969
                glPopMatrix();
 
970
        }
 
971
 
 
972
        if (bd3d->moving)
 
973
        {
 
974
                glPushMatrix();
 
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);
 
981
                glPopMatrix();
 
982
        }
 
983
}
 
984
 
 
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);
 
988
 
 
989
        if (blend)
 
990
        {       /* Draw back of piece separately */
 
991
                glCullFace(GL_FRONT);
 
992
                glEnable(GL_BLEND);
 
993
                renderSpecialPieces(bd, bd3d, prd);
 
994
                glCullFace(GL_BACK);
 
995
                glEnable(GL_BLEND);
 
996
        }
 
997
        renderSpecialPieces(bd, bd3d, prd);
 
998
 
 
999
        if (blend)
 
1000
                glDisable(GL_BLEND);
 
1001
}
 
1002
 
 
1003
void drawPiece(BoardData3d* bd3d, int point, int pos)
 
1004
{
 
1005
        float v[3];
 
1006
        glPushMatrix();
 
1007
 
 
1008
        getPiecePos(point, pos, fClockwise, v);
 
1009
        glTranslatef(v[0], v[1], v[2]);
 
1010
 
 
1011
        /* Home pieces are sideways */
 
1012
        if (point == 26)
 
1013
                glRotatef(-90, 1, 0, 0);
 
1014
        if (point == 27)
 
1015
                glRotatef(90, 1, 0, 0);
 
1016
 
 
1017
        glRotatef((float)bd3d->pieceRotation[point][pos - 1], 0, 0, 1);
 
1018
        glCallList(bd3d->pieceList);
 
1019
 
 
1020
        glPopMatrix();
 
1021
}
 
1022
 
 
1023
void drawPieces(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
 
1024
{
 
1025
        int i, j;
 
1026
        int blend = (prd->ChequerMat[0].alphaBlend) || (prd->ChequerMat[1].alphaBlend);
 
1027
 
 
1028
        if (blend)
 
1029
        {       /* Draw back of piece separately */
 
1030
                glCullFace(GL_FRONT);
 
1031
 
 
1032
                setMaterial(&prd->ChequerMat[0]);
 
1033
                for (i = 0; i < 28; i++)
 
1034
                {
 
1035
                        for (j = 1; j <= -bd->points[i]; j++)
 
1036
                        {
 
1037
                                glEnable(GL_BLEND);
 
1038
                                drawPiece(bd3d, i, j);
 
1039
                        }
 
1040
                }
 
1041
                setMaterial(&prd->ChequerMat[1]);
 
1042
                for (i = 0; i < 28; i++)
 
1043
                {
 
1044
                        for (j = 1; j <= bd->points[i]; j++)
 
1045
                        {
 
1046
                                glEnable(GL_BLEND);
 
1047
                                drawPiece(bd3d, i, j);
 
1048
                        }
 
1049
                }
 
1050
                glCullFace(GL_BACK);
 
1051
        }
 
1052
 
 
1053
        setMaterial(&prd->ChequerMat[0]);
 
1054
        for (i = 0; i < 28; i++)
 
1055
        {
 
1056
                for (j = 1; j <= -bd->points[i]; j++)
 
1057
                {
 
1058
                        if (blend)
 
1059
                                glEnable(GL_BLEND);
 
1060
                        drawPiece(bd3d, i, j);
 
1061
                }
 
1062
        }
 
1063
        setMaterial(&prd->ChequerMat[1]);
 
1064
        for (i = 0; i < 28; i++)
 
1065
        {
 
1066
                for (j = 1; j <= bd->points[i]; j++)
 
1067
                {
 
1068
                        if (blend)
 
1069
                                glEnable(GL_BLEND);
 
1070
                        drawPiece(bd3d, i, j);
 
1071
                }
 
1072
        }
 
1073
        if (blend)
 
1074
                glDisable(GL_BLEND);
 
1075
 
 
1076
        if (bd->DragTargetHelp)
 
1077
        {       /* highlight target points */
 
1078
                glPolygonMode(GL_FRONT, GL_LINE);
 
1079
                SetColour3d(0, 1, 0, 0);        /* Nice bright green... */
 
1080
 
 
1081
                for (i = 0; i <= 3; i++)
 
1082
                {
 
1083
                        int target = bd->iTargetHelpPoints[i];
 
1084
                        if (target != -1)
 
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);
 
1089
                        }
 
1090
                }
 
1091
                glPolygonMode(GL_FRONT, GL_FILL);
 
1092
        }
 
1093
}
 
1094
 
 
1095
void DrawNumbers(BoardData* bd, int sides)
 
1096
{
 
1097
        int i;
 
1098
        char num[3];
 
1099
        float x;
 
1100
        float textHeight = bd->bd3d.numberFont.height;
 
1101
        int n;
 
1102
 
 
1103
        glPushMatrix();
 
1104
        glTranslatef(0, (EDGE_HEIGHT - textHeight) / 2.0f, BASE_DEPTH + EDGE_DEPTH);
 
1105
        x = TRAY_WIDTH - PIECE_HOLE / 2.0f;
 
1106
 
 
1107
        for (i = 0; i < 12; i++)
 
1108
        {
 
1109
                x += PIECE_HOLE;
 
1110
                if (i == 6)
 
1111
                        x += BAR_WIDTH;
 
1112
 
 
1113
                if ((i < 6 && (sides & 1)) || (i >= 6 && (sides & 2)))
 
1114
                {
 
1115
                        glPushMatrix();
 
1116
                        glTranslatef(x, 0, 0);
 
1117
                        if (!fClockwise)
 
1118
                                n = 12 - i;
 
1119
                        else
 
1120
                                n = i + 1;
 
1121
 
 
1122
                        if (bd->turn == -1 && bd->rd->fDynamicLabels)
 
1123
                                n = 25 - n;
 
1124
 
 
1125
                        sprintf(num, "%d", n);
 
1126
                        glPrintPointNumbers(&bd->bd3d, num);
 
1127
                        glPopMatrix();
 
1128
                }
 
1129
        }
 
1130
 
 
1131
        glPopMatrix();
 
1132
        glPushMatrix();
 
1133
        glTranslatef(0, TOTAL_HEIGHT - textHeight - (EDGE_HEIGHT - textHeight) / 2.0f, BASE_DEPTH + EDGE_DEPTH);
 
1134
        x = TRAY_WIDTH - PIECE_HOLE / 2.0f;
 
1135
 
 
1136
        for (i = 0; i < 12; i++)
 
1137
        {
 
1138
                x += PIECE_HOLE;
 
1139
                if (i == 6)
 
1140
                        x += BAR_WIDTH;
 
1141
                if ((i < 6 && (sides & 1)) || (i >= 6 && (sides & 2)))
 
1142
                {
 
1143
                        glPushMatrix();
 
1144
                        glTranslatef(x, 0, 0);
 
1145
                        if (!fClockwise)
 
1146
                                n = 13 + i;
 
1147
                        else
 
1148
                                n = 24 - i;
 
1149
 
 
1150
                        if (bd->turn == -1 && bd->rd->fDynamicLabels)
 
1151
                                n = 25 - n;
 
1152
 
 
1153
                        sprintf(num, "%d", n);
 
1154
                        glPrintPointNumbers(&bd->bd3d, num);
 
1155
                        glPopMatrix();
 
1156
                }
 
1157
        }
 
1158
        glPopMatrix();
 
1159
}
 
1160
 
 
1161
void drawNumbers(BoardData* bd, int sides)
 
1162
{
 
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);
 
1168
 
 
1169
        glLineWidth(1);
 
1170
        DrawNumbers(bd, sides);
 
1171
        glEnable(GL_DEPTH_TEST);
 
1172
}
 
1173
 
 
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;
 
1178
        float x, y;
 
1179
 
 
1180
        if (p)
 
1181
        {
 
1182
                x = TRAY_WIDTH - EDGE_WIDTH + PIECE_HOLE * i;
 
1183
                y = -LIFT_OFF;
 
1184
        }
 
1185
        else
 
1186
        {
 
1187
                x = TRAY_WIDTH - EDGE_WIDTH + BOARD_WIDTH - (PIECE_HOLE * i);
 
1188
                y = TOTAL_HEIGHT - EDGE_HEIGHT * 2 + LIFT_OFF;
 
1189
                w = -w;
 
1190
                h = -h;
 
1191
        }
 
1192
 
 
1193
        glPushMatrix();
 
1194
        if (prd->bgInTrays)
 
1195
                glTranslatef(EDGE_WIDTH, EDGE_HEIGHT, BASE_DEPTH);
 
1196
        else
 
1197
        {
 
1198
                x -= TRAY_WIDTH - EDGE_WIDTH;
 
1199
                glTranslatef(TRAY_WIDTH, EDGE_HEIGHT, BASE_DEPTH);
 
1200
        }
 
1201
 
 
1202
        if (prd->roundedPoints)
 
1203
        {       /* Draw rounded point ends */
 
1204
                float xoff;
 
1205
 
 
1206
                w = w * TAKI_WIDTH;
 
1207
                y += w / 2.0f;
 
1208
                h -= w / 2.0f;
 
1209
 
 
1210
                if (p)
 
1211
                        xoff = x + (PIECE_HOLE / 2.0f);
 
1212
                else
 
1213
                        xoff = x - (PIECE_HOLE / 2.0f);
 
1214
 
 
1215
                /* Draw rounded semi-circle end of point (with correct texture co-ords) */
 
1216
                {
 
1217
                        int i;
 
1218
                        float angle, step;
 
1219
                        float radius = w / 2.0f;
 
1220
 
 
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);
 
1226
                         
 
1227
                        glVertex3f(xoff, y, 0);
 
1228
                        for (i = 0; i <= prd->curveAccuracy / 2; i++)
 
1229
                        {
 
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);
 
1232
                                angle -= step;
 
1233
                        }
 
1234
                        glEnd();
 
1235
                }
 
1236
                /* Move rest of point in slighlty */
 
1237
                if (p)
 
1238
                        x -= -((PIECE_HOLE * (1 - TAKI_WIDTH)) / 2.0f);
 
1239
                else
 
1240
                        x -= ((PIECE_HOLE * (1 - TAKI_WIDTH)) / 2.0f);
 
1241
        }
 
1242
 
 
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);
 
1251
        glEnd();
 
1252
 
 
1253
        glPopMatrix();
 
1254
}
 
1255
 
 
1256
void drawPoints(renderdata* prd)
 
1257
{
 
1258
        /* texture unit value */
 
1259
        float tuv;
 
1260
 
 
1261
        /* Don't worry about depth testing (but set depth values) */
 
1262
        glDepthFunc(GL_ALWAYS);
 
1263
 
 
1264
        setMaterial(&prd->BaseMat);
 
1265
        if (prd->bgInTrays)
 
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);
 
1267
        else
 
1268
                drawChequeredRect(TRAY_WIDTH, EDGE_HEIGHT, BASE_DEPTH, BOARD_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT * 2, prd->acrossCheq, prd->downCheq, prd->BaseMat.pTexture);
 
1269
 
 
1270
        /* Ignore depth values when drawing points */
 
1271
        glDepthMask(GL_FALSE);
 
1272
 
 
1273
        if (prd->PointMat[0].pTexture)
 
1274
                tuv = (TEXTURE_SCALE) / prd->PointMat[0].pTexture->width;
 
1275
        else
 
1276
                tuv = 0;
 
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);
 
1284
 
 
1285
        glLineWidth(1);
 
1286
        glEnable(GL_LINE_SMOOTH);
 
1287
        glEnable(GL_BLEND);
 
1288
 
 
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);
 
1295
 
 
1296
        glDisable(GL_BLEND);
 
1297
        glDisable(GL_LINE_SMOOTH);
 
1298
 
 
1299
        if (prd->PointMat[1].pTexture)
 
1300
                tuv = (TEXTURE_SCALE) / prd->PointMat[1].pTexture->width;
 
1301
        else
 
1302
                tuv = 0;
 
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);
 
1310
 
 
1311
        glEnable(GL_LINE_SMOOTH);
 
1312
        glEnable(GL_BLEND);
 
1313
 
 
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);
 
1320
 
 
1321
        glDisable(GL_BLEND);
 
1322
        glDisable(GL_LINE_SMOOTH);
 
1323
 
 
1324
        /* Restore depth buffer settings */
 
1325
        glDepthFunc(GL_LEQUAL);
 
1326
        glDepthMask(GL_TRUE);
 
1327
}
 
1328
 
 
1329
void drawBase(renderdata* prd, int sides)
 
1330
{
 
1331
        if (sides & 1)
 
1332
                drawPoints(prd);
 
1333
 
 
1334
        if (sides & 2)
 
1335
        {
 
1336
                /* Rotate right board around */
 
1337
                glPushMatrix();
 
1338
                glTranslatef(TOTAL_WIDTH, TOTAL_HEIGHT, 0);
 
1339
                glRotatef(180, 0, 0, 1);
 
1340
                drawPoints(prd);
 
1341
                glPopMatrix();
 
1342
        }
 
1343
}
 
1344
 
 
1345
void drawHinge(BoardData3d *bd3d, renderdata *prd, float height)
 
1346
{
 
1347
        setMaterial(&prd->HingeMat);
 
1348
 
 
1349
        glMatrixMode(GL_TEXTURE);
 
1350
        glPushMatrix();
 
1351
        glScalef(1, HINGE_SEGMENTS, 1);
 
1352
        glMatrixMode(GL_MODELVIEW);
 
1353
 
 
1354
        glPushMatrix();
 
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);
 
1358
 
 
1359
        glMatrixMode(GL_TEXTURE);
 
1360
        glPopMatrix();
 
1361
        glMatrixMode(GL_MODELVIEW);
 
1362
 
 
1363
        glRotatef(180, 1, 0, 0);
 
1364
        gluDisk(bd3d->qobjTex, 0, HINGE_WIDTH, prd->curveAccuracy, 1);
 
1365
 
 
1366
        glPopMatrix();
 
1367
}
 
1368
 
 
1369
void tidyEdges(renderdata* prd)
 
1370
{       /* Anti-alias board edges */
 
1371
        setMaterial(&prd->BoxMat);
 
1372
 
 
1373
        glLineWidth(1);
 
1374
        glEnable(GL_BLEND);
 
1375
        glEnable(GL_LINE_SMOOTH);
 
1376
        glDepthMask(GL_FALSE);
 
1377
 
 
1378
        glNormal3f(0, 0, 1);
 
1379
 
 
1380
        glBegin(GL_LINES);
 
1381
                if (prd->roundedEdges)
 
1382
                {
 
1383
                        /* bar */
 
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);
 
1387
 
 
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);
 
1391
 
 
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);
 
1396
 
 
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);
 
1401
 
 
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);
 
1406
 
 
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);
 
1411
 
 
1412
                }
 
1413
                else
 
1414
                {
 
1415
                        /* bar */
 
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);
 
1418
 
 
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);
 
1421
 
 
1422
                        /* left bear off tray */
 
1423
                        glVertex3f(0, 0, BASE_DEPTH + EDGE_DEPTH);
 
1424
                        glVertex3f(0, TOTAL_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
 
1425
 
 
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);
 
1430
 
 
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);
 
1435
 
 
1436
                        glVertex3f(TRAY_WIDTH, EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
 
1437
                        glVertex3f(TRAY_WIDTH, TOTAL_HEIGHT - EDGE_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
 
1438
 
 
1439
                        /* right bear off tray */
 
1440
                        glVertex3f(TOTAL_WIDTH, 0, BASE_DEPTH + EDGE_DEPTH);
 
1441
                        glVertex3f(TOTAL_WIDTH, TOTAL_HEIGHT, BASE_DEPTH + EDGE_DEPTH);
 
1442
 
 
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);
 
1447
 
 
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);
 
1452
 
 
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);
 
1455
                }
 
1456
 
 
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);
 
1463
 
 
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);
 
1469
        glEnd();
 
1470
        glDepthMask(GL_TRUE);
 
1471
        glDisable(GL_BLEND);
 
1472
        glDisable(GL_LINE_SMOOTH);
 
1473
}
 
1474
 
 
1475
void getMoveIndicatorPos(BoardData* bd, float pos[3])
 
1476
{
 
1477
        if (!fClockwise)
 
1478
                pos[0] = TOTAL_WIDTH - TRAY_WIDTH + ARROW_SIZE / 2.0f;
 
1479
        else
 
1480
                pos[0] = TRAY_WIDTH - ARROW_SIZE / 2.0f;
 
1481
 
 
1482
        if (bd->turn == 1)
 
1483
                pos[1] = EDGE_HEIGHT / 2.0f;
 
1484
        else
 
1485
                pos[1] = TOTAL_HEIGHT - EDGE_HEIGHT / 2.0f;
 
1486
 
 
1487
        pos[2] = BASE_DEPTH + EDGE_DEPTH;
 
1488
}
 
1489
 
 
1490
void showMoveIndicator(BoardData* bd)
 
1491
{
 
1492
        float pos[3];
 
1493
/* ARROW_UNIT used to draw sub-bits of arrow */
 
1494
#define ARROW_UNIT (ARROW_SIZE / 4.0f)
 
1495
 
 
1496
        setMaterial(&bd->rd->ChequerMat[(bd->turn == 1)]);
 
1497
 
 
1498
        glDisable(GL_DEPTH_TEST);
 
1499
        glDisable(GL_TEXTURE_2D);
 
1500
        glNormal3f(0, 0, 1);
 
1501
 
 
1502
        glPushMatrix();
 
1503
        getMoveIndicatorPos(bd, pos);
 
1504
        glTranslatef(pos[0], pos[1], pos[2]);
 
1505
        if (fClockwise)
 
1506
                glRotatef(180, 0, 0, 1);
 
1507
 
 
1508
        glBegin(GL_QUADS);
 
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);
 
1513
        glEnd();
 
1514
        glBegin(GL_TRIANGLES);
 
1515
                glVertex2f(0, ARROW_UNIT * 2);
 
1516
                glVertex2f(0, -ARROW_UNIT * 2);
 
1517
                glVertex2f(ARROW_UNIT * 2, 0);
 
1518
        glEnd();
 
1519
 
 
1520
        /* Outline arrow */
 
1521
        SetColour3d(0, 0, 0, 1);        /* Black outline */
 
1522
 
 
1523
        glLineWidth(.5f);
 
1524
        glEnable(GL_BLEND);
 
1525
        glEnable(GL_LINE_SMOOTH);
 
1526
 
 
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);
 
1535
        glEnd();
 
1536
 
 
1537
        glDisable(GL_BLEND);
 
1538
        glDisable(GL_LINE_SMOOTH);
 
1539
 
 
1540
        glPopMatrix();
 
1541
        glEnable(GL_DEPTH_TEST);
 
1542
}
 
1543
 
 
1544
void ClearScreen(renderdata *prd)
 
1545
{
 
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);
 
1548
}
 
1549
 
 
1550
void RotateClosingBoard(BoardData3d* bd3d, renderdata *prd)
 
1551
{
 
1552
        float rotAngle = 90;
 
1553
        float trans = getBoardHeight() * .4f;
 
1554
        float zoom = .2f;
 
1555
 
 
1556
        glPopMatrix();
 
1557
 
 
1558
        ClearScreen(prd);
 
1559
 
 
1560
        if ((bd3d->State == BOARD_OPENING) || (bd3d->State == BOARD_CLOSING))
 
1561
        {
 
1562
                rotAngle *= bd3d->perOpen;
 
1563
                trans *= bd3d->perOpen;
 
1564
                zoom *= bd3d->perOpen;
 
1565
        }
 
1566
        glPushMatrix();
 
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);
 
1571
}
 
1572
 
 
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);
 
1576
 
 
1577
#define DrawBottom(x, y, z, w, h)\
 
1578
        glNormal3f(0, -1, 0);\
 
1579
        glBegin(GL_QUADS);\
 
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);\
 
1588
        glEnd();
 
1589
 
 
1590
#define DrawTop(x, y, z, w, h)\
 
1591
        glNormal3f(0, 1, 0);\
 
1592
        glBegin(GL_QUADS);\
 
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);\
 
1601
        glEnd();
 
1602
 
 
1603
#define DrawLeft(x, y, z, w, h)\
 
1604
        glNormal3f(-1, 0, 0);\
 
1605
        glBegin(GL_QUADS);\
 
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);\
 
1614
        glEnd();
 
1615
 
 
1616
#define DrawRight(x, y, z, w, h)\
 
1617
        glNormal3f(1, 0, 0);\
 
1618
        glBegin(GL_QUADS);\
 
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);\
 
1627
        glEnd();
 
1628
 
 
1629
#define TextureOffset(s, t) if (tuv)\
 
1630
{\
 
1631
        glMatrixMode(GL_TEXTURE);\
 
1632
        glPushMatrix();\
 
1633
        glTranslatef(s, t, 0);\
 
1634
        glMatrixMode(GL_MODELVIEW);\
 
1635
}
 
1636
 
 
1637
#define TextureReset if (tuv)\
 
1638
{\
 
1639
        glMatrixMode(GL_TEXTURE);\
 
1640
        glPopMatrix();\
 
1641
        glMatrixMode(GL_MODELVIEW);\
 
1642
}
 
1643
 
 
1644
/* texture unit value */
 
1645
float tuv;
 
1646
 
 
1647
void InsideFillet(float x, float y, float z, float w, float h, float radius, int accuracy, Texture* texture, float curveTextOff)
 
1648
{
 
1649
        /* Left */
 
1650
        DrawRight(x + BOARD_FILLET, y + BOARD_FILLET, BASE_DEPTH, h, EDGE_DEPTH - BOARD_FILLET);
 
1651
        /* Top */
 
1652
        DrawBottom(x + BOARD_FILLET, y + h + BOARD_FILLET, BASE_DEPTH, w, EDGE_DEPTH - BOARD_FILLET + LIFT_OFF);
 
1653
        /* Bottom */
 
1654
        DrawTop(x + BOARD_FILLET, y + BOARD_FILLET, BASE_DEPTH, w, EDGE_DEPTH - BOARD_FILLET)
 
1655
        /* Right */
 
1656
        DrawLeft(x + w + BOARD_FILLET, y + BOARD_FILLET, BASE_DEPTH + LIFT_OFF, h, EDGE_DEPTH - BOARD_FILLET);
 
1657
 
 
1658
        if (tuv)
 
1659
        {
 
1660
                glMatrixMode(GL_TEXTURE);
 
1661
                glPushMatrix();
 
1662
                glTranslatef((x + curveTextOff) * tuv, (y + h + radius * 2) * tuv, 0);
 
1663
                glRotatef(-90, 0, 0, 1);
 
1664
                glMatrixMode(GL_MODELVIEW);
 
1665
        }
 
1666
        glPushMatrix();
 
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);
 
1671
        glPopMatrix();
 
1672
        TextureReset
 
1673
 
 
1674
        TextureOffset(x * tuv, (y + curveTextOff) * tuv);
 
1675
        glPushMatrix();
 
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);
 
1680
        glPopMatrix();
 
1681
        TextureReset
 
1682
 
 
1683
        if (tuv)
 
1684
        {
 
1685
                glMatrixMode(GL_TEXTURE);
 
1686
                glPushMatrix();
 
1687
                glTranslatef((x + w + radius * 2 - curveTextOff) * tuv, y * tuv, 0);
 
1688
                glRotatef(90, 0, 0, 1);
 
1689
                glMatrixMode(GL_MODELVIEW);
 
1690
        }
 
1691
        glPushMatrix();
 
1692
        glTranslatef(x + w + radius * 2, y, z - radius);
 
1693
        glRotatef(-90, 0, 1, 0);
 
1694
        QuarterCylinderSplayed(radius, h + radius * 2, accuracy, texture);
 
1695
        glPopMatrix();
 
1696
        TextureReset
 
1697
 
 
1698
        TextureOffset((x + radius) * tuv, (y + h + radius * 2) * tuv);
 
1699
        glPushMatrix();
 
1700
        glTranslatef(x + radius, y + h + radius * 2, z - radius);
 
1701
        glRotatef(-90, 0, 0, 1);
 
1702
        QuarterCylinderSplayedRev(radius, w, accuracy, texture);
 
1703
        glPopMatrix();
 
1704
        TextureReset
 
1705
}
 
1706
 
 
1707
void drawTable(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
 
1708
{
 
1709
        float st, ct, dInc, curveTextOff = 0;
 
1710
        tuv = 0;
 
1711
 
 
1712
        if (bd3d->State != BOARD_OPEN)
 
1713
                RotateClosingBoard(bd3d, prd);
 
1714
 
 
1715
        /* Draw background */
 
1716
        setMaterial(&prd->BackGroundMat);
 
1717
 
 
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);
 
1722
 
 
1723
        /* Right side of board */
 
1724
        if (!prd->fHinges3d)
 
1725
                drawBase(prd, 1 | 2);
 
1726
        else
 
1727
                drawBase(prd, 2);
 
1728
        setMaterial(&prd->BoxMat);
 
1729
 
 
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);
 
1732
 
 
1733
if (prd->roundedEdges)
 
1734
{
 
1735
        if (prd->BoxMat.pTexture)
 
1736
        {
 
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;
 
1742
        }
 
1743
 
 
1744
        /* Right edge */
 
1745
        glBegin(GL_QUADS);
 
1746
                /* Front Face */
 
1747
                glNormal3f(0, 0, 1);
 
1748
 
 
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);
 
1753
 
 
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);
 
1758
        glEnd();
 
1759
 
 
1760
        /* Right face */
 
1761
        DrawRight(TOTAL_WIDTH, BOARD_FILLET, 0, TOTAL_HEIGHT - BOARD_FILLET * 2, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
 
1762
 
 
1763
        if (tuv)
 
1764
        {
 
1765
                glMatrixMode(GL_TEXTURE);
 
1766
                glPushMatrix();
 
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);
 
1770
        }
 
1771
        glPushMatrix();
 
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);
 
1775
        glPopMatrix();
 
1776
        TextureReset
 
1777
 
 
1778
        if (tuv)
 
1779
        {
 
1780
                glMatrixMode(GL_TEXTURE);
 
1781
                glPushMatrix();
 
1782
                glTranslatef((TOTAL_WIDTH - BOARD_FILLET) * tuv, (TOTAL_HEIGHT - (BOARD_FILLET - curveTextOff)) * tuv, 0);
 
1783
                glRotatef(90, 0, 0, 1);
 
1784
                glMatrixMode(GL_MODELVIEW);
 
1785
        }
 
1786
        glPushMatrix();
 
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);
 
1790
        glPopMatrix();
 
1791
        TextureReset
 
1792
 
 
1793
        if (tuv)
 
1794
        {
 
1795
                glMatrixMode(GL_TEXTURE);
 
1796
                glPushMatrix();
 
1797
                glTranslatef((TOTAL_WIDTH - BOARD_FILLET + curveTextOff) * tuv, (TOTAL_HEIGHT - BOARD_FILLET) * tuv, 0);
 
1798
                glRotatef(-90, 0, 0, 1);
 
1799
                glMatrixMode(GL_MODELVIEW);
 
1800
        }
 
1801
        glPushMatrix();
 
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);
 
1806
        glPopMatrix();
 
1807
        TextureReset
 
1808
 
 
1809
        glPushMatrix();
 
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);
 
1813
        glPopMatrix();
 
1814
 
 
1815
        glPushMatrix();
 
1816
        glTranslatef(TOTAL_WIDTH - BOARD_FILLET, TOTAL_HEIGHT - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
 
1817
        drawCornerEigth(bd3d->boardPoints, BOARD_FILLET, prd->curveAccuracy);
 
1818
        glPopMatrix();
 
1819
 
 
1820
        /* Top + bottom edges */
 
1821
        if (!prd->fHinges3d)
 
1822
        {
 
1823
                glBegin(GL_QUADS);
 
1824
                        /* Front Face */
 
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);
 
1830
 
 
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);
 
1835
                glEnd();
 
1836
 
 
1837
                DrawBottom(BOARD_FILLET, 0, 0, TOTAL_WIDTH - BOARD_FILLET * 2, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
 
1838
 
 
1839
                glBegin(GL_QUADS);
 
1840
                        /* Front Face */
 
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);
 
1846
 
 
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);
 
1851
                glEnd();
 
1852
                /* Top Face */
 
1853
                DrawTop(BOARD_FILLET, TOTAL_HEIGHT, 0, TOTAL_WIDTH - BOARD_FILLET * 2, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
 
1854
 
 
1855
                TextureOffset(BOARD_FILLET * tuv, BOARD_FILLET * tuv);
 
1856
                glPushMatrix();
 
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);
 
1860
                glPopMatrix();
 
1861
                TextureReset
 
1862
 
 
1863
                TextureOffset(BOARD_FILLET * tuv, (TOTAL_HEIGHT - (BOARD_FILLET - curveTextOff)) * tuv);
 
1864
                glPushMatrix();
 
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);
 
1869
                glPopMatrix();
 
1870
                TextureReset
 
1871
        }
 
1872
        else
 
1873
        {
 
1874
                glBegin(GL_QUADS);
 
1875
                        /* Front Face */
 
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);
 
1881
                glEnd();
 
1882
 
 
1883
                DrawBottom((TOTAL_WIDTH + HINGE_GAP) / 2.0f, 0, 0, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
 
1884
 
 
1885
                glBegin(GL_QUADS);
 
1886
                        /* Front Face */
 
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);
 
1892
                glEnd();
 
1893
                        /* Top Face */
 
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)
 
1895
 
 
1896
                glBegin(GL_QUADS);
 
1897
 
 
1898
                        if (bd3d->State != BOARD_OPEN)
 
1899
                        {
 
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);
 
1906
                        }
 
1907
                glEnd();
 
1908
 
 
1909
                TextureOffset(((TOTAL_WIDTH + HINGE_GAP) / 2.0f) * tuv, BOARD_FILLET * tuv);
 
1910
                glPushMatrix();
 
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);
 
1914
                glPopMatrix();
 
1915
                TextureReset
 
1916
 
 
1917
                TextureOffset(((TOTAL_WIDTH + HINGE_GAP) / 2.0f) * tuv, (TOTAL_HEIGHT - (BOARD_FILLET - curveTextOff)) * tuv);
 
1918
                glPushMatrix();
 
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);
 
1923
                glPopMatrix();
 
1924
                TextureReset
 
1925
        }
 
1926
        /* Bar */
 
1927
        if (!prd->fHinges3d)
 
1928
        {
 
1929
                glBegin(GL_QUADS);
 
1930
                        /* Front Face */
 
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);
 
1936
 
 
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);
 
1941
                glEnd();
 
1942
        }
 
1943
        else
 
1944
        {
 
1945
                glBegin(GL_QUADS);
 
1946
                        /* Front Face */
 
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);
 
1952
 
 
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);
 
1957
                glEnd();
 
1958
        }
 
1959
        /* Bear-off edge */
 
1960
        glBegin(GL_QUADS);
 
1961
                /* Front Face */
 
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);
 
1967
 
 
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);
 
1972
        glEnd();
 
1973
 
 
1974
        glBegin(GL_QUADS);
 
1975
                /* Front Face */
 
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);
 
1981
        glEnd();
 
1982
 
 
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);
 
1985
 
 
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);
 
1987
}
 
1988
else
 
1989
{
 
1990
        /* Right edge */
 
1991
        drawBox(BOX_SPLITTOP, TOTAL_WIDTH - EDGE_WIDTH, 0, 0, EDGE_WIDTH, TOTAL_HEIGHT, BASE_DEPTH + EDGE_DEPTH, prd->BoxMat.pTexture);
 
1992
 
 
1993
        /* Top + bottom edges */
 
1994
        if (!prd->fHinges3d)
 
1995
        {
 
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);
 
1998
        }
 
1999
        else
 
2000
        {
 
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);
 
2003
        }
 
2004
 
 
2005
        /* Bar */
 
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);
 
2008
        else
 
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);
 
2010
 
 
2011
        /* Bear-off edge */
 
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);
 
2014
}
 
2015
 
 
2016
        if (prd->fLabels)
 
2017
                drawNumbers(bd, 2);
 
2018
 
 
2019
        /* Left side of board*/
 
2020
        glPushMatrix();
 
2021
 
 
2022
        if (bd3d->State != BOARD_OPEN)
 
2023
        {
 
2024
                float boardAngle = 180;
 
2025
                if ((bd3d->State == BOARD_OPENING) || (bd3d->State == BOARD_CLOSING))
 
2026
                        boardAngle *= bd3d->perOpen;
 
2027
 
 
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));
 
2031
        }
 
2032
 
 
2033
        if (prd->fHinges3d)
 
2034
                drawBase(prd, 1);
 
2035
 
 
2036
        setMaterial(&prd->BoxMat);
 
2037
 
 
2038
        if (!prd->bgInTrays)
 
2039
                drawSplitRect(EDGE_WIDTH - LIFT_OFF, EDGE_HEIGHT, BASE_DEPTH, PIECE_HOLE, TOTAL_HEIGHT - EDGE_HEIGHT * 2, prd->BoxMat.pTexture);
 
2040
 
 
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);
 
2045
                /* logo */
 
2046
                glPushMatrix();
 
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);
 
2051
                glBegin(GL_QUADS);
 
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);
 
2056
                glEnd();
 
2057
                glPopMatrix();
 
2058
                setMaterial(&prd->BoxMat);
 
2059
        }
 
2060
 
 
2061
if (prd->roundedEdges)
 
2062
{
 
2063
        /* Left edge */
 
2064
        glBegin(GL_QUADS);
 
2065
                /* Front Face */
 
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);
 
2071
 
 
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);
 
2076
        glEnd();
 
2077
        /* Left Face */
 
2078
        DrawLeft(0, BOARD_FILLET, 0, TOTAL_HEIGHT - BOARD_FILLET * 2, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
 
2079
 
 
2080
        if (tuv)
 
2081
        {
 
2082
                glMatrixMode(GL_TEXTURE);
 
2083
                glPushMatrix();
 
2084
                glTranslatef(BOARD_FILLET * tuv, (BOARD_FILLET - curveTextOff) * tuv, 0);
 
2085
                glRotatef(-90, 0, 0, 1);
 
2086
                glMatrixMode(GL_MODELVIEW);
 
2087
        }
 
2088
        glPushMatrix();
 
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);
 
2093
        glPopMatrix();
 
2094
        TextureReset
 
2095
 
 
2096
        if (tuv)
 
2097
        {
 
2098
                glMatrixMode(GL_TEXTURE);
 
2099
                glPushMatrix();
 
2100
                glTranslatef((BOARD_FILLET - curveTextOff) * tuv, (TOTAL_HEIGHT - (BOARD_FILLET - curveTextOff)) * tuv, 0);
 
2101
                glRotatef(90, 0, 0, 1);
 
2102
                glMatrixMode(GL_MODELVIEW);
 
2103
        }
 
2104
        glPushMatrix();
 
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);
 
2109
        glPopMatrix();
 
2110
        TextureReset
 
2111
 
 
2112
        if (tuv)
 
2113
        {
 
2114
                glMatrixMode(GL_TEXTURE);
 
2115
                glPushMatrix();
 
2116
                glTranslatef((BOARD_FILLET - curveTextOff) * tuv, BOARD_FILLET * tuv, 0);
 
2117
                glRotatef(90, 0, 0, 1);
 
2118
        }
 
2119
        glMatrixMode(GL_MODELVIEW);
 
2120
        glPushMatrix();
 
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);
 
2124
        glPopMatrix();
 
2125
        TextureReset
 
2126
 
 
2127
        glPushMatrix();
 
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);
 
2131
        glPopMatrix();
 
2132
 
 
2133
        glPushMatrix();
 
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);
 
2137
        glPopMatrix();
 
2138
 
 
2139
        if (prd->fHinges3d)
 
2140
        {       /* Top + bottom edges and bar */
 
2141
                glBegin(GL_QUADS);
 
2142
                        /* Front Face */
 
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);
 
2148
                glEnd();
 
2149
 
 
2150
                DrawBottom(BOARD_FILLET, 0, 0, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET);
 
2151
 
 
2152
                glBegin(GL_QUADS);
 
2153
                        /* Front Face */
 
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);
 
2159
                        /* Top Face */
 
2160
                glEnd();
 
2161
 
 
2162
                DrawTop(BOARD_FILLET, TOTAL_HEIGHT, 0, (TOTAL_WIDTH - HINGE_GAP) / 2.0f - BOARD_FILLET, BASE_DEPTH + EDGE_DEPTH - BOARD_FILLET)
 
2163
 
 
2164
                glBegin(GL_QUADS);
 
2165
                        if (bd3d->State != BOARD_OPEN)
 
2166
                        {
 
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);
 
2173
                        }
 
2174
                glEnd();
 
2175
 
 
2176
                TextureOffset(BOARD_FILLET * tuv, BOARD_FILLET * tuv);
 
2177
                glPushMatrix();
 
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);
 
2181
                glPopMatrix();
 
2182
                TextureReset
 
2183
 
 
2184
                TextureOffset(BOARD_FILLET * tuv, (TOTAL_HEIGHT - (BOARD_FILLET - curveTextOff)) * tuv);
 
2185
                glPushMatrix();
 
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);
 
2190
                glPopMatrix();
 
2191
                TextureReset
 
2192
 
 
2193
                glBegin(GL_QUADS);
 
2194
                        /* Front Face */
 
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);
 
2200
 
 
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);
 
2205
                glEnd();
 
2206
        }
 
2207
 
 
2208
/* Bear-off edge */
 
2209
        glBegin(GL_QUADS);
 
2210
                /* Front Face */
 
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);
 
2216
 
 
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);
 
2221
        glEnd();
 
2222
 
 
2223
        glBegin(GL_QUADS);
 
2224
                /* Front Face */
 
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);
 
2230
        glEnd();
 
2231
 
 
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);
 
2234
 
 
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);
 
2236
}
 
2237
else
 
2238
{
 
2239
        /* Left edge */
 
2240
        drawBox(BOX_SPLITTOP, 0, 0, 0, EDGE_WIDTH, TOTAL_HEIGHT, BASE_DEPTH + EDGE_DEPTH, prd->BoxMat.pTexture);
 
2241
 
 
2242
        if (prd->fHinges3d)
 
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);
 
2246
        }
 
2247
 
 
2248
        if (prd->fHinges3d)
 
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);
 
2250
 
 
2251
        /* Bear-off edge */
 
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);
 
2254
}
 
2255
 
 
2256
        if (prd->fHinges3d)
 
2257
        {
 
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);
 
2260
 
 
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);
 
2265
                }
 
2266
        }
 
2267
 
 
2268
        if (prd->fLabels)
 
2269
                drawNumbers(bd, 1);
 
2270
 
 
2271
        glPopMatrix();
 
2272
 
 
2273
        if (prd->showMoveIndicator)
 
2274
                showMoveIndicator(bd);
 
2275
}
 
2276
 
 
2277
int DiceShowing(BoardData* bd)
 
2278
{
 
2279
        return ((bd->diceShown == DICE_ON_BOARD && bd->diceRoll[0]) ||
 
2280
                (bd->rd->fDiceArea && bd->diceShown == DICE_BELOW_BOARD));
 
2281
}
 
2282
 
 
2283
void drawPick(BoardData* bd)
 
2284
{       /* Draw all the objects on the board to see if any have been selected */
 
2285
        int i, j;
 
2286
        float barHeight;
 
2287
 
 
2288
        /* pieces */
 
2289
        for (i = 0; i < 28; i++)
 
2290
        {
 
2291
                glLoadName(i);
 
2292
                for (j = 1; j <= abs(bd->points[i]); j++)
 
2293
                        drawPiece(&bd->bd3d, i, j);
 
2294
        }
 
2295
 
 
2296
        /* points */
 
2297
        for (i = 0; i < 6; i++)
 
2298
        {
 
2299
                glLoadName(fClockwise ? i + 1 : 12 - i);
 
2300
                drawRect(TRAY_WIDTH + PIECE_HOLE * i, EDGE_HEIGHT, BASE_DEPTH, PIECE_HOLE, POINT_HEIGHT, 0);
 
2301
 
 
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);
 
2304
 
 
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);
 
2307
 
 
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);
 
2310
        }
 
2311
        /* bars + homes */
 
2312
        barHeight = (PIECE_HOLE + PIECE_GAP_HEIGHT) * 4;
 
2313
        glLoadName(25);
 
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);
 
2316
        glLoadName(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);
 
2319
 
 
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);
 
2325
 
 
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);
 
2330
 
 
2331
        /* Dice areas */
 
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);
 
2336
 
 
2337
        /* Dice */
 
2338
        if (DiceShowing(bd))
 
2339
        {
 
2340
                glLoadName(POINT_DICE);
 
2341
                glPushMatrix();
 
2342
                moveToDicePos(bd, 0);
 
2343
                drawCube(getDiceSize(bd->rd) * .95f);
 
2344
                glPopMatrix();
 
2345
                glPushMatrix();
 
2346
                moveToDicePos(bd, 1);
 
2347
                drawCube(getDiceSize(bd->rd) * .95f);
 
2348
                glPopMatrix();
 
2349
        }
 
2350
 
 
2351
        /* Double Cube */
 
2352
        glPushMatrix();
 
2353
        glLoadName(POINT_CUBE);
 
2354
        moveToDoubleCubePos(bd);
 
2355
        drawCube(DOUBLECUBE_SIZE * .95f);
 
2356
        glPopMatrix();
 
2357
}
 
2358
 
 
2359
int NearestHit(int hits, GLuint* ptr)
 
2360
{
 
2361
        int i, sel = -1;
 
2362
        GLuint names;
 
2363
        float minDepth = 0, depth;
 
2364
 
 
2365
        for (i = 0; i < hits; i++)
 
2366
        {       /* for each hit */
 
2367
                names = *ptr++;
 
2368
                depth = (float) *ptr++/0x7fffffff;
 
2369
                ptr++;  /* Skip max depth */
 
2370
                if (i == 0 || depth < minDepth)
 
2371
                {       /* if closer */
 
2372
                        minDepth = depth;
 
2373
                        sel = *ptr;
 
2374
                }
 
2375
                ptr += names;
 
2376
        }
 
2377
        return sel;
 
2378
}
 
2379
 
 
2380
void getProjectedPos(int x, int y, float atDepth, float pos[3])
 
2381
{       /* Work out where point (x, y) projects to at depth atDepth */
 
2382
        GLint viewport[4];
 
2383
        GLdouble mvmatrix[16], projmatrix[16];
 
2384
        double nX, nY, nZ, fX, fY, fZ, zRange;
 
2385
 
 
2386
        glGetIntegerv (GL_VIEWPORT, viewport);
 
2387
        glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
 
2388
        glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);
 
2389
 
 
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);
 
2392
 
 
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);
 
2397
}
 
2398
 
 
2399
void getProjectedPieceDragPos(int x, int y, float pos[3])
 
2400
{
 
2401
        getProjectedPos(x, y, BASE_DEPTH + EDGE_DEPTH + DOUBLECUBE_SIZE + LIFT_OFF * 3, pos);
 
2402
}
 
2403
 
 
2404
void calculateBackgroundSize(BoardData3d *bd3d, int viewport[4])
 
2405
{
 
2406
        float pos1[3], pos2[3], pos3[3];
 
2407
 
 
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);
 
2411
 
 
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];
 
2416
}
 
2417
 
 
2418
void getFlagPos(BoardData* bd, float v[3])
 
2419
{
 
2420
        v[0] = (TRAY_WIDTH + BOARD_WIDTH) / 2.0f;
 
2421
        v[1] = TOTAL_HEIGHT / 2.0f;
 
2422
        v[2] = BASE_DEPTH + EDGE_DEPTH;
 
2423
 
 
2424
        if (bd->turn == -1)     /* Move to other side of board */
 
2425
                v[0] += BOARD_WIDTH + BAR_WIDTH;
 
2426
}
 
2427
 
 
2428
void waveFlag(float ctlpoints[S_NUMPOINTS][T_NUMPOINTS][3], float wag)
 
2429
{
 
2430
        int i, j;
 
2431
 
 
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;
 
2436
}
 
2437
 
 
2438
void drawFlagPick(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
 
2439
{
 
2440
        int s;
 
2441
        float v[3];
 
2442
 
 
2443
        waveFlag(bd3d->ctlpoints, bd3d->flagWaved);
 
2444
 
 
2445
        glLoadName(POINT_RESIGN);
 
2446
 
 
2447
        glPushMatrix();
 
2448
 
 
2449
        getFlagPos(bd, v);
 
2450
        glTranslatef(v[0], v[1], v[2]);
 
2451
 
 
2452
        /* Draw flag surface (approximation) */
 
2453
        glBegin(GL_QUAD_STRIP);
 
2454
        for (s = 0; s < S_NUMPOINTS; s++)
 
2455
        {
 
2456
                glVertex3fv(bd3d->ctlpoints[s][1]);
 
2457
                glVertex3fv(bd3d->ctlpoints[s][0]);
 
2458
        }
 
2459
        glEnd();
 
2460
 
 
2461
        /* Draw flag pole */
 
2462
        glTranslatef(0, -FLAG_HEIGHT, 0);
 
2463
 
 
2464
        glRotatef(-90, 1, 0, 0);
 
2465
        gluCylinder(bd3d->qobj, FLAGPOLE_WIDTH, FLAGPOLE_WIDTH, FLAGPOLE_HEIGHT, prd->curveAccuracy, 1);
 
2466
 
 
2467
        circleRev(FLAGPOLE_WIDTH, 0, prd->curveAccuracy);
 
2468
        circleRev(FLAGPOLE_WIDTH * 2, FLAGPOLE_HEIGHT, prd->curveAccuracy);
 
2469
 
 
2470
        glPopMatrix();
 
2471
}
 
2472
 
 
2473
static void drawPointPick(int point)
 
2474
{       /* Draw sub parts of point to work out which part of point clicked */
 
2475
        int i;
 
2476
        float pos[3];
 
2477
 
 
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)
 
2482
 
 
2483
                getPiecePos(point, 1, fClockwise, pos);
 
2484
 
 
2485
                glLoadName(0);
 
2486
                if (point > 12)
 
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);
 
2488
                else
 
2489
                        drawRect(pos[0] - (PIECE_HOLE / 2.0f), pos[1] - (PIECE_HOLE / 2.0f), pos[2], PIECE_HOLE, SPLIT_HEIGHT, 0);
 
2490
 
 
2491
                glLoadName(1);
 
2492
                if (point > 12)
 
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);
 
2494
                else
 
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);
 
2496
 
 
2497
                for (i = 2; i < 6; i++)
 
2498
                {
 
2499
                        /* Only 3 places for bar */
 
2500
                        if ((point == 0 || point == 25) && i == 4)
 
2501
                                break;
 
2502
                        getPiecePos(point, i, fClockwise, pos);
 
2503
                        glLoadName(i);
 
2504
                        drawRect(pos[0] - (PIECE_HOLE / 2.0f), pos[1] - (PIECE_HOLE / 2.0f), pos[2], PIECE_HOLE, PIECE_HOLE + PIECE_GAP_HEIGHT, 0);
 
2505
                }
 
2506
                /* extra bit */
 
2507
/*              glLoadName(i);
 
2508
                if (point > 12)
 
2509
                {
 
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);
 
2512
                }
 
2513
                else
 
2514
                {
 
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);
 
2517
                }
 
2518
*/      }
 
2519
}
 
2520
 
 
2521
/* 20 allows for 5 hit records (more than enough) */
 
2522
#define BUFSIZE 20
 
2523
 
 
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];
 
2527
        GLint hits;
 
2528
        GLint viewport[4];
 
2529
 
 
2530
        glSelectBuffer(BUFSIZE, selectBuf);
 
2531
        glRenderMode(GL_SELECT);
 
2532
        glInitNames();
 
2533
        glPushName(0);
 
2534
 
 
2535
        glGetIntegerv (GL_VIEWPORT, viewport);
 
2536
 
 
2537
        glMatrixMode(GL_PROJECTION);
 
2538
        glPushMatrix();
 
2539
 
 
2540
        glLoadIdentity();
 
2541
        gluPickMatrix(x, y, 1, 1, viewport);
 
2542
 
 
2543
        /* Setup projection matrix - using saved values */
 
2544
        if (prd->planView)
 
2545
                glOrtho(-bd3d->horFrustrum, bd3d->horFrustrum, -bd3d->vertFrustrum, bd3d->vertFrustrum, 0, 5);
 
2546
        else
 
2547
                glFrustum(-bd3d->horFrustrum, bd3d->horFrustrum, -bd3d->vertFrustrum, bd3d->vertFrustrum, zNear, zFar);
 
2548
 
 
2549
        glMatrixMode(GL_MODELVIEW);
 
2550
        glLoadMatrixf(bd3d->modelMatrix);
 
2551
 
 
2552
        if (bd->resigned)
 
2553
        {       /* Flag showing - just pick this */
 
2554
                drawFlagPick(bd, &bd->bd3d, bd->rd);
 
2555
        }
 
2556
        else
 
2557
        {
 
2558
                /* Either draw all the objects of just a single point */
 
2559
                if (point == -1)
 
2560
                        drawPick(bd);
 
2561
                else
 
2562
                        drawPointPick(point);
 
2563
        }
 
2564
 
 
2565
        glPopName();
 
2566
 
 
2567
        hits = glRenderMode(GL_RENDER);
 
2568
 
 
2569
        glMatrixMode(GL_PROJECTION);
 
2570
        glPopMatrix() ;
 
2571
        glMatrixMode(GL_MODELVIEW);
 
2572
        
 
2573
        return NearestHit(hits, (GLuint*)selectBuf);
 
2574
}
 
2575
 
 
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 */
 
2578
        float point[3];
 
2579
        float w, h, xDist, yDist;
 
2580
        float xDiff, yDiff;
 
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;
 
2586
        int yDir = 0;
 
2587
 
 
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);
 
2592
 
 
2593
        /* Only rotate piece going home */
 
2594
        *pRotate = -1;
 
2595
 
 
2596
        /* Swap boards if displaying other way around */
 
2597
        if (fClockwise)
 
2598
        {
 
2599
                int swap[] = {0, 2, 1, 4, 3, 5};
 
2600
                fromBoard = swap[fromBoard];
 
2601
                toBoard = swap[toBoard];
 
2602
        }
 
2603
 
 
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;
 
2610
        }
 
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;
 
2616
        }
 
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);
 
2622
                yDir = 1;
 
2623
        }
 
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);
 
2629
                yDir = 1;
 
2630
        }
 
2631
        else if (fromBoard == toBoard)
 
2632
        {
 
2633
                if (fromBoard <= 2)
 
2634
                {
 
2635
                        if (fClockwise)
 
2636
                        {
 
2637
                                fromPoint = 13 - fromPoint;
 
2638
                                toPoint = 13 - toPoint;
 
2639
                        }
 
2640
 
 
2641
                        if (fromPoint < toPoint)
 
2642
                                toPoint--;
 
2643
                        else
 
2644
                                fromPoint--;
 
2645
 
 
2646
                        fromPoint = 12 - fromPoint;
 
2647
                        toPoint = 12 - toPoint;
 
2648
                }
 
2649
                else
 
2650
                {
 
2651
                        if (fClockwise)
 
2652
                        {
 
2653
                                fromPoint = 24 + 13 - fromPoint;
 
2654
                                toPoint = 24 + 13 - toPoint;
 
2655
                        }
 
2656
 
 
2657
                        if (fromPoint < toPoint)
 
2658
                                fromPoint++;
 
2659
                        else
 
2660
                                toPoint++;
 
2661
                        fromPoint = fromPoint - 13;
 
2662
                        toPoint = toPoint - 13;
 
2663
                }
 
2664
                obj1 = TRAY_WIDTH + PIECE_HOLE * fromPoint;
 
2665
                obj2 = TRAY_WIDTH + PIECE_HOLE * toPoint;
 
2666
                if ((fromBoard == 1) || (fromBoard == 4))
 
2667
                {
 
2668
                        obj1 += BAR_WIDTH;
 
2669
                        obj2 += BAR_WIDTH;
 
2670
                }
 
2671
 
 
2672
                objHeight = BASE_DEPTH + PIECE_DEPTH * 3;
 
2673
        }
 
2674
        else
 
2675
        {
 
2676
                if (fromPoint == 0 || fromPoint == 25)
 
2677
                {       /* Move from bar */
 
2678
                        if (!fClockwise)
 
2679
                        {
 
2680
                                obj1 = TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH;
 
2681
                                if (fromPoint == 0)
 
2682
                                {
 
2683
                                        obj2 = TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH;
 
2684
                                        if (toPoint > 20)
 
2685
                                                obj2 += PIECE_HOLE * (toPoint - 20);
 
2686
                                }
 
2687
                                else
 
2688
                                {
 
2689
                                        obj2 = TRAY_WIDTH + BOARD_WIDTH + BAR_WIDTH;
 
2690
                                        if (toPoint < 5)
 
2691
                                                obj2 += PIECE_HOLE * (5 - toPoint);
 
2692
                                }
 
2693
                        }
 
2694
                        else
 
2695
                        {
 
2696
                                obj1 = TRAY_WIDTH + BOARD_WIDTH;
 
2697
                                if (fromPoint == 0)
 
2698
                                {
 
2699
                                        obj2 = TRAY_WIDTH + PIECE_HOLE * (25 - toPoint);
 
2700
                                        if (toPoint > 19)
 
2701
                                                obj2 += PIECE_HOLE;
 
2702
                                }
 
2703
                                else
 
2704
                                {
 
2705
                                        obj2 = TRAY_WIDTH + PIECE_HOLE * toPoint;
 
2706
                                        if (toPoint < 6)
 
2707
                                                obj2 += PIECE_HOLE;
 
2708
                                }
 
2709
                        }
 
2710
                        objHeight = BASE_DEPTH + EDGE_DEPTH + DOUBLECUBE_SIZE;
 
2711
                }
 
2712
                else
 
2713
                {       /* Move home */
 
2714
                        if (!fClockwise)
 
2715
                        {
 
2716
                                if (toPoint == 26)
 
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);
 
2720
                        }
 
2721
                        else
 
2722
                        {
 
2723
                                if (toPoint == 26)
 
2724
                                        obj1 = TRAY_WIDTH + PIECE_HOLE * (fromPoint - 1);
 
2725
                                else /* (toPoint == 27) */
 
2726
                                        obj1 = TRAY_WIDTH + PIECE_HOLE * (24 - fromPoint);
 
2727
                        }
 
2728
 
 
2729
                        if (!fClockwise)
 
2730
                                obj2 = TOTAL_WIDTH - TRAY_WIDTH + EDGE_WIDTH;
 
2731
                        else
 
2732
                                obj2 = TRAY_WIDTH - EDGE_WIDTH;
 
2733
 
 
2734
                        *pRotate = 0;
 
2735
                        objHeight = BASE_DEPTH + EDGE_DEPTH + getDiceSize(bd->rd);
 
2736
                }
 
2737
        }
 
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;
 
2742
        }
 
2743
 
 
2744
        /* Now setup path object */
 
2745
        /* Start point */
 
2746
        initPath(p, start);
 
2747
 
 
2748
        /* obstacle height */
 
2749
        point[2] = objHeight;
 
2750
 
 
2751
        if (yDir)
 
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;
 
2759
 
 
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);
 
2766
 
 
2767
                if (h > w)
 
2768
                {
 
2769
                        point[0] = start[0] + xDiff * bar1Ratio;
 
2770
                        point[1] = obj1;
 
2771
                }
 
2772
                else
 
2773
                {
 
2774
                        point[0] = start[0] + xDist * (h / w);
 
2775
                        point[1] = start[1] + yDist * (h / w);
 
2776
                }
 
2777
                addPathSegment(p, PATH_CURVE_9TO12, point);
 
2778
 
 
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];
 
2784
 
 
2785
                /* 3rd point - moved along from 2nd one */
 
2786
                if (h > w)
 
2787
                {
 
2788
                        point[0] = start[0] + xDiff * bar2Ratio;
 
2789
                        point[1] = obj2;
 
2790
                }
 
2791
                else
 
2792
                {
 
2793
                        point[0] = end[0] - xDist * (h / w);
 
2794
                        point[1] = end[1] - yDist * (h / w);
 
2795
                }
 
2796
                addPathSegment(p, PATH_LINE, point);
 
2797
        }
 
2798
        else
 
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;
 
2806
 
 
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);
 
2812
 
 
2813
                /* 2nd point - moved up from 1st one */
 
2814
                if (h > w)
 
2815
                {
 
2816
                        point[0] = obj1;
 
2817
                        point[1] = start[1] + yDiff * bar1Ratio;
 
2818
                }
 
2819
                else
 
2820
                {
 
2821
                        point[0] = start[0] + xDist * (h / w);
 
2822
                        point[1] = start[1] + yDist * (h / w);
 
2823
                }
 
2824
                addPathSegment(p, PATH_CURVE_9TO12, point);
 
2825
 
 
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];
 
2831
 
 
2832
                /* 3rd point - moved along from 2nd one */
 
2833
                if (h > w)
 
2834
                {
 
2835
                        point[0] = obj2;
 
2836
                        point[1] = start[1] + yDiff * bar2Ratio;
 
2837
                }
 
2838
                else
 
2839
                {
 
2840
                        point[0] = end[0] - xDist * (h / w);
 
2841
                        point[1] = end[1] - yDist * (h / w);
 
2842
                }
 
2843
                addPathSegment(p, PATH_LINE, point);
 
2844
        }
 
2845
        /* End point */
 
2846
        addPathSegment(p, PATH_CURVE_12TO3, end);
 
2847
}
 
2848
 
 
2849
void setupDicePath(int num, float stepSize, Path* p, BoardData* bd)
 
2850
{
 
2851
        float point[3];
 
2852
        getDicePos(bd, num, point);
 
2853
 
 
2854
        point[0] -= stepSize * 5;
 
2855
        initPath(p, point);
 
2856
 
 
2857
        point[0] += stepSize * 2;
 
2858
        addPathSegment(p, PATH_PARABOLA_12TO3, point);
 
2859
 
 
2860
        point[0] += stepSize * 2;
 
2861
        addPathSegment(p, PATH_PARABOLA, point);
 
2862
 
 
2863
        point[0] += stepSize;
 
2864
        addPathSegment(p, PATH_PARABOLA, point);
 
2865
}
 
2866
 
 
2867
void randomDiceRotation(Path* p, DiceRotation* diceRotation, int dir)
 
2868
{
 
2869
/* Dice rotation range values */
 
2870
#define XROT_MIN 1
 
2871
#define XROT_RANGE 1.5f
 
2872
 
 
2873
#define YROT_MIN -.5f
 
2874
#define YROT_RANGE 1
 
2875
 
 
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;
 
2879
 
 
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;
 
2883
 
 
2884
        if (dir == -1)
 
2885
        {
 
2886
                diceRotation->xRotFactor = -diceRotation->xRotFactor;
 
2887
                diceRotation->yRotFactor = -diceRotation->yRotFactor;
 
2888
        }
 
2889
}
 
2890
 
 
2891
void setupDicePaths(BoardData* bd, Path dicePaths[2], float diceMovingPos[2][3], DiceRotation diceRotation[2])
 
2892
{
 
2893
        int firstDie = (bd->turn == 1);
 
2894
        int dir = (bd->turn == 1) ? -1 : 1;
 
2895
 
 
2896
        setupDicePath(firstDie, dir * DICE_STEP_SIZE0, &dicePaths[firstDie], bd);
 
2897
        setupDicePath(!firstDie, dir * DICE_STEP_SIZE1, &dicePaths[!firstDie], bd);
 
2898
 
 
2899
        randomDiceRotation(&dicePaths[firstDie], &diceRotation[firstDie], dir);
 
2900
        randomDiceRotation(&dicePaths[!firstDie], &diceRotation[!firstDie], dir);
 
2901
 
 
2902
        copyPoint(diceMovingPos[0], dicePaths[0].pts[0]);
 
2903
        copyPoint(diceMovingPos[1], dicePaths[1].pts[0]);
 
2904
}
 
2905
 
 
2906
int DiceTooClose(BoardData3d *bd3d, renderdata *prd)
 
2907
{
 
2908
        float dist;
 
2909
        float orgX[2];
 
2910
        int firstDie = bd3d->dicePos[0][0] > bd3d->dicePos[1][0];
 
2911
 
 
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);
 
2917
}
 
2918
 
 
2919
void setDicePos(BoardData *bd, BoardData3d *bd3d)
 
2920
{
 
2921
        int iter = 0;
 
2922
        float diceSize = getDiceSize(bd->rd);
 
2923
        float firstX = TRAY_WIDTH + DICE_STEP_SIZE0 * 3 + diceSize * .75f;
 
2924
        int firstDie = (bd->turn == 1);
 
2925
 
 
2926
        bd3d->dicePos[firstDie][0] = firstX + randRange(BOARD_WIDTH + TRAY_WIDTH - firstX - diceSize * 2);
 
2927
        bd3d->dicePos[firstDie][1] = randRange(DICE_AREA_HEIGHT);
 
2928
 
 
2929
        do      /* insure dice are not too close together */
 
2930
        {
 
2931
                if (iter++ > 20)
 
2932
                {       /* Trouble placing 2nd dice - replace 1st dice */
 
2933
                        setDicePos(bd, bd3d);
 
2934
                        return;;
 
2935
                }
 
2936
 
 
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);
 
2940
        }
 
2941
        while (DiceTooClose(bd3d, bd->rd));
 
2942
 
 
2943
        bd3d->dicePos[firstDie][2] = (float)(rand() % 360);
 
2944
        bd3d->dicePos[!firstDie][2] = (float)(rand() % 360);
 
2945
 
 
2946
        updateDiceOccPos(bd, bd3d);
 
2947
}
 
2948
 
 
2949
void drawDie(BoardData* bd, BoardData3d *bd3d, int num)
 
2950
{
 
2951
        glPushMatrix();
 
2952
        /* Move to correct position for die */
 
2953
        if (bd3d->shakingDice)
 
2954
        {
 
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);
 
2959
        }
 
2960
        else
 
2961
                moveToDicePos(bd, num);
 
2962
        /* Now draw dice */
 
2963
        drawDice(bd, num);
 
2964
 
 
2965
        glPopMatrix();
 
2966
}
 
2967
 
 
2968
void initViewArea(viewArea* pva)
 
2969
{       /* Initialize values to extremes */
 
2970
        pva->top = -base_unit * 1000;
 
2971
        pva->bottom = base_unit * 1000;
 
2972
        pva->width = 0;
 
2973
}
 
2974
 
 
2975
float getViewAreaHeight(viewArea* pva)
 
2976
{
 
2977
        return pva->top - pva->bottom;
 
2978
}
 
2979
 
 
2980
float getViewAreaWidth(viewArea* pva)
 
2981
{
 
2982
        return pva->width;
 
2983
}
 
2984
 
 
2985
float getAreaRatio(viewArea* pva)
 
2986
{
 
2987
        return getViewAreaWidth(pva) / getViewAreaHeight(pva);
 
2988
}
 
2989
 
 
2990
void addViewAreaHeightPoint(viewArea* pva, float halfRadianFOV, float boardRadAngle, float inY, float inZ)
 
2991
{       /* Rotate points by board angle */
 
2992
        float adj;
 
2993
        float y, z;
 
2994
 
 
2995
        y = inY * (float)cos(boardRadAngle) - inZ * (float)sin(boardRadAngle);
 
2996
        z = inZ * (float)cos(boardRadAngle) + inY * (float)sin(boardRadAngle);
 
2997
 
 
2998
        /* Project height to zero depth */
 
2999
        adj = z * (float)tan(halfRadianFOV);
 
3000
        if (y > 0)
 
3001
                y += adj;
 
3002
        else
 
3003
                y -= adj;
 
3004
 
 
3005
        /* Store max / min heights */
 
3006
        if (pva->top < y)
 
3007
                pva->top = y;
 
3008
        if (pva->bottom > y)
 
3009
                pva->bottom = y;
 
3010
}
 
3011
 
 
3012
void workOutWidth(viewArea* pva, float halfRadianFOV, float boardRadAngle, float aspectRatio, float ip[3])
 
3013
{
 
3014
        float halfRadianXFOV;
 
3015
        float w = getViewAreaHeight(pva) * aspectRatio;
 
3016
        float w2, l;
 
3017
 
 
3018
        float p[3];
 
3019
 
 
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);
 
3024
 
 
3025
        /* Rotate z coord by board angle */
 
3026
        copyPoint(p, ip);
 
3027
        p[2] = ip[2] * (float)cos(boardRadAngle) + ip[1] * (float)sin(boardRadAngle);
 
3028
 
 
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);
 
3033
 
 
3034
        if (pva->width < p[0] * 2)
 
3035
                pva->width = p[0] * 2;
 
3036
}
 
3037
 
 
3038
float GetFOVAngle(BoardData* bd)
 
3039
{
 
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;
 
3044
}
 
3045
 
 
3046
void WorkOutViewArea(BoardData* bd, viewArea *pva, float *pHalfRadianFOV, float aspectRatio, int AssumeCubeAtTop)
 
3047
{
 
3048
        float p[3];
 
3049
        float boardRadAngle;
 
3050
        initViewArea(pva);
 
3051
 
 
3052
        boardRadAngle = (bd->rd->boardAngle * (float)PI) / 180.0f;
 
3053
        *pHalfRadianFOV = ((GetFOVAngle(bd) * (float)PI) / 180.0f) / 2.0f;
 
3054
 
 
3055
        /* Sort out viewing area */
 
3056
        addViewAreaHeightPoint(pva, *pHalfRadianFOV, boardRadAngle, -getBoardHeight() / 2, 0);
 
3057
        addViewAreaHeightPoint(pva, *pHalfRadianFOV, boardRadAngle, -getBoardHeight() / 2, BASE_DEPTH + EDGE_DEPTH);
 
3058
 
 
3059
        if (bd->rd->fDiceArea)
 
3060
        {
 
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);
 
3064
        }
 
3065
        else
 
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);
 
3069
        }
 
3070
 
 
3071
        if (AssumeCubeAtTop)
 
3072
                addViewAreaHeightPoint(pva, *pHalfRadianFOV, boardRadAngle, -(getBoardHeight() / 2 - EDGE_HEIGHT), BASE_DEPTH + EDGE_DEPTH + DOUBLECUBE_SIZE);
 
3073
 
 
3074
        if (!bd->doubled)
 
3075
        {
 
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);
 
3080
        }
 
3081
        p[0] = getBoardWidth() / 2;
 
3082
        p[1] = getBoardHeight() / 2;
 
3083
        p[2] = BASE_DEPTH + EDGE_DEPTH;
 
3084
        workOutWidth(pva, *pHalfRadianFOV, boardRadAngle, aspectRatio, p);
 
3085
}
 
3086
 
 
3087
void SetupPerspVolume(BoardData* bd, BoardData3d* bd3d, renderdata* prd, int viewport[4])
 
3088
{
 
3089
        float aspectRatio = (float)viewport[2]/(float)(viewport[3]);
 
3090
        if (!prd->planView)
 
3091
        {
 
3092
                viewArea va;
 
3093
                float halfRadianFOV;
 
3094
                float fovScale;
 
3095
                float zoom;
 
3096
 
 
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]);
 
3103
                        aspectRatio = .5f;
 
3104
                        /* Clear screen so top + bottom outside board shown ok */
 
3105
                        ClearScreen(prd);
 
3106
                }
 
3107
 
 
3108
                /* Workout how big the board is (in 3d space) */
 
3109
                WorkOutViewArea(bd, &va, &halfRadianFOV, aspectRatio, FALSE);
 
3110
 
 
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)))
 
3114
                {
 
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);
 
3119
                        }
 
3120
                }
 
3121
 
 
3122
                fovScale = zNear * (float)tan(halfRadianFOV);
 
3123
 
 
3124
                if (aspectRatio > getAreaRatio(&va))
 
3125
                {
 
3126
                        bd3d->vertFrustrum = fovScale;
 
3127
                        bd3d->horFrustrum = bd3d->vertFrustrum * aspectRatio;
 
3128
                }
 
3129
                else
 
3130
                {
 
3131
                        bd3d->horFrustrum = fovScale * getAreaRatio(&va);
 
3132
                        bd3d->vertFrustrum = bd3d->horFrustrum / aspectRatio;
 
3133
                }
 
3134
                /* Setup projection matrix */
 
3135
                glFrustum(-bd3d->horFrustrum, bd3d->horFrustrum, -bd3d->vertFrustrum, bd3d->vertFrustrum, zNear, zFar);
 
3136
 
 
3137
                /* Setup modelview matrix */
 
3138
                glMatrixMode(GL_MODELVIEW);
 
3139
                glLoadIdentity();
 
3140
 
 
3141
                /* Zoom back so image fills window */
 
3142
                zoom = (getViewAreaHeight(&va) / 2) / (float)tan(halfRadianFOV);
 
3143
                glTranslatef(0, 0, -zoom);
 
3144
 
 
3145
                /* Offset from centre because of perspective */
 
3146
                glTranslatef(0, getViewAreaHeight(&va) / 2 + va.bottom, 0);
 
3147
 
 
3148
                /* Rotate board */
 
3149
                glRotatef((float)prd->boardAngle, -1, 0, 0);
 
3150
 
 
3151
                /* Origin is bottom left, so move from centre */
 
3152
                glTranslatef(-(getBoardWidth() / 2.0f), -((getBoardHeight()) / 2.0f), 0);
 
3153
        }
 
3154
        else
 
3155
        {
 
3156
                float size;
 
3157
 
 
3158
                if (aspectRatio > getBoardWidth() / getBoardHeight())
 
3159
                {
 
3160
                        size = (getBoardHeight() / 2);
 
3161
                        bd3d->horFrustrum = size * aspectRatio;
 
3162
                        bd3d->vertFrustrum = size;
 
3163
                }
 
3164
                else
 
3165
                {
 
3166
                        size = (getBoardWidth() / 2);
 
3167
                        bd3d->horFrustrum = size;
 
3168
                        bd3d->vertFrustrum = size / aspectRatio;
 
3169
                }
 
3170
                glOrtho(-bd3d->horFrustrum, bd3d->horFrustrum, -bd3d->vertFrustrum, bd3d->vertFrustrum, 0, 5);
 
3171
 
 
3172
                glMatrixMode(GL_MODELVIEW);
 
3173
                glLoadIdentity();
 
3174
 
 
3175
                glTranslatef(-(getBoardWidth() / 2.0f), -(getBoardHeight() / 2.0f), -3);
 
3176
        }
 
3177
 
 
3178
        /* Save matrix for later */
 
3179
        glGetFloatv(GL_MODELVIEW_MATRIX, bd3d->modelMatrix);
 
3180
}
 
3181
 
 
3182
void setupFlag(BoardData3d *bd3d)
 
3183
{
 
3184
        int i;
 
3185
        float width = FLAG_WIDTH;
 
3186
        float height = FLAG_HEIGHT;
 
3187
 
 
3188
        if (bd3d->flagNurb)
 
3189
                gluDeleteNurbsRenderer(bd3d->flagNurb);
 
3190
        bd3d->flagNurb = gluNewNurbsRenderer();
 
3191
 
 
3192
        for (i = 0; i < S_NUMPOINTS; i++)
 
3193
        {
 
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;
 
3200
        }
 
3201
}
 
3202
 
 
3203
void renderFlag(BoardData *bd, BoardData3d *bd3d, int curveAccuracy)
 
3204
{
 
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};
 
3208
 
 
3209
        /* Draw flag surface */
 
3210
        setMaterial(&bd3d->flagMat);
 
3211
 
 
3212
        /* Set size of polygons */
 
3213
        gluNurbsProperty(bd3d->flagNurb, GLU_SAMPLING_TOLERANCE, 500.0f / curveAccuracy);
 
3214
 
 
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);
 
3219
 
 
3220
        /* Draw flag pole */
 
3221
        glPushMatrix();
 
3222
 
 
3223
        glTranslatef(-FLAGPOLE_WIDTH, -FLAG_HEIGHT, 0);
 
3224
 
 
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);
 
3228
 
 
3229
        circleRev(FLAGPOLE_WIDTH, 0, curveAccuracy);
 
3230
        circleRev(FLAGPOLE_WIDTH * 2, FLAGPOLE_HEIGHT, curveAccuracy);
 
3231
 
 
3232
        glPopMatrix();
 
3233
 
 
3234
        /* Draw number on flag */
 
3235
        glDisable(GL_DEPTH_TEST);
 
3236
 
 
3237
        setMaterial(&bd3d->flagNumberMat);
 
3238
 
 
3239
        glPushMatrix();
 
3240
        {
 
3241
                /* Move to middle of flag */
 
3242
                float v[3];
 
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]);
 
3247
        }
 
3248
        {
 
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;
 
3252
 
 
3253
                glRotatef(degAng, 0, 1, 0);
 
3254
        }
 
3255
 
 
3256
        {
 
3257
                /* Draw number */
 
3258
                char flagValue[2] = "x";
 
3259
                /* No specular light */
 
3260
                float specular[4];
 
3261
                float zero[4] = {0,0,0,0};
 
3262
                glGetLightfv(GL_LIGHT0, GL_SPECULAR, specular);
 
3263
                glLightfv(GL_LIGHT0, GL_SPECULAR, zero);
 
3264
 
 
3265
                flagValue[0] = '0' + (char)abs(bd->resigned);
 
3266
                glScalef(1.3f, 1.3f, 1);
 
3267
 
 
3268
                glLineWidth(.5f);
 
3269
                glPrintCube(&bd->bd3d, flagValue);
 
3270
 
 
3271
                glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
 
3272
        }
 
3273
        glPopMatrix();
 
3274
 
 
3275
        glEnable(GL_DEPTH_TEST);
 
3276
}
 
3277
 
 
3278
void drawFlag(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
 
3279
{
 
3280
        float v[4];
 
3281
        int isStencil = glIsEnabled(GL_STENCIL_TEST);
 
3282
 
 
3283
        if (isStencil)
 
3284
                glDisable(GL_STENCIL_TEST);
 
3285
 
 
3286
        waveFlag(bd3d->ctlpoints, bd3d->flagWaved);
 
3287
 
 
3288
        glPushMatrix();
 
3289
 
 
3290
        getFlagPos(bd, v);
 
3291
        glTranslatef(v[0], v[1], v[2]);
 
3292
 
 
3293
        renderFlag(bd, bd3d, prd->curveAccuracy);
 
3294
 
 
3295
        glPopMatrix();
 
3296
        if (isStencil)
 
3297
                glEnable(GL_STENCIL_TEST);
 
3298
}
 
3299
 
 
3300
void updateDieOccPos(BoardData* bd, BoardData3d* bd3d, Occluder* pOcc, int num)
 
3301
{
 
3302
        float id[4][4];
 
3303
 
 
3304
        if (bd3d->shakingDice)
 
3305
        {
 
3306
                copyPoint(pOcc->trans, bd3d->diceMovingPos[num]);
 
3307
 
 
3308
                pOcc->rot[0] = bd3d->diceRotation[num].xRot;
 
3309
                pOcc->rot[1] = bd3d->diceRotation[num].yRot;
 
3310
                pOcc->rot[2] = bd3d->dicePos[num][2];
 
3311
 
 
3312
                makeInverseRotateMatrixZ(pOcc->invMat, pOcc->rot[2]);
 
3313
 
 
3314
                makeInverseRotateMatrixX(id, pOcc->rot[1]);
 
3315
                matrixmult(pOcc->invMat, id);
 
3316
 
 
3317
                makeInverseRotateMatrixY(id, pOcc->rot[0]);
 
3318
                matrixmult(pOcc->invMat, id);
 
3319
 
 
3320
                makeInverseTransposeMatrix(id, pOcc->trans);
 
3321
                matrixmult(pOcc->invMat, id);
 
3322
        }
 
3323
        else
 
3324
        {
 
3325
                getDicePos(bd, num, pOcc->trans);
 
3326
 
 
3327
                makeInverseTransposeMatrix(id, pOcc->trans);
 
3328
 
 
3329
                if (bd->diceShown == DICE_ON_BOARD)
 
3330
                {
 
3331
                        pOcc->rot[0] = pOcc->rot[1] = 0;
 
3332
                        pOcc->rot[2] = bd3d->dicePos[num][2];
 
3333
 
 
3334
                        makeInverseRotateMatrixZ(pOcc->invMat, pOcc->rot[2]);
 
3335
                        matrixmult(pOcc->invMat, id);
 
3336
                }
 
3337
                else
 
3338
                {
 
3339
                        pOcc->rot[0] = pOcc->rot[1] = pOcc->rot[2] = 0;
 
3340
                        copyMatrix(pOcc->invMat, id);
 
3341
                }
 
3342
        }
 
3343
}
 
3344
 
 
3345
void updateDiceOccPos(BoardData* bd, BoardData3d* bd3d)
 
3346
{
 
3347
        int show = DiceShowing(bd);
 
3348
 
 
3349
        bd3d->Occluders[OCC_DICE1].show = bd3d->Occluders[OCC_DICE2].show = show;
 
3350
        if (show)
 
3351
        {
 
3352
                updateDieOccPos(bd, bd3d, &bd3d->Occluders[OCC_DICE1], 0);
 
3353
                updateDieOccPos(bd, bd3d, &bd3d->Occluders[OCC_DICE2], 1);
 
3354
        }
 
3355
}
 
3356
 
 
3357
void updateCubeOccPos(BoardData* bd, BoardData3d* bd3d)
 
3358
{
 
3359
        getDoubleCubePos(bd, bd3d->Occluders[OCC_CUBE].trans);
 
3360
        makeInverseTransposeMatrix(bd3d->Occluders[OCC_CUBE].invMat, bd3d->Occluders[OCC_CUBE].trans);
 
3361
 
 
3362
        bd3d->Occluders[OCC_CUBE].show = (bd->cube_use && !bd->crawford_game);
 
3363
}
 
3364
 
 
3365
void updateMovingPieceOccPos(BoardData* bd, BoardData3d* bd3d)
 
3366
{
 
3367
        if (bd->drag_point >= 0)
 
3368
        {
 
3369
                copyPoint(bd3d->Occluders[LAST_PIECE].trans, bd3d->dragPos);
 
3370
                makeInverseTransposeMatrix(bd3d->Occluders[LAST_PIECE].invMat, bd3d->Occluders[LAST_PIECE].trans);
 
3371
        }
 
3372
        else /* if (bd3d->moving) */
 
3373
        {
 
3374
                copyPoint(bd3d->Occluders[LAST_PIECE].trans, bd3d->movingPos);
 
3375
 
 
3376
                if (bd3d->rotateMovingPiece > 0)
 
3377
                {       /* rotate shadow as piece is put in bear off tray */
 
3378
                        float id[4][4];
 
3379
 
 
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);
 
3385
                }
 
3386
                else
 
3387
                        makeInverseTransposeMatrix(bd3d->Occluders[LAST_PIECE].invMat, bd3d->Occluders[LAST_PIECE].trans);
 
3388
        }
 
3389
}
 
3390
 
 
3391
void updatePieceOccPos(BoardData* bd, BoardData3d* bd3d)
 
3392
{
 
3393
        int i, j, p = OCC_PIECE;
 
3394
 
 
3395
        for (i = 0; i < 28; i++)
 
3396
        {
 
3397
                for (j = 1; j <= abs(bd->points[i]); j++)
 
3398
                {
 
3399
                        if (p > LAST_PIECE)
 
3400
                                break;  /* Found all pieces */
 
3401
                        getPiecePos(i, j, fClockwise, bd3d->Occluders[p].trans);
 
3402
 
 
3403
                        if (i == 26 || i == 27)
 
3404
                        {       /* bars */
 
3405
                                float id[4][4];
 
3406
 
 
3407
                                bd3d->Occluders[p].rotator = 1;
 
3408
                                if (i == 26)
 
3409
                                        bd3d->Occluders[p].rot[1] = -90;
 
3410
                                else
 
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);
 
3415
                        }
 
3416
                        else
 
3417
                        {
 
3418
                                makeInverseTransposeMatrix(bd3d->Occluders[p].invMat, bd3d->Occluders[p].trans);
 
3419
                                bd3d->Occluders[p].rotator = 0;
 
3420
                        }
 
3421
                        p++;
 
3422
                }
 
3423
        }
 
3424
        if (p == LAST_PIECE)
 
3425
        {
 
3426
                updateMovingPieceOccPos(bd, bd3d);
 
3427
                bd3d->Occluders[p].rotator = 0;
 
3428
        }
 
3429
}
 
3430
 
 
3431
void updateFlagOccPos(BoardData* bd, BoardData3d* bd3d)
 
3432
{
 
3433
        if (bd->resigned)
 
3434
        {
 
3435
                freeOccluder(&bd3d->Occluders[OCC_FLAG]);
 
3436
                initOccluder(&bd3d->Occluders[OCC_FLAG]);
 
3437
 
 
3438
                bd3d->Occluders[OCC_FLAG].show = 1;
 
3439
 
 
3440
                getFlagPos(bd, bd3d->Occluders[OCC_FLAG].trans);
 
3441
                makeInverseTransposeMatrix(bd3d->Occluders[OCC_FLAG].invMat, bd3d->Occluders[OCC_FLAG].trans);
 
3442
 
 
3443
                /* Flag pole */
 
3444
                addCube(&bd3d->Occluders[OCC_FLAG], -FLAGPOLE_WIDTH * 1.95f, -FLAG_HEIGHT, -LIFT_OFF,
 
3445
                        FLAGPOLE_WIDTH * 1.95f, FLAGPOLE_HEIGHT, LIFT_OFF * 2);
 
3446
 
 
3447
                /* Flag surface (approximation) */
 
3448
                {
 
3449
                        int s;
 
3450
                        /* Change first ctlpoint to better match flag shape */
 
3451
                        float p1x = bd3d->ctlpoints[1][0][2];
 
3452
                        bd3d->ctlpoints[1][0][2] *= .7f;
 
3453
 
 
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];
 
3459
                                if (s == 2)
 
3460
                                        w *= .95f;
 
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);
 
3464
                        }
 
3465
                        bd3d->ctlpoints[1][0][2] = p1x;
 
3466
                }
 
3467
        }
 
3468
        else
 
3469
        {
 
3470
                bd3d->Occluders[OCC_FLAG].show = 0;
 
3471
        }
 
3472
}
 
3473
 
 
3474
void updateHingeOccPos(BoardData3d* bd3d, int show3dHinges)
 
3475
{
 
3476
        bd3d->Occluders[OCC_HINGE1].show = bd3d->Occluders[OCC_HINGE2].show = show3dHinges;
 
3477
}
 
3478
 
 
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);
 
3484
}
 
3485
 
 
3486
void MakeShadowModel(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
 
3487
{
 
3488
        int i;
 
3489
        TidyShadows(bd3d);
 
3490
 
 
3491
        initOccluder(&bd3d->Occluders[OCC_BOARD]);
 
3492
 
 
3493
        if (prd->roundedEdges)
 
3494
        {
 
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);
 
3502
        }
 
3503
        else
 
3504
        {
 
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);
 
3512
        }
 
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;
 
3515
 
 
3516
        initOccluder(&bd3d->Occluders[OCC_HINGE1]);
 
3517
        copyOccluder(&bd3d->Occluders[OCC_HINGE1], &bd3d->Occluders[OCC_HINGE2]);
 
3518
 
 
3519
        addHalfTube(&bd3d->Occluders[OCC_HINGE1], HINGE_WIDTH, HINGE_HEIGHT, prd->curveAccuracy / 2);
 
3520
 
 
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;
 
3525
 
 
3526
        makeInverseTransposeMatrix(bd3d->Occluders[OCC_HINGE1].invMat, bd3d->Occluders[OCC_HINGE1].trans);
 
3527
        makeInverseTransposeMatrix(bd3d->Occluders[OCC_HINGE2].invMat, bd3d->Occluders[OCC_HINGE2].trans);
 
3528
 
 
3529
        updateHingeOccPos(bd3d, prd->fHinges3d);
 
3530
 
 
3531
        initOccluder(&bd3d->Occluders[OCC_CUBE]);
 
3532
        addSquareCentered(&bd3d->Occluders[OCC_CUBE], 0, 0, 0, DOUBLECUBE_SIZE * .88f, DOUBLECUBE_SIZE * .88f, DOUBLECUBE_SIZE * .88f);
 
3533
 
 
3534
        updateCubeOccPos(bd, bd3d);
 
3535
 
 
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);
 
3541
 
 
3542
        initOccluder(&bd3d->Occluders[OCC_PIECE]);
 
3543
        {
 
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;
 
3548
 
 
3549
                addCylinder(&bd3d->Occluders[OCC_PIECE], 0, 0, lip, PIECE_HOLE / 2.0f - LIFT_OFF, height, prd->curveAccuracy);
 
3550
        }
 
3551
        for (i = OCC_PIECE; i < OCC_PIECE + 30; i++)
 
3552
        {
 
3553
                bd3d->Occluders[i].rot[0] = 0;
 
3554
                bd3d->Occluders[i].rot[2] = 0;
 
3555
                if (i > OCC_PIECE)
 
3556
                        copyOccluder(&bd3d->Occluders[OCC_PIECE], &bd3d->Occluders[i]);
 
3557
        }
 
3558
 
 
3559
        updatePieceOccPos(bd, bd3d);
 
3560
        updateFlagOccPos(bd, bd3d);
 
3561
}
 
3562
 
 
3563
void getCheqSize(renderdata* prd)
 
3564
{
 
3565
        int accuracy = (prd->curveAccuracy / 4) - 1;
 
3566
        int i;
 
3567
        prd->acrossCheq = prd->downCheq = 1;
 
3568
        for (i = 1; i < accuracy; i++)
 
3569
        {
 
3570
                if (((float)prd->acrossCheq) / prd->downCheq > .5)
 
3571
                        prd->downCheq++;
 
3572
                else
 
3573
                        prd->acrossCheq++;
 
3574
        }
 
3575
}
 
3576
 
 
3577
void preDraw3d(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
 
3578
{
 
3579
        if (!bd3d->qobjTex)
 
3580
        {
 
3581
                bd3d->qobjTex = gluNewQuadric();
 
3582
                gluQuadricDrawStyle(bd3d->qobjTex, GLU_FILL);
 
3583
                gluQuadricNormals(bd3d->qobjTex, GLU_FLAT);
 
3584
                gluQuadricTexture(bd3d->qobjTex, GL_TRUE);
 
3585
        }
 
3586
        if (!bd3d->qobj)
 
3587
        {
 
3588
                bd3d->qobj = gluNewQuadric();
 
3589
                gluQuadricDrawStyle(bd3d->qobj, GLU_FILL);
 
3590
                gluQuadricNormals(bd3d->qobj, GLU_FLAT);
 
3591
                gluQuadricTexture(bd3d->qobj, GL_FALSE);
 
3592
        }
 
3593
 
 
3594
        if (bd3d->boardPoints)
 
3595
                freeEigthPoints(&bd3d->boardPoints, prd->curveAccuracy);
 
3596
        calculateEigthPoints(&bd3d->boardPoints, BOARD_FILLET, prd->curveAccuracy);
 
3597
 
 
3598
        preDrawPiece(bd);
 
3599
        preDrawDice(bd3d, prd);
 
3600
 
 
3601
        MakeShadowModel(bd, bd3d, prd);
 
3602
 
 
3603
        getCheqSize(prd);
 
3604
}
 
3605
 
 
3606
void RestrictiveDrawPiece(int pos, int depth)
 
3607
{
 
3608
        float newPos[3];
 
3609
        getPiecePos(pos, depth, fClockwise, newPos);
 
3610
        RestrictiveDrawFrame(newPos, PIECE_HOLE, PIECE_HOLE, PIECE_DEPTH);
 
3611
}
 
3612
 
 
3613
static void RestrictiveDoDrawDice(BoardData* bd, DiceShown dicePos)
 
3614
{
 
3615
        float pos[3];
 
3616
        float diceSize = getDiceSize(bd->rd);
 
3617
        float overSize = diceSize * 1.5f;
 
3618
        ClipBox temp;
 
3619
        DiceShown tempDiceShown;
 
3620
 
 
3621
        tempDiceShown = bd->diceShown;
 
3622
        bd->diceShown = dicePos;
 
3623
 
 
3624
        getDicePos(bd, 0, pos);
 
3625
        pos[2] -= diceSize / 2.0f;
 
3626
        RestrictiveDrawFrame(pos, overSize, overSize, overSize);
 
3627
 
 
3628
        getDicePos(bd, 1, pos);
 
3629
        pos[2] -= diceSize / 2.0f;
 
3630
        RestrictiveDraw(&temp, pos, overSize, overSize, overSize);
 
3631
        EnlargeCurrentToBox(&temp);
 
3632
 
 
3633
        bd->diceShown = tempDiceShown;
 
3634
}
 
3635
 
 
3636
void RestrictiveDrawDice(BoardData* bd)
 
3637
{
 
3638
        int tempTurn = 0;
 
3639
 
 
3640
        if (numRestrictFrames == -1)
 
3641
                return;
 
3642
 
 
3643
        if (bd->rd->fDiceArea)
 
3644
                RestrictiveDoDrawDice(bd, DICE_BELOW_BOARD);
 
3645
 
 
3646
        if (bd->diceShown != DICE_ON_BOARD)
 
3647
        {
 
3648
                tempTurn = bd->turn;
 
3649
                bd->turn *= -1;
 
3650
        }
 
3651
        RestrictiveDoDrawDice(bd, DICE_ON_BOARD);
 
3652
 
 
3653
        if (tempTurn)
 
3654
                bd->turn = tempTurn;
 
3655
}
 
3656
 
 
3657
void RestrictiveDrawCube(BoardData* bd, int old_doubled, int old_cube_owner)
 
3658
{
 
3659
        float pos[3];
 
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);
 
3671
}
 
3672
 
 
3673
void RestrictiveDrawMoveIndicator(BoardData* bd)
 
3674
{       /* Need to redraw both indicators */
 
3675
        float pos[3];
 
3676
 
 
3677
        bd->turn *= -1;
 
3678
        getMoveIndicatorPos(bd, pos);
 
3679
        RestrictiveDrawFrame(pos, ARROW_SIZE, ARROW_SIZE, LIFT_OFF);
 
3680
 
 
3681
        bd->turn *= -1;
 
3682
        getMoveIndicatorPos(bd, pos);
 
3683
        RestrictiveDrawFrame(pos, ARROW_SIZE, ARROW_SIZE, LIFT_OFF);
 
3684
}
 
3685
 
 
3686
void RestrictiveDrawBoardNumbers(BoardData3d *bd3d)
 
3687
{
 
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;;
 
3691
 
 
3692
        RestrictiveDrawFrame(pos, NUMBER_WIDTH, textHeight, LIFT_OFF);
 
3693
        pos[1] = EDGE_HEIGHT / 2.0f;
 
3694
        RestrictiveDrawFrame(pos, NUMBER_WIDTH, textHeight, LIFT_OFF);
 
3695
}
 
3696
 
 
3697
void RestrictiveDrawFlag(BoardData* bd)
 
3698
{
 
3699
        float v[4];
 
3700
        getFlagPos(bd, v);
 
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);
 
3704
}
 
3705
 
 
3706
void drawBoard(BoardData *bd, BoardData3d *bd3d, renderdata *prd)
 
3707
{
 
3708
        drawTable(bd, bd3d, prd);
 
3709
 
 
3710
        if (bd->cube_use && !bd->crawford_game)
 
3711
                drawDC(bd, bd3d, prd);
 
3712
 
 
3713
        /* Draw things in correct order so transparency works correctly */
 
3714
        /* First pieces, then dice, then moving pieces */
 
3715
        drawPieces(bd, bd3d, prd);
 
3716
 
 
3717
        if (bd3d->State == BOARD_OPEN)
 
3718
                tidyEdges(prd);
 
3719
 
 
3720
        if (DiceShowing(bd))
 
3721
        {
 
3722
                drawDie(bd, bd3d, 0);
 
3723
                drawDie(bd, bd3d, 1);
 
3724
        }
 
3725
 
 
3726
        if (bd3d->moving || bd->drag_point >= 0)
 
3727
                drawSpecialPieces(bd, bd3d, prd);
 
3728
 
 
3729
        if (bd->resigned)
 
3730
                drawFlag(bd, bd3d, prd);
 
3731
}