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

Last change on this file since 2828 was 2828, checked in by ldelgass, 9 years ago

Remove cruft - ifdef disabled code that calls nonexistant functions

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