~ubuntu-branches/ubuntu/gutsy/rss-glx/gutsy

« back to all changes in this revision

Viewing changes to reallyslick/cpp_src/impCubeVolume.cpp

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2005-11-30 18:21:27 UTC
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20051130182127-5iww7elbiyzej1lk
Tags: upstream-0.8.0
ImportĀ upstreamĀ versionĀ 0.8.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2002  Terence M. Welsh
3
 
 * Ported to Linux by Tugrul Galatali <tugrul@galatali.com>
4
 
 *
5
 
 * Implicit is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License version 2 as 
7
 
 * published by the Free Software Foundation.
8
 
 *
9
 
 * Implicit is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 * GNU General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU General Public License
15
 
 * along with this program; if not, write to the Free Software
16
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 
 */
18
 
 
19
 
#include "impCubeVolume.h"
20
 
 
21
 
impCubeVolume::impCubeVolume ()
22
 
{
23
 
        cubes = NULL;
24
 
        corners = NULL;
25
 
        edges = NULL;
26
 
        surface = 0;
27
 
        init (4, 4, 4, 0.2f);
28
 
        surfacevalue = 0.5f;
29
 
        thecubetable = new impCubeTable ();
30
 
        cubetable = thecubetable->cubetable;
31
 
        crawltable = thecubetable->crawltable;
32
 
}
33
 
 
34
 
impCubeVolume::~impCubeVolume ()
35
 
{
36
 
        delete[]cubes;
37
 
        delete[]corners;
38
 
        delete[]edges;
39
 
}
40
 
 
41
 
void
42
 
  impCubeVolume::init (int width, int height, int length, float cw)
43
 
{
44
 
        int i, j, k;
45
 
 
46
 
        if (cubes)
47
 
                delete[]cubes;
48
 
        if (corners) {
49
 
                /*for(i=0; i<=width; i++){
50
 
                   for(j=0; j<=height; j++){
51
 
                   for(k=0; k<=length; k++)
52
 
                   delete[] corners[i][j][k];
53
 
                   delete[] corners[i][j];
54
 
                   }
55
 
                   delete[] corners[i];
56
 
                   } */
57
 
                delete[]corners;
58
 
        }
59
 
        if (edges)
60
 
                delete[]edges;
61
 
 
62
 
        whl[0] = width;
63
 
        whl[1] = height;
64
 
        whl[2] = length;
65
 
 
66
 
        // calculate position of left-bottom-front corner
67
 
        cubewidth = cw;
68
 
        lbf[0] = -float (width) * cubewidth * 0.5f;
69
 
        lbf[1] = -float (height) * cubewidth * 0.5f;
70
 
        lbf[2] = -float (length) * cubewidth * 0.5f;
71
 
 
72
 
        // allocate cubeinfo memory and set cube positions
73
 
        cubes = new cubeinfo **[width];
74
 
        for (i = 0; i < width; i++) {
75
 
                cubes[i] = new cubeinfo *[height];
76
 
                for (j = 0; j < height; j++) {
77
 
                        cubes[i][j] = new cubeinfo[length];
78
 
                        for (k = 0; k < length; k++) {
79
 
                                cubes[i][j][k].done = 0;
80
 
                                cubes[i][j][k].x = lbf[0] + (cubewidth * (float (i) + 0.5f));
81
 
                                cubes[i][j][k].y = lbf[1] + (cubewidth * (float (j) + 0.5f));
82
 
                                cubes[i][j][k].z = lbf[2] + (cubewidth * (float (k) + 0.5f));
83
 
                        }
84
 
                }
85
 
        }
86
 
 
87
 
        // "corners" will store the position of each corner
88
 
        // plus the value of the gradient at that location
89
 
        corners = new cornerinfo **[width + 1];
90
 
        for (i = 0; i <= width; i++) {
91
 
                corners[i] = new cornerinfo *[height + 1];
92
 
                for (j = 0; j <= height; j++) {
93
 
                        corners[i][j] = new cornerinfo[length + 1];
94
 
                        for (k = 0; k <= length; k++) {
95
 
                                corners[i][j][k].done = 0;
96
 
                                corners[i][j][k].position[0] = lbf[0] + (cubewidth * float (i));
97
 
                                corners[i][j][k].position[1] = lbf[1] + (cubewidth * float (j));
98
 
                                corners[i][j][k].position[2] = lbf[2] + (cubewidth * float (k));
99
 
                        }
100
 
                }
101
 
        }
102
 
        /*corners = new float***[width+1];
103
 
           for(i=0; i<=width; i++){
104
 
           corners[i] = new float**[height+1];
105
 
           for(j=0; j<=height; j++){
106
 
           corners[i][j] = new float*[length+1];
107
 
           for(k=0; k<=length; k++)
108
 
           corners[i][j][k] = new float[4];
109
 
           }
110
 
           }
111
 
 
112
 
           for(i=0; i<=width; i++){
113
 
           for(j=0; j<=height; j++){
114
 
           for(k=0; k<=length; k++){
115
 
           corners[i][j][k][0] = lbf[0] + (cubewidth * float(i));
116
 
           corners[i][j][k][1] = lbf[1] + (cubewidth * float(j));
117
 
           corners[i][j][k][2] = lbf[2] + (cubewidth * float(k));
118
 
           }
119
 
           }
120
 
           } */
121
 
 
122
 
        edges = new edgeinfo ***[3];    // a set of edges aligned with each axis
123
 
        // edges along x-axis
124
 
        edges[0] = new edgeinfo **[width];
125
 
        for (i = 0; i < width; i++) {
126
 
                edges[0][i] = new edgeinfo *[height + 1];
127
 
                for (j = 0; j <= height; j++) {
128
 
                        edges[0][i][j] = new edgeinfo[length + 1];
129
 
                        for (k = 0; k <= length; k++)
130
 
                                edges[0][i][j][k].done = 0;
131
 
                }
132
 
        }
133
 
        // edges along y-axis
134
 
        edges[1] = new edgeinfo **[width + 1];
135
 
        for (i = 0; i <= width; i++) {
136
 
                edges[1][i] = new edgeinfo *[height];
137
 
                for (j = 0; j < height; j++) {
138
 
                        edges[1][i][j] = new edgeinfo[length + 1];
139
 
                        for (k = 0; k <= length; k++)
140
 
                                edges[1][i][j][k].done = 0;
141
 
                }
142
 
        }
143
 
        // edges along z-axis
144
 
        edges[2] = new edgeinfo **[width + 1];
145
 
        for (i = 0; i <= width; i++) {
146
 
                edges[2][i] = new edgeinfo *[height + 1];
147
 
                for (j = 0; j <= height; j++) {
148
 
                        edges[2][i][j] = new edgeinfo[length];
149
 
                        for (k = 0; k < length; k++)
150
 
                                edges[2][i][j][k].done = 0;
151
 
                }
152
 
        }
153
 
}
154
 
 
155
 
