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

Last change on this file since 2822 was 2822, checked in by ldelgass, 13 years ago

Const correctness fixes, pass vector/matrix objects by reference, various
formatting and style cleanups, don't spam syslog and uncomment openlog() call.
Still needs to be compiled with -DWANT_TRACE to get tracing, but now trace
output will be output to file in /tmp.

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