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

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