source: nanovis/trunk/LIC.cpp @ 4988

Last change on this file since 4988 was 4901, checked in by ldelgass, 9 years ago

sync with release branch

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