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

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