void impCubeVolume::make_surface ()
156
 
{
157
 
        int i, j, k;
158
 
 
159
 
        if (surface == NULL)
160
 
                return;
161
 
 
162
 
        // find gradient value at every corner
163
 
        for (i = 0; i <= whl[0]; i++) {
164
 
                for (j = 0; j <= whl[1]; j++) {
165
 
                        for (k = 0; k <= whl[2]; k++)
166
 
                                corners[i][j][k].value = function (corners[i][j][k].position);
167
 
                }
168
 
        }
169
 
 
170
 
        // polygonize surface
171
 
        for (i = 0; i < whl[0]; i++) {
172
 
                for (j = 0; j < whl[1]; j++) {
173
 
                        for (k = 0; k < whl[2]; k++) {
174
 
                                cubes[i][j][k].index = findcubetableindex (i, j, k);
175
 
                                polygonize (i, j, k);
176
 
                        }
177
 
                }
178
 
        }
179
 
 
180
 
        // zero-out edges' done labels
181
 
        for (i = 0; i < whl[0]; i++) {
182
 
                for (j = 0; j <= whl[1]; j++) {
183
 
                        for (k = 0; k <= whl[2]; k++) {
184
 
                                edges[0][i][j][k].done = 0;
185
 
                        }
186
 
                }
187
 
        }
188
 
        for (i = 0; i <= whl[0]; i++) {
189
 
                for (j = 0; j < whl[1]; j++) {
190
 
                        for (k = 0; k <= whl[2]; k++) {
191
 
                                edges[1][i][j][k].done = 0;
192
 
                        }
193
 
                }
194
 
        }
195
 
        for (i = 0; i <= whl[0]; i++) {
196
 
                for (j = 0; j <= whl[1]; j++) {
197
 
                        for (k = 0; k < whl[2]; k++) {
198
 
                                edges[2][i][j][k].done = 0;
199
 
                        }
200
 
                }
201
 
        }
202
 
}
203
 
 
204
 
void impCubeVolume::make_surface (float eyex, float eyey, float eyez)
205
 
{
206
 
        int i, j, k;
207
 
        int index;
208
 
        cubelistelem *currentcube;
209
 
        float xdist, ydist, zdist;
210
 
 
211
 
        if (surface == NULL)
212
 
                return;
213
 
 
214
 
        // find gradient value at every corner
215
 
        for (i = 0; i <= whl[0]; i++) {
216
 
                for (j = 0; j <= whl[1]; j++) {
217
 
                        for (k = 0; k <= whl[2]; k++)
218
 
                                corners[i][j][k].value = function (corners[i][j][k].position);
219
 
                }
220
 
        }
221
 
 
222
 
        // erase list from last frame
223
 
        cubelist.clear ();
224
 
 
225
 
        // polygonize surface
226
 
        for (i = 0; i < whl[0]; i++) {
227
 
                for (j = 0; j < whl[1]; j++) {
228
 
                        for (k = 0; k < whl[2]; k++) {
229
 
                                index = findcubetableindex (i, j, k);
230
 
                                if (index != 0 && index != 255) {
231
 
                                        cubelist.push_back (cubelistelem (index));
232
 
                                        currentcube = &(cubelist.back ());
233
 
                                        currentcube->position[0] = i;
234
 
                                        currentcube->position[1] = j;
235
 
                                        currentcube->position[2] = k;
236
 
                                        xdist = cubes[i][j][k].x - eyex;
237
 
                                        ydist = cubes[i][j][k].y - eyey;
238
 
                                        zdist = cubes[i][j][k].z - eyez;
239
 
                                        currentcube->depth = xdist * xdist + ydist * ydist + zdist * zdist;
240
 
                                }
241
 
                        }
242
 
                }
243
 
        }
244
 
 
245
 
        // sort the cubes
246
 
        cubelist.sort ();
247
 
 
248
 
        // polygonize surface
249
 
        polygonize ();
250
 
 
251
 
        // zero-out edges' done labels
252
 
        for (i = 0; i < whl[0]; i++) {
253
 
                for (j = 0; j <= whl[1]; j++) {
254
 
                        for (k = 0; k <= whl[2]; k++) {
255
 
                                edges[0][i][j][k].done = 0;
256
 
                        }
257
 
                }
258
 
        }
259
 
        for (i = 0; i <= whl[0]; i++) {
260
 
                for (j = 0; j < whl[1]; j++) {
261
 
                        for (k = 0; k <= whl[2]; k++) {
262
 
                                edges[1][i][j][k].done = 0;
263
 
                        }
264
 
                }
265
 
        }
266
 
        for (i = 0; i <= whl[0]; i++) {
267
 
                for (j = 0; j <= whl[1]; j++) {
268
 
                        for (k = 0; k < whl[2]; k++) {
269
 
                                edges[2][i][j][k].done = 0;
270
 
                        }
271
 
                }
272
 
        }
273
 
}
274
 
 
275
 
