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

Last change on this file since 1484 was 1484, checked in by vrinside, 15 years ago

added 2d arrows (arrow tip will be added)

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