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

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

Assume baseline requirement of NV40 GPU, which translates to Cg profiles vp40
and fp40, which in turn require NV_vertex_program3 and NV_fragment_program2
assembly shader extensions. Add explicit check for these extensions.

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