void impCubeVolume::make_surface (std::list < impCrawlPoint > crawlpointlist)
276
 
{
277
 
        int i, j, k;
278
 
        bool crawlpointexit;
279
 
        int index;
280
 
 
281
 
        if (surface == NULL)
282
 
                return;
283
 
 
284
 
        // crawl from every crawl point to create the surface
285
 
        std::list < impCrawlPoint >::iterator crawliter = crawlpointlist.begin ();
286
 
        while (crawliter != crawlpointlist.end ()) {
287
 
                // find cube corresponding to crawl point
288
 
                i = int ((crawliter->position[0] - lbf[0]) / cubewidth);
289
 
 
290
 
                if (i < 0)
291
 
                        i = 0;
292
 
                if (i >= whl[0])
293
 
                        i = whl[0] - 1;
294
 
                j = int ((crawliter->position[1] - lbf[1]) / cubewidth);
295
 
 
296
 
                if (j < 0)
297
 
                        j = 0;
298
 
                if (j >= whl[1])
299
 
                        j = whl[1] - 1;
300
 
                k = int ((crawliter->position[2] - lbf[2]) / cubewidth);
301
 
 
302
 
                if (k < 0)
303
 
                        k = 0;
304
 
                if (k >= whl[2])
305
 
                        k = whl[2] - 1;
306
 
 
307
 
                // escape if starting on a finished cube
308
 
                crawlpointexit = 0;
309
 
                while (!crawlpointexit) {
310
 
                        if (cubes[i][j][k].done)
311
 
                                crawlpointexit = 1;     // escape if starting on a finished cube
312
 
                        else {  // find index for this cube
313
 
                                findcornervalues (i, j, k);
314
 
                                index = findcubetableindex (i, j, k);
315
 
                                // save index for uncrawling
316
 
                                cubes[i][j][k].index = index;
317
 
                                if (index == 255)       // escape if outside surface
318
 
                                        crawlpointexit = 1;
319
 
                                else {
320
 
                                        if (index == 0) {       // this cube is inside volume
321
 
                                                cubes[i][j][k].done = 1;
322
 
                                                i--;    // step to an adjacent cube and start over
323
 
                                                if (i < 0)      // escape if you step outside of volume
324
 
                                                        crawlpointexit = 1;
325
 
                                        } else {
326
 
                                                crawl_nosort (i, j, k);
327
 
                                                crawlpointexit = 1;
328
 
                                        }
329
 
                                }
330
 
                        }
331
 
                }
332
 
 
333
 
                crawliter++;
334
 
        }
335
 
 
336
 
        // crawl from every crawl point to zero-out done flags
337
 
        crawliter = crawlpointlist.begin ();
338
 
        while (crawliter != crawlpointlist.end ()) {
339
 
                // find cube corresponding to crawl point
340
 
                i = int ((crawliter->position[0] - lbf[0]) / cubewidth);
341
 
 
342
 
                if (i < 0)
343
 
                        i = 0;
344
 
                if (i >= whl[0])
345
 
                        i = whl[0] - 1;
346
 
                j = int ((crawliter->position[1] - lbf[1]) / cubewidth);
347
 
 
348
 
                if (j < 0)
349
 
                        j = 0;
350
 
                if (j >= whl[1])
351
 
                        j = whl[1] - 1;
352
 
                k = int ((crawliter->position[2] - lbf[2]) / cubewidth);
353
 
 
354
 
                if (k < 0)
355
 
                        k = 0;
356
 
                if (k >= whl[2])
357
 
                        k = whl[2] - 1;
358
 
 
359
 
                // escape if starting on a finished cube
360
 
                crawlpointexit = 0;
361
 
                while (!crawlpointexit) {
362
 
                        if (!(cubes[i][j][k].done))
363
 
                                crawlpointexit = 1;     // escape if starting on an unused cube
364
 
                        else {
365
 
                                index = cubes[i][j][k].index;   //findcubetableindex(i, j, k);
366
 
                                if (index == 0) {
367
 
                                        cubes[i][j][k].done = 0;
368
 
                                        corners[i][j][k].done = 0;
369
 
                                        corners[i][j][k + 1].done = 0;
370
 
                                        corners[i][j + 1][k].done = 0;
371
 
                                        corners[i][j + 1][k + 1].done = 0;
372
 
                                        corners[i + 1][j][k].done = 0;
373
 
                                        corners[i + 1][j][k + 1].done = 0;
374
 
                                        corners[i + 1][j + 1][k].done = 0;
375
 
                                        corners[i + 1][j + 1][k + 1].done = 0;
376
 
                                        i--;    // step to an adjacent cube and start over
377
 
                                        if (i < 0)      // escape if you step outside of volume
378
 
                                                crawlpointexit = 1;
379
 
                                } else {
380
 
                                        uncrawl (i, j, k);
381
 
                                        crawlpointexit = 1;
382
 
                                }
383
 
                        }
384
 
                }
385
 
 
386
 
                crawliter++;
387
 
        }
388
 
}
389
 
 
390
 
