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

Last change on this file since 1049 was 1028, checked in by gah, 16 years ago

various cleanups

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