source: nanovis/trunk/LIC.cpp @ 4897

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