00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "carol_glsl.h"
00019
00020 #define DEBUG_OPENGL 1
00021
00022 #define VOLUME_SHADERS_DIR "./glsl_volumeShaders"
00023 #define SHADERS_DIR "./shaders"
00024 #define BACKGROUND_IMAGE "backgrounds/chess.ppm"
00025 #define SPHEREMAP "spheremaps/grace_probe.ppm"
00026
00027 #define FORCE_POWER_OF_TWO_TEXTURE 0
00028 #define NORMALIZE_VOLUME_DATA 1
00029 #define WRITE_FLOAT_GRADIENTS 0
00030
00031 #define SOBEL 1
00032 #define GRAD_FILTER_SIZE 5
00033 #define SIGMA2 5.0
00034
00035 #define MOUSE_SCALE 10.0
00036
00037 #define FRAG_PROG_EXT ".fp"
00038 #define AA_FRAG_PROG_EXT ".fpa"
00039 #define VOL_FILE_EXT ".dat"
00040 #define SETTINGS_EXT ".stg"
00041 #define GRADIENTS_EXT ".grd"
00042
00043 #define MAX_FRAMES 50
00044
00045 #define WINDOW_WIDTH 512
00046 #define WINDOW_HEIGHT 512
00047
00048 #define FOVY 60.0
00049 #define NEAR_CLIP 0.1
00050 #define FAR_CLIP 3.0
00051
00052 #define SLICE_STEP .1
00053 #define MAX_SLICE_THICKNESS 10.0
00054 #define MIN_SLICE_THICKNESS SLICE_STEP
00055
00056 #define STEPSIZE_STEP .001
00057 #define MAX_STEPSIZE 1.0
00058 #define MIN_STEPSIZE 0.0
00059
00060 #define GRAD_SCALE_STEP .01
00061 #define GRAD_OFFSET_STEP .1
00062
00063 #define TEX_COORD_SCALE_STEP .05
00064
00065 #define ISO_VALUE_STEP .005
00066
00067 #define SCATTERING_STEP .5
00068
00069 #define LIGHT_POS_STEP 1.0
00070
00071 #define AA_THRESHOLD_STEP 0.005
00072
00073 #define TEXTURE_TRANSFERFUNCTION "TRANSFERFUNCTION"
00074 #define TEXTURE_OPTICALDENSITY "OPTICALDENSITY"
00075 #define TEXTURE_BACKGROUND "BACKGROUND"
00076 #define TEXTURE_CLIPVOLUME "CLIPVOLUME"
00077 #define TEXTURE_SCATTERING "SCATTERING"
00078 #define TEXTURE_SPHEREMAP "SPHEREMAP"
00079 #define TEXTURE_VOLUME "VOLUME"
00080
00081 #ifndef SQR
00082 #define SQR(a) ((a) * (a))
00083 #endif
00084 #define MAX(a,b) ((a) > (b) ? (a) : (b))
00085 #define MIN(a,b) ((a) < (b) ? (a) : (b))
00086
00087
00088 #define CONTINOUS_FPS 0
00089
00090 #if DEBUG_OPENGL == 1
00091 #define CHECK_FOR_OGL_ERROR() \
00092 do { \
00093 GLenum err; \
00094 err = glGetError(); \
00095 if (err != GL_NO_ERROR) \
00096 { \
00097 fprintf(stderr, "%s(%d) glError: %s\n", \
00098 __FILE__, __LINE__, gluErrorString(err)); \
00099 } \
00100 } while(0)
00101 #else
00102 #define CHECK_FOR_OGL_ERROR()
00103 #endif
00104
00105 int getNextPowerOfTwo(int n)
00106 {
00107 int i;
00108
00109 i = 1;
00110 while (i < n) {
00111 i *= 2;
00112 }
00113
00114 return i;
00115 }
00116
00117 unsigned char getVoxel8(int x, int y, int z)
00118 {
00119 return ((unsigned char*)g.volData)[z * g.numSlices[0] * g.numSlices[1] +
00120 y * g.numSlices[0] +
00121 x];
00122 }
00123
00124 unsigned short getVoxel16(int x, int y, int z)
00125 {
00126 return ((unsigned short*)g.volData)[z * g.numSlices[0] * g.numSlices[1] +
00127 y * g.numSlices[0] +
00128 x];
00129 }
00130
00131 float getVoxel(int x, int y, int z, DataType dataType)
00132 {
00133 switch (dataType) {
00134 case DATRAW_UCHAR:
00135 return (float)getVoxel8(x, y, z);
00136 break;
00137 case DATRAW_USHORT:
00138 return (float)getVoxel16(x, y, z);
00139 break;
00140 default:
00141 fprintf(stderr, "Unsupported data type\n");
00142 exit(1);
00143 break;
00144 }
00145 return 0.0;
00146 }
00147
00148 char *getGradientsFilename(void)
00149 {
00150 char *filename;
00151
00152 if (! (filename = (char *)malloc(strlen(g.basename) +
00153 strlen(GRADIENTS_EXT) + 1))) {
00154 fprintf(stderr, "not enough memory for filename\n");
00155 exit(1);
00156 }
00157
00158 strcpy(filename, g.basename);
00159 strcat(filename, GRADIENTS_EXT);
00160
00161 return filename;
00162 }
00163
00164 int loadGradients(void *gradients, int *sizes, DataType dataType)
00165 {
00166 char *filename;
00167 int size;
00168 FILE *fp;
00169
00170 filename = getGradientsFilename();
00171 if (! (fp = fopen(filename, "rb"))) {
00172 fprintf(stderr, "no pre-computed gradients found\n");
00173 return 0;
00174 }
00175
00176 size = 3 * sizes[0] * sizes[1] * sizes[2]
00177 * getDataTypeSize(dataType);
00178 if (fread(gradients, size, 1, fp) != 1) {
00179 fprintf(stderr, "reading gradients failed\n");
00180 exit(1);
00181 }
00182
00183 fclose(fp);
00184
00185 return 1;
00186 }
00187
00188 void saveGradients(void *gradients, int *sizes, DataType dataType)
00189 {
00190 char *filename;
00191 int size;
00192 FILE *fp;
00193
00194 filename = getGradientsFilename();
00195 if (! (fp = fopen(filename, "wb"))) {
00196 perror("cannot open gradients file for writing");
00197 exit(1);
00198 }
00199
00200 size = 3 * sizes[0] * sizes[1] * sizes[2]
00201 * getDataTypeSize(dataType);
00202
00203 if (fwrite(gradients, size, 1, fp) != 1) {
00204 fprintf(stderr, "writing gradients failed\n");
00205 exit(1);
00206 }
00207
00208 fclose(fp);
00209 }
00210
00211 #if WRITE_FLOAT_GRADIENTS == 1
00212 char *getFloatGradientsFilename(void)
00213 {
00214 char floatExt[] = "_float";
00215 char *filename;
00216
00217 if (! (filename = (char *)malloc(strlen(g.basename) +
00218 strlen(floatExt) +
00219 strlen(GRADIENTS_EXT) + 1))) {
00220 fprintf(stderr, "not enough memory for filename\n");
00221 exit(1);
00222 }
00223
00224 strcpy(filename, g.basename);
00225 strcat(filename, floatExt);
00226 strcat(filename, GRADIENTS_EXT);
00227
00228 return filename;
00229 }
00230
00231 void saveFloatGradients(float *gradients, int *sizes)
00232 {
00233 char *filename;
00234 FILE *fp;
00235
00236 filename = getFloatGradientsFilename();
00237 if (! (fp = fopen(filename, "wb"))) {
00238 perror("cannot open gradients file for writing");
00239 exit(1);
00240 }
00241
00242 if (fwrite(gradients, 3 * sizes[0] * sizes[1] * sizes[2] * sizeof(float),
00243 1, fp) != 1) {
00244 fprintf(stderr, "writing float gradients failed\n");
00245 exit(1);
00246 }
00247
00248 fclose(fp);
00249 }
00250 #endif
00251
00252 void computeGradients(float *gradients, int *sizes, DataType dataType)
00253 {
00254 int i, j, k, dir, di, vdi, idz, idy, idx;
00255 float *gp;
00256
00257 static int weights[][3][3][3] = {
00258 {{{-1, -3, -1},
00259 {-3, -6, -3},
00260 {-1, -3, -1}},
00261 {{ 0, 0, 0},
00262 { 0, 0, 0},
00263 { 0, 0, 0}},
00264 {{ 1, 3, 1},
00265 { 3, 6, 3},
00266 { 1, 3, 1}}},
00267 {{{-1, -3, -1},
00268 { 0, 0, 0},
00269 { 1, 3, 1}},
00270 {{-3, -6, -3},
00271 { 0, 0, 0},
00272 { 3, 6, 3}},
00273 {{-1, -3, -1},
00274 { 0, 0, 0},
00275 { 1, 3, 1}}},
00276 {{{-1, 0, 1},
00277 {-3, 0, 3},
00278 {-1, 0, 1}},
00279 {{-3, 0, 3},
00280 {-6, 0, 6},
00281 {-3, 0, 3}},
00282 {{-1, 0, 1},
00283 {-3, 0, 3},
00284 {-1, 0, 1}}}
00285 };
00286
00287 fprintf(stderr, "computing gradients ... may take a while\n");
00288
00289 di = 0;
00290 vdi = 0;
00291 gp = gradients;
00292 for (idz = 0; idz < sizes[2]; idz++) {
00293 for (idy = 0; idy < sizes[1]; idy++) {
00294 for (idx = 0; idx < sizes[0]; idx++) {
00295 #if SOBEL == 1
00296 if (idx > 0 && idx < sizes[0] - 1 &&
00297 idy > 0 && idy < sizes[1] - 1 &&
00298 idz > 0 && idz < sizes[2] - 1) {
00299
00300 for (dir = 0; dir < 3; dir++) {
00301 gp[dir] = 0.0;
00302 for (i = -1; i < 2; i++) {
00303 for (j = -1; j < 2; j++) {
00304 for (k = -1; k < 2; k++) {
00305 gp[dir] += weights[dir][i + 1]
00306 [j + 1]
00307 [k + 1] *
00308 getVoxel(idx + i,
00309 idy + j,
00310 idz + k,
00311 dataType);
00312 }
00313 }
00314 }
00315
00316 gp[dir] /= 2.0 * g.sliceDists[dir];
00317 }
00318 } else {
00319
00320 if (idx < 1) {
00321 gp[0] = (getVoxel(idx + 1, idy, idz, dataType) -
00322 getVoxel(idx, idy, idz, dataType))/
00323 (g.sliceDists[0]);
00324 } else {
00325 gp[0] = (getVoxel(idx, idy, idz, dataType) -
00326 getVoxel(idx - 1, idy, idz, dataType))/
00327 (g.sliceDists[0]);
00328 }
00329
00330
00331 if (idy < 1) {
00332 gp[1] = (getVoxel(idx, idy + 1, idz, dataType) -
00333 getVoxel(idx, idy, idz, dataType))/
00334 (g.sliceDists[1]);
00335 } else {
00336 gp[1] = (getVoxel(idx, idy, idz, dataType) -
00337 getVoxel(idx, idy - 1, idz, dataType))/
00338 (g.sliceDists[1]);
00339 }
00340
00341
00342 if (idz < 1) {
00343 gp[2] = (getVoxel(idx, idy, idz + 1, dataType) -
00344 getVoxel(idx, idy, idz, dataType))/
00345 (g.sliceDists[2]);
00346 } else {
00347 gp[2] = (getVoxel(idx, idy, idz, dataType) -
00348 getVoxel(idx, idy, idz - 1, dataType))/
00349 (g.sliceDists[2]);
00350 }
00351 }
00352 #else
00353
00354 if (idx < 1) {
00355 gp[0] = (getVoxel(idx + 1, idy, idz, dataType) -
00356 getVoxel(idx, idy, idz, dataType))/
00357 (g.sliceDists[0]);
00358 } else if (idx > g.numSlices[0] - 1) {
00359 gp[0] = (getVoxel(idx, idy, idz, dataType) -
00360 getVoxel(idx - 1, idy, idz, dataType))/
00361 (g.sliceDists[0]);
00362 } else {
00363 gp[0] = (getVoxel(idx + 1, idy, idz, dataType) -
00364 getVoxel(idx - 1, idy, idz, dataType))/
00365 (2.0 * g.sliceDists[0]);
00366 }
00367
00368
00369 if (idy < 1) {
00370 gp[1] = (getVoxel(idx, idy + 1, idz, dataType) -
00371 getVoxel(idx, idy, idz, dataType))/
00372 (g.sliceDists[1]);
00373 } else if (idy > g.numSlices[1] - 1) {
00374 gp[1] = (getVoxel(idx, idy, idz, dataType) -
00375 getVoxel(idx, idy - 1, idz, dataType))/
00376 (g.sliceDists[1]);
00377 } else {
00378 gp[1] = (getVoxel(idx, idy + 1, idz, dataType) -
00379 getVoxel(idx, idy - 1, idz, dataType))/
00380 (2.0 * g.sliceDists[1]);
00381 }
00382
00383
00384 if (idz < 1) {
00385 gp[2] = (getVoxel(idx, idy, idz + 1, dataType) -
00386 getVoxel(idx, idy, idz, dataType))/
00387 (g.sliceDists[2]);
00388 } else if (idz > g.numSlices[2] - 1) {
00389 gp[2] = (getVoxel(idx, idy, idz, dataType) -
00390 getVoxel(idx, idy, idz - 1, dataType))/
00391 (g.sliceDists[2]);
00392 } else {
00393 gp[2] = (getVoxel(idx, idy, idz + 1, dataType) -
00394 getVoxel(idx, idy, idz - 1, dataType))/
00395 (2.0 * g.sliceDists[2]);
00396 }
00397 #endif
00398 gp += 3;
00399 }
00400 }
00401 }
00402
00403 }
00404
00405 void filterGradients(float *gradients, int *sizes)
00406 {
00407 int i, j, k, idz, idy, idx, gi, ogi, filterWidth, n, borderDist[3];
00408 float sum, *filteredGradients, ****filter;
00409
00410 fprintf(stderr, "filtering gradients ... may also take a while\n");
00411
00412 if (! (filteredGradients = (float *)malloc(sizes[0] * sizes[1] * sizes[2]
00413 * 3 * sizeof(float)))) {
00414 fprintf(stderr, "not enough memory for filtered gradients\n");
00415 exit(1);
00416 }
00417
00418
00419 if (! (filter = (float ****)malloc((GRAD_FILTER_SIZE/2 + 1) *
00420 sizeof(float ***)))) {
00421 fprintf(stderr, "failed to allocate gradient filter\n");
00422 exit(1);
00423 }
00424
00425 for (i = 0; i < GRAD_FILTER_SIZE/2 + 1; i++) {
00426 if (! (filter[i] = (float ***)malloc((GRAD_FILTER_SIZE) *
00427 sizeof(float **)))) {
00428 fprintf(stderr, "failed to allocate gradient filter\n");
00429 exit(1);
00430 }
00431 }
00432 for (i = 0; i < GRAD_FILTER_SIZE/2 + 1; i++) {
00433 for (j = 0; j < GRAD_FILTER_SIZE; j++) {
00434 if (! (filter[i][j] = (float **)malloc((GRAD_FILTER_SIZE) *
00435 sizeof(float *)))) {
00436 fprintf(stderr, "failed to allocate gradient filter\n");
00437 exit(1);
00438 }
00439 }
00440 }
00441 for (i = 0; i < GRAD_FILTER_SIZE/2 + 1; i++) {
00442 for (j = 0; j < GRAD_FILTER_SIZE; j++) {
00443 for (k = 0; k < GRAD_FILTER_SIZE; k++) {
00444 if (! (filter[i][j][k] = (float *)malloc((GRAD_FILTER_SIZE) *
00445 sizeof(float)))) {
00446 fprintf(stderr, "failed to allocate gradient filter\n");
00447 exit(1);
00448 }
00449 }
00450 }
00451 }
00452
00453 filterWidth = GRAD_FILTER_SIZE/2;
00454
00455
00456 for (n = 0; n <= filterWidth; n++) {
00457 sum = 0.0f;
00458 for (k = -filterWidth; k <= filterWidth; k++) {
00459 for (j = -filterWidth; j <= filterWidth; j++) {
00460 for (i = -filterWidth; i <= filterWidth; i++) {
00461 sum += (filter[n][filterWidth + k]
00462 [filterWidth + j]
00463 [filterWidth + i] =
00464 exp(-(SQR(i) + SQR(j) + SQR(k)) / SIGMA2));
00465 }
00466 }
00467 }
00468 for (k = -filterWidth; k <= filterWidth; k++) {
00469 for (j = -filterWidth; j <= filterWidth; j++) {
00470 for (i = -filterWidth; i <= filterWidth; i++) {
00471 filter[n][filterWidth + k]
00472 [filterWidth + j]
00473 [filterWidth + i] /= sum;
00474 }
00475 }
00476 }
00477 }
00478
00479 gi = 0;
00480
00481 for (idz = 0; idz < sizes[2]; idz++) {
00482 for (idy = 0; idy < sizes[1]; idy++) {
00483 for (idx = 0; idx < sizes[0]; idx++) {
00484 borderDist[0] = MIN(idx, sizes[0] - idx - 1);
00485 borderDist[1] = MIN(idy, sizes[1] - idy - 1);
00486 borderDist[2] = MIN(idz, sizes[2] - idz - 1);
00487
00488 filterWidth = MIN(GRAD_FILTER_SIZE/2,
00489 MIN(MIN(borderDist[0],
00490 borderDist[1]),
00491 borderDist[2]));
00492
00493 for (n = 0; n < 3; n++) {
00494 filteredGradients[gi] = 0.0;
00495 for (k = -filterWidth; k <= filterWidth; k++) {
00496 for (j = -filterWidth; j <= filterWidth; j++) {
00497 for (i = -filterWidth; i <= filterWidth; i++) {
00498 ogi = (((idz + k) * sizes[1] + (idy + j)) *
00499 sizes[0] + (idx + i)) * 3 +
00500 n;
00501 filteredGradients[gi] += filter[filterWidth]
00502 [filterWidth + k]
00503 [filterWidth + j]
00504 [filterWidth + i] *
00505 gradients[ogi];
00506 }
00507 }
00508 }
00509 gi++;
00510 }
00511 }
00512 }
00513 }
00514
00515
00516 memcpy(gradients, filteredGradients,
00517 sizes[0] * sizes[1] * sizes[2] * 3 * sizeof(float));
00518
00519 free(filteredGradients);
00520
00521
00522 for (i = 0; i < GRAD_FILTER_SIZE/2 + 1; i++) {
00523 for (j = 0; j < GRAD_FILTER_SIZE; j++) {
00524 for (k = 0; k < GRAD_FILTER_SIZE; k++) {
00525 free(filter[i][j][k]);
00526 }
00527 }
00528 }
00529 for (i = 0; i < GRAD_FILTER_SIZE/2 + 1; i++) {
00530 for (j = 0; j < GRAD_FILTER_SIZE; j++) {
00531 free(filter[i][j]);
00532 }
00533 }
00534 for (i = 0; i < GRAD_FILTER_SIZE/2 + 1; i++) {
00535 free(filter[i]);
00536 }
00537 free(filter);
00538 }
00539
00540 void quantize8(float *grad, unsigned char *data)
00541 {
00542 float len;
00543 int i;
00544
00545 len = sqrt(SQR(grad[0]) + SQR(grad[1]) + SQR(grad[2]));
00546
00547 if (len < EPS) {
00548 grad[0] = grad[1] = grad[2] = 0.0;
00549 } else {
00550 grad[0] /= len;
00551 grad[1] /= len;
00552 grad[2] /= len;
00553 }
00554
00555 for (i = 0; i < 3; i++) {
00556 data[i] = (unsigned char)((grad[i] + 1.0)/2.0 * UCHAR_MAX);
00557 }
00558 }
00559
00560 void quantize16(float *grad, unsigned short *data)
00561 {
00562 float len;
00563 int i;
00564
00565 len = sqrt(SQR(grad[0]) + SQR(grad[1]) + SQR(grad[2]));
00566
00567 if (len < EPS) {
00568 grad[0] = grad[1] = grad[2] = 0.0;
00569 } else {
00570 grad[0] /= len;
00571 grad[1] /= len;
00572 grad[2] /= len;
00573 }
00574
00575 for (i = 0; i < 3; i++) {
00576 data[i] = (unsigned short)((grad[i] + 1.0)/2.0 * USHRT_MAX);
00577 }
00578 }
00579
00580 void quantizeGradients(float *gradientsIn, void *gradientsOut,
00581 int *sizes, DataType dataType)
00582 {
00583 int idx, idy, idz, di;
00584
00585 di = 0;
00586 for (idz = 0; idz < sizes[2]; idz++) {
00587 for (idy = 0; idy < sizes[1]; idy++) {
00588 for (idx = 0; idx < sizes[0]; idx++) {
00589 switch (dataType) {
00590 case DATRAW_UCHAR:
00591 quantize8(&gradientsIn[di],
00592 &((unsigned char*)gradientsOut)[di]);
00593 break;
00594 case DATRAW_USHORT:
00595 quantize16(&gradientsIn[di],
00596 &((unsigned short*)gradientsOut)[di]);
00597 break;
00598 default:
00599 fprintf(stderr, "unsupported data type\n");
00600 break;
00601 }
00602 di += 3;
00603 }
00604 }
00605 }
00606 }
00607
00608 void addTexture(GLuint texId, GLenum texTarget, const char *texName)
00609 {
00610 Texture *texture;
00611
00612 g.numTextures++;
00613 if (! (g.textures = (Texture *)realloc(g.textures, g.numTextures *
00614 sizeof(Texture)))) {
00615 fprintf(stderr, "not enough memory for textures\n");
00616 exit(1);
00617 }
00618 texture = &g.textures[g.numTextures - 1];
00619
00620 strcpy(texture->name, texName);
00621 texture->target = texTarget;
00622 texture->id = texId;
00623 }
00624
00625 Texture *getTexture(const char *texName)
00626 {
00627 Texture *texture;
00628 int i;
00629
00630 for (i = 0; i < g.numTextures; i++) {
00631 texture = g.textures + i;
00632 if (!strcmp(texture->name, texName)) {
00633 return texture;
00634 }
00635 }
00636 return NULL;
00637 }
00638
00639 void loadVolumeTexture8()
00640 {
00641 unsigned char *voldata = (unsigned char*)g.volData;
00642 unsigned char *data, *gradients, *gp, min, max;
00643 int di, vdi, idz, idy, idx, haveGradients;
00644 GLuint texId;
00645
00646 if (! (data = (unsigned char *)calloc(g.volTexSizes[0] *
00647 g.volTexSizes[1] *
00648 g.volTexSizes[2] * 4,
00649 sizeof(unsigned char)))) {
00650 fprintf(stderr, "not enough memory for volume texture\n");
00651 exit(1);
00652 }
00653
00654 if (! (gradients = (unsigned char *)malloc(g.numSlices[0] *
00655 g.numSlices[1] *
00656 g.numSlices[2] *
00657 3 * sizeof(unsigned char)))) {
00658 fprintf(stderr, "not enough memory for gradients\n");
00659 exit(1);
00660 }
00661
00662 if (! (haveGradients = loadGradients(gradients, g.numSlices, DATRAW_UCHAR))) {
00663 float *tempGradients;
00664
00665 if (! (tempGradients = (float *)malloc(g.numSlices[0] *
00666 g.numSlices[1] *
00667 g.numSlices[2] *
00668 3 * sizeof(float)))) {
00669 fprintf(stderr, "not enough memory for temporary gradients\n");
00670 exit(1);
00671 }
00672 computeGradients(tempGradients, g.numSlices, DATRAW_UCHAR);
00673 filterGradients(tempGradients, g.numSlices);
00674 #if WRITE_FLOAT_GRADIENTS == 1
00675 saveFloatGradients(tempGradients, g.numSlices);
00676 #endif
00677 quantizeGradients(tempGradients, gradients, g.numSlices, DATRAW_UCHAR);
00678 saveGradients(gradients, g.numSlices, DATRAW_UCHAR);
00679
00680 free(tempGradients);
00681 }
00682
00683
00684 di = 0;
00685 min = UCHAR_MAX;
00686 max = 0;
00687 for (idz = 0; idz < g.numSlices[2]; idz++) {
00688 for (idy = 0; idy < g.numSlices[1]; idy++) {
00689 for (idx = 0; idx < g.numSlices[0]; idx++) {
00690 if (voldata[di] > max) {
00691 max = voldata[di];
00692 }
00693 if (voldata[di] < min) {
00694 min = voldata[di];
00695 }
00696 di++;
00697 }
00698 }
00699 }
00700 printf("data range: %d - %d\n", (int)min, (int)max);
00701
00702 di = 0;
00703 vdi = 0;
00704 gp = gradients;
00705
00706 for (idz = 0; idz < g.volTexSizes[2]; idz++) {
00707 for (idy = 0; idy < g.volTexSizes[1]; idy++) {
00708 for (idx = 0; idx < g.volTexSizes[0]; idx++) {
00709 if (idx < g.numSlices[0] &&
00710 idy < g.numSlices[1] &&
00711 idz < g.numSlices[2]) {
00712 memcpy(&data[di], gp, 3);
00713 gp += 3;
00714 #if NORMALIZE_VOLUME_DATA == 1
00715 data[di + 3] = (unsigned char)
00716 ((voldata[vdi++] - min)/(float)(max - min) * UCHAR_MAX);
00717 #else
00718 data[di + 3] = voldata[vdi++];
00719 #endif
00720 }
00721 di += 4;
00722 }
00723 }
00724 }
00725
00726 free(gradients);
00727
00728 glGenTextures(1, &texId);
00729 glBindTexture(GL_TEXTURE_3D, texId);
00730 glTexImage3DEXT(GL_TEXTURE_3D, 0, GL_RGBA, g.volTexSizes[0],
00731 g.volTexSizes[1], g.volTexSizes[2], 0, GL_RGBA,
00732 GL_UNSIGNED_BYTE, data);
00733 addTexture(texId, GL_TEXTURE_3D, TEXTURE_VOLUME);
00734
00735 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00736 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00737 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00738
00739 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00740 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
00741 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00742 free(data);
00743 }
00744
00745 void loadVolumeTexture16()
00746 {
00747 unsigned short *voldata = (unsigned short*)g.volData;
00748 unsigned short *data, *gradients, *gp, min, max;
00749 int di, vdi, idz, idy, idx, haveGradients;
00750 GLuint texId;
00751
00752 if (! (data = (unsigned short *)calloc(g.volTexSizes[0] *
00753 g.volTexSizes[1] *
00754 g.volTexSizes[2] * 4,
00755 sizeof(unsigned short)))) {
00756 fprintf(stderr, "not enough memory for volume texture\n");
00757 exit(1);
00758 }
00759
00760 if (! (gradients = (unsigned short *)malloc(g.numSlices[0] *
00761 g.numSlices[1] *
00762 g.numSlices[2] * 3
00763 * sizeof(unsigned short)))) {
00764 fprintf(stderr, "not enough memory for gradients\n");
00765 exit(1);
00766 }
00767
00768 if (! (haveGradients = loadGradients(gradients, g.numSlices, DATRAW_USHORT))) {
00769 float *tempGradients;
00770
00771 if (! (tempGradients = (float *)malloc(g.numSlices[0] *
00772 g.numSlices[1] *
00773 g.numSlices[2] *
00774 3 * sizeof(float)))) {
00775 fprintf(stderr, "not enough memory for temporary gradients\n");
00776 exit(1);
00777 }
00778 computeGradients(tempGradients, g.numSlices, DATRAW_USHORT);
00779 filterGradients(tempGradients, g.numSlices);
00780 #if WRITE_FLOAT_GRADIENTS == 1
00781 saveFloatGradients(tempGradients, g.numSlices);
00782 #endif
00783 quantizeGradients(tempGradients, gradients, g.numSlices, DATRAW_USHORT);
00784 saveGradients(gradients, g.numSlices, DATRAW_USHORT);
00785
00786 free(tempGradients);
00787 }
00788
00789
00790 di = 0;
00791 min = USHRT_MAX;
00792 max = 0;
00793 for (idz = 0; idz < g.numSlices[2]; idz++) {
00794 for (idy = 0; idy < g.numSlices[1]; idy++) {
00795 for (idx = 0; idx < g.numSlices[0]; idx++) {
00796 if (voldata[di] > max) {
00797 max = voldata[di];
00798 }
00799 if (voldata[di] < min) {
00800 min = voldata[di];
00801 }
00802 di++;
00803 }
00804 }
00805 }
00806 printf("data range: %d - %d\n", (int)min, (int)max);
00807
00808
00809 di = 0;
00810 vdi = 0;
00811 gp = gradients;
00812 for (idz = 0; idz < g.volTexSizes[2]; idz++) {
00813 for (idy = 0; idy < g.volTexSizes[1]; idy++) {
00814 for (idx = 0; idx < g.volTexSizes[0]; idx++) {
00815 if (idx < g.numSlices[0] &&
00816 idy < g.numSlices[1] &&
00817 idz < g.numSlices[2]) {
00818 memcpy(&data[di], gp, 6);
00819 gp += 3;
00820 #if NORMALIZE_VOLUME_DATA == 1
00821 data[di + 3] = (unsigned short)
00822 ((voldata[vdi++] - min)/(float)(max - min) * USHRT_MAX);
00823 #else
00824 data[di + 3] = voldata[vdi++];
00825 #endif
00826 }
00827 di += 4;
00828 }
00829 }
00830 }
00831
00832 free(gradients);
00833
00834 glGenTextures(1, &texId);
00835 glBindTexture(GL_TEXTURE_3D, texId);
00836 glTexImage3DEXT(GL_TEXTURE_3D, 0, GL_RGBA16, g.volTexSizes[0],
00837 g.volTexSizes[1], g.volTexSizes[2], 0, GL_RGBA,
00838 GL_UNSIGNED_SHORT, data);
00839
00840 addTexture(texId, GL_TEXTURE_3D, TEXTURE_VOLUME);
00841
00842 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00843 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00844 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00845
00846 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00847 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
00848 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00849
00850 free(data);
00851 }
00852
00853 void loadVolumeTexture(char *filename)
00854 {
00855 int i, numComponents, maxVolTexSize;
00856 float volSizes[3], maxVolSize;
00857 DataType dataType;
00858
00859 readData(filename, g.numSlices, g.sliceDists, (void **)&g.volData,
00860 &dataType, &numComponents);
00861
00862 for (i = 0; i < 3; i++) {
00863 #if FORCE_POWER_OF_TWO_TEXTURE == 1
00864 g.volTexSizes[i] = getNextPowerOfTwo(g.numSlices[i]);
00865 #else
00866 g.volTexSizes[i] = g.numSlices[i];
00867 #endif
00868 }
00869
00870 fprintf(stderr, "volume: %i %i %i\n",
00871 g.volTexSizes[0],
00872 g.volTexSizes[1],
00873 g.volTexSizes[2]);
00874
00875 if (numComponents != 1) {
00876 fprintf(stderr, "invalid volume data set\n");
00877 exit(1);
00878 }
00879
00880 switch(dataType) {
00881 case DATRAW_UCHAR:
00882 loadVolumeTexture8();
00883 break;
00884 case DATRAW_USHORT:
00885 loadVolumeTexture16();
00886 break;
00887 default:
00888 fprintf(stderr, "Only 8bit and 16bit data format supported\n");
00889 exit(1);
00890 }
00891
00892 for (i = 0; i < 3; i++) {
00893 volSizes[i] = g.numSlices[i] * g.sliceDists[i];
00894 }
00895
00896 maxVolSize = MAX(MAX(volSizes[0], volSizes[1]), volSizes[2]);
00897 maxVolTexSize = MAX(MAX(g.volTexSizes[0], g.volTexSizes[1]),
00898 g.volTexSizes[2]);
00899
00900 for (i = 0; i < 3; i++) {
00901 g.scaleFactors[i] = maxVolSize/(g.volTexSizes[i] * g.sliceDists[i]);
00902 g.extents[i] = (g.numSlices[i] * g.sliceDists[i])/maxVolSize;
00903 g.scaleFactorsInv[i] = 1.0/g.scaleFactors[i];
00904 g.center[i] = g.extents[i]/2.0;
00905 }
00906 g.scaleFactorsInv[3] = 1.0;
00907 g.scaleFactors[3] = 0.0;
00908 g.center[3] = 0.0;
00909 }
00910
00911 void updateTransferFunction(void)
00912 {
00913 int i, j, index;
00914
00915 index = 0;
00916 for (j = 0; j < NUM_TE_ENTRIES; j++) {
00917
00918 for (i = 0; i < 4; i++) {
00919 g.tfFunc[index++] = g.dataTE[i][j];
00920 }
00921 }
00922 }
00923
00924 void loadTETexture(void)
00925 {
00926 static int initialized = 0;
00927 static GLuint texId;
00928
00929 if (! initialized) {
00930 glGenTextures(1, &texId);
00931 addTexture(texId, GL_TEXTURE_2D, TEXTURE_TRANSFERFUNCTION);
00932 initialized = 1;
00933 }
00934
00935 glBindTexture(GL_TEXTURE_2D, texId);
00936 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, NUM_TE_ENTRIES, NUM_TE_ENTRIES,
00937 0, GL_RGBA, GL_UNSIGNED_BYTE, g.preIntTable);
00938
00939 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00940 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00941 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00942
00943 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00944 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00945 }
00946
00947 void loadClipTexture(char* filename)
00948 {
00949 int numComponents, i, sizes[3], volTexSizes[3];
00950 unsigned char *temp, *data, noClipData = 255;
00951 DataType dataType;
00952 float dists[3];
00953 GLuint texId;
00954 #if FORCE_POWER_OF_TWO_TEXTURE == 1
00955 int idx, idy, idz;
00956 #endif
00957
00958 if (! filename) {
00959 data = &noClipData;
00960 for (i = 0; i < 3; i++) {
00961 volTexSizes[i] = 1;
00962 }
00963 } else {
00964 readData(filename, sizes, dists, (void**)&temp, &dataType, &numComponents);
00965
00966 if (dataType != DATRAW_UCHAR || numComponents != 1) {
00967 fprintf(stderr, "invalid volume data set\n");
00968 exit(1);
00969 }
00970
00971 for (i = 0; i < 3; i++) {
00972 #if FORCE_POWER_OF_TWO_TEXTURE == 1
00973 volTexSizes[i] = getNextPowerOfTwo(sizes[i]);
00974 #else
00975 volTexSizes[i] = sizes[i];
00976 #endif
00977 }
00978
00979 if (! (data = (unsigned char *)malloc(volTexSizes[0] *
00980 volTexSizes[1] *
00981 volTexSizes[2]))) {
00982 fprintf(stderr, "not enough memory for clip volume data\n");
00983 exit(1);
00984 }
00985
00986 #if FORCE_POWER_OF_TWO_TEXTURE == 1
00987 i = 0;
00988 for (idz = 0; idz < volTexSizes[2]; idz++) {
00989 for (idy = 0; idy < volTexSizes[1]; idy++) {
00990 for (idx = 0; idx < volTexSizes[0]; idx++) {
00991 if (idx < sizes[0] && idy < sizes[1] && idz < sizes[2]) {
00992 data[i] = temp[(idz * sizes[1] + idy) *
00993 sizes[0] + idx];
00994 } else {
00995 data[i] = 0;
00996 }
00997 i++;
00998 }
00999 }
01000 }
01001 #else
01002 memcpy(data, temp, sizes[0] * sizes[1] * sizes[2]);
01003 #endif
01004 }
01005
01006 glGenTextures(1, &texId);
01007 glBindTexture(GL_TEXTURE_3D, texId);
01008 glTexImage3DEXT(GL_TEXTURE_3D, 0, GL_LUMINANCE, volTexSizes[0],
01009 volTexSizes[1], volTexSizes[2], 0, GL_LUMINANCE,
01010 GL_UNSIGNED_BYTE, data);
01011
01012 addTexture(texId, GL_TEXTURE_3D, TEXTURE_CLIPVOLUME);
01013
01014 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
01015 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01016
01017 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
01018 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
01019 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
01020
01021 if (filename) {
01022 free(data);
01023 free(temp);
01024 }
01025 }
01026
01027 void loadBackgroundTexture(void)
01028 {
01029 static int initialized = 0;
01030 static PPMFile image;
01031 static GLuint texId;
01032
01033 if (! initialized) {
01034 glGenTextures(1, &texId);
01035 addTexture(texId, GL_TEXTURE_2D, TEXTURE_BACKGROUND);
01036 ppmRead(BACKGROUND_IMAGE, &image);
01037 initialized = 1;
01038 }
01039
01040 glBindTexture(GL_TEXTURE_2D, texId);
01041
01042 if (g.u.backgroundImage) {
01043 fprintf(stderr, "%i\n", g.u.backgroundImage);
01044 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width, image.height,
01045 0, GL_RGB, GL_UNSIGNED_BYTE, image.data);
01046 } else {
01047 unsigned char rgb[3];
01048 memset(rgb, g.u.backgroundGrayVal, 3);
01049 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1,
01050 0, GL_RGB, GL_UNSIGNED_BYTE, rgb);
01051 }
01052
01053 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01054 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
01055 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01056
01057 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
01058 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
01059 }
01060
01061 void loadSphereMapTexture(void)
01062 {
01063 PPMFile image;
01064 GLuint texId;
01065
01066 glGenTextures(1, &texId);
01067 ppmRead(SPHEREMAP, &image);
01068
01069 glBindTexture(GL_TEXTURE_2D, texId);
01070 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width, image.height,
01071 0, GL_RGB, GL_UNSIGNED_BYTE, image.data);
01072
01073 addTexture(texId, GL_TEXTURE_2D, TEXTURE_SPHEREMAP);
01074
01075 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
01076 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01077
01078 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
01079 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
01080 }
01081
01082 void vertex(float x, float y, float z)
01083 {
01084 glMultiTexCoord3fARB(GL_TEXTURE0_ARB, x, y, z);
01085 glVertex3f(x, y, z);
01086 }
01087
01088 void vertexv(double *coords)
01089 {
01090 glMultiTexCoord3dvARB(GL_TEXTURE0_ARB, coords);
01091 glVertex3dv(coords);
01092 }
01093
01094 void drawQuads(void)
01095 {
01096 glBegin(GL_QUADS);
01097
01098 glNormal3f(0.0, 0.0, -1.0);
01099 glMultiTexCoord4fARB(GL_TEXTURE5_ARB, 0.0, 0.0, -1.0, 0.0);
01100 vertex(0.0, 0.0, 0.0);
01101 vertex(0.0, g.extents[1], 0.0);
01102 vertex(g.extents[0], g.extents[1], 0.0);
01103 vertex(g.extents[0], 0.0, 0.0);
01104
01105
01106 glNormal3f(0.0, 0.0, 1.0);
01107 glMultiTexCoord4fARB(GL_TEXTURE5_ARB, 0.0, 0.0, 1.0, 0.0);
01108 vertex(0.0, 0.0, g.extents[2]);
01109 vertex(g.extents[0], 0.0, g.extents[2]);
01110 vertex(g.extents[0], g.extents[1], g.extents[2]);
01111 vertex(0.0, g.extents[1], g.extents[2]);
01112
01113
01114 glNormal3f(0.0, 1.0, 0.0);
01115 glMultiTexCoord4fARB(GL_TEXTURE5_ARB, 0.0, 1.0, 0.0, 0.0);
01116 vertex(0.0, g.extents[1], 0.0);
01117 vertex(0.0, g.extents[1], g.extents[2]);
01118 vertex(g.extents[0], g.extents[1], g.extents[2]);
01119 vertex(g.extents[0], g.extents[1], 0.0);
01120
01121
01122 glNormal3f(0.0, -1.0, 0.0);
01123 glMultiTexCoord4fARB(GL_TEXTURE5_ARB, 0.0, -1.0, 0.0, 0.0);
01124 vertex(0.0, 0.0, 0.0);
01125 vertex(g.extents[0], 0.0, 0.0);
01126 vertex(g.extents[0], 0.0, g.extents[2]);
01127 vertex(0.0, 0.0, g.extents[2]);
01128
01129
01130 glNormal3f(-1.0, 0.0, 0.0);
01131 glMultiTexCoord4fARB(GL_TEXTURE5_ARB, -1.0, 0.0, 0.0, 0.0);
01132 vertex(0.0, 0.0, 0.0);
01133 vertex(0.0, 0.0, g.extents[2]);
01134 vertex(0.0, g.extents[1], g.extents[2]);
01135 vertex(0.0, g.extents[1], 0.0);
01136
01137
01138 glNormal3f(1.0, 0.0, 0.0);
01139 glMultiTexCoord4fARB(GL_TEXTURE5_ARB, 1.0, 0.0, 0.0, 0.0);
01140 vertex(g.extents[0], 0.0, 0.0);
01141 vertex(g.extents[0], g.extents[1], 0.0);
01142 vertex(g.extents[0], g.extents[1], g.extents[2]);
01143 vertex(g.extents[0], 0.0, g.extents[2]);
01144 glEnd();
01145 }
01146
01147 void drawLight(void)
01148 {
01149 glDisable(GL_LIGHTING);
01150
01151 glColor4f(1.0, 1.0, 0.0, 1.0);
01152
01153 glDisable(GL_CULL_FACE);
01154
01155 glPushMatrix();
01156 glLoadIdentity();
01157 glTranslatef(0.0, 0.0, -g.u.camZ);
01158 glBegin(GL_LINES);
01159 glVertex3f(0.0, 0.0, 0.0);
01160 glVertex3f(g.u.lightPos[0], g.u.lightPos[1], g.u.lightPos[2]);
01161 glEnd();
01162 glTranslatef(g.u.lightPos[0], g.u.lightPos[1], g.u.lightPos[2]);
01163 glutSolidSphere(.1, 8, 8);
01164 glPopMatrix();
01165 }
01166
01167 void drawWireframe(void)
01168 {
01169 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
01170
01171 glDisable(GL_CULL_FACE);
01172
01173 glColor3f(2.0, 3.0, 5.0);
01174 drawQuads();
01175
01176 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
01177 }
01178
01179 void setLight(void)
01180 {
01181 GLfloat transLight[4];
01182 GLfloat invMVM[16];
01183 Vector3 axis;
01184 float angle;
01185
01186 Quaternion_getAngleAxis(g.u.camRot, &angle, &axis);
01187
01188 glPushMatrix();
01189 glLoadIdentity();
01190 glTranslatef(g.center[0], g.center[1], g.center[2]);
01191 glRotatef(-angle * 180.0 / M_PI, axis.x, axis.y, axis.z);
01192 glRotatef(-g.animatedAngle, 0.0, 1.0, 0.0);
01193 glTranslatef(0.0, 0.0, g.u.camZ);
01194 glTranslatef(-g.u.translate[0], -g.u.translate[1], -g.u.translate[2]);
01195
01196 glGetFloatv(GL_MODELVIEW_MATRIX, invMVM);
01197
01198
01199 glPopMatrix();
01200
01201
01202 transLight[0] = invMVM[0] * g.u.lightPos[0] +
01203 invMVM[4] * g.u.lightPos[1] +
01204 invMVM[8] * g.u.lightPos[2] +
01205 invMVM[12];
01206 transLight[1] = invMVM[1] * g.u.lightPos[0] +
01207 invMVM[5] * g.u.lightPos[1] +
01208 invMVM[9] * g.u.lightPos[2] +
01209 invMVM[13];
01210 transLight[2] = invMVM[2] * g.u.lightPos[0] +
01211 invMVM[6] * g.u.lightPos[1] +
01212 invMVM[10] * g.u.lightPos[2] +
01213 invMVM[14];
01214 transLight[3] = 1.0f;
01215
01216 glPushMatrix();
01217 glLoadIdentity();
01218 glLightfv(GL_LIGHT0, GL_POSITION, transLight);
01219 glPopMatrix();
01220 }
01221
01222 void raycastBackground(GLenum destinationBuffer)
01223 {
01224 GLdouble modelview[16], projection[16], vertizes[4][3];
01225 GLint viewport[4];
01226 GLdouble x, y, z;
01227 int i;
01228
01229 float texelHeight = 1.0/(float)g.windowHeight;
01230 float texelWidth = 1.0/(float)g.windowWidth;
01231
01232 activateARBProg(g.currentFragProg);
01233
01234 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
01235 glEnable(GL_CULL_FACE);
01236
01237 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1,
01238 g.u.texCoordScale, 0.0, 0.0, 0.0);
01239
01240 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 2,
01241 g.center);
01242
01243 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 3,
01244 g.extents[0] * g.scaleFactors[0],
01245 g.extents[1] * g.scaleFactors[1],
01246 g.extents[2] * g.scaleFactors[2],
01247 0.0);
01248
01249 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 5,
01250 g.scaleFactors);
01251
01252 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 6,
01253 g.scaleFactorsInv);
01254
01255 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 7,
01256 (1.0 - texelWidth)/(float)g.windowWidth,
01257 (1.0 - texelHeight)/(float)g.windowHeight,
01258 0.5 * texelWidth, 0.5 * texelHeight);
01259
01260 glGetIntegerv(GL_VIEWPORT, viewport);
01261 glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
01262 glGetDoublev(GL_PROJECTION_MATRIX, projection);
01263
01264 for (i = 0; i < 4; i++) {
01265 x = ((i&1)>>0) * viewport[2];
01266 y = ((i&2)>>1) * viewport[3];
01267 z = .5;
01268
01269 gluUnProject(x, y, z, modelview, projection, viewport,
01270 &vertizes[i][0], &vertizes[i][1], &vertizes[i][2]);
01271 }
01272
01273 glBegin(GL_QUADS);
01274 vertexv(vertizes[0]);
01275 vertexv(vertizes[1]);
01276 vertexv(vertizes[3]);
01277 vertexv(vertizes[2]);
01278 glEnd();
01279
01280 deactivateARBProg(g.currentFragProg);
01281
01282 glDrawBuffer(GL_BACK);
01283 }
01284
01285 void renderVolume(void)
01286 {
01287 float texelHeight = 1.0/(float)g.windowHeight;
01288 float texelWidth = 1.0/(float)g.windowWidth;
01289
01290 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1,
01291 g.u.texCoordScale, g.u.numIterations,
01292 g.u.isoValue, 0);
01293
01294 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 2,
01295 g.center);
01296
01297 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 3,
01298 g.extents[0] * g.scaleFactors[0],
01299 g.extents[1] * g.scaleFactors[1],
01300 g.extents[2] * g.scaleFactors[2],
01301 0.0);
01302
01303 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 4,
01304 g.u.scatteringScale, g.u.clipIsoValue,
01305 0.0, 0.0);
01306
01307 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 5,
01308 g.scaleFactors);
01309
01310 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 6,
01311 g.scaleFactorsInv);
01312
01313 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, g.u.stepSize,
01314 g.u.gradScale, g.u.gradOffset, -5.0);
01315
01316 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 7,
01317 (1.0 - texelWidth)/(float)g.windowWidth,
01318 (1.0 - texelHeight)/(float)g.windowHeight,
01319 0.5 * texelWidth, 0.5 * texelHeight);
01320 drawQuads();
01321 }
01322
01323 void raycastVolume()
01324 {
01325 activateARBProg(g.currentFragProg);
01326
01327 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
01328 glDisable(GL_DEPTH_TEST);
01329
01330 glEnable(GL_CULL_FACE);
01331
01332 renderVolume();
01333
01334 deactivateARBProg(g.currentFragProg);
01335 }
01336
01337 void display(void)
01338 {
01339 static int frameCount = 0;
01340 static double t0, t1;
01341 Vector3 axis;
01342 float angle;
01343
01344 if (!g.initialized) {
01345 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01346 glViewport(0, 0, g.windowWidth, g.windowHeight);
01347
01348
01349 glMatrixMode(GL_PROJECTION);
01350 glLoadIdentity();
01351 #if 1
01352 gluPerspective(FOVY, (float)g.windowWidth/(float)g.windowHeight,
01353 NEAR_CLIP, FAR_CLIP);
01354 #else
01355 gluPerspective(FOVY, (float)g.windowWidth/(float)g.windowHeight,
01356 g.u.camZ - 1.0, g.u.camZ + 1.0);
01357 #endif
01358 resizeTE();
01359 CHECK_FOR_OGL_ERROR();
01360 g.initialized = 1;
01361 }
01362
01363 CHECK_FOR_OGL_ERROR();
01364
01365 if (frameCount == 0) {
01366 t0 = timer();
01367 }
01368
01369 glMatrixMode(GL_PROJECTION);
01370 glLoadIdentity();
01371 #if 1
01372 gluPerspective(FOVY, (float)g.windowWidth/(float)g.windowHeight,
01373 NEAR_CLIP, FAR_CLIP);
01374 #else
01375 gluPerspective(FOVY, (float)g.windowWidth/(float)g.windowHeight,
01376 g.u.camZ - 1.0, g.u.camZ + 1.0);
01377 #endif
01378 glMatrixMode(GL_MODELVIEW);
01379 glLoadIdentity();
01380
01381 glTranslatef(g.u.translate[0], g.u.translate[1], g.u.translate[2]);
01382 glTranslatef(0.0, 0.0, -g.u.camZ);
01383 glRotatef(g.animatedAngle, 0.0, 1.0, 0.0);
01384 Quaternion_getAngleAxis(g.u.camRot, &angle, &axis);
01385 glRotatef(angle * 180.0 / M_PI, axis.x, axis.y, axis.z);
01386
01387 glTranslatef(-g.center[0], -g.center[1], -g.center[2]);
01388
01389 setLight();
01390
01391 CHECK_FOR_OGL_ERROR();
01392
01393 glDisable(GL_DEPTH_TEST);
01394 glClear(GL_DEPTH_BUFFER_BIT);
01395
01396
01397 raycastBackground(GL_BACK);
01398
01399 GLSL_raycastVolume();
01400
01401 if (g.u.wireframe) {
01402 drawWireframe();
01403 }
01404
01405 if (g.u.drawLight) {
01406 drawLight();
01407 }
01408
01409
01410 drawTE();
01411
01412 glutSwapBuffers();
01413
01414 frameCount++;
01415
01416 if (frameCount == MAX_FRAMES) {
01417 float fps;
01418
01419 t1 = timer();
01420 fps = (float)MAX_FRAMES/(t1 - t0) * 1000.0;
01421
01422 frameCount = 0;
01423
01424 #if CONTINOUS_FPS == 0
01425 if (fps < g.minFps) {
01426 g.minFps = fps;
01427 }
01428
01429 if (fps > g.maxFps) {
01430 g.maxFps = fps;
01431 }
01432
01433 g.fpsSum += fps;
01434 g.animatedFrames++;
01435 #else
01436 fprintf(stdout, "%f fps\n", fps);
01437 #endif
01438 }
01439 }
01440
01441 void idle(void)
01442 {
01443
01444 if (g.animated) {
01445 g.animatedAngle += 1.0;
01446 if (g.animatedAngle > 359.5) {
01447 #if CONTINOUS_FPS == 0
01448 fprintf(stdout, "minFps: %f\n", g.minFps);
01449 fprintf(stdout, "avgFps: %f\n", g.fpsSum/(float)g.animatedFrames);
01450 fprintf(stdout, "maxFps: %f\n\n", g.maxFps);
01451 g.animatedFrames = 0;
01452 g.minFps = FLT_MAX;
01453 g.fpsSum = 0.0;
01454 g.maxFps = 0.0;
01455 #endif
01456 g.animatedAngle = 0.0;
01457 }
01458 }
01459 glutPostRedisplay();
01460 }
01461
01462 void updatePreIntTable(void)
01463 {
01464 updateTransferFunction();
01465
01466 calcPreIntTable(NUM_TE_ENTRIES, g.u.sliceThickness, g.tfFunc,
01467 g.preIntTable);
01468
01469 loadTETexture();
01470 }
01471
01472 void updateOptDensityTexture(void)
01473 {
01474 static int initialized = 0;
01475 static GLuint texId;
01476
01477 if (! initialized) {
01478 glGenTextures(1, &texId);
01479 addTexture(texId, GL_TEXTURE_1D, TEXTURE_OPTICALDENSITY);
01480 initialized = 1;
01481 }
01482
01483 memcpy(g.optDensity, g.dataTE[4], NUM_TE_ENTRIES);
01484
01485 glBindTexture(GL_TEXTURE_1D, texId);
01486 glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE, NUM_TE_ENTRIES,
01487 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, g.optDensity);
01488
01489 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01490 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
01491 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01492
01493 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
01494 }
01495
01496 void initScatteringTexture(void)
01497 {
01498 unsigned char line[100];
01499 unsigned char *data;
01500 int numEntries;
01501 GLuint texId;
01502 FILE *fp;
01503
01504 if (! (fp = fopen("colortables/colortable_wax.tab", "rb"))) {
01505 fprintf(stderr, "opening scattering colortable failed\n");
01506 exit(1);
01507 }
01508
01509 if (! fgets((char *)line, sizeof(line), fp)) {
01510 fprintf(stderr, "invalid colortable\n");
01511 exit(1);
01512 }
01513
01514 if (sscanf((const char *)line, "%i\n", &numEntries) != 1) {
01515 fprintf(stderr, "invalid colortable\n");
01516 exit(1);
01517 }
01518
01519 if (! (data = (unsigned char *)malloc(numEntries * 3))) {
01520 fprintf(stderr, "not enough memory for scattering colortable\n");
01521 exit(1);
01522 }
01523
01524 if (fread(data, numEntries * 3, 1, fp) != 1) {
01525 fprintf(stderr, "reading scattering colortable failed\n");
01526 exit(1);
01527 }
01528
01529 fclose(fp);
01530
01531 glGenTextures(1, &texId);
01532 glBindTexture(GL_TEXTURE_1D, texId);
01533 glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, numEntries, 0, GL_RGB,
01534 GL_UNSIGNED_BYTE, data);
01535
01536 addTexture(texId, GL_TEXTURE_1D, TEXTURE_SCATTERING);
01537
01538 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
01539 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01540
01541 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
01542 }
01543
01544 void printARBProgs(int numProgs, ARBProgram *progs)
01545 {
01546 ARBProgram *prog;
01547 int i;
01548
01549 for (i = 0; i < numProgs && i < 12; i++) {
01550 prog = &progs[i];
01551 fprintf(stderr, "\tF%i: %s (%i bytes)\n",
01552 i + 1, prog->filename, prog->size);
01553
01554 #if 0
01555 for (j = 0; j < prog->numTextureObjects; j++) {
01556 fprintf(stderr, "\t\ttexture unit %i: %s\n",
01557 prog->textureObjects[j].texUnit,
01558 prog->textureObjects[j].texture.name);
01559 }
01560 #endif
01561 }
01562
01563 fprintf(stderr, "\n");
01564 }
01565
01566 void loadVolumeShaders()
01567 {
01568 loadARBProgs(VOLUME_SHADERS_DIR, FRAG_PROG_EXT,
01569 g.numTextures, g.textures,
01570 &g.numFragProgs, &g.fragProgs);
01571 if (g.numFragProgs <= 0) {
01572 fprintf(stderr, "No shaders found\n");
01573 exit(1);
01574 }
01575 printARBProgs(g.numFragProgs, g.fragProgs);
01576 g.currentFragProg = &g.fragProgs[0];
01577 }
01578
01579 void freeVolumeShaders(void)
01580 {
01581
01582 ARBProgram *prog;
01583 int i;
01584
01585 for (i = 0; i < g.numFragProgs; i++) {
01586 prog = &g.fragProgs[i];
01587
01588 glDeleteProgram(prog->id);
01589
01590 free(prog->filename);
01591 free(prog->prog);
01592 }
01593 free(g.fragProgs);
01594
01595 }
01596
01597 char *getSettingsFilename(void)
01598 {
01599 char *filename;
01600
01601 if (! (filename = (char *)malloc(strlen(g.basename) + 1 +
01602 strlen(g.currentFragProg->filename) - strlen(FRAG_PROG_EXT) +
01603 + strlen(SETTINGS_EXT) + 1))) {
01604 fprintf(stderr, "not enough memory for filename\n");
01605 exit(1);
01606 }
01607
01608 strcpy(filename, g.basename);
01609 strcat(filename, "_");
01610 strcat(filename, g.currentFragProg->filename);
01611 *strrchr(filename, '.') = 0;
01612 strcat(filename, SETTINGS_EXT);
01613
01614 return filename;
01615 }
01616
01617 void saveSettings(void)
01618 {
01619 char *filename;
01620 FILE *fp;
01621 int i;
01622
01623 filename = getSettingsFilename();
01624
01625 fprintf(stderr, "saving settings to file %s\n", filename);
01626
01627 if (! (fp = fopen(filename, "wb"))) {
01628 perror("cannot open settings file for writing");
01629 return;
01630 }
01631
01632 if (fwrite(&g.u, sizeof(UserSettings), 1, fp) != 1) {
01633 fprintf(stderr, "saving user settings failed\n");
01634 exit(1);
01635 }
01636
01637 for (i = 0; i < NUM_TE; i++) {
01638 if (fwrite(g.dataTE[i], NUM_TE_ENTRIES * sizeof(DataTypeTE),
01639 1, fp) != 1) {
01640 fprintf(stderr, "saving transfer functions failed\n");
01641 exit(1);
01642 }
01643 }
01644
01645 fclose(fp);
01646
01647 free(filename);
01648 }
01649
01650 void loadSettings(void)
01651 {
01652 char *filename;
01653 FILE *fp;
01654 int i;
01655
01656 filename = getSettingsFilename();
01657
01658 fprintf(stderr, "loading settings from file %s\n", filename);
01659
01660 if (! (fp = fopen(filename, "rb"))) {
01661 perror("cannot open settings file for reading");
01662
01663 } else {
01664 if (fread(&g.u, sizeof(UserSettings), 1, fp) != 1) {
01665 fprintf(stderr, "loading user settings failed\n");
01666 exit(1);
01667 }
01668
01669 for (i = 0; i < NUM_TE; i++) {
01670 if (fread(g.dataTE[i], NUM_TE_ENTRIES * sizeof(DataTypeTE),
01671 1, fp) != 1) {
01672 fprintf(stderr, "loading transfer functions failed\n");
01673 exit(1);
01674 }
01675 }
01676 updateOptDensityTexture();
01677 loadBackgroundTexture();
01678 updatePreIntTable();
01679
01680 fclose(fp);
01681 }
01682
01683 free(filename);
01684
01685 glutPostRedisplay();
01686 }
01687
01688 void printSettings(void)
01689 {
01690 Vector3 axis;
01691 float angle;
01692
01693 printf("step size ........................: %g\n", g.u.stepSize);
01694 printf("slice thickness ..................: %g\n", g.u.sliceThickness);
01695 printf("gradient scale ...................: %g\n", g.u.gradScale);
01696 printf("gradient offset ..................: %g\n", g.u.gradOffset);
01697 printf("texture coordinate scale .........: %g\n", g.u.texCoordScale);
01698 printf("isovalue of volume ...............: %g\n", g.u.isoValue);
01699 printf("isovalue of clipping volume ......: %g\n", g.u.clipIsoValue);
01700 printf("isovalue step ....................: %g\n", g.isoValueStep);
01701 printf("number of iterations per loop ....: %i\n", g.u.numIterations);
01702 printf("wireframe mode ...................: %s\n",
01703 g.u.wireframe ? "yes" : "no");
01704 printf("light show mode ..................: %s\n",
01705 g.u.drawLight ? "yes" : "no");
01706 printf("scattering scale .................: %g\n", g.u.scatteringScale);
01707 printf("light source position ............: %.2g %.2g %.2g\n",
01708 g.u.lightPos[0], g.u.lightPos[1], g.u.lightPos[2]);
01709 printf("object translation ...............: %.2g %.2g %.2g\n",
01710 g.u.translate[0], g.u.translate[1], g.u.translate[2]);
01711 printf("camera z-value ...................: %g\n", g.u.camZ);
01712 Quaternion_getAngleAxis(g.u.camRot, &angle, &axis);
01713 printf("camera rotation ..................: (%.2g, %.2g, %.2g) "
01714 "at %g degrees\n", axis.x, axis.y, axis.z, angle);
01715 printf("background image mode ............: %s\n",
01716 g.u.backgroundImage ? "yes" : "no");
01717 printf("background gray value ............: %i\n", g.u.backgroundGrayVal);
01718 printf("\n");
01719 }
01720
01721 void key(unsigned char k, int x, int y)
01722 {
01723 int already_handled;
01724 already_handled = keyTE(k, x, y);
01725
01726 if (already_handled) {
01727 updateOptDensityTexture();
01728 } else {
01729 switch (k) {
01730 case 27:
01731 case 'q':
01732 exit(0);
01733 break;
01734 case '!':
01735 g.initialized = 0;
01736 break;
01737 case 'w':
01738 g.u.wireframe = ! g.u.wireframe;
01739 break;
01740 case 't':
01741 toggleHidden();
01742 break;
01743 case 'p':
01744 updatePreIntTable();
01745 break;
01746 case '+':
01747 g.u.sliceThickness += SLICE_STEP;
01748 if (g.u.sliceThickness > MAX_SLICE_THICKNESS) {
01749 g.u.sliceThickness = MAX_SLICE_THICKNESS;
01750 }
01751 break;
01752 case '-':
01753 g.u.sliceThickness -= SLICE_STEP;
01754 if (g.u.sliceThickness < MIN_SLICE_THICKNESS) {
01755 g.u.sliceThickness = MIN_SLICE_THICKNESS;
01756 }
01757 break;
01758 case '>':
01759 g.u.stepSize += STEPSIZE_STEP;
01760 if (g.u.stepSize > MAX_STEPSIZE) {
01761 g.u.stepSize = MAX_STEPSIZE;
01762 }
01763 break;
01764 case '<':
01765 g.u.stepSize -= STEPSIZE_STEP;
01766 if (g.u.stepSize < MIN_STEPSIZE) {
01767 g.u.stepSize = MIN_STEPSIZE;
01768 }
01769 break;
01770 case ']':
01771 g.u.stepSize *= 2.0;
01772 if (g.u.stepSize > MAX_STEPSIZE) {
01773 g.u.stepSize = MAX_STEPSIZE;
01774 }
01775 break;
01776 case '[':
01777 g.u.stepSize /= 2.0;
01778 if (g.u.stepSize < MIN_STEPSIZE) {
01779 g.u.stepSize = MIN_STEPSIZE;
01780 }
01781 break;
01782 case 's':
01783 g.u.gradScale += GRAD_SCALE_STEP;
01784 fprintf(stderr, "gradient: scale %f, offset %f\n",
01785 g.u.gradScale, g.u.gradOffset);
01786 break;
01787 case 'x':
01788 g.u.gradScale -= GRAD_SCALE_STEP;
01789 break;
01790 case 'd':
01791 g.u.gradOffset += GRAD_OFFSET_STEP;
01792 break;
01793 case 'c':
01794 g.u.gradOffset -= GRAD_OFFSET_STEP;
01795 break;
01796 case 'f':
01797 g.u.texCoordScale += TEX_COORD_SCALE_STEP;
01798 break;
01799 case 'v':
01800 g.u.texCoordScale -= TEX_COORD_SCALE_STEP;
01801 break;
01802 case 'l':
01803 g.u.drawLight = ! g.u.drawLight;
01804 break;
01805 case 'j':
01806 if (glutGetModifiers() & GLUT_ACTIVE_ALT) {
01807 g.isoValueStep *= 2.0;
01808 if (g.isoValueStep > 1.0) {
01809 g.isoValueStep = 1.0;
01810 }
01811 } else {
01812 g.u.isoValue += g.isoValueStep;
01813 if (g.u.isoValue > 1.0) {
01814 g.u.isoValue = 1.0;
01815 }
01816 }
01817 break;
01818 case 'm':
01819 if (glutGetModifiers() & GLUT_ACTIVE_ALT) {
01820 g.isoValueStep /= 2.0;
01821 } else {
01822 g.u.isoValue -= g.isoValueStep;
01823 if (g.u.isoValue < 0.0) {
01824 g.u.isoValue = 0.0;
01825 }
01826 }
01827 break;
01828 case 'J':
01829 g.u.clipIsoValue += g.isoValueStep;
01830 if (g.u.clipIsoValue > 1.0) {
01831 g.u.clipIsoValue = 1.0;
01832 }
01833 break;
01834 case 'M':
01835 g.u.clipIsoValue -= g.isoValueStep;
01836 if (g.u.clipIsoValue < 0.0) {
01837 g.u.clipIsoValue = 0.0;
01838 }
01839 break;
01840 case 'r':
01841 freeVolumeShaders();
01842 loadVolumeShaders();
01843 break;
01844 case '.':
01845 g.u.scatteringScale += SCATTERING_STEP;
01846 break;
01847 case ',':
01848 g.u.scatteringScale -= SCATTERING_STEP;
01849 if (g.u.scatteringScale < 0.0) {
01850 g.u.scatteringScale = 0.0;
01851 }
01852 break;
01853 case '1':
01854 case '2':
01855 case '3':
01856 case '4':
01857 case '5':
01858 case '6': {
01859 int coord = (k - '1')/2;
01860 if ((k - '1')%2) {
01861 g.u.lightPos[coord] += LIGHT_POS_STEP;
01862 } else {
01863 g.u.lightPos[coord] -= LIGHT_POS_STEP;
01864 }
01865 break;
01866 }
01867 case 'S':
01868 saveSettings();
01869 break;
01870 case 'L':
01871 loadSettings();
01872 break;
01873 case 'k':
01874 g.u.backgroundImage = ! g.u.backgroundImage;
01875 loadBackgroundTexture();
01876 break;
01877 case '}':
01878 if (g.u.backgroundGrayVal < 255) {
01879 g.u.backgroundGrayVal++;
01880 loadBackgroundTexture();
01881 }
01882 break;
01883 case '{':
01884 if (g.u.backgroundGrayVal > 0) {
01885 g.u.backgroundGrayVal--;
01886 loadBackgroundTexture();
01887 }
01888 break;
01889 case 'i':
01890 printSettings();
01891 break;
01892 case ' ':
01893 g.animated = ! g.animated;
01894 g.animatedFrames = 0;
01895 g.minFps = FLT_MAX;
01896 g.fpsSum = 0.0;
01897 g.maxFps = 0.0;
01898 g.animatedAngle = 0.0;
01899 break;
01900 }
01901 }
01902
01903 glutPostRedisplay();
01904 }
01905
01906 void special(int key, int x, int y)
01907 {
01908 int num;
01909
01910 if (key >= GLUT_KEY_F1 && key <= GLUT_KEY_F12) {
01911 num = key - GLUT_KEY_F1;
01912
01913 if (num < g.numFragProgs) {
01914 g.currentFragProg = &g.fragProgs[num];
01915 fprintf(stderr, "activated fragment program '%s'\n",
01916 g.currentFragProg->filename);
01917
01918 #if 0
01919 loadSettings();
01920 #endif
01921 glutPostRedisplay();
01922 }
01923 }
01924 }
01925
01926 void mouseMouseInteract(int button, int state, int x, int y)
01927 {
01928 int modifiers = glutGetModifiers();
01929
01930 g.mousePosLast[0] = x;
01931 g.mousePosLast[1] = y;
01932
01933
01934 switch (button) {
01935 case GLUT_LEFT_BUTTON:
01936 if (modifiers & GLUT_ACTIVE_CTRL) {
01937 g.mouseMode = MOUSE_MOVE_LIGHT_XY;
01938 }
01939 else {
01940 g.mouseMode = MOUSE_ROTATE;
01941 }
01942 break;
01943 case GLUT_MIDDLE_BUTTON:
01944 if (modifiers & GLUT_ACTIVE_CTRL) {
01945 }
01946 else {
01947 g.mouseMode = MOUSE_TRANSLATE;
01948 }
01949 break;
01950 case GLUT_RIGHT_BUTTON:
01951 if (modifiers & GLUT_ACTIVE_CTRL) {
01952 g.mouseMode = MOUSE_MOVE_LIGHT_Z;
01953 }
01954 else {
01955 g.mouseMode = MOUSE_DOLLY;
01956 }
01957 break;
01958 default:
01959 break;
01960 }
01961 }
01962
01963 void motionMouseInteract(int x, int y)
01964 {
01965 Vector3 mouseVector, view, rotAxis;
01966 Quaternion rot;
01967
01968 float dx = MOUSE_SCALE * (x - g.mousePosLast[0]) / (float)g.windowWidth;
01969 float dy = MOUSE_SCALE * (g.mousePosLast[1] - y) / (float)g.windowHeight;
01970
01971 mouseVector.x = dx;
01972 mouseVector.y = dy;
01973 mouseVector.z = 0.0;
01974
01975 view.x = 0.0;
01976 view.y = 0.0;
01977 view.z = -1.0;
01978
01979 rotAxis = Vector3_cross(mouseVector, view);
01980 Vector3_normalize(&rotAxis);
01981
01982 switch (g.mouseMode) {
01983 case MOUSE_DOLLY:
01984 g.u.camZ += dy;
01985 break;
01986 case MOUSE_ROTATE:
01987 rot = Quaternion_fromAngleAxis(SQR(dx) + SQR(dy), rotAxis);
01988 g.u.camRot = Quaternion_mult(rot, g.u.camRot);
01989 Quaternion_normalize(&g.u.camRot);
01990 break;
01991 case MOUSE_TRANSLATE:
01992 g.u.translate[0] += mouseVector.x;
01993 g.u.translate[1] += mouseVector.y;
01994 g.u.translate[2] += mouseVector.z;
01995 break;
01996 case MOUSE_MOVE_LIGHT_XY:
01997 g.u.lightPos[0] += dx;
01998 g.u.lightPos[1] += dy;
01999 fprintf(stderr, "lightPos= %f, %f, %f\n", g.u.lightPos[0], g.u.lightPos[1], g.u.lightPos[2]);
02000 break;
02001 case MOUSE_MOVE_LIGHT_Z:
02002 g.u.lightPos[2] -= dy;
02003 fprintf(stderr, "lightPos= %f, %f, %f\n", g.u.lightPos[0], g.u.lightPos[1], g.u.lightPos[2]);
02004 break;
02005 default:
02006 break;
02007 }
02008
02009 g.mousePosLast[0] = x;
02010 g.mousePosLast[1] = y;
02011 }
02012
02013 void mouse(int button, int state, int x, int y)
02014 {
02015 int already_handled;
02016
02017 already_handled = mouseTE(x, y);
02018
02019 if (! already_handled) {
02020 mouseMouseInteract(button, state, x, y);
02021 }
02022
02023 glutPostRedisplay();
02024 }
02025
02026 void motion(int x, int y)
02027 {
02028 int already_handled;
02029
02030 already_handled = motionTE(x, y);
02031
02032 if (already_handled) {
02033 updateOptDensityTexture();
02034 } else {
02035 motionMouseInteract(x, y);
02036 }
02037
02038 glutPostRedisplay();
02039 }
02040
02041 void init(char *volfilename, char *clipfilename)
02042 {
02043 g.initialized = 0;
02044 g.numTextures = 0;
02045 g.textures = NULL;
02046 g.mouseMode = MOUSE_ROTATE;
02047 g.u.camZ = 2.0;
02048 g.u.camRot.x = g.u.camRot.y = g.u.camRot.z = 0.0;
02049 g.u.camRot.w = 1.0;
02050 g.windowWidth = WINDOW_WIDTH;
02051 g.windowHeight = WINDOW_HEIGHT;
02052 g.u.translate[0] = 0.0;
02053 g.u.translate[1] = 0.0;
02054 g.u.translate[2] = 0.0;
02055 g.u.wireframe = 0;
02056 g.u.drawLight = 0;
02057 g.u.stepSize = 1.0/128.0;
02058 g.u.sliceThickness = 1.0;
02059 g.u.gradOffset = .9;
02060 g.u.gradScale = .2;
02061 g.u.texCoordScale = .45;
02062
02063 g.u.numIterations = 255;
02064 g.u.isoValue = 0.5;
02065 g.isoValueStep = ISO_VALUE_STEP;
02066 g.u.clipIsoValue = 0.5;
02067 g.u.scatteringScale = 6.0;
02068 g.u.lightPos[0] = 2.0;
02069 g.u.lightPos[1] = 2.0;
02070 g.u.lightPos[2] = 2.0;
02071 g.u.lightPos[3] = 1.0;
02072 g.u.backgroundImage = 0;
02073 g.u.backgroundGrayVal = 127;
02074 g.animatedAngle = 0.0;
02075 g.animated = 0;
02076 g.minFps = FLT_MAX;
02077 g.fpsSum = 0.0;
02078 g.maxFps = 0.0;
02079
02080 if (! (g.basename = strdup(volfilename))) {
02081 fprintf(stderr, "cannot duplicate filename;\n");
02082 }
02083 if (endsWith(g.basename, VOL_FILE_EXT)) {
02084 *strrchr(g.basename, '.') = 0;
02085 }
02086 fprintf(stderr, "%s\n", g.basename);
02087
02088 if (! (g.preIntTable = (unsigned char *)malloc(NUM_TE_ENTRIES *
02089 NUM_TE_ENTRIES * 4))) {
02090 fprintf(stderr, "not enough memory for preintegrated table\n");
02091 exit(1);
02092 }
02093
02094 if (! (g.tfFunc = (unsigned char *)malloc(4 * NUM_TE_ENTRIES))) {
02095 fprintf(stderr, "not enough memory for transfer function data\n");
02096 exit(1);
02097 }
02098
02099 if (! (g.optDensity = (unsigned char *)malloc(NUM_TE_ENTRIES))) {
02100 fprintf(stderr, "not enough memory for optical density data\n");
02101 exit(1);
02102 }
02103 }
02104
02105 void initOpenGL(char *volfilename, char *clipfilename)
02106 {
02107 GLfloat lightSpecular[] = {1.0, 1.0, 1.0, 1.0};
02108 GLfloat lightAmbient[] = {0.3, 0.3, 0.3, 1.0};
02109 GLfloat lightDiffuse[] = {0.7, 0.7, 0.7, 1.0};
02110
02111 #if 0
02112 fprintf(stdout, "%s\n", glGetString(GL_EXTENSIONS));
02113 #endif
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130 initTE();
02131 g.dataTE = getDataTE();
02132 loadVolumeTexture(volfilename);
02133 loadClipTexture(clipfilename);
02134 loadBackgroundTexture();
02135 loadSphereMapTexture();
02136 updateOptDensityTexture();
02137 initScatteringTexture();
02138 updatePreIntTable();
02139
02140
02141 loadVolumeShaders();
02142 GLSL_init();
02143
02144 glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
02145 glDisable(GL_DEPTH_TEST);
02146
02147 glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
02148 glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
02149 glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular);
02150
02151 CHECK_FOR_OGL_ERROR();
02152 }
02153
02154 void resize(int w, int h)
02155 {
02156 if (h == 0) {
02157 return;
02158 }
02159
02160 g.windowWidth = w;
02161 g.windowHeight = h;
02162
02163 g.initialized = 0;
02164
02165 glutPostRedisplay();
02166 }
02167
02168 int main(int argc, char *argv[])
02169 {
02170 if ( argc != 2 && argc != 3) {
02171 fprintf(stderr, "usage: spvolren <volfilename.dat>\
02172 [<clipfilename.dat>]\n");
02173 exit(1);
02174 }
02175
02176 if (argc == 2) {
02177 init(argv[1], NULL);
02178 } else {
02179 init(argv[1], argv[2]);
02180 }
02181
02182 glutInit(&argc, argv);
02183 glutInitWindowPosition(
02184 (720 - WINDOW_WIDTH)/2,
02185 (576 - WINDOW_HEIGHT)/2);
02186 glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
02187 glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA | GLUT_ALPHA);
02188 glutCreateWindow("Single Pass Volume Raycasting Demo");
02189
02190 if (argc == 2) {
02191 initOpenGL(argv[1], NULL);
02192 } else {
02193 initOpenGL(argv[1], argv[2]);
02194 }
02195
02196 glutDisplayFunc(display);
02197 glutMotionFunc(motion);
02198 glutMouseFunc(mouse);
02199 glutIdleFunc(idle);
02200 glutKeyboardFunc(key);
02201 glutSpecialFunc(special);
02202 glutReshapeFunc(resize);
02203
02204 glutMainLoop();
02205
02206 return 0;
02207 }