source: trunk/packages/vizservers/nanovis/nanovis.cpp @ 1544

Last change on this file since 1544 was 1544, checked in by gah, 15 years ago
File size: 70.1 KB
Line 
1
2/*
3 * ----------------------------------------------------------------------
4 * Nanovis: Visualization of Nanoelectronics Data
5 *
6 * ======================================================================
7 *  AUTHOR:  Wei Qiao <qiaow@purdue.edu>
8 *           Michael McLennan <mmclennan@purdue.edu>
9 *           Purdue Rendering and Perceptualization Lab (PURPL)
10 *
11 *  Copyright (c) 2004-2006  Purdue Research Foundation
12 *
13 *  See the file "license.terms" for information on usage and
14 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 * ======================================================================
16 */
17
18#include <assert.h>
19#include <errno.h>
20#include <fcntl.h>
21#include <fstream>
22#include <getopt.h>
23#include <iostream>
24#include <math.h>
25#include <memory.h>
26#include <signal.h>
27#include <sstream>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string>
31#include <sys/resource.h>
32#include <sys/time.h>
33#include <sys/times.h>
34#include <sys/types.h>
35#include <time.h>
36#include <unistd.h>
37
38#include "Nv.h"
39#include "PointSetRenderer.h"
40#include "PointSet.h"
41#include "Util.h"
42#include <NvLIC.h>
43#include <Trace.h>
44
45#include "nanovis.h"
46#include "define.h"
47#include "RpField1D.h"
48#include "RpFieldRect3D.h"
49#include "RpFieldPrism3D.h"
50#include "RpEncode.h"
51
52#include "ZincBlendeVolume.h"
53#include "NvLoadFile.h"
54#include "NvColorTableRenderer.h"
55#include "NvEventLog.h"
56#include "NvZincBlendeReconstructor.h"
57#include "NvFlowVisRenderer.h"
58#include "HeightMap.h"
59#include "Grid.h"
60#include "VolumeInterpolator.h"
61#include <RenderContext.h>
62
63#include <BMPImageLoaderImpl.h>
64#include <ImageLoaderFactory.h>
65
66//#define  _LOCAL_ZINC_TEST_
67
68// R2 headers
69#include <R2/R2FilePath.h>
70#include <R2/R2Fonts.h>
71
72#include "Unirect.h"
73#include "Switch.h"
74#include "FlowCmd.h"
75
76#define SIZEOF_BMP_HEADER   54
77
78extern void NvInitCG(); // in Shader.cpp
79
80// Indicates "up" axis:  x=1, y=2, z=3, -x=-1, -y=-2, -z=-3
81enum AxisDirections {
82    X_POS = 1, Y_POS = 2, Z_POS = 3, X_NEG = -1, Y_NEG = -2, Z_NEG = -3
83};
84
85#define KEEPSTATS       1
86
87#define CVT2SECS(x)  ((double)(x).tv_sec) + ((double)(x).tv_usec * 1.0e-6)
88
89#define TRUE    1
90#define FALSE   0
91
92typedef struct {
93    pid_t pid;
94    size_t nFrames;             /* # of frames sent to client. */
95    size_t nBytes;              /* # of bytes for all frames. */
96    size_t nCommands;           /* # of commands executed */
97    double cmdTime;             /* Elasped time spend executing commands. */
98    struct timeval start;       /* Start of elapsed time. */
99} Stats;
100
101static Stats stats;
102
103// STATIC MEMBER DATA
104Grid *NanoVis::grid = NULL;
105int NanoVis::updir = Y_POS;
106NvCamera* NanoVis::cam = NULL;
107Tcl_HashTable NanoVis::volumeTable;
108Tcl_HashTable NanoVis::heightmapTable;
109VolumeRenderer* NanoVis::vol_renderer = NULL;
110PointSetRenderer* NanoVis::pointset_renderer = NULL;
111vector<PointSet*> NanoVis::pointSet;
112PlaneRenderer* NanoVis::plane_render = NULL;
113Texture2D* NanoVis::plane[10];
114NvColorTableRenderer* NanoVis::color_table_renderer = NULL;
115
116#ifndef NEW_FLOW_ENGINE
117NvParticleRenderer* NanoVis::flowVisRenderer = NULL;
118#else
119NvFlowVisRenderer* NanoVis::flowVisRenderer = NULL;
120#endif
121VelocityArrowsSlice* NanoVis::velocityArrowsSlice = 0;
122
123graphics::RenderContext* NanoVis::renderContext = NULL;
124NvLIC* NanoVis::licRenderer = NULL;
125R2Fonts* NanoVis::fonts;
126
127FILE *NanoVis::stdin = NULL;
128FILE *NanoVis::logfile = NULL;
129FILE *NanoVis::recfile = NULL;
130
131bool NanoVis::axis_on = true;
132bool NanoVis::config_pending = false;
133bool NanoVis::debug_flag = false;
134
135Tcl_Interp *NanoVis::interp;
136Tcl_DString NanoVis::cmdbuffer;
137
138//frame buffer for final rendering
139GLuint NanoVis::final_color_tex = 0;
140GLuint NanoVis::final_depth_rb = 0;
141GLuint NanoVis::final_fbo = 0;
142int NanoVis::render_window = 0;       /* GLUT handle for the render window */
143int NanoVis::win_width = NPIX;        /* Width of the render window */
144int NanoVis::win_height = NPIX;       /* Height of the render window */
145
146unsigned char* NanoVis::screen_buffer = NULL;
147
148unsigned int NanoVis::flags = 0;
149Tcl_HashTable NanoVis::flowTable;
150double NanoVis::magMin = DBL_MAX;
151double NanoVis::magMax = -DBL_MAX;
152float NanoVis::xMin = FLT_MAX;
153float NanoVis::xMax = -FLT_MAX;
154float NanoVis::yMin = FLT_MAX;
155float NanoVis::yMax = -FLT_MAX;
156float NanoVis::zMin = FLT_MAX;
157float NanoVis::zMax = -FLT_MAX;
158float NanoVis::wMin = FLT_MAX;
159float NanoVis::wMax = -FLT_MAX;
160float NanoVis::xOrigin;
161float NanoVis::yOrigin;
162float NanoVis::zOrigin;
163
164/* FIXME: This variable is always true. */
165bool volume_mode = true;
166
167// in Command.cpp
168extern Tcl_Interp *initTcl();
169
170float vert[NMESH*NMESH*3];              //particle positions in main memory
171float slice_vector[NMESH*NMESH*4];      //per slice vectors in main memory
172
173// maps transfunc name to TransferFunction object
174Tcl_HashTable NanoVis::tfTable;
175
176// pointers to 2D planes, currently handle up 10
177
178
179PerfQuery* perf;                        //perfromance counter
180
181CGprogram m_passthru_fprog;
182CGparameter m_passthru_scale_param, m_passthru_bias_param;
183
184// Variables for mouse events
185
186// Default camera rotation angles.
187const float def_rot_x = 90.0f;
188const float def_rot_y = 180.0f;
189const float def_rot_z = -135.0f;
190
191// Default camera target.
192const float def_target_x = 0.0f;
193const float def_target_y = 0.0f;
194const float def_target_z = 100.0f;
195
196// Default camera location.
197const float def_eye_x = -0.0f;
198const float def_eye_y = -0.0f;
199const float def_eye_z = -2.5f;
200
201
202#ifndef XINETD
203// Last locations mouse events
204static int left_last_x;
205static int left_last_y;
206static int right_last_x;
207static int right_last_y;
208static bool left_down = false;
209static bool right_down = false;
210#endif /*XINETD*/
211
212// Image based flow visualization slice location
213// FLOW
214float NanoVis::lic_slice_x = 0.5f;
215float NanoVis::lic_slice_y = 0.5f;
216float NanoVis::lic_slice_z = 0.5f;
217int NanoVis::lic_axis = 2; // z axis
218
219using namespace std;
220
221#define RM_VOLUME 1
222#define RM_POINT 2
223
224int renderMode = RM_VOLUME;
225
226/*
227 * ----------------------------------------------------------------------
228 * USAGE: debug("string", ...)
229 *
230 * Use this anywhere within the package to send a debug message
231 * back to the client.  The string can have % fields as used by
232 * the printf() package.  Any remaining arguments are treated as
233 * field substitutions on that.
234 * ----------------------------------------------------------------------
235 */
236void
237debug(char *str)
238{
239    ssize_t nWritten;
240
241    nWritten = write(0, str, strlen(str));
242}
243
244void
245debug(char *str, double v1)
246{
247    char buffer[512];
248    sprintf(buffer, str, v1);
249    debug(buffer);
250}
251
252void
253debug(char *str, double v1, double v2)
254{
255    char buffer[512];
256    sprintf(buffer, str, v1, v2);
257    debug(buffer);
258}
259
260void
261debug(char *str, double v1, double v2, double v3)
262{
263    char buffer[512];
264    sprintf(buffer, str, v1, v2, v3);
265    debug(buffer);
266}
267
268void removeAllData()
269{
270    //
271}
272
273
274void
275NanoVis::EventuallyRedraw(unsigned int flag)
276{
277    if (flag) {
278        flags |= flag;
279    }
280    if ((flags & REDRAW_PENDING) == 0) {
281        glutPostRedisplay();
282        flags |= REDRAW_PENDING;
283    }
284}
285
286#if KEEPSTATS
287
288static int
289WriteStats(const char *who, int code)
290{
291    double start, finish;
292    pid_t pid;
293    char buf[BUFSIZ];
294    Tcl_DString ds;
295
296    {
297        struct timeval tv;
298
299        /* Get ending time.  */
300        gettimeofday(&tv, NULL);
301        finish = CVT2SECS(tv);
302        tv = stats.start;
303        start = CVT2SECS(tv);
304    }
305    pid = getpid();
306    Tcl_DStringInit(&ds);
307
308    sprintf(buf, "<session server=\"%s\" ", who);
309    Tcl_DStringAppend(&ds, buf, -1);
310
311    gethostname(buf, BUFSIZ-1);
312    buf[BUFSIZ-1] = '\0';
313    Tcl_DStringAppend(&ds, "host=\"", -1);
314    Tcl_DStringAppend(&ds, buf, -1);
315    Tcl_DStringAppend(&ds, "\" ", -1);
316
317    strcpy(buf, ctime(&stats.start.tv_sec));
318    buf[strlen(buf) - 1] = '\0';
319    Tcl_DStringAppend(&ds, "date=\"", -1);
320    Tcl_DStringAppend(&ds, buf, -1);
321    Tcl_DStringAppend(&ds, "\" ", -1);
322
323    sprintf(buf, "date_secs=\"%ld\" ", stats.start.tv_sec);
324    Tcl_DStringAppend(&ds, buf, -1);
325
326    sprintf(buf, "pid=\"%d\" ", pid);
327    Tcl_DStringAppend(&ds, buf, -1);
328    sprintf(buf, "num_frames=\"%lu\" ", (unsigned long int)stats.nFrames);
329    Tcl_DStringAppend(&ds, buf, -1);
330    sprintf(buf, "frame_bytes=\"%lu\" ", (unsigned long int)stats.nBytes);
331    Tcl_DStringAppend(&ds, buf, -1);
332    sprintf(buf, "num_commands=\"%lu\" ", (unsigned long int)stats.nCommands);
333    Tcl_DStringAppend(&ds, buf, -1);
334    sprintf(buf, "cmd_time=\"%g\" ", stats.cmdTime);
335    Tcl_DStringAppend(&ds, buf, -1);
336    sprintf(buf, "session_time=\"%g\" ", finish - start);
337    Tcl_DStringAppend(&ds, buf, -1);
338    sprintf(buf, "status=\"%d\" ", code);
339    Tcl_DStringAppend(&ds, buf, -1);
340    {
341        long clocksPerSec = sysconf(_SC_CLK_TCK);
342        double clockRes = 1.0 / clocksPerSec;
343        struct tms tms;
344
345        memset(&tms, 0, sizeof(tms));
346        times(&tms);
347        sprintf(buf, "utime=\"%g\" ", tms.tms_utime * clockRes);
348        Tcl_DStringAppend(&ds, buf, -1);
349        sprintf(buf, "stime=\"%g\" ", tms.tms_stime * clockRes);
350        Tcl_DStringAppend(&ds, buf, -1);
351        sprintf(buf, "cutime=\"%g\" ", tms.tms_cutime * clockRes);
352        Tcl_DStringAppend(&ds, buf, -1);
353        sprintf(buf, "cstime=\"%g\" ", tms.tms_cstime * clockRes);
354        Tcl_DStringAppend(&ds, buf, -1);
355    }
356    Tcl_DStringAppend(&ds, "/>\n", -1);
357
358    {
359        int f;
360        ssize_t length;
361        int result;
362
363#define STATSDIR        "/var/tmp/visservers"
364#define STATSFILE       STATSDIR "/" "data.xml"
365        if (access(STATSDIR, X_OK) != 0) {
366            mkdir(STATSDIR, 0770);
367        }
368        length = Tcl_DStringLength(&ds);
369        f = open(STATSFILE, O_APPEND | O_CREAT | O_WRONLY, 0600);
370        result = FALSE;
371        if (f < 0) {
372            goto error;
373        }
374        if (write(f, Tcl_DStringValue(&ds), length) != length) {
375            goto error;
376        }
377        result = TRUE;
378    error:
379        if (f >= 0) {
380            close(f);
381        }
382        Tcl_DStringFree(&ds);
383        return result;
384    }
385}
386#endif
387
388static void
389DoExit(int code)
390{
391    if (NanoVis::debug_flag) {
392        fprintf(stderr, "in DoExit\n");
393    }
394    removeAllData();
395    NvExit();
396#if KEEPSTATS
397    WriteStats("nanovis", code);
398#endif
399    exit(code);
400}
401
402//report errors related to CG shaders
403void
404cgErrorCallback(void)
405{
406    CGerror lastError = cgGetError();
407    if(lastError) {
408        const char *listing = cgGetLastListing(g_context);
409        Trace("\n---------------------------------------------------\n");
410        Trace("%s\n\n", cgGetErrorString(lastError));
411        Trace("%s\n", listing);
412        Trace("-----------------------------------------------------\n");
413        Trace("Cg error, exiting...\n");
414        cgDestroyContext(g_context);
415        DoExit(-1);
416    }
417}
418
419
420CGprogram
421LoadCgSourceProgram(CGcontext context, const char *fileName, CGprofile profile,
422                    const char *entryPoint)
423{
424    const char *path = R2FilePath::getInstance()->getPath(fileName);
425    if (path == NULL) {
426        fprintf(stderr, "can't find program \"%s\"\n", fileName);
427        Trace("can't find program \"%s\"\n", fileName);
428    }
429    Trace("cg program compiling: %s\n", path);
430    fflush(stdout);
431    CGprogram program;
432    program = cgCreateProgramFromFile(context, CG_SOURCE, path, profile,
433                                      entryPoint, NULL);
434    cgGLLoadProgram(program);
435    CGerror LastError = cgGetError();
436    if (LastError) {
437        printf("Error message: %s\n", cgGetLastListing(context));
438        Trace("Error message: %s\n", cgGetLastListing(context));
439    }
440    Trace("successfully compiled program: %s\n", path);
441    delete [] path;
442    return program;
443}
444
445static int
446ExecuteCommand(Tcl_Interp *interp, Tcl_DString *dsPtr)
447{
448    struct timeval tv;
449    double start, finish;
450    int result;
451
452#ifndef notdef
453    if (NanoVis::debug_flag) {
454        fprintf(stderr, "in ExecuteCommand(%s)\n", Tcl_DStringValue(dsPtr));
455    }
456#endif
457    gettimeofday(&tv, NULL);
458    start = CVT2SECS(tv);
459
460    Trace("in ExecuteCommand(%s)\n", Tcl_DStringValue(dsPtr));
461#ifndef notdef
462    if (NanoVis::logfile != NULL) {
463        fprintf(NanoVis::logfile, "%s", Tcl_DStringValue(dsPtr));
464        fflush(NanoVis::logfile);
465    }
466#endif
467    if (NanoVis::recfile != NULL) {
468        fprintf(NanoVis::recfile, "%s", Tcl_DStringValue(dsPtr));
469        fflush(NanoVis::recfile);
470    }
471    result = Tcl_Eval(interp, Tcl_DStringValue(dsPtr));
472    Tcl_DStringSetLength(dsPtr, 0);
473
474    gettimeofday(&tv, NULL);
475    finish = CVT2SECS(tv);
476
477    stats.cmdTime += finish - start;
478    stats.nCommands++;
479#ifndef notdef
480    if (NanoVis::debug_flag) {
481        fprintf(stderr, "leaving ExecuteCommand status=%d\n", result);
482    }
483#endif
484    return result;
485}
486
487void
488NanoVis::pan(float dx, float dy)
489{
490    /* Move the camera and its target by equal amounts along the x and y
491     * axes. */
492    fprintf(stderr, "x=%f, y=%f\n", dx, dy);
493
494    cam->x(def_eye_x + dx);
495    cam->y(def_eye_y + dy);
496    fprintf(stderr, "set eye to %f %f\n", cam->x(), cam->y());
497
498    cam->xAim(def_target_x + dx);
499    cam->yAim(def_target_y + dy);
500    fprintf(stderr, "set aim to %f %f\n", cam->xAim(), cam->yAim());
501}
502
503
504/* Load a 3D volume
505 * index:       the index into the volume array, which stores pointers
506 *              to 3D volume instances
507 * data:        pointer to an array of floats.
508 * n_component: the number of scalars for each space point. All component
509 *              scalars for a point are placed consequtively in data array
510 *              width, height and depth: number of points in each dimension
511 */
512Volume *
513NanoVis::load_volume(const char *name, int width, int height, int depth,
514                     int n_component, float* data, double vmin, double vmax,
515                     double nzero_min)
516{
517    Tcl_HashEntry *hPtr;
518    hPtr = Tcl_FindHashEntry(&NanoVis::volumeTable, name);
519    if (hPtr != NULL) {
520        Volume *volPtr;
521        Trace("volume \"%s\" already exists", name);
522        volPtr = (Volume *)Tcl_GetHashValue(hPtr);
523        remove_volume(volPtr);
524    }
525    int isNew;
526    hPtr = Tcl_CreateHashEntry(&NanoVis::volumeTable, name, &isNew);
527    Volume* volPtr;
528    volPtr = new Volume(0.f, 0.f, 0.f, width, height, depth, 1., n_component,
529                data, vmin, vmax, nzero_min);
530    Tcl_SetHashValue(hPtr, volPtr);
531    volPtr->name(Tcl_GetHashKey(&NanoVis::volumeTable, hPtr));
532    return volPtr;
533}
534
535// Gets a colormap 1D texture by name.
536TransferFunction*
537NanoVis::get_transfunc(const char *name)
538{
539    Tcl_HashEntry *hPtr;
540
541    hPtr = Tcl_FindHashEntry(&tfTable, name);
542    if (hPtr == NULL) {
543        return NULL;
544    }
545    return (TransferFunction*)Tcl_GetHashValue(hPtr);
546}
547
548// Creates of updates a colormap 1D texture by name.
549TransferFunction*
550NanoVis::DefineTransferFunction(const char *name, size_t n, float *data)
551{
552    int isNew;
553    Tcl_HashEntry *hPtr;
554    TransferFunction *tfPtr;
555
556    hPtr = Tcl_CreateHashEntry(&tfTable, name, &isNew);
557    if (isNew) {
558        tfPtr = new TransferFunction(n, data);
559        tfPtr->name(Tcl_GetHashKey(&tfTable, hPtr));
560        Tcl_SetHashValue(hPtr, tfPtr);
561    } else {
562        /*
563         * You can't delete the transfer function because many
564         * objects may be holding its pointer.  We must update it.
565         */
566        tfPtr = (TransferFunction *)Tcl_GetHashValue(hPtr);
567        tfPtr->update(n, data);
568    }
569    return tfPtr;
570}
571
572int
573NanoVis::render_legend(TransferFunction *tf, double min, double max,
574                       int width, int height, const char* volArg)
575{
576    if (debug_flag) {
577        fprintf(stderr, "in render_legend\n");
578    }
579    int old_width = win_width;
580    int old_height = win_height;
581
582    plane_render->set_screen_size(width, height);
583    resize_offscreen_buffer(width, height);
584
585    // generate data for the legend
586    float data[512];
587    for (int i=0; i < 256; i++) {
588        data[i] = data[i+256] = (float)(i/255.0);
589    }
590    plane[0] = new Texture2D(256, 2, GL_FLOAT, GL_LINEAR, 1, data);
591    int index = plane_render->add_plane(plane[0], tf);
592    plane_render->set_active_plane(index);
593
594    offscreen_buffer_capture();
595    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear screen
596    plane_render->render();
597
598    // INSOO
599    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, screen_buffer);
600    //glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, screen_buffer); // INSOO's
601
602    if (debug_flag) {
603        fprintf(stderr, "ppm legend image not written (debug mode)\n");
604    } else {
605        char prefix[200];
606        ssize_t nWritten;
607
608        sprintf(prefix, "nv>legend %s %g %g", volArg, min, max);
609        ppm_write(prefix);
610        nWritten = write(0, "\n", 1);
611        assert(nWritten == 1);
612    }
613    plane_render->remove_plane(index);
614    resize_offscreen_buffer(old_width, old_height);
615
616    if (debug_flag) {
617        fprintf(stderr, "leaving render_legend\n");
618    }
619    delete plane[0];
620    return TCL_OK;
621}
622
623//initialize frame buffer objects for offscreen rendering
624void
625NanoVis::init_offscreen_buffer()
626{
627    if (debug_flag) {
628        fprintf(stderr, "in init_offscreen_buffer\n");
629    }
630    // Initialize a fbo for final display.
631    glGenFramebuffersEXT(1, &final_fbo);
632   
633    glGenTextures(1, &final_color_tex);
634    glBindTexture(GL_TEXTURE_2D, final_color_tex);
635   
636    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
637    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
638#ifdef NV40
639    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, win_width, win_height, 0,
640                 GL_RGB, GL_INT, NULL);
641#else
642    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, win_width, win_height, 0,
643                 GL_RGB, GL_INT, NULL);
644#endif
645    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, final_fbo);
646    glGenRenderbuffersEXT(1, &final_depth_rb);
647    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, final_depth_rb);
648    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24,
649                             win_width, win_height);
650    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
651                              GL_TEXTURE_2D, final_color_tex, 0);
652    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
653                                 GL_RENDERBUFFER_EXT, final_depth_rb);
654
655    GLenum status;
656    if (!CheckFBO(&status)) {
657        PrintFBOStatus(status, "final_fbo");
658        DoExit(3);
659    }
660
661    // Check framebuffer completeness at the end of initialization.
662    //CHECK_FRAMEBUFFER_STATUS();
663   
664    //assert(glGetError()==0);
665    if (debug_flag) {
666        fprintf(stderr, "leaving init_offscreen_buffer\n");
667    }
668}
669
670
671//resize the offscreen buffer
672void
673NanoVis::resize_offscreen_buffer(int w, int h)
674{
675    Trace("in resize_offscreen_buffer(%d, %d)\n", w, h);
676    if ((w == win_width) && (h == win_height)) {
677        return;
678    }
679    if (debug_flag) {
680        fprintf(stderr, "in resize_offscreen_buffer(%d, %d)\n", w, h);
681    }
682
683    win_width = w;
684    win_height = h;
685   
686    if (fonts) {
687        fonts->resize(w, h);
688    }
689    //fprintf(stderr, "screen_buffer size: %d\n", sizeof(screen_buffer));
690    Trace("screen_buffer size: %d %d\n", w, h);
691   
692    if (screen_buffer != NULL) {
693        delete [] screen_buffer;
694        screen_buffer = NULL;
695    }
696   
697    screen_buffer = new unsigned char[4*win_width*win_height];
698    assert(screen_buffer != NULL);
699   
700    //delete the current render buffer resources
701    glDeleteTextures(1, &final_color_tex);
702    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, final_depth_rb);
703    glDeleteRenderbuffersEXT(1, &final_depth_rb);
704
705    if (debug_flag) {
706        fprintf(stderr, "before deleteframebuffers\n");
707    }
708    glDeleteFramebuffersEXT(1, &final_fbo);
709
710    if (debug_flag) {
711        fprintf(stderr, "reinitialize FBO\n");
712    }
713    //Reinitialize final fbo for final display
714    glGenFramebuffersEXT(1, &final_fbo);
715
716    glGenTextures(1, &final_color_tex);
717    glBindTexture(GL_TEXTURE_2D, final_color_tex);
718
719    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
720    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
721#ifdef NV40
722    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, win_width, win_height, 0,
723                 GL_RGB, GL_INT, NULL);
724#else
725    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, win_width, win_height, 0,
726                 GL_RGB, GL_INT, NULL);
727#endif
728    if (debug_flag) {
729        fprintf(stderr, "before bindframebuffer\n");
730    }
731    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, final_fbo);
732    if (debug_flag) {
733        fprintf(stderr, "after bindframebuffer\n");
734    }
735    glGenRenderbuffersEXT(1, &final_depth_rb);
736    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, final_depth_rb);
737    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24,
738                             win_width, win_height);
739    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
740                              GL_TEXTURE_2D, final_color_tex, 0);
741    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
742                                 GL_RENDERBUFFER_EXT, final_depth_rb);
743   
744    GLenum status;
745    if (!CheckFBO(&status)) {
746        PrintFBOStatus(status, "final_fbo");
747        DoExit(3);
748    }
749
750    //CHECK_FRAMEBUFFER_STATUS();
751    if (debug_flag) {
752        fprintf(stderr, "change camera\n");
753    }
754    //change the camera setting
755    cam->set_screen_size(0, 0, win_width, win_height);
756    plane_render->set_screen_size(win_width, win_height);
757
758    if (debug_flag) {
759        fprintf(stderr, "leaving resize_offscreen_buffer(%d, %d)\n", w, h);
760    }
761}
762
763/*
764 * FIXME: This routine is fairly expensive (60000 floating pt divides).
765 *      I've put an ifdef around the call to it so that the released
766 *      builds don't include it.  Define PROTOTYPE to 1 in config.h
767 *      to turn it back on.
768 */
769void
770make_test_2D_data()
771{
772    int w = 300;
773    int h = 200;
774    float* data = new float[w*h];
775
776    //procedurally make a gradient plane
777    for(int j=0; j<h; j++){
778        for(int i=0; i<w; i++){
779            data[w*j+i] = float(i)/float(w);
780        }
781    }
782    NanoVis::plane[0] = new Texture2D(w, h, GL_FLOAT, GL_LINEAR, 1, data);
783    delete[] data;
784}
785
786void NanoVis::initParticle()
787{
788    flowVisRenderer->initialize();
789    licRenderer->make_patterns();
790}
791
792void CgErrorCallback(void)
793{
794    CGerror lastError = cgGetError();
795
796    if(lastError) {
797        const char *listing = cgGetLastListing(g_context);
798        printf("\n---------------------------------------------------\n");
799        printf("%s\n\n", cgGetErrorString(lastError));
800        printf("%s\n", listing);
801        printf("-----------------------------------------------------\n");
802        printf("Cg error, exiting...\n");
803        cgDestroyContext(g_context);
804        fflush(stdout);
805        DoExit(-1);
806    }
807}
808
809void NanoVis::init(const char* path)
810{
811    // print system information
812    fprintf(stderr,
813            "-----------------------------------------------------------\n");
814    fprintf(stderr, "OpenGL driver: %s %s\n", glGetString(GL_VENDOR),
815            glGetString(GL_VERSION));
816    fprintf(stderr, "Graphics hardware: %s\n", glGetString(GL_RENDERER));
817    fprintf(stderr,
818            "-----------------------------------------------------------\n");
819    if (path == NULL) {
820        fprintf(stderr, "No path defined for shaders or resources\n");
821        fflush(stderr);
822        DoExit(1);
823    }
824    GLenum err = glewInit();
825    if (GLEW_OK != err) {
826        fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
827        getchar();
828        //assert(false);
829    }
830    fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
831
832    if (!R2FilePath::getInstance()->setPath(path)) {
833        fprintf(stderr, "can't set file path to %s\n", path);
834        fflush(stderr);
835        DoExit(1);
836    }
837   
838    NvInitCG();
839    NvShader::setErrorCallback(CgErrorCallback);
840   
841    fonts = new R2Fonts();
842    fonts->addFont("verdana", "verdana.fnt");
843    fonts->setFont("verdana");
844   
845    color_table_renderer = new NvColorTableRenderer();
846    color_table_renderer->setFonts(fonts);
847#ifndef NEW_FLOW_ENGINE
848    flowVisRenderer = new NvParticleRenderer(NMESH, NMESH, g_context);
849#else
850    flowVisRenderer = new NvFlowVisRenderer(NMESH, NMESH, g_context);
851#endif
852
853    NanoVis::velocityArrowsSlice = new VelocityArrowsSlice;
854
855    licRenderer = new NvLIC(NMESH, NPIX, NPIX, lic_axis,
856                            Vector3(lic_slice_x, lic_slice_y, lic_slice_z),
857                            g_context);
858
859    ImageLoaderFactory::getInstance()->addLoaderImpl("bmp", new BMPImageLoaderImpl());
860    grid = new Grid();
861    grid->setFont(fonts);
862
863#ifdef notdef
864    pointset_renderer = new PointSetRenderer();
865#endif
866}
867
868/*----------------------------------------------------*/
869void
870NanoVis::initGL(void)
871{
872    if (debug_flag) {
873        fprintf(stderr, "in initGL\n");
874    }
875    //buffer to store data read from the screen
876    if (screen_buffer) {
877        delete[] screen_buffer;
878        screen_buffer = NULL;
879    }
880    screen_buffer = new unsigned char[4*win_width*win_height];
881    assert(screen_buffer != NULL);
882
883    //create the camera with default setting
884    cam = new NvCamera(0, 0, win_width, win_height,
885                       def_eye_x, def_eye_y, def_eye_z,          /* location. */
886                       def_target_x, def_target_y, def_target_z, /* target. */
887                       def_rot_x, def_rot_y, def_rot_z);         /* angle. */
888
889    glEnable(GL_TEXTURE_2D);
890    glShadeModel(GL_FLAT);
891    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
892
893    glClearColor(0,0,0,1);
894    //glClearColor(0.7,0.7,0.7,1);
895    glClear(GL_COLOR_BUFFER_BIT);
896
897    //initialize lighting
898    GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
899    GLfloat mat_shininess[] = {30.0};
900    GLfloat white_light[] = {1.0, 1.0, 1.0, 1.0};
901    GLfloat green_light[] = {0.1, 0.5, 0.1, 1.0};
902
903    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
904    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
905    glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
906    glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);
907    glLightfv(GL_LIGHT1, GL_DIFFUSE, green_light);
908    glLightfv(GL_LIGHT1, GL_SPECULAR, white_light);
909
910    // init table of transfer functions
911    Tcl_InitHashTable(&tfTable, TCL_STRING_KEYS);
912
913    //check if performance query is supported
914    if(check_query_support()){
915        //create queries to count number of rendered pixels
916        perf = new PerfQuery();
917    }
918
919    init_offscreen_buffer();    //frame buffer object for offscreen rendering
920
921    //create volume renderer and add volumes to it
922    vol_renderer = new VolumeRenderer();
923
924    // create
925    renderContext = new graphics::RenderContext();
926   
927    //create an 2D plane renderer
928    plane_render = new PlaneRenderer(g_context, win_width, win_height);
929#if PROTOTYPE
930    make_test_2D_data();
931#endif  /* PROTOTYPE */
932    plane_render->add_plane(plane[0], get_transfunc("default"));
933
934    //assert(glGetError()==0);
935
936    if (debug_flag) {
937        fprintf(stderr, "leaving initGL\n");
938    }
939}
940
941#if DO_RLE
942char rle[512*512*3];
943int rle_size;
944
945short offsets[512*512*3];
946int offsets_size;
947
948void
949do_rle()
950{
951    int len = NanoVis::win_width*NanoVis::win_height*3;
952    rle_size = 0;
953    offsets_size = 0;
954
955    int i=0;
956    while(i<len){
957        if (NanoVis::screen_buffer[i] == 0) {
958            int pos = i+1;
959            while ( (pos<len) && (NanoVis::screen_buffer[pos] == 0)) {
960                pos++;
961            }
962            offsets[offsets_size++] = -(pos - i);
963            i = pos;
964        }
965
966        else {
967            int pos;
968            for (pos = i; (pos<len) && (NanoVis::screen_buffer[pos] != 0);pos++){
969                rle[rle_size++] = NanoVis::screen_buffer[pos];
970            }
971            offsets[offsets_size++] = (pos - i);
972            i = pos;
973        }
974
975    }
976}
977#endif
978
979// used internally to build up the BMP file header
980// Writes an integer value into the header data structure at pos
981static inline void
982bmp_header_add_int(unsigned char* header, int& pos, int data)
983{
984#ifdef WORDS_BIGENDIAN
985    header[pos++] = (data >> 24) & 0xFF;
986    header[pos++] = (data >> 16) & 0xFF;
987    header[pos++] = (data >> 8)  & 0xFF;
988    header[pos++] = (data)       & 0xFF;
989#else
990    header[pos++] = data & 0xff;
991    header[pos++] = (data >> 8) & 0xff;
992    header[pos++] = (data >> 16) & 0xff;
993    header[pos++] = (data >> 24) & 0xff;
994#endif
995}
996
997// INSOO
998// FOR DEBUGGING
999void
1000NanoVis::bmp_write_to_file(int frame_number, const char *directory_name)
1001{
1002    unsigned char header[SIZEOF_BMP_HEADER];
1003    int pos = 0;
1004    header[pos++] = 'B';
1005    header[pos++] = 'M';
1006
1007    // BE CAREFUL:  BMP files must have an even multiple of 4 bytes
1008    // on each scan line.  If need be, we add padding to each line.
1009    int pad = 0;
1010    if ((3*win_width) % 4 > 0) {
1011        pad = 4 - ((3*win_width) % 4);
1012    }
1013
1014    // file size in bytes
1015    int fsize = (3*win_width+pad)*win_height + SIZEOF_BMP_HEADER;
1016    bmp_header_add_int(header, pos, fsize);
1017
1018    // reserved value (must be 0)
1019    bmp_header_add_int(header, pos, 0);
1020
1021    // offset in bytes to start of bitmap data
1022    bmp_header_add_int(header, pos, SIZEOF_BMP_HEADER);
1023
1024    // size of the BITMAPINFOHEADER
1025    bmp_header_add_int(header, pos, 40);
1026
1027    // width of the image in pixels
1028    bmp_header_add_int(header, pos, win_width);
1029
1030    // height of the image in pixels
1031    bmp_header_add_int(header, pos, win_height);
1032
1033    // 1 plane + (24 bits/pixel << 16)
1034    bmp_header_add_int(header, pos, 1572865);
1035
1036    // no compression
1037    // size of image for compression
1038    bmp_header_add_int(header, pos, 0);
1039    bmp_header_add_int(header, pos, 0);
1040
1041    // x pixels per meter
1042    // y pixels per meter
1043    bmp_header_add_int(header, pos, 0);
1044    bmp_header_add_int(header, pos, 0);
1045
1046    // number of colors used (0 = compute from bits/pixel)
1047    // number of important colors (0 = all colors important)
1048    bmp_header_add_int(header, pos, 0);
1049    bmp_header_add_int(header, pos, 0);
1050
1051    // BE CAREFUL: BMP format wants BGR ordering for screen data
1052    unsigned char* scr = screen_buffer;
1053    for (int row=0; row < win_height; row++) {
1054        for (int col=0; col < win_width; col++) {
1055            unsigned char tmp = scr[2];
1056            scr[2] = scr[0];  // B
1057            scr[0] = tmp;     // R
1058            scr += 3;
1059        }
1060        scr += pad;  // skip over padding already in screen data
1061    }
1062
1063    FILE* f;
1064    char filename[100];
1065    if (frame_number >= 0) {
1066        if (directory_name)
1067            sprintf(filename, "%s/image%03d.bmp", directory_name, frame_number);
1068        else
1069            sprintf(filename, "/tmp/flow_animation/image%03d.bmp", frame_number);
1070
1071        fprintf(stderr, "Writing %s\n", filename);
1072        f = fopen(filename, "wb");
1073        if (f == 0) {
1074            Trace("cannot create file\n");
1075        }
1076    } else {
1077        f = fopen("/tmp/image.bmp", "wb");
1078        if (f == 0) {
1079            Trace("cannot create file\n");
1080        }
1081    }
1082    if (fwrite(header, SIZEOF_BMP_HEADER, 1, f) != 1) {
1083        Trace("can't write header: short write\n");
1084    }
1085    if (fwrite(screen_buffer, (3*win_width+pad)*win_height, 1, f) != 1) {
1086        Trace("can't write data: short write\n");
1087    }
1088    fclose(f);
1089}
1090
1091void
1092NanoVis::bmp_write(const char *prefix)
1093{
1094    unsigned char header[SIZEOF_BMP_HEADER];
1095    ssize_t nWritten;
1096    int pos = 0;
1097
1098    // BE CAREFUL:  BMP files must have an even multiple of 4 bytes
1099    // on each scan line.  If need be, we add padding to each line.
1100    int pad = 0;
1101    if ((3*win_width) % 4 > 0) {
1102        pad = 4 - ((3*win_width) % 4);
1103    }
1104    pad = 0;
1105    int fsize = (3*win_width+pad)*win_height + sizeof(header);
1106
1107    char string[200];
1108    sprintf(string, "%s %d\n", prefix, fsize);
1109    nWritten = write(0, string, strlen(string));
1110    assert(nWritten == (ssize_t)strlen(string));
1111    header[pos++] = 'B';
1112    header[pos++] = 'M';
1113
1114    // file size in bytes
1115    bmp_header_add_int(header, pos, fsize);
1116
1117    // reserved value (must be 0)
1118    bmp_header_add_int(header, pos, 0);
1119
1120    // offset in bytes to start of bitmap data
1121    bmp_header_add_int(header, pos, SIZEOF_BMP_HEADER);
1122
1123    // size of the BITMAPINFOHEADER
1124    bmp_header_add_int(header, pos, 40);
1125
1126    // width of the image in pixels
1127    bmp_header_add_int(header, pos, win_width);
1128
1129    // height of the image in pixels
1130    bmp_header_add_int(header, pos, win_height);
1131
1132    // 1 plane + (24 bits/pixel << 16)
1133    bmp_header_add_int(header, pos, 1572865);
1134
1135    // no compression
1136    // size of image for compression
1137    bmp_header_add_int(header, pos, 0);
1138    bmp_header_add_int(header, pos, 0);
1139
1140    // x pixels per meter
1141    // y pixels per meter
1142    bmp_header_add_int(header, pos, 0);
1143    bmp_header_add_int(header, pos, 0);
1144
1145    // number of colors used (0 = compute from bits/pixel)
1146    // number of important colors (0 = all colors important)
1147    bmp_header_add_int(header, pos, 0);
1148    bmp_header_add_int(header, pos, 0);
1149
1150    // BE CAREFUL: BMP format wants BGR ordering for screen data
1151    unsigned char* scr = screen_buffer;
1152    for (int row=0; row < win_height; row++) {
1153        for (int col=0; col < win_width; col++) {
1154            unsigned char tmp = scr[2];
1155            scr[2] = scr[0];  // B
1156            scr[0] = tmp;     // R
1157            scr += 3;
1158        }
1159        scr += pad;  // skip over padding already in screen data
1160    }
1161
1162    nWritten = write(0, header, SIZEOF_BMP_HEADER);
1163    assert(nWritten == SIZEOF_BMP_HEADER);
1164    nWritten = write(0, screen_buffer, (3*win_width+pad)*win_height);
1165    assert(nWritten == (3*win_width+pad)*win_height);
1166    stats.nFrames++;
1167    stats.nBytes += (3*win_width+pad)*win_height;
1168}
1169
1170/*
1171 * ppm_write --
1172 *
1173 *  Writes the screen image as PPM binary data to the nanovisviewer
1174 *  client.  The PPM binary format is very simple.
1175 *
1176 *      P6 w h 255\n
1177 *      3-byte RGB pixel data.
1178 *
1179 *  The nanovisviewer client (using the TkImg library) will do less work
1180 *  to unpack this format, as opposed to BMP or PNG.  (This doesn't
1181 *  eliminate the need to look into DXT compression performed on the GPU).
1182 *
1183 *      Note that currently the image data from the screen is both row-padded
1184 *      and the scan lines are reversed.  This routine could be made even
1185 *      simpler (faster) if the screen buffer is an array of packed 3-bytes
1186 *      per pixels (no padding) and where the origin is the top-left corner.
1187 */
1188void
1189NanoVis::ppm_write(const char *prefix)
1190{
1191#define PPM_MAXVAL 255
1192    char header[200];
1193
1194    // Generate the PPM binary file header
1195    sprintf(header, "P6 %d %d %d\n", win_width, win_height, PPM_MAXVAL);
1196
1197    size_t header_length = strlen(header);
1198    size_t data_length = win_width * win_height * 3;
1199
1200    char command[200];
1201    sprintf(command, "%s %lu\n", prefix,
1202            (unsigned long)header_length + data_length);
1203
1204    size_t wordsPerRow = (win_width * 24 + 31) / 32;
1205    size_t bytesPerRow = wordsPerRow * 4;
1206    size_t rowLength = win_width * 3;
1207    size_t nRecs = win_height + 2;
1208
1209    struct iovec *iov;
1210    iov = (struct iovec *)malloc(sizeof(struct iovec) * nRecs);
1211
1212    // Write the nanovisviewer command, then the image header and data.
1213    // Command
1214    iov[0].iov_base = command;
1215    iov[0].iov_len = strlen(command);
1216    // Header of image data
1217    iov[1].iov_base = header;
1218    iov[1].iov_len = header_length;
1219    // Image data.
1220    int y;
1221    unsigned char *srcRowPtr = screen_buffer;
1222    for (y = win_height + 1; y >= 2; y--) {
1223        iov[y].iov_base = srcRowPtr;
1224        iov[y].iov_len = rowLength;
1225        srcRowPtr += bytesPerRow;
1226    }
1227    if (writev(0, iov, nRecs) < 0) {
1228        fprintf(stderr, "write failed: %s\n", strerror(errno));
1229    }
1230    free(iov);
1231    stats.nFrames++;
1232    stats.nBytes += (bytesPerRow * win_height);
1233}
1234
1235void
1236NanoVis::sendDataToClient(const char *command, const char *data, size_t dlen)
1237{
1238    /*
1239      char header[200];
1240
1241      // Generate the PPM binary file header
1242      sprintf(header, "P6 %d %d %d\n", win_width, win_height, PPM_MAXVAL);
1243
1244      size_t header_length = strlen(header);
1245      size_t data_length = win_width * win_height * 3;
1246
1247      char command[200];
1248      sprintf(command, "%s %lu\n", prefix,
1249      (unsigned long)header_length + data_length);
1250    */
1251
1252    //    size_t wordsPerRow = (win_width * 24 + 31) / 32;
1253    //    size_t bytesPerRow = wordsPerRow * 4;
1254    //    size_t rowLength = win_width * 3;
1255    size_t nRecs = 2;
1256
1257    struct iovec *iov;
1258    iov = (struct iovec *)malloc(sizeof(struct iovec) * nRecs);
1259
1260    // Write the nanovisviewer command, then the image header and data.
1261    // Command
1262    // FIXME: shouldn't have to cast this
1263    iov[0].iov_base = (char *)command;
1264    iov[0].iov_len = strlen(command);
1265    // Data
1266    // FIXME: shouldn't have to cast this
1267    iov[1].iov_base = (char *)data;
1268    iov[1].iov_len = dlen;
1269    if (writev(0, iov, nRecs) < 0) {
1270        fprintf(stderr, "write failed: %s\n", strerror(errno));
1271    }
1272    free(iov);
1273    // stats.nFrames++;
1274    // stats.nBytes += (bytesPerRow * win_height);
1275}
1276
1277
1278/*----------------------------------------------------*/
1279void
1280NanoVis::idle()
1281{
1282    if (debug_flag) {
1283        fprintf(stderr, "in idle()\n");
1284    }
1285    glutSetWindow(render_window);
1286
1287#ifdef XINETD
1288    xinetd_listen();
1289#else
1290    glutPostRedisplay();
1291#endif
1292    if (debug_flag) {
1293        fprintf(stderr, "leaving idle()\n");
1294    }
1295}
1296
1297void
1298NanoVis::display_offscreen_buffer()
1299{
1300    if (debug_flag) {
1301        fprintf(stderr, "in display_offscreen_buffer\n");
1302    }
1303    glEnable(GL_TEXTURE_2D);
1304    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1305    glBindTexture(GL_TEXTURE_2D, final_color_tex);
1306
1307    glViewport(0, 0, win_width, win_height);
1308    glMatrixMode(GL_PROJECTION);
1309    glLoadIdentity();
1310    gluOrtho2D(0, win_width, 0, win_height);
1311    glMatrixMode(GL_MODELVIEW);
1312    glLoadIdentity();
1313
1314    glColor3f(1.,1.,1.);                //MUST HAVE THIS LINE!!!
1315    glBegin(GL_QUADS);
1316    {
1317        glTexCoord2f(0, 0); glVertex2f(0, 0);
1318        glTexCoord2f(1, 0); glVertex2f(win_width, 0);
1319        glTexCoord2f(1, 1); glVertex2f(win_width, win_height);
1320        glTexCoord2f(0, 1); glVertex2f(0, win_height);
1321    }
1322    glEnd();
1323    if (debug_flag) {
1324        fprintf(stderr, "leaving display_offscreen_buffer\n");
1325    }
1326}
1327
1328
1329
1330#if 0
1331//oddeven sort on GPU
1332void
1333sortstep()
1334{
1335    // perform one step of the current sorting algorithm
1336
1337#ifdef notdef
1338    // swap buffers
1339    int sourceBuffer = targetBuffer;
1340    targetBuffer = (targetBuffer+1)%2;
1341    int pstage = (1<<stage);
1342    int ppass  = (1<<pass);
1343    int activeBitonicShader = 0;
1344
1345#ifdef _WIN32
1346    buffer->BindBuffer(wglTargets[sourceBuffer]);
1347#else
1348    buffer->BindBuffer(glTargets[sourceBuffer]);
1349#endif
1350    if (buffer->IsDoubleBuffered()) glDrawBuffer(glTargets[targetBuffer]);
1351#endif
1352
1353    checkGLError("after db");
1354
1355    int pstage = (1<<stage);
1356    int ppass  = (1<<pass);
1357    //int activeBitonicShader = 0;
1358
1359    // switch on correct sorting shader
1360    oddevenMergeSort.bind();
1361    glUniform3fARB(oddevenMergeSort.getUniformLocation("Param1"), float(pstage+pstage),
1362                   float(ppass%pstage), float((pstage+pstage)-(ppass%pstage)-1));
1363    glUniform3fARB(oddevenMergeSort.getUniformLocation("Param2"),
1364                   float(psys_width), float(psys_height), float(ppass));
1365    glUniform1iARB(oddevenMergeSort.getUniformLocation("Data"), 0);
1366    staticdebugmsg("sort","stage "<<pstage<<" pass "<<ppass);
1367
1368    // This clear is not necessary for sort to function. But if we are in
1369    // interactive mode unused parts of the texture that are visible will look
1370    // bad.
1371#ifdef notdef
1372    if (!perfTest) glClear(GL_COLOR_BUFFER_BIT);
1373
1374    buffer->Bind();
1375    buffer->EnableTextureTarget();
1376#endif
1377
1378    // Initiate the sorting step on the GPU a full-screen quad
1379    glBegin(GL_QUADS);
1380    {
1381#ifdef notdef
1382        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,0.0f,0.0f,1.0f);
1383        glVertex2f(-1.0f,-1.0f);
1384        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),0.0f,1.0f,1.0f);
1385        glVertex2f(1.0f,-1.0f);
1386        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),float(psys_height),1.0f,0.0f);
1387        glVertex2f(1.0f,1.0f);
1388        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,float(psys_height),0.0f,0.0f);
1389        glVertex2f(-1.0f,1.0f);
1390#endif
1391        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,0.0f,0.0f,1.0f);
1392        glVertex2f(0.,0.);
1393        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),0.0f,1.0f,1.0f);
1394        glVertex2f(float(psys_width), 0.);
1395        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),float(psys_height),1.0f,0.0f);
1396        glVertex2f(float(psys_width), float(psys_height));
1397        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,float(psys_height),0.0f,0.0f);
1398        glVertex2f(0., float(psys_height));
1399    }
1400    glEnd();
1401
1402    // switch off sorting shader
1403    oddevenMergeSort.release();
1404
1405    //buffer->DisableTextureTarget();
1406
1407    //assert(glGetError()==0);
1408}
1409#endif
1410
1411
1412void
1413draw_3d_axis()
1414{
1415    glDisable(GL_TEXTURE_2D);
1416    glEnable(GL_DEPTH_TEST);
1417
1418    //draw axes
1419    GLUquadric *obj;
1420
1421    obj = gluNewQuadric();
1422
1423    glDepthFunc(GL_LESS);
1424    glEnable(GL_COLOR_MATERIAL);
1425    glEnable(GL_DEPTH_TEST);
1426    glDisable(GL_BLEND);
1427
1428    int segments = 50;
1429
1430    glColor3f(0.8, 0.8, 0.8);
1431    glPushMatrix();
1432    glTranslatef(0.4, 0., 0.);
1433    glRotatef(90, 1, 0, 0);
1434    glRotatef(180, 0, 1, 0);
1435    glScalef(0.0005, 0.0005, 0.0005);
1436    glutStrokeCharacter(GLUT_STROKE_ROMAN, 'x');
1437    glPopMatrix();
1438
1439    glPushMatrix();
1440    glTranslatef(0., 0.4, 0.);
1441    glRotatef(90, 1, 0, 0);
1442    glRotatef(180, 0, 1, 0);
1443    glScalef(0.0005, 0.0005, 0.0005);
1444    glutStrokeCharacter(GLUT_STROKE_ROMAN, 'y');
1445    glPopMatrix();
1446
1447    glPushMatrix();
1448    glTranslatef(0., 0., 0.4);
1449    glRotatef(90, 1, 0, 0);
1450    glRotatef(180, 0, 1, 0);
1451    glScalef(0.0005, 0.0005, 0.0005);
1452    glutStrokeCharacter(GLUT_STROKE_ROMAN, 'z');
1453    glPopMatrix();
1454
1455    glEnable(GL_LIGHTING);
1456    glEnable(GL_LIGHT0);
1457
1458    //glColor3f(0.2, 0.2, 0.8);
1459    glPushMatrix();
1460    glutSolidSphere(0.02, segments, segments );
1461    glPopMatrix();
1462
1463    glPushMatrix();
1464    glRotatef(-90, 1, 0, 0);
1465    gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments);
1466    glPopMatrix();
1467
1468    glPushMatrix();
1469    glTranslatef(0., 0.3, 0.);
1470    glRotatef(-90, 1, 0, 0);
1471    gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments);
1472    glPopMatrix();
1473
1474    glPushMatrix();
1475    glRotatef(90, 0, 1, 0);
1476    gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments);
1477    glPopMatrix();
1478
1479    glPushMatrix();
1480    glTranslatef(0.3, 0., 0.);
1481    glRotatef(90, 0, 1, 0);
1482    gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments);
1483    glPopMatrix();
1484
1485    glPushMatrix();
1486    gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments);
1487    glPopMatrix();
1488
1489    glPushMatrix();
1490    glTranslatef(0., 0., 0.3);
1491    gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments);
1492    glPopMatrix();
1493
1494    glDisable(GL_LIGHTING);
1495    glDisable(GL_DEPTH_TEST);
1496    gluDeleteQuadric(obj);
1497
1498    glEnable(GL_TEXTURE_2D);
1499    glDisable(GL_DEPTH_TEST);
1500}
1501
1502void NanoVis::update()
1503{
1504    if (vol_renderer->_volumeInterpolator->is_started()) {
1505        struct timeval clock;
1506        gettimeofday(&clock, NULL);
1507        double elapsed_time;
1508
1509        elapsed_time = clock.tv_sec + clock.tv_usec/1000000.0 -
1510            vol_renderer->_volumeInterpolator->getStartTime();
1511
1512        Trace("%lf %lf\n", elapsed_time, vol_renderer->_volumeInterpolator->getInterval());
1513        float fraction;
1514        float f;
1515
1516        f = fmod((float) elapsed_time, (float)vol_renderer->_volumeInterpolator->getInterval());
1517        if (f == 0.0) {
1518            fraction = 0.0f;
1519        } else {
1520            fraction = f / vol_renderer->_volumeInterpolator->getInterval();
1521        }
1522        Trace("fraction : %f\n", fraction);
1523        vol_renderer->_volumeInterpolator->update(fraction);
1524    }
1525}
1526
1527void
1528NanoVis::SetVolumeRanges()
1529{
1530    double xMin, xMax, yMin, yMax, zMin, zMax, wMin, wMax;
1531
1532    if (debug_flag) {
1533        fprintf(stderr, "in SetVolumeRanges\n");
1534    }
1535    xMin = yMin = zMin = wMin = FLT_MAX;
1536    xMax = yMax = zMax = wMax = -FLT_MAX;
1537    Tcl_HashEntry *hPtr;
1538    Tcl_HashSearch iter;
1539    for (hPtr = Tcl_FirstHashEntry(&volumeTable, &iter); hPtr != NULL;
1540         hPtr = Tcl_NextHashEntry(&iter)) {
1541        Volume *volPtr;
1542
1543        volPtr = (Volume *)Tcl_GetHashValue(hPtr);
1544        if (xMin > volPtr->xAxis.min()) {
1545            xMin = volPtr->xAxis.min();
1546        }
1547        if (xMax < volPtr->xAxis.max()) {
1548            xMax = volPtr->xAxis.max();
1549        }
1550        if (yMin > volPtr->yAxis.min()) {
1551            yMin = volPtr->yAxis.min();
1552        }
1553        if (yMax < volPtr->yAxis.max()) {
1554            yMax = volPtr->yAxis.max();
1555        }
1556        if (zMin > volPtr->zAxis.min()) {
1557            zMin = volPtr->zAxis.min();
1558        }
1559        if (zMax < volPtr->zAxis.max()) {
1560            zMax = volPtr->zAxis.max();
1561        }
1562        if (wMin > volPtr->wAxis.min()) {
1563            wMin = volPtr->wAxis.min();
1564        }
1565        if (wMax < volPtr->wAxis.max()) {
1566            wMax = volPtr->wAxis.max();
1567        }
1568    }
1569    if ((xMin < DBL_MAX) && (xMax > -DBL_MAX)) {
1570        grid->xAxis.SetScale(xMin, xMax);
1571    }
1572    if ((yMin < DBL_MAX) && (yMax > -DBL_MAX)) {
1573        grid->yAxis.SetScale(yMin, yMax);
1574    }
1575    if ((zMin < DBL_MAX) && (zMax > -DBL_MAX)) {
1576        grid->zAxis.SetScale(zMin, zMax);
1577    }
1578    if ((wMin < DBL_MAX) && (wMax > -DBL_MAX)) {
1579        Volume::valueMin = wMin;
1580        Volume::valueMax = wMax;
1581    }
1582    Volume::update_pending = false;
1583    if (debug_flag) {
1584        fprintf(stderr, "leaving SetVolumeRanges\n");
1585    }
1586}
1587
1588void
1589NanoVis::SetHeightmapRanges()
1590{
1591    double xMin, xMax, yMin, yMax, zMin, zMax, wMin, wMax;
1592
1593    if (debug_flag) {
1594        fprintf(stderr, "in SetHeightmapRanges\n");
1595    }
1596    xMin = yMin = zMin = wMin = FLT_MAX;
1597    xMax = yMax = zMax = wMax = -FLT_MAX;
1598    Tcl_HashEntry *hPtr;
1599    Tcl_HashSearch iter;
1600    for (hPtr = Tcl_FirstHashEntry(&heightmapTable, &iter); hPtr != NULL;
1601         hPtr = Tcl_NextHashEntry(&iter)) {
1602        HeightMap *hmPtr;
1603        hmPtr = (HeightMap *)Tcl_GetHashValue(hPtr);
1604        if (xMin > hmPtr->xAxis.min()) {
1605            xMin = hmPtr->xAxis.min();
1606        }
1607        if (xMax < hmPtr->xAxis.max()) {
1608            xMax = hmPtr->xAxis.max();
1609        }
1610        if (yMin > hmPtr->yAxis.min()) {
1611            yMin = hmPtr->yAxis.min();
1612        }
1613        if (yMax < hmPtr->yAxis.max()) {
1614            yMax = hmPtr->yAxis.max();
1615        }
1616        if (zMin > hmPtr->zAxis.min()) {
1617            zMin = hmPtr->zAxis.min();
1618        }
1619        if (zMax < hmPtr->zAxis.max()) {
1620            zMax = hmPtr->zAxis.max();
1621        }
1622        if (wMin > hmPtr->wAxis.min()) {
1623            wMin = hmPtr->wAxis.min();
1624        }
1625        if (wMax < hmPtr->wAxis.max()) {
1626            wMax = hmPtr->wAxis.max();
1627        }
1628    }
1629    if ((xMin < DBL_MAX) && (xMax > -DBL_MAX)) {
1630        grid->xAxis.SetScale(xMin, xMax);
1631    }
1632    if ((yMin < DBL_MAX) && (yMax > -DBL_MAX)) {
1633        grid->yAxis.SetScale(yMin, yMax);
1634    }
1635    if ((zMin < DBL_MAX) && (zMax > -DBL_MAX)) {
1636        grid->zAxis.SetScale(zMin, zMax);
1637    }
1638    if ((wMin < DBL_MAX) && (wMax > -DBL_MAX)) {
1639        HeightMap::valueMin = grid->yAxis.min();
1640        HeightMap::valueMax = grid->yAxis.max();
1641    }
1642    for (hPtr = Tcl_FirstHashEntry(&heightmapTable, &iter); hPtr != NULL;
1643         hPtr = Tcl_NextHashEntry(&iter)) {
1644        HeightMap *hmPtr;
1645        hmPtr = (HeightMap *)Tcl_GetHashValue(hPtr);
1646        hmPtr->MapToGrid(grid);
1647    }
1648    HeightMap::update_pending = false;
1649    if (debug_flag) {
1650        fprintf(stderr, "leaving SetHeightmapRanges\n");
1651    }
1652}
1653
1654/*----------------------------------------------------*/
1655void
1656NanoVis::display()
1657{
1658    if (debug_flag) {
1659        fprintf(stderr, "in display\n");
1660    }
1661#ifdef notdef
1662    if (flags & MAP_FLOWS) {
1663        xMin = yMin = zMin = wMin = FLT_MAX, magMin = DBL_MAX;
1664        xMax = yMax = zMax = wMax = -FLT_MAX, magMax = -DBL_MAX;
1665    }
1666#endif
1667    if (flags & MAP_FLOWS) {
1668        MapFlows();
1669        grid->xAxis.SetScale(xMin, xMax);
1670        grid->yAxis.SetScale(yMin, yMax);
1671        grid->zAxis.SetScale(zMin, zMax);
1672    }
1673    //assert(glGetError()==0);
1674    if (HeightMap::update_pending) {
1675        SetHeightmapRanges();
1676    }
1677    if (Volume::update_pending) {
1678        SetVolumeRanges();
1679    }
1680    if (debug_flag) {
1681        fprintf(stderr, "in display: glClear\n");
1682    }
1683    //start final rendering
1684    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear screen
1685
1686    if (volume_mode) {
1687        if (debug_flag) {
1688            fprintf(stderr, "in display: volume_mode\n");
1689        }
1690        //3D rendering mode
1691        // TBD..
1692        //glEnable(GL_TEXTURE_2D);
1693        glEnable(GL_DEPTH_TEST);
1694
1695        //camera setting activated
1696        cam->initialize();
1697
1698        //set up the orientation of items in the scene.
1699        glPushMatrix();
1700        switch (updir) {
1701        case 1:  // x
1702            glRotatef(90, 0, 0, 1);
1703            glRotatef(90, 1, 0, 0);
1704            break;
1705
1706        case 2:  // y
1707            // this is the default
1708            break;
1709
1710        case 3:  // z
1711            glRotatef(-90, 1, 0, 0);
1712            glRotatef(-90, 0, 0, 1);
1713            break;
1714
1715        case -1:  // -x
1716            glRotatef(-90, 0, 0, 1);
1717            break;
1718
1719        case -2:  // -y
1720            glRotatef(180, 0, 0, 1);
1721            glRotatef(-90, 0, 1, 0);
1722            break;
1723
1724        case -3:  // -z
1725            glRotatef(90, 1, 0, 0);
1726            break;
1727        }
1728
1729        // TBD : This will be removed after being sure that all the functions work well.
1730        //glPushMatrix();
1731
1732        //now render things in the scene
1733        if (axis_on) {
1734            draw_3d_axis();
1735        }
1736        if (grid->isVisible()) {
1737            grid->render();
1738        }
1739        if ((licRenderer != NULL) && (licRenderer->active())) {
1740            licRenderer->render();
1741        }
1742
1743        if ((velocityArrowsSlice != NULL) && (velocityArrowsSlice->enabled())) {
1744            velocityArrowsSlice->render();
1745        }
1746#ifdef notdef
1747        if ((flowVisRenderer != NULL) && (flowVisRenderer->active())) {
1748            flowVisRenderer->render();
1749        }
1750#endif
1751        if (flowTable.numEntries > 0) {
1752            RenderFlows();
1753        }
1754
1755        //soft_display_verts();
1756        //perf->enable();
1757        //perf->disable();
1758        //fprintf(stderr, "particle pixels: %d\n", perf->get_pixel_count());
1759        //perf->reset();
1760
1761        //perf->enable();
1762        vol_renderer->render_all();
1763        //perf->disable();
1764
1765        if (debug_flag) {
1766            fprintf(stderr, "in display: render heightmap\n");
1767        }
1768        Tcl_HashEntry *hPtr;
1769        Tcl_HashSearch iter;
1770        for (hPtr = Tcl_FirstHashEntry(&heightmapTable, &iter); hPtr != NULL;
1771             hPtr = Tcl_NextHashEntry(&iter)) {
1772            HeightMap *hmPtr;
1773            hmPtr = (HeightMap *)Tcl_GetHashValue(hPtr);
1774            if (hmPtr->isVisible()) {
1775                hmPtr->render(renderContext);
1776            }
1777        }
1778        glPopMatrix();
1779    } else {
1780        //2D rendering mode
1781        perf->enable();
1782        plane_render->render();
1783        perf->disable();
1784    }
1785    perf->reset();
1786    if (debug_flag) {
1787        fprintf(stderr, "leaving display\n");
1788    }
1789
1790
1791}
1792
1793#ifndef XINETD
1794void
1795NanoVis::mouse(int button, int state, int x, int y)
1796{
1797    if(button==GLUT_LEFT_BUTTON){
1798        if (state==GLUT_DOWN) {
1799            left_last_x = x;
1800            left_last_y = y;
1801            left_down = true;
1802            right_down = false;
1803        } else {
1804            left_down = false;
1805            right_down = false;
1806        }
1807    } else {
1808        //fprintf(stderr, "right mouse\n");
1809
1810        if(state==GLUT_DOWN){
1811            //fprintf(stderr, "right mouse down\n");
1812            right_last_x = x;
1813            right_last_y = y;
1814            left_down = false;
1815            right_down = true;
1816        } else {
1817            //fprintf(stderr, "right mouse up\n");
1818            left_down = false;
1819            right_down = false;
1820        }
1821    }
1822}
1823
1824void
1825NanoVis::update_rot(int delta_x, int delta_y)
1826{
1827    Vector3 angle;
1828
1829    angle = cam->rotate();
1830    angle.x += delta_x;
1831    angle.y += delta_y;
1832
1833    if (angle.x > 360.0) {
1834        angle.x -= 360.0;
1835    } else if(angle.x < -360.0) {
1836        angle.x += 360.0;
1837    }
1838    if (angle.y > 360.0) {
1839        angle.y -= 360.0;
1840    } else if(angle.y < -360.0) {
1841        angle.y += 360.0;
1842    }
1843    cam->rotate(angle);
1844}
1845
1846void
1847NanoVis::update_trans(int delta_x, int delta_y, int delta_z)
1848{
1849    cam->x(cam->x() + delta_x * 0.03);
1850    cam->y(cam->y() + delta_y * 0.03);
1851    cam->z(cam->z() + delta_z * 0.03);
1852}
1853
1854#ifdef NEW_FLOW_ENGINE
1855void addVectorField(const char* filename, const char* vf_name,
1856                    const char* plane_name1, const char* plane_name2,
1857                    const Vector4& color1, const Vector4& color2)
1858{
1859    Rappture::Outcome result;
1860    Rappture::Buffer buf;
1861
1862    buf.load(filename);
1863    int n = NanoVis::n_volumes;
1864    if (load_vector_stream2(result, n, buf.size(), buf.bytes())) {
1865        Volume *volPtr = NanoVis::volume[n];
1866        if (volPtr != NULL) {
1867            volPtr->set_n_slice(256-n);
1868            // volPtr->set_n_slice(512-n);
1869            volPtr->disable_cutplane(0);
1870            volPtr->disable_cutplane(1);
1871            volPtr->disable_cutplane(2);
1872            volPtr->transferFunction(NanoVis::get_transfunc("default"));
1873
1874            float dx0 = -0.5;
1875            float dy0 = -0.5*volPtr->height/volPtr->width;
1876            float dz0 = -0.5*volPtr->depth/volPtr->width;
1877            volPtr->move(Vector3(dx0, dy0, dz0));
1878            //volPtr->data(true);
1879            volPtr->data(false);
1880            NanoVis::flowVisRenderer->addVectorField(vf_name, volPtr,
1881                *(volPtr->get_location()),
1882                1.0f,
1883                volPtr->height / (float)volPtr->width,
1884                volPtr->depth  / (float)volPtr->width,
1885                1.0f);
1886            NanoVis::flowVisRenderer->activateVectorField(vf_name);
1887           
1888            //////////////////////////////////
1889            // ADD Particle Injection Plane1
1890            NanoVis::flowVisRenderer->addPlane(vf_name, plane_name1);
1891            NanoVis::flowVisRenderer->setPlaneAxis(vf_name, plane_name1, 0);
1892            NanoVis::flowVisRenderer->setPlanePos(vf_name, plane_name1, 0.9);
1893            NanoVis::flowVisRenderer->setParticleColor(vf_name, plane_name1, color1);
1894            // ADD Particle Injection Plane2
1895            NanoVis::flowVisRenderer->addPlane(vf_name, plane_name2);
1896            NanoVis::flowVisRenderer->setPlaneAxis(vf_name, plane_name2, 0);
1897            NanoVis::flowVisRenderer->setPlanePos(vf_name, plane_name2, 0.2);
1898            NanoVis::flowVisRenderer->setParticleColor(vf_name, plane_name2, color2);
1899            NanoVis::flowVisRenderer->initialize(vf_name);
1900           
1901            NanoVis::flowVisRenderer->activatePlane(vf_name, plane_name1);
1902            NanoVis::flowVisRenderer->activatePlane(vf_name, plane_name2);
1903           
1904            NanoVis::licRenderer->setVectorField(volPtr->id,
1905                                *(volPtr->get_location()),
1906                                1.0f / volPtr->aspect_ratio_width,
1907                                1.0f / volPtr->aspect_ratio_height,
1908                                1.0f / volPtr->aspect_ratio_depth,
1909                                volPtr->wAxis.max());
1910        }
1911    }
1912    //NanoVis::initParticle();
1913}
1914#endif
1915
1916void
1917NanoVis::keyboard(unsigned char key, int x, int y)
1918{
1919#ifdef EVENTLOG
1920    if(log){
1921        float param[3];
1922        param[0] = cam->x();
1923        param[1] = cam->y();
1924        param[2] = cam->z();
1925        Event* tmp = new Event(EVENT_MOVE, param, NvGetTimeInterval());
1926        tmp->write(event_log);
1927        delete tmp;
1928    }
1929#endif
1930
1931#ifdef NEW_FLOW_ENGINE
1932    switch (key) {
1933    case 'a' :
1934        {
1935            printf("flowvis active\n");
1936            char cmd[] = {
1937                "foreach flow [flow names] {\n"
1938                "    $flow configure -hide no -slice yes\n"
1939                "}\n"
1940            };
1941            Tcl_Eval(interp, cmd);
1942#ifdef notdef
1943            NanoVis::flowVisRenderer->active(true);
1944            NanoVis::licRenderer->active(true);
1945#endif
1946        }
1947        break;
1948    case 'd' :
1949        {
1950            printf("flowvis deactived\n");
1951            char cmd[] = {
1952                "foreach flow [flow names] {\n"
1953                "    $flow configure -hide yes -slice no\n"
1954                "}\n"
1955            };
1956#ifdef notdef
1957            NanoVis::flowVisRenderer->active(false);
1958            NanoVis::licRenderer->active(false);
1959#endif
1960        }
1961        break;
1962    case '1' :
1963        {
1964            printf("add vector field\n");
1965            char cmd[] = {
1966                "flow create flow1\n"
1967                "flow1 data file /home/iwoo/projects/nanovis/rappture/packages/vizservers/nanovis/data/flowvis_dx_files/jwire/J-wire-vec.dx 3\n"
1968                "flow1 particles add plane1 -color { 0 0 1 1 }\n"
1969                "flow1 particles add plane2 -color { 0 1 1 1 }\n"
1970            };
1971            Tcl_Eval(interp, cmd);
1972#ifdef notdef
1973            addVectorField("/home/iwoo/projects/nanovis/rappture/packages/vizservers/nanovis/data/flowvis_dx_files/jwire/J-wire-vec.dx",
1974                           "vf_name2", "plane_name1", "plane_name2", Vector4(0, 0, 1, 1), Vector4(0, 1, 1, 1));
1975#endif
1976        }
1977        break;
1978    case '2' :
1979        {
1980            char cmd[] = {
1981                "flow create flow2\n"
1982                "flow2 data file /home/iwoo/projects/nanovis/rappture/packages/vizservers/nanovis/data/flowvis_dx_files/3DWireLeakage/SiO2/SiO2.dx 3\n"
1983                "flow2 particles add plane1 -color { 1 0 0 1 }\n"
1984                "flow2 particles add plane2 -color { 1 1 0 1 }\n"
1985            };
1986            Tcl_Eval(interp, cmd);
1987            printf("add vector field\n");
1988            addVectorField("/home/iwoo/projects/nanovis/rappture/packages/vizservers/nanovis/data/flowvis_dx_files/3DWireLeakage/SiO2/SiO2.dx",
1989                           "vf_name1", "plane_name1", "plane_name2", Vector4(1, 0, 0, 1), Vector4(1, 1, 0, 1));
1990        }
1991        break;
1992    case '3':
1993        {
1994            printf("activate\n");
1995            char cmd[] = {
1996                "flow1 particles add plane2 -hide no\n"
1997            };
1998            Tcl_Eval(interp, cmd);
1999#ifdef notdef
2000            NanoVis::flowVisRenderer->activatePlane("vf_name1", "plane_name2");
2001#endif
2002        }
2003        break;
2004    case '4' :
2005        {
2006            printf("deactivate\n");
2007            char cmd[] = {
2008                "flow1 particles add plane2 -hide yes\n"
2009            };
2010            Tcl_Eval(interp, cmd);
2011#ifdef notdef
2012            NanoVis::flowVisRenderer->deactivatePlane("vf_name1", "plane_name2");
2013#endif
2014        }
2015        break;
2016    case '5' :
2017        {
2018            printf("vector field deleted (vf_name2)\n");
2019            char cmd[] = {
2020                "flow delete flow2\n"
2021            };
2022            Tcl_Eval(interp, cmd);
2023#ifdef notdef
2024            NanoVis::flowVisRenderer->removeVectorField("vf_name2");
2025#endif
2026        }
2027        break;
2028    case '6' :
2029        {
2030            printf("add device shape\n");
2031            char cmd[] = {
2032                "flow1 box add box1 -corner1 {0 0 0} -corner2 {30 3 3} -color { 1 0 0 1 }\n"
2033                "flow1 box add box2 -corner1 {0 -1 -1} -corner2 {30 4 4} -color { 0 1 0 1 }\n"
2034                "flow1 box add box3 -corner1 {10 -1.5 -1} -corner2 {20 4.5 4.5} -color { 0 0 1 1 }\n"
2035            };
2036            Tcl_Eval(interp, cmd);
2037#ifdef notdef
2038            NvDeviceShape shape;
2039            shape.min.set(0, 0, 0);
2040            shape.max.set(30, 3, 3);
2041            shape.color.set(1, 0, 0, 1);
2042            NanoVis::flowVisRenderer->addDeviceShape("vf_name1", "device1", shape);
2043            shape.min.set(0, -1, -1);
2044            shape.max.set(30, 4, 4);
2045            shape.color.set(0, 1, 0, 1);
2046            NanoVis::flowVisRenderer->addDeviceShape("vf_name1", "device2", shape);
2047            shape.min.set(10, -1.5, -1);
2048            shape.max.set(20, 4.5, 4.5);
2049            shape.color.set(0, 0, 1, 1);
2050            NanoVis::flowVisRenderer->addDeviceShape("vf_name1", "device3", shape);
2051            NanoVis::flowVisRenderer->activateDeviceShape("vf_name1");
2052#endif
2053        }
2054        break;
2055    case '7' :
2056        {
2057            printf("hide shape \n");
2058            char cmd[] = {
2059                "flow1 box configure box1 -hide yes\n"
2060            };
2061            Tcl_Eval(interp, cmd);
2062#ifdef notdef
2063            NanoVis::flowVisRenderer->deactivateDeviceShape("vf_name1");
2064#endif
2065        }
2066        break;
2067    case '8' :
2068        {
2069            printf("show shape\n");
2070            char cmd[] = {
2071                "flow1 box configure box1 -hide no\n"
2072            };
2073            Tcl_Eval(interp, cmd);
2074#ifdef notdef
2075            NanoVis::flowVisRenderer->activateDeviceShape("vf_name1");
2076#endif
2077        }
2078        break;
2079    case '9' :
2080        {
2081            printf("show a shape \n");
2082            char cmd[] = {
2083                "flow1 box configure box3 -hide no\n"
2084            };
2085            Tcl_Eval(interp, cmd);
2086#ifdef notdef
2087            NanoVis::flowVisRenderer->activateDeviceShape("vf_name1", "device3");
2088#endif
2089        }
2090        break;
2091    case '0' :
2092        {
2093            printf("delete a shape \n");
2094            char cmd[] = {
2095                "flow1 box delete box3\n"
2096            };
2097            Tcl_Eval(interp, cmd);
2098#ifdef notdef
2099            NanoVis::flowVisRenderer->deactivateDeviceShape("vf_name1", "device3");
2100#endif
2101        }
2102        break;
2103    case 'r' :
2104        {
2105            printf("reset \n");
2106            char cmd[] = {
2107                "flow reset\n"
2108            };
2109            Tcl_Eval(interp, cmd);
2110#ifdef notdef
2111            NanoVis::flowVisRenderer->reset();
2112            NanoVis::licRenderer->reset();
2113#endif
2114        }
2115        break;
2116    }
2117#endif
2118}
2119
2120void
2121NanoVis::motion(int x, int y)
2122{
2123    int old_x, old_y;
2124
2125    if(left_down){
2126        old_x = left_last_x;
2127        old_y = left_last_y;
2128    } else if(right_down){
2129        old_x = right_last_x;
2130        old_y = right_last_y;
2131    }
2132
2133    int delta_x = x - old_x;
2134    int delta_y = y - old_y;
2135
2136    //more coarse event handling
2137    //if(abs(delta_x)<10 && abs(delta_y)<10)
2138    //return;
2139
2140    if(left_down){
2141        left_last_x = x;
2142        left_last_y = y;
2143
2144        update_rot(-delta_y, -delta_x);
2145    } else if (right_down){
2146        //fprintf(stderr, "right mouse motion (%d,%d)\n", x, y);
2147
2148        right_last_x = x;
2149        right_last_y = y;
2150
2151        update_trans(0, 0, delta_x);
2152    }
2153
2154#ifdef EVENTLOG
2155    Vector3 angle = cam->rotate();
2156    Event* tmp = new Event(EVENT_ROTATE, &angle, NvGetTimeInterval());
2157    tmp->write(event_log);
2158    delete tmp;
2159#endif
2160    glutPostRedisplay();
2161}
2162
2163#endif /*XINETD*/
2164
2165void
2166NanoVis::render()
2167{
2168
2169#ifdef notdef
2170    if ((NanoVis::licRenderer != NULL) && (NanoVis::licRenderer->active())) {
2171        NanoVis::licRenderer->convolve();
2172    }
2173#else
2174    if (NanoVis::licRenderer != NULL) {
2175        NanoVis::licRenderer->convolve();
2176    }
2177#endif
2178
2179#ifdef notdef
2180    if ((NanoVis::flowVisRenderer != NULL) && (NanoVis::flowVisRenderer->active())) {
2181        NanoVis::flowVisRenderer->advect();
2182    }
2183#endif
2184    NanoVis::update();
2185    display();
2186    glutSwapBuffers();
2187}
2188
2189void
2190NanoVis::resize(int x, int y)
2191{
2192    glViewport(0, 0, x, y);
2193}
2194
2195void
2196NanoVis::xinetd_listen(void)
2197{
2198    if (debug_flag) {
2199        fprintf(stderr, "in xinetd_listen\n");
2200    }
2201    int flags = fcntl(0, F_GETFL, 0);
2202    fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
2203
2204    int status = TCL_OK;
2205
2206    //  Read and execute as many commands as we can from stdin...
2207
2208    bool isComplete = false;
2209    while ((!feof(NanoVis::stdin)) && (status == TCL_OK)) {
2210        //
2211        //  Read the next command from the buffer.  First time through we
2212        //  block here and wait if necessary until a command comes in.
2213        //
2214        //  BE CAREFUL: Read only one command, up to a newline.  The "volume
2215        //  data follows" command needs to be able to read the data
2216        //  immediately following the command, and we shouldn't consume it
2217        //  here.
2218        //
2219        if (debug_flag) {
2220            fprintf(stderr, "in xinetd_listen: check eof %d\n",
2221                    feof(NanoVis::stdin));
2222        }
2223        while (!feof(NanoVis::stdin)) {
2224            int c = fgetc(NanoVis::stdin);
2225            char ch;
2226            if (c <= 0) {
2227                if (errno == EWOULDBLOCK) {
2228                    break;
2229                }
2230                DoExit(100);
2231            }
2232            ch = (char)c;
2233            Tcl_DStringAppend(&cmdbuffer, &ch, 1);
2234            if (ch == '\n') {
2235                isComplete = Tcl_CommandComplete(Tcl_DStringValue(&cmdbuffer));
2236                if (isComplete) {
2237                    break;
2238                }
2239            }
2240        }
2241        // no command? then we're done for now
2242        if (Tcl_DStringLength(&cmdbuffer) == 0) {
2243            break;
2244        }
2245        if (isComplete) {
2246            // back to original flags during command evaluation...
2247            fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
2248            status = ExecuteCommand(interp, &cmdbuffer);
2249            // non-blocking for next read -- we might not get anything
2250            fcntl(0, F_SETFL, flags | O_NONBLOCK);
2251            isComplete = false;
2252        }
2253    }
2254    fcntl(0, F_SETFL, flags);
2255
2256    if (status != TCL_OK) {
2257        const char *string;
2258        int nBytes;
2259
2260        string = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
2261        Trace("errorInfo=(%s)\n", string);
2262        nBytes = strlen(string);
2263        struct iovec iov[3];
2264        iov[0].iov_base = (char *)"NanoVis Server Error: ";
2265        iov[0].iov_len = strlen((char *)iov[0].iov_base);
2266        iov[1].iov_base = (char *)string;
2267        iov[1].iov_len = nBytes;
2268        iov[2].iov_len = 1;
2269        iov[2].iov_base = (char *)'\n';
2270        if (writev(0, iov, 3) < 0) {
2271            fprintf(stderr, "write failed: %s\n", strerror(errno));
2272        }
2273        if (debug_flag) {
2274            fprintf(stderr, "leaving xinetd_listen\n");
2275        }
2276        return;
2277    }
2278
2279    NanoVis::update();
2280
2281    NanoVis::offscreen_buffer_capture();  //enable offscreen render
2282
2283    NanoVis::display();
2284
2285    // INSOO
2286#ifdef XINETD
2287    NanoVis::read_screen();
2288    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
2289#else
2290    NanoVis::display_offscreen_buffer(); //display the final rendering on screen
2291    NanoVis::read_screen();
2292    glutSwapBuffers();
2293#endif
2294
2295#if DO_RLE
2296    do_rle();
2297    int sizes[2] = {  offsets_size*sizeof(offsets[0]), rle_size };
2298    fprintf(stderr, "Writing %d,%d\n", sizes[0], sizes[1]); fflush(stderr);
2299    write(0, &sizes, sizeof(sizes));
2300    write(0, offsets, offsets_size*sizeof(offsets[0]));
2301    write(0, rle, rle_size);    //unsigned byte
2302#else
2303    if (debug_flag) {
2304        fprintf(stderr, "ppm image not written (debug mode)\n");
2305        bmp_write_to_file(1, "/tmp");
2306    } else {
2307        NanoVis::ppm_write("\nnv>image -type image -bytes");
2308    }
2309#endif
2310    if (feof(NanoVis::stdin)) {
2311        DoExit(90);
2312    }
2313    if (debug_flag) {
2314        fprintf(stderr, "leaving xinetd_listen\n");
2315    }
2316}
2317
2318
2319/*----------------------------------------------------*/
2320int
2321main(int argc, char** argv)
2322{
2323    const char *path;
2324    char *newPath;
2325    struct timeval tv;
2326
2327    newPath = NULL;
2328    path = NULL;
2329    NanoVis::stdin = stdin;
2330    NanoVis::logfile = stderr;
2331
2332    gettimeofday(&tv, NULL);
2333    stats.start = tv;
2334
2335    /* Initialize GLUT here so it can parse and remove GLUT-specific
2336     * command-line options before we parse the command-line below. */
2337    glutInit(&argc, argv);
2338    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
2339    glutInitWindowSize(NanoVis::win_width, NanoVis::win_height);
2340    glutInitWindowPosition(10, 10);
2341    NanoVis::render_window = glutCreateWindow("nanovis");
2342    glutIdleFunc(NanoVis::idle);
2343
2344#ifndef XINETD
2345    glutMouseFunc(NanoVis::mouse);
2346    glutMotionFunc(NanoVis::motion);
2347    glutKeyboardFunc(NanoVis::keyboard);
2348    glutReshapeFunc(NanoVis::resize);
2349    glutDisplayFunc(NanoVis::render);
2350#else
2351    glutDisplayFunc(NanoVis::display);
2352    glutReshapeFunc(NanoVis::resize_offscreen_buffer);
2353#endif
2354
2355    while (1) {
2356        static struct option long_options[] = {
2357            {"infile",  required_argument, NULL,           0},
2358            {"logfile", required_argument, NULL,           1},
2359            {"path",    required_argument, NULL,           2},
2360            {"debug",   no_argument,       NULL,           3},
2361            {"record",  required_argument, NULL,           4},
2362            {0, 0, 0, 0}
2363        };
2364        int option_index = 0;
2365        int c;
2366
2367        c = getopt_long(argc, argv, ":dp:i:l:r:", long_options, &option_index);
2368        if (c == -1) {
2369            break;
2370        }
2371        switch (c) {
2372        case '?':
2373            fprintf(stderr, "unknown option -%c\n", optopt);
2374            return 1;
2375        case ':':
2376            if (optopt < 4) {
2377                fprintf(stderr, "argument missing for --%s option\n",
2378                        long_options[optopt].name);
2379            } else {
2380                fprintf(stderr, "argument missing for -%c option\n", optopt);
2381            }
2382            return 1;
2383        case 2:
2384        case 'p':
2385            path = optarg;
2386            break;
2387        case 3:
2388        case 'd':
2389            NanoVis::debug_flag = true;
2390            break;
2391        case 0:
2392        case 'i':
2393            NanoVis::stdin = fopen(optarg, "r");
2394            if (NanoVis::stdin == NULL) {
2395                perror(optarg);
2396                return 2;
2397            }
2398            break;
2399        case 1:
2400        case 'l':
2401            NanoVis::logfile = fopen(optarg, "w");
2402            if (NanoVis::logfile == NULL) {
2403                perror(optarg);
2404                return 2;
2405            }
2406            break;
2407        case 4:
2408        case 'r':
2409            Tcl_DString ds;
2410            char buf[200];
2411
2412            Tcl_DStringInit(&ds);
2413            Tcl_DStringAppend(&ds, optarg, -1);
2414            sprintf(buf, ".%d", getpid());
2415            Tcl_DStringAppend(&ds, buf, -1);
2416            NanoVis::recfile = fopen(Tcl_DStringValue(&ds), "w");
2417            if (NanoVis::recfile == NULL) {
2418                perror(optarg);
2419                return 2;
2420            }
2421            break;
2422        default:
2423            fprintf(stderr,"unknown option '%c'.\n", c);
2424            return 1;
2425        }
2426    }     
2427    if (path == NULL) {
2428        char *p;
2429
2430        // See if we can derive the path from the location of the program.
2431        // Assume program is in the form <path>/bin/nanovis.
2432
2433#ifdef XINETD
2434        path = argv[0];
2435        p = strrchr(path, '/');
2436        if (p != NULL) {
2437            *p = '\0';
2438            p = strrchr(path, '/');
2439        }
2440        if (p == NULL) {
2441            fprintf(stderr, "path not specified\n");
2442            return 1;
2443        }
2444        *p = '\0';
2445        newPath = new char[(strlen(path) + 15) * 2 + 1];
2446        sprintf(newPath, "%s/lib/shaders:%s/lib/resources", path, path);
2447        path = newPath;
2448#else
2449        char buff[256];
2450        getcwd(buff, 255);
2451        p = strrchr(buff, '/');
2452        if (p != NULL) {
2453            *p = '\0';
2454        }
2455        newPath = new char[(strlen(buff) + 15) * 2 + 1];
2456        sprintf(newPath, "%s/lib/shaders:%s/lib/resources", buff, buff);
2457        path = newPath;
2458#endif
2459    }
2460    R2FilePath::getInstance()->setWorkingDirectory(argc, (const char**) argv);
2461
2462#ifdef XINETD
2463    signal(SIGPIPE,SIG_IGN);
2464    NvInitService();
2465#endif
2466
2467    NanoVis::init(path);
2468    if (newPath != NULL) {
2469        delete [] newPath;
2470    }
2471    NanoVis::initGL();
2472#ifdef EVENTLOG
2473    NvInitEventLog();
2474#endif
2475    Tcl_DStringInit(&NanoVis::cmdbuffer);
2476    NanoVis::interp = initTcl();
2477    NanoVis::resize_offscreen_buffer(NanoVis::win_width, NanoVis::win_height);
2478
2479    glutMainLoop();
2480    DoExit(80);
2481}
2482
2483int
2484NanoVis::render_2d_contour(HeightMap* heightmap, int width, int height)
2485{
2486    int old_width = win_width;
2487    int old_height = win_height;
2488
2489    resize_offscreen_buffer(width, height);
2490
2491    /*
2492      plane_render->set_screen_size(width, height);
2493
2494      // generate data for the legend
2495      float data[512];
2496      for (int i=0; i < 256; i++) {
2497      data[i] = data[i+256] = (float)(i/255.0);
2498      }
2499      plane[0] = new Texture2D(256, 2, GL_FLOAT, GL_LINEAR, 1, data);
2500      int index = plane_render->add_plane(plane[0], tf);
2501      plane_render->set_active_plane(index);
2502
2503      offscreen_buffer_capture();
2504      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear screen
2505
2506      //plane_render->render();
2507      // INSOO : is going to implement here for the topview of the heightmap
2508      heightmap->render(renderContext);
2509
2510      // INSOO
2511      glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, screen_buffer);
2512      //glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, screen_buffer); // INSOO's
2513      */
2514
2515
2516    // HELP ME
2517    // GEORGE
2518    // I am not sure what I should do
2519    //char prefix[200];
2520    //sprintf(prefix, "nv>height_top_view %s %g %g", volArg, min, max);
2521    //ppm_write(prefix);
2522    //write(0, "\n", 1);
2523    //plane_render->remove_plane(index);
2524
2525    // CURRENT
2526    offscreen_buffer_capture();
2527    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear screen
2528    //glEnable(GL_TEXTURE_2D);
2529    //glEnable(GL_DEPTH_TEST);
2530    //heightmap->render_topview(renderContext, width, height);
2531    //NanoVis::display();
2532    if (HeightMap::update_pending) {
2533        SetHeightmapRanges();
2534    }
2535
2536    //cam->initialize();
2537
2538    heightmap->render_topview(renderContext, width, height);
2539
2540    NanoVis::read_screen();
2541    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
2542
2543    // INSOO TEST CODE
2544    bmp_write_to_file(1, "/tmp");
2545
2546    resize_offscreen_buffer(old_width, old_height);
2547
2548    return TCL_OK;
2549}
2550
2551void
2552NanoVis::remove_volume(Volume *volPtr)
2553{
2554    Tcl_HashEntry *hPtr;
2555    hPtr = Tcl_FindHashEntry(&volumeTable, volPtr->name());
2556    if (hPtr != NULL) {
2557        Tcl_DeleteHashEntry(hPtr);
2558    }
2559    delete volPtr;                     
2560}
2561
2562/*
2563void NanoVis::drawArrows(const Vector3& v1, const Vector3& v2)
2564{
2565    Vector3 v3, v4;
2566    if if((v1.z-v2.z) != 0)
2567    {
2568        v3.set(1, 1, (-(v1.x-v2.x)-(v1.y-v2.y))/(v1.z-v2.z));
2569
2570        adj = sqrt((x1-x2)^2 + (y1-y2)^2 + (z1-z2)^2)) / (4 * sqrt((x3^2)+(y3^2)+(z3^2)));
2571        v3.scale(adj);
2572        v4 = -v3;
2573
2574        //x3 = x1 + (3/4)*(x1-x2) + x3
2575        //y3 = y1 + (3/4)*(y1-y2) + y3
2576        //z3 = z1 + (3/4)*(z1-z2) + z3
2577
2578        //x4 = x1 + (3/4)*(x1-x2) + x4
2579        //y4 = y1 + (3/4)*(y1-y2) + y4
2580        //z4 = z1 + (3/4)*(z1-z2) + z4
2581    }
2582}
2583*/
Note: See TracBrowser for help on using the repository browser.