void impCubeVolume::make_surface (float eyex, float eyey, float eyez, std::list < impCrawlPoint > crawlpointlist)
391
 
{
392
 
        int i, j, k;
393
 
        bool crawlpointexit;
394
 
        int index;
395
 
        float xdist, ydist, zdist;
396
 
 
397
 
        if (surface == NULL)
398
 
                return;
399
 
 
400
 
        // erase list from last fram
401
 
        cubelist.clear ();
402
 
 
403
 
        // crawl from every crawl point to create the surface
404
 
        std::list < impCrawlPoint >::iterator crawliter = crawlpointlist.begin ();
405
 
        while (crawliter != crawlpointlist.end ()) {
406
 
                // find cube corresponding to crawl point
407
 
                i = int ((crawliter->position[0] - lbf[0]) / cubewidth);
408
 
 
409
 
                if (i < 0)
410
 
                        i = 0;
411
 
                if (i >= whl[0])
412
 
                        i = whl[0] - 1;
413
 
                j = int ((crawliter->position[1] - lbf[1]) / cubewidth);
414
 
 
415
 
                if (j < 0)
416
 
                        j = 0;
417
 
                if (j >= whl[1])
418
 
                        j = whl[1] - 1;
419
 
                k = int ((crawliter->position[2] - lbf[2]) / cubewidth);
420
 
 
421
 
                if (k < 0)
422
 
                        k = 0;
423
 
                if (k >= whl[2])
424
 
                        k = whl[2] - 1;
425
 
 
426
 
                // escape if starting on a finished cube
427
 
                crawlpointexit = 0;
428
 
                while (!crawlpointexit) {
429
 
                        if (cubes[i][j][k].done)
430
 
                                crawlpointexit = 1;     // escape if starting on a finished cube
431
 
                        else {  // find index for this cube
432
 
                                findcornervalues (i, j, k);
433
 
                                index = findcubetableindex (i, j, k);
434
 
                                // save index for uncrawling
435
 
                                cubes[i][j][k].index = index;
436
 
                                if (index == 255)       // escape if outside surface
437
 
                                        crawlpointexit = 1;
438
 
                                else {
439
 
                                        if (index == 0) {       // this cube is inside volume
440
 
                                                cubes[i][j][k].done = 1;
441
 
                                                i--;    // step to an adjacent cube and start over
442
 
                                                if (i < 0)      // escape if you step outside of volume
443
 
                                                        crawlpointexit = 1;
444
 
                                        } else {
445
 
                                                crawl_sort (i, j, k);
446
 
                                                crawlpointexit = 1;
447
 
                                        }
448
 
                                }
449
 
                        }
450
 
                }
451
 
 
452
 
                crawliter++;
453
 
        }
454
 
 
455
 
        // sort the cubes
456
 
        std::list < cubelistelem >::iterator cubeiter = cubelist.begin ();
457
 
        while (cubeiter != cubelist.end ()) {
458
 
                i = cubeiter->position[0];
459
 
                j = cubeiter->position[1];
460
 
                k = cubeiter->position[2];
461
 
                xdist = cubes[i][j][k].x - eyex;
462
 
                ydist = cubes[i][j][k].y - eyey;
463
 
                zdist = cubes[i][j][k].z - eyez;
464
 
                cubeiter->depth = xdist * xdist + ydist * ydist + zdist * zdist;
465
 
                cubeiter++;
466
 
        }
467
 
        cubelist.sort ();
468
 
 
469
 
        // polygonize surface
470
 
        polygonize ();
471
 
 
472
 
        // crawl from every crawl point to zero-out done flags
473
 
        crawliter = crawlpointlist.begin ();
474
 
        while (crawliter != crawlpointlist.end ()) {
475
 
                // find cube corresponding to crawl point
476
 
                i = int ((crawliter->position[0] - lbf[0]) / cubewidth);
477
 
 
478
 
                if (i < 0)
479
 
                        i = 0;
480
 
                if (i >= whl[0])
481
 
                        i = whl[0] - 1;
482
 
                j = int ((crawliter->position[1] - lbf[1]) / cubewidth);
483
 
 
484
 
                if (j < 0)
485
 
                        j = 0;
486
 
                if (j >= whl[1])
487
 
                        j = whl[1] - 1;
488
 
                k = int ((crawliter->position[2] - lbf[2]) / cubewidth);
489
 
 
490
 
                if (k < 0)
491
 
                        k = 0;
492
 
                if (k >= whl[2])
493
 
                        k = whl[2] - 1;
494
 
 
495
 
                // escape if starting on a finished cube
496
 
                crawlpointexit = 0;
497
 
                while (!crawlpointexit) {
498
 
                        if (!(cubes[i][j][k].done))
499
 
                                crawlpointexit = 1;     // escape if starting on an unused cube
500
 
                        else {
501
 
                                index = cubes[i][j][k].index;
502
 
                                if (index == 0) {
503
 
                                        cubes[i][j][k].done = 0;
504
 
                                        corners[i][j][k].done = 0;
505
 
                                        corners[i][j][k + 1].done = 0;
506
 
                                        corners[i][j + 1][k].done = 0;
507
 
                                        corners[i][j + 1][k + 1].done = 0;
508
 
                                        corners[i + 1][j][k].done = 0;
509
 
                                        corners[i + 1][j][k + 1].done = 0;
510
 
                                        corners[i + 1][j + 1][k].done = 0;
511
 
                                        corners[i + 1][j + 1][k + 1].done = 0;
512
 
                                        i--;    // step to an adjacent cube and start over
513
 
                                        if (i < 0)      // escape if you step outside of volume
514
 
                                                crawlpointexit = 1;
515
 
                                } else {
516
 
                                        uncrawl (i, j, k);
517
 
                                        crawlpointexit = 1;
518
 
                                }
519
 
                        }
520
 
                }
521
 
 
522
 
                crawliter++;
523
 
        }
524
 
}
525
 
 
526
 
