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

Last change on this file since 3628 was 3612, checked in by ldelgass, 11 years ago

Remove Nv prefix from shader classes now that they are in nv namespace.

  • 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 *    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(int size, int width, int height, int axis,
27         float offset) :
28    _width(width),
29    _height(height),
30    _size(size),
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    _activate(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", "main");
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 LIC::makeMagnitudes()
181{
182    GLubyte mag[NMESH][NMESH][4];
183
184    //read vector field
185    for (int i = 0; i < NMESH; i++) {
186        for (int j = 0; j < NMESH; j++) {
187            float x = DM*i;
188            float y = DM*j;
189 
190            float magnitude = sqrt(x*x+y*y)/1.414;
191
192            //from green to red
193            GLubyte r = (GLubyte)floor(magnitude*255);
194            GLubyte g = 0;
195            GLubyte b = 255 - r;
196            GLubyte a = 122;
197
198            mag[i][j][0] = r;
199            mag[i][j][1] = g;
200            mag[i][j][2] = b;
201            mag[i][j][3] = a;
202        }
203    }
204    glGenTextures(1, &_magTex);
205    glBindTexture(GL_TEXTURE_2D, _magTex);
206    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
207    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
208    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
209    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
210    //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
211    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, NMESH, NMESH, 0, GL_RGBA,
212                 GL_UNSIGNED_BYTE, mag);
213    glBindTexture(GL_TEXTURE_2D, 0);
214}
215
216void
217LIC::getSlice()
218{
219    int fboOrig;
220    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fboOrig);
221
222    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _velFbo);
223
224    glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);
225
226    glClear(GL_COLOR_BUFFER_BIT);
227    glDisable(GL_DEPTH_TEST);
228    glDisable(GL_BLEND);
229
230    glViewport(0, 0, _size, _size);
231    glMatrixMode(GL_PROJECTION);
232    glPushMatrix();
233    glLoadIdentity();
234    gluOrtho2D(0, _size, 0, _size);
235    glMatrixMode(GL_MODELVIEW);
236    glPushMatrix();
237    glLoadIdentity();
238
239    glEnable(GL_TEXTURE_3D);
240    glBindTexture(GL_TEXTURE_3D, _vectorFieldId);
241
242    _renderVelShader->bind();
243    _renderVelShader->setFPTextureParameter("vel_tex", _vectorFieldId);
244    _renderVelShader->setFPParameter1f("timestep", 0.0005);
245    _renderVelShader->setFPParameter1f("vmax", _max > 100.0 ? 100.0 : _max);
246
247    switch (_axis) {
248    case 0:
249        _renderVelShader->setFPParameter3f("projection_vector", 0., 1., 1.);
250        break;
251    case 1:
252        _renderVelShader->setFPParameter3f("projection_vector", 1., 0., 1.);
253        break;
254    default:
255    case 2:
256        _renderVelShader->setFPParameter3f("projection_vector", 1., 1., 0.);
257        break;
258    }
259
260    glBegin(GL_QUADS);
261    {
262        switch (_axis) {
263        case 0:
264            glTexCoord3f(_offset, 0., 0.); glVertex2f(0.,    0.);
265            glTexCoord3f(_offset, 1., 0.); glVertex2f(_size, 0.);
266            glTexCoord3f(_offset, 1., 1.); glVertex2f(_size, _size);
267            glTexCoord3f(_offset, 0., 1.); glVertex2f(0.,    _size);
268            break;
269        case 1:
270            glTexCoord3f(0., _offset, 0.); glVertex2f(0.,    0.);
271            glTexCoord3f(1., _offset, 0.); glVertex2f(_size, 0.);
272            glTexCoord3f(1., _offset, 1.); glVertex2f(_size, _size);
273            glTexCoord3f(0., _offset, 1.); glVertex2f(0.,    _size);
274            break;
275        case 2:
276            glTexCoord3f(0., 0., _offset); glVertex2f(0.,    0.);
277            glTexCoord3f(1., 0., _offset); glVertex2f(_size, 0.);
278            glTexCoord3f(1., 1., _offset); glVertex2f(_size, _size);
279            glTexCoord3f(0., 1., _offset); glVertex2f(0.,    _size);
280            break;
281        }
282    }
283    glEnd();
284
285    _renderVelShader->disableFPTextureParameter("vel_tex");
286    _renderVelShader->unbind();
287
288    glBindTexture(GL_TEXTURE_3D, 0);
289    glDisable(GL_TEXTURE_3D);
290
291    //read the vectors
292    glReadPixels(0, 0, _size, _size, GL_RGBA, GL_FLOAT, _sliceVector);
293
294    int lim = _size * _size * 4;
295    float *v = _sliceVector;
296    for (int i = 0; i < lim; ++i) {
297        if (isnan(*v)) {
298            *v = 0.0f;   
299        }
300        ++v;
301    }
302
303    glMatrixMode(GL_PROJECTION);
304    glPopMatrix();
305    glMatrixMode(GL_MODELVIEW);
306    glPopMatrix();
307
308    glPopAttrib();
309
310    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig);
311}
312
313//line integral convolution
314void
315LIC::convolve()
316{
317    if (_vectorFieldId == 0) {
318        return;
319    }
320
321    int   i, j;
322    float x1, x2, y, px, py;
323
324    int fboOrig;
325    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fboOrig);
326
327    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo);
328
329    glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
330
331    glMatrixMode(GL_PROJECTION);
332    glPushMatrix();
333    glLoadIdentity();
334
335    glViewport(0, 0, (GLsizei) NPIX, (GLsizei) NPIX);
336    //glTranslatef(-1.0, -1.0, 0.0);
337    //glScalef(2.0, 2.0, 1.0);
338    glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -10.0f, 10.0f);
339
340    glMatrixMode(GL_MODELVIEW);
341    glPushMatrix();
342    glLoadIdentity();
343
344    glClear(GL_COLOR_BUFFER_BIT);
345    //glDepthMask(GL_FALSE);
346    glDisable(GL_DEPTH_TEST);
347    glDisable(GL_LIGHTING);
348    glDisable(GL_ALPHA_TEST);
349
350    //_sa = 0.010*cos(_iframe*2.0*M_PI/200.0);
351    glEnable(GL_TEXTURE_2D);
352    glBindTexture(GL_TEXTURE_2D, _patternTex);
353    _sa = 0.01;
354 
355    glColor4f(1, 1, 1, 1);
356    for (i = 0; i < NMESH-1; i++) {
357        x1 = DM*i; x2 = x1 + DM;
358        glBegin(GL_QUAD_STRIP);
359        for (j = 0; j < NMESH-1; j++) {
360            y = DM*j;
361            glTexCoord2f(x1, y);
362            getVelocity(x1, y, &px, &py);
363            glVertex2f(px, py);
364
365            glTexCoord2f(x2, y);
366            getVelocity(x2, y, &px, &py);
367            glVertex2f(px, py);
368        }
369        glEnd();
370    }
371    _iframe = _iframe + 1;
372
373    glEnable(GL_BLEND);
374
375    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
376
377    glEnable(GL_TEXTURE_2D);
378    glCallList(_iframe % _Npat + _disListID);
379    glBegin(GL_QUADS);
380    {
381        glTexCoord2f(0.0,   0.0);   glVertex2f(0.0, 0.0);
382        glTexCoord2f(_tmax, 0.0);   glVertex2f(1.0, 0.0);
383        glTexCoord2f(_tmax, _tmax); glVertex2f(1.0, 1.0);
384        glTexCoord2f(0.0,   _tmax); glVertex2f(0.0, 1.0);
385    }
386    glEnd();
387    glDisable(GL_TEXTURE_2D);
388
389    /*
390    //inject dye
391    glDisable(GL_TEXTURE_2D);
392    glColor4f(1.,0.8,0.,1.);
393    glBegin(GL_QUADS);
394    glVertex2d(0.6, 0.6);
395    glVertex2d(0.6, 0.62);
396    glVertex2d(0.62, 0.62);
397    glVertex2d(0.62, 0.6);
398    glEnd();
399    */
400
401    glDisable(GL_BLEND);
402    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, NPIX, NPIX, 0);
403
404    /*
405    //blend magnitude texture
406    glBindTexture(GL_TEXTURE_2D, _magTex);
407    glEnable(GL_TEXTURE_2D);
408    glEnable(GL_BLEND);
409    glBegin(GL_QUADS);
410    glTexCoord2f(0.0,  0.0);  glVertex2f(0.0, 0.0);
411    glTexCoord2f(0.0,  1.0); glVertex2f(0.0, 1.);
412    glTexCoord2f(1.0, 1.0);  glVertex2f(1., 1.);
413    glTexCoord2f(1.0, 0.0); glVertex2f(1., 0.0);
414    glEnd();
415    */
416
417    glMatrixMode(GL_PROJECTION);
418    glPopMatrix();
419    glMatrixMode(GL_MODELVIEW);
420    glPopMatrix();
421
422    glPopAttrib();
423
424    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig);
425}
426
427void
428LIC::render()
429{
430    if (_vectorFieldId == 0) {
431        return;
432    }
433
434    //draw line integral convolution quad
435
436    glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT);
437    glBindTexture(GL_TEXTURE_2D, _colorTex);
438    glEnable(GL_TEXTURE_2D);
439    //glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
440    //glEnable(GL_LIGHTING);
441    glDisable(GL_LIGHTING);
442    glEnable(GL_DEPTH_TEST);
443
444    glMatrixMode(GL_MODELVIEW);
445    glPushMatrix();
446
447    glTranslatef(_origin.x, _origin.y, _origin.z);
448    glScalef(_scale.x, _scale.y, _scale.z);
449
450    glColor4f(1, 1, 1, 1);
451    glBegin(GL_QUADS);
452    switch (_axis) {
453    case 0:
454        glNormal3f(1, 0, 0);
455        glTexCoord2f(0, 0); glVertex3f(_offset, 0, 0);
456        glTexCoord2f(1, 0); glVertex3f(_offset, 1, 0);
457        glTexCoord2f(1, 1); glVertex3f(_offset, 1, 1);
458        glTexCoord2f(0, 1); glVertex3f(_offset, 0, 1);
459        break;
460    case 1:
461        glNormal3f(0, 1, 0);
462        glTexCoord2f(0, 0); glVertex3f(0, _offset, 0);
463        glTexCoord2f(1, 0); glVertex3f(1, _offset, 0);
464        glTexCoord2f(1, 1); glVertex3f(1, _offset, 1);
465        glTexCoord2f(0, 1); glVertex3f(0, _offset, 1);
466        break;
467    case 2:
468        glNormal3f(0, 0, 1);
469        glTexCoord2f(0, 0); glVertex3f(0, 0, _offset);
470        glTexCoord2f(1, 0); glVertex3f(1, 0, _offset);
471        glTexCoord2f(1, 1); glVertex3f(1, 1, _offset);
472        glTexCoord2f(0, 1); glVertex3f(0, 1, _offset);
473        break;
474    }
475    glEnd();
476
477    glPopMatrix();
478
479    glBindTexture(GL_TEXTURE_2D, 0);
480
481    glPopAttrib();
482}
483
484void
485LIC::setVectorField(unsigned int texID, const Vector3f& origin,
486                      float scaleX, float scaleY, float scaleZ, float max)
487{
488    TRACE("LIC: vector field is assigned [%d]", texID);
489    _vectorFieldId = texID;
490    _origin = origin;
491    _scale = Vector3f(scaleX, scaleY, scaleZ);
492    _max = 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 0:
510       vx = _sliceVector[4 * (xi+yi*_size)+2];
511       vy = _sliceVector[4 * (xi+yi*_size)+1];
512       break;
513   case 1:
514       vx = _sliceVector[4 * (xi+yi*_size)];
515       vy = _sliceVector[4 * (xi+yi*_size)+2];
516       break;
517   case 2:
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::setOffset(float offset)
540{
541    _offset = offset;
542    getSlice();
543}
544
545void LIC::setAxis(int axis)
546{
547    _axis = axis;
548}
549
550void LIC::reset()
551{
552    makePatterns();
553}
Note: See TracBrowser for help on using the repository browser.