source: trunk/vizservers/nanovis/nanovis.cpp @ 973

Last change on this file since 973 was 973, checked in by gah, 13 years ago
File size: 49.2 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 <getopt.h>
19#include <stdio.h>
20#include <math.h>
21#include <fstream>
22#include <iostream>
23#include <sstream>
24#include <string>
25#include <time.h>
26#include <sys/time.h>
27#include <sys/types.h>
28#include <unistd.h>
29#include <fcntl.h>
30#include <signal.h>
31#include <stdlib.h>
32
33#include "Nv.h"
34#include "PointSetRenderer.h"
35#include "PointSet.h"
36#include "Util.h"
37#include <NvLIC.h>
38#include <Trace.h>
39
40#include "nanovis.h"
41#include "RpField1D.h"
42#include "RpFieldRect3D.h"
43#include "RpFieldPrism3D.h"
44#include "RpEncode.h"
45
46//transfer function headers
47#include "transfer-function/TransferFunctionMain.h"
48#include "transfer-function/ControlPoint.h"
49#include "transfer-function/TransferFunctionGLUTWindow.h"
50#include "transfer-function/ColorGradientGLUTWindow.h"
51#include "transfer-function/ColorPaletteWindow.h"
52#include "transfer-function/MainWindow.h"
53#include "ZincBlendeVolume.h"
54#include "NvLoadFile.h"
55#include "NvColorTableRenderer.h"
56#include "NvEventLog.h"
57#include "NvZincBlendeReconstructor.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
72extern void NvInitCG(); // in Shader.cpp
73
74// Indicates "up" axis:  x=1, y=2, z=3, -x=-1, -y=-2, -z=-3
75enum AxisDirections {
76    X_POS = 1, Y_POS = 2, Z_POS = 3, X_NEG = -1, Y_NEG = -2, Z_NEG = -3
77};
78
79// STATIC MEMBER DATA
80Grid *NanoVis::grid = NULL;
81int NanoVis::updir = Y_POS;
82NvCamera* NanoVis::cam = NULL;
83bool NanoVis::axis_on = true;
84//bool NanoVis::axis_on = false;
85int NanoVis::win_width = NPIX;                  //size of the render window
86int NanoVis::win_height = NPIX;                 //size of the render window
87int NanoVis::n_volumes = 0;
88unsigned char* NanoVis::screen_buffer = NULL;
89vector<HeightMap*> NanoVis::heightMap;
90VolumeRenderer* NanoVis::vol_renderer = 0;
91PointSetRenderer* NanoVis::pointset_renderer = 0;
92vector<PointSet*> NanoVis::pointSet;
93PlaneRenderer* NanoVis::plane_render = 0;
94Texture2D* NanoVis::plane[10];
95NvColorTableRenderer* NanoVis::color_table_renderer = 0;
96NvParticleRenderer* NanoVis::particleRenderer = 0;
97graphics::RenderContext* NanoVis::renderContext = 0;
98NvLIC* NanoVis::licRenderer = 0;
99
100bool NanoVis::lic_on = false;
101bool NanoVis::particle_on = false;
102bool NanoVis::vector_on = false;
103bool NanoVis::config_pending = false;
104
105
106// pointers to volumes, currently handle up to 10 volumes
107/*FIXME: Is the above comment true? Is there a 10 volume limit */
108vector<Volume*> NanoVis::volume;
109
110//if true nanovis renders volumes in 3D, if not renders 2D plane
111/* FIXME: This variable is always true. */
112bool volume_mode = true;
113
114// color table for built-in transfer function editor
115float color_table[256][4];     
116
117/*
118#ifdef XINETD
119FILE* xinetd_log;
120#endif
121
122FILE* event_log;
123//log
124void init_event_log();
125void end_event_log();
126double cur_time;        //in seconds
127double get_time_interval();
128*/
129
130int render_window;              //the handle of the render window;
131
132// in Command.cpp
133extern void xinetd_listen();
134extern void initTcl();
135
136//ParticleSystem* psys;
137//float psys_x=0.4, psys_y=0, psys_z=0;
138
139//static Lic* lic;
140
141//frame buffer for final rendering
142static NVISid final_fbo, final_color_tex, final_depth_rb;
143
144//bool advect=false;
145float vert[NMESH*NMESH*3];              //particle positions in main memory
146float slice_vector[NMESH*NMESH*4];      //per slice vectors in main memory
147
148// maps transfunc name to TransferFunction object
149static Tcl_HashTable tftable;
150
151// pointers to 2D planes, currently handle up 10
152
153
154PerfQuery* perf;                        //perfromance counter
155
156CGprogram m_passthru_fprog;
157CGparameter m_passthru_scale_param, m_passthru_bias_param;
158
159R2Fonts* NanoVis::fonts;
160
161// Variables for mouse events
162
163// Object rotation angles
164static float live_rot_x = 90.;         
165static float live_rot_y = 180.;
166static float live_rot_z = -135;
167
168// Object translation location from the origin
169static float live_obj_x = -0.0;
170static float live_obj_y = -0.0;
171static float live_obj_z = -2.5;
172
173
174#ifndef XINETD
175// Last locations mouse events
176static int left_last_x;
177static int left_last_y;
178static int right_last_x;
179static int right_last_y;
180static bool left_down = false;                                         
181static bool right_down = false;
182#endif /*XINETD*/
183
184// Image based flow visualization slice location
185// FLOW
186float NanoVis::lic_slice_x = 1.0f;
187float NanoVis::lic_slice_y = 0.0f;
188float NanoVis::lic_slice_z = 0.5f;
189int NanoVis::lic_axis = 2;
190
191/*
192CGprogram m_copy_texcoord_fprog;
193CGprogram m_one_volume_fprog;
194CGparameter m_vol_one_volume_param;
195CGparameter m_tf_one_volume_param;
196CGparameter m_mvi_one_volume_param;
197CGparameter m_mv_one_volume_param;
198CGparameter m_render_param_one_volume_param;
199*/
200
201/*
202CGprogram m_vert_std_vprog;
203CGparameter m_mvp_vert_std_param;
204CGparameter m_mvi_vert_std_param;
205*/
206
207using namespace std;
208
209#define RM_VOLUME 1
210#define RM_POINT 2
211
212int renderMode = RM_VOLUME;
213
214/*
215 * ----------------------------------------------------------------------
216 * USAGE: debug("string", ...)
217 *
218 * Use this anywhere within the package to send a debug message
219 * back to the client.  The string can have % fields as used by
220 * the printf() package.  Any remaining arguments are treated as
221 * field substitutions on that.
222 * ----------------------------------------------------------------------
223 */
224void
225debug(char *str)
226{
227    write(0, str, strlen(str));
228}
229
230void
231debug(char *str, double v1)
232{
233    char buffer[512];
234    sprintf(buffer, str, v1);
235    write(0, buffer, strlen(buffer));
236}
237
238void
239debug(char *str, double v1, double v2)
240{
241    char buffer[512];
242    sprintf(buffer, str, v1, v2);
243    write(0, buffer, strlen(buffer));
244}
245
246void
247debug(char *str, double v1, double v2, double v3)
248{
249    char buffer[512];
250    sprintf(buffer, str, v1, v2, v3);
251    write(0, buffer, strlen(buffer));
252}
253
254//report errors related to CG shaders
255void cgErrorCallback(void)
256{
257    CGerror lastError = cgGetError();
258    if(lastError) {
259        const char *listing = cgGetLastListing(g_context);
260        Trace("\n---------------------------------------------------\n");
261        Trace("%s\n\n", cgGetErrorString(lastError));
262        Trace("%s\n", listing);
263        Trace("-----------------------------------------------------\n");
264        Trace("Cg error, exiting...\n");
265        cgDestroyContext(g_context);
266        exit(-1);
267    }
268}
269
270
271/* Load a 3D volume
272 * index: the index into the volume array, which stores pointers to 3D volume instances
273 * data: pointer to an array of floats. 
274 * n_component: the number of scalars for each space point.
275 *              All component scalars for a point are placed consequtively in data array
276 * width, height and depth: number of points in each dimension
277 */
278Volume *
279NanoVis::load_volume(int index, int width, int height, int depth,
280                     int n_component, float* data, double vmin,
281                     double vmax, double nzero_min)
282{
283    while (n_volumes <= index) {
284        volume.push_back(NULL);
285        n_volumes++;
286    }
287
288    Volume* vol = volume[index];
289    if (vol != NULL) {
290        volume[index] = NULL;
291
292        if (vol->pointsetIndex != -1) {
293            if (((unsigned  int) vol->pointsetIndex) < pointSet.size() &&
294                pointSet[vol->pointsetIndex] != NULL) {
295                delete pointSet[vol->pointsetIndex];
296                pointSet[vol->pointsetIndex] = 0;
297            }
298        }
299        delete vol;
300    }
301    volume[index] = new Volume(0.f, 0.f, 0.f, width, height, depth, 1.,
302        n_component, data, vmin, vmax, nzero_min);
303    return volume[index];
304}
305
306// Gets a colormap 1D texture by name.
307TransferFunction*
308NanoVis::get_transfunc(const char *name)
309{
310    Tcl_HashEntry *hPtr;
311   
312    hPtr = Tcl_FindHashEntry(&tftable, name);
313    if (hPtr == NULL) {
314        return NULL;
315    }
316    return (TransferFunction*)Tcl_GetHashValue(hPtr);
317}
318
319// Creates of updates a colormap 1D texture by name.
320TransferFunction*
321NanoVis::DefineTransferFunction(const char *name, size_t n, float *data)
322{
323    int isNew;
324    Tcl_HashEntry *hPtr;
325    TransferFunction *tf;
326
327    hPtr = Tcl_CreateHashEntry(&tftable, name, &isNew);
328    if (isNew) {
329        tf = new TransferFunction(n, data);
330        Tcl_SetHashValue(hPtr, (ClientData)tf);
331    } else {
332        /*
333         * You can't delete the transfer function because many
334         * objects may be holding its pointer.  We must update it.
335         */
336        tf = (TransferFunction *)Tcl_GetHashValue(hPtr);
337        tf->update(n, data);
338    }
339    return tf;
340}
341
342void
343NanoVis::zoom(double zoom)
344{
345    live_obj_z = -2.5 / zoom;
346    cam->move(live_obj_x, live_obj_y, live_obj_z);
347}
348
349//Update the transfer function using local GUI in the non-server mode
350void
351update_tf_texture()
352{
353    glutSetWindow(render_window);
354   
355    //fprintf(stderr, "tf update\n");
356    TransferFunction *tf = NanoVis::get_transfunc("default");
357    if (tf == NULL) {
358        return;
359    }
360   
361    float data[256*4];
362    for(int i=0; i<256; i++) {
363        data[4*i+0] = color_table[i][0];
364        data[4*i+1] = color_table[i][1];
365        data[4*i+2] = color_table[i][2];
366        data[4*i+3] = color_table[i][3];
367        //fprintf(stderr, "(%f,%f,%f,%f) ", data[4*i+0], data[4*i+1], data[4*i+2], data[4*i+3]);
368    }
369   
370    tf->update(data);
371   
372#ifdef EVENTLOG
373    float param[3] = {0,0,0};
374    Event* tmp = new Event(EVENT_ROTATE, param, NvGetTimeInterval());
375    tmp->write(event_log);
376    delete tmp;
377#endif
378}
379
380int
381NanoVis::render_legend(
382    TransferFunction *tf,
383    double min, double max,
384    int width, int height,
385    const char* volArg)
386{
387    int old_width = win_width;
388    int old_height = win_height;
389
390    plane_render->set_screen_size(width, height);
391    resize_offscreen_buffer(width, height);
392
393    // generate data for the legend
394    float data[512];
395    for (int i=0; i < 256; i++) {
396        data[i] = data[i+256] = (float)(i/255.0);
397    }
398    plane[0] = new Texture2D(256, 2, GL_FLOAT, GL_LINEAR, 1, data);
399    int index = plane_render->add_plane(plane[0], tf);
400    plane_render->set_active_plane(index);
401
402    offscreen_buffer_capture();
403    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear screen
404    plane_render->render();
405
406    // INSOO
407    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, screen_buffer);
408    //glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, screen_buffer); // INSOO's
409
410    std::ostringstream result;
411    result << "nv>legend " << volArg;
412    result << " " << min;
413    result << " " << max;
414    bmp_write(result.str().c_str());
415    write(0, "\n", 1);
416
417    plane_render->remove_plane(index);
418    resize_offscreen_buffer(old_width, old_height);
419
420    return TCL_OK;
421}
422
423//initialize frame buffer objects for offscreen rendering
424void
425NanoVis::init_offscreen_buffer()
426{
427    //initialize final fbo for final display
428    glGenFramebuffersEXT(1, &final_fbo);
429    glGenTextures(1, &final_color_tex);
430    glGenRenderbuffersEXT(1, &final_depth_rb);
431   
432    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, final_fbo);
433   
434    //initialize final color texture
435    glBindTexture(GL_TEXTURE_2D, final_color_tex);
436    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
437    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
438#ifdef NV40
439    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, win_width, win_height, 0,
440                 GL_RGB, GL_INT, NULL);
441#else
442    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, win_width, win_height, 0,
443                 GL_RGB, GL_INT, NULL);
444#endif
445    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
446                              GL_COLOR_ATTACHMENT0_EXT,
447                              GL_TEXTURE_2D, final_color_tex, 0);
448   
449    // initialize final depth renderbuffer
450    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, final_depth_rb);
451    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
452                             GL_DEPTH_COMPONENT24, win_width, win_height);
453    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
454                                 GL_DEPTH_ATTACHMENT_EXT,
455                                 GL_RENDERBUFFER_EXT, final_depth_rb);
456   
457    // Check framebuffer completeness at the end of initialization.
458    CHECK_FRAMEBUFFER_STATUS();
459
460    //assert(glGetError()==0);
461}
462
463
464//resize the offscreen buffer
465void
466NanoVis::resize_offscreen_buffer(int w, int h)
467{
468    win_width = w;
469    win_height = h;
470   
471    if (fonts) {
472        fonts->resize(w, h);
473    }
474   
475    //fprintf(stderr, "screen_buffer size: %d\n", sizeof(screen_buffer));
476    printf("screen_buffer size: %d %d\n", w, h);
477   
478    if (screen_buffer) {
479        delete[] screen_buffer;
480        screen_buffer = NULL;
481    }
482   
483    screen_buffer = new unsigned char[4*win_width*win_height];
484    assert(screen_buffer != NULL);
485   
486    //delete the current render buffer resources
487    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, final_fbo);
488    glDeleteTextures(1, &final_color_tex);
489    glDeleteFramebuffersEXT(1, &final_fbo);
490   
491    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, final_depth_rb);
492    glDeleteRenderbuffersEXT(1, &final_depth_rb);
493   
494    //change the camera setting
495    cam->set_screen_size(0, 0, win_width, win_height);
496    plane_render->set_screen_size(win_width, win_height);
497   
498    //Reinitialize final fbo for final display
499    glGenFramebuffersEXT(1, &final_fbo);
500    glGenTextures(1, &final_color_tex);
501    glGenRenderbuffersEXT(1, &final_depth_rb);
502
503    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, final_fbo);
504   
505    //initialize final color texture
506    glBindTexture(GL_TEXTURE_2D, final_color_tex);
507    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
508    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
509#ifdef NV40
510    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, win_width, win_height, 0,
511                 GL_RGB, GL_INT, NULL);
512#else
513    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, win_width, win_height, 0,
514                 GL_RGB, GL_INT, NULL);
515#endif
516    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
517                              GL_COLOR_ATTACHMENT0_EXT,
518                              GL_TEXTURE_2D, final_color_tex, 0);
519       
520    // initialize final depth renderbuffer
521    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, final_depth_rb);
522    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
523                             GL_DEPTH_COMPONENT24, win_width, win_height);
524    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
525                                 GL_DEPTH_ATTACHMENT_EXT,
526                                 GL_RENDERBUFFER_EXT, final_depth_rb);
527
528    // Check framebuffer completeness at the end of initialization.
529    CHECK_FRAMEBUFFER_STATUS();
530    //assert(glGetError()==0);
531    fprintf(stdin,"  after assert\n");
532}
533
534void
535make_test_2D_data()
536{
537
538    int w = 300;
539    int h = 200;
540    float* data = new float[w*h];
541   
542    //procedurally make a gradient plane
543    for(int j=0; j<h; j++){
544        for(int i=0; i<w; i++){
545            data[w*j+i] = float(i)/float(w);
546        }
547    }
548    NanoVis::plane[0] = new Texture2D(w, h, GL_FLOAT, GL_LINEAR, 1, data);
549    delete[] data;
550}
551
552void NanoVis::initParticle()
553{
554    //random placement on a slice
555    float* data = new float[particleRenderer->psys_width * particleRenderer->psys_height * 4];
556    bzero(data, sizeof(float)*4* particleRenderer->psys_width * particleRenderer->psys_height);
557
558    int index;
559    //bool particle;
560    for (int i=0; i<particleRenderer->psys_width; i++) {
561        for (int j=0; j<particleRenderer->psys_height; j++) {
562            index = i + particleRenderer->psys_height*j;
563            //particle = rand() % 256 > 150;
564            //if(particle)
565            {
566                //assign any location (x,y,z) in range [0,1]
567                // TEMP
568                data[4*index] = lic_slice_x;
569                data[4*index+1]= j/float(particleRenderer->psys_height);
570                data[4*index+2]= i/float(particleRenderer->psys_width);
571                data[4*index+3]= 30; //shorter life span, quicker iterations   
572                //data[4*index+3]= 1.0f; //shorter life span, quicker iterations       
573            }
574/*
575            else
576            {
577                data[4*index] = 0;
578                data[4*index+1]= 0;
579                data[4*index+2]= 0;
580                data[4*index+3]= 0;     
581            }
582*/
583        }
584    }
585
586    particleRenderer->initialize((Particle*)data);
587
588    delete[] data;
589}
590
591void CgErrorCallback(void)
592{
593    CGerror lastError = cgGetError();
594
595    if(lastError) {
596        const char *listing = cgGetLastListing(g_context);
597        printf("\n---------------------------------------------------\n");
598        printf("%s\n\n", cgGetErrorString(lastError));
599        printf("%s\n", listing);
600        printf("-----------------------------------------------------\n");
601        printf("Cg error, exiting...\n");
602        cgDestroyContext(g_context);
603        fflush(stdout);
604        exit(-1);
605    }
606}
607
608void NanoVis::init(const char* path)
609{
610    // print system information
611    fprintf(stderr, "-----------------------------------------------------------\n");
612    fprintf(stderr, "OpenGL driver: %s %s\n", glGetString(GL_VENDOR), glGetString(GL_VERSION));
613    fprintf(stderr, "Graphics hardware: %s\n", glGetString(GL_RENDERER));
614    fprintf(stderr, "-----------------------------------------------------------\n");
615
616    // init GLEW
617    GLenum err = glewInit();
618    if (GLEW_OK != err) {
619        //glew init failed, exit.
620        fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
621        getchar();
622        //assert(false);
623    }
624    fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
625
626    if (path)
627    {
628        R2FilePath::getInstance()->setPath(path);
629    }
630
631    NvInitCG();
632    NvShader::setErrorCallback(CgErrorCallback);
633
634    fonts = new R2Fonts();
635    fonts->addFont("verdana", "verdana.fnt");
636    fonts->setFont("verdana");
637
638    color_table_renderer = new NvColorTableRenderer();
639    color_table_renderer->setFonts(fonts);
640   
641    particleRenderer = new NvParticleRenderer(NMESH, NMESH, g_context);
642    licRenderer = new NvLIC(NMESH, NPIX, NPIX, 0.5, g_context);
643
644    ImageLoaderFactory::getInstance()->addLoaderImpl("bmp", new BMPImageLoaderImpl());
645
646    grid = new Grid();
647    grid->setFont(fonts);
648
649    pointset_renderer = new PointSetRenderer();
650}
651
652/*----------------------------------------------------*/
653void
654NanoVis::initGL(void)
655{
656   //buffer to store data read from the screen
657   if (screen_buffer) {
658       delete[] screen_buffer;
659       screen_buffer = NULL;
660   }
661   screen_buffer = new unsigned char[4*win_width*win_height];
662   assert(screen_buffer != NULL);
663
664   //create the camera with default setting
665   cam = new NvCamera(0, 0, win_width, win_height,
666                   live_obj_x, live_obj_y, live_obj_z,
667                   0., 0., 100.,
668                   (int)live_rot_x, (int)live_rot_y, (int)live_rot_z);
669
670   glEnable(GL_TEXTURE_2D);
671   glShadeModel(GL_FLAT);
672   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
673
674   glClearColor(0,0,0,1);
675   glClear(GL_COLOR_BUFFER_BIT);
676
677   //initialize lighting
678   GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
679   GLfloat mat_shininess[] = {30.0};
680   GLfloat white_light[] = {1.0, 1.0, 1.0, 1.0};
681   GLfloat green_light[] = {0.1, 0.5, 0.1, 1.0};
682
683   glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
684   glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
685   glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
686   glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);     
687   glLightfv(GL_LIGHT1, GL_DIFFUSE, green_light);
688   glLightfv(GL_LIGHT1, GL_SPECULAR, white_light);     
689
690   // init table of transfer functions
691   Tcl_InitHashTable(&tftable, TCL_STRING_KEYS);
692
693   //check if performance query is supported
694   if(check_query_support()){
695     //create queries to count number of rendered pixels
696     perf = new PerfQuery();
697   }
698
699   init_offscreen_buffer();    //frame buffer object for offscreen rendering
700
701   //create volume renderer and add volumes to it
702   vol_renderer = new VolumeRenderer();
703
704
705   // create
706   renderContext = new graphics::RenderContext();
707   
708#ifdef notdef
709   //I added this to debug : Wei
710   float tmp_data[4*124];
711   memset(tmp_data, 0, 4*4*124);
712   TransferFunction* tmp_tf = new TransferFunction(124, tmp_data);
713   vol_renderer->add_volume(volume[0], tmp_tf);
714   volume[0]->get_cutplane(0)->enabled = false;
715   volume[0]->get_cutplane(1)->enabled = false;
716   volume[0]->get_cutplane(2)->enabled = false;
717
718   //volume[1]->move(Vector3(0.5, 0.6, 0.7));
719   //vol_renderer->add_volume(volume[1], tmp_tf);
720#endif
721
722   //create an 2D plane renderer
723   plane_render = new PlaneRenderer(g_context, win_width, win_height);
724   make_test_2D_data();
725
726   plane_render->add_plane(plane[0], get_transfunc("default"));
727
728   //assert(glGetError()==0);
729
730#ifdef notdef
731   init_particle_system();
732   NanoVis::init_lic();
733#endif
734}
735
736void
737NanoVis::read_screen()
738{
739    glReadPixels(0, 0, win_width, win_height, GL_RGB, GL_UNSIGNED_BYTE,
740                 screen_buffer);
741}
742
743#if DO_RLE
744char rle[512*512*3];
745int rle_size;
746
747short offsets[512*512*3];
748int offsets_size;
749
750void
751do_rle()
752{
753    int len = NanoVis::win_width*NanoVis::win_height*3;
754    rle_size = 0;
755    offsets_size = 0;
756   
757    int i=0;
758    while(i<len){
759        if (NanoVis::screen_buffer[i] == 0) {
760            int pos = i+1;
761            while ( (pos<len) && (NanoVis::screen_buffer[pos] == 0)) {
762                pos++;
763            }
764            offsets[offsets_size++] = -(pos - i);
765            i = pos;
766        }
767       
768        else {
769            int pos;
770            for (pos = i; (pos<len) && (NanoVis::screen_buffer[pos] != 0);pos++){
771                rle[rle_size++] = NanoVis::screen_buffer[pos];
772            }
773            offsets[offsets_size++] = (pos - i);
774            i = pos;
775        }
776       
777    }
778}
779#endif
780
781// used internally to build up the BMP file header
782// writes an integer value into the header data structure at pos
783static void
784bmp_header_add_int(unsigned char* header, int& pos, int data)
785{
786    header[pos++] = data & 0xff;
787    header[pos++] = (data >> 8) & 0xff;
788    header[pos++] = (data >> 16) & 0xff;
789    header[pos++] = (data >> 24) & 0xff;
790}
791
792// INSOO
793// FOR DEBUGGING
794void
795NanoVis::bmp_write_to_file(int frame_number, char* directory_name)
796{
797    unsigned char header[54];
798    int pos = 0;
799    header[pos++] = 'B';
800    header[pos++] = 'M';
801
802    // BE CAREFUL:  BMP files must have an even multiple of 4 bytes
803    // on each scan line.  If need be, we add padding to each line.
804    int pad = 0;
805    if ((3*win_width) % 4 > 0) {
806        pad = 4 - ((3*win_width) % 4);
807    }
808
809    // file size in bytes
810    int fsize = (3*win_width+pad)*win_height + sizeof(header);
811    bmp_header_add_int(header, pos, fsize);
812
813    // reserved value (must be 0)
814    bmp_header_add_int(header, pos, 0);
815
816    // offset in bytes to start of bitmap data
817    bmp_header_add_int(header, pos, sizeof(header));
818
819    // size of the BITMAPINFOHEADER
820    bmp_header_add_int(header, pos, 40);
821
822    // width of the image in pixels
823    bmp_header_add_int(header, pos, win_width);
824
825    // height of the image in pixels
826    bmp_header_add_int(header, pos, win_height);
827
828    // 1 plane + (24 bits/pixel << 16)
829    bmp_header_add_int(header, pos, 1572865);
830
831    // no compression
832    // size of image for compression
833    bmp_header_add_int(header, pos, 0);
834    bmp_header_add_int(header, pos, 0);
835
836    // x pixels per meter
837    // y pixels per meter
838    bmp_header_add_int(header, pos, 0);
839    bmp_header_add_int(header, pos, 0);
840
841    // number of colors used (0 = compute from bits/pixel)
842    // number of important colors (0 = all colors important)
843    bmp_header_add_int(header, pos, 0);
844    bmp_header_add_int(header, pos, 0);
845
846    // BE CAREFUL: BMP format wants BGR ordering for screen data
847    unsigned char* scr = screen_buffer;
848    for (int row=0; row < win_height; row++) {
849        for (int col=0; col < win_width; col++) {
850            unsigned char tmp = scr[2];
851            scr[2] = scr[0];  // B
852            scr[0] = tmp;     // R
853            scr += 3;
854        }
855        scr += pad;  // skip over padding already in screen data
856    }
857
858    FILE* f;
859    char filename[100];
860    if (frame_number >= 0) {
861        if (directory_name)
862            sprintf(filename, "%s/image%03d.bmp", directory_name, frame_number);
863        else
864            sprintf(filename, "/tmp/flow_animation/image%03d.bmp", frame_number);
865
866        printf("Writing %s\n", filename);
867        f = fopen(filename, "wb");
868        if (f == 0) {
869            Trace("cannot create file\n");
870        }
871    } else {
872        f = fopen("/tmp/image.bmp", "wb");
873        if (f == 0) {
874            Trace("cannot create file\n");
875        }
876    }
877    fwrite((void*) header, sizeof(header), 1, f);
878    fwrite((void*) screen_buffer, (3*win_width+pad)*win_height, 1, f);
879    fclose(f);
880}
881
882void
883NanoVis::bmp_write(const char* cmd)
884{
885    unsigned char header[54];
886    int pos = 0;
887    header[pos++] = 'B';
888    header[pos++] = 'M';
889
890    // BE CAREFUL:  BMP files must have an even multiple of 4 bytes
891    // on each scan line.  If need be, we add padding to each line.
892    int pad = 0;
893    if ((3*win_width) % 4 > 0) {
894        pad = 4 - ((3*win_width) % 4);
895    }
896
897    // file size in bytes
898    int fsize = (3*win_width+pad)*win_height + sizeof(header);
899    bmp_header_add_int(header, pos, fsize);
900
901    // reserved value (must be 0)
902    bmp_header_add_int(header, pos, 0);
903
904    // offset in bytes to start of bitmap data
905    bmp_header_add_int(header, pos, sizeof(header));
906
907    // size of the BITMAPINFOHEADER
908    bmp_header_add_int(header, pos, 40);
909
910    // width of the image in pixels
911    bmp_header_add_int(header, pos, win_width);
912
913    // height of the image in pixels
914    bmp_header_add_int(header, pos, win_height);
915
916    // 1 plane + (24 bits/pixel << 16)
917    bmp_header_add_int(header, pos, 1572865);
918
919    // no compression
920    // size of image for compression
921    bmp_header_add_int(header, pos, 0);
922    bmp_header_add_int(header, pos, 0);
923
924    // x pixels per meter
925    // y pixels per meter
926    bmp_header_add_int(header, pos, 0);
927    bmp_header_add_int(header, pos, 0);
928
929    // number of colors used (0 = compute from bits/pixel)
930    // number of important colors (0 = all colors important)
931    bmp_header_add_int(header, pos, 0);
932    bmp_header_add_int(header, pos, 0);
933
934    // BE CAREFUL: BMP format wants BGR ordering for screen data
935    unsigned char* scr = screen_buffer;
936    for (int row=0; row < win_height; row++) {
937        for (int col=0; col < win_width; col++) {
938            unsigned char tmp = scr[2];
939            scr[2] = scr[0];  // B
940            scr[0] = tmp;     // R
941            scr += 3;
942        }
943        scr += pad;  // skip over padding already in screen data
944    }
945
946    std::ostringstream result;
947    result << cmd << " " << fsize << "\n";
948    write(0, result.str().c_str(), result.str().size());
949
950    write(0, header, sizeof(header));
951    write(0, screen_buffer, (3*win_width+pad)*win_height);
952
953}
954
955#ifdef notdef
956//draw vectors
957void draw_arrows()
958{
959    glColor4f(0.,0.,1.,1.);
960    for(int i=0; i<NMESH; i++){
961        for(int j=0; j<NMESH; j++){
962            Vector2 v = grid.get(i, j);
963           
964            int x1 = i*DM;
965            int y1 = j*DM;
966           
967            int x2 = x1 + v.x;
968            int y2 = y1 + v.y;
969           
970            glBegin(GL_LINES);
971            glVertex2d(x1, y1);
972            glVertex2d(x2, y2);
973            glEnd();
974        }
975    }
976}
977#endif
978
979
980/*----------------------------------------------------*/
981static void
982idle()
983{
984    glutSetWindow(render_window);
985 
986#ifdef notdef
987      struct timespec ts;
988      ts.tv_sec = 0;
989      ts.tv_nsec = 300000000;
990      nanosleep(&ts, 0);
991#endif
992#ifdef XINETD
993    xinetd_listen();
994#else
995    glutPostRedisplay();
996#endif
997}
998
999void
1000NanoVis::display_offscreen_buffer()
1001{
1002    glEnable(GL_TEXTURE_2D);
1003    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1004    glBindTexture(GL_TEXTURE_2D, final_color_tex);
1005   
1006    glViewport(0, 0, win_width, win_height);
1007    glMatrixMode(GL_PROJECTION);
1008    glLoadIdentity();
1009    gluOrtho2D(0, win_width, 0, win_height);
1010    glMatrixMode(GL_MODELVIEW);
1011    glLoadIdentity();
1012   
1013    glColor3f(1.,1.,1.);                //MUST HAVE THIS LINE!!!
1014    glBegin(GL_QUADS);
1015    {
1016        glTexCoord2f(0, 0); glVertex2f(0, 0);
1017        glTexCoord2f(1, 0); glVertex2f(win_width, 0);
1018        glTexCoord2f(1, 1); glVertex2f(win_width, win_height);
1019        glTexCoord2f(0, 1); glVertex2f(0, win_height);
1020    }
1021    glEnd();
1022}
1023
1024void
1025NanoVis::offscreen_buffer_capture()
1026{
1027    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, final_fbo);
1028}
1029
1030#ifdef notdef
1031/*
1032 * Is this routine being used? --gah
1033 */
1034void
1035draw_bounding_box(float x0, float y0, float z0,
1036                  float x1, float y1, float z1,
1037                  float r, float g, float b, float line_width)
1038{
1039    glDisable(GL_TEXTURE_2D);
1040    glColor4d(r, g, b, 1.0);
1041    glLineWidth(line_width);
1042    glBegin(GL_LINE_LOOP);
1043    {
1044        glVertex3d(x0, y0, z0);
1045        glVertex3d(x1, y0, z0);
1046        glVertex3d(x1, y1, z0);
1047        glVertex3d(x0, y1, z0);
1048    }
1049    glEnd();
1050    glBegin(GL_LINE_LOOP);
1051    {
1052        glVertex3d(x0, y0, z1);
1053        glVertex3d(x1, y0, z1);
1054        glVertex3d(x1, y1, z1);
1055        glVertex3d(x0, y1, z1);
1056    }
1057    glEnd();
1058    glBegin(GL_LINE_LOOP);
1059    {
1060        glVertex3d(x0, y0, z0);
1061        glVertex3d(x0, y0, z1);
1062        glVertex3d(x0, y1, z1);
1063        glVertex3d(x0, y1, z0);
1064    }
1065    glEnd();
1066    glBegin(GL_LINE_LOOP);
1067    {
1068        glVertex3d(x1, y0, z0);
1069        glVertex3d(x1, y0, z1);
1070        glVertex3d(x1, y1, z1);
1071        glVertex3d(x1, y1, z0);
1072    }
1073    glEnd();
1074    glEnable(GL_TEXTURE_2D);
1075}
1076#endif
1077
1078
1079#ifdef notdef
1080
1081static int
1082particle_distance_sort(const void* a, const void* b)
1083{
1084    if((*((Particle*)a)).aux > (*((Particle*)b)).aux) {
1085        return -1;
1086    } else {
1087        return 1;
1088    }
1089}
1090
1091void soft_read_verts()
1092{
1093    glReadPixels(0, 0, psys->psys_width, psys->psys_height, GL_RGB, GL_FLOAT, vert);
1094    //fprintf(stderr, "soft_read_vert");
1095   
1096    //cpu sort the distance 
1097    Particle* p;
1098    p = (Particle*)malloc(sizeof(Particle)*psys->psys_width*psys->psys_height);
1099    for (int i=0; i<psys->psys_width * psys->psys_height; i++) {
1100        float x = vert[3*i];
1101        float y = vert[3*i+1];
1102        float z = vert[3*i+2];
1103       
1104        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);
1105        p[i].x = x;
1106        p[i].y = y;
1107        p[i].z = z;
1108        p[i].aux = dis;
1109    }
1110   
1111    qsort(p, psys->psys_width * psys->psys_height, sizeof(Particle), particle_distance_sort);
1112   
1113    for(int i=0; i<psys->psys_width * psys->psys_height; i++){
1114        vert[3*i] = p[i].x;
1115        vert[3*i+1] = p[i].y;
1116        vert[3*i+2] = p[i].z;
1117    }
1118   
1119    free(p);
1120}
1121#endif
1122
1123#ifdef notdef
1124//display the content of a texture as a screen aligned quad
1125void
1126display_texture(NVISid tex, int width, int height)
1127{
1128    glPushMatrix();
1129   
1130    glEnable(GL_TEXTURE_2D);
1131    glBindTexture(GL_TEXTURE_RECTANGLE_NV, tex);
1132   
1133    glViewport(0, 0, width, height);
1134    glMatrixMode(GL_PROJECTION);
1135    glLoadIdentity();
1136    gluOrtho2D(0, width, 0, height);
1137    glMatrixMode(GL_MODELVIEW);
1138    glLoadIdentity();
1139   
1140    cgGLBindProgram(m_passthru_fprog);
1141    cgGLEnableProfile(CG_PROFILE_FP30);
1142   
1143    cgGLSetParameter4f(m_passthru_scale_param, 1.0, 1.0, 1.0, 1.0);
1144    cgGLSetParameter4f(m_passthru_bias_param, 0.0, 0.0, 0.0, 0.0);
1145   
1146    draw_quad(width, height, width, height);
1147    cgGLDisableProfile(CG_PROFILE_FP30);
1148   
1149    glPopMatrix();
1150   
1151    //assert(glGetError()==0);
1152}
1153#endif
1154
1155
1156//draw vertices in the main memory
1157#ifdef notdef
1158void
1159soft_display_verts()
1160{
1161    glDisable(GL_TEXTURE_2D);
1162    glEnable(GL_BLEND);
1163   
1164    glPointSize(0.5);
1165    glColor4f(0,0.8,0.8,0.6);
1166    glBegin(GL_POINTS);
1167    {
1168        for(int i=0; i < psys->psys_width * psys->psys_height; i++){
1169            glVertex3f(vert[3*i], vert[3*i+1], vert[3*i+2]);
1170        }
1171    }
1172    glEnd();
1173    //fprintf(stderr, "soft_display_vert");
1174}
1175#endif
1176
1177#if 0
1178//oddeven sort on GPU
1179void
1180sortstep()
1181{
1182    // perform one step of the current sorting algorithm
1183   
1184#ifdef notdef
1185    // swap buffers
1186    int sourceBuffer = targetBuffer;
1187    targetBuffer = (targetBuffer+1)%2;   
1188    int pstage = (1<<stage);
1189    int ppass  = (1<<pass);
1190    int activeBitonicShader = 0;
1191   
1192#ifdef _WIN32
1193    buffer->BindBuffer(wglTargets[sourceBuffer]);
1194#else
1195    buffer->BindBuffer(glTargets[sourceBuffer]);
1196#endif
1197    if (buffer->IsDoubleBuffered()) glDrawBuffer(glTargets[targetBuffer]);
1198#endif
1199
1200    checkGLError("after db");
1201
1202    int pstage = (1<<stage);
1203    int ppass  = (1<<pass);
1204    //int activeBitonicShader = 0;
1205
1206    // switch on correct sorting shader
1207    oddevenMergeSort.bind();
1208    glUniform3fARB(oddevenMergeSort.getUniformLocation("Param1"), float(pstage+pstage),
1209                   float(ppass%pstage), float((pstage+pstage)-(ppass%pstage)-1));
1210    glUniform3fARB(oddevenMergeSort.getUniformLocation("Param2"),
1211                   float(psys_width), float(psys_height), float(ppass));
1212    glUniform1iARB(oddevenMergeSort.getUniformLocation("Data"), 0);
1213    staticdebugmsg("sort","stage "<<pstage<<" pass "<<ppass);
1214   
1215    // This clear is not necessary for sort to function. But if we are in
1216    // interactive mode unused parts of the texture that are visible will look
1217    // bad.
1218#ifdef notdef
1219    if (!perfTest) glClear(GL_COLOR_BUFFER_BIT);
1220   
1221    buffer->Bind();
1222    buffer->EnableTextureTarget();
1223#endif
1224   
1225    // Initiate the sorting step on the GPU a full-screen quad
1226    glBegin(GL_QUADS);
1227    {
1228#ifdef notdef
1229        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,0.0f,0.0f,1.0f);
1230        glVertex2f(-1.0f,-1.0f);
1231        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),0.0f,1.0f,1.0f);
1232        glVertex2f(1.0f,-1.0f);
1233        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),float(psys_height),1.0f,0.0f);
1234        glVertex2f(1.0f,1.0f);       
1235        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,float(psys_height),0.0f,0.0f);
1236        glVertex2f(-1.0f,1.0f);   
1237#endif
1238        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,0.0f,0.0f,1.0f);
1239        glVertex2f(0.,0.);       
1240        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),0.0f,1.0f,1.0f);
1241        glVertex2f(float(psys_width), 0.);
1242        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),float(psys_height),1.0f,0.0f);
1243        glVertex2f(float(psys_width), float(psys_height));   
1244        glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,float(psys_height),0.0f,0.0f);
1245        glVertex2f(0., float(psys_height));       
1246    }
1247    glEnd();
1248
1249    // switch off sorting shader
1250    oddevenMergeSort.release();
1251
1252    //buffer->DisableTextureTarget();
1253
1254    //assert(glGetError()==0);
1255}
1256#endif
1257
1258
1259void
1260draw_3d_axis()
1261{
1262    glDisable(GL_TEXTURE_2D);
1263    glEnable(GL_DEPTH_TEST);
1264   
1265    //draw axes
1266    GLUquadric *obj;
1267
1268    obj = gluNewQuadric();
1269   
1270    glDepthFunc(GL_LESS);
1271    glEnable(GL_COLOR_MATERIAL);
1272    glEnable(GL_DEPTH_TEST);
1273    glDisable(GL_BLEND);
1274   
1275    int segments = 50;
1276   
1277    glColor3f(0.8, 0.8, 0.8);
1278    glPushMatrix();
1279    glTranslatef(0.4, 0., 0.);
1280    glRotatef(90, 1, 0, 0);
1281    glRotatef(180, 0, 1, 0);
1282    glScalef(0.0005, 0.0005, 0.0005);
1283    glutStrokeCharacter(GLUT_STROKE_ROMAN, 'x');
1284    glPopMatrix();     
1285   
1286    glPushMatrix();
1287    glTranslatef(0., 0.4, 0.);
1288    glRotatef(90, 1, 0, 0);
1289    glRotatef(180, 0, 1, 0);
1290    glScalef(0.0005, 0.0005, 0.0005);
1291    glutStrokeCharacter(GLUT_STROKE_ROMAN, 'y');
1292    glPopMatrix();     
1293   
1294    glPushMatrix();
1295    glTranslatef(0., 0., 0.4);
1296    glRotatef(90, 1, 0, 0);
1297    glRotatef(180, 0, 1, 0);
1298    glScalef(0.0005, 0.0005, 0.0005);
1299    glutStrokeCharacter(GLUT_STROKE_ROMAN, 'z');
1300    glPopMatrix();     
1301   
1302    glEnable(GL_LIGHTING);
1303    glEnable(GL_LIGHT0);
1304   
1305    //glColor3f(0.2, 0.2, 0.8);
1306    glPushMatrix();
1307    glutSolidSphere(0.02, segments, segments );
1308    glPopMatrix();
1309   
1310    glPushMatrix();
1311    glRotatef(-90, 1, 0, 0);   
1312    gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments);
1313    glPopMatrix();     
1314   
1315    glPushMatrix();
1316    glTranslatef(0., 0.3, 0.);
1317    glRotatef(-90, 1, 0, 0);   
1318    gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments);
1319    glPopMatrix();     
1320   
1321    glPushMatrix();
1322    glRotatef(90, 0, 1, 0);
1323    gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments);
1324    glPopMatrix();     
1325   
1326    glPushMatrix();
1327    glTranslatef(0.3, 0., 0.);
1328    glRotatef(90, 0, 1, 0);     
1329    gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments);
1330    glPopMatrix();     
1331   
1332    glPushMatrix();
1333    gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments);
1334    glPopMatrix();     
1335   
1336    glPushMatrix();
1337    glTranslatef(0., 0., 0.3);
1338    gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments);
1339    glPopMatrix();     
1340   
1341    glDisable(GL_LIGHTING);
1342    glDisable(GL_DEPTH_TEST);
1343    gluDeleteQuadric(obj);
1344   
1345    glEnable(GL_TEXTURE_2D);
1346    glDisable(GL_DEPTH_TEST);
1347}
1348
1349#ifdef notdef
1350void
1351draw_axis()
1352{
1353    glDisable(GL_TEXTURE_2D);
1354    glEnable(GL_DEPTH_TEST);
1355   
1356    //red x
1357    glColor3f(1,0,0);
1358    glBegin(GL_LINES);
1359    {
1360        glVertex3f(0,0,0);
1361        glVertex3f(1.5,0,0);
1362    }
1363    glEnd();
1364   
1365    //blue y
1366    glColor3f(0,0,1);
1367    glBegin(GL_LINES);
1368    {
1369        glVertex3f(0,0,0);
1370        glVertex3f(0,1.5,0);
1371    }
1372    glEnd();
1373   
1374    //green z
1375    glColor3f(0,1,0);
1376    glBegin(GL_LINES);
1377    {
1378        glVertex3f(0,0,0);
1379        glVertex3f(0,0,1.5);
1380    }
1381    glEnd();
1382   
1383    glEnable(GL_TEXTURE_2D);
1384    glDisable(GL_DEPTH_TEST);
1385}
1386#endif
1387
1388void NanoVis::update()
1389{
1390    if (vol_renderer->_volumeInterpolator->is_started()) {
1391        struct timeval clock;
1392        gettimeofday(&clock, NULL);
1393        double elapsed_time;
1394
1395        elapsed_time = clock.tv_sec + clock.tv_usec/1000000.0 -
1396            vol_renderer->_volumeInterpolator->getStartTime();
1397       
1398        Trace("%lf %lf\n", elapsed_time, vol_renderer->_volumeInterpolator->getInterval());
1399        float fraction;
1400        float f;
1401
1402        f = fmod((float) elapsed_time, (float)vol_renderer->_volumeInterpolator->getInterval());
1403        if (f == 0.0) {
1404            fraction = 0.0f;
1405        } else {
1406            fraction = f / vol_renderer->_volumeInterpolator->getInterval();
1407        }
1408        Trace("fraction : %f\n", fraction);
1409        vol_renderer->_volumeInterpolator->update(fraction);
1410    }
1411}
1412
1413void
1414NanoVis::SetVolumeRanges()
1415{
1416    double xMin, xMax, yMin, yMax, zMin, zMax, wMin, wMax;
1417   
1418    xMin = yMin = zMin = wMin = DBL_MAX;
1419    xMax = yMax = zMax = wMax = -DBL_MAX;
1420    for (unsigned int i = 0; i < volume.size(); i++) {
1421        Volume *volPtr;
1422       
1423        volPtr = volume[i];
1424        if (volPtr == NULL) {
1425            continue;
1426        }
1427        if (!volPtr->enabled) {
1428            continue;
1429        }
1430        if (xMin > volPtr->xAxis.Min()) {
1431            xMin = volPtr->xAxis.Min();
1432        }
1433        if (xMax < volPtr->xAxis.Max()) {
1434            xMax = volPtr->xAxis.Max();
1435        }
1436        if (yMin > volPtr->yAxis.Min()) {
1437            yMin = volPtr->yAxis.Min();
1438        }
1439        if (yMax < volPtr->yAxis.Max()) {
1440            yMax = volPtr->yAxis.Max();
1441        }
1442        if (zMin > volPtr->zAxis.Min()) {
1443            zMin = volPtr->zAxis.Min();
1444        }
1445        if (zMax < volPtr->zAxis.Max()) {
1446            zMax = volPtr->zAxis.Max();
1447        }
1448        if (wMin > volPtr->wAxis.Min()) {
1449            wMin = volPtr->wAxis.Min();
1450        }
1451        if (wMax < volPtr->wAxis.Max()) {
1452            wMax = volPtr->wAxis.Max();
1453        }
1454    }
1455    if ((xMin < DBL_MAX) && (xMax > -DBL_MAX)) {
1456        grid->xAxis.SetScale(xMin, xMax);
1457    }
1458    if ((yMin < DBL_MAX) && (yMax > -DBL_MAX)) {
1459        grid->yAxis.SetScale(yMin, yMax);
1460    }
1461    if ((zMin < DBL_MAX) && (zMax > -DBL_MAX)) {
1462        grid->zAxis.SetScale(zMin, zMax);
1463    }
1464    if ((wMin < DBL_MAX) && (wMax > -DBL_MAX)) {
1465        Volume::valueMin = wMin;
1466        Volume::valueMax = wMax;
1467    }
1468    Volume::update_pending = false;
1469}
1470
1471void
1472NanoVis::SetHeightmapRanges()
1473{
1474    double xMin, xMax, yMin, yMax, zMin, zMax, wMin, wMax;
1475   
1476    xMin = yMin = zMin = wMin = DBL_MAX;
1477    xMax = yMax = zMax = wMax = -DBL_MAX;
1478    for (unsigned int i = 0; i < heightMap.size(); i++) {
1479        HeightMap *hmPtr;
1480       
1481        hmPtr = heightMap[i];
1482        if (hmPtr == NULL) {
1483            continue;
1484        }
1485        if (xMin > hmPtr->xAxis.Min()) {
1486            xMin = hmPtr->xAxis.Min();
1487        }
1488        if (xMax < hmPtr->xAxis.Max()) {
1489            xMax = hmPtr->xAxis.Max();
1490        }
1491        if (yMin > hmPtr->yAxis.Min()) {
1492            yMin = hmPtr->yAxis.Min();
1493        }
1494        if (yMax < hmPtr->yAxis.Max()) {
1495            yMax = hmPtr->yAxis.Max();
1496        }
1497        if (zMin > hmPtr->zAxis.Min()) {
1498            zMin = hmPtr->zAxis.Min();
1499        }
1500        if (zMax < hmPtr->zAxis.Max()) {
1501            zMax = hmPtr->zAxis.Max();
1502        }
1503        if (wMin > hmPtr->wAxis.Min()) {
1504            wMin = hmPtr->wAxis.Min();
1505        }
1506        if (wMax < hmPtr->wAxis.Max()) {
1507            wMax = hmPtr->wAxis.Max();
1508        }
1509    }
1510    if ((xMin < DBL_MAX) && (xMax > -DBL_MAX)) {
1511        grid->xAxis.SetScale(xMin, xMax);
1512    }
1513    if ((yMin < DBL_MAX) && (yMax > -DBL_MAX)) {
1514        grid->yAxis.SetScale(yMin, yMax);
1515    }
1516    if ((zMin < DBL_MAX) && (zMax > -DBL_MAX)) {
1517        grid->zAxis.SetScale(zMin, zMax);
1518    }
1519    if ((wMin < DBL_MAX) && (wMax > -DBL_MAX)) {
1520        HeightMap::valueMin = wMin;
1521        HeightMap::valueMax = wMax;
1522    }
1523    HeightMap::update_pending = false;
1524}
1525
1526/*----------------------------------------------------*/
1527void
1528NanoVis::display()
1529{
1530    //assert(glGetError()==0);
1531    if (HeightMap::update_pending) {
1532        SetHeightmapRanges();
1533    }
1534    if (Volume::update_pending) {
1535        SetVolumeRanges();
1536    }
1537    //start final rendering
1538    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear screen
1539
1540    if (volume_mode) {
1541        //3D rendering mode
1542        glEnable(GL_TEXTURE_2D);
1543        glEnable(GL_DEPTH_TEST);
1544       
1545        //camera setting activated
1546        cam->activate();
1547       
1548        //set up the orientation of items in the scene.
1549        glPushMatrix();
1550        switch (updir) {
1551        case 1:  // x
1552            glRotatef(90, 0, 0, 1);
1553            glRotatef(90, 1, 0, 0);
1554            break;
1555
1556        case 2:  // y
1557            // this is the default
1558            break;
1559           
1560        case 3:  // z
1561            glRotatef(-90, 1, 0, 0);
1562            glRotatef(-90, 0, 0, 1);
1563            break;
1564           
1565        case -1:  // -x
1566            glRotatef(-90, 0, 0, 1);
1567            break;
1568           
1569        case -2:  // -y
1570            glRotatef(180, 0, 0, 1);
1571            glRotatef(-90, 0, 1, 0);
1572            break;
1573           
1574        case -3:  // -z
1575            glRotatef(90, 1, 0, 0);
1576            break;
1577        }
1578       
1579        // TBD : This will be removed after being sure that all the functions work well.
1580        //glPushMatrix();
1581       
1582        //now render things in the scene
1583        if (axis_on) {
1584            draw_3d_axis();
1585        }
1586        if (grid->isVisible()) {
1587            grid->render();
1588        }
1589        if (licRenderer && licRenderer->isActivated()) {
1590            licRenderer->render();
1591        }
1592        if (particleRenderer && particleRenderer->isActivated()) {
1593            particleRenderer->render();
1594        }
1595        //soft_display_verts();
1596        //perf->enable();
1597        //perf->disable();
1598        //fprintf(stderr, "particle pixels: %d\n", perf->get_pixel_count());
1599        //perf->reset();
1600       
1601        //perf->enable();
1602        vol_renderer->render_all();
1603        //perf->disable();
1604       
1605        for (unsigned int i = 0; i < heightMap.size(); ++i) {
1606            if (heightMap[i]->isVisible()) {
1607                heightMap[i]->render(renderContext);
1608            }
1609        }
1610        glPopMatrix();
1611   } else {
1612        //2D rendering mode
1613        perf->enable();
1614        plane_render->render();
1615        perf->disable();
1616    }
1617
1618#ifdef XINETD
1619    float cost  = perf->get_pixel_count();
1620    write(3, &cost, sizeof(cost));
1621#endif
1622    perf->reset();
1623
1624}
1625
1626#ifndef XINETD
1627void
1628NanoVis::mouse(int button, int state, int x, int y)
1629{
1630    if(button==GLUT_LEFT_BUTTON){
1631        if (state==GLUT_DOWN) {
1632            left_last_x = x;
1633            left_last_y = y;
1634            left_down = true;
1635            right_down = false;
1636        } else {
1637            left_down = false;
1638            right_down = false;
1639        }
1640    } else {
1641        //fprintf(stderr, "right mouse\n");
1642
1643        if(state==GLUT_DOWN){
1644            //fprintf(stderr, "right mouse down\n");
1645            right_last_x = x;
1646            right_last_y = y;
1647            left_down = false;
1648            right_down = true;
1649        } else {
1650            //fprintf(stderr, "right mouse up\n");
1651            left_down = false;
1652            right_down = false;
1653        }
1654    }
1655}
1656
1657void
1658NanoVis::update_rot(int delta_x, int delta_y)
1659{
1660    live_rot_x += delta_x;
1661    live_rot_y += delta_y;
1662   
1663    if (live_rot_x > 360.0) {
1664        live_rot_x -= 360.0;   
1665    } else if(live_rot_x < -360.0) {
1666        live_rot_x += 360.0;
1667    }
1668    if (live_rot_y > 360.0) {
1669        live_rot_y -= 360.0;   
1670    } else if(live_rot_y < -360.0) {
1671        live_rot_y += 360.0;
1672    }
1673    cam->rotate(live_rot_x, live_rot_y, live_rot_z);
1674}
1675
1676void
1677NanoVis::update_trans(int delta_x, int delta_y, int delta_z)
1678{
1679    live_obj_x += delta_x*0.03;
1680    live_obj_y += delta_y*0.03;
1681    live_obj_z += delta_z*0.03;
1682}
1683
1684void
1685NanoVis::keyboard(unsigned char key, int x, int y)
1686{
1687   bool log = false;
1688
1689   switch (key) {
1690   case 'q':
1691       exit(0);
1692       break;
1693   case '+':
1694       lic_slice_z+=0.05;
1695       lic->set_offset(lic_slice_z);
1696       break;
1697   case '-':
1698       lic_slice_z-=0.05;
1699       lic->set_offset(lic_slice_z);
1700       break;
1701   case ',':
1702       lic_slice_x+=0.05;
1703       //init_particles();
1704       break;
1705   case '.':
1706       lic_slice_x-=0.05;
1707       //init_particles();
1708       break;
1709   case '1':
1710       //advect = true;
1711       break;
1712   case '2':
1713       //psys_x+=0.05;
1714       break;
1715   case '3':
1716       //psys_x-=0.05;
1717       break;
1718   case 'w': //zoom out
1719       live_obj_z-=0.05;
1720       log = true;
1721       cam->move(live_obj_x, live_obj_y, live_obj_z);
1722       break;
1723   case 's': //zoom in
1724       live_obj_z+=0.05;
1725       log = true;
1726       cam->move(live_obj_x, live_obj_y, live_obj_z);
1727       break;
1728   case 'a': //left
1729       live_obj_x-=0.05;
1730       log = true;
1731       cam->move(live_obj_x, live_obj_y, live_obj_z);
1732       break;
1733   case 'd': //right
1734       live_obj_x+=0.05;
1735       log = true;
1736       cam->move(live_obj_x, live_obj_y, live_obj_z);
1737       break;
1738   case 'i':
1739       //init_particles();
1740       break;
1741   case 'v':
1742       vol_renderer->switch_volume_mode();
1743       break;
1744   case 'b':
1745       vol_renderer->switch_slice_mode();
1746       break;
1747   case 'n':
1748       resize_offscreen_buffer(win_width*2, win_height*2);
1749       break;
1750   case 'm':
1751       resize_offscreen_buffer(win_width/2, win_height/2);
1752       break;
1753   default:
1754       break;
1755   }   
1756#ifdef EVENTLOG
1757   if(log){
1758       float param[3] = {live_obj_x, live_obj_y, live_obj_z};
1759       Event* tmp = new Event(EVENT_MOVE, param, NvGetTimeInterval());
1760       tmp->write(event_log);
1761       delete tmp;
1762   }
1763#endif
1764}
1765
1766void
1767NanoVis::motion(int x, int y)
1768{
1769    int old_x, old_y;   
1770
1771    if(left_down){
1772        old_x = left_last_x;
1773        old_y = left_last_y;   
1774    } else if(right_down){
1775        old_x = right_last_x;
1776        old_y = right_last_y;   
1777    }
1778   
1779    int delta_x = x - old_x;
1780    int delta_y = y - old_y;
1781   
1782    //more coarse event handling
1783    //if(abs(delta_x)<10 && abs(delta_y)<10)
1784    //return;
1785   
1786    if(left_down){
1787        left_last_x = x;
1788        left_last_y = y;
1789       
1790        update_rot(-delta_y, -delta_x);
1791    } else if (right_down){
1792        //fprintf(stderr, "right mouse motion (%d,%d)\n", x, y);
1793       
1794        right_last_x = x;
1795        right_last_y = y;
1796       
1797        update_trans(0, 0, delta_x);
1798    }
1799   
1800#ifdef EVENTLOG
1801    float param[3] = {live_rot_x, live_rot_y, live_rot_z};
1802    Event* tmp = new Event(EVENT_ROTATE, param, NvGetTimeInterval());
1803    tmp->write(event_log);
1804    delete tmp;
1805#endif
1806    glutPostRedisplay();
1807}
1808
1809#endif /*XINETD*/
1810
1811#ifdef notdef
1812
1813#ifdef XINETD
1814void
1815init_service()
1816{
1817    //open log and map stderr to log file
1818    xinetd_log = fopen("/tmp/log.txt", "w");
1819    close(2);
1820    dup2(fileno(xinetd_log), 2);
1821    dup2(2,1);
1822   
1823    //flush junk
1824    fflush(stdout);
1825    fflush(stderr);
1826}
1827
1828void
1829end_service()
1830{
1831    //close log file
1832    fclose(xinetd_log);
1833}
1834#endif  /*XINETD*/
1835
1836void
1837init_event_log()
1838{
1839    event_log = fopen("event.txt", "w");
1840    assert(event_log!=0);
1841   
1842    struct timeval time;
1843    gettimeofday(&time, NULL);
1844    cur_time = time.tv_sec*1000. + time.tv_usec/1000.;
1845}
1846
1847void
1848end_event_log()
1849{
1850    fclose(event_log);
1851}
1852
1853double
1854get_time_interval()
1855{
1856    struct timeval time;
1857    gettimeofday(&time, NULL);
1858    double new_time = time.tv_sec*1000. + time.tv_usec/1000.;
1859   
1860    double interval = new_time - cur_time;
1861    cur_time = new_time;
1862    return interval;
1863}
1864#endif
1865
1866void removeAllData()
1867{
1868    //
1869}
1870
1871
1872/*----------------------------------------------------*/
1873int
1874main(int argc, char** argv)
1875{
1876
1877    char *path;
1878    path = NULL;
1879    while(1) {
1880        int c;
1881        int option_index = 0;
1882        struct option long_options[] = {
1883            // name, has_arg, flag, val
1884            { 0,0,0,0 },
1885        };
1886
1887        c = getopt_long(argc, argv, "+p:", long_options, &option_index);
1888        if (c == -1) {
1889            break;
1890        }
1891        switch(c) {
1892        case 'p':
1893            path = optarg;
1894            break;
1895        default:
1896            fprintf(stderr,"Don't know what option '%c'.\n", c);
1897            return 1;
1898        }
1899    }
1900
1901    R2FilePath::getInstance()->setWorkingDirectory(argc, (const char**) argv);
1902   
1903#ifdef XINETD
1904    signal(SIGPIPE,SIG_IGN);
1905    NvInitService();
1906#endif
1907   
1908    glutInit(&argc, argv);
1909    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
1910   
1911    glutInitWindowSize(NanoVis::win_width, NanoVis::win_height);
1912   
1913    glutInitWindowPosition(10, 10);
1914    render_window = glutCreateWindow(argv[0]);
1915    glutDisplayFunc(NanoVis::display);
1916   
1917#ifndef XINETD
1918    glutMouseFunc(NanoVis::mouse);
1919    glutMotionFunc(NanoVis::motion);
1920    glutKeyboardFunc(NanoVis::keyboard);
1921#endif
1922   
1923    glutIdleFunc(idle);
1924    glutReshapeFunc(NanoVis::resize_offscreen_buffer);
1925   
1926    NanoVis::init(path);
1927    NanoVis::initGL();
1928    initTcl();
1929   
1930#ifdef EVENTLOG
1931    NvInitEventLog();
1932#endif
1933    //event loop
1934    glutMainLoop();
1935   
1936    removeAllData();
1937   
1938    NvExit();
1939   
1940    return 0;
1941}
1942
Note: See TracBrowser for help on using the repository browser.