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

Last change on this file since 3464 was 3452, checked in by ldelgass, 11 years ago

Remove XINETD define from nanovis. We only support server mode now, no glut
interaction loop with mouse/keyboard handlers. Fixes for trace logging to make
output closer to vtkvis: inlcude function name for trace messages, remove
newlines from format strings in macros since newlines get added by syslog.

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