// calculate index into cubetable
527
 
inline int impCubeVolume::findcubetableindex (int x, int y, int z)
528
 
{
529
 
        int index;
530
 
 
531
 
        index = 0;
532
 
        if (corners[x][y][z].value < surfacevalue)
533
 
                index |= LBF;
534
 
        if (corners[x][y][z + 1].value < surfacevalue)
535
 
                index |= LBN;
536
 
        if (corners[x][y + 1][z].value < surfacevalue)
537
 
                index |= LTF;
538
 
        if (corners[x][y + 1][z + 1].value < surfacevalue)
539
 
                index |= LTN;
540
 
        if (corners[x + 1][y][z].value < surfacevalue)
541
 
                index |= RBF;
542
 
        if (corners[x + 1][y][z + 1].value < surfacevalue)
543
 
                index |= RBN;
544
 
        if (corners[x + 1][y + 1][z].value < surfacevalue)
545
 
                index |= RTF;
546
 
        if (corners[x + 1][y + 1][z + 1].value < surfacevalue)
547
 
                index |= RTN;
548
 
 
549
 
        return (index);
550
 
}
551
 
 
552
 
inline void impCubeVolume::crawl_nosort (int x, int y, int z)
553
 
{
554
 
        findcornervalues (x, y, z);
555
 
        int index = findcubetableindex (x, y, z);
556
 
 
557
 
        // quit if this cube has been done or does not intersect surface
558
 
        if (cubes[x][y][z].done || index == 0 || index == 255)
559
 
                return;
560
 
 
561
 
        // save index for polygonizing and uncrawling
562
 
        cubes[x][y][z].index = index;
563
 
 
564
 
        // polygonize this cube if it intersects surface
565
 
        polygonize (x, y, z);
566
 
 
567
 
        // mark this cube as completed
568
 
        cubes[x][y][z].done = 1;
569
 
 
570
 
        // polygonize adjacent cubes
571
 
        if (crawltable[index][0] && x > 0)
572
 
                crawl_nosort (x - 1, y, z);
573
 
        if (crawltable[index][1] && x < whl[0] - 1)
574
 
                crawl_nosort (x + 1, y, z);
575
 
        if (crawltable[index][2] && y > 0)
576
 
                crawl_nosort (x, y - 1, z);
577
 
        if (crawltable[index][3] && y < whl[1] - 1)
578
 
                crawl_nosort (x, y + 1, z);
579
 
        if (crawltable[index][4] && z > 0)
580
 
                crawl_nosort (x, y, z - 1);
581
 
        if (crawltable[index][5] && z < whl[2] - 1)
582
 
                crawl_nosort (x, y, z + 1);
583
 
}
584
 
 
585
 
inline void impCubeVolume::crawl_sort (int x, int y, int z)
586
 
