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

Last change on this file since 2835 was 2835, checked in by ldelgass, 12 years ago

Exclude unused file from build, misc. cleanups

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