source: trunk/gui/vizservers/nanovis/nanovis.cpp @ 420

Last change on this file since 420 was 418, checked in by qiaow, 18 years ago

Minor fixes.

File size: 49.4 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 * Nanovis: Visualization of Nanoelectronics Data
4 *
5 * ======================================================================
6 *  AUTHOR:  Wei Qiao <qiaow@purdue.edu>
7 *           Purdue Rendering and Perceptualization Lab (PURPL)
8 *
9 *  Copyright (c) 2004-2006  Purdue Research Foundation
10 *
11 *  See the file "license.terms" for information on usage and
12 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * ======================================================================
14 */
15
16#include <stdio.h>
17#include <math.h>
18#include <fstream>
19#include <iostream>
20#include <string>
21#include <sys/time.h>
22
23#include "nanovis.h"
24#include "RpFieldRect3D.h"
25#include "RpFieldPrism3D.h"
26
27//transfer function headers
28#include "transfer-function/TransferFunctionMain.h"
29#include "transfer-function/ControlPoint.h"
30#include "transfer-function/TransferFunctionGLUTWindow.h"
31#include "transfer-function/ColorGradientGLUTWindow.h"
32#include "transfer-function/ColorPaletteWindow.h"
33#include "transfer-function/MainWindow.h"
34
35//render server
36
37VolumeRenderer* vol_render;
38Camera* cam;
39
40float color_table[256][4];     
41
42#ifdef XINETD
43FILE* xinetd_log;
44#endif
45
46FILE* event_log;
47//log
48void init_event_log();
49void end_event_log();
50double cur_time;        //in seconds
51double get_time_interval();
52
53int render_window;              //the handle of the render window;
54// forward declarations
55void init_particles();
56void get_slice_vectors();
57
58ParticleSystem* psys;
59float psys_x=0.4, psys_y=0, psys_z=0;
60
61Lic* lic;
62
63unsigned char* screen_buffer = new unsigned char[3*win_width*win_height+1];     //buffer to store data read from the screen
64NVISid final_fbo, final_color_tex, final_depth_rb;      //frame buffer for final rendering
65NVISid vel_fbo, slice_vector_tex;       //for projecting 3d vector to 2d vector on a plane
66
67bool advect=false;
68float vert[NMESH*NMESH*3];              //particle positions in main memory
69float slice_vector[NMESH*NMESH*4];      //per slice vectors in main memory
70
71int n_volumes = 0;
72Volume* volume[MAX_N_VOLUMES];          //point to volumes, currently handle up to 10 volumes
73TransferFunction* tf[MAX_N_VOLUMES];    //transfer functions, currently handle up to 10 colormaps
74
75PerfQuery* perf;                        //perfromance counter
76
77//Nvidia CG shaders and their parameters
78CGcontext g_context;
79
80CGprogram m_passthru_fprog;
81CGparameter m_passthru_scale_param, m_passthru_bias_param;
82
83CGprogram m_copy_texcoord_fprog;
84
85CGprogram m_one_volume_fprog;
86CGparameter m_vol_one_volume_param;
87CGparameter m_tf_one_volume_param;
88CGparameter m_mvi_one_volume_param;
89CGparameter m_mv_one_volume_param;
90CGparameter m_render_param_one_volume_param;
91
92CGprogram m_vert_std_vprog;
93CGparameter m_mvp_vert_std_param;
94CGparameter m_mvi_vert_std_param;
95
96using namespace std;
97
98static void set_camera(float x_angle, float y_angle, float z_angle){
99  live_rot_x = x_angle;
100  live_rot_y = y_angle;
101  live_rot_z = z_angle;
102}
103
104
105// Tcl interpreter for incoming messages
106static Tcl_Interp *interp;
107
108static int CameraCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
109static int ClearCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
110static int SizeCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
111static int OutlineCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
112static int CutCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
113static int HelloCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
114static int LoadCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
115static int RefreshCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
116static int MoveCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]));
117
118//Tcl callback functions
119static int
120CameraCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])
121{
122
123        fprintf(stderr, "camera cmd\n");
124        double x, y, z;
125
126        if (argc != 4) {
127                Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
128                        " x_angle y_angle z_angle\"", (char*)NULL);
129                return TCL_ERROR;
130        }
131        if (Tcl_GetDouble(interp, argv[1], &x) != TCL_OK) {
132                return TCL_ERROR;
133        }
134        if (Tcl_GetDouble(interp, argv[2], &y) != TCL_OK) {
135                return TCL_ERROR;
136        }
137        if (Tcl_GetDouble(interp, argv[3], &z) != TCL_OK) {
138                return TCL_ERROR;
139        }
140        set_camera(x, y, z);
141        return TCL_OK;
142}
143
144
145static int
146RefreshCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])
147{
148  fprintf(stderr, "refresh cmd\n");
149  return TCL_OK;
150}
151
152void set_object(float x, float y, float z){
153  live_obj_x = x;
154  live_obj_y = y;
155  live_obj_z = z;
156}
157
158
159static int
160MoveCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])
161{
162
163        fprintf(stderr, "move cmd\n");
164        double x, y, z;
165
166        if (argc != 4) {
167                Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
168                        " x_angle y_angle z_angle\"", (char*)NULL);
169                return TCL_ERROR;
170        }
171        if (Tcl_GetDouble(interp, argv[1], &x) != TCL_OK) {
172                return TCL_ERROR;
173        }
174        if (Tcl_GetDouble(interp, argv[2], &y) != TCL_OK) {
175                return TCL_ERROR;
176        }
177        if (Tcl_GetDouble(interp, argv[3], &z) != TCL_OK) {
178                return TCL_ERROR;
179        }
180        set_object(x, y, z);
181        return TCL_OK;
182}
183
184
185static int
186HelloCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])
187{
188        //send back 4 bytes as confirmation
189        char ack[4]="ACK";
190        fprintf(stderr, "wrote %d\n", write(fileno(stdout), ack, 4));
191        fflush(stdout);
192        return TCL_OK;
193}
194
195//report errors related to CG shaders
196void cgErrorCallback(void)
197{
198    CGerror lastError = cgGetError();
199    if(lastError) {
200        const char *listing = cgGetLastListing(g_context);
201        printf("\n---------------------------------------------------\n");
202        printf("%s\n\n", cgGetErrorString(lastError));
203        printf("%s\n", listing);
204        printf("-----------------------------------------------------\n");
205        printf("Cg error, exiting...\n");
206        cgDestroyContext(g_context);
207        exit(-1);
208    }
209}
210
211
212void init_glew(){
213        GLenum err = glewInit();
214        if (GLEW_OK != err)
215        {
216                //glew init failed, exit.
217                fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
218                getchar();
219                assert(false);
220        }
221
222        fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
223}
224
225
226void load_volume(int index, int width, int height, int depth, int n_component, float* data);
227
228/* Load a 3D vector field from a dx-format file
229 */
230void
231load_vector_file(int index, char *fname) {
232    int dummy, nx, ny, nz, nxy, npts;
233    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
234    char line[128], type[128], *start;
235    std::ifstream fin(fname);
236
237    do {
238        fin.getline(line,sizeof(line)-1);
239        for (start=&line[0]; *start == ' ' || *start == '\t'; start++)
240            ;  // skip leading blanks
241
242        if (*start != '#') {  // skip comment lines
243            if (sscanf(start, "object %d class gridpositions counts %d %d %d", &dummy, &nx, &ny, &nz) == 4) {
244                // found grid size
245            }
246            else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
247                // found origin
248            }
249            else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
250                // found one of the delta lines
251                if (ddx != 0.0) { dx = ddx; }
252                else if (ddy != 0.0) { dy = ddy; }
253                else if (ddz != 0.0) { dz = ddz; }
254            }
255            else if (sscanf(start, "object %d class array type %s shape 3 rank 1 items %d data follows", &dummy, type, &npts) == 3) {
256                if (npts != nx*ny*nz) {
257                    std::cerr << "inconsistent data: expected " << nx*ny*nz << " points but found " << npts << " points" << std::endl;
258                    return;
259                }
260                break;
261            }
262        }
263    } while (!fin.eof());
264
265    // read data points
266    if (!fin.eof()) {
267        Rappture::Mesh1D xgrid(x0, x0+nx*dx, nx);
268        Rappture::Mesh1D ygrid(y0, y0+ny*dy, ny);
269        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
270        Rappture::FieldRect3D xfield(xgrid, ygrid, zgrid);
271        Rappture::FieldRect3D yfield(xgrid, ygrid, zgrid);
272        Rappture::FieldRect3D zfield(xgrid, ygrid, zgrid);
273
274        double vx, vy, vz;
275        int nread = 0;
276        for (int ix=0; ix < nx; ix++) {
277            for (int iy=0; iy < ny; iy++) {
278                for (int iz=0; iz < nz; iz++) {
279                    if (fin.eof() || nread > npts) {
280                        break;
281                    }
282                    fin.getline(line,sizeof(line)-1);
283                    if (sscanf(line, "%lg %lg %lg", &vx, &vy, &vz) == 3) {
284                        int nindex = iz*nx*ny + iy*nx + ix;
285                        xfield.define(nindex, vx);
286                        yfield.define(nindex, vy);
287                        zfield.define(nindex, vz);
288                        nread++;
289                    }
290                }
291            }
292        }
293
294        // make sure that we read all of the expected points
295        if (nread != nx*ny*nz) {
296            std::cerr << "inconsistent data: expected " << nx*ny*nz << " points but found " << nread << " points" << std::endl;
297            return;
298        }
299
300        // figure out a good mesh spacing
301        int nsample = 30;
302        dx = xfield.rangeMax(Rappture::xaxis) - xfield.rangeMin(Rappture::xaxis);
303        dy = xfield.rangeMax(Rappture::yaxis) - xfield.rangeMin(Rappture::yaxis);
304        dz = xfield.rangeMax(Rappture::zaxis) - xfield.rangeMin(Rappture::zaxis);
305        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
306
307        nx = (int)ceil(dx/dmin);
308        ny = (int)ceil(dy/dmin);
309        nz = (int)ceil(dz/dmin);
310
311#ifndef NV40
312        nx = pow(2.0, ceil(log10((double)nx)/log10(2.0)));  // must be an even power of 2
313        ny = pow(2.0, ceil(log10((double)ny)/log10(2.0)));
314        nz = pow(2.0, ceil(log10((double)nz)/log10(2.0)));
315#endif
316
317        float *data = new float[3*nx*ny*nz];
318
319        std::cout << "generating " << nx << "x" << ny << "x" << nz << " = " << nx*ny*nz << " points" << std::endl;
320
321        // generate the uniformly sampled data that we need for a volume
322        double vmin = 0.0;
323        double vmax = 0.0;
324        int ngen = 0;
325        for (int iz=0; iz < nz; iz++) {
326            double zval = z0 + iz*dmin;
327            for (int iy=0; iy < ny; iy++) {
328                double yval = y0 + iy*dmin;
329                for (int ix=0; ix < nx; ix++) {
330                    double xval = x0 + ix*dmin;
331
332                    vx = xfield.value(xval,yval,zval);
333                    vy = yfield.value(xval,yval,zval);
334                    vz = zfield.value(xval,yval,zval);
335                    //vx = 1;
336                    //vy = 1;
337                    vz = 0;
338                    double vm = sqrt(vx*vx + vy*vy + vz*vz);
339
340                    if (vm < vmin) { vmin = vm; }
341                    if (vm > vmax) { vmax = vm; }
342
343                    data[ngen++] = vx;
344                    data[ngen++] = vy;
345                    data[ngen++] = vz;
346                }
347            }
348        }
349
350        ngen = 0;
351        for (ngen=0; ngen < npts; ngen++) {
352            data[ngen] = (data[ngen]/(2.0*vmax) + 0.5);
353        }
354
355        load_volume(index, nx, ny, nz, 3, data);
356        delete [] data;
357    } else {
358        std::cerr << "WARNING: data not found in file " << fname << std::endl;
359    }
360}
361
362
363/* Load a 3D volume from a dx-format file
364 */
365void
366load_volume_file(int index, char *fname) {
367    Rappture::MeshTri2D xymesh;
368    int dummy, nx, ny, nz, nxy, npts;
369    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
370    char line[128], type[128], *start;
371    std::ifstream fin(fname);
372
373    int isrect = 1;
374
375    do {
376        fin.getline(line,sizeof(line)-1);
377        for (start=&line[0]; *start == ' ' || *start == '\t'; start++)
378            ;  // skip leading blanks
379
380        if (*start != '#') {  // skip comment lines
381            if (sscanf(start, "object %d class gridpositions counts %d %d %d", &dummy, &nx, &ny, &nz) == 4) {
382                // found grid size
383                isrect = 1;
384            }
385            else if (sscanf(start, "object %d class array type float rank 1 shape 3 items %d data follows", &dummy, &nxy) == 2) {
386                isrect = 0;
387                double xx, yy, zz;
388                for (int i=0; i < nxy; i++) {
389                    fin.getline(line,sizeof(line)-1);
390                    if (sscanf(line, "%lg %lg %lg", &xx, &yy, &zz) == 3) {
391                        xymesh.addNode( Rappture::Node2D(xx,yy) );
392                    }
393                }
394
395                std::ofstream ftmp("tmppts");
396                // save corners of bounding box first, to work around meshing
397                // problems in voronoi utility
398                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
399                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
400                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
401                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
402                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
403                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
404                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
405                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
406                for (int i=0; i < nxy; i++) {
407                    ftmp << xymesh.atNode(i).x() << " " << xymesh.atNode(i).y() << std::endl;
408                }
409                ftmp.close();
410
411                if (system("voronoi -t < tmppts > tmpcells") == 0) {
412                    int cx, cy, cz;
413                    std::ifstream ftri("tmpcells");
414                    while (!ftri.eof()) {
415                        ftri.getline(line,sizeof(line)-1);
416                        if (sscanf(line, "%d %d %d", &cx, &cy, &cz) == 3) {
417                            if (cx >= 4 && cy >= 4 && cz >= 4) {
418                                // skip first 4 boundary points
419                                xymesh.addCell(cx-4, cy-4, cz-4);
420                            }
421                        }
422                    }
423                    ftri.close();
424                } else {
425                    std::cerr << "WARNING: triangularization failed" << std::endl;
426                }
427            }
428            else if (sscanf(start, "object %d class regulararray count %d", &dummy, &nz) == 2) {
429                // found z-grid
430            }
431            else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
432                // found origin
433            }
434            else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
435                // found one of the delta lines
436                if (ddx != 0.0) { dx = ddx; }
437                else if (ddy != 0.0) { dy = ddy; }
438                else if (ddz != 0.0) { dz = ddz; }
439            }
440            else if (sscanf(start, "object %d class array type %s rank 0 items %d data follows", &dummy, type, &npts) == 3) {
441                if (isrect && (npts != nx*ny*nz)) {
442                    std::cerr << "inconsistent data: expected " << nx*ny*nz << " points but found " << npts << " points" << std::endl;
443                    return;
444                }
445                else if (!isrect && (npts != nxy*nz)) {
446                    std::cerr << "inconsistent data: expected " << nxy*nz << " points but found " << npts << " points" << std::endl;
447                    return;
448                }
449                break;
450            }
451        }
452    } while (!fin.eof());
453
454    // read data points
455    if (!fin.eof()) {
456        if (isrect) {
457            Rappture::Mesh1D xgrid(x0, x0+nx*dx, nx);
458            Rappture::Mesh1D ygrid(y0, y0+ny*dy, ny);
459            Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
460            Rappture::FieldRect3D field(xgrid, ygrid, zgrid);
461
462            double dval;
463            int nread = 0;
464            for (int ix=0; ix < nx; ix++) {
465                for (int iy=0; iy < ny; iy++) {
466                    for (int iz=0; iz < nz; iz++) {
467                        if (fin.eof() || nread > npts) {
468                            break;
469                        }
470                        fin.getline(line,sizeof(line)-1);
471                        if (sscanf(line, "%lg", &dval) == 1) {
472                            int nindex = iz*nx*ny + iy*nx + ix;
473                            field.define(nindex, dval);
474                            nread++;
475                        }
476                    }
477                }
478            }
479
480            // make sure that we read all of the expected points
481            if (nread != nx*ny*nz) {
482                std::cerr << "inconsistent data: expected " << nx*ny*nz << " points but found " << nread << " points" << std::endl;
483                return;
484            }
485
486            // figure out a good mesh spacing
487            int nsample = 30;
488            dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
489            dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
490            dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
491            double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
492
493            nx = (int)ceil(dx/dmin);
494            ny = (int)ceil(dy/dmin);
495            nz = (int)ceil(dz/dmin);
496
497#ifndef NV40
498            nx = pow(2.0, ceil(log10((double)nx)/log10(2.0)));  // must be an even power of 2
499            ny = pow(2.0, ceil(log10((double)ny)/log10(2.0)));
500            nz = pow(2.0, ceil(log10((double)nz)/log10(2.0)));
501#endif
502
503            float *data = new float[4*nx*ny*nz];
504
505            double vmin = field.valueMin();
506            double dv = field.valueMax() - field.valueMin();
507            if (dv == 0.0) { dv = 1.0; }
508
509            std::cout << "generating " << nx << "x" << ny << "x" << nz << " = " << nx*ny*nz << " points" << std::endl;
510
511            // generate the uniformly sampled data that we need for a volume
512            int ngen = 0;
513            for (int iz=0; iz < nz; iz++) {
514                double zval = z0 + iz*dmin;
515                for (int iy=0; iy < ny; iy++) {
516                    double yval = y0 + iy*dmin;
517                    for (int ix=0; ix < nx; ix++) {
518                        double xval = x0 + ix*dmin;
519                        double v = field.value(xval,yval,zval);
520
521                        // scale all values [0-1], -1 => out of bounds
522                        v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
523                        data[ngen] = v;
524
525                        // gradient in x-direction
526                        double curval = (v < 0) ? 0.0 : v;
527                        double oldval = ((ngen/4) % nx == 0) ? 0.0 : data[ngen-4];
528                        oldval = (oldval < 0) ? 0.0 : oldval;
529                        data[ngen+1] = (curval-oldval)/dmin;
530
531                        // gradient in y-direction
532                        oldval = (ngen-4*nx >= 0) ? data[ngen-4*nx] : 0.0;
533                        oldval = (oldval < 0) ? 0.0 : oldval;
534                        data[ngen+2] = (curval-oldval)/dmin;
535
536                        // gradient in z-direction
537                        oldval = (ngen-4*nx*ny >= 0) ? data[ngen-4*nx*ny] : 0.0;
538                        oldval = (oldval < 0) ? 0.0 : oldval;
539                        data[ngen+3] = (curval-oldval)/dmin;
540                        ngen += 4;
541                    }
542                }
543            }
544
545            /*
546            //hack very first and last yz slice have 0 grad
547            for(int iz=0; iz<nz; iz++){
548              for(int iy=0; iy<ny; iy++){
549                 int index1, index2;
550                 int ix1 = 0;
551                 int ix2 = 3;
552                 index1 = ix1 + iy*nx + iz*nx*ny;
553                 index2 = ix2 + iy*nx + iz*nx*ny;
554                 data[4*index1 + 1] = data[4*index2 + 1];
555                 data[4*index1 + 2] = data[4*index2 + 2];
556                 data[4*index1 + 3] = data[4*index2 + 3];
557
558                 ix1 = nx-1;
559                 ix2 = nx-2;
560                 index1 = ix1 + iy*nx + iz*nx*ny;
561                 index2 = ix2 + iy*nx + iz*nx*ny;
562                 data[4*index1 + 1] = data[4*index2 + 1];
563                 data[4*index1 + 2] = data[4*index2 + 2];
564                 data[4*index1 + 3] = data[4*index2 + 3];
565              }
566            }
567            */
568
569            load_volume(index, nx, ny, nz, 4, data);
570            delete [] data;
571
572        } else {
573            Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
574            Rappture::FieldPrism3D field(xymesh, zgrid);
575
576            double dval;
577            int nread = 0;
578            while (!fin.eof() && nread < npts) {
579                if (!(fin >> dval).fail()) {
580                    field.define(nread++, dval);
581                }
582            }
583
584            // make sure that we read all of the expected points
585            if (nread != nxy*nz) {
586                std::cerr << "inconsistent data: expected " << nxy*nz << " points but found " << nread << " points" << std::endl;
587                return;
588            }
589
590            // figure out a good mesh spacing
591            int nsample = 30;
592            x0 = field.rangeMin(Rappture::xaxis);
593            dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
594            y0 = field.rangeMin(Rappture::yaxis);
595            dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
596            z0 = field.rangeMin(Rappture::zaxis);
597            dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
598            double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
599
600            nx = (int)ceil(dx/dmin);
601            nx = pow(2.0, ceil(log10((double)nx)/log10(2.0)));  // must be an even power of 2
602            ny = (int)ceil(dy/dmin);
603            ny = pow(2.0, ceil(log10((double)ny)/log10(2.0)));
604            nz = (int)ceil(dz/dmin);
605            nz = pow(2.0, ceil(log10((double)nz)/log10(2.0)));
606            float *data = new float[4*nx*ny*nz];
607
608            double vmin = field.valueMin();
609            double dv = field.valueMax() - field.valueMin();
610            if (dv == 0.0) { dv = 1.0; }
611            std::cout << "generating " << nx << "x" << ny << "x" << nz << " = " << nx*ny*nz << " points" << std::endl;
612
613            // generate the uniformly sampled data that we need for a volume
614            int ngen = 0;
615            for (int iz=0; iz < nz; iz++) {
616                double zval = z0 + iz*dmin;
617                for (int iy=0; iy < ny; iy++) {
618                    double yval = y0 + iy*dmin;
619                    for (int ix=0; ix < nx; ix++) {
620                        double xval = x0 + ix*dmin;
621                        double v = field.value(xval,yval,zval);
622                        data[ngen++] = (isnan(v)) ? -1.0 : (v - vmin)/dv;
623                        data[ngen++] = 0.0;
624                        data[ngen++] = 0.0;
625                        data[ngen++] = 0.0;
626                    }
627                }
628            }
629            load_volume(index, nx, ny, nz, 4, data);
630            delete [] data;
631        }
632    } else {
633        std::cerr << "WARNING: data not found in file " << fname << std::endl;
634    }
635}
636
637/* Load a 3D volume
638 * index: the index into the volume array, which stores pointers to 3D volume instances
639 * data: pointer to an array of floats. 
640 * n_component: the number of scalars for each space point.
641 *              All component scalars for a point are placed consequtively in data array
642 * width, height and depth: number of points in each dimension
643 */
644void load_volume(int index, int width, int height, int depth, int n_component, float* data){
645  if(volume[index]!=0){
646    delete volume[index];
647    volume[index]=0;
648  }
649
650  volume[index] = new Volume(0.f, 0.f, 0.f, width, height, depth, 1.,  n_component, data);
651  assert(volume[index]!=0);
652}
653
654
655//load a colormap 1D texture
656void load_transfer_function(int index, int size, float* data){
657
658  if(tf[index]!=0){
659    delete tf[index];
660    tf[index]=0;
661  }
662
663  tf[index] = new TransferFunction(size, data);
664}
665
666
667//load value from the gui, only one transfer function
668extern void update_tf_texture(){
669  glutSetWindow(render_window);
670
671  //fprintf(stderr, "tf update\n");
672  if(tf[0]==0) return;
673
674  float data[256*4];
675  for(int i=0; i<256; i++){
676    data[4*i+0] = color_table[i][0];
677    data[4*i+1] = color_table[i][1];
678    data[4*i+2] = color_table[i][2];
679    data[4*i+3] = color_table[i][3];
680    //fprintf(stderr, "(%f,%f,%f,%f) ", data[4*i+0], data[4*i+1], data[4*i+2], data[4*i+3]);
681  }
682
683  tf[0]->update(data);
684
685#ifdef EVENTLOG
686  float param[3] = {0,0,0};
687  Event* tmp = new Event(EVENT_ROTATE, param, get_time_interval());
688  tmp->write(event_log);
689  delete tmp;
690#endif
691}
692
693
694
695//initialize frame buffer objects for offscreen rendering
696void init_fbo(){
697
698  //initialize final fbo for final display
699  glGenFramebuffersEXT(1, &final_fbo);
700  glGenTextures(1, &final_color_tex);
701  glGenRenderbuffersEXT(1, &final_depth_rb);
702
703  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, final_fbo);
704
705  //initialize final color texture
706  glBindTexture(GL_TEXTURE_2D, final_color_tex);
707  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
708  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
709#ifdef NV40
710  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, win_width, win_height, 0,
711               GL_RGB, GL_INT, NULL);
712#else
713  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, win_width, win_height, 0,
714               GL_RGB, GL_INT, NULL);
715#endif
716  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
717                            GL_COLOR_ATTACHMENT0_EXT,
718                            GL_TEXTURE_2D, final_color_tex, 0);
719
720       
721  // initialize final depth renderbuffer
722  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, final_depth_rb);
723  glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
724                           GL_DEPTH_COMPONENT24, win_width, win_height);
725  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
726                               GL_DEPTH_ATTACHMENT_EXT,
727                               GL_RENDERBUFFER_EXT, final_depth_rb);
728
729  // Check framebuffer completeness at the end of initialization.
730  CHECK_FRAMEBUFFER_STATUS();
731  assert(glGetError()==0);
732}
733
734
735void init_cg(){
736    cgSetErrorCallback(cgErrorCallback);
737    g_context = cgCreateContext();
738
739#ifdef NEW_CG
740    m_posvel_fprog = loadProgram(g_context, CG_PROFILE_FP40, CG_SOURCE, "./shaders/update_pos_vel.cg");
741    m_posvel_timestep_param  = cgGetNamedParameter(m_posvel_fprog, "timestep");
742    m_posvel_damping_param   = cgGetNamedParameter(m_posvel_fprog, "damping");
743    m_posvel_gravity_param   = cgGetNamedParameter(m_posvel_fprog, "gravity");
744    m_posvel_spherePos_param = cgGetNamedParameter(m_posvel_fprog, "spherePos");
745    m_posvel_sphereVel_param = cgGetNamedParameter(m_posvel_fprog, "sphereVel");
746#endif
747}
748
749
750//switch shader to change render mode
751void switch_shader(int choice){
752
753  switch (choice){
754    case 0:
755      break;
756
757   case 1:
758      break;
759     
760   default:
761      break;
762  }
763}
764
765void init_particles(){
766  //random placement on a slice
767  float* data = new float[psys->psys_width * psys->psys_height * 4];
768  bzero(data, sizeof(float)*4* psys->psys_width * psys->psys_height);
769
770  for (int i=0; i<psys->psys_width; i++){
771    for (int j=0; j<psys->psys_height; j++){
772      int index = i + psys->psys_height*j;
773      bool particle = rand() % 256 > 150;
774      //particle = true;
775      if(particle) /*&& i/float(psys->psys_width)>0.3 && i/float(psys->psys_width)<0.7
776                      && j/float(psys->psys_height)>0.1 && j/float(psys->psys_height)<0.4)*/
777      {
778        //assign any location (x,y,z) in range [0,1]
779        data[4*index] = lic_slice_x;
780        data[4*index+1]= j/float(psys->psys_height);
781        data[4*index+2]= i/float(psys->psys_width);
782        data[4*index+3]= 30; //shorter life span, quicker iterations   
783      }
784      else
785      {
786        data[4*index] = 0;
787        data[4*index+1]= 0;
788        data[4*index+2]= 0;
789        data[4*index+3]= 0;     
790      }
791    }
792   }
793
794  psys->initialize((Particle*)data);
795  delete[] data;
796}
797
798
799void init_tf(){
800  float data[256*4];
801  memset(data, 0, 4*256*sizeof(float));
802
803  tf[0] = new TransferFunction(256, data);
804}
805
806
807//init line integral convolution
808void init_lic(){
809  lic = new Lic(NMESH, win_width, win_height, 0.3, g_context, volume[0]->id,
810                  volume[0]->aspect_ratio_width,
811                  volume[0]->aspect_ratio_height,
812                  volume[0]->aspect_ratio_depth);
813}
814
815/*----------------------------------------------------*/
816void initGL(void)
817{
818   system_info();
819   init_glew();
820
821   //create the camera with default setting
822   cam = new Camera(win_width, win_height,
823                   live_obj_x, live_obj_y, live_obj_z,
824                   0., 0., 100.,
825                   live_rot_x, live_rot_y, live_rot_z);
826
827   glEnable(GL_TEXTURE_2D);
828   glShadeModel(GL_FLAT);
829   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
830   glClearColor(0,0,0,1);
831   glClear(GL_COLOR_BUFFER_BIT);
832
833   //initialize lighting
834   GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
835   GLfloat mat_shininess[] = {30.0};
836   GLfloat white_light[] = {1.0, 1.0, 1.0, 1.0};
837   GLfloat green_light[] = {0.1, 0.5, 0.1, 1.0};
838
839   glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
840   glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
841   glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
842   glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);     
843   glLightfv(GL_LIGHT1, GL_DIFFUSE, green_light);
844   glLightfv(GL_LIGHT1, GL_SPECULAR, white_light);     
845
846   //init volume and colormap arrays
847   for(int i=0; i<MAX_N_VOLUMES; i++){
848     volume[i] = 0;
849     tf[i] = 0;
850   }
851
852   //check if performance query is supported
853   if(check_query_support()){
854     //create queries to count number of rendered pixels
855     perf = new PerfQuery();
856   }
857
858   //load_volume_file(0, "./data/A-apbs-2-out-potential-PE0.dx");
859   //load_volume_file(0, "./data/nw-AB-Vg=0.000-Vd=1.000-potential.dx");
860   //load_volume_file(0, "./data/test2.dx");
861
862   load_vector_file(0, "./data/J-wire-vec.dx");
863   load_volume_file(1, "./data/mu-wire-3d.dx");
864   load_volume_file(2, "./data/mu-wire-3d.dx");
865   //load_volume_file(3, "./data/mu-wire-3d.dx");
866
867   init_tf();   //initialize transfer function
868   init_fbo();  //frame buffer objects
869   init_cg();   //init cg shaders
870   init_lic();  //init line integral convolution
871
872   //create volume renderer and add volumes to it
873   vol_render = new VolumeRenderer(g_context);
874   vol_render->add_volume(volume[1], tf[0]);
875
876   volume[2]->move(Vector3(0.42, 0.1, 0.1));
877   vol_render->add_volume(volume[2], tf[0]);
878
879   //volume[3]->move(Vector3(0.2, -0.1, -0.1));
880   //vol_render->add_volume(volume[3], tf[0]);
881
882   
883   psys = new ParticleSystem(NMESH, NMESH, g_context, volume[0]->id,
884                   1./volume[0]->aspect_ratio_width,
885                   1./volume[0]->aspect_ratio_height,
886                   1./volume[0]->aspect_ratio_depth);
887   
888   //psys = new ParticleSystem(NMESH, NMESH, g_context, volume[0]->id, 0.25, 1., 1.);
889
890   init_particles();    //fill initial particles
891}
892
893
894
895void initTcl(){
896  interp = Tcl_CreateInterp();
897  Tcl_MakeSafe(interp);
898
899  Tcl_CreateCommand(interp, "camera", CameraCmd, (ClientData)0, (Tcl_CmdDeleteProc*)NULL);
900  //Tcl_CreateCommand(interp, "size", SizeCmd, (ClientData)0, (Tcl_CmdDeleteProc*)NULL);
901  //Tcl_CreateCommand(interp, "clear", ClearCmd, (ClientData)0, (Tcl_CmdDeleteProc*)NULL);
902  //Tcl_CreateCommand(interp, "cut", CutCmd, (ClientData)0, (Tcl_CmdDeleteProc*)NULL);
903  //Tcl_CreateCommand(interp, "outline", OutlineCmd, (ClientData)0, (Tcl_CmdDeleteProc*)NULL);
904  Tcl_CreateCommand(interp, "hello", HelloCmd, (ClientData)0, (Tcl_CmdDeleteProc*)NULL);
905  Tcl_CreateCommand(interp, "move", MoveCmd, (ClientData)0, (Tcl_CmdDeleteProc*)NULL);
906  Tcl_CreateCommand(interp, "refresh", RefreshCmd, (ClientData)0, (Tcl_CmdDeleteProc*)NULL);
907  //Tcl_CreateCommand(interp, "load", LoadCmd, (ClientData)0, (Tcl_CmdDeleteProc*)NULL);
908}
909
910
911void read_screen(){
912  //glBindTexture(GL_TEXTURE_2D, 0);
913  //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, final_fbo);
914  glReadPixels(0, 0, win_width, win_height, GL_RGB, GL_UNSIGNED_BYTE, screen_buffer);
915  assert(glGetError()==0);
916 
917  for(int i=0; i<win_width*win_height; i++){
918    if(screen_buffer[3*i]!=0 || screen_buffer[3*i+1]!=0 || screen_buffer[3*i+2]!=0)
919      fprintf(stderr, "(%d %d %d) ", screen_buffer[3*i], screen_buffer[3*i+1],  screen_buffer[3*i+2]);
920  }
921 
922}
923
924void display();
925
926
927char rle[512*512*3];
928int rle_size;
929
930short offsets[512*512*3];
931int offsets_size;
932
933void do_rle(){
934  int len = win_width*win_height*3;
935  rle_size = 0;
936  offsets_size = 0;
937
938  int i=0;
939  while(i<len){
940    if (screen_buffer[i] == 0) {
941      int pos = i+1;
942      while ( (pos<len) && (screen_buffer[pos] == 0)) {
943        pos++;
944      }
945      offsets[offsets_size++] = -(pos - i);
946      i = pos;
947    }
948
949    else {
950      int pos;
951      for (pos = i; (pos<len) && (screen_buffer[pos] != 0); pos++) {
952        rle[rle_size++] = screen_buffer[pos];
953      }
954      offsets[offsets_size++] = (pos - i);
955      i = pos;
956    }
957
958  }
959}
960
961// used internally to build up the BMP file header
962// writes an integer value into the header data structure at pos
963void
964bmp_header_add_int(unsigned char* header, int& pos, int data)
965{
966    header[pos++] = data & 0xff;
967    header[pos++] = (data >> 8) & 0xff;
968    header[pos++] = (data >> 16) & 0xff;
969    header[pos++] = (data >> 24) & 0xff;
970}
971
972
973void xinetd_listen(){
974    //command:
975    // 0. load data
976    // 1. flip on/off screen
977    // 2. rotation
978    // 3. zoom
979    // 4. more slices
980    // 5. less sleces
981
982    std::string data;
983    char tmp[256];
984    bzero(tmp, 256);
985    int status = read(0, tmp, 256);
986    if (status <= 0) {
987      exit(0);
988    }
989    fprintf(stderr, "read %d\n", status);
990    data = tmp;
991
992    if(Tcl_Eval(interp, (char*)data.c_str()) != TCL_OK) {
993      //error to log file...
994      fprintf(stderr, "Tcl error: parser\n");
995      return;
996    }
997
998    display();
999
1000#if DO_RLE
1001    do_rle();
1002    int sizes[2] = {  offsets_size*sizeof(offsets[0]), rle_size };
1003    fprintf(stderr, "Writing %d,%d\n", sizes[0], sizes[1]); fflush(stderr);
1004    write(0, &sizes, sizeof(sizes));
1005    write(0, offsets, offsets_size*sizeof(offsets[0]));
1006    write(0, rle, rle_size);    //unsigned byte
1007#else
1008    unsigned char header[54];
1009    int pos = 0;
1010    header[pos++] = 'B';
1011    header[pos++] = 'M';
1012
1013    // file size in bytes
1014    bmp_header_add_int(header, pos, win_width*win_height*3 + sizeof(header));
1015
1016    // reserved value (must be 0)
1017    bmp_header_add_int(header, pos, 0);
1018
1019    // offset in bytes to start of bitmap data
1020    bmp_header_add_int(header, pos, sizeof(header));
1021
1022    // size of the BITMAPINFOHEADER
1023    bmp_header_add_int(header, pos, 40);
1024
1025    // width of the image in pixels
1026    bmp_header_add_int(header, pos, win_width);
1027
1028    // height of the image in pixels
1029    bmp_header_add_int(header, pos, win_height);
1030
1031    // 1 plane + 24 bits/pixel << 16
1032    bmp_header_add_int(header, pos, 1572865);
1033
1034    // no compression
1035    // size of image for compression
1036    bmp_header_add_int(header, pos, 0);
1037    bmp_header_add_int(header, pos, 0);
1038
1039    // x pixels per meter
1040    // y pixels per meter
1041    bmp_header_add_int(header, pos, 0);
1042    bmp_header_add_int(header, pos, 0);
1043
1044    // number of colors used (0 = compute from bits/pixel)
1045    // number of important colors (0 = all colors important)
1046    bmp_header_add_int(header, pos, 0);
1047    bmp_header_add_int(header, pos, 0);
1048
1049    write(0, header, sizeof(header));
1050    write(0, screen_buffer, win_width * win_height * 3);
1051#endif
1052
1053    cerr << "server: serve() image sent" << endl;
1054}
1055
1056
1057/*
1058//draw vectors
1059void draw_arrows(){
1060  glColor4f(0.,0.,1.,1.);
1061  for(int i=0; i<NMESH; i++){
1062    for(int j=0; j<NMESH; j++){
1063      Vector2 v = grid.get(i, j);
1064
1065      int x1 = i*DM;
1066      int y1 = j*DM;
1067
1068      int x2 = x1 + v.x;
1069      int y2 = y1 + v.y;
1070
1071      glBegin(GL_LINES);
1072        glVertex2d(x1, y1);
1073        glVertex2d(x2, y2);
1074      glEnd();
1075    }
1076  }
1077}
1078*/
1079
1080
1081/*----------------------------------------------------*/
1082void idle(){
1083  glutSetWindow(render_window);
1084
1085 
1086  /*
1087  struct timespec ts;
1088  ts.tv_sec = 0;
1089  ts.tv_nsec = 300000000;
1090  nanosleep(&ts, 0);
1091  */
1092 
1093
1094#ifdef XINETD
1095  xinetd_listen();
1096#else
1097  glutPostRedisplay();
1098#endif
1099}
1100
1101
1102void display_final_fbo(){
1103   glEnable(GL_TEXTURE_2D);
1104   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1105   glBindTexture(GL_TEXTURE_2D, final_color_tex);
1106
1107   glMatrixMode(GL_PROJECTION);
1108   glLoadIdentity();
1109   gluOrtho2D(-1, 1, -1, 1);
1110   glMatrixMode(GL_MODELVIEW);
1111   glLoadIdentity();
1112
1113   //glColor3f(1.,1.,1.);               //MUST HAVE THIS LINE!!!
1114   glBegin(GL_QUADS);
1115   glTexCoord2f(0, 0); glVertex2f(-1, -1);
1116   glTexCoord2f(1, 0); glVertex2f(1, -1);
1117   glTexCoord2f(1, 1); glVertex2f(1, 1);
1118   glTexCoord2f(0, 1); glVertex2f(-1, 1);
1119   glEnd();
1120}
1121
1122void final_fbo_capture(){
1123   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, final_fbo);
1124}
1125
1126void draw_bounding_box(float x0, float y0, float z0,
1127                float x1, float y1, float z1,
1128                float r, float g, float b, float line_width)
1129{
1130        glDisable(GL_TEXTURE_2D);
1131
1132        glColor4d(r, g, b, 1.0);
1133        glLineWidth(line_width);
1134       
1135        glBegin(GL_LINE_LOOP);
1136
1137                glVertex3d(x0, y0, z0);
1138                glVertex3d(x1, y0, z0);
1139                glVertex3d(x1, y1, z0);
1140                glVertex3d(x0, y1, z0);
1141               
1142        glEnd();
1143
1144        glBegin(GL_LINE_LOOP);
1145
1146                glVertex3d(x0, y0, z1);
1147                glVertex3d(x1, y0, z1);
1148                glVertex3d(x1, y1, z1);
1149                glVertex3d(x0, y1, z1);
1150               
1151        glEnd();
1152
1153
1154        glBegin(GL_LINE_LOOP);
1155
1156                glVertex3d(x0, y0, z0);
1157                glVertex3d(x0, y0, z1);
1158                glVertex3d(x0, y1, z1);
1159                glVertex3d(x0, y1, z0);
1160               
1161        glEnd();
1162
1163        glBegin(GL_LINE_LOOP);
1164
1165                glVertex3d(x1, y0, z0);
1166                glVertex3d(x1, y0, z1);
1167                glVertex3d(x1, y1, z1);
1168                glVertex3d(x1, y1, z0);
1169               
1170        glEnd();
1171
1172        glEnable(GL_TEXTURE_2D);
1173}
1174
1175
1176
1177int particle_distance_sort(const void* a, const void* b){
1178  if((*((Particle*)a)).aux > (*((Particle*)b)).aux)
1179    return -1;
1180  else
1181    return 1;
1182}
1183
1184
1185void soft_read_verts(){
1186  glReadPixels(0, 0, psys->psys_width, psys->psys_height, GL_RGB, GL_FLOAT, vert);
1187  //fprintf(stderr, "soft_read_vert");
1188
1189  //cpu sort the distance 
1190  Particle* p = (Particle*) malloc(sizeof(Particle)* psys->psys_width * psys->psys_height);
1191  for(int i=0; i<psys->psys_width * psys->psys_height; i++){
1192    float x = vert[3*i];
1193    float y = vert[3*i+1];
1194    float z = vert[3*i+2];
1195
1196    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);
1197    p[i].x = x;
1198    p[i].y = y;
1199    p[i].z = z;
1200    p[i].aux = dis;
1201  }
1202
1203  qsort(p, psys->psys_width * psys->psys_height, sizeof(Particle), particle_distance_sort);
1204
1205  for(int i=0; i<psys->psys_width * psys->psys_height; i++){
1206    vert[3*i] = p[i].x;
1207    vert[3*i+1] = p[i].y;
1208    vert[3*i+2] = p[i].z;
1209  }
1210
1211  free(p);
1212}
1213
1214
1215//display the content of a texture as a screen aligned quad
1216void display_texture(NVISid tex, int width, int height){
1217   glPushMatrix();
1218
1219   glEnable(GL_TEXTURE_2D);
1220   glBindTexture(GL_TEXTURE_RECTANGLE_NV, tex);
1221
1222   glViewport(0, 0, width, height);
1223   glMatrixMode(GL_PROJECTION);
1224   glLoadIdentity();
1225   gluOrtho2D(0, width, 0, height);
1226   glMatrixMode(GL_MODELVIEW);
1227   glLoadIdentity();
1228
1229   cgGLBindProgram(m_passthru_fprog);
1230   cgGLEnableProfile(CG_PROFILE_FP30);
1231
1232   cgGLSetParameter4f(m_passthru_scale_param, 1.0, 1.0, 1.0, 1.0);
1233   cgGLSetParameter4f(m_passthru_bias_param, 0.0, 0.0, 0.0, 0.0);
1234   
1235   draw_quad(width, height, width, height);
1236   cgGLDisableProfile(CG_PROFILE_FP30);
1237
1238   glPopMatrix();
1239
1240   assert(glGetError()==0);
1241}
1242
1243
1244//draw vertices in the main memory
1245void soft_display_verts(){
1246  glDisable(GL_TEXTURE_2D);
1247  glEnable(GL_BLEND);
1248
1249  glPointSize(0.5);
1250  glColor4f(0,0.8,0.8,0.6);
1251  glBegin(GL_POINTS);
1252  for(int i=0; i<psys->psys_width * psys->psys_height; i++){
1253    glVertex3f(vert[3*i], vert[3*i+1], vert[3*i+2]);
1254  }
1255  glEnd();
1256  //fprintf(stderr, "soft_display_vert");
1257}
1258
1259
1260#if 0
1261
1262//oddeven sort on GPU
1263void sortstep()
1264{
1265    // perform one step of the current sorting algorithm
1266
1267        /*
1268    // swap buffers
1269    int sourceBuffer = targetBuffer;
1270    targetBuffer = (targetBuffer+1)%2;   
1271    int pstage = (1<<stage);
1272    int ppass  = (1<<pass);
1273    int activeBitonicShader = 0;
1274
1275#ifdef _WIN32
1276    buffer->BindBuffer(wglTargets[sourceBuffer]);
1277#else
1278    buffer->BindBuffer(glTargets[sourceBuffer]);
1279#endif
1280    if (buffer->IsDoubleBuffered()) glDrawBuffer(glTargets[targetBuffer]);
1281    */
1282
1283    checkGLError("after db");
1284
1285    int pstage = (1<<stage);
1286    int ppass  = (1<<pass);
1287    //int activeBitonicShader = 0;
1288
1289    // switch on correct sorting shader
1290    oddevenMergeSort.bind();
1291    glUniform3fARB(oddevenMergeSort.getUniformLocation("Param1"), float(pstage+pstage),
1292                   float(ppass%pstage), float((pstage+pstage)-(ppass%pstage)-1));
1293    glUniform3fARB(oddevenMergeSort.getUniformLocation("Param2"), float(psys_width), float(psys_height), float(ppass));
1294    glUniform1iARB(oddevenMergeSort.getUniformLocation("Data"), 0);
1295    staticdebugmsg("sort","stage "<<pstage<<" pass "<<ppass);
1296
1297    // This clear is not necessary for sort to function. But if we are in interactive mode
1298    // unused parts of the texture that are visible will look bad.
1299    //if (!perfTest) glClear(GL_COLOR_BUFFER_BIT);
1300
1301    //buffer->Bind();
1302    //buffer->EnableTextureTarget();
1303
1304    // initiate the sorting step on the GPU
1305    // a full-screen quad
1306    glBegin(GL_QUADS);
1307    /*
1308    glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,0.0f,0.0f,1.0f); glVertex2f(-1.0f,-1.0f);
1309    glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),0.0f,1.0f,1.0f); glVertex2f(1.0f,-1.0f);
1310    glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),float(psys_height),1.0f,0.0f); glVertex2f(1.0f,1.0f);       
1311    glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,float(psys_height),0.0f,0.0f); glVertex2f(-1.0f,1.0f);   
1312    */
1313    glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,0.0f,0.0f,1.0f); glVertex2f(0.,0.);       
1314    glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),0.0f,1.0f,1.0f); glVertex2f(float(psys_width), 0.);
1315    glMultiTexCoord4fARB(GL_TEXTURE0_ARB,float(psys_width),float(psys_height),1.0f,0.0f); glVertex2f(float(psys_width), float(psys_height));   
1316    glMultiTexCoord4fARB(GL_TEXTURE0_ARB,0.0f,float(psys_height),0.0f,0.0f); glVertex2f(0., float(psys_height));       
1317    glEnd();
1318
1319
1320    // switch off sorting shader
1321    oddevenMergeSort.release();
1322
1323    //buffer->DisableTextureTarget();
1324
1325    assert(glGetError()==0);
1326}
1327
1328#endif
1329
1330
1331void draw_3d_axis(){
1332  glDisable(GL_TEXTURE_2D);
1333  glEnable(GL_DEPTH_TEST);
1334
1335        //draw axes
1336        GLUquadric *obj;
1337        obj = gluNewQuadric();
1338       
1339        glDepthFunc(GL_LESS);
1340        glEnable(GL_DEPTH_TEST);
1341        glDisable(GL_BLEND);
1342
1343        int segments = 50;
1344
1345        glColor3f(0.8, 0.8, 0.8);
1346        glPushMatrix();
1347        glTranslatef(0.4, 0., 0.);
1348        glScalef(0.0005, 0.0005, 0.0005);
1349        glutStrokeCharacter(GLUT_STROKE_ROMAN, 'x');
1350        glPopMatrix(); 
1351
1352        glPushMatrix();
1353        glTranslatef(0., 0.4, 0.);
1354        glScalef(0.0005, 0.0005, 0.0005);
1355        glutStrokeCharacter(GLUT_STROKE_ROMAN, 'y');
1356        glPopMatrix(); 
1357
1358        glPushMatrix();
1359        glTranslatef(0., 0., 0.4);
1360        glScalef(0.0005, 0.0005, 0.0005);
1361        glutStrokeCharacter(GLUT_STROKE_ROMAN, 'z');
1362        glPopMatrix(); 
1363
1364        glEnable(GL_LIGHTING);
1365        glEnable(GL_LIGHT0);
1366
1367        glColor3f(0.2, 0.2, 0.8);
1368        glPushMatrix();
1369        glutSolidSphere(0.02, segments, segments );
1370        glPopMatrix();
1371
1372        glPushMatrix();
1373        glRotatef(-90, 1, 0, 0);       
1374        gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments);
1375        glPopMatrix(); 
1376
1377        glPushMatrix();
1378        glTranslatef(0., 0.3, 0.);
1379        glRotatef(-90, 1, 0, 0);       
1380        gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments);
1381        glPopMatrix(); 
1382
1383        glPushMatrix();
1384        glRotatef(90, 0, 1, 0);
1385        gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments);
1386        glPopMatrix(); 
1387
1388        glPushMatrix();
1389        glTranslatef(0.3, 0., 0.);
1390        glRotatef(90, 0, 1, 0);
1391        gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments);
1392        glPopMatrix(); 
1393
1394        glPushMatrix();
1395        gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments);
1396        glPopMatrix(); 
1397
1398        glPushMatrix();
1399        glTranslatef(0., 0., 0.3);
1400        gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments);
1401        glPopMatrix(); 
1402
1403        glDisable(GL_LIGHTING);
1404        glDisable(GL_DEPTH_TEST);
1405        gluDeleteQuadric(obj);
1406
1407  glEnable(GL_TEXTURE_2D);
1408  glDisable(GL_DEPTH_TEST);
1409}
1410
1411
1412void draw_axis(){
1413
1414  glDisable(GL_TEXTURE_2D);
1415  glEnable(GL_DEPTH_TEST);
1416
1417  //red x
1418  glColor3f(1,0,0);
1419  glBegin(GL_LINES);
1420    glVertex3f(0,0,0);
1421    glVertex3f(1.5,0,0);
1422  glEnd();
1423
1424  //blue y
1425  glColor3f(0,0,1);
1426  glBegin(GL_LINES);
1427    glVertex3f(0,0,0);
1428    glVertex3f(0,1.5,0);
1429  glEnd();
1430
1431  //green z
1432  glColor3f(0,1,0);
1433  glBegin(GL_LINES);
1434    glVertex3f(0,0,0);
1435    glVertex3f(0,0,1.5);
1436  glEnd();
1437
1438  glEnable(GL_TEXTURE_2D);
1439  glDisable(GL_DEPTH_TEST);
1440}
1441
1442
1443
1444/*----------------------------------------------------*/
1445void display()
1446{
1447
1448   assert(glGetError()==0);
1449
1450   lic->convolve(); //flow line integral convolution
1451
1452   psys->advect(); //advect particles
1453
1454   final_fbo_capture();
1455   //display_texture(slice_vector_tex, NMESH, NMESH);
1456
1457#if 1
1458   //start final rendering
1459   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear screen
1460
1461   glEnable(GL_TEXTURE_2D);
1462   glEnable(GL_DEPTH_TEST);
1463
1464   //camera setting activated
1465   cam->activate();
1466
1467   //now render things in the scene
1468   //
1469   draw_3d_axis();
1470   
1471   lic->render();       //display the line integral convolution result
1472   
1473   //soft_display_verts();
1474   perf->enable();
1475     psys->render();
1476   perf->disable();
1477   //fprintf(stderr, "particle pixels: %d\n", perf->get_pixel_count());
1478   perf->reset();
1479
1480
1481   perf->enable();
1482     //vol_render->render(0);
1483     vol_render->render_all();
1484
1485     //fprintf(stderr, "%lf\n", get_time_interval());
1486   perf->disable();
1487   //fprintf(stderr, "volume pixels: %d\n", perf->get_pixel_count());
1488 
1489#ifdef XINETD
1490   float cost  = perf->get_pixel_count();
1491   write(3, &cost, sizeof(cost));
1492#endif
1493   perf->reset();
1494
1495#endif
1496
1497   display_final_fbo(); //display the final rendering on screen
1498
1499#ifdef XINETD
1500   read_screen();
1501#else
1502   //read_screen();
1503#endif   
1504
1505   glutSwapBuffers();
1506}
1507
1508
1509void mouse(int button, int state, int x, int y){
1510  if(button==GLUT_LEFT_BUTTON){
1511
1512    if(state==GLUT_DOWN){
1513      left_last_x = x;
1514      left_last_y = y;
1515      left_down = true;
1516      right_down = false;
1517    }
1518    else{
1519      left_down = false;
1520      right_down = false;
1521    }
1522  }
1523  else{
1524    //fprintf(stderr, "right mouse\n");
1525
1526    if(state==GLUT_DOWN){
1527      //fprintf(stderr, "right mouse down\n");
1528      right_last_x = x;
1529      right_last_y = y;
1530      left_down = false;
1531      right_down = true;
1532    }
1533    else{
1534      //fprintf(stderr, "right mouse up\n");
1535      left_down = false;
1536      right_down = false;
1537    }
1538  }
1539}
1540
1541
1542void update_rot(int delta_x, int delta_y){
1543        live_rot_x += delta_x;
1544        live_rot_y += delta_y;
1545
1546        if(live_rot_x > 360.0)
1547                live_rot_x -= 360.0;   
1548        else if(live_rot_x < -360.0)
1549                live_rot_x += 360.0;
1550
1551        if(live_rot_y > 360.0)
1552                live_rot_y -= 360.0;   
1553        else if(live_rot_y < -360.0)
1554                live_rot_y += 360.0;
1555
1556        cam->rotate(live_rot_x, live_rot_y, live_rot_z);
1557}
1558
1559
1560void update_trans(int delta_x, int delta_y, int delta_z){
1561        live_obj_x += delta_x*0.03;
1562        live_obj_y += delta_y*0.03;
1563        live_obj_z += delta_z*0.03;
1564}
1565
1566void end_service();
1567
1568void keyboard(unsigned char key, int x, int y){
1569 
1570   bool log = false;
1571
1572   switch (key){
1573        case 'q':
1574#ifdef XINETD
1575                end_service();
1576#endif
1577                exit(0);
1578                break;
1579        case '+':
1580                lic_slice_z+=0.05;
1581                lic->set_offset(lic_slice_z);
1582                break;
1583        case '-':
1584                lic_slice_z-=0.05;
1585                lic->set_offset(lic_slice_z);
1586                break;
1587        case ',':
1588                lic_slice_x+=0.05;
1589                init_particles();
1590                break;
1591        case '.':
1592                lic_slice_x-=0.05;
1593                init_particles();
1594                break;
1595        case '1':
1596                advect = true;
1597                break;
1598        case '2':
1599                psys_x+=0.05;
1600                break;
1601        case '3':
1602                psys_x-=0.05;
1603                break;
1604        case 'w': //zoom out
1605                live_obj_z-=0.05;
1606                log = true;
1607                cam->move(live_obj_x, live_obj_y, live_obj_z);
1608                break;
1609        case 's': //zoom in
1610                live_obj_z+=0.05;
1611                log = true;
1612                cam->move(live_obj_x, live_obj_y, live_obj_z);
1613                break;
1614        case 'a': //left
1615                live_obj_x-=0.05;
1616                log = true;
1617                cam->move(live_obj_x, live_obj_y, live_obj_z);
1618                break;
1619        case 'd': //right
1620                live_obj_x+=0.05;
1621                log = true;
1622                cam->move(live_obj_x, live_obj_y, live_obj_z);
1623                break;
1624        case 'i':
1625                init_particles();
1626                break;
1627        case 'o':
1628                live_specular+=1;
1629                fprintf(stderr, "specular: %f\n", live_specular);
1630                vol_render->set_specular(live_specular);
1631                break;
1632        case 'p':
1633                live_specular-=1;
1634                fprintf(stderr, "specular: %f\n", live_specular);
1635                vol_render->set_specular(live_specular);
1636                break;
1637        case '[':
1638                live_diffuse+=0.5;
1639                vol_render->set_diffuse(live_diffuse);
1640                break;
1641        case ']':
1642                live_diffuse-=0.5;
1643                vol_render->set_diffuse(live_diffuse);
1644                break;
1645        case 'v':
1646                vol_render->switch_volume_mode();
1647                break;
1648        case 'b':
1649                vol_render->switch_slice_mode();
1650                break;
1651
1652        default:
1653                break;
1654    }   
1655
1656#ifdef EVENTLOG
1657   if(log){
1658     float param[3] = {live_obj_x, live_obj_y, live_obj_z};
1659     Event* tmp = new Event(EVENT_MOVE, param, get_time_interval());
1660     tmp->write(event_log);
1661     delete tmp;
1662   }
1663#endif
1664}
1665
1666void motion(int x, int y){
1667
1668    int old_x, old_y;   
1669
1670    if(left_down){
1671      old_x = left_last_x;
1672      old_y = left_last_y;   
1673    }
1674    else if(right_down){
1675      old_x = right_last_x;
1676      old_y = right_last_y;   
1677    }
1678
1679    int delta_x = x - old_x;
1680    int delta_y = y - old_y;
1681
1682    //more coarse event handling
1683    //if(abs(delta_x)<10 && abs(delta_y)<10)
1684      //return;
1685
1686    if(left_down){
1687      left_last_x = x;
1688      left_last_y = y;
1689
1690      update_rot(-delta_y, -delta_x);
1691    }
1692    else if (right_down){
1693      //fprintf(stderr, "right mouse motion (%d,%d)\n", x, y);
1694
1695      right_last_x = x;
1696      right_last_y = y;
1697
1698      update_trans(0, 0, delta_x);
1699    }
1700
1701#ifdef EVENTLOG
1702    float param[3] = {live_rot_x, live_rot_y, live_rot_z};
1703    Event* tmp = new Event(EVENT_ROTATE, param, get_time_interval());
1704    tmp->write(event_log);
1705    delete tmp;
1706#endif
1707
1708    glutPostRedisplay();
1709}
1710
1711#ifdef XINETD
1712void init_service(){
1713  //open log and map stderr to log file
1714  xinetd_log = fopen("log.txt", "w");
1715  close(2);
1716  dup2(fileno(xinetd_log), 2);
1717  dup2(2,1);
1718
1719  //flush junk
1720  fflush(stdout);
1721  fflush(stderr);
1722}
1723
1724void end_service(){
1725  //close log file
1726  fclose(xinetd_log);
1727}
1728#endif
1729
1730void init_event_log(){
1731  event_log = fopen("event.txt", "w");
1732  assert(event_log!=0);
1733
1734  struct timeval time;
1735  gettimeofday(&time, NULL);
1736  cur_time = time.tv_sec*1000. + time.tv_usec/1000.;
1737}
1738
1739void end_event_log(){
1740  fclose(event_log);
1741}
1742
1743double get_time_interval(){
1744  struct timeval time;
1745  gettimeofday(&time, NULL);
1746  double new_time = time.tv_sec*1000. + time.tv_usec/1000.;
1747
1748  double interval = new_time - cur_time;
1749  cur_time = new_time;
1750  return interval;
1751}
1752
1753
1754/*----------------------------------------------------*/
1755int main(int argc, char** argv)
1756{
1757#ifdef XINETD
1758   init_service();
1759#endif
1760
1761   glutInit(&argc, argv);
1762   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
1763
1764   MainTransferFunctionWindow * tf_window;
1765   tf_window = new MainTransferFunctionWindow();
1766   tf_window->mainInit();
1767   
1768   glutInitWindowSize(NPIX, NPIX);
1769   glutInitWindowPosition(10, 10);
1770   render_window = glutCreateWindow(argv[0]);
1771
1772   glutDisplayFunc(display);
1773   glutMouseFunc(mouse);
1774   glutMotionFunc(motion);
1775   glutKeyboardFunc(keyboard);
1776   glutIdleFunc(idle);
1777
1778   initGL();
1779   initTcl();
1780
1781#ifdef EVENTLOG
1782   init_event_log();
1783#endif
1784   //event loop
1785   glutMainLoop();
1786#ifdef EVENTLOG
1787   end_event_log();
1788#endif
1789
1790#ifdef XINETD
1791   end_service();
1792#endif
1793
1794   return 0;
1795}
Note: See TracBrowser for help on using the repository browser.