{
587
 
        findcornervalues (x, y, z);
588
 
        int index = findcubetableindex (x, y, z);
589
 
 
590
 
        // quit if this cube has been done or does not intersect surface
591
 
        if (cubes[x][y][z].done || index == 0 || index == 255)
592
 
                return;
593
 
 
594
 
        // save index for uncrawling
595
 
        cubes[x][y][z].index = index;
596
 
 
597
 
        // mark this cube as completed
598
 
        cubes[x][y][z].done = 1;
599
 
 
600
 
        // add cube to list
601
 
        cubelist.push_back (cubelistelem (index));
602
 
        cubelistelem *currentcube = &(cubelist.back ());
603
 
 
604
 
        currentcube->position[0] = x;
605
 
        currentcube->position[1] = y;
606
 
        currentcube->position[2] = z;
607
 
 
608
 
        // polygonize adjacent cubes
609
 
        if (crawltable[index][0] && x > 0)
610
 
                crawl_sort (x - 1, y, z);
611
 
        if (crawltable[index][1] && x < whl[0] - 1)
612
 
                crawl_sort (x + 1, y, z);
613
 
        if (crawltable[index][2] && y > 0)
614
 
                crawl_sort (x, y - 1, z);
615
 
        if (crawltable[index][3] && y < whl[1] - 1)
616
 
                crawl_sort (x, y + 1, z);
617
 
        if (crawltable[index][4] && z > 0)
618
 
                crawl_sort (x, y, z - 1);
619
 
        if (crawltable[index][5] && z < whl[2] - 1)
620
 
                crawl_sort (x, y, z + 1);
621
 
}
622
 
 
623
 
inline void impCubeVolume::uncrawl (int x, int y, int z)
624
 
{
625
 
        if (!(cubes[x][y][z].done))
626
 
                return;
627
 
 
628
 
        corners[x][y][z].done = 0;
629
 
        corners[x][y][z + 1].done = 0;
630
 
        corners[x][y + 1][z].done = 0;
631
 
        corners[x][y + 1][z + 1].done = 0;
632
 
        corners[x + 1][y][z].done = 0;
633
 
        corners[x + 1][y][z + 1].done = 0;
634
 
        corners[x + 1][y + 1][z].done = 0;
635
 
        corners[x + 1][y + 1][z + 1].done = 0;
636
 
 
637
 
        cubes[x][y][z].done = 0;
638
 
 
639
 
        edges[0][x][y][z].done = 0;
640
 
        edges[0][x][y + 1][z].done = 0;
641
 
        edges[0][x][y][z + 1].done = 0;
642
 
        edges[0][x][y + 1][z + 1].done = 0;
643
 
        edges[1][x][y][z].done = 0;
644
 
        edges[1][x + 1][y][z].done = 0;
645
 
        edges[1][x][y][z + 1].done = 0;
646
 
        edges[1][x + 1][y][z + 1].done = 0;
647
 
        edges[2][x][y][z].done = 0;
648
 
        edges[2][x + 1][y][z].done = 0;
649
 
        edges[2][x][y + 1][z].done = 0;
650
 
        edges[2][x + 1][y + 1][z].done = 0;
651
 
 
652
 
        // uncrawl adjacent cubes
653
 
        int index = cubes[x][y][z].index;
654
 
 
655
 
        if (crawltable[index][0] && x > 0)
656
 
                uncrawl (x - 1, y, z);
657
 
        if (crawltable[index][1] && x < whl[0] - 1)
658
 
                uncrawl (x + 1, y, z);
659
 
        if (crawltable[index][2] && y > 0)
660
 
                uncrawl (x, y - 1, z);
661
 
        if (crawltable[index][3] && y < whl[1] - 1)
662
 
                uncrawl (x, y + 1, z);
663
 
        if (crawltable[index][4] && z > 0)
664
 
                uncrawl (x, y, z - 1);
665
 
        if (crawltable[index][5] && z < whl[2] - 1)
666
 
                uncrawl (x, y, z + 1);
667
 
}
668
 
 
669
 
// polygonize an individual cube
670
 
inline void impCubeVolume::polygonize (int x, int y, int z)
671
 
{
672
 
        // stores data for computed triangle strips
673
 
        static int i;
674
 
        static float data[42];
675
 
        static int index, counter;
676
 
        static int nedges;
677
 
        static int copysize = 6 * sizeof (float);
678
 
 
679
 
        // find index into cubetable
680
 
        index = cubes[x][y][z].index;
681
 
 
682
 
        counter = 0;
683
 
        nedges = cubetable[index][counter];
684
 
        while (nedges != 0) {
685
 
                for (i = 0; i < nedges; i++) {
686
 
                        // generate vertex position and normal data
687
 
                        switch (cubetable[index][i + counter + 1]) {
688
 
                        case 0:
689
 
                                findvert (2, x, y, z);
690
 
                                memcpy (&data[i * 6], edges[2][x][y][z].data, copysize);
691
 
                                break;
692
 
                        case 1:
693
 
                                findvert (1, x, y, z);
694
 
                                memcpy (&data[i * 6], edges[1][x][y][z].data, copysize);
695
 
                                break;
696
 
                        case 2:
697
 
                                findvert (1, x, y, z + 1);
698
 
                                memcpy (&data[i * 6], edges[1][x][y][z + 1].data, copysize);
699
 
                                break;
700
 
                        case 3:
701
 
                                findvert (2, x, y + 1, z);
702
 
                                memcpy (&data[i * 6], edges[2][x][y + 1][z].data, copysize);
703
 
                                break;
704
 
                        case 4:
705
 
                                findvert (0, x, y, z);
706
 
                                memcpy (&data[i * 6], edges[0][x][y][z].data, copysize);
707
 
                                break;
708
 
                        case 5:
709
 
                                findvert (0, x, y, z + 1);
710
 
                                memcpy (&data[i * 6], edges[0][x][y][z + 1].data, copysize);
711
 
                                break;
712
 
                        case 6:
713
 
                                findvert (0, x, y + 1, z);
714
 
                                memcpy (&data[i * 6], edges[0][x][y + 1][z].data, copysize);
715
 
                                break;
716
 
                        case 7:
717
 
                                findvert (0, x, y + 1, z + 1);
718
 
                                memcpy (&data[i * 6], edges[0][x][y + 1][z + 1].data, copysize);
719
 
                                break;
720
 
                        case 8:
721
 
                                findvert (2, x + 1, y, z);
722
 
                                memcpy (&data[i * 6], edges[2][x + 1][y][z].data, copysize);
723
 
                                break;
724
 
                        case 9:
725
 
                                findvert (1, x + 1, y, z);
726
 
                                memcpy (&data[i * 6], edges[1][x + 1][y][z].data, copysize);
727
 
                                break;
728
 
                        case 10:
729
 
                                findvert (1, x + 1, y, z + 1);
730
 
                                memcpy (&data[i * 6], edges[1][x + 1][y][z + 1].data, copysize);
731
 
                                break;
732
 
                        case 11:
733
 
                                findvert (2, x + 1, y + 1, z);
734
 
                                memcpy (&data[i * 6], edges[2][x + 1][y + 1][z].data, copysize);
735
 
                        }
736
 
                }
737
 
                surface->addstrip (nedges, data);
738
 
                counter += (nedges + 1);
739
 
                nedges = cubetable[index][counter];
740
 
        }
741
 
}
742
 
 
743
 
