source: nanovis/branches/1.1/LIC.cpp @ 4891

Last change on this file since 4891 was 4889, checked in by ldelgass, 10 years ago

Merge r3611:3618 from trunk

  • Property svn:eol-style set to native
File size: 14.7 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(int size, int width, int height, int axis,
28         float offset) :
29    _width(width),
30    _height(height),
31    _size(size),
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    _activate(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    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
60
61    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, NPN, NPN, 0,
62                 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
63
64    //initialize frame buffer objects
65    //render buffer for projecting 3D velocity onto a 2D plane
66    glGenFramebuffersEXT(1, &_velFbo);
67    glGenTextures(1, &_sliceVectorTex);
68
69    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _velFbo);
70
71    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _sliceVectorTex);
72    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
73    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
74    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
75    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
76
77    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB, _size, _size,
78                 0, GL_RGBA, GL_FLOAT, NULL);
79
80    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
81                              GL_TEXTURE_RECTANGLE_ARB, _sliceVectorTex, 0);
82
83    //render buffer for the convolution
84    glGenFramebuffersEXT(1, &_fbo);
85    glGenTextures(1, &_colorTex);
86
87    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo);
88
89    //initialize color texture for lic
90    glBindTexture(GL_TEXTURE_2D, _colorTex);
91    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
92    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
93    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
94
95    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, _width, _height, 0,
96                 GL_RGB, GL_UNSIGNED_BYTE, NULL);
97
98    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
99                              GL_TEXTURE_2D, _colorTex, 0);
100
101    // Check framebuffer completeness at the end of initialization.
102    CHECK_FRAMEBUFFER_STATUS();
103
104    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig);
105
106    _renderVelShader = new Shader();
107    _renderVelShader->loadFragmentProgram("render_vel.cg", "main");
108
109    makePatterns();
110}
111
112LIC::~LIC()
113{
114    glDeleteTextures(1, &_patternTex);
115    glDeleteTextures(1, &_magTex);
116
117    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _velFbo);
118    glDeleteTextures(1, &_sliceVectorTex);
119
120    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo);
121    glDeleteTextures(1, &_colorTex);
122
123    GLuint buffers[2] = {_velFbo, _fbo};
124    glDeleteFramebuffersEXT(2, buffers);
125
126    glDeleteLists(_disListID, _Npat);
127
128    delete _renderVelShader;
129
130    delete [] _sliceVector;
131}
132
133void
134LIC::makePatterns()
135{
136    TRACE("Enter");
137
138    if (_disListID > 0) {
139        glDeleteLists(_disListID, _Npat);
140    }
141    _disListID = glGenLists(_Npat);
142
143    TRACE("DisplayList : %d", _disListID);
144
145    int lut[256];
146    int phase[NPN][NPN];
147    GLubyte pat[NPN][NPN][4];
148    int i, j, k, t;
149
150    for (i = 0; i < 256; i++) {
151        lut[i] = i < 127 ? 0 : 255;
152    }
153    for (i = 0; i < NPN; i++) {
154        for (j = 0; j < NPN; j++) {
155            phase[i][j] = rand() >> 8;
156        }
157    }
158    for (k = 0; k < _Npat; k++) {
159        t = (k << 8) / _Npat;
160        for (i = 0; i < NPN; i++) {
161            for (j = 0; j < NPN; j++) {
162                pat[i][j][0] = pat[i][j][1] = pat[i][j][2] =
163                    lut[(t + phase[i][j]) % 255];
164                pat[i][j][3] = _alpha;
165            }
166        }
167        glNewList(_disListID + k, GL_COMPILE);
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        glEndList();
172    }
173
174    glBindTexture(GL_TEXTURE_2D, _patternTex);
175    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, NPN, NPN, 0,
176                 GL_RGBA, GL_UNSIGNED_BYTE, pat);
177
178    TRACE("Leave");
179}
180
181void LIC::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 0:
250        _renderVelShader->setFPParameter3f("projection_vector", 0., 1., 1.);
251        break;
252    case 1:
253        _renderVelShader->setFPParameter3f("projection_vector", 1., 0., 1.);
254        break;
255    default:
256    case 2:
257        _renderVelShader->setFPParameter3f("projection_vector", 1., 1., 0.);
258        break;
259    }
260
261    glBegin(GL_QUADS);
262    {
263        switch (_axis) {
264        case 0:
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 1:
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 2:
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) {
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 0:
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 1:
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 2:
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(unsigned int texID, const Vector3f& origin,
487                      float scaleX, float scaleY, float scaleZ, float max)
488{
489    TRACE("LIC: vector field is assigned [%d]", texID);
490    _vectorFieldId = texID;
491    _origin = origin;
492    _scale = Vector3f(scaleX, scaleY, scaleZ);
493    _max = max;
494
495    makePatterns();
496
497    getSlice();
498}
499
500void
501LIC::getVelocity(float x, float y, float *px, float *py)
502{
503   float vx, vy, r;
504
505   int xi = (int)(x*_size);
506   int yi = (int)(y*_size);
507
508    //TRACE("(xi yi) = (%d %d), ", xi, yi);
509   switch (_axis) {
510   case 0:
511       vx = _sliceVector[4 * (xi+yi*_size)+2];
512       vy = _sliceVector[4 * (xi+yi*_size)+1];
513       break;
514   case 1:
515       vx = _sliceVector[4 * (xi+yi*_size)];
516       vy = _sliceVector[4 * (xi+yi*_size)+2];
517       break;
518   case 2:
519   default:
520       vx = _sliceVector[4 * (xi+yi*_size)];
521       vy = _sliceVector[4 * (xi+yi*_size)+1];
522       break;
523   }
524   r  = vx*vx + vy*vy;
525
526    //TRACE("(vx vx) = (%f %f), r=%f, ", vx, vy, r);
527   if (r > (_dmax * _dmax)) {
528      r  = sqrt(r);
529      vx *= _dmax/r;
530      vy *= _dmax/r;
531   }
532
533   *px = x + vx;
534   *py = y + vy;
535
536    //TRACE("vel %f %f -> %f %f, (dmax = %f)", x, y, *px, *py, dmax);
537}
538
539void
540LIC::setOffset(float offset)
541{
542    _offset = offset;
543    getSlice();
544}
545
546void LIC::setAxis(int axis)
547{
548    _axis = axis;
549}
550
551void LIC::reset()
552{
553    makePatterns();
554}
Note: See TracBrowser for help on using the repository browser.