source: nanovis/branches/1.1/NvLIC.cpp @ 4795

Last change on this file since 4795 was 3502, checked in by ldelgass, 12 years ago

Add basic VTK structured points reader to nanovis, update copyright dates.

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