source: trunk/packages/vizservers/nanovis/LIC.cpp @ 4050

Last change on this file since 4050 was 3630, checked in by ldelgass, 11 years ago

Nanovis refactoring to fix problems with scaling and multiple results.
Do rendering in world space to properly place and scale multiple data sets.
Also fix flows to reduce resets of animations. More work toward removing
Cg dependency. Fix panning to convert viewport coords to world coords.

  • Property svn:eol-style set to native
File size: 14.8 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 *  Copyright (c) 2004-2013  HUBzero Foundation, LLC
4 *
5 *  Authors:
6 *    Wei Qiao <qiaow@purdue.edu>
7 */
8#include <stdlib.h>
9#include <math.h>
10#include <assert.h>
11
12#include "nanovis.h"
13#include "define.h"
14
15#include "LIC.h"
16#include "Shader.h"
17#include "Trace.h"
18
19#define NPN 256   //resolution of background pattern
20#define DM ((float) (1.0/(NMESH-1.0))) //distance in world coords between mesh lines
21#define SCALE 3.0 //scale for background pattern. small value -> fine texture
22
23using namespace nv;
24using namespace vrmath;
25
26LIC::LIC(FlowSliceAxis axis,
27         float offset) :
28    _width(NPIX),
29    _height(NPIX),
30    _size(NMESH),
31    _scale(1.0f, 1.0f, 1.0f),
32    _origin(0, 0, 0),
33    _offset(offset),
34    _axis(axis),
35    _iframe(0),
36    _Npat(64),
37    _alpha((int)0.12*255),
38    _tmax(NPIX/(SCALE*NPN)),
39    _dmax(SCALE/NPIX),
40    _max(1.0f),
41    _disListID(0),
42    _vectorFieldId(0),
43    _visible(false)
44{
45    _sliceVector = new float[_size * _size * 4];
46    memset(_sliceVector, 0, sizeof(float) * _size * _size * 4);
47
48    int fboOrig;
49    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fboOrig);
50
51    //initialize the pattern texture
52    glGenTextures(1, &_patternTex);
53    glBindTexture(GL_TEXTURE_2D, _patternTex);
54    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
55    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
56    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
57    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
58    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
59
60    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, NPN, NPN, 0,
61                 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
62
63    //initialize frame buffer objects
64    //render buffer for projecting 3D velocity onto a 2D plane
65    glGenFramebuffersEXT(1, &_velFbo);
66    glGenTextures(1, &_sliceVectorTex);
67
68    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _velFbo);
69
70    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _sliceVectorTex);
71    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
72    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
73    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
74    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
75
76    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB, _size, _size,
77                 0, GL_RGBA, GL_FLOAT, NULL);
78
79    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
80                              GL_TEXTURE_RECTANGLE_ARB, _sliceVectorTex, 0);
81
82    //render buffer for the convolution
83    glGenFramebuffersEXT(1, &_fbo);
84    glGenTextures(1, &_colorTex);
85
86    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo);
87
88    //initialize color texture for lic
89    glBindTexture(GL_TEXTURE_2D, _colorTex);
90    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
91    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
92    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
93
94    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, _width, _height, 0,
95                 GL_RGB, GL_UNSIGNED_BYTE, NULL);
96
97    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
98                              GL_TEXTURE_2D, _colorTex, 0);
99
100    // Check framebuffer completeness at the end of initialization.
101    CHECK_FRAMEBUFFER_STATUS();
102
103    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig);
104
105    _renderVelShader = new Shader();
106    _renderVelShader->loadFragmentProgram("render_vel.cg");
107
108    makePatterns();
109}
110
111LIC::~LIC()
112{
113    glDeleteTextures(1, &_patternTex);
114    glDeleteTextures(1, &_magTex);
115
116    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _velFbo);
117    glDeleteTextures(1, &_sliceVectorTex);
118
119    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo);
120    glDeleteTextures(1, &_colorTex);
121
122    GLuint buffers[2] = {_velFbo, _fbo};
123    glDeleteFramebuffersEXT(2, buffers);
124
125    glDeleteLists(_disListID, _Npat);
126
127    delete _renderVelShader;
128
129    delete [] _sliceVector;
130}
131
132void
133LIC::makePatterns()
134{
135    TRACE("Enter");
136
137    if (_disListID > 0) {
138        glDeleteLists(_disListID, _Npat);
139    }
140    _disListID = glGenLists(_Npat);
141
142    TRACE("DisplayList : %d", _disListID);
143
144    int lut[256];
145    int phase[NPN][NPN];
146    GLubyte pat[NPN][NPN][4];
147    int i, j, k, t;
148
149    for (i = 0; i < 256; i++) {
150        lut[i] = i < 127 ? 0 : 255;
151    }
152    for (i = 0; i < NPN; i++) {
153        for (j = 0; j < NPN; j++) {
154            phase[i][j] = rand() >> 8;
155        }
156    }
157    for (k = 0; k < _Npat; k++) {
158        t = (k << 8) / _Npat;
159        for (i = 0; i < NPN; i++) {
160            for (j = 0; j < NPN; j++) {
161                pat[i][j][0] = pat[i][j][1] = pat[i][j][2] =
162                    lut[(t + phase[i][j]) % 255];
163                pat[i][j][3] = _alpha;
164            }
165        }
166        glNewList(_disListID + k, GL_COMPILE);
167        glBindTexture(GL_TEXTURE_2D, _patternTex);
168        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, NPN, NPN, 0,
169                     GL_RGBA, GL_UNSIGNED_BYTE, pat);
170        glEndList();
171    }
172
173    glBindTexture(GL_TEXTURE_2D, _patternTex);
174    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, NPN, NPN, 0,
175                 GL_RGBA, GL_UNSIGNED_BYTE, pat);
176
177    TRACE("Leave");
178}
179
180void
181LIC::makeMagnitudes()
182{
183    GLubyte mag[NMESH][NMESH][4];
184
185    //read vector field
186    for (int i = 0; i < NMESH; i++) {
187        for (int j = 0; j < NMESH; j++) {
188            float x = DM*i;
189            float y = DM*j;
190 
191            float magnitude = sqrt(x*x+y*y)/1.414;
192
193            //from green to red
194            GLubyte r = (GLubyte)floor(magnitude*255);
195            GLubyte g = 0;
196            GLubyte b = 255 - r;
197            GLubyte a = 122;
198
199            mag[i][j][0] = r;
200            mag[i][j][1] = g;
201            mag[i][j][2] = b;
202            mag[i][j][3] = a;
203        }
204    }
205    glGenTextures(1, &_magTex);
206    glBindTexture(GL_TEXTURE_2D, _magTex);
207    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
208    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
209    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
210    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
211    //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
212    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, NMESH, NMESH, 0, GL_RGBA,
213                 GL_UNSIGNED_BYTE, mag);
214    glBindTexture(GL_TEXTURE_2D, 0);
215}
216
217void
218LIC::getSlice()
219{
220    int fboOrig;
221    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fboOrig);
222
223    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _velFbo);
224
225    glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);
226
227    glClear(GL_COLOR_BUFFER_BIT);
228    glDisable(GL_DEPTH_TEST);
229    glDisable(GL_BLEND);
230
231    glViewport(0, 0, _size, _size);
232    glMatrixMode(GL_PROJECTION);
233    glPushMatrix();
234    glLoadIdentity();
235    gluOrtho2D(0, _size, 0, _size);
236    glMatrixMode(GL_MODELVIEW);
237    glPushMatrix();
238    glLoadIdentity();
239
240    glEnable(GL_TEXTURE_3D);
241    glBindTexture(GL_TEXTURE_3D, _vectorFieldId);
242
243    _renderVelShader->bind();
244    _renderVelShader->setFPTextureParameter("vel_tex", _vectorFieldId);
245    _renderVelShader->setFPParameter1f("timestep", 0.0005);
246    _renderVelShader->setFPParameter1f("vmax", _max > 100.0 ? 100.0 : _max);
247
248    switch (_axis) {
249    case AXIS_X:
250        _renderVelShader->setFPParameter3f("projection_vector", 0., 1., 1.);
251        break;
252    case AXIS_Y:
253        _renderVelShader->setFPParameter3f("projection_vector", 1., 0., 1.);
254        break;
255    default:
256    case AXIS_Z:
257        _renderVelShader->setFPParameter3f("projection_vector", 1., 1., 0.);
258        break;
259    }
260
261    glBegin(GL_QUADS);
262    {
263        switch (_axis) {
264        case AXIS_X:
265            glTexCoord3f(_offset, 0., 0.); glVertex2f(0.,    0.);
266            glTexCoord3f(_offset, 1., 0.); glVertex2f(_size, 0.);
267            glTexCoord3f(_offset, 1., 1.); glVertex2f(_size, _size);
268            glTexCoord3f(_offset, 0., 1.); glVertex2f(0.,    _size);
269            break;
270        case AXIS_Y:
271            glTexCoord3f(0., _offset, 0.); glVertex2f(0.,    0.);
272            glTexCoord3f(1., _offset, 0.); glVertex2f(_size, 0.);
273            glTexCoord3f(1., _offset, 1.); glVertex2f(_size, _size);
274            glTexCoord3f(0., _offset, 1.); glVertex2f(0.,    _size);
275            break;
276        case AXIS_Z:
277            glTexCoord3f(0., 0., _offset); glVertex2f(0.,    0.);
278            glTexCoord3f(1., 0., _offset); glVertex2f(_size, 0.);
279            glTexCoord3f(1., 1., _offset); glVertex2f(_size, _size);
280            glTexCoord3f(0., 1., _offset); glVertex2f(0.,    _size);
281            break;
282        }
283    }
284    glEnd();
285
286    _renderVelShader->disableFPTextureParameter("vel_tex");
287    _renderVelShader->unbind();
288
289    glBindTexture(GL_TEXTURE_3D, 0);
290    glDisable(GL_TEXTURE_3D);
291
292    //read the vectors
293    glReadPixels(0, 0, _size, _size, GL_RGBA, GL_FLOAT, _sliceVector);
294
295    int lim = _size * _size * 4;
296    float *v = _sliceVector;
297    for (int i = 0; i < lim; ++i) {
298        if (isnan(*v)) {
299            *v = 0.0f;   
300        }
301        ++v;
302    }
303
304    glMatrixMode(GL_PROJECTION);
305    glPopMatrix();
306    glMatrixMode(GL_MODELVIEW);
307    glPopMatrix();
308
309    glPopAttrib();
310
311    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig);
312}
313
314//line integral convolution
315void
316LIC::convolve()
317{
318    if (_vectorFieldId == 0) {
319        return;
320    }
321
322    int   i, j;
323    float x1, x2, y, px, py;
324
325    int fboOrig;
326    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fboOrig);
327
328    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo);
329
330    glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
331
332    glMatrixMode(GL_PROJECTION);
333    glPushMatrix();
334    glLoadIdentity();
335
336    glViewport(0, 0, (GLsizei) NPIX, (GLsizei) NPIX);
337    //glTranslatef(-1.0, -1.0, 0.0);
338    //glScalef(2.0, 2.0, 1.0);
339    glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -10.0f, 10.0f);
340
341    glMatrixMode(GL_MODELVIEW);
342    glPushMatrix();
343    glLoadIdentity();
344
345    glClear(GL_COLOR_BUFFER_BIT);
346    //glDepthMask(GL_FALSE);
347    glDisable(GL_DEPTH_TEST);
348    glDisable(GL_LIGHTING);
349    glDisable(GL_ALPHA_TEST);
350
351    //_sa = 0.010*cos(_iframe*2.0*M_PI/200.0);
352    glEnable(GL_TEXTURE_2D);
353    glBindTexture(GL_TEXTURE_2D, _patternTex);
354    _sa = 0.01;
355 
356    glColor4f(1, 1, 1, 1);
357    for (i = 0; i < NMESH-1; i++) {
358        x1 = DM*i; x2 = x1 + DM;
359        glBegin(GL_QUAD_STRIP);
360        for (j = 0; j < NMESH-1; j++) {
361            y = DM*j;
362            glTexCoord2f(x1, y);
363            getVelocity(x1, y, &px, &py);
364            glVertex2f(px, py);
365
366            glTexCoord2f(x2, y);
367            getVelocity(x2, y, &px, &py);
368            glVertex2f(px, py);
369        }
370        glEnd();
371    }
372    _iframe = _iframe + 1;
373
374    glEnable(GL_BLEND);
375
376    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
377
378    glEnable(GL_TEXTURE_2D);
379    glCallList(_iframe % _Npat + _disListID);
380    glBegin(GL_QUADS);
381    {
382        glTexCoord2f(0.0,   0.0);   glVertex2f(0.0, 0.0);
383        glTexCoord2f(_tmax, 0.0);   glVertex2f(1.0, 0.0);
384        glTexCoord2f(_tmax, _tmax); glVertex2f(1.0, 1.0);
385        glTexCoord2f(0.0,   _tmax); glVertex2f(0.0, 1.0);
386    }
387    glEnd();
388    glDisable(GL_TEXTURE_2D);
389
390    /*
391    //inject dye
392    glDisable(GL_TEXTURE_2D);
393    glColor4f(1.,0.8,0.,1.);
394    glBegin(GL_QUADS);
395    glVertex2d(0.6, 0.6);
396    glVertex2d(0.6, 0.62);
397    glVertex2d(0.62, 0.62);
398    glVertex2d(0.62, 0.6);
399    glEnd();
400    */
401
402    glDisable(GL_BLEND);
403    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, NPIX, NPIX, 0);
404
405    /*
406    //blend magnitude texture
407    glBindTexture(GL_TEXTURE_2D, _magTex);
408    glEnable(GL_TEXTURE_2D);
409    glEnable(GL_BLEND);
410    glBegin(GL_QUADS);
411    glTexCoord2f(0.0,  0.0);  glVertex2f(0.0, 0.0);
412    glTexCoord2f(0.0,  1.0); glVertex2f(0.0, 1.);
413    glTexCoord2f(1.0, 1.0);  glVertex2f(1., 1.);
414    glTexCoord2f(1.0, 0.0); glVertex2f(1., 0.0);
415    glEnd();
416    */
417
418    glMatrixMode(GL_PROJECTION);
419    glPopMatrix();
420    glMatrixMode(GL_MODELVIEW);
421    glPopMatrix();
422
423    glPopAttrib();
424
425    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig);
426}
427
428void
429LIC::render()
430{
431    if (_vectorFieldId == 0 || !_visible) {
432        return;
433    }
434
435    //draw line integral convolution quad
436
437    glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT);
438    glBindTexture(GL_TEXTURE_2D, _colorTex);
439    glEnable(GL_TEXTURE_2D);
440    //glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
441    //glEnable(GL_LIGHTING);
442    glDisable(GL_LIGHTING);
443    glEnable(GL_DEPTH_TEST);
444
445    glMatrixMode(GL_MODELVIEW);
446    glPushMatrix();
447
448    glTranslatef(_origin.x, _origin.y, _origin.z);
449    glScalef(_scale.x, _scale.y, _scale.z);
450
451    glColor4f(1, 1, 1, 1);
452    glBegin(GL_QUADS);
453    switch (_axis) {
454    case AXIS_X:
455        glNormal3f(1, 0, 0);
456        glTexCoord2f(0, 0); glVertex3f(_offset, 0, 0);
457        glTexCoord2f(1, 0); glVertex3f(_offset, 1, 0);
458        glTexCoord2f(1, 1); glVertex3f(_offset, 1, 1);
459        glTexCoord2f(0, 1); glVertex3f(_offset, 0, 1);
460        break;
461    case AXIS_Y:
462        glNormal3f(0, 1, 0);
463        glTexCoord2f(0, 0); glVertex3f(0, _offset, 0);
464        glTexCoord2f(1, 0); glVertex3f(1, _offset, 0);
465        glTexCoord2f(1, 1); glVertex3f(1, _offset, 1);
466        glTexCoord2f(0, 1); glVertex3f(0, _offset, 1);
467        break;
468    case AXIS_Z:
469        glNormal3f(0, 0, 1);
470        glTexCoord2f(0, 0); glVertex3f(0, 0, _offset);
471        glTexCoord2f(1, 0); glVertex3f(1, 0, _offset);
472        glTexCoord2f(1, 1); glVertex3f(1, 1, _offset);
473        glTexCoord2f(0, 1); glVertex3f(0, 1, _offset);
474        break;
475    }
476    glEnd();
477
478    glPopMatrix();
479
480    glBindTexture(GL_TEXTURE_2D, 0);
481
482    glPopAttrib();
483}
484
485void
486LIC::setVectorField(Volume *volume)
487{
488    TRACE("LIC: vector field is assigned [%d]", volume->textureID());
489
490    _vectorFieldId = volume->textureID();
491    Vector3f bmin, bmax;
492    volume->getBounds(bmin, bmax);
493    _origin = bmin;
494    _scale.set(bmax.x-bmin.x, bmax.y-bmin.y, bmax.z-bmin.z);
495    _max = volume->wAxis.max();
496
497    makePatterns();
498
499    getSlice();
500}
501
502void
503LIC::getVelocity(float x, float y, float *px, float *py)
504{
505   float vx, vy, r;
506
507   int xi = (int)(x*_size);
508   int yi = (int)(y*_size);
509
510    //TRACE("(xi yi) = (%d %d), ", xi, yi);
511   switch (_axis) {
512   case AXIS_X:
513       vx = _sliceVector[4 * (xi+yi*_size)+2];
514       vy = _sliceVector[4 * (xi+yi*_size)+1];
515       break;
516   case AXIS_Y:
517       vx = _sliceVector[4 * (xi+yi*_size)];
518       vy = _sliceVector[4 * (xi+yi*_size)+2];
519       break;
520   case AXIS_Z:
521   default:
522       vx = _sliceVector[4 * (xi+yi*_size)];
523       vy = _sliceVector[4 * (xi+yi*_size)+1];
524       break;
525   }
526   r  = vx*vx + vy*vy;
527
528    //TRACE("(vx vx) = (%f %f), r=%f, ", vx, vy, r);
529   if (r > (_dmax * _dmax)) {
530      r  = sqrt(r);
531      vx *= _dmax/r;
532      vy *= _dmax/r;
533   }
534
535   *px = x + vx;
536   *py = y + vy;
537
538    //TRACE("vel %f %f -> %f %f, (dmax = %f)", x, y, *px, *py, dmax);
539}
540
541void
542LIC::setSlicePosition(float offset)
543{
544    _offset = offset;
545    getSlice();
546}
547
548void LIC::setSliceAxis(FlowSliceAxis axis)
549{
550    _axis = axis;
551}
552
553void LIC::reset()
554{
555    makePatterns();
556}
Note: See TracBrowser for help on using the repository browser.