Changeset 829


Ignore:
Timestamp:
Dec 17, 2007 8:17:29 AM (13 years ago)
Author:
vrinside
Message:

Moved all the functions related to TCL to Command.cpp

Location:
trunk/vizservers/nanovis
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/vizservers/nanovis/Makefile.in

    r828 r829  
    4646                newmatrm.o nm_misc.o solution.o sort.o svd.o submat.o \
    4747                Image.o ImageLoader.o ImageLoaderImpl.o BMPImageLoaderImpl.o ImageLoaderFactory.o \
    48                 Util.o \
     48                Util.o Command.o \
    4949                R2string.o R2FilePath.o R2Fonts.o R2Object.o R2Geometry.o R2IndexBuffer.o R2VertexBuffer.o
    5050
     
    219219
    220220Util.o: Util.cpp Util.h
     221Command.o: Command.cpp Command.h
    221222
    222223nanovis.o: nanovis.cpp nanovis.h $(AUXSRC)
  • trunk/vizservers/nanovis/config.h

    r434 r829  
    1414 */
    1515
     16#ifndef __CONFIG_H__
     17#define __CONFIG_H__
    1618
    1719#define NV40      //Uncomment if using 6 series card. By default we assume older card the 5xxx series
     
    1921//#define EVENTLOG  //enable event logging
    2022//#define DO_RLE  //do run length compression
     23
     24#endif
  • trunk/vizservers/nanovis/nanovis.cpp

    r827 r829  
    5555#include "Grid.h"
    5656
    57 //#define  _LOCAL_ZINC_TEST_
    58 //
    59 // FOR testing new functions
    60 //#include "Test.h"
    6157
    6258// R2 headers
     
    122118bool axis_on = true;
    123119
     120// in Command.cpp
     121extern void xinetd_listen();
     122extern void initTcl();
     123
     124
    124125// forward declarations
    125126//void init_particles();
     
    155156// pointers to volumes, currently handle up to 10 volumes
    156157vector<Volume*> volume;
    157 
    158158vector<HeightMap*> g_heightMap;
    159159vector<PointSet*> g_pointSet;
     
    178178
    179179extern R2Fonts* g_fonts;
     180
     181// FOR NANOVIS.H
     182//variables for mouse events
     183float live_rot_x = 90.;         //object rotation angles
     184float live_rot_y = 180.;
     185float live_rot_z = -135;
     186
     187float live_obj_x = -0.0;        //object translation location from the origin
     188float live_obj_y = -0.0;
     189float live_obj_z = -2.5;
     190
     191float live_diffuse = 1.;
     192float live_specular = 3.;
     193
     194int left_last_x, left_last_y, right_last_x, right_last_y;       //last locations mouse events
     195bool left_down = false;                                         
     196bool right_down = false;
     197
     198float lic_slice_x=0, lic_slice_y=0, lic_slice_z=0.3;//image based flow visualization slice location
     199
     200int win_width = NPIX;                   //size of the render window
     201int win_height = NPIX;                  //size of the render window
     202
     203
     204//image based flow visualization variables
     205int    iframe = 0;
     206int    Npat   = 64;
     207int    alpha  = (int)round(0.12*255);
     208float  sa;
     209float  tmax   = NPIX/(SCALE*NPN);
     210float  dmax   = SCALE/NPIX;
     211
     212
     213//currently active shader, default renders one volume only
     214int cur_shader = 0;
    180215
    181216/*
     
    202237int renderMode = RM_VOLUME;
    203238
    204 // Tcl interpreter for incoming messages
    205 static Tcl_Interp *interp;
    206 static Tcl_DString cmdbuffer;
    207 
    208 static int ScreenShotCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
    209 static int CameraCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
    210 static int CutplaneCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
    211 static int LegendCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
    212 static int ScreenCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
    213 static int TransfuncCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
    214 static int UpCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
    215 static int VolumeCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
    216 
    217 static int PlaneNewCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
    218 static int PlaneLinkCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
    219 static int PlaneEnableCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
    220 
    221 static int GridCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
    222 static int AxisCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
    223 
    224 static int GetVolumeIndices _ANSI_ARGS_((Tcl_Interp *interp, int argc, CONST84 char *argv[], vector<int>* vectorPtr));
    225 static int GetIndices(Tcl_Interp *interp, int argc, CONST84 char *argv[], vector<int>* vectorPtr);
    226 static int GetAxis _ANSI_ARGS_((Tcl_Interp *interp, char *str, int *valPtr));
    227 static int GetColor _ANSI_ARGS_((Tcl_Interp *interp, char *str, float *rgbPtr));
    228 
    229 /*
    230  * ----------------------------------------------------------------------
    231  * CLIENT COMMAND:
    232  *   camera aim <x0> <y0> <z0>
    233  *   camera angle <xAngle> <yAngle> <zAngle>
    234  *   camera zoom <factor>
    235  *
    236  * Clients send these commands to manipulate the camera.  The "angle"
    237  * operation controls the angle of the camera around the focal point.
    238  * The "zoom" operation sets the zoom factor, moving the camera in
    239  * and out.
    240  * ----------------------------------------------------------------------
    241  */
    242 static int
    243 CameraCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])
    244 {
    245         if (argc < 2) {
    246                 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    247                         " option arg arg...\"", (char*)NULL);
    248                 return TCL_ERROR;
    249     }
    250 
    251     char c = *argv[1];
    252         if (c == 'a' && strcmp(argv[1],"angle") == 0) {
    253         if (argc != 5) {
    254                     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    255                             " angle xangle yangle zangle\"", (char*)NULL);
    256                     return TCL_ERROR;
    257         }
    258 
    259         double xangle, yangle, zangle;
    260             if (Tcl_GetDouble(interp, argv[2], &xangle) != TCL_OK) {
    261                     return TCL_ERROR;
    262             }
    263             if (Tcl_GetDouble(interp, argv[3], &yangle) != TCL_OK) {
    264                     return TCL_ERROR;
    265             }
    266             if (Tcl_GetDouble(interp, argv[4], &zangle) != TCL_OK) {
    267                     return TCL_ERROR;
    268             }
    269             cam->rotate(xangle, yangle, zangle);
    270 
    271             return TCL_OK;
    272         }
    273         else if (c == 'a' && strcmp(argv[1],"aim") == 0) {
    274         if (argc != 5) {
    275                     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    276                             " aim x y z\"", (char*)NULL);
    277                     return TCL_ERROR;
    278         }
    279 
    280         double x0, y0, z0;
    281             if (Tcl_GetDouble(interp, argv[2], &x0) != TCL_OK) {
    282                     return TCL_ERROR;
    283             }
    284             if (Tcl_GetDouble(interp, argv[3], &y0) != TCL_OK) {
    285                     return TCL_ERROR;
    286             }
    287             if (Tcl_GetDouble(interp, argv[4], &z0) != TCL_OK) {
    288                     return TCL_ERROR;
    289             }
    290             cam->aim(x0, y0, z0);
    291 
    292             return TCL_OK;
    293         }
    294         else if (c == 'z' && strcmp(argv[1],"zoom") == 0) {
    295         if (argc != 3) {
    296                     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    297                             " zoom factor\"", (char*)NULL);
    298                     return TCL_ERROR;
    299         }
    300 
    301         double zoom;
    302             if (Tcl_GetDouble(interp, argv[2], &zoom) != TCL_OK) {
    303                     return TCL_ERROR;
    304             }
    305 
    306         live_obj_z = -2.5/zoom;
    307                 cam->move(live_obj_x, live_obj_y, live_obj_z);
    308 
    309             return TCL_OK;
    310     }
    311 
    312         Tcl_AppendResult(interp, "bad option \"", argv[1],
    313                 "\": should be aim, angle, or zoom", (char*)NULL);
    314         return TCL_ERROR;
    315 }
    316 
    317 static int
    318 ScreenShotCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])
    319 {
    320     int old_win_width = win_width;
    321     int old_win_height = win_height;
    322 
    323 #ifdef XINETD
    324     resize_offscreen_buffer(1024, 1024);
    325     cam->set_screen_size(30, 90, 1024 - 60, 1024 - 120);
    326     offscreen_buffer_capture();  //enable offscreen render
    327     display();
    328 
    329     // INSOO
    330     // TBD
    331     Volume* vol = volume[0];
    332     TransferFunction* tf = g_vol_render->get_volume_shading(vol);
    333     if (tf)
    334     {
    335         float data[512];
    336         for (int i=0; i < 256; i++) {
    337             data[i] = data[i+256] = (float)(i/255.0);
    338         }
    339         Texture2D* plane = new Texture2D(256, 2, GL_FLOAT, GL_LINEAR, 1, data);
    340         g_color_table_renderer->render(1024, 1024, plane, tf, vol->range_min(), vol->range_max());
    341         delete plane;
    342     }
    343 
    344     read_screen();
    345     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    346 
    347     bmp_write("nv>screenshot -bytes");
    348    
    349     resize_offscreen_buffer(old_win_width, old_win_height);
    350 #endif
    351 
    352         return TCL_OK;
    353 }
    354 
    355 /*
    356  * ----------------------------------------------------------------------
    357  * CLIENT COMMAND:
    358  *   cutplane state on|off <axis> ?<volume>...?
    359  *   cutplane position <relvalue> <axis> ?<volume>...?
    360  *
    361  * Clients send these commands to manipulate the cutplanes in one or
    362  * more data volumes.  The "state" command turns a cutplane on or
    363  * off.  The "position" command changes the position to a relative
    364  * value in the range 0-1.  The <axis> can be x, y, or z.  These
    365  * operations are applied to the volumes represented by one or more
    366  * <volume> indices.  If no volumes are specified, then all volumes
    367  * are updated.
    368  * ----------------------------------------------------------------------
    369  */
    370 static int
    371 CutplaneCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])
    372 {
    373     if (argc < 2) {
    374         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    375             " option ?arg arg...?\"", (char*)NULL);
    376         return TCL_ERROR;
    377     }
    378 
    379     char c = *argv[1];
    380     if (c == 's' && strcmp(argv[1],"state") == 0) {
    381         if (argc < 4) {
    382             Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    383                 " state on|off axis ?volume ...? \"", (char*)NULL);
    384             return TCL_ERROR;
    385         }
    386 
    387         int state;
    388         if (Tcl_GetBoolean(interp, argv[2], &state) != TCL_OK) {
    389             return TCL_ERROR;
    390         }
    391 
    392         int axis;
    393         if (GetAxis(interp, (char*) argv[3], &axis) != TCL_OK) {
    394             return TCL_ERROR;
    395         }
    396 
    397         vector<int> ivol;
    398         if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) {
    399             return TCL_ERROR;
    400         }
    401 
    402         vector<int>::iterator iter = ivol.begin();
    403         while (iter != ivol.end()) {
    404             if (state) {
    405                 volume[*iter]->enable_cutplane(axis);
    406             } else {
    407                 volume[*iter]->disable_cutplane(axis);
    408             }
    409             ++iter;
    410         }
    411         return TCL_OK;
    412     }
    413     else if (c == 'p' && strcmp(argv[1],"position") == 0) {
    414         if (argc < 4) {
    415             Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    416                 " position relval axis ?volume ...? \"", (char*)NULL);
    417             return TCL_ERROR;
    418         }
    419 
    420         double relval;
    421         if (Tcl_GetDouble(interp, argv[2], &relval) != TCL_OK) {
    422             return TCL_ERROR;
    423         }
    424         // keep this just inside the volume so it doesn't disappear
    425         if (relval < 0.01) { relval = 0.01; }
    426         if (relval > 0.99) { relval = 0.99; }
    427 
    428         int axis;
    429         if (GetAxis(interp, (char*) argv[3], &axis) != TCL_OK) {
    430             return TCL_ERROR;
    431         }
    432 
    433         vector<int> ivol;
    434         if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) {
    435             return TCL_ERROR;
    436         }
    437 
    438         vector<int>::iterator iter = ivol.begin();
    439         while (iter != ivol.end()) {
    440             volume[*iter]->move_cutplane(axis, (float)relval);
    441             ++iter;
    442         }
    443         return TCL_OK;
    444     }
    445 
    446     Tcl_AppendResult(interp, "bad option \"", argv[1],
    447         "\": should be position or state", (char*)NULL);
    448     return TCL_ERROR;
    449 }
    450 
    451 /*
    452  * ----------------------------------------------------------------------
    453  * CLIENT COMMAND:
    454  *   legend <volumeIndex> <width> <height>
    455  *
    456  * Clients use this to generate a legend image for the specified
    457  * transfer function.  The legend image is a color gradient from 0
    458  * to one, drawn in the given transfer function.  The resulting image
    459  * is returned in the size <width> x <height>.
    460  * ----------------------------------------------------------------------
    461  */
    462 static int
    463 LegendCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])
    464 {
    465     if (argc != 4) {
    466         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    467             " transfunc width height\"", (char*)NULL);
    468         return TCL_ERROR;
    469     }
    470 
    471     TransferFunction *tf = NULL;
    472     int ivol;
    473     if (Tcl_GetInt(interp, argv[1], &ivol) != TCL_OK) {
    474         return TCL_ERROR;
    475     }
    476     if (ivol < n_volumes) {
    477         tf = g_vol_render->get_volume_shading(volume[ivol]);
    478     }
    479     if (tf == NULL) {
    480         Tcl_AppendResult(interp, "transfer function not defined for volume ", argv[1], (char*)NULL);
    481         return TCL_ERROR;
    482     }
    483 
    484     int old_width = win_width;
    485     int old_height = win_height;
    486 
    487     int width, height;
    488     if (Tcl_GetInt(interp, argv[2], &width) != TCL_OK) {
    489         return TCL_ERROR;
    490     }
    491     if (Tcl_GetInt(interp, argv[3], &height) != TCL_OK) {
    492         return TCL_ERROR;
    493     }
    494 
    495     plane_render->set_screen_size(width, height);
    496     resize_offscreen_buffer(width, height);
    497 
    498     // generate data for the legend
    499     float data[512];
    500     for (int i=0; i < 256; i++) {
    501         data[i] = data[i+256] = (float)(i/255.0);
    502     }
    503     plane[0] = new Texture2D(256, 2, GL_FLOAT, GL_LINEAR, 1, data);
    504     int index = plane_render->add_plane(plane[0], tf);
    505     plane_render->set_active_plane(index);
    506 
    507     offscreen_buffer_capture();
    508     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear screen
    509     plane_render->render();
    510 
    511 // INSOO
    512     glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, screen_buffer);
    513     //glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, screen_buffer); // INSOO's
    514 
    515     std::ostringstream result;
    516     result << "nv>legend " << argv[1];
    517     result << " " << volume[ivol]->range_min();
    518     result << " " << volume[ivol]->range_max();
    519     bmp_write(result.str().c_str());
    520     write(0, "\n", 1);
    521 
    522     plane_render->remove_plane(index);
    523     resize_offscreen_buffer(old_width, old_height);
    524 
    525     return TCL_OK;
    526 }
    527 
    528 
    529 
    530 /*
    531  * ----------------------------------------------------------------------
    532  * CLIENT COMMAND:
    533  *   screen <width> <height>
    534  *
    535  * Clients send this command to set the size of the rendering area.
    536  * Future images are generated at the specified width/height.
    537  * ----------------------------------------------------------------------
    538  */
    539 static int
    540 ScreenCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])
    541 {
    542     int w, h;
    543 
    544     if (argc != 3) {
    545         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    546             " width height\"", (char*)NULL);
    547         return TCL_ERROR;
    548     }
    549     if (Tcl_GetInt(interp, argv[1], &w) != TCL_OK) {
    550         return TCL_ERROR;
    551     }
    552     if (Tcl_GetInt(interp, argv[2], &h) != TCL_OK) {
    553         return TCL_ERROR;
    554     }
    555     resize_offscreen_buffer(w, h);
    556 
    557     return TCL_OK;
    558 }
    559 
    560 /*
    561  * ----------------------------------------------------------------------
    562  * CLIENT COMMAND:
    563  *   transfunc define <name> <colormap> <alphamap>
    564  *     where <colormap> = { <v> <r> <g> <b> ... }
    565  *           <alphamap> = { <v> <w> ... }
    566  *
    567  * Clients send these commands to manipulate the transfer functions.
    568  * ----------------------------------------------------------------------
    569  */
    570 static int
    571 TransfuncCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])
    572 {
    573         if (argc < 2) {
    574                 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    575                         " option arg arg...\"", (char*)NULL);
    576                 return TCL_ERROR;
    577     }
    578 
    579     char c = *argv[1];
    580         if (c == 'd' && strcmp(argv[1],"define") == 0) {
    581         if (argc != 5) {
    582                     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    583                             argv[1], " define name colormap alphamap\"", (char*)NULL);
    584             return TCL_ERROR;
    585         }
    586 
    587         // decode the data and store in a series of fields
    588         Rappture::Field1D rFunc, gFunc, bFunc, wFunc;
    589         int cmapc, wmapc, i, j;
    590         char **cmapv, **wmapv;
    591 
    592         if (Tcl_SplitList(interp, argv[3], &cmapc, (const char***)&cmapv) != TCL_OK) {
    593             return TCL_ERROR;
    594         }
    595         if (cmapc % 4 != 0) {
    596             Tcl_Free((char*)cmapv);
    597                     Tcl_AppendResult(interp, "bad colormap in transfunc: should be ",
    598                 "{ v r g b ... }", (char*)NULL);
    599             return TCL_ERROR;
    600         }
    601 
    602         if (Tcl_SplitList(interp, argv[4], &wmapc, (const char***)&wmapv) != TCL_OK) {
    603             return TCL_ERROR;
    604         }
    605         if (wmapc % 2 != 0) {
    606             Tcl_Free((char*)cmapv);
    607             Tcl_Free((char*)wmapv);
    608                     Tcl_AppendResult(interp, "bad alphamap in transfunc: should be ",
    609                 "{ v w ... }", (char*)NULL);
    610             return TCL_ERROR;
    611         }
    612 
    613         for (i=0; i < cmapc; i += 4) {
    614             double vals[4];
    615             for (j=0; j < 4; j++) {
    616                 if (Tcl_GetDouble(interp, cmapv[i+j], &vals[j]) != TCL_OK) {
    617                     Tcl_Free((char*)cmapv);
    618                     Tcl_Free((char*)wmapv);
    619                     return TCL_ERROR;
    620                 }
    621                 if (vals[j] < 0 || vals[j] > 1) {
    622                     Tcl_Free((char*)cmapv);
    623                     Tcl_Free((char*)wmapv);
    624                             Tcl_AppendResult(interp, "bad value \"", cmapv[i+j],
    625                         "\": should be in the range 0-1", (char*)NULL);
    626                     return TCL_ERROR;
    627                 }
    628             }
    629             rFunc.define(vals[0], vals[1]);
    630             gFunc.define(vals[0], vals[2]);
    631             bFunc.define(vals[0], vals[3]);
    632         }
    633 
    634         for (i=0; i < wmapc; i += 2) {
    635             double vals[2];
    636             for (j=0; j < 2; j++) {
    637                 if (Tcl_GetDouble(interp, wmapv[i+j], &vals[j]) != TCL_OK) {
    638                     Tcl_Free((char*)cmapv);
    639                     Tcl_Free((char*)wmapv);
    640                     return TCL_ERROR;
    641                 }
    642                 if (vals[j] < 0 || vals[j] > 1) {
    643                     Tcl_Free((char*)cmapv);
    644                     Tcl_Free((char*)wmapv);
    645                             Tcl_AppendResult(interp, "bad value \"", wmapv[i+j],
    646                         "\": should be in the range 0-1", (char*)NULL);
    647                     return TCL_ERROR;
    648                 }
    649             }
    650             wFunc.define(vals[0], vals[1]);
    651         }
    652         Tcl_Free((char*)cmapv);
    653         Tcl_Free((char*)wmapv);
    654 
    655         // sample the given function into discrete slots
    656         const int nslots = 256;
    657         float data[4*nslots];
    658         for (i=0; i < nslots; i++) {
    659             double xval = double(i)/(nslots-1);
    660             data[4*i]   = rFunc.value(xval);
    661             data[4*i+1] = gFunc.value(xval);
    662             data[4*i+2] = bFunc.value(xval);
    663             data[4*i+3] = wFunc.value(xval);
    664         }
    665 
    666         // find or create this transfer function
    667         int newEntry;
    668         Tcl_HashEntry *entryPtr;
    669         TransferFunction *tf;
    670 
    671         entryPtr = Tcl_CreateHashEntry(&tftable, argv[2], &newEntry);
    672         if (newEntry) {
    673             tf = new TransferFunction(nslots, data);
    674             Tcl_SetHashValue(entryPtr, (ClientData)tf);
    675         } else {
    676             tf = (TransferFunction*)Tcl_GetHashValue(entryPtr);
    677             tf->update(data);
    678         }
    679 
    680         return TCL_OK;
    681     }
    682 
    683 
    684     Tcl_AppendResult(interp, "bad option \"", argv[1],
    685         "\": should be define", (char*)NULL);
    686     return TCL_ERROR;
    687 }
    688 
    689 /*
    690  * ----------------------------------------------------------------------
    691  * CLIENT COMMAND:
    692  *   up axis
    693  *
    694  * Clients use this to set the "up" direction for all volumes.  Volumes
    695  * are oriented such that this direction points upward.
    696  * ----------------------------------------------------------------------
    697  */
    698 static int
    699 UpCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])
    700 {
    701     if (argc != 2) {
    702         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    703             " x|y|z|-x|-y|-z\"", (char*)NULL);
    704         return TCL_ERROR;
    705     }
    706 
    707     int sign = 1;
    708     char *axisName = (char*)argv[1];
    709     if (*axisName == '-') {
    710         sign = -1;
    711         axisName++;
    712     }
    713 
    714     int axis;
    715     if (GetAxis(interp, axisName, &axis) != TCL_OK) {
    716         return TCL_ERROR;
    717     }
    718 
    719     updir = (axis+1)*sign;
    720 
    721     return TCL_OK;
    722 }
    723 
    724 /*
    725  * ----------------------------------------------------------------------
    726  * CLIENT COMMAND:
    727  *   volume axis label x|y|z <value> ?<volumeId> ...?
    728  *   volume data state on|off ?<volumeId> ...?
    729  *   volume outline state on|off ?<volumeId> ...?
    730  *   volume outline color on|off ?<volumeId> ...?
    731  *   volume shading transfunc <name> ?<volumeId> ...?
    732  *   volume shading diffuse <value> ?<volumeId> ...?
    733  *   volume shading specular <value> ?<volumeId> ...?
    734  *   volume shading opacity <value> ?<volumeId> ...?
    735  *   volume state on|off ?<volumeId> ...?
    736  *
    737  * Clients send these commands to manipulate the volumes.
    738  * ----------------------------------------------------------------------
    739  */
    740 void NvLoadVolumeBinFile2(int index, char* filename);
    741 static int
    742 VolumeCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])
    743 {
    744     if (argc < 2) {
    745         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    746             " option arg arg...\"", (char*)NULL);
    747         return TCL_ERROR;
    748     }
    749 
    750     char c = *argv[1];
    751     if (c == 'a' && strcmp(argv[1],"axis") == 0) {
    752         if (argc < 3) {
    753             Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    754                 argv[1], " option ?arg arg...?\"", (char*)NULL);
    755             return TCL_ERROR;
    756         }
    757         c = *argv[2];
    758         if (c == 'l' && strcmp(argv[2],"label") == 0) {
    759             if (argc < 4) {
    760                 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    761                     argv[1], " label x|y|z string ?volume ...?\"", (char*)NULL);
    762                 return TCL_ERROR;
    763             }
    764 
    765             int axis;
    766             if (GetAxis(interp, (char*)argv[3], &axis) != TCL_OK) {
    767                 return TCL_ERROR;
    768             }
    769 
    770             vector<int> ivol;
    771             if (GetVolumeIndices(interp, argc-5, argv+5, &ivol) != TCL_OK) {
    772                 return TCL_ERROR;
    773             }
    774 
    775             vector<int>::iterator iter = ivol.begin();
    776             while (iter != ivol.end()) {
    777                 volume[*iter]->set_label(axis, (char*)argv[4]);
    778                 ++iter;
    779             }
    780             return TCL_OK;
    781         }
    782 
    783         Tcl_AppendResult(interp, "bad option \"", argv[2],
    784             "\": should be label", (char*)NULL);
    785         return TCL_ERROR;
    786     }
    787     else if (c == 'd' && strcmp(argv[1],"data") == 0) {
    788         if (argc < 3) {
    789             Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    790                 argv[1], " option ?arg arg...?\"", (char*)NULL);
    791             return TCL_ERROR;
    792         }
    793         c = *argv[2];
    794         if (c == 's' && strcmp(argv[2],"state") == 0) {
    795             if (argc < 4) {
    796                 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    797                     argv[1], " state on|off ?volume ...?\"", (char*)NULL);
    798                 return TCL_ERROR;
    799             }
    800 
    801             int state;
    802             if (Tcl_GetBoolean(interp, argv[3], &state) != TCL_OK) {
    803                 return TCL_ERROR;
    804             }
    805 
    806             vector<int> ivol;
    807             if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) {
    808                 return TCL_ERROR;
    809             }
    810 
    811             vector<int>::iterator iter = ivol.begin();
    812             while (iter != ivol.end()) {
    813                 if (state) {
    814                     volume[*iter]->enable_data();
    815                 } else {
    816                     volume[*iter]->disable_data();
    817                 }
    818                 ++iter;
    819             }
    820             return TCL_OK;
    821         }
    822         else if (c == 'f' && strcmp(argv[2],"follows") == 0) {
    823             printf("Data Loading\n");
    824             //fflush(stdout);
    825             //return TCL_OK;
    826 
    827             int nbytes;
    828             if (Tcl_GetInt(interp, argv[3], &nbytes) != TCL_OK) {
    829                 return TCL_ERROR;
    830             }
    831 
    832             Rappture::Outcome err;
    833             Rappture::Buffer buf;
    834 
    835             // DEBUG
    836             int totalsize = nbytes;
    837             char buffer[8096];
    838             while (nbytes > 0)
    839             {
    840                 int chunk = (sizeof(buffer) < nbytes) ? sizeof(buffer) : nbytes;
    841                 int status = fread(buffer, 1, chunk, stdin);
    842                 //printf("Begin Reading [%d Read : %d Left]\n", status, nbytes - status);
    843                 fflush(stdout);
    844                 if (status > 0) {
    845                     buf.append(buffer,status);
    846                     nbytes -= status;
    847                 } else {
    848                     printf("data unpacking failed\n");
    849                     Tcl_AppendResult(interp, "data unpacking failed: unexpected EOF",
    850                         (char*)NULL);
    851                     return TCL_ERROR;
    852                 }
    853             }
    854 
    855             err = Rappture::encoding::decode(buf,RPENC_Z|RPENC_B64|RPENC_HDR);
    856             if (err) {
    857                 printf("ERROR -- DECODING\n");
    858                 fflush(stdout);
    859                 Tcl_AppendResult(interp, err.remark().c_str(), (char*)NULL);
    860                 return TCL_ERROR;
    861             }
    862 
    863             int n = n_volumes;
    864             char header[6];
    865             memcpy(header, buf.bytes(), sizeof(char) * 5);
    866             header[5] = '\0';
    867 
    868 #ifdef _LOCAL_ZINC_TEST_
    869             //FILE* fp = fopen("/home/nanohub/vrinside/nv/data/HOON/QDWL_100_100_50_strain_8000i.nd_zatom_12_1", "rb");
    870             FILE* fp = fopen("/home/nanohub/vrinside/nv/data/HOON/GaAs_AlGaAs_2QD_B4.nd_zc_1_wf", "rb");
    871             unsigned char* b = (unsigned char*) malloc(buf.size());
    872             if (fp == 0)
    873             {
    874                 printf("cannot open the file\n");
    875                 fflush(stdout);
    876                 return TCL_ERROR;
    877             }
    878             fread(b, buf.size(), 1, fp);
    879             fclose(fp);
    880 #endif
    881 
    882            
    883             printf("Checking header[%s]\n", header);
    884             fflush(stdout);
    885             if (!strcmp(header, "<HDR>"))
    886             {
    887                 Volume* vol = NULL;
    888 
    889                 printf("ZincBlende stream is in\n");
    890                 fflush(stdout);
    891                 //std::stringstream fdata(std::ios_base::out|std::ios_base::in|std::ios_base::binary);
    892                 //fdata.write(buf.bytes(),buf.size());
    893                 //vol = NvZincBlendeReconstructor::getInstance()->loadFromStream(fdata);
    894                
    895 #ifdef _LOCAL_ZINC_TEST_
    896                 vol = NvZincBlendeReconstructor::getInstance()->loadFromMemory(b);
    897 #else
    898                 vol = NvZincBlendeReconstructor::getInstance()->loadFromMemory((void*) buf.bytes());
    899 #endif
    900 
    901                 printf("finish loading\n");
    902                 fflush(stdout);
    903                 if (vol)
    904                 {
    905                     while (n_volumes <= n)
    906                     {
    907                         volume.push_back((Volume*) NULL);
    908                         n_volumes++;
    909                     }
    910 
    911                     if (volume[n] != NULL)
    912                     {
    913                         delete volume[n];
    914                         volume[n] = NULL;
    915                     }
    916 
    917                     float dx0 = -0.5;
    918                     float dy0 = -0.5*vol->height/vol->width;
    919                     float dz0 = -0.5*vol->depth/vol->width;
    920                     vol->move(Vector3(dx0, dy0, dz0));
    921 
    922                     volume[n] = vol;
    923                 }
    924             }
    925 #ifdef __TEST_CODE__
    926             else if (!strcmp(header, "<FET>"))
    927             {
    928                 printf("FET loading...\n");
    929                 fflush(stdout);
    930                 std::stringstream fdata;
    931                 fdata.write(buf.bytes(),buf.size());
    932                 err = load_volume_stream3(n, fdata);
    933 
    934                 if (err) {
    935                     Tcl_AppendResult(interp, err.remark().c_str(), (char*)NULL);
    936                     return TCL_ERROR;
    937                 }
    938             }
    939 #endif
    940             else
    941             {
    942                 printf("OpenDX loading...\n");
    943                 fflush(stdout);
    944                 std::stringstream fdata;
    945                 fdata.write(buf.bytes(),buf.size());
    946                 err = load_volume_stream(n, fdata);
    947                 //err = load_volume_stream2(n, fdata);
    948                 if (err) {
    949                     Tcl_AppendResult(interp, err.remark().c_str(), (char*)NULL);
    950                     return TCL_ERROR;
    951                 }
    952             }
    953            
    954 
    955             //
    956             // BE CAREFUL:  Set the number of slices to something
    957             //   slightly different for each volume.  If we have
    958             //   identical volumes at exactly the same position
    959             //   with exactly the same number of slices, the second
    960             //   volume will overwrite the first, so the first won't
    961             //   appear at all.
    962             //
    963             if (volume[n])
    964             {
    965                 volume[n]->set_n_slice(256-n);
    966                 volume[n]->disable_cutplane(0);
    967                 volume[n]->disable_cutplane(1);
    968                 volume[n]->disable_cutplane(2);
    969 
    970                 g_vol_render->add_volume(volume[n], get_transfunc("default"));
    971             }
    972 
    973             return TCL_OK;
    974         }
    975         Tcl_AppendResult(interp, "bad option \"", argv[2],
    976             "\": should be follows or state", (char*)NULL);
    977         return TCL_ERROR;
    978     }
    979     else if (c == 'o' && strcmp(argv[1],"outline") == 0) {
    980         if (argc < 3) {
    981             Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    982                 argv[1], " option ?arg arg...?\"", (char*)NULL);
    983             return TCL_ERROR;
    984         }
    985         c = *argv[2];
    986         if (c == 's' && strcmp(argv[2],"state") == 0) {
    987             if (argc < 3) {
    988                 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    989                     argv[1], " state on|off ?volume ...? \"", (char*)NULL);
    990                 return TCL_ERROR;
    991             }
    992 
    993             int state;
    994             if (Tcl_GetBoolean(interp, argv[3], &state) != TCL_OK) {
    995                 return TCL_ERROR;
    996             }
    997 
    998             vector<int> ivol;
    999             if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) {
    1000                 return TCL_ERROR;
    1001             }
    1002 
    1003             vector<int>::iterator iter = ivol.begin();
    1004             while (iter != ivol.end()) {
    1005                 if (state) {
    1006                     volume[*iter]->enable_outline();
    1007                 } else {
    1008                     volume[*iter]->disable_outline();
    1009                 }
    1010                 ++iter;
    1011             }
    1012             return TCL_OK;
    1013         }
    1014         else if (c == 'v' && strcmp(argv[2],"visible") == 0) {
    1015             if (argv[3] == "false")
    1016             {
    1017                 for (int i = 0; i < n_volumes; ++i)
    1018                 {
    1019                     if (volume[i]) volume[i]->disable_outline();
    1020                 }
    1021             }
    1022             else if (argv[3] == "true")
    1023             {
    1024                 for (int i = 0; i < n_volumes; ++i)
    1025                 {
    1026                     if (volume[i]) volume[i]->enable_outline();
    1027                 }
    1028             }
    1029 
    1030             return TCL_OK;
    1031         }
    1032         else if (c == 'c' && strcmp(argv[2],"color") == 0) {
    1033             if (argc < 3) {
    1034                 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    1035                     argv[1], " color {R G B} ?volume ...? \"", (char*)NULL);
    1036                 return TCL_ERROR;
    1037             }
    1038 
    1039             float rgb[3];
    1040             if (GetColor(interp, (char*) argv[3], rgb) != TCL_OK) {
    1041                 return TCL_ERROR;
    1042             }
    1043 
    1044             vector<int> ivol;
    1045             if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) {
    1046                 return TCL_ERROR;
    1047             }
    1048 
    1049             vector<int>::iterator iter = ivol.begin();
    1050             while (iter != ivol.end()) {
    1051                 volume[*iter]->set_outline_color(rgb);
    1052                 ++iter;
    1053             }
    1054             return TCL_OK;
    1055         }
    1056 
    1057         Tcl_AppendResult(interp, "bad option \"", argv[2],
    1058             "\": should be color or state", (char*)NULL);
    1059         return TCL_ERROR;
    1060     }
    1061     else if (c == 's' && strcmp(argv[1],"shading") == 0) {
    1062         if (argc < 3) {
    1063             Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    1064                 argv[1], " option ?arg arg...?\"", (char*)NULL);
    1065             return TCL_ERROR;
    1066         }
    1067         c = *argv[2];
    1068         if (c == 't' && strcmp(argv[2],"transfunc") == 0) {
    1069             if (argc < 4) {
    1070                 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    1071                     argv[1], " transfunc name ?volume ...?\"", (char*)NULL);
    1072                 return TCL_ERROR;
    1073             }
    1074 
    1075             TransferFunction *tf = get_transfunc((char*)argv[3]);
    1076             if (tf == NULL) {
    1077                 Tcl_AppendResult(interp, "transfer function \"", argv[3],
    1078                     "\" is not defined", (char*)NULL);
    1079                 return TCL_ERROR;
    1080             }
    1081 
    1082             vector<int> ivol;
    1083             if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) {
    1084                 return TCL_ERROR;
    1085             }
    1086 
    1087             vector<int>::iterator iter = ivol.begin();
    1088             while (iter != ivol.end()) {
    1089                 g_vol_render->shade_volume(volume[*iter], tf);
    1090                 ++iter;
    1091             }
    1092             return TCL_OK;
    1093         }
    1094         else if (c == 'd' && strcmp(argv[2],"diffuse") == 0) {
    1095             if (argc < 4) {
    1096                 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    1097                     argv[1], " diffuse value ?volume ...?\"", (char*)NULL);
    1098                 return TCL_ERROR;
    1099             }
    1100 
    1101             double dval;
    1102             if (Tcl_GetDouble(interp, argv[3], &dval) != TCL_OK) {
    1103                 return TCL_ERROR;
    1104             }
    1105 
    1106             vector<int> ivol;
    1107             if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) {
    1108                 return TCL_ERROR;
    1109             }
    1110 
    1111             vector<int>::iterator iter = ivol.begin();
    1112             while (iter != ivol.end()) {
    1113                 volume[*iter]->set_diffuse((float)dval);
    1114                 ++iter;
    1115             }
    1116             return TCL_OK;
    1117         }
    1118         else if (c == 'o' && strcmp(argv[2],"opacity") == 0) {
    1119             if (argc < 4) {
    1120                 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    1121                     argv[1], " opacity value ?volume ...?\"", (char*)NULL);
    1122                 return TCL_ERROR;
    1123             }
    1124 
    1125             double dval;
    1126             if (Tcl_GetDouble(interp, argv[3], &dval) != TCL_OK) {
    1127                 return TCL_ERROR;
    1128             }
    1129 
    1130             vector<int> ivol;
    1131             if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) {
    1132                 return TCL_ERROR;
    1133             }
    1134 
    1135             vector<int>::iterator iter = ivol.begin();
    1136             while (iter != ivol.end()) {
    1137                 volume[*iter]->set_opacity_scale((float)dval);
    1138                 ++iter;
    1139             }
    1140             return TCL_OK;
    1141         }
    1142         else if (c == 's' && strcmp(argv[2],"specular") == 0) {
    1143             if (argc < 4) {
    1144                 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    1145                     argv[1], " specular value ?volume ...?\"", (char*)NULL);
    1146                 return TCL_ERROR;
    1147             }
    1148 
    1149             double dval;
    1150             if (Tcl_GetDouble(interp, argv[3], &dval) != TCL_OK) {
    1151                 return TCL_ERROR;
    1152             }
    1153 
    1154             vector<int> ivol;
    1155             if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) {
    1156                 return TCL_ERROR;
    1157             }
    1158 
    1159             vector<int>::iterator iter = ivol.begin();
    1160             while (iter != ivol.end()) {
    1161                 volume[*iter]->set_specular((float)dval);
    1162                 ++iter;
    1163             }
    1164             return TCL_OK;
    1165         }
    1166         Tcl_AppendResult(interp, "bad option \"", argv[2],
    1167             "\": should be diffuse, opacity, specular, or transfunc", (char*)NULL);
    1168         return TCL_ERROR;
    1169     }
    1170     else if (c == 's' && strcmp(argv[1],"state") == 0) {
    1171         if (argc < 3) {
    1172             Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    1173                 argv[1], " on|off ?volume...?\"", (char*)NULL);
    1174             return TCL_ERROR;
    1175         }
    1176 
    1177         int state;
    1178         if (Tcl_GetBoolean(interp, argv[2], &state) != TCL_OK) {
    1179             return TCL_ERROR;
    1180         }
    1181 
    1182         vector<int> ivol;
    1183         if (GetVolumeIndices(interp, argc-3, argv+3, &ivol) != TCL_OK) {
    1184             return TCL_ERROR;
    1185         }
    1186 
    1187         vector<int>::iterator iter = ivol.begin();
    1188         while (iter != ivol.end()) {
    1189             if (state) {
    1190                 volume[*iter]->enable();
    1191             } else {
    1192                 volume[*iter]->disable();
    1193             }
    1194             ++iter;
    1195         }
    1196         return TCL_OK;
    1197     }
    1198     else if (c == 't' && strcmp(argv[1],"test2") == 0) {
    1199         volume[1]->disable_data();
    1200         volume[1]->disable();
    1201         return TCL_OK;
    1202     }
    1203 
    1204     Tcl_AppendResult(interp, "bad option \"", argv[1],
    1205         "\": should be data, outline, shading, or state", (char*)NULL);
    1206     return TCL_ERROR;
    1207 }
    1208 
    1209 int HeightMapCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]))
    1210 {
    1211     if (argc < 2)
    1212     {
    1213         {   
    1214         srand( (unsigned)time( NULL ) );
    1215         int size = 20 * 20;
    1216         float sigma = 5.0f;
    1217         float mean = exp(0.0f) / (sigma * sqrt(2.0f));
    1218         float* data = (float*) malloc(sizeof(float) * size);
    1219 
    1220         float x;
    1221         for (int i = 0; i < size; ++i)
    1222         {
    1223             x = - 10 + i%20;
    1224             data[i] = exp(- (x * x)/(2 * sigma * sigma)) / (sigma * sqrt(2.0f)) / mean;
    1225         }
    1226 
    1227         HeightMap* heightMap = new HeightMap();
    1228         heightMap->setHeight(0, 0, 1, 1, 20, 20, data);
    1229         heightMap->setColorMap(get_transfunc("default"));
    1230         heightMap->setVisible(true);
    1231         heightMap->setLineContourVisible(true);
    1232         g_heightMap.push_back(heightMap);
    1233         }
    1234 
    1235         return TCL_OK;
    1236     }
    1237 
    1238     char c = *argv[1];
    1239     if (c == 'd' && strcmp(argv[1],"data") == 0)
    1240     {
    1241         //bytes
    1242         vector<int> indices;
    1243         if (strcmp(argv[2],"visible") == 0)
    1244         {
    1245             bool visible = !strcmp(argv[3], "true");
    1246            
    1247             if (GetIndices(interp, argc-4, argv+4, &indices) != TCL_OK)
    1248             {
    1249                return TCL_ERROR;
    1250             }
    1251 
    1252             for (int i = 0; i < indices.size(); ++i)
    1253             {
    1254                 if ((indices[i] < g_heightMap.size()) && (g_heightMap[indices[i]] != NULL))
    1255                 {
    1256                     g_heightMap[indices[i]]->setVisible(visible);
    1257                 }
    1258             }
    1259             return TCL_OK;
    1260         }
    1261         else if (c == 'f' && strcmp(argv[2],"follows") == 0) {
    1262             int nbytes;
    1263             if (Tcl_GetInt(interp, argv[3], &nbytes) != TCL_OK) {
    1264                 return TCL_ERROR;
    1265             }
    1266         }
    1267     }
    1268     else if (c == 'l' && (strcmp(argv[1], "linecontour") == 0))
    1269     {
    1270         //bytes
    1271         vector<int> indices;
    1272         if (strcmp(argv[2],"visible") == 0)
    1273         {
    1274            
    1275             bool visible = !(strcmp("true", argv[3]));
    1276             printf("heightmap linecontour visible %s\n", (visible)?"true":"false");
    1277             if (GetIndices(interp, argc-4, argv+4, &indices) != TCL_OK)
    1278             {
    1279                 return TCL_ERROR;
    1280             }
    1281 
    1282             for (int i = 0; i < indices.size(); ++i)
    1283             {
    1284                 printf("heightmap index %d\n");
    1285                 if ((indices[i] < g_heightMap.size()) && (g_heightMap[indices[i]] != NULL))
    1286                 {
    1287                     printf("heightmap index %d visible applied\n");
    1288                     g_heightMap[indices[i]]->setLineContourVisible(visible);
    1289                 }
    1290             }
    1291             return TCL_OK;
    1292         }
    1293         else if (strcmp(argv[2],"color") == 0)
    1294         {
    1295             double r, g, b;
    1296             if ((Tcl_GetDouble(interp, argv[3], &r) == TCL_OK) &&
    1297                 (Tcl_GetDouble(interp, argv[4], &g) == TCL_OK) &&
    1298                 (Tcl_GetDouble(interp, argv[5], &b) == TCL_OK)) {
    1299                 r = r / 255.0;
    1300                 g = g / 255.0;
    1301                 b = b / 255.0;
    1302             }
    1303             else
    1304             {
    1305                 return TCL_ERROR;
    1306             }
    1307 
    1308             vector<int> indices;
    1309             if (GetIndices(interp, argc-6, argv+6, &indices) != TCL_OK)
    1310             {
    1311                 return TCL_ERROR;
    1312             }
    1313             for (int i = 0; i < indices.size(); ++i)
    1314             {
    1315                 if ((indices[i] < g_heightMap.size()) && (g_heightMap[indices[i]] != NULL))
    1316                 {
    1317                     g_heightMap[indices[i]]->setLineContourColor(r, g, b);
    1318                 }
    1319             }
    1320 
    1321             return TCL_OK;
    1322         }
    1323     }
    1324     else if (c == 't' && (strcmp(argv[1], "transfunc") == 0))
    1325     {
    1326         TransferFunction *tf = get_transfunc((char*)argv[2]);
    1327         if (tf == NULL) {
    1328             Tcl_AppendResult(interp, "transfer function \"", argv[3],
    1329                 "\" is not defined", (char*)NULL);
    1330             return TCL_ERROR;
    1331         }
    1332 
    1333         vector<int> indices;
    1334         if (GetVolumeIndices(interp, argc - 3, argv + 3, &indices) != TCL_OK)
    1335         {
    1336             for (int i = 0; i < indices.size(); ++i)
    1337             {
    1338                 if ((indices[i] < g_heightMap.size()) && (g_heightMap[indices[i]] != NULL))
    1339                 {
    1340                     g_heightMap[indices[i]]->setColorMap(tf);
    1341                 }
    1342             }
    1343         }
    1344         return TCL_OK;
    1345     }
    1346    
    1347     Tcl_AppendResult(interp, "bad option \"", argv[1],
    1348         "\": should be data, outline, shading, or state", (char*)NULL);
    1349     return TCL_ERROR;
    1350 }
    1351 
    1352 int GridCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]))
    1353 {
    1354     char c = *argv[1];
    1355     if (c == 'v' && strcmp(argv[1],"visible") == 0)
    1356     {
    1357         if (strcmp(argv[2],"true") == 0)
    1358         {
    1359             g_grid->setVisible(true);
    1360             return TCL_OK;
    1361         }
    1362         else if (strcmp(argv[2],"false") == 0)
    1363         {
    1364             g_grid->setVisible(false);
    1365             return TCL_OK;
    1366         }
    1367     }
    1368     else if (c == 'l' && strcmp(argv[1],"linecount") == 0)
    1369     {
    1370         int x, y, z;
    1371 
    1372         if ((Tcl_GetInt(interp, argv[2], &x) == TCL_OK) &&
    1373             (Tcl_GetInt(interp, argv[3], &y) == TCL_OK) &&
    1374             (Tcl_GetInt(interp, argv[4], &z) == TCL_OK)) {
    1375 
    1376             if (g_grid) g_grid->setGridLineCount(x, y, z);
    1377 
    1378             return TCL_OK;
    1379         }
    1380     }
    1381     else if (c == 'a' && strcmp(argv[1],"axiscolor") == 0)
    1382     {
    1383         int r, g, b;
    1384         if ((Tcl_GetInt(interp, argv[2], &r) == TCL_OK) &&
    1385             (Tcl_GetInt(interp, argv[3], &g) == TCL_OK) &&
    1386             (Tcl_GetInt(interp, argv[4], &b) == TCL_OK)) {
    1387 
    1388             if (g_grid) g_grid->setAxisColor(r / 255.0f, g / 255.0f, b / 255.0f);
    1389             return TCL_OK;
    1390         }
    1391     }
    1392     else if (c == 'l' && strcmp(argv[1],"linecolor") == 0)
    1393     {
    1394         int r, g, b;
    1395         if ((Tcl_GetInt(interp, argv[2], &r) == TCL_OK) &&
    1396             (Tcl_GetInt(interp, argv[3], &g) == TCL_OK) &&
    1397             (Tcl_GetInt(interp, argv[4], &b) == TCL_OK)) {
    1398 
    1399             if (g_grid) g_grid->setGridLineColor(r / 255.0f, g / 255.0f, b / 255.0f);
    1400             return TCL_OK;
    1401         }
    1402     }
    1403     else if (c == 'm')
    1404     {
    1405         if (strcmp(argv[1],"minmax") == 0)
    1406         {
    1407             double x1, y1, z1, x2, y2, z2;
    1408             if ((Tcl_GetDouble(interp, argv[2], &x1) == TCL_OK) &&
    1409                 (Tcl_GetDouble(interp, argv[3], &y1) == TCL_OK) &&
    1410                 (Tcl_GetDouble(interp, argv[4], &z1) == TCL_OK) &&
    1411                 (Tcl_GetDouble(interp, argv[5], &x2) == TCL_OK) &&
    1412                 (Tcl_GetDouble(interp, argv[6], &y2) == TCL_OK) &&
    1413                 (Tcl_GetDouble(interp, argv[7], &z2) == TCL_OK)) {
    1414 
    1415                 if (g_grid) g_grid->setMinMax(Vector3(x1, y1, z1), Vector3(x2, y2, z2));
    1416 
    1417                 return TCL_OK;
    1418             }
    1419         }
    1420     }
    1421     else if (c == 'a' && strcmp(argv[1],"axisname") == 0)
    1422     {
    1423         int axisID = 0;
    1424         if (!strcmp(argv[2], "x")) axisID = 0;
    1425         if (!strcmp(argv[2], "y")) axisID = 1;
    1426         if (!strcmp(argv[2], "z")) axisID = 2;
    1427        
    1428         if (g_grid) g_grid->setAxisName(axisID, argv[3]);
    1429         return TCL_OK;
    1430     }
    1431 
    1432     Tcl_AppendResult(interp, "bad option \"", argv[1],
    1433         "\": should be data, outline, shading, or state", (char*)NULL);
    1434     return TCL_ERROR;
    1435 }
    1436 
    1437 int AxisCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]))
    1438 {
    1439     if (argc < 2) {
    1440         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    1441             " option arg arg...\"", (char*)NULL);
    1442         return TCL_ERROR;
    1443     }
    1444 
    1445     char c = *argv[1];
    1446     if (c == 'v' && strcmp(argv[1],"visible") == 0)
    1447     {
    1448         if (strcmp(argv[2],"true") == 0)
    1449         {
    1450             axis_on = true;
    1451         }
    1452         else if (strcmp(argv[2],"false") == 0)
    1453         {
    1454             axis_on = false;
    1455         }
    1456            
    1457         return TCL_OK;
    1458     }
    1459 
    1460     Tcl_AppendResult(interp, "bad option \"", argv[1],
    1461         "\": should be data, outline, shading, or state", (char*)NULL);
    1462     return TCL_ERROR;
    1463 }
    1464 
    1465 /*
    1466  * ----------------------------------------------------------------------
    1467  * FUNCTION: GetVolumeIndices()
    1468  *
    1469  * Used internally to decode a series of volume index values and
    1470  * store then in the specified vector.  If there are no volume index
    1471  * arguments, this means "all volumes" to most commands, so all
    1472  * active volume indices are stored in the vector.
    1473  *
    1474  * Updates pushes index values into the vector.  Returns TCL_OK or
    1475  * TCL_ERROR to indicate an error.
    1476  * ----------------------------------------------------------------------
    1477  */
    1478 static int
    1479 GetVolumeIndices(Tcl_Interp *interp, int argc, CONST84 char *argv[],
    1480     vector<int>* vectorPtr)
    1481 {
    1482     if (argc == 0) {
    1483         for (int n=0; n < volume.size(); n++) {
    1484             if (volume[n] != NULL) {
    1485                 vectorPtr->push_back(n);
    1486             }
    1487         }
    1488     } else {
    1489         int ivol;
    1490         for (int n=0; n < argc; n++) {
    1491             if (Tcl_GetInt(interp, argv[n], &ivol) != TCL_OK) {
    1492                 return TCL_ERROR;
    1493             }
    1494             if (ivol < 0 || ivol >= volume.size()) {
    1495                 Tcl_AppendResult(interp, "bad volume index \"", argv[n],
    1496                     "\"", (char*)NULL);
    1497                 return TCL_ERROR;
    1498             }
    1499             if (volume[ivol] != NULL) {
    1500                 vectorPtr->push_back(ivol);
    1501             }
    1502         }
    1503     }
    1504     return TCL_OK;
    1505 }
    1506 
    1507 static int
    1508 GetIndices(Tcl_Interp *interp, int argc, CONST84 char *argv[],
    1509     vector<int>* vectorPtr)
    1510 {
    1511     int ivol;
    1512     for (int n=0; n < argc; n++)
    1513     {
    1514         if (Tcl_GetInt(interp, argv[n], &ivol) != TCL_OK) {
    1515             return TCL_ERROR;
    1516         }
    1517         vectorPtr->push_back(ivol);
    1518     }
    1519     return TCL_OK;
    1520 }
    1521 
    1522 /*
    1523  * ----------------------------------------------------------------------
    1524  * FUNCTION: GetAxis()
    1525  *
    1526  * Used internally to decode an axis value from a string ("x", "y",
    1527  * or "z") to its index (0, 1, or 2).  Returns TCL_OK if successful,
    1528  * along with a value in valPtr.  Otherwise, it returns TCL_ERROR
    1529  * and an error message in the interpreter.
    1530  * ----------------------------------------------------------------------
    1531  */
    1532 static int
    1533 GetAxis(Tcl_Interp *interp, char *str, int *valPtr)
    1534 {
    1535     if (strcmp(str,"x") == 0) {
    1536         *valPtr = 0;
    1537         return TCL_OK;
    1538     }
    1539     else if (strcmp(str,"y") == 0) {
    1540         *valPtr = 1;
    1541         return TCL_OK;
    1542     }
    1543     else if (strcmp(str,"z") == 0) {
    1544         *valPtr = 2;
    1545         return TCL_OK;
    1546     }
    1547     Tcl_AppendResult(interp, "bad axis \"", str,
    1548         "\": should be x, y, or z", (char*)NULL);
    1549     return TCL_ERROR;
    1550 }
    1551 
    1552 /*
    1553  * ----------------------------------------------------------------------
    1554  * FUNCTION: GetColor()
    1555  *
    1556  * Used internally to decode a color value from a string ("R G B")
    1557  * as a list of three numbers 0-1.  Returns TCL_OK if successful,
    1558  * along with RGB values in valPtr.  Otherwise, it returns TCL_ERROR
    1559  * and an error message in the interpreter.
    1560  * ----------------------------------------------------------------------
    1561  */
    1562 static int
    1563 GetColor(Tcl_Interp *interp, char *str, float *rgbPtr)
    1564 {
    1565     int rgbc;
    1566     char **rgbv;
    1567     if (Tcl_SplitList(interp, str, &rgbc, (const char***)&rgbv) != TCL_OK) {
    1568         return TCL_ERROR;
    1569     }
    1570     if (rgbc != 3) {
    1571         Tcl_AppendResult(interp, "bad color \"", str,
    1572             "\": should be {R G B} as double values 0-1", (char*)NULL);
    1573         return TCL_ERROR;
    1574     }
    1575 
    1576     double rval, gval, bval;
    1577     if (Tcl_GetDouble(interp, rgbv[0], &rval) != TCL_OK) {
    1578         Tcl_Free((char*)rgbv);
    1579         return TCL_ERROR;
    1580     }
    1581     if (Tcl_GetDouble(interp, rgbv[1], &gval) != TCL_OK) {
    1582         Tcl_Free((char*)rgbv);
    1583         return TCL_ERROR;
    1584     }
    1585     if (Tcl_GetDouble(interp, rgbv[2], &bval) != TCL_OK) {
    1586         Tcl_Free((char*)rgbv);
    1587         return TCL_ERROR;
    1588     }
    1589     Tcl_Free((char*)rgbv);
    1590 
    1591     rgbPtr[0] = (float)rval;
    1592     rgbPtr[1] = (float)gval;
    1593     rgbPtr[2] = (float)bval;
    1594 
    1595     return TCL_OK;
    1596 }
     239
    1597240
    1598241/*
     
    1634277    sprintf(buffer, str, v1, v2, v3);
    1635278    write(0, buffer, strlen(buffer));
    1636 }
    1637 
    1638 
    1639 static int
    1640 PlaneNewCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])){
    1641   fprintf(stderr, "load plane for 2D visualization command\n");
    1642 
    1643   int index, w, h;
    1644 
    1645   if (argc != 4) {
    1646     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    1647                 " plane_index w h \"", (char*)NULL);
    1648     return TCL_ERROR;
    1649   }
    1650   if (Tcl_GetInt(interp, argv[1], &index) != TCL_OK) {
    1651         return TCL_ERROR;
    1652   }
    1653   if (Tcl_GetInt(interp, argv[2], &w) != TCL_OK) {
    1654         return TCL_ERROR;
    1655   }
    1656   if (Tcl_GetInt(interp, argv[3], &h) != TCL_OK) {
    1657         return TCL_ERROR;
    1658   }
    1659 
    1660   //Now read w*h*4 bytes. The server expects the plane to be a stream of floats
    1661   char* tmp = new char[int(w*h*sizeof(float))];
    1662   bzero(tmp, w*h*4);
    1663   int status = read(0, tmp, w*h*sizeof(float));
    1664   if (status <= 0){
    1665     exit(0);
    1666   }
    1667  
    1668   plane[index] = new Texture2D(w, h, GL_FLOAT, GL_LINEAR, 1, (float*)tmp);
    1669  
    1670   delete[] tmp;
    1671   return TCL_OK;
    1672 }
    1673 
    1674 
    1675 static
    1676 int PlaneLinkCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])){
    1677   fprintf(stderr, "link the plane to the 2D renderer command\n");
    1678 
    1679   int plane_index, tf_index;
    1680 
    1681   if (argc != 3) {
    1682     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    1683                 " plane_index tf_index \"", (char*)NULL);
    1684     return TCL_ERROR;
    1685   }
    1686   if (Tcl_GetInt(interp, argv[1], &plane_index) != TCL_OK) {
    1687         return TCL_ERROR;
    1688   }
    1689   if (Tcl_GetInt(interp, argv[2], &tf_index) != TCL_OK) {
    1690         return TCL_ERROR;
    1691   }
    1692 
    1693   //plane_render->add_plane(plane[plane_index], tf[tf_index]);
    1694 
    1695   return TCL_OK;
    1696 }
    1697 
    1698 
    1699 //Enable a 2D plane for render
    1700 //The plane_index is the index mantained in the 2D plane renderer
    1701 static
    1702 int PlaneEnableCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])){
    1703   fprintf(stderr, "enable a plane so the 2D renderer can render it command\n");
    1704 
    1705   int plane_index, mode;
    1706 
    1707   if (argc != 3) {
    1708     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    1709                 " plane_index mode \"", (char*)NULL);
    1710     return TCL_ERROR;
    1711   }
    1712   if (Tcl_GetInt(interp, argv[1], &plane_index) != TCL_OK) {
    1713         return TCL_ERROR;
    1714   }
    1715   if (Tcl_GetInt(interp, argv[2], &mode) != TCL_OK) {
    1716         return TCL_ERROR;
    1717   }
    1718 
    1719   if(mode==0)
    1720     plane_render->set_active_plane(-1);
    1721   else
    1722     plane_render->set_active_plane(plane_index);
    1723 
    1724   return TCL_OK;
    1725279}
    1726280
     
    27081262}
    27091263
     1264
     1265int renderLegend(int ivol, int width, int height, const char* volArg)
     1266{
     1267    TransferFunction *tf = NULL;
     1268
     1269    if (ivol < n_volumes) {
     1270        tf = g_vol_render->get_volume_shading(volume[ivol]);
     1271    }
     1272
     1273    if (tf == NULL) {
     1274        return TCL_ERROR;
     1275    }
     1276
     1277    int old_width = win_width;
     1278    int old_height = win_height;
     1279
     1280    plane_render->set_screen_size(width, height);
     1281    resize_offscreen_buffer(width, height);
     1282
     1283    // generate data for the legend
     1284    float data[512];
     1285    for (int i=0; i < 256; i++) {
     1286        data[i] = data[i+256] = (float)(i/255.0);
     1287    }
     1288    plane[0] = new Texture2D(256, 2, GL_FLOAT, GL_LINEAR, 1, data);
     1289    int index = plane_render->add_plane(plane[0], tf);
     1290    plane_render->set_active_plane(index);
     1291
     1292    offscreen_buffer_capture();
     1293    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear screen
     1294    plane_render->render();
     1295
     1296    // INSOO
     1297    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, screen_buffer);
     1298    //glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, screen_buffer); // INSOO's
     1299
     1300    std::ostringstream result;
     1301    result << "nv>legend " << volArg;
     1302    result << " " << volume[ivol]->range_min();
     1303    result << " " << volume[ivol]->range_max();
     1304    bmp_write(result.str().c_str());
     1305    write(0, "\n", 1);
     1306
     1307    plane_render->remove_plane(index);
     1308    resize_offscreen_buffer(old_width, old_height);
     1309
     1310    return TCL_OK;
     1311}
    27101312
    27111313//initialize frame buffer objects for offscreen rendering
     
    29421544}
    29431545
    2944 
    2945 
    2946 void initTcl()
    2947 {
    2948     interp = Tcl_CreateInterp();
    2949     Tcl_MakeSafe(interp);
    2950 
    2951     Tcl_DStringInit(&cmdbuffer);
    2952 
    2953     // manipulate the viewpoint
    2954     Tcl_CreateCommand(interp, "camera", CameraCmd,
    2955         (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
    2956 
    2957     // turn on/off cut planes in x/y/z directions
    2958     Tcl_CreateCommand(interp, "cutplane", CutplaneCmd,
    2959         (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
    2960 
    2961     // request the legend for a plot (transfer function)
    2962     Tcl_CreateCommand(interp, "legend", LegendCmd,
    2963         (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
    2964 
    2965     // change the size of the screen (size of picture generated)
    2966     Tcl_CreateCommand(interp, "screen", ScreenCmd,
    2967         (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
    2968 
    2969     // manipulate transfer functions
    2970     Tcl_CreateCommand(interp, "transfunc", TransfuncCmd,
    2971         (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
    2972 
    2973     // set the "up" direction for volumes
    2974     Tcl_CreateCommand(interp, "up", UpCmd,
    2975         (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
    2976 
    2977     // manipulate volume data
    2978     Tcl_CreateCommand(interp, "volume", VolumeCmd,
    2979         (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
    2980 
    2981     Tcl_CreateCommand(interp, "axis", AxisCmd,
    2982         (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
    2983 
    2984     Tcl_CreateCommand(interp, "grid", GridCmd,
    2985         (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
    2986 
    2987     Tcl_CreateCommand(interp, "heightmap", HeightMapCmd,
    2988         (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
    2989 
    2990     // get screenshot
    2991     Tcl_CreateCommand(interp, "screenshot", ScreenShotCmd,
    2992         (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
    2993 
    2994 #ifdef __TEST_CODE__
    2995     Tcl_CreateCommand(interp, "test", TestCmd,
    2996         (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
    2997 #endif
    2998 
    2999     // create a default transfer function
    3000     if (Tcl_Eval(interp, def_transfunc) != TCL_OK) {
    3001         fprintf(stdin, "WARNING: bad default transfer function\n");
    3002         fprintf(stdin, Tcl_GetStringResult(interp));
    3003     }
    3004 }
    3005 
    3006 
    30071546void read_screen()
    30081547{
     
    32071746}
    32081747
    3209 
    3210 void xinetd_listen(){
    3211 
    3212     int flags = fcntl(0, F_GETFL, 0);
    3213     fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
    3214 
    3215     int status = TCL_OK;
    3216     int npass = 0;
    3217 
    3218     //
    3219     //  Read and execute as many commands as we can from stdin...
    3220     //
    3221     while (status == TCL_OK) {
    3222         //
    3223         //  Read the next command from the buffer.  First time through
    3224         //  we block here and wait if necessary until a command comes in.
    3225         //
    3226         //  BE CAREFUL:  Read only one command, up to a newline.
    3227         //  The "volume data follows" command needs to be able to read
    3228         //  the data immediately following the command, and we shouldn't
    3229         //  consume it here.
    3230         //
    3231         while (1) {
    3232             char c = getchar();
    3233             if (c <= 0) {
    3234                 if (npass == 0) {
    3235                     exit(0);  // EOF -- we're done!
    3236                 } else {
    3237                     break;
    3238                 }
    3239             }
    3240             Tcl_DStringAppend(&cmdbuffer, &c, 1);
    3241 
    3242             if (c=='\n' && Tcl_CommandComplete(Tcl_DStringValue(&cmdbuffer))) {
    3243                 break;
    3244             }
    3245         }
    3246 
    3247         // no command? then we're done for now
    3248         if (Tcl_DStringLength(&cmdbuffer) == 0) {
    3249             break;
    3250         }
    3251 
    3252         // back to original flags during command evaluation...
    3253         fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
    3254 
    3255         status = Tcl_Eval(interp, Tcl_DStringValue(&cmdbuffer));
    3256         Tcl_DStringSetLength(&cmdbuffer, 0);
    3257 
    3258         // non-blocking for next read -- we might not get anything
    3259         fcntl(0, F_SETFL, flags | O_NONBLOCK);
    3260         npass++;
    3261     }
    3262     fcntl(0, F_SETFL, flags);
    3263 
    3264     if (status != TCL_OK) {
    3265         std::ostringstream errmsg;
    3266         errmsg << "ERROR: " << Tcl_GetStringResult(interp) << std::endl;
    3267         write(0, errmsg.str().c_str(), errmsg.str().size());
    3268         return;
    3269     }
    3270 
    3271     //
    3272     //  Generate the latest frame and send it back to the client
    3273     //
    3274     // INSOO
    3275     offscreen_buffer_capture();  //enable offscreen render
    3276 
    3277     display();
    3278 
    3279     // INSOO
    3280 #ifdef XINETD
    3281    read_screen();
    3282    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    3283 #else
    3284    display_offscreen_buffer(); //display the final rendering on screen
    3285    read_screen();
    3286    glutSwapBuffers();
    3287 #endif   
    3288 
    3289 #if DO_RLE
    3290     do_rle();
    3291     int sizes[2] = {  offsets_size*sizeof(offsets[0]), rle_size };
    3292     fprintf(stderr, "Writing %d,%d\n", sizes[0], sizes[1]); fflush(stderr);
    3293     write(0, &sizes, sizeof(sizes));
    3294     write(0, offsets, offsets_size*sizeof(offsets[0]));
    3295     write(0, rle, rle_size);    //unsigned byte
    3296 #else
    3297     bmp_write("nv>image -bytes");
    3298 #endif
    3299 }
    3300 
    3301 
    33021748/*
    33031749//draw vectors
     
    33371783
    33381784#ifdef XINETD
     1785    // in Command.cpp
    33391786    xinetd_listen();
    33401787#else
  • trunk/vizservers/nanovis/nanovis.h

    r457 r829  
    1313 * ======================================================================
    1414 */
     15#ifndef __NANOVIS_H__
     16#define __NANOVIS_H__
    1517
    1618#include <GL/glew.h>
     
    2426#include <assert.h>
    2527#include <float.h>
     28#include <getopt.h>
     29#include <stdio.h>
     30#include <math.h>
     31#include <fstream>
     32#include <sstream>
     33#include <string>
     34#include <sys/time.h>
     35#include <sys/types.h>
     36#include <unistd.h>
     37#include <fcntl.h>
     38#include <signal.h>
    2639
    2740#include "define.h"
     
    87100
    88101
     102/*
    89103//variables for mouse events
    90104float live_rot_x = 90.;         //object rotation angles
     
    120134//currently active shader, default renders one volume only
    121135int cur_shader = 0;
     136*/
     137
     138#endif
Note: See TracChangeset for help on using the changeset viewer.