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

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

Remove some unused code/macros

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