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

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

remove global.h header. Move global Cg context handle into NvShader? as a
static member. Move LoadCgSourceProgram? to NvShader?.cpp, but make shader
classes use the methods NvShader::loadVertex/FragmentProgram instead.
There are still some users of LoadCgSourceProgram? left that need the context
handle.

  • 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_FP30, "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_FP30);
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_FP30);
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.