source: trunk/vizservers/nanovis/Command.cpp @ 829

Last change on this file since 829 was 829, checked in by vrinside, 13 years ago

Moved all the functions related to TCL to Command.cpp

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