source: nanovis/trunk/LIC.cpp @ 4643

Last change on this file since 4643 was 4167, checked in by ldelgass, 10 years ago

Texture environment is not part of texture object stored state, so don't set
environment mode before loading textures, should be done at render time.

  • 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 *    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    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.