- Timestamp:
- Feb 14, 2008, 2:29:02 PM (17 years ago)
- Location:
- trunk/vizservers/nanovis
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/vizservers/nanovis/Command.cpp
r886 r887 4 4 * Command.cpp 5 5 * 6 * 7 * 8 * 9 * 10 * 6 * This modules creates the Tcl interface to the nanovis server. 7 * The communication protocol of the server is the Tcl language. 8 * Commands given to the server by clients are executed in a 9 * safe interpreter and the resulting image rendered offscreen 10 * is returned as BMP-formatted image data. 11 11 * 12 12 * ====================================================================== … … 24 24 /* 25 25 * TODO: In no particular order... 26 * 27 * 28 * 29 * 30 * 31 * 32 * 33 * 34 * 35 * 26 * o Convert to Tcl_CmdObj interface. 27 * o Use Tcl command option parser to reduce size of procedures, remove 28 * lots of extra error checking code. 29 * o Convert GetVolumeIndices to GetVolumes. Goal is to remove 30 * all references of Nanovis::volume[] from this file. Don't 31 * want to know how volumes are stored. Same for heightmaps. 32 * o Rationalize volume id scheme. Right now it's the index in 33 * the vector. 1) Use a list instead of a vector. 2) carry 34 * an id field that's a number that gets incremented each new volume. 35 * o Create R2, matrix, etc. libraries. 36 36 */ 37 37 … … 80 80 extern vector<PointSet*> g_pointSet; 81 81 82 extern float live_rot_x; 82 extern float live_rot_x; //object rotation angles 83 83 extern float live_rot_y; 84 84 extern float live_rot_z; 85 extern float live_obj_x; 85 extern float live_obj_x; //object translation location from the origin 86 86 extern float live_obj_y; 87 87 extern float live_obj_z; … … 92 92 extern Rappture::Outcome load_volume_stream(int index, std::iostream& fin); 93 93 extern Rappture::Outcome load_volume_stream_odx(int index, const char *buf, 94 94 int nBytes); 95 95 extern Rappture::Outcome load_volume_stream2(int index, std::iostream& fin); 96 96 extern void load_volume(int index, int width, int height, int depth, 97 98 97 int n_component, float* data, double vmin, double vmax, 98 double nzero_min); 99 99 extern void load_vector_stream(int index, std::istream& fin); 100 100 … … 147 147 148 148 static int GetVolumeIndices(Tcl_Interp *interp, int argc, const char *argv[], 149 149 vector<unsigned int>* vectorPtr); 150 150 static int GetVolumes(Tcl_Interp *interp, int argc, const char *argv[], 151 151 vector<Volume *>* vectorPtr); 152 152 static int GetVolume(Tcl_Interp *interp, const char *string, 153 153 Volume **volPtrPtr); 154 154 static int GetVolumeIndex(Tcl_Interp *interp, const char *string, 155 155 unsigned int *indexPtr); 156 156 static int GetHeightMap(Tcl_Interp *interp, const char *string, 157 157 HeightMap **hmPtrPtr); 158 158 static int GetIndices(Tcl_Interp *interp, int argc, const char *argv[], 159 159 vector<unsigned int>* vectorPtr); 160 160 static int GetAxis(Tcl_Interp *interp, const char *string, int *valPtr); 161 161 static int GetColor(Tcl_Interp *interp, const char *string, float *rgbPtr); 162 162 static int GetDataStream(Tcl_Interp *interp, Rappture::Buffer &buf, 163 163 int nBytes); 164 164 static HeightMap *CreateHeightMap(ClientData clientData, Tcl_Interp *interp, 165 165 int argc, const char *argv[]); 166 166 167 167 static int … … 171 171 172 172 if (Tcl_GetDouble(interp, string, &value) != TCL_OK) { 173 173 return TCL_ERROR; 174 174 } 175 175 *valuePtr = (float)value; … … 179 179 static int 180 180 GetCullMode(Tcl_Interp *interp, const char *string, 181 181 graphics::RenderContext::CullMode *modePtr) 182 182 { 183 183 if (strcmp(string, "none") == 0) { 184 184 *modePtr = graphics::RenderContext::NO_CULL; 185 185 } else if (strcmp(string, "front") == 0) { 186 186 *modePtr = graphics::RenderContext::FRONT; 187 187 } else if (strcmp(string, "back") == 0) { 188 188 *modePtr = graphics::RenderContext::BACK; 189 189 } else { 190 191 192 190 Tcl_AppendResult(interp, "invalid cull mode \"", string, 191 "\": should be front, back, or none\"", (char *)NULL); 192 return TCL_ERROR; 193 193 } 194 194 return TCL_OK; … … 197 197 static int 198 198 GetShadingModel(Tcl_Interp *interp, const char *string, 199 199 graphics::RenderContext::ShadingModel *modelPtr) 200 200 { 201 201 if (strcmp(string,"flat") == 0) { 202 202 *modelPtr = graphics::RenderContext::FLAT; 203 203 } else if (strcmp(string,"smooth") == 0) { 204 204 *modelPtr = graphics::RenderContext::SMOOTH; 205 205 } else { 206 207 208 206 Tcl_AppendResult(interp, "bad shading model \"", string, 207 "\": should be flat or smooth", (char *)NULL); 208 return TCL_ERROR; 209 209 } 210 210 return TCL_OK; … … 213 213 static int 214 214 GetPolygonMode(Tcl_Interp *interp, const char *string, 215 215 graphics::RenderContext::PolygonMode *modePtr) 216 216 { 217 217 if (strcmp(string,"wireframe") == 0) { 218 218 *modePtr = graphics::RenderContext::LINE; 219 219 } else if (strcmp(string,"fill") == 0) { 220 220 *modePtr = graphics::RenderContext::FILL; 221 221 } else { 222 223 224 222 Tcl_AppendResult(interp, "invalid polygon mode \"", string, 223 "\": should be wireframe or fill\"", (char *)NULL); 224 return TCL_ERROR; 225 225 } 226 226 return TCL_OK; … … 235 235 /* Find the first volume. */ 236 236 for (i = 0; i < NanoVis::n_volumes; i++) { 237 238 239 237 if (NanoVis::volume[i] != NULL) { 238 break; 239 } 240 240 } 241 241 if (i == NanoVis::n_volumes) { 242 243 242 Tcl_AppendResult(interp, "no volumes found", (char *)NULL); 243 return TCL_ERROR; 244 244 } 245 245 Volume *volPtr; … … 249 249 max = volPtr->range_max(); 250 250 for (i++; i < NanoVis::n_volumes; i++) { 251 252 253 254 255 256 257 258 259 260 251 if (NanoVis::volume[i] == NULL) { 252 continue; 253 } 254 volPtr = NanoVis::volume[i]; 255 if (min > volPtr->range_min()) { 256 min = volPtr->range_min(); 257 } 258 if (max < volPtr->range_max()) { 259 max = volPtr->range_max(); 260 } 261 261 } 262 262 *minPtr = min; … … 282 282 { 283 283 if (argc < 2) { 284 285 286 284 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 285 " option arg arg...\"", (char*)NULL); 286 return TCL_ERROR; 287 287 } 288 288 … … 290 290 if ((c == 'a') && (strcmp(argv[1],"angle") == 0)) { 291 291 if (argc != 5) { 292 293 294 292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 293 " angle xangle yangle zangle\"", (char*)NULL); 294 return TCL_ERROR; 295 295 } 296 296 double xangle, yangle, zangle; 297 298 299 300 301 302 297 if ((Tcl_GetDouble(interp, argv[2], &xangle) != TCL_OK) || 298 (Tcl_GetDouble(interp, argv[3], &yangle) != TCL_OK) || 299 (Tcl_GetDouble(interp, argv[4], &zangle) != TCL_OK)) { 300 return TCL_ERROR; 301 } 302 NanoVis::cam->rotate(xangle, yangle, zangle); 303 303 } else if ((c == 'a') && (strcmp(argv[1], "aim") == 0)) { 304 304 if (argc != 5) { 305 306 307 308 } 309 305 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 306 " aim x y z\"", (char*)NULL); 307 return TCL_ERROR; 308 } 309 310 310 double x0, y0, z0; 311 312 313 314 315 316 311 if ((Tcl_GetDouble(interp, argv[2], &x0) != TCL_OK) || 312 (Tcl_GetDouble(interp, argv[3], &y0) != TCL_OK) || 313 (Tcl_GetDouble(interp, argv[4], &z0) != TCL_OK)) { 314 return TCL_ERROR; 315 } 316 NanoVis::cam->aim(x0, y0, z0); 317 317 } else if ((c == 'z') && (strcmp(argv[1],"zoom") == 0)) { 318 318 if (argc != 3) { 319 320 321 322 } 323 319 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 320 " zoom factor\"", (char*)NULL); 321 return TCL_ERROR; 322 } 323 324 324 double zoom; 325 326 327 328 325 if (Tcl_GetDouble(interp, argv[2], &zoom) != TCL_OK) { 326 return TCL_ERROR; 327 } 328 NanoVis::zoom(zoom); 329 329 } else { 330 331 332 330 Tcl_AppendResult(interp, "bad camera option \"", argv[1], 331 "\": should be aim, angle, or zoom", (char*)NULL); 332 return TCL_ERROR; 333 333 } 334 334 … … 349 349 static int 350 350 ScreenShotCmd(ClientData cdata, Tcl_Interp *interp, int argc, 351 351 const char *argv[]) 352 352 { 353 353 #ifdef XINETD … … 372 372 Texture2D* plane = new Texture2D(256, 2, GL_FLOAT, GL_LINEAR, 1, data); 373 373 NanoVis::color_table_renderer->render(1024, 1024, plane, tf, vol->range_min(), 374 374 vol->range_max()); 375 375 delete plane; 376 376 … … 399 399 static int 400 400 CutplaneCmd(ClientData cdata, Tcl_Interp *interp, int argc, 401 401 const char *argv[]) 402 402 { 403 403 if (argc < 2) { … … 429 429 return TCL_ERROR; 430 430 } 431 432 433 431 if (state) { 432 vector<Volume *>::iterator iter; 433 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 434 434 (*iter)->enable_cutplane(axis); 435 436 437 438 435 } 436 } else { 437 vector<Volume *>::iterator iter; 438 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 439 439 (*iter)->disable_cutplane(axis); 440 440 } 441 441 } 442 442 } else if ((c == 'p') && (strcmp(argv[1],"position") == 0)) { … … 454 454 // keep this just inside the volume so it doesn't disappear 455 455 if (relval < 0.01f) { 456 457 458 459 456 relval = 0.01f; 457 } else if (relval > 0.99f) { 458 relval = 0.99f; 459 } 460 460 461 461 int axis; … … 468 468 return TCL_ERROR; 469 469 } 470 471 470 vector<Volume *>::iterator iter; 471 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 472 472 (*iter)->move_cutplane(axis, relval); 473 473 } 474 474 } else { 475 476 477 475 Tcl_AppendResult(interp, "bad option \"", argv[1], 476 "\": should be position or state", (char*)NULL); 477 return TCL_ERROR; 478 478 } 479 479 return TCL_OK; … … 508 508 if (tf == NULL) { 509 509 Tcl_AppendResult(interp, "no transfer function defined for volume \"", 510 510 argv[1], "\"", (char*)NULL); 511 511 return TCL_ERROR; 512 512 } … … 514 514 int width, height; 515 515 if ((Tcl_GetInt(interp, argv[2], &width) != TCL_OK) || 516 516 (Tcl_GetInt(interp, argv[3], &height) != TCL_OK)) { 517 517 return TCL_ERROR; 518 518 } 519 519 float vmin, vmax; 520 520 if (GetVolumeLimits(interp, &vmin, &vmax) != TCL_OK) { 521 521 return TCL_ERROR; 522 522 } 523 523 NanoVis::render_legend(tf, vmin, vmax, width, height, argv[1]); … … 566 566 static int 567 567 TransfuncCmd(ClientData cdata, Tcl_Interp *interp, int argc, 568 568 const char *argv[]) 569 569 { 570 570 if (argc < 2) { 571 572 573 571 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 572 " option arg arg...\"", (char*)NULL); 573 return TCL_ERROR; 574 574 } 575 575 … … 577 577 if ((c == 'd') && (strcmp(argv[1],"define") == 0)) { 578 578 if (argc != 5) { 579 580 579 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 580 " define name colormap alphamap\"", (char*)NULL); 581 581 return TCL_ERROR; 582 582 } … … 586 586 int cmapc, wmapc, i; 587 587 const char **cmapv; 588 589 590 588 const char **wmapv; 589 590 wmapv = cmapv = NULL; 591 591 if (Tcl_SplitList(interp, argv[3], &cmapc, &cmapv) != TCL_OK) { 592 592 return TCL_ERROR; 593 593 } 594 594 if ((cmapc % 4) != 0) { 595 595 Tcl_AppendResult(interp, "bad colormap in transfunc: should be ", 596 596 "{ v r g b ... }", (char*)NULL); 597 598 597 Tcl_Free((char*)cmapv); 598 return TCL_ERROR; 599 599 } 600 600 601 601 if (Tcl_SplitList(interp, argv[4], &wmapc, &wmapv) != TCL_OK) { 602 603 602 Tcl_Free((char*)cmapv); 603 return TCL_ERROR; 604 604 } 605 605 if ((wmapc % 2) != 0) { 606 607 608 609 610 606 Tcl_AppendResult(interp, "wrong # elements in alphamap: should be ", 607 " { v w ... }", (char*)NULL); 608 Tcl_Free((char*)cmapv); 609 Tcl_Free((char*)wmapv); 610 return TCL_ERROR; 611 611 } 612 612 for (i=0; i < cmapc; i += 4) { 613 613 int j; 614 614 double vals[4]; 615 615 616 616 for (j=0; j < 4; j++) { 617 617 if (Tcl_GetDouble(interp, cmapv[i+j], &vals[j]) != TCL_OK) { 618 619 620 618 Tcl_Free((char*)cmapv); 619 Tcl_Free((char*)wmapv); 620 return TCL_ERROR; 621 621 } 622 622 if ((vals[j] < 0.0) || (vals[j] > 1.0)) { 623 623 Tcl_AppendResult(interp, "bad value \"", cmapv[i+j], 624 624 "\": should be in the range 0-1", (char*)NULL); 625 626 627 625 Tcl_Free((char*)cmapv); 626 Tcl_Free((char*)wmapv); 627 return TCL_ERROR; 628 628 } 629 629 } … … 634 634 for (i=0; i < wmapc; i += 2) { 635 635 double vals[2]; 636 636 int j; 637 637 638 638 for (j=0; j < 2; j++) { 639 639 if (Tcl_GetDouble(interp, wmapv[i+j], &vals[j]) != TCL_OK) { 640 641 642 640 Tcl_Free((char*)cmapv); 641 Tcl_Free((char*)wmapv); 642 return TCL_ERROR; 643 643 } 644 644 if ((vals[j] < 0.0) || (vals[j] > 1.0)) { 645 645 Tcl_AppendResult(interp, "bad value \"", wmapv[i+j], 646 646 "\": should be in the range 0-1", (char*)NULL); 647 648 649 647 Tcl_Free((char*)cmapv); 648 Tcl_Free((char*)wmapv); 649 return TCL_ERROR; 650 650 } 651 651 } … … 668 668 // find or create this transfer function 669 669 TransferFunction *tf; 670 671 672 673 674 675 670 tf = NanoVis::get_transfunc(argv[2]); 671 if (tf != NULL) { 672 tf->update(data); 673 } else { 674 tf = NanoVis::set_transfunc(argv[2], nslots, data); 675 } 676 676 } else { 677 678 679 677 Tcl_AppendResult(interp, "bad option \"", argv[1], 678 "\": should be define", (char*)NULL); 679 return TCL_ERROR; 680 680 } 681 681 return TCL_OK; … … 763 763 return TCL_ERROR; 764 764 } 765 766 765 vector<Volume *>::iterator iter; 766 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 767 767 (*iter)->set_label(axis, argv[4]); 768 768 } 769 769 } else { 770 771 772 773 770 Tcl_AppendResult(interp, "bad option \"", argv[2], 771 "\": should be label", (char*)NULL); 772 return TCL_ERROR; 773 } 774 774 } else if ((c == 'd') && (strcmp(argv[1],"data") == 0)) { 775 775 if (argc < 3) { … … 793 793 return TCL_ERROR; 794 794 } 795 796 797 798 799 800 801 802 803 804 805 795 if (state) { 796 vector<Volume *>::iterator iter; 797 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 798 (*iter)->enable_data(); 799 } 800 } else { 801 vector<Volume *>::iterator iter; 802 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 803 (*iter)->disable_data(); 804 } 805 } 806 806 } else if (c == 'f' && strcmp(argv[2], "follows") == 0) { 807 807 if (argc < 4) { … … 817 817 return TCL_ERROR; 818 818 } 819 820 821 822 823 819 820 Rappture::Buffer buf; 821 if (GetDataStream(interp, buf, nbytes) != TCL_OK) { 822 return TCL_ERROR; 823 } 824 824 int n = NanoVis::n_volumes; 825 825 char header[6]; … … 831 831 FILE* fp; 832 832 833 833 fp = fopen("/home/nanohub/vrinside/nv/data/HOON/GaAs_AlGaAs_2QD_B4.nd_zc_1_wf", "rb"); 834 834 if (fp == NULL) { 835 835 printf("cannot open the file\n"); … … 840 840 fread(b, buf.size(), 1, fp); 841 841 fclose(fp); 842 #endif 842 #endif /*_LOCAL_ZINC_TEST_*/ 843 843 printf("Checking header[%s]\n", header); 844 844 fflush(stdout); … … 856 856 #else 857 857 vol = NvZincBlendeReconstructor::getInstance()->loadFromMemory((void*) buf.bytes()); 858 #endif 858 #endif /*_LOCAL_ZINC_TEST_*/ 859 859 860 860 printf("finish loading\n"); … … 892 892 } 893 893 */ 894 #endif 895 896 894 #endif /*__TEST_CODE__*/ 895 } else if (strcmp(header, "<ODX>") == 0) { 896 Rappture::Outcome err; 897 897 898 898 printf("Loading DX using OpenDX library...\n"); … … 905 905 } 906 906 } else { 907 907 Rappture::Outcome err; 908 908 909 909 printf("OpenDX loading...\n"); … … 936 936 } 937 937 938 939 940 941 942 943 944 945 946 947 948 949 950 938 { 939 Volume *volPtr; 940 char info[1024]; 941 float vmin, vmax; 942 943 if (GetVolumeLimits(interp, &vmin, &vmax) != TCL_OK) { 944 return TCL_ERROR; 945 } 946 volPtr = NanoVis::volume[n]; 947 sprintf(info, "nv>data id %d min %g max %g vmin %g vmax %g\n", 948 n, volPtr->range_min(), volPtr->range_max(),vmin, vmax); 949 write(0, info, strlen(info)); 950 } 951 951 } else { 952 953 954 955 952 Tcl_AppendResult(interp, "bad data option \"", argv[2], 953 "\": should be follows or state", (char*)NULL); 954 return TCL_ERROR; 955 } 956 956 } else if (c == 'o' && strcmp(argv[1],"outline") == 0) { 957 957 if (argc < 3) { … … 976 976 return TCL_ERROR; 977 977 } 978 979 980 978 if (state) { 979 vector<Volume *>::iterator iter; 980 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 981 981 (*iter)->enable_outline(); 982 983 984 985 982 } 983 } else { 984 vector<Volume *>::iterator iter; 985 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 986 986 (*iter)->disable_outline(); 987 987 } 988 988 } 989 989 } else if (c == 'v' && strcmp(argv[2],"visible") == 0) { 990 991 992 993 994 } 990 int ivisible; 991 992 if (Tcl_GetBoolean(interp, argv[3], &ivisible) != TCL_OK) { 993 return TCL_ERROR; 994 } 995 995 if (!ivisible) { 996 996 for (int i = 0; i < NanoVis::n_volumes; ++i) { 997 997 if (NanoVis::volume[i]) { 998 999 998 NanoVis::volume[i]->disable_outline(); 999 } 1000 1000 } 1001 1001 } else { 1002 1002 for (int i = 0; i < NanoVis::n_volumes; ++i) { 1003 1003 if (NanoVis::volume[i]) { 1004 1005 1004 NanoVis::volume[i]->enable_outline(); 1005 } 1006 1006 } 1007 1007 } … … 1026 1026 } 1027 1027 else { 1028 1029 1030 1031 1028 Tcl_AppendResult(interp, "bad outline option \"", argv[2], 1029 "\": should be color, visible, or state", (char*)NULL); 1030 return TCL_ERROR; 1031 } 1032 1032 } else if ((c == 's') && (strcmp(argv[1],"shading") == 0)) { 1033 1033 if (argc < 3) { … … 1040 1040 if (argc < 4) { 1041 1041 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1042 1042 " shading transfunc name ?volume ...?\"", (char*)NULL); 1043 1043 return TCL_ERROR; 1044 1044 } 1045 1045 TransferFunction *tf; 1046 1046 tf = NanoVis::get_transfunc(argv[3]); 1047 1047 if (tf == NULL) { 1048 1048 Tcl_AppendResult(interp, "transfer function \"", argv[3], … … 1055 1055 } 1056 1056 vector<Volume *>::iterator iter; 1057 1057 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 1058 1058 NanoVis::vol_renderer->shade_volume(*iter, tf); 1059 1059 // TBD.. … … 1068 1068 if (argc < 4) { 1069 1069 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1070 1070 " shading diffuse value ?volume ...?\"", (char*)NULL); 1071 1071 return TCL_ERROR; 1072 1072 } … … 1126 1126 return TCL_ERROR; 1127 1127 } 1128 1129 1130 1131 1128 int iso_surface = 0; 1129 if (Tcl_GetBoolean(interp, argv[3], &iso_surface) != TCL_OK) { 1130 return TCL_ERROR; 1131 } 1132 1132 vector<Volume *> ivol; 1133 1133 if (GetVolumes(interp, argc-4, argv+4, &ivol) != TCL_OK) { … … 1138 1138 (*iter)->set_isosurface(iso_surface); 1139 1139 } 1140 1141 1142 1143 1144 1145 1140 } else { 1141 Tcl_AppendResult(interp, "bad shading option \"", argv[2], 1142 "\": should be diffuse, opacity, specular, transfunc, or ", 1143 "isosurface", (char*)NULL); 1144 return TCL_ERROR; 1145 } 1146 1146 } else if ((c == 's') && (strcmp(argv[1], "state") == 0)) { 1147 1147 if (argc < 3) { … … 1158 1158 return TCL_ERROR; 1159 1159 } 1160 1161 1162 1160 if (state) { 1161 vector<Volume *>::iterator iter; 1162 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 1163 1163 (*iter)->enable(); 1164 1165 1166 1167 1164 } 1165 } else { 1166 vector<Volume *>::iterator iter; 1167 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 1168 1168 (*iter)->disable(); 1169 1169 } 1170 1170 } 1171 1171 } 1172 1172 else if (strcmp(argv[1],"animation") == 0) { … … 1201 1201 return TCL_OK; 1202 1202 } else { 1203 1204 1205 1203 Tcl_AppendResult(interp, "bad option \"", argv[1], "\": should be ", 1204 "data, outline, shading, or state", (char*)NULL); 1205 return TCL_ERROR; 1206 1206 } 1207 1207 return TCL_OK; … … 1214 1214 1215 1215 if (argc < 2) { 1216 1217 1218 1216 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1217 " option ?arg arg?", (char *)NULL); 1218 return TCL_ERROR; 1219 1219 } 1220 1220 char c = argv[1][0]; 1221 1221 if ((c == 'v') && (strcmp(argv[1], "vectorid") == 0)) { 1222 1223 1224 1225 1226 1222 if (argc != 3) { 1223 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1224 " vectorid volume", (char *)NULL); 1225 return TCL_ERROR; 1226 } 1227 1227 Volume *volPtr; 1228 1228 1229 1229 if (GetVolume(interp, argv[2], &volPtr) != TCL_OK) { 1230 1230 return TCL_ERROR; 1231 1231 } 1232 1232 if (NanoVis::particleRenderer != NULL) { … … 1235 1235 volPtr->depth / (float)volPtr->width, 1236 1236 volPtr->range_max()); 1237 1237 NanoVis::initParticle(); 1238 1238 } 1239 1239 if (NanoVis::licRenderer != NULL) { … … 1251 1251 return TCL_ERROR; 1252 1252 } 1253 1254 1255 1256 1257 1253 int ibool; 1254 if (Tcl_GetBoolean(interp, argv[2], &ibool) != TCL_OK) { 1255 return TCL_ERROR; 1256 } 1257 NanoVis::lic_on = (bool)ibool; 1258 1258 } else if ((c == 'p') && (strcmp(argv[1], "particle") == 0)) { 1259 1259 if (argc < 3) { 1260 1260 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1261 1262 return TCL_ERROR; 1263 } 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1261 " particle visible|slice|slicepos arg \"", (char*)NULL); 1262 return TCL_ERROR; 1263 } 1264 c = argv[2][0]; 1265 if ((c == 'v') && (strcmp(argv[2], "visible") == 0)) { 1266 if (argc != 4) { 1267 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1268 " particle visible on|off\"", (char*)NULL); 1269 return TCL_ERROR; 1270 } 1271 int state; 1272 if (Tcl_GetBoolean(interp, argv[2], &state) != TCL_OK) { 1273 return TCL_ERROR; 1274 } 1275 NanoVis::particle_on = state; 1276 } else if ((c == 's') && (strcmp(argv[2], "slice") == 0)) { 1277 if (argc != 4) { 1278 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1279 " particle slice volume\"", (char*)NULL); 1280 return TCL_ERROR; 1281 } 1282 int axis; 1283 if (GetAxis(interp, argv[3], &axis) != TCL_OK) { 1284 return TCL_ERROR; 1285 } 1286 NanoVis::lic_axis = axis; 1287 } else if ((c == 's') && (strcmp(argv[2], "slicepos") == 0)) { 1288 if (argc != 4) { 1289 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1290 " particle slicepos value\"", (char*)NULL); 1291 return TCL_ERROR; 1292 } 1293 float pos; 1294 if (GetFloat(interp, argv[2], &pos) != TCL_OK) { 1295 return TCL_ERROR; 1296 } 1297 if (pos < 0.0f) { 1298 pos = 0.0f; 1299 } else if (pos > 1.0f) { 1300 pos = 1.0f; 1301 } 1302 switch (NanoVis::lic_axis) { 1303 case 0 : 1304 NanoVis::lic_slice_x = pos; 1305 break; 1306 case 1 : 1307 NanoVis::lic_slice_y = pos; 1308 break; 1309 case 2 : 1310 NanoVis::lic_slice_z = pos; 1311 break; 1312 } 1313 } else { 1314 Tcl_AppendResult(interp, "unknown option \"", argv[2], 1315 "\": should be \"", argv[0], " visible, slice, or slicepos\"", 1316 (char *)NULL); 1317 return TCL_ERROR; 1318 } 1319 1319 } else if ((c == 'r') && (strcmp(argv[1],"reset") == 0)) { 1320 1320 NanoVis::initParticle(); 1321 1321 } else if ((c == 'c') && (strcmp(argv[1],"capture") == 0)) { 1322 1322 if (argc != 3) { 1323 1323 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1324 1325 return TCL_ERROR; 1326 } 1327 1328 1329 1330 1331 1324 " capture numframes\"", (char*)NULL); 1325 return TCL_ERROR; 1326 } 1327 int total_frame_count; 1328 1329 if (Tcl_GetInt(interp, argv[2], &total_frame_count) != TCL_OK) { 1330 return TCL_ERROR; 1331 } 1332 1332 if (NanoVis::licRenderer) { 1333 1334 1333 NanoVis::licRenderer->activate(); 1334 } 1335 1335 if (NanoVis::particleRenderer) { 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 //printf("Read Screen for Writing to file...\n");1355 1356 1357 1358 1359 1360 //printf("Writing to file...\n");1361 1362 1336 NanoVis::particleRenderer->activate(); 1337 } 1338 // Karl 1339 for (int frame_count = 0; frame_count < total_frame_count; 1340 frame_count++) { 1341 1342 // Generate the latest frame and send it back to the client 1343 if (NanoVis::licRenderer && 1344 NanoVis::licRenderer->isActivated()) { 1345 NanoVis::licRenderer->convolve(); 1346 } 1347 if (NanoVis::particleRenderer && 1348 NanoVis::particleRenderer->isActivated()) { 1349 NanoVis::particleRenderer->advect(); 1350 } 1351 NanoVis::offscreen_buffer_capture(); //enable offscreen render 1352 NanoVis::display(); 1353 1354 // printf("Read Screen for Writing to file...\n"); 1355 1356 NanoVis::read_screen(); 1357 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 1358 1359 NanoVis::bmp_write_to_file(frame_count); 1360 // printf("Writing to file...\n"); 1361 } 1362 // put your code... 1363 1363 if (NanoVis::licRenderer) { 1364 1365 1364 NanoVis::licRenderer->deactivate(); 1365 } 1366 1366 if (NanoVis::particleRenderer) { 1367 1368 1367 NanoVis::particleRenderer->deactivate(); 1368 } 1369 1369 NanoVis::initParticle(); 1370 1370 } else if (c == 'd' && strcmp(argv[1],"data") == 0) { 1371 1372 1373 1374 1375 1376 1371 if (argc < 3) { 1372 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1373 " data follows ?args?", (char *)NULL); 1374 return TCL_ERROR; 1375 } 1376 c = argv[2][0]; 1377 1377 if ((c == 'f') && (strcmp(argv[2],"follows") == 0)) { 1378 1379 1380 1381 1382 1378 if (argc != 4) { 1379 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1380 " data follows length", (char *)NULL); 1381 return TCL_ERROR; 1382 } 1383 1383 int nbytes; 1384 1384 if (Tcl_GetInt(interp, argv[3], &nbytes) != TCL_OK) { 1385 1385 return TCL_ERROR; 1386 1386 } 1387 1388 1389 1390 1387 Rappture::Buffer buf; 1388 if (GetDataStream(interp, buf, nbytes) != TCL_OK) { 1389 return TCL_ERROR; 1390 } 1391 1391 int n = NanoVis::n_volumes; 1392 1392 std::stringstream fdata; 1393 1393 fdata.write(buf.bytes(),buf.size()); 1394 1394 load_vector_stream(n, fdata); 1395 1395 Volume *volPtr = NanoVis::volume[n]; 1396 1396 1397 1397 // … … 1410 1410 1411 1411 NanoVis::vol_renderer->add_volume(volPtr, 1412 1412 NanoVis::get_transfunc("default")); 1413 1413 } 1414 1414 } … … 1421 1421 static int 1422 1422 HeightMapCmd(ClientData cdata, Tcl_Interp *interp, int argc, 1423 1423 const char *argv[]) 1424 1424 { 1425 1425 if (argc < 2) { 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1426 srand((unsigned)time(NULL)); 1427 int size = 20 * 200; 1428 double sigma = 5.0; 1429 double mean = exp(0.0) / (sigma * sqrt(2.0)); 1430 float* data = (float*) malloc(sizeof(float) * size); 1431 1432 float x; 1433 for (int i = 0; i < size; ++i) { 1434 x = - 10 + i%20; 1435 data[i] = exp(- (x * x)/(2 * sigma * sigma)) / 1436 (sigma * sqrt(2.0)) / mean * 2 + 1000; 1437 } 1438 1439 HeightMap* heightMap = new HeightMap(); 1440 float minx = 0.0f; 1441 float maxx = 1.0f; 1442 float miny = 0.5f; 1443 float maxy = 3.5f; 1444 heightMap->setHeight(minx, miny, maxx, maxy, 20, 200, data); 1445 heightMap->setColorMap(NanoVis::get_transfunc("default")); 1446 heightMap->setVisible(true); 1447 heightMap->setLineContourVisible(true); 1448 NanoVis::heightMap.push_back(heightMap); 1449 1450 1451 Vector3 min(minx, (float) heightMap->range_min(), miny); 1452 Vector3 max(maxx, (float) heightMap->range_max(), maxy); 1453 1454 NanoVis::grid->setMinMax(min, max); 1455 NanoVis::grid->setVisible(true); 1456 1457 return TCL_OK; 1458 1458 } 1459 1459 1460 1460 char c = argv[1][0]; 1461 1461 if ((c == 'c') && (strcmp(argv[1], "create") == 0)) { 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1462 HeightMap *hMap; 1463 1464 /* heightmap create xmin ymin xmax ymax xnum ynum values */ 1465 hMap = CreateHeightMap(cdata, interp, argc - 2, argv + 2); 1466 if (hMap == NULL) { 1467 return TCL_ERROR; 1468 } 1469 NanoVis::heightMap.push_back(hMap); 1470 /* FIXME: Convert this file to use Tcl_CmdObjProc */ 1471 sprintf(interp->result, "%d", NanoVis::heightMap.size() - 1); 1472 return TCL_OK; 1473 1473 } else if ((c == 'd') && (strcmp(argv[1],"data") == 0)) { 1474 1475 1476 1477 1478 1474 if (argc < 3) { 1475 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1476 " data follows|visible ?args?", (char *)NULL); 1477 return TCL_ERROR; 1478 } 1479 1479 //bytes 1480 1480 char c; 1481 1481 c = argv[2][0]; 1482 1482 if ((c == 'v') && (strcmp(argv[2],"visible") == 0)) { 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1483 if (argc < 4) { 1484 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1485 " data visible bool ?indices?", (char *)NULL); 1486 return TCL_ERROR; 1487 } 1488 int ivisible; 1489 vector<unsigned int> indices; 1490 1491 if (Tcl_GetBoolean(interp, argv[3], &ivisible) != TCL_OK) { 1492 return TCL_ERROR; 1493 } 1494 1494 if (GetIndices(interp, argc-4, argv+4, &indices) != TCL_OK) { 1495 1495 return TCL_ERROR; 1496 1496 } 1497 1498 1497 bool visible; 1498 visible = (bool)ivisible; 1499 1499 for (unsigned int i = 0; i < indices.size(); ++i) { 1500 1500 if ((indices[i] < NanoVis::heightMap.size()) && 1501 1501 (NanoVis::heightMap[indices[i]] != NULL)) { 1502 1502 NanoVis::heightMap[indices[i]]->setVisible(visible); 1503 1503 } 1504 1504 } 1505 1505 } else if ((c == 'f') && (strcmp(argv[2],"follows") == 0)) { 1506 1507 1508 1509 1510 1511 1506 if (argc != 4) { 1507 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1508 " data follow length", (char *)NULL); 1509 return TCL_ERROR; 1510 } 1511 Rappture::Buffer buf; 1512 1512 int nBytes; 1513 1513 … … 1515 1515 return TCL_ERROR; 1516 1516 } 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1517 if (GetDataStream(interp, buf, nBytes) != TCL_OK) { 1518 return TCL_ERROR; 1519 } 1520 buf.append("\0", 1); 1521 if (Tcl_Eval(interp, buf.bytes()) != TCL_OK) { 1522 fprintf(stderr, "error in command: %s\n", 1523 Tcl_GetStringResult(interp)); 1524 fflush(stderr); 1525 return TCL_ERROR; 1526 } 1527 1527 } else { 1528 1529 1530 1531 1528 Tcl_AppendResult(interp, "unknown option \"", argv[2], "\": ", 1529 "should be visible or follows", (char *)NULL); 1530 return TCL_ERROR; 1531 } 1532 1532 } else if ((c == 'l') && (strcmp(argv[1], "linecontour") == 0)) { 1533 1534 1535 1536 1537 1533 if (argc < 3) { 1534 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1535 " linecontour visible|color ?args?", (char *)NULL); 1536 return TCL_ERROR; 1537 } 1538 1538 vector<unsigned int> indices; 1539 1540 1539 char c; 1540 c = argv[2][0]; 1541 1541 if ((c == 'v') && (strcmp(argv[2],"visible") == 0)) { 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1542 if (argc < 4) { 1543 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1544 " linecontour visible boolean ?indices?", (char *)NULL); 1545 return TCL_ERROR; 1546 } 1547 int ivisible; 1548 bool visible; 1549 if (Tcl_GetBoolean(interp, argv[3], &ivisible) != TCL_OK) { 1550 return TCL_ERROR; 1551 } 1552 1552 visible = (bool)ivisible; 1553 1553 if (GetIndices(interp, argc-4, argv+4, &indices) != TCL_OK) { … … 1556 1556 for (unsigned int i = 0; i < indices.size(); ++i) { 1557 1557 if ((indices[i] < NanoVis::heightMap.size()) && 1558 1558 (NanoVis::heightMap[indices[i]] != NULL)) { 1559 1559 NanoVis::heightMap[indices[i]]->setLineContourVisible(visible); 1560 1560 } 1561 1561 } 1562 1562 } else if ((c == 'c') && (strcmp(argv[2],"color") == 0)) { 1563 1564 1565 1566 1567 1563 if (argc < 6) { 1564 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1565 " linecontour color r g b ?indices?", (char *)NULL); 1566 return TCL_ERROR; 1567 } 1568 1568 float r, g, b; 1569 1569 if ((GetFloat(interp, argv[3], &r) != TCL_OK) || … … 1571 1571 (GetFloat(interp, argv[5], &b) != TCL_OK)) { 1572 1572 return TCL_ERROR; 1573 } 1573 } 1574 1574 vector<unsigned int> indices; 1575 1575 if (GetIndices(interp, argc-6, argv+6, &indices) != TCL_OK) { … … 1578 1578 for (unsigned int i = 0; i < indices.size(); ++i) { 1579 1579 if ((indices[i] < NanoVis::heightMap.size()) && 1580 1580 (NanoVis::heightMap[indices[i]] != NULL)) { 1581 1581 NanoVis::heightMap[indices[i]]->setLineContourColor(r, g, b); 1582 1582 } 1583 1583 } 1584 1584 } else { 1585 1586 1587 1588 1585 Tcl_AppendResult(interp, "unknown option \"", argv[2], "\": ", 1586 "should be visible or color", (char *)NULL); 1587 return TCL_ERROR; 1588 } 1589 1589 } else if ((c == 't') && (strcmp(argv[1], "transfunc") == 0)) { 1590 1591 1592 1593 1594 1590 if (argc < 3) { 1591 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1592 " transfunc name ?indices?", (char *)NULL); 1593 return TCL_ERROR; 1594 } 1595 1595 TransferFunction *tf; 1596 1596 1597 1597 tf = NanoVis::get_transfunc(argv[2]); 1598 1598 if (tf == NULL) { 1599 1599 Tcl_AppendResult(interp, "transfer function \"", argv[2], … … 1603 1603 vector<unsigned int> indices; 1604 1604 if (GetIndices(interp, argc - 3, argv + 3, &indices) != TCL_OK) { 1605 1606 1607 1608 1609 1610 1611 1605 return TCL_ERROR; 1606 } 1607 for (unsigned int i = 0; i < indices.size(); ++i) { 1608 if ((indices[i] < NanoVis::heightMap.size()) && 1609 (NanoVis::heightMap[indices[i]] != NULL)) { 1610 NanoVis::heightMap[indices[i]]->setColorMap(tf); 1611 } 1612 1612 } 1613 1613 } else if ((c == 'l') && (strcmp(argv[1], "legend") == 0)) { 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1614 if (argc != 5) { 1615 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1616 " legend index width height\"", (char*)NULL); 1617 return TCL_ERROR; 1618 } 1619 HeightMap *hMap; 1620 if (GetHeightMap(interp, argv[2], &hMap) != TCL_OK) { 1621 return TCL_ERROR; 1622 } 1623 TransferFunction *tf; 1624 tf = hMap->getColorMap(); 1625 if (tf == NULL) { 1626 Tcl_AppendResult(interp, 1627 "no transfer function defined for heightmap \"", argv[1], "\"", 1628 (char*)NULL); 1629 return TCL_ERROR; 1630 } 1631 int width, height; 1632 if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK) || 1633 (Tcl_GetInt(interp, argv[4], &height) != TCL_OK)) { 1634 return TCL_ERROR; 1635 } 1636 NanoVis::render_legend(tf, hMap->range_min(), hMap->range_max(), 1637 width, height, argv[1]); 1638 1638 } else if ((c == 'p') && (strcmp(argv[1], "polygon") == 0)) { 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1639 if (argc != 3) { 1640 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1641 " polygon mode", (char *)NULL); 1642 return TCL_ERROR; 1643 } 1644 graphics::RenderContext::PolygonMode mode; 1645 if (GetPolygonMode(interp, argv[2], &mode) != TCL_OK) { 1646 return TCL_ERROR; 1647 } 1648 NanoVis::renderContext->setPolygonMode(mode); 1649 1649 } else if ((c == 'c') && (strcmp(argv[1], "cull") == 0)) { 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1650 if (argc != 3) { 1651 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1652 " cull mode", (char *)NULL); 1653 return TCL_ERROR; 1654 } 1655 graphics::RenderContext::CullMode mode; 1656 if (GetCullMode(interp, argv[2], &mode) != TCL_OK) { 1657 return TCL_ERROR; 1658 } 1659 NanoVis::renderContext->setCullMode(mode); 1660 1660 } else if ((c == 's') && (strcmp(argv[1], "shade") == 0)) { 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1661 if (argc != 3) { 1662 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1663 " shade model", (char *)NULL); 1664 return TCL_ERROR; 1665 } 1666 graphics::RenderContext::ShadingModel model; 1667 if (GetShadingModel(interp, argv[2], &model) != TCL_OK) { 1668 return TCL_ERROR; 1669 } 1670 NanoVis::renderContext->setShadingModel(model); 1671 1671 } else { 1672 1673 1674 1672 Tcl_AppendResult(interp, "bad option \"", argv[1], 1673 "\": should be data, linecontour, legend, or transfunc", (char*)NULL); 1674 return TCL_ERROR; 1675 1675 } 1676 1676 return TCL_OK; … … 1681 1681 { 1682 1682 if (argc < 2) { 1683 1684 1685 1683 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1684 " option ?args?", (char *)NULL); 1685 return TCL_ERROR; 1686 1686 } 1687 1687 char c = argv[1][0]; 1688 1688 if ((c == 'v') && (strcmp(argv[1],"visible") == 0)) { 1689 1690 1691 1692 1693 1694 1689 int ivisible; 1690 1691 if (Tcl_GetBoolean(interp, argv[2], &ivisible) != TCL_OK) { 1692 return TCL_ERROR; 1693 } 1694 NanoVis::grid->setVisible((bool)ivisible); 1695 1695 } else if ((c == 'l') && (strcmp(argv[1],"linecount") == 0)) { 1696 1696 int x, y, z; … … 1699 1699 (Tcl_GetInt(interp, argv[3], &y) != TCL_OK) || 1700 1700 (Tcl_GetInt(interp, argv[4], &z) != TCL_OK)) { 1701 1702 1703 1704 1705 1701 return TCL_ERROR; 1702 } 1703 if (NanoVis::grid) { 1704 NanoVis::grid->setGridLineCount(x, y, z); 1705 } 1706 1706 } else if ((c == 'a') && (strcmp(argv[1],"axiscolor") == 0)) { 1707 1707 float r, g, b, a; … … 1709 1709 (GetFloat(interp, argv[3], &g) != TCL_OK) || 1710 1710 (GetFloat(interp, argv[4], &b) != TCL_OK)) { 1711 1712 1713 1714 1715 1716 }1717 1718 1719 1711 return TCL_ERROR; 1712 } 1713 a = 1.0f; 1714 if ((argc == 6) && (GetFloat(interp, argv[5], &a) != TCL_OK)) { 1715 return TCL_ERROR; 1716 } 1717 if (NanoVis::grid) { 1718 NanoVis::grid->setAxisColor(r, g, b, a); 1719 } 1720 1720 } else if ((c == 'l') && (strcmp(argv[1],"linecolor") == 0)) { 1721 1721 float r, g, b, a; 1722 1722 if ((GetFloat(interp, argv[2], &r) != TCL_OK) || 1723 1723 (GetFloat(interp, argv[3], &g) != TCL_OK) || 1724 1725 1726 1727 1728 1729 1730 }1731 1732 1733 1724 (GetFloat(interp, argv[4], &b) != TCL_OK)) { 1725 return TCL_ERROR; 1726 } 1727 a = 1.0f; 1728 if ((argc == 6) && (GetFloat(interp, argv[5], &a) != TCL_OK)) { 1729 return TCL_ERROR; 1730 } 1731 if (NanoVis::grid) { 1732 NanoVis::grid->setGridLineColor(r, g, b, a); 1733 } 1734 1734 } else if ((c == 'm') && (strcmp(argv[1],"minmax") == 0)) { 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1735 double x1, y1, z1, x2, y2, z2; 1736 if ((Tcl_GetDouble(interp, argv[2], &x1) != TCL_OK) || 1737 (Tcl_GetDouble(interp, argv[3], &y1) != TCL_OK) || 1738 (Tcl_GetDouble(interp, argv[4], &z1) != TCL_OK) || 1739 (Tcl_GetDouble(interp, argv[5], &x2) != TCL_OK) || 1740 (Tcl_GetDouble(interp, argv[6], &y2) != TCL_OK) || 1741 (Tcl_GetDouble(interp, argv[7], &z2) != TCL_OK)) { 1742 return TCL_ERROR; 1743 } 1744 if (NanoVis::grid) { 1745 NanoVis::grid->setMinMax(Vector3(x1, y1, z1), Vector3(x2, y2, z2)); 1746 } 1747 1747 } else if ((c == 'a') && (strcmp(argv[1],"axisname") == 0)) { 1748 1748 int axisId; 1749 1750 1751 1749 if (GetAxis(interp, argv[2], &axisId) != TCL_OK) { 1750 return TCL_ERROR; 1751 } 1752 1752 if (NanoVis::grid) { 1753 1754 1753 NanoVis::grid->setAxisName(axisId, argv[3]); 1754 } 1755 1755 } else { 1756 1757 1758 1759 1756 Tcl_AppendResult(interp, "bad option \"", argv[1], 1757 "\": should be data, outline, shading, or state", 1758 (char*)NULL); 1759 return TCL_ERROR; 1760 1760 } 1761 1761 return TCL_OK; … … 1772 1772 char c = argv[1][0]; 1773 1773 if ((c == 'v') && (strcmp(argv[1],"visible") == 0)) { 1774 1775 1776 1777 1778 1779 1774 int ivisible; 1775 1776 if (Tcl_GetBoolean(interp, argv[2], &ivisible) != TCL_OK) { 1777 return TCL_ERROR; 1778 } 1779 NanoVis::axis_on = (bool)ivisible; 1780 1780 } else { 1781 1782 1783 1781 Tcl_AppendResult(interp, "bad axis option \"", argv[1], 1782 "\": should be visible", (char*)NULL); 1783 return TCL_ERROR; 1784 1784 } 1785 1785 return TCL_OK; … … 1804 1804 int mapIndex; 1805 1805 if (Tcl_GetInt(interp, string, &mapIndex) != TCL_OK) { 1806 1806 return TCL_ERROR; 1807 1807 } 1808 1808 if ((mapIndex < 0) || (mapIndex >= (int)NanoVis::heightMap.size()) || 1809 1810 1811 1812 1809 (NanoVis::heightMap[mapIndex] == NULL)) { 1810 Tcl_AppendResult(interp, "invalid heightmap index \"", string, "\"", 1811 (char *)NULL); 1812 return TCL_ERROR; 1813 1813 } 1814 1814 *hmPtrPtr = NanoVis::heightMap[mapIndex]; … … 1834 1834 int index; 1835 1835 if (Tcl_GetInt(interp, string, &index) != TCL_OK) { 1836 1836 return TCL_ERROR; 1837 1837 } 1838 1838 if (index < 0) { 1839 1840 1841 1839 Tcl_AppendResult(interp, "can't have negative index \"", string, 1840 "\"", (char*)NULL); 1841 return TCL_ERROR; 1842 1842 } 1843 1843 if (index >= (int)NanoVis::volume.size()) { 1844 1845 1846 1844 Tcl_AppendResult(interp, "index \"", string, 1845 "\" is out of range", (char*)NULL); 1846 return TCL_ERROR; 1847 1847 } 1848 1848 *indexPtr = (unsigned int)index; … … 1868 1868 unsigned int index; 1869 1869 if (GetVolumeIndex(interp, string, &index) != TCL_OK) { 1870 1870 return TCL_ERROR; 1871 1871 } 1872 1872 Volume *vol; 1873 1873 vol = NanoVis::volume[index]; 1874 1874 if (vol == NULL) { 1875 1876 1877 1875 Tcl_AppendResult(interp, "no volume defined for index \"", string, 1876 "\"", (char*)NULL); 1877 return TCL_ERROR; 1878 1878 } 1879 1879 *volPtrPtr = vol; … … 1906 1906 } else { 1907 1907 for (int n = 0; n < argc; n++) { 1908 1909 1910 1911 return TCL_ERROR; 1912 1908 unsigned int index; 1909 1910 if (GetVolumeIndex(interp, argv[n], &index) != TCL_OK) { 1911 return TCL_ERROR; 1912 } 1913 1913 if (NanoVis::volume[index] != NULL) { 1914 1914 vectorPtr->push_back(index); … … 1924 1924 { 1925 1925 for (int n = 0; n < argc; n++) { 1926 1926 int index; 1927 1927 1928 1928 if (Tcl_GetInt(interp, argv[n], &index) != TCL_OK) { 1929 1929 return TCL_ERROR; 1930 1930 } 1931 1932 1933 1934 1935 1931 if (index < 0) { 1932 Tcl_AppendResult(interp, "can't have negative index \"", argv[n], 1933 "\"", (char *)NULL); 1934 return TCL_ERROR; 1935 } 1936 1936 vectorPtr->push_back((unsigned int)index); 1937 1937 } … … 1965 1965 } else { 1966 1966 for (int n = 0; n < argc; n++) { 1967 1968 1969 1970 return TCL_ERROR; 1971 1967 Volume *volPtr; 1968 1969 if (GetVolume(interp, argv[n], &volPtr) != TCL_OK) { 1970 return TCL_ERROR; 1971 } 1972 1972 if (volPtr != NULL) { 1973 1973 vectorPtr->push_back(volPtr); … … 1992 1992 { 1993 1993 if (string[1] == '\0') { 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 1994 char c; 1995 1996 c = tolower((unsigned char)string[0]); 1997 if (c == 'x') { 1998 *valPtr = 0; 1999 return TCL_OK; 2000 } else if (c == 'y') { 2001 *valPtr = 1; 2002 return TCL_OK; 2003 } else if (c == 'z') { 2004 *valPtr = 2; 2005 return TCL_OK; 2006 } 2007 /*FALLTHRU*/ 2008 2008 } 2009 2009 Tcl_AppendResult(interp, "bad axis \"", string, 2010 2010 "\": should be x, y, or z", (char*)NULL); 2011 2011 return TCL_ERROR; 2012 2012 } … … 2037 2037 } 2038 2038 if ((GetFloat(interp, argv[0], rgbPtr + 0) != TCL_OK) || 2039 2040 2039 (GetFloat(interp, argv[1], rgbPtr + 1) != TCL_OK) || 2040 (GetFloat(interp, argv[2], rgbPtr + 2) != TCL_OK)) { 2041 2041 Tcl_Free((char*)argv); 2042 2042 return TCL_ERROR; … … 2049 2049 static int 2050 2050 PlaneNewCmd(ClientData cdata, Tcl_Interp *interp, int argc, 2051 2051 const char *argv[]) 2052 2052 { 2053 2053 fprintf(stderr, "load plane for 2D visualization command\n"); … … 2056 2056 2057 2057 if (argc != 4) { 2058 2059 2060 2058 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 2059 " plane_index w h \"", (char*)NULL); 2060 return TCL_ERROR; 2061 2061 } 2062 2062 if (Tcl_GetInt(interp, argv[1], &index) != TCL_OK) { 2063 2063 return TCL_ERROR; 2064 2064 } 2065 2065 if (Tcl_GetInt(interp, argv[2], &w) != TCL_OK) { 2066 2066 return TCL_ERROR; 2067 2067 } 2068 2068 if (Tcl_GetInt(interp, argv[3], &h) != TCL_OK) { 2069 2069 return TCL_ERROR; 2070 2070 } 2071 2071 … … 2073 2073 char* tmp = new char[int(w*h*sizeof(float))]; 2074 2074 if (tmp == NULL) { 2075 2076 2075 Tcl_AppendResult(interp, "can't allocate stream data", (char *)NULL); 2076 return TCL_ERROR; 2077 2077 } 2078 2078 bzero(tmp, w*h*4); 2079 2079 int status = read(0, tmp, w*h*sizeof(float)); 2080 2080 if (status <= 0) { 2081 exit(0);// Bail out on read error? Should log the2082 2081 exit(0); // Bail out on read error? Should log the 2082 // error and return a non-zero exit status. 2083 2083 } 2084 2084 plane[index] = new Texture2D(w, h, GL_FLOAT, GL_LINEAR, 1, (float*)tmp); … … 2090 2090 static int 2091 2091 PlaneLinkCmd(ClientData cdata, Tcl_Interp *interp, int argc, 2092 2092 const char *argv[]) 2093 2093 { 2094 2094 fprintf(stderr, "link the plane to the 2D renderer command\n"); … … 2097 2097 2098 2098 if (argc != 3) { 2099 2100 2101 2099 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 2100 " plane_index tf_index \"", (char*)NULL); 2101 return TCL_ERROR; 2102 2102 } 2103 2103 if (Tcl_GetInt(interp, argv[1], &plane_index) != TCL_OK) { 2104 2104 return TCL_ERROR; 2105 2105 } 2106 2106 if (Tcl_GetInt(interp, argv[2], &tf_index) != TCL_OK) { 2107 2107 return TCL_ERROR; 2108 2108 } 2109 2109 //plane_render->add_plane(plane[plane_index], tf[tf_index]); … … 2115 2115 static int 2116 2116 PlaneEnableCmd(ClientData cdata, Tcl_Interp *interp, int argc, 2117 2117 const char *argv[]) 2118 2118 { 2119 2119 fprintf(stderr,"enable a plane so the 2D renderer can render it command\n"); 2120 2120 2121 2121 if (argc != 3) { 2122 2123 2124 2122 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 2123 " plane_index mode \"", (char*)NULL); 2124 return TCL_ERROR; 2125 2125 } 2126 2126 int plane_index; 2127 2127 if (Tcl_GetInt(interp, argv[1], &plane_index) != TCL_OK) { 2128 2128 return TCL_ERROR; 2129 2129 } 2130 2130 int mode; 2131 2131 if (Tcl_GetInt(interp, argv[2], &mode) != TCL_OK) { 2132 2132 return TCL_ERROR; 2133 2133 } 2134 2134 if (mode == 0) { 2135 2135 plane_index = -1; 2136 2136 } 2137 2137 plane_render->set_active_plane(plane_index); … … 2325 2325 write(0, &sizes, sizeof(sizes)); 2326 2326 write(0, offsets, offsets_size*sizeof(offsets[0])); 2327 write(0, rle, rle_size); 2327 write(0, rle, rle_size); //unsigned byte 2328 2328 #else 2329 2329 NanoVis::bmp_write("nv>image -bytes"); … … 2337 2337 * GetDataStream -- 2338 2338 * 2339 * 2340 * 2339 * Read the requested number of bytes from standard input into the given 2340 * buffer. The buffer is then decompressed and decoded. 2341 2341 * 2342 2342 * ----------------------------------------------------------------------- … … 2349 2349 clearerr(stdin); 2350 2350 while (nBytes > 0) { 2351 2352 2353 2354 2355 2356 2357 2351 unsigned int chunk; 2352 int nRead; 2353 2354 chunk = (sizeof(buffer) < (unsigned int) nBytes) ? 2355 sizeof(buffer) : nBytes; 2356 nRead = fread(buffer, sizeof(char), chunk, stdin); 2357 if (ferror(stdin)) { 2358 2358 Tcl_AppendResult(interp, "while reading data stream: ", 2359 2360 return TCL_ERROR; 2361 2362 2359 Tcl_PosixError(interp), (char*)NULL); 2360 return TCL_ERROR; 2361 } 2362 if (feof(stdin)) { 2363 2363 Tcl_AppendResult(interp, "premature EOF while reading data stream", 2364 2365 return TCL_ERROR; 2366 2367 2368 2364 (char*)NULL); 2365 return TCL_ERROR; 2366 } 2367 buf.append(buffer, nRead); 2368 nBytes -= nRead; 2369 2369 } 2370 2370 { 2371 2372 2373 2374 2375 2376 2377 2378 2379 2371 Rappture::Outcome err; 2372 2373 err = Rappture::encoding::decode(buf, RPENC_Z|RPENC_B64|RPENC_HDR); 2374 if (err) { 2375 printf("ERROR -- DECODING\n"); 2376 fflush(stdout); 2377 Tcl_AppendResult(interp, err.remark().c_str(), (char*)NULL); 2378 return TCL_ERROR; 2379 } 2380 2380 } 2381 2381 return TCL_OK; … … 2387 2387 * CreateHeightMap -- 2388 2388 * 2389 * 2390 * 2391 * 2392 * 2393 * 2394 * 2395 * 2389 * Creates a heightmap from the given the data. The format of the data 2390 * should be as follows: 2391 * 2392 * xMin, xMax, xNum, yMin, yMax, yNum, heights... 2393 * 2394 * xNum and yNum must be integer values, all others are real numbers. 2395 * The number of heights must be xNum * yNum; 2396 2396 * 2397 2397 * ----------------------------------------------------------------------- … … 2399 2399 static HeightMap * 2400 2400 CreateHeightMap(ClientData clientData, Tcl_Interp *interp, int argc, 2401 2401 const char *argv[]) 2402 2402 { 2403 2403 float xMin, yMin, xMax, yMax; … … 2405 2405 2406 2406 if (argc != 7) { 2407 2408 2409 2410 2407 Tcl_AppendResult(interp, 2408 "wrong # of values: should be xMin yMin xMax yMax xNum yNum heights", 2409 (char *)NULL); 2410 return NULL; 2411 2411 } 2412 2412 if ((GetFloat(interp, argv[0], &xMin) != TCL_OK) || 2413 2414 2415 2416 2417 2418 2413 (GetFloat(interp, argv[1], &yMin) != TCL_OK) || 2414 (GetFloat(interp, argv[2], &xMax) != TCL_OK) || 2415 (GetFloat(interp, argv[3], &yMax) != TCL_OK) || 2416 (Tcl_GetInt(interp, argv[4], &xNum) != TCL_OK) || 2417 (Tcl_GetInt(interp, argv[5], &yNum) != TCL_OK)) { 2418 return NULL; 2419 2419 } 2420 2420 int nValues; 2421 2421 const char **elem; 2422 2422 if (Tcl_SplitList(interp, argv[6], &nValues, &elem) != TCL_OK) { 2423 2423 return NULL; 2424 2424 } 2425 2425 if ((xNum <= 0) || (yNum <= 0)) { 2426 2427 2426 Tcl_AppendResult(interp, "bad number of x or y values", (char *)NULL); 2427 goto error; 2428 2428 } 2429 2429 if (nValues != (xNum * yNum)) { 2430 2431 2430 Tcl_AppendResult(interp, "wrong # of heights", (char *)NULL); 2431 goto error; 2432 2432 } 2433 2433 … … 2435 2435 heights = new float[nValues]; 2436 2436 if (heights == NULL) { 2437 2438 2439 2437 Tcl_AppendResult(interp, "can't allocate array of heights", 2438 (char *)NULL); 2439 goto error; 2440 2440 } 2441 2441 2442 2442 int i; 2443 2443 for (i = 0; i < nValues; i++) { 2444 2445 2446 2447 2444 if (GetFloat(interp, elem[i], heights + i) != TCL_OK) { 2445 delete [] heights; 2446 goto error; 2447 } 2448 2448 } 2449 2449 HeightMap* hMap; … … 2481 2481 2482 2482 if ((argc & 0x01) == 0) { 2483 2484 2485 2486 2483 Tcl_AppendResult(interp, 2484 "wrong number of arguments: should be key-value pairs", 2485 (char *)NULL); 2486 return TCL_ERROR; 2487 2487 } 2488 2488 zValues = NULL; … … 2491 2491 int i; 2492 2492 for (i = 1; i < argc; i += 2) { 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2493 if (strcmp(argv[i], "xmin") == 0) { 2494 if (GetFloat(interp, argv[i+1], &xMin) != TCL_OK) { 2495 return TCL_ERROR; 2496 } 2497 } else if (strcmp(argv[i], "xmax") == 0) { 2498 if (GetFloat(interp, argv[i+1], &xMax) != TCL_OK) { 2499 return TCL_ERROR; 2500 } 2501 } else if (strcmp(argv[i], "xnum") == 0) { 2502 if (Tcl_GetInt(interp, argv[i+1], &xNum) != TCL_OK) { 2503 return TCL_ERROR; 2504 } 2505 if (xNum <= 0) { 2506 Tcl_AppendResult(interp, "bad xnum value: must be > 0", 2507 (char *)NULL); 2508 return TCL_ERROR; 2509 } 2510 } else if (strcmp(argv[i], "ymin") == 0) { 2511 if (GetFloat(interp, argv[i+1], &yMin) != TCL_OK) { 2512 return TCL_ERROR; 2513 } 2514 } else if (strcmp(argv[i], "ymax") == 0) { 2515 if (GetFloat(interp, argv[i+1], &yMax) != TCL_OK) { 2516 return TCL_ERROR; 2517 } 2518 } else if (strcmp(argv[i], "ynum") == 0) { 2519 if (Tcl_GetInt(interp, argv[i+1], &yNum) != TCL_OK) { 2520 return TCL_ERROR; 2521 } 2522 if (yNum <= 0) { 2523 Tcl_AppendResult(interp, "bad ynum value: must be > 0", 2524 (char *)NULL); 2525 return TCL_ERROR; 2526 } 2527 } else if (strcmp(argv[i], "zvalues") == 0) { 2528 const char **zlist; 2529 2530 if (Tcl_SplitList(interp, argv[i+1], &zNum, &zlist) != TCL_OK) { 2531 return TCL_ERROR; 2532 } 2533 int j; 2534 zValues = new float[zNum]; 2535 for (j = 0; j < zNum; j++) { 2536 if (GetFloat(interp, zlist[j], zValues + j) != TCL_OK) { 2537 Tcl_Free((char *)zlist); 2538 return TCL_ERROR; 2539 } 2540 } 2541 Tcl_Free((char *)zlist); 2542 } else { 2543 Tcl_AppendResult(interp, "unknown key \"", argv[i], 2544 "\": should be xmin, xmax, xnum, ymin, ymax, ynum, or zvalues", 2545 (char *)NULL); 2546 return TCL_ERROR; 2547 } 2548 2548 } 2549 2549 if (zValues == NULL) { 2550 2551 2550 Tcl_AppendResult(interp, "missing \"zvalues\" key", (char *)NULL); 2551 return TCL_ERROR; 2552 2552 } 2553 2553 if (zNum != (xNum * yNum)) { 2554 2555 2556 2554 Tcl_AppendResult(interp, "wrong number of z values must be xnum*ynum", 2555 (char *)NULL); 2556 return TCL_ERROR; 2557 2557 } 2558 2558 HeightMap* hMap; -
trunk/vizservers/nanovis/GradientFilter.cpp
r883 r887 1 1 2 #include <stdlib.h> 2 3 #include <float.h> -
trunk/vizservers/nanovis/GradientFilter.h
r883 r887 1 #pragma once; 1 #ifndef _GRADIENT_FILTER_H 2 #define _GRADIENT_FILTER_H 2 3 3 4 typedef enum {DATRAW_UCHAR, DATRAW_FLOAT, DATRAW_USHORT} DataType; … … 7 8 extern void quantizeGradients(float *gradientsIn, void *gradientsOut, 8 9 int *sizes, DataType dataType); 10 11 #endif /*_GRADIENT_FILTER_H*/ -
trunk/vizservers/nanovis/Makefile.in
r884 r887 15 15 bindir = @bindir@ 16 16 libdir = @libdir@ 17 srcdir = @srcdir@ 17 18 includedir = @includedir@ 18 19 mandir = @mandir@ … … 27 28 AUXSRC = config.h define.h global.h 28 29 30 RP_DIR = @RP_DIR@ 29 31 R2INC = ./R2/include 30 32 MATINC = ./newmat11 31 33 32 LIB_DX = -lDXcallm -lm 33 LIB_NANOVIS = -L@RP_DIR@/lib -ltcl8.4 -lGL -lglut -lglui -lGLEW -lCg -lCgGL -pthread -lrappture2 -lb64 -lz 34 INCLUDES = -I@RP_DIR@/include -I@RP2_INCL_DIR@ -I/usr/include/GL -I$(R2INC) -I. -I$(MATINC) 34 DX_DIR = /usr/dx 35 DX_INC_SPEC = -I$(DX_DIR)/include 36 DX_LIB_SPEC = -L$(DX_DIR)/lib_linux -lDXcallm -lm 37 DX_INC_SPEC = -I/usr/include/dx 38 DX_LIB_SPEC = -L/usr/lib/dx/lib_linux -lDXcallm -lm 39 GL_INC_SPEC = -I/usr/include/GL 40 GL_LIB_SPEC = -lGL -lglut -lglui -lGLEW -lCg -lCgGL -lpthread 41 MAT_INC_SPEC = -I$(MATINC) 42 R2_INC_SPEC = -I$(R2INC) 43 RP_INC_SPEC = -I$(RP_DIR)/include -I$(RP_DIR)/include/rappture2 44 RP_LIB_SPEC = -L$(RP_DIR)/lib -lrappture2 -lb64 -lz 45 46 LIBS = \ 47 $(RP_LIB_SPEC) \ 48 -ltcl8.4 \ 49 $(GL_LIB_SPEC) \ 50 $(DX_LIB_SPEC) 51 52 INCLUDES = \ 53 -I. \ 54 $(RP_INC_SPEC) \ 55 $(GL_INC_SPEC) \ 56 $(R2_INC_SPEC) \ 57 $(MAT_INC_SPEC) 35 58 36 59 CFLAGS = @CFLAGS@ … … 112 135 cholesky.o \ 113 136 dxReader.o \ 137 dxReader2.o \ 114 138 evalue.o \ 115 139 fft.o \ … … 150 174 151 175 clean: 152 rm -f *.o nanovis client176 rm -f nanovis client $(OBJS) 153 177 154 178 distclean: clean 155 rm Makefile179 rm -f Makefile *~ 156 180 157 181 nanovis: $(OBJS) 158 $(CC) $(CC_SWITCHES) -o $@ $^ $(LIB _NANOVIS) $(LIB_DX)182 $(CC) $(CC_SWITCHES) -o $@ $^ $(LIBS) 159 183 160 184 client: Socket.o ClientSocket.o RenderClient.o Event.o 161 $(CC) $(CC_SWITCHES) -o $@ $^ $(LIB _NANOVIS) $(LIB_DX)185 $(CC) $(CC_SWITCHES) -o $@ $^ $(LIBS) 162 186 163 187 .cpp.o: … … 167 191 $(CC) $(CC_SWITCHES) -c $^ 168 192 193 dxReader2.o: $(srcdir)/dxReader2.cpp 194 $(CC) -c $(CC_SWITCHES) $(DX_INC_SPEC) $? 169 195 ColorGradient.o: transfer-function/ColorGradient.cpp 170 196 $(CC) $(CC_SWITCHES) -o $@ -c $< -
trunk/vizservers/nanovis/VolumeRenderer.cpp
r884 r887 17 17 #include <R2/R2FilePath.h> 18 18 #include "VolumeRenderer.h" 19 #include "VolumeInterpolator.h" 19 20 #include "NvStdVertexShader.h" 20 21 #include <time.h> -
trunk/vizservers/nanovis/nanovis.cpp
r884 r887 82 82 bool NanoVis::axis_on = true; 83 83 //bool NanoVis::axis_on = false; 84 int NanoVis::win_width = NPIX; 85 int NanoVis::win_height = NPIX; 84 int NanoVis::win_width = NPIX; //size of the render window 85 int NanoVis::win_height = NPIX; //size of the render window 86 86 int NanoVis::n_volumes = 0; 87 87 unsigned char* NanoVis::screen_buffer = NULL; … … 110 110 111 111 // color table for built-in transfer function editor 112 float color_table[256][4]; 112 float color_table[256][4]; 113 113 114 114 /* … … 121 121 void init_event_log(); 122 122 void end_event_log(); 123 double cur_time; 123 double cur_time; //in seconds 124 124 double get_time_interval(); 125 125 */ 126 126 127 int render_window; 127 int render_window; //the handle of the render window; 128 128 129 129 // in Command.cpp … … 140 140 141 141 //bool advect=false; 142 float vert[NMESH*NMESH*3]; 143 float slice_vector[NMESH*NMESH*4]; 142 float vert[NMESH*NMESH*3]; //particle positions in main memory 143 float slice_vector[NMESH*NMESH*4]; //per slice vectors in main memory 144 144 145 145 // maps transfunc name to TransferFunction object … … 149 149 150 150 151 PerfQuery* perf; 151 PerfQuery* perf; //perfromance counter 152 152 153 153 CGprogram m_passthru_fprog; … … 159 159 160 160 // Object rotation angles 161 static float live_rot_x = 90.; 161 static float live_rot_x = 90.; 162 162 static float live_rot_y = 180.; 163 163 static float live_rot_z = -135; 164 164 165 165 // Object translation location from the origin 166 static float live_obj_x = -0.0; 166 static float live_obj_x = -0.0; 167 167 static float live_obj_y = -0.0; 168 168 static float live_obj_z = -2.5; … … 175 175 static int right_last_x; 176 176 static int right_last_y; 177 static bool left_down = false; 177 static bool left_down = false; 178 178 static bool right_down = false; 179 179 #endif /*XINETD*/ … … 270 270 * data: pointer to an array of floats. 271 271 * n_component: the number of scalars for each space point. 272 * 272 * All component scalars for a point are placed consequtively in data array 273 273 * width, height and depth: number of points in each dimension 274 274 */ 275 275 void 276 276 NanoVis::load_volume(int index, int width, int height, int depth, 277 278 277 int n_component, float* data, double vmin, 278 double vmax, double nzero_min) 279 279 { 280 280 while (n_volumes <= index) { … … 300 300 301 301 volume[index] = new Volume(0.f, 0.f, 0.f, width, height, depth, 1., 302 302 n_component, data, vmin, vmax, nzero_min); 303 303 assert(volume[index]!=0); 304 304 } … … 312 312 hPtr = Tcl_FindHashEntry(&tftable, name); 313 313 if (hPtr == NULL) { 314 314 return NULL; 315 315 } 316 316 return (TransferFunction*)Tcl_GetHashValue(hPtr); … … 327 327 hPtr = Tcl_CreateHashEntry(&tftable, name, &isNew); 328 328 if (isNew) { 329 330 329 tf = new TransferFunction(nSlots, data); 330 Tcl_SetHashValue(hPtr, (ClientData)tf); 331 331 } else { 332 333 332 tf = (TransferFunction*)Tcl_GetHashValue(hPtr); 333 tf->update(data); 334 334 } 335 335 return tf; … … 352 352 TransferFunction *tf = NanoVis::get_transfunc("default"); 353 353 if (tf == NULL) { 354 354 return; 355 355 } 356 356 357 357 float data[256*4]; 358 358 for(int i=0; i<256; i++) { 359 360 361 362 363 359 data[4*i+0] = color_table[i][0]; 360 data[4*i+1] = color_table[i][1]; 361 data[4*i+2] = color_table[i][2]; 362 data[4*i+3] = color_table[i][3]; 363 //fprintf(stderr, "(%f,%f,%f,%f) ", data[4*i+0], data[4*i+1], data[4*i+2], data[4*i+3]); 364 364 } 365 365 … … 434 434 #ifdef NV40 435 435 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, win_width, win_height, 0, 436 436 GL_RGB, GL_INT, NULL); 437 437 #else 438 438 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, win_width, win_height, 0, 439 439 GL_RGB, GL_INT, NULL); 440 440 #endif 441 441 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 442 443 442 GL_COLOR_ATTACHMENT0_EXT, 443 GL_TEXTURE_2D, final_color_tex, 0); 444 444 445 445 // initialize final depth renderbuffer 446 446 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, final_depth_rb); 447 447 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, 448 448 GL_DEPTH_COMPONENT24, win_width, win_height); 449 449 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 450 451 450 GL_DEPTH_ATTACHMENT_EXT, 451 GL_RENDERBUFFER_EXT, final_depth_rb); 452 452 453 453 // Check framebuffer completeness at the end of initialization. … … 473 473 474 474 if (screen_buffer) { 475 476 475 delete[] screen_buffer; 476 screen_buffer = NULL; 477 477 } 478 478 … … 505 505 #ifdef NV40 506 506 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, win_width, win_height, 0, 507 507 GL_RGB, GL_INT, NULL); 508 508 #else 509 509 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, win_width, win_height, 0, 510 510 GL_RGB, GL_INT, NULL); 511 511 #endif 512 512 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 513 514 515 513 GL_COLOR_ATTACHMENT0_EXT, 514 GL_TEXTURE_2D, final_color_tex, 0); 515 516 516 // initialize final depth renderbuffer 517 517 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, final_depth_rb); 518 518 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, 519 519 GL_DEPTH_COMPONENT24, win_width, win_height); 520 520 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 521 522 521 GL_DEPTH_ATTACHMENT_EXT, 522 GL_RENDERBUFFER_EXT, final_depth_rb); 523 523 524 524 // Check framebuffer completeness at the end of initialization. … … 538 538 //procedurally make a gradient plane 539 539 for(int j=0; j<h; j++){ 540 541 542 540 for(int i=0; i<w; i++){ 541 data[w*j+i] = float(i)/float(w); 542 } 543 543 } 544 544 NanoVis::plane[0] = new Texture2D(w, h, GL_FLOAT, GL_LINEAR, 1, data); … … 565 565 data[4*index+1]= j/float(particleRenderer->psys_height); 566 566 data[4*index+2]= i/float(particleRenderer->psys_width); 567 data[4*index+3]= 30; //shorter life span, quicker iterations 568 //data[4*index+3]= 1.0f; //shorter life span, quicker iterations 567 data[4*index+3]= 30; //shorter life span, quicker iterations 568 //data[4*index+3]= 1.0f; //shorter life span, quicker iterations 569 569 } 570 570 /* … … 574 574 data[4*index+1]= 0; 575 575 data[4*index+2]= 0; 576 data[4*index+3]= 0; 576 data[4*index+3]= 0; 577 577 } 578 578 */ … … 662 662 //create the camera with default setting 663 663 cam = new NvCamera(0, 0, win_width, win_height, 664 665 666 664 live_obj_x, live_obj_y, live_obj_z, 665 0., 0., 100., 666 (int)live_rot_x, (int)live_rot_y, (int)live_rot_z); 667 667 668 668 glEnable(GL_TEXTURE_2D); … … 682 682 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); 683 683 glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light); 684 glLightfv(GL_LIGHT0, GL_SPECULAR, white_light); 684 glLightfv(GL_LIGHT0, GL_SPECULAR, white_light); 685 685 glLightfv(GL_LIGHT1, GL_DIFFUSE, green_light); 686 glLightfv(GL_LIGHT1, GL_SPECULAR, white_light); 686 glLightfv(GL_LIGHT1, GL_SPECULAR, white_light); 687 687 688 688 // init table of transfer functions … … 736 736 { 737 737 glReadPixels(0, 0, win_width, win_height, GL_RGB, GL_UNSIGNED_BYTE, 738 738 screen_buffer); 739 739 } 740 740 … … 755 755 int i=0; 756 756 while(i<len){ 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 757 if (NanoVis::screen_buffer[i] == 0) { 758 int pos = i+1; 759 while ( (pos<len) && (NanoVis::screen_buffer[pos] == 0)) { 760 pos++; 761 } 762 offsets[offsets_size++] = -(pos - i); 763 i = pos; 764 } 765 766 else { 767 int pos; 768 for (pos = i; (pos<len) && (NanoVis::screen_buffer[pos] != 0);pos++){ 769 rle[rle_size++] = NanoVis::screen_buffer[pos]; 770 } 771 offsets[offsets_size++] = (pos - i); 772 i = pos; 773 } 774 775 775 } 776 776 } … … 857 857 char filename[100]; 858 858 if (frame_number >= 0) { 859 860 859 sprintf(filename, "/tmp/flow_animation/image%03d.bmp", frame_number); 860 printf("Writing %s\n", filename); 861 861 f = fopen(filename, "wb"); 862 862 } … … 948 948 glColor4f(0.,0.,1.,1.); 949 949 for(int i=0; i<NMESH; i++){ 950 951 952 953 954 955 956 957 958 959 960 961 962 963 950 for(int j=0; j<NMESH; j++){ 951 Vector2 v = grid.get(i, j); 952 953 int x1 = i*DM; 954 int y1 = j*DM; 955 956 int x2 = x1 + v.x; 957 int y2 = y1 + v.y; 958 959 glBegin(GL_LINES); 960 glVertex2d(x1, y1); 961 glVertex2d(x2, y2); 962 glEnd(); 963 } 964 964 } 965 965 } … … 1001 1001 glLoadIdentity(); 1002 1002 1003 glColor3f(1.,1.,1.); 1003 glColor3f(1.,1.,1.); //MUST HAVE THIS LINE!!! 1004 1004 glBegin(GL_QUADS); 1005 1005 glTexCoord2f(0, 0); glVertex2f(0, 0); … … 1021 1021 void 1022 1022 draw_bounding_box(float x0, float y0, float z0, 1023 1024 1023 float x1, float y1, float z1, 1024 float r, float g, float b, float line_width) 1025 1025 { 1026 1026 glDisable(GL_TEXTURE_2D); … … 1076 1076 { 1077 1077 if((*((Particle*)a)).aux > (*((Particle*)b)).aux) { 1078 1078 return -1; 1079 1079 } else { 1080 1080 return 1; 1081 1081 } 1082 1082 } … … 1091 1091 p = (Particle*)malloc(sizeof(Particle)*psys->psys_width*psys->psys_height); 1092 1092 for (int i=0; i<psys->psys_width * psys->psys_height; i++) { 1093 1094 1095 1096 1097 1098 1099 1100 1101 1093 float x = vert[3*i]; 1094 float y = vert[3*i+1]; 1095 float z = vert[3*i+2]; 1096 1097 float dis = (x-live_obj_x)*(x-live_obj_x) + (y-live_obj_y)*(y-live_obj_y) + (z-live_obj_z)*(z-live_obj_z); 1098 p[i].x = x; 1099 p[i].y = y; 1100 p[i].z = z; 1101 p[i].aux = dis; 1102 1102 } 1103 1103 … … 1105 1105 1106 1106 for(int i=0; i<psys->psys_width * psys->psys_height; i++){ 1107 1108 1109 1107 vert[3*i] = p[i].x; 1108 vert[3*i+1] = p[i].y; 1109 vert[3*i+2] = p[i].z; 1110 1110 } 1111 1111 … … 1159 1159 glBegin(GL_POINTS); 1160 1160 for(int i=0; i<psys->psys_width * psys->psys_height; i++){ 1161 1161 glVertex3f(vert[3*i], vert[3*i+1], vert[3*i+2]); 1162 1162 } 1163 1163 glEnd(); … … 1198 1198 oddevenMergeSort.bind(); 1199 1199 glUniform3fARB(oddevenMergeSort.getUniformLocation("Param1"), float(pstage+pstage), 1200 1200 float(ppass%pstage), float((pstage+pstage)-(ppass%pstage)-1)); 1201 1201 glUniform3fARB(oddevenMergeSort.getUniformLocation("Param2"), float(psys_width), float(psys_height), float(ppass)); 1202 1202 glUniform1iARB(oddevenMergeSort.getUniformLocation("Data"), 0); … … 1216 1216 glBegin(GL_QUADS); 1217 1217 #ifdef notdef 1218 glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,0.0f,0.0f,1.0f); glVertex2f(-1.0f,-1.0f); 1218 glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,0.0f,0.0f,1.0f); glVertex2f(-1.0f,-1.0f); 1219 1219 glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),0.0f,1.0f,1.0f); glVertex2f(1.0f,-1.0f); 1220 glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),float(psys_height),1.0f,0.0f); glVertex2f(1.0f,1.0f); 1221 glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,float(psys_height),0.0f,0.0f); glVertex2f(-1.0f,1.0f); 1222 #endif 1223 glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,0.0f,0.0f,1.0f); glVertex2f(0.,0.); 1220 glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),float(psys_height),1.0f,0.0f); glVertex2f(1.0f,1.0f); 1221 glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,float(psys_height),0.0f,0.0f); glVertex2f(-1.0f,1.0f); 1222 #endif 1223 glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,0.0f,0.0f,1.0f); glVertex2f(0.,0.); 1224 1224 glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),0.0f,1.0f,1.0f); glVertex2f(float(psys_width), 0.); 1225 glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),float(psys_height),1.0f,0.0f); glVertex2f(float(psys_width), float(psys_height)); 1226 glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,float(psys_height),0.0f,0.0f); glVertex2f(0., float(psys_height)); 1225 glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),float(psys_height),1.0f,0.0f); glVertex2f(float(psys_width), float(psys_height)); 1226 glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,float(psys_height),0.0f,0.0f); glVertex2f(0., float(psys_height)); 1227 1227 glEnd(); 1228 1228 … … 1263 1263 glScalef(0.0005, 0.0005, 0.0005); 1264 1264 glutStrokeCharacter(GLUT_STROKE_ROMAN, 'x'); 1265 glPopMatrix(); 1265 glPopMatrix(); 1266 1266 1267 1267 glPushMatrix(); … … 1271 1271 glScalef(0.0005, 0.0005, 0.0005); 1272 1272 glutStrokeCharacter(GLUT_STROKE_ROMAN, 'y'); 1273 glPopMatrix(); 1273 glPopMatrix(); 1274 1274 1275 1275 glPushMatrix(); … … 1279 1279 glScalef(0.0005, 0.0005, 0.0005); 1280 1280 glutStrokeCharacter(GLUT_STROKE_ROMAN, 'z'); 1281 glPopMatrix(); 1281 glPopMatrix(); 1282 1282 1283 1283 glEnable(GL_LIGHTING); … … 1290 1290 1291 1291 glPushMatrix(); 1292 glRotatef(-90, 1, 0, 0); 1292 glRotatef(-90, 1, 0, 0); 1293 1293 gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments); 1294 glPopMatrix(); 1294 glPopMatrix(); 1295 1295 1296 1296 glPushMatrix(); 1297 1297 glTranslatef(0., 0.3, 0.); 1298 glRotatef(-90, 1, 0, 0); 1298 glRotatef(-90, 1, 0, 0); 1299 1299 gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments); 1300 glPopMatrix(); 1300 glPopMatrix(); 1301 1301 1302 1302 glPushMatrix(); 1303 1303 glRotatef(90, 0, 1, 0); 1304 1304 gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments); 1305 glPopMatrix(); 1305 glPopMatrix(); 1306 1306 1307 1307 glPushMatrix(); 1308 1308 glTranslatef(0.3, 0., 0.); 1309 glRotatef(90, 0, 1, 0); 1309 glRotatef(90, 0, 1, 0); 1310 1310 gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments); 1311 glPopMatrix(); 1311 glPopMatrix(); 1312 1312 1313 1313 glPushMatrix(); 1314 1314 gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments); 1315 glPopMatrix(); 1315 glPopMatrix(); 1316 1316 1317 1317 glPushMatrix(); 1318 1318 glTranslatef(0., 0., 0.3); 1319 1319 gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments); 1320 glPopMatrix(); 1320 glPopMatrix(); 1321 1321 1322 1322 glDisable(GL_LIGHTING); … … 1339 1339 glBegin(GL_LINES); 1340 1340 { 1341 1342 1341 glVertex3f(0,0,0); 1342 glVertex3f(1.5,0,0); 1343 1343 } 1344 1344 glEnd(); … … 1348 1348 glBegin(GL_LINES); 1349 1349 { 1350 1351 1350 glVertex3f(0,0,0); 1351 glVertex3f(0,1.5,0); 1352 1352 } 1353 1353 glEnd(); … … 1357 1357 glBegin(GL_LINES); 1358 1358 { 1359 1360 1359 glVertex3f(0,0,0); 1360 glVertex3f(0,0,1.5); 1361 1361 } 1362 1362 glEnd(); … … 1369 1369 void NanoVis::update() 1370 1370 { 1371 if (vol_renderer->_volumeInterpolator->is_started()) 1372 { 1373 struct timeval clock; 1374 gettimeofday(&clock, NULL); 1375 double cur_time = clock.tv_sec + clock.tv_usec/1000000.0; 1376 1377 float fraction; 1378 float f = fmod(cur_time - vol_renderer->_volumeInterpolator->getStartTime(), 1379 vol_renderer->_volumeInterpolator->getInterval()); 1380 1381 if (f == 0.0f) fraction = 0.0f; 1382 else fraction = f / vol_renderer->_volumeInterpolator->getInterval(); 1383 1384 vol_renderer->_volumeInterpolator->update(fraction); 1385 } 1371 if (vol_renderer->_volumeInterpolator->is_started()) { 1372 struct timeval clock; 1373 gettimeofday(&clock, NULL); 1374 double cur_time = clock.tv_sec + clock.tv_usec/1000000.0; 1375 1376 float fraction; 1377 float f; 1378 1379 f = fmod(cur_time - vol_renderer->_volumeInterpolator->getStartTime(), 1380 vol_renderer->_volumeInterpolator->getInterval()); 1381 if (f == 0.0f) { 1382 fraction = 0.0f; 1383 } else { 1384 fraction = f / vol_renderer->_volumeInterpolator->getInterval(); 1385 } 1386 vol_renderer->_volumeInterpolator->update(fraction); 1387 } 1386 1388 } 1387 1389 … … 1399 1401 glEnable(GL_TEXTURE_2D); 1400 1402 glEnable(GL_DEPTH_TEST); 1401 1403 1402 1404 //camera setting activated 1403 1405 cam->activate(); 1404 1406 1405 1407 //set up the orientation of items in the scene. 1406 1408 glPushMatrix(); … … 1414 1416 // this is the default 1415 1417 break; 1416 1418 1417 1419 case 3: // z 1418 1420 glRotatef(-90, 1, 0, 0); 1419 1421 glRotatef(-90, 0, 0, 1); 1420 1422 break; 1421 1423 1422 1424 case -1: // -x 1423 1425 glRotatef(-90, 0, 0, 1); 1424 1426 break; 1425 1427 1426 1428 case -2: // -y 1427 1429 glRotatef(180, 0, 0, 1); 1428 1430 glRotatef(-90, 0, 1, 0); 1429 1431 break; 1430 1432 1431 1433 case -3: // -z 1432 1434 glRotatef(90, 1, 0, 0); 1433 1435 break; 1434 1436 } 1435 1437 1436 1438 // TBD : This will be removed after being sure that all the functions work well. 1437 1439 //glPushMatrix(); … … 1439 1441 //now render things in the scene 1440 1442 if (axis_on) { 1441 1442 1443 draw_3d_axis(); 1444 } 1443 1445 if (grid->isVisible()) { 1444 1446 grid->render(); … … 1455 1457 //fprintf(stderr, "particle pixels: %d\n", perf->get_pixel_count()); 1456 1458 //perf->reset(); 1457 1459 1458 1460 //perf->enable(); 1459 1461 vol_renderer->render_all(); 1460 1462 //perf->disable(); 1461 1463 1462 1464 for (unsigned int i = 0; i < heightMap.size(); ++i) { 1463 1465 if (heightMap[i]->isVisible()) { 1464 1466 heightMap[i]->render(renderContext); 1465 1467 } 1466 1468 } 1467 1469 glPopMatrix(); … … 1486 1488 { 1487 1489 if(button==GLUT_LEFT_BUTTON){ 1488 1489 1490 1491 1492 1493 1494 1495 1496 1490 if (state==GLUT_DOWN) { 1491 left_last_x = x; 1492 left_last_y = y; 1493 left_down = true; 1494 right_down = false; 1495 } else { 1496 left_down = false; 1497 right_down = false; 1498 } 1497 1499 } else { 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1500 //fprintf(stderr, "right mouse\n"); 1501 1502 if(state==GLUT_DOWN){ 1503 //fprintf(stderr, "right mouse down\n"); 1504 right_last_x = x; 1505 right_last_y = y; 1506 left_down = false; 1507 right_down = true; 1508 } else { 1509 //fprintf(stderr, "right mouse up\n"); 1510 left_down = false; 1511 right_down = false; 1512 } 1511 1513 } 1512 1514 } … … 1519 1521 1520 1522 if (live_rot_x > 360.0) { 1521 live_rot_x -= 360.0; 1523 live_rot_x -= 360.0; 1522 1524 } else if(live_rot_x < -360.0) { 1523 1525 live_rot_x += 360.0; 1524 1526 } 1525 1527 if (live_rot_y > 360.0) { 1526 live_rot_y -= 360.0; 1528 live_rot_y -= 360.0; 1527 1529 } else if(live_rot_y < -360.0) { 1528 1530 live_rot_y += 360.0; 1529 1531 } 1530 1532 cam->rotate(live_rot_x, live_rot_y, live_rot_z); … … 1610 1612 default: 1611 1613 break; 1612 } 1614 } 1613 1615 #ifdef EVENTLOG 1614 1616 if(log){ … … 1624 1626 NanoVis::motion(int x, int y) 1625 1627 { 1626 int old_x, old_y; 1628 int old_x, old_y; 1627 1629 1628 1630 if(left_down){ 1629 1630 1631 old_x = left_last_x; 1632 old_y = left_last_y; 1631 1633 } else if(right_down){ 1632 1633 1634 old_x = right_last_x; 1635 old_y = right_last_y; 1634 1636 } 1635 1637 … … 1642 1644 1643 1645 if(left_down){ 1644 1645 1646 1647 1646 left_last_x = x; 1647 left_last_y = y; 1648 1649 update_rot(-delta_y, -delta_x); 1648 1650 } else if (right_down){ 1649 1650 1651 1652 1653 1654 1651 //fprintf(stderr, "right mouse motion (%d,%d)\n", x, y); 1652 1653 right_last_x = x; 1654 right_last_y = y; 1655 1656 update_trans(0, 0, delta_x); 1655 1657 } 1656 1658 … … 1689 1691 fclose(xinetd_log); 1690 1692 } 1691 #endif 1693 #endif /*XINETD*/ 1692 1694 1693 1695 void … … 1738 1740 int option_index = 0; 1739 1741 struct option long_options[] = { 1740 1741 1742 // name, has_arg, flag, val 1743 { 0,0,0,0 }, 1742 1744 }; 1743 1745 … … 1745 1747 if (c == -1) { 1746 1748 break; 1747 1749 } 1748 1750 switch(c) { 1749 1750 1751 1752 1753 1754 1751 case 'p': 1752 path = optarg; 1753 break; 1754 default: 1755 fprintf(stderr,"Don't know what option '%c'.\n", c); 1756 return 1; 1755 1757 } 1756 1758 }
Note: See TracChangeset
for help on using the changeset viewer.