source: trunk/packages/vizservers/nanovis/NvLIC.cpp @ 3423

Last change on this file since 3423 was 3177, checked in by mmc, 12 years ago

Updated all of the copyright notices to reference the transfer to
the new HUBzero Foundation, LLC.

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