// polygonize a list of cubes stored in "cubelist"
744
 
inline void impCubeVolume::polygonize ()
745
 
{
746
 
        // stores data for computed triangle strips
747
 
        static int x, y, z;
748
 
        static int i;
749
 
        static float data[42];
750
 
        static int index, counter;
751
 
        static int nedges;
752
 
        static int copysize = 6 * sizeof (float);
753
 
 
754
 
        // polygonize in reverse order so that the farthest cube
755
 
        // is drawn first and the closest is drawn last
756
 
        std::list < cubelistelem >::iterator iter = cubelist.end ();
757
 
        while (iter != cubelist.begin ()) {
758
 
                iter--;
759
 
 
760
 
                x = iter->position[0];
761
 
                y = iter->position[1];
762
 
                z = iter->position[2];
763
 
 
764
 
                // find index into cubetable
765
 
                index = iter->index;
766
 
 
767
 
                counter = 0;
768
 
                nedges = cubetable[index][counter];
769
 
                while (nedges != 0) {
770
 
                        for (i = 0; i < nedges; i++) {
771
 
                                // generate vertex position and normal data
772
 
                                switch (cubetable[index][i + counter + 1]) {
773
 
                                case 0:
774
 
                                        findvert (2, x, y, z);
775
 
                                        memcpy (&data[i * 6], edges[2][x][y][z].data, copysize);
776
 
                                        break;
777
 
                                case 1:
778
 
                                        findvert (1, x, y, z);
779
 
                                        memcpy (&data[i * 6], edges[1][x][y][z].data, copysize);
780
 
                                        break;
781
 
                                case 2:
782
 
                                        findvert (1, x, y, z + 1);
783
 
                                        memcpy (&data[i * 6], edges[1][x][y][z + 1].data, copysize);
784
 
                                        break;
785
 
                                case 3:
786
 
                                        findvert (2, x, y + 1, z);
787
 
                                        memcpy (&data[i * 6], edges[2][x][y + 1][z].data, copysize);
788
 
                                        break;
789
 
                                case 4:
790
 
                                        findvert (0, x, y, z);
791
 
                                        memcpy (&data[i * 6], edges[0][x][y][z].data, copysize);
792
 
                                        break;
793
 
                                case 5:
794
 
                                        findvert (0, x, y, z + 1);
795
 
                                        memcpy (&data[i * 6], edges[0][x][y][z + 1].data, copysize);
796
 
                                        break;
797
 
                                case 6:
798
 
                                        findvert (0, x, y + 1, z);
799
 
                                        memcpy (&data[i * 6], edges[0][x][y + 1][z].data, copysize);
800
 
                                        break;
801
 
                                case 7:
802
 
                                        findvert (0, x, y + 1, z + 1);
803
 
                                        memcpy (&data[i * 6], edges[0][x][y + 1][z + 1].data, copysize);
804
 
                                        break;
805
 
                                case 8:
806
 
                                        findvert (2, x + 1, y, z);
807
 
                                        memcpy (&data[i * 6], edges[2][x + 1][y][z].data, copysize);
808
 
                                        break;
809
 
                                case 9:
810
 
                                        findvert (1, x + 1, y, z);
811
 
                                        memcpy (&data[i * 6], edges[1][x + 1][y][z].data, copysize);
812
 
                                        break;
813
 
                                case 10:
814
 
                                        findvert (1, x + 1, y, z + 1);
815
 
                                        memcpy (&data[i * 6], edges[1][x + 1][y][z + 1].data, copysize);
816
 
                                        break;
817
 
                                case 11:
818
 
                                        findvert (2, x + 1, y + 1, z);
819
 
                                        memcpy (&data[i * 6], edges[2][x + 1][y + 1][z].data, copysize);
820
 
                                }
821
 
                        }
822
 
                        surface->addstrip (nedges, data);
823
 
                        counter += (nedges + 1);
824
 
                        nedges = cubetable[index][counter];
825
 
                }
826
 
        }
827
 
}
828
 
 
829
 
