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

Last change on this file since 915 was 915, checked in by gah, 15 years ago

more clean up

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