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

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

Normalize line endings, set eol-style to native on *.cpp, *.h files

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