// find value at all corners of this cube
830
 
inline void impCubeVolume::findcornervalues (int x, int y, int z)
831
 
{
832
 
        if (!corners[x][y][z].done) {
833
 
                corners[x][y][z].value = function (corners[x][y][z].position);
834
 
                corners[x][y][z].done = 1;
835
 
        }
836
 
        z++;
837
 
        if (!corners[x][y][z].done) {
838
 
                corners[x][y][z].value = function (corners[x][y][z].position);
839
 
                corners[x][y][z].done = 1;
840
 
        }
841
 
        y++;
842
 
        if (!corners[x][y][z].done) {
843
 
                corners[x][y][z].value = function (corners[x][y][z].position);
844
 
                corners[x][y][z].done = 1;
845
 
        }
846
 
        z--;
847
 
        if (!corners[x][y][z].done) {
848
 
                corners[x][y][z].value = function (corners[x][y][z].position);
849
 
                corners[x][y][z].done = 1;
850
 
        }
851
 
        x++;
852
 
        if (!corners[x][y][z].done) {
853
 
                corners[x][y][z].value = function (corners[x][y][z].position);
854
 
                corners[x][y][z].done = 1;
855
 
        }
856
 
        z++;
857
 
        if (!corners[x][y][z].done) {
858
 
                corners[x][y][z].value = function (corners[x][y][z].position);
859
 
                corners[x][y][z].done = 1;
860
 
        }
861
 
        y--;
862
 
        if (!corners[x][y][z].done) {
863
 
                corners[x][y][z].value = function (corners[x][y][z].position);
864
 
                corners[x][y][z].done = 1;
865
 
        }
866
 
        z--;
867
 
        if (!corners[x][y][z].done) {
868
 
                corners[x][y][z].value = function (corners[x][y][z].position);
869
 
                corners[x][y][z].done = 1;
870
 
        }
871
 
}
872
 
 
873
 
inline void impCubeVolume::findvert (int axis, int x, int y, int z)
874
 
{
875
 
        // values used to determine the normal vector
876
 
        static float no, nx, ny, nz;
877
 
        static float pos[3];
878
 
        static int copysize = 3 * sizeof (float);
879
 
 
880
 
        if (edges[axis][x][y][z].done)
881
 
                return;
882
 
        edges[axis][x][y][z].done = 1;
883
 
 
884
 
        // find position of vertex along this edge
885
 
        switch (axis) {
886
 
        case 0:         // x-axis
887
 
                edges[axis][x][y][z].data[3] = corners[x][y][z].position[0]
888
 
                        + (cubewidth * ((surfacevalue - corners[x][y][z].value)
889
 
                                        / (corners[x + 1][y][z].value - corners[x][y][z].value)));
890
 
                edges[axis][x][y][z].data[4] = corners[x][y][z].position[1];
891
 
                edges[axis][x][y][z].data[5] = corners[x][y][z].position[2];
892
 
                break;
893
 
        case 1:         // y-axis
894
 
                edges[axis][x][y][z].data[3] = corners[x][y][z].position[0];
895
 
                edges[axis][x][y][z].data[4] = corners[x][y][z].position[1]
896
 
                        + (cubewidth * ((surfacevalue - corners[x][y][z].value)
897
 
                                        / (corners[x][y + 1][z].value - corners[x][y][z].value)));
898
 
                edges[axis][x][y][z].data[5] = corners[x][y][z].position[2];
899
 
                break;
900
 
        case 2:         // z-axis
901
 
                edges[axis][x][y][z].data[3] = corners[x][y][z].position[0];
902
 
                edges[axis][x][y][z].data[4] = corners[x][y][z].position[1];
903
 
                edges[axis][x][y][z].data[5] = corners[x][y][z].position[2]
904
 
                        + (cubewidth * ((surfacevalue - corners[x][y][z].value)
905
 
                                        / (corners[x][y][z + 1].value - corners[x][y][z].value)));
906
 
        }
907
 
 
908
 
        // find normal vector at vertex along this edge
909
 
        // first find normal vector origin value
910
 
        memcpy (pos, &(edges[axis][x][y][z].data[3]), copysize);
911
 
        no = function (pos);
912
 
        // then find values at slight displacements and subtract
913
 
        pos[0] -= 0.01f;
914
 
        nx = function (pos) - no;
915
 
        pos[0] += 0.01f;
916
 
        pos[1] -= 0.01f;
917
 
        ny = function (pos) - no;
918
 
        pos[1] += 0.01f;
919
 
        pos[2] -= 0.01f;
920
 
        nz = function (pos) - no;
921
 
        // then normalize
922
 
        no = 1.0f / sqrt (nx * nx + ny * ny + nz * nz);
923
 
        edges[axis][x][y][z].data[0] = nx * no;
924
 
        edges[axis][x][y][z].data[1] = ny * no;
925
 
        edges[axis][x][y][z].data[2] = nz * no;
926
 
}