source: nanovis/branches/1.1/VelocityArrowsSlice.cpp @ 4822

Last change on this file since 4822 was 3502, checked in by ldelgass, 11 years ago

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

  • Property svn:eol-style set to native
File size: 18.4 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2004-2013  HUBzero Foundation, LLC
4 *
5 */
6#include "nvconf.h"
7
8#include <math.h>
9
10#include <GL/glew.h>
11#include <GL/gl.h>
12
13#include <vrmath/Vector3f.h>
14#include <util/FilePath.h>
15#include <Image.h>
16#include <ImageLoaderFactory.h>
17#include <ImageLoader.h>
18
19#include "nanovis.h"
20#include "VelocityArrowsSlice.h"
21#include "NvShader.h"
22#include "NvCamera.h"
23
24using namespace nv::util;
25using namespace vrmath;
26
27static inline float deg2rad(float deg)
28{
29    return ((deg * M_PI) / 180.);
30}
31
32static inline float rad2deg(float rad)
33{
34    return ((rad * 180.) / M_PI);
35}
36
37VelocityArrowsSlice::VelocityArrowsSlice() :
38    _vectorFieldGraphicsID(0),
39    _vfXscale(0),
40    _vfYscale(0),
41    _vfZscale(0),
42    _slicePos(0.5f),
43    _axis(2),
44    _fbo(0),
45    _tex(0),
46    _maxPointSize(1.0f),
47    _renderTargetWidth(128),
48    _renderTargetHeight(128),
49    _velocities(NULL),
50    _projectionVector(1, 1, 0),
51    _tickCountForMinSizeAxis(10),
52    _tickCountX(0),
53    _tickCountY(0),
54    _tickCountZ(0),
55    _pointCount(0),
56    _maxVelocityScale(1, 1, 1),
57    _arrowColor(1, 1, 0),
58    _enabled(false),
59    _dirty(true),
60    _vertexBufferGraphicsID(0),
61    _arrowsTex(NULL),
62    _renderMode(LINES)
63{
64    axis(2);
65
66    _queryVelocityFP.loadFragmentProgram("queryvelocity.cg", "main");
67
68    _particleShader.loadVertexProgram("velocityslicevp.cg", "vpmain");
69    _particleShader.loadFragmentProgram("velocityslicefp.cg", "fpmain");
70
71    createRenderTarget();
72
73    std::string path = FilePath::getInstance()->getPath("arrows.bmp");
74    if (!path.empty()) {
75        ImageLoader *loader = ImageLoaderFactory::getInstance()->createLoader("bmp");
76        if (loader != NULL) {
77            Image *image = loader->load(path.c_str(), Image::IMG_RGBA);
78            if (image != NULL) {
79                unsigned char *bytes = (unsigned char *)image->getImageBuffer();
80                if (bytes != NULL) {
81                    _arrowsTex = new Texture2D(image->getWidth(), image->getHeight(),
82                                               GL_UNSIGNED_BYTE, GL_LINEAR, 4, NULL);
83                    _arrowsTex->setWrapS(GL_MIRRORED_REPEAT);
84                    _arrowsTex->setWrapT(GL_MIRRORED_REPEAT);
85                    _arrowsTex->initialize(image->getImageBuffer());
86                }
87                delete image;
88            } else {
89                ERROR("Failed to load arrows image");
90            }
91            delete loader;
92        } else {
93            ERROR("Couldn't find loader for arrows image");
94        }
95    } else {
96        ERROR("Couldn't find arrows image");
97    }
98
99    GLfloat minMax[2];
100    glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, minMax);
101    TRACE("Aliased point size range: %g %g", minMax[0], minMax[1]);
102    _maxPointSize = minMax[1];
103    glGetFloatv(GL_SMOOTH_POINT_SIZE_RANGE, minMax);
104    TRACE("Smooth point size range: %g %g", minMax[0], minMax[1]);
105    _maxPointSize = minMax[1] > _maxPointSize ? minMax[1] : _maxPointSize;
106    TRACE("Max point size: %g", _maxPointSize);
107
108    TRACE("Leaving VelocityArrowsSlice constructor");
109}
110
111VelocityArrowsSlice::~VelocityArrowsSlice()
112{
113    if (_tex != 0) {
114        glDeleteTextures(1, &_tex);
115    }
116    if (_fbo != 0) {
117        glDeleteFramebuffersEXT(1, &_fbo);
118    }
119    if (_arrowsTex != NULL) {
120        delete _arrowsTex;
121    }
122    if (_vertexBufferGraphicsID != 0) {
123        glDeleteBuffers(1, &_vertexBufferGraphicsID);
124    }
125    if (_velocities != NULL) {
126        delete [] _velocities;
127    }
128}
129
130void VelocityArrowsSlice::createRenderTarget()
131{
132    if (_velocities != NULL) {
133        delete [] _velocities;
134    }
135    _velocities = new Vector3f[_renderTargetWidth * _renderTargetHeight];
136
137    if (_vertexBufferGraphicsID != 0) {
138        glDeleteBuffers(1, &_vertexBufferGraphicsID);
139    }
140
141    glGenBuffers(1, &_vertexBufferGraphicsID);
142    glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vertexBufferGraphicsID);
143    glBufferDataARB(GL_ARRAY_BUFFER_ARB, _renderTargetWidth * _renderTargetHeight * 3 * sizeof(float),
144                    0, GL_DYNAMIC_DRAW_ARB);
145    glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
146
147    if (_tex != 0) {
148        glDeleteTextures(1, &_tex);
149    }
150    if (_fbo != 0) {
151        glDeleteFramebuffersEXT(1, &_fbo);
152    }
153
154    glGenFramebuffersEXT(1, &_fbo);
155    glGenTextures(1, &_tex);
156    int fboOrig;
157    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fboOrig);
158    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo);
159
160    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _tex);
161    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
162    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
163    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
164    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
165
166    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB,
167                 _renderTargetWidth, _renderTargetHeight, 0,
168                 GL_RGBA, GL_FLOAT, NULL);
169
170    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
171                              GL_TEXTURE_RECTANGLE_ARB, _tex, 0);
172
173    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig);
174}
175
176void VelocityArrowsSlice::axis(int axis)
177{
178    _axis = axis;
179    switch (_axis) {
180    case 0:
181        _projectionVector.x = 0;
182        _projectionVector.y = 1;
183        _projectionVector.z = 1;
184        break;
185    case 1 :
186        _projectionVector.x = 1;
187        _projectionVector.y = 0;
188        _projectionVector.z = 1;
189        break;
190    case 2:
191        _projectionVector.x = 1;
192        _projectionVector.y = 1;
193        _projectionVector.z = 0;
194        break;
195    }
196    _dirty = true;
197}
198
199void VelocityArrowsSlice::queryVelocity()
200{
201    if (!_enabled) return;
202
203    glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);
204    int fboOrig;
205    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fboOrig);
206
207    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo);
208
209    _queryVelocityFP.bind();
210    _queryVelocityFP.setFPTextureParameter("vfield", _vectorFieldGraphicsID);
211
212    glDisable(GL_DEPTH_TEST);
213    glViewport(0, 0, _renderTargetWidth, _renderTargetHeight);
214    glMatrixMode(GL_PROJECTION);
215    glPushMatrix();
216    glLoadIdentity();
217    glOrtho(0, _renderTargetWidth, 0, _renderTargetHeight, -10.0f, 10.0f);
218    glMatrixMode(GL_MODELVIEW);
219    glPushMatrix();
220    glLoadIdentity();
221
222    glBegin(GL_QUADS);
223    switch (_axis) {
224    case 0:
225        glTexCoord3f(_slicePos, 0, 0); glVertex2i(0,                  0);
226        glTexCoord3f(_slicePos, 1, 0); glVertex2i(_renderTargetWidth, 0);
227        glTexCoord3f(_slicePos, 1, 1); glVertex2i(_renderTargetWidth, _renderTargetHeight);
228        glTexCoord3f(_slicePos, 0, 1); glVertex2i(0,                  _renderTargetHeight);
229        break;
230    case 1:
231        glTexCoord3f(0, _slicePos, 0); glVertex2i(0,                  0);
232        glTexCoord3f(1, _slicePos, 0); glVertex2i(_renderTargetWidth, 0);
233        glTexCoord3f(1, _slicePos, 1); glVertex2i(_renderTargetWidth, _renderTargetHeight);
234        glTexCoord3f(0, _slicePos, 1); glVertex2i(0,                  _renderTargetHeight);
235        break;
236    case 2:
237    default:
238        glTexCoord3f(0, 0, _slicePos); glVertex2i(0,                  0);
239        glTexCoord3f(1, 0, _slicePos); glVertex2i(_renderTargetWidth, 0);
240        glTexCoord3f(1, 1, _slicePos); glVertex2i(_renderTargetWidth, _renderTargetHeight);
241        glTexCoord3f(0, 1, _slicePos); glVertex2i(0,                  _renderTargetHeight);
242        break;
243    }
244    glEnd();
245
246    _queryVelocityFP.disableFPTextureParameter("vfield");
247    _queryVelocityFP.unbind();
248
249    glReadPixels(0, 0, _renderTargetWidth, _renderTargetHeight, GL_RGB, GL_FLOAT, _velocities);
250
251    glMatrixMode(GL_PROJECTION);
252    glPopMatrix();
253    glMatrixMode(GL_MODELVIEW);
254    glPopMatrix();
255
256    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig);
257
258    glPopAttrib();
259}
260
261static void drawLineArrow(int axis)
262{
263    glBegin(GL_LINES);
264    switch (axis) {
265    case 0: // ZY plane
266        glVertex3f(0.0, 0.0, 0.0);
267        glVertex3f(0.0, 0.0, 1.0);
268
269        glVertex3f(0.0, 0.0, 1.0);
270        glVertex3f(0.0, 0.25, 0.75);
271
272        glVertex3f(0.0, 0.0, 1.0);
273        glVertex3f(0.0, -0.25, 0.75);
274        break;
275    case 1: // XZ plane
276        glVertex3f(0.0, 0.0, 0.0);
277        glVertex3f(1.0, 0.0, 0.0);
278
279        glVertex3f(1.0, 0.0, 0.0);
280        glVertex3f(0.75, 0.0, 0.25);
281
282        glVertex3f(1.0, 0.0, 0.0);
283        glVertex3f(0.75, 0.0, -0.25);
284        break;
285    case 2: // XY plane
286    default:
287        glVertex3f(0.0, 0.0, 0.0);
288        glVertex3f(1.0, 0.0, 0.0);
289
290        glVertex3f(1.0, 0.0, 0.0);
291        glVertex3f(0.75, 0.25, 0.0);
292
293        glVertex3f(1.0, 0.0, 0.0);
294        glVertex3f(0.75, -0.25, 0.0);
295        break;
296    }
297    glEnd();
298}
299
300void VelocityArrowsSlice::render()
301{
302    if (!_enabled)
303        return;
304
305    if (_dirty) {
306        computeSamplingTicks();
307        queryVelocity();
308        _dirty = false;
309    }
310
311    TRACE("_vf: %g %g %g", _vfXscale,_vfYscale, _vfZscale);
312    TRACE("_maxVelocityScale: %g %g %g",
313          _maxVelocityScale.x, _maxVelocityScale.y, _maxVelocityScale.z);
314
315    glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
316
317    glMatrixMode(GL_MODELVIEW);
318    glPushMatrix();
319
320    glScalef(_vfXscale,_vfYscale, _vfZscale);
321    glTranslatef(-0.5f, -0.5f, -0.5f);
322
323    if (_renderMode == LINES) {
324        glDisable(GL_TEXTURE_2D);
325        glDisable(GL_LIGHTING);
326        glLineWidth(2.0);
327        glColor3f(_arrowColor.x, _arrowColor.y, _arrowColor.z);
328 
329        Vector3f pos;
330        Vector3f vel;
331        Vector3f refVec;
332        Vector3f blue(0, 0, 1);
333        Vector3f red(1, 0, 0);
334
335        int index = 0, icount, jcount;
336        switch (_axis) {
337        case 0:
338            icount = _tickCountZ;
339            jcount = _tickCountY;
340            refVec.set(0, 0, 1);
341            break;
342        case 1:
343            icount = _tickCountZ;
344            jcount = _tickCountX;
345            refVec.set(1, 0, 0);
346            break;
347        case 2:
348        default:
349            icount = _tickCountY;
350            jcount = _tickCountX;
351            refVec.set(1, 0, 0);
352            break;
353        }
354
355        for (int i = 0; i < icount; ++i) {
356            for (int j = 0; j < jcount; ++j, ++index) {
357                pos = _samplingPositions[index];
358                // Normalized velocity: [-1,1] components
359                // Project 3D vector onto sample plane
360                vel = _velocities[index].scale(_projectionVector);
361                // Length: [0,1]
362                double length = vel.length();
363                if (length < 0.0 || length > 1.0) {
364                    TRACE("***vec: (%g, %g, %g) length: %g***", vel.x, vel.y, vel.z, length);
365                    continue;
366                }
367                if (length > 1.0e-6) {
368                    Vector3f vnorm = vel.normalize();
369                    Vector3f rotationAxis = refVec.cross(vnorm);
370                    double angle = rad2deg(acos(refVec.dot(vnorm)));
371                    Vector3f color = blue * (1.0 - length) + red * length;
372                    float scale = length;
373                    if (scale < 0.10) scale = 0.10;
374                    glMatrixMode(GL_MODELVIEW);
375                    glPushMatrix();
376                    glColor3f(color.x, color.y, color.z);
377                    glTranslatef(pos.x, pos.y, pos.z);
378                    glScalef(2.0 * _maxVelocityScale.x,
379                             2.0 * _maxVelocityScale.y,
380                             2.0 * _maxVelocityScale.z);
381                    glScalef(scale, scale, scale);
382                    if (angle > 1.0e-6 || angle < -1.0e-6)
383                        glRotated(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
384                    drawLineArrow(_axis);
385                    glPopMatrix();
386                }
387            }
388        }
389
390        glLineWidth(1.0);
391    } else {
392        glColor4f(_arrowColor.x, _arrowColor.y, _arrowColor.z, 1.0f);
393        glEnable(GL_DEPTH_TEST);
394        glDisable(GL_LIGHTING);
395#if 0
396        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
397        glEnable(GL_BLEND);
398        glDepthMask(GL_FALSE);
399#else
400        glDisable(GL_BLEND);
401#endif
402        glAlphaFunc(GL_GREATER, 0.6);
403        glEnable(GL_ALPHA_TEST);
404        glEnable(GL_POINT_SPRITE_ARB);
405        glPointSize(20);
406        glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
407
408        _arrowsTex->activate();
409        glEnable(GL_TEXTURE_2D);
410        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
411
412        GLfloat atten[] = {1, 0, 0};
413        glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, atten);
414        glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 0.0f);
415        glPointParameterfARB(GL_POINT_SIZE_MIN_ARB, 1.0f);
416        glPointParameterfARB(GL_POINT_SIZE_MAX_ARB, _maxPointSize);
417        glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
418
419        _particleShader.bind();
420        _particleShader.setVPTextureParameter("vfield", _vectorFieldGraphicsID);
421        _particleShader.setFPTextureParameter("arrows", _arrowsTex->id());
422        _particleShader.setVPParameter1f("tanHalfFOV",
423                                         tan(NanoVis::getCamera()->fov() * 0.5) * NanoVis::winHeight * 0.5);
424        _particleShader.setGLStateMatrixVPParameter("modelview",
425                                                    NvShader::MODELVIEW_MATRIX,
426                                                    NvShader::MATRIX_IDENTITY);
427        _particleShader.setGLStateMatrixVPParameter("mvp",
428                                                    NvShader::MODELVIEW_PROJECTION_MATRIX,
429                                                    NvShader::MATRIX_IDENTITY);
430
431        glEnableClientState(GL_VERTEX_ARRAY);
432        glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vertexBufferGraphicsID);
433        glVertexPointer(3, GL_FLOAT, 0, 0);
434        //glEnableClientState(GL_COLOR_ARRAY);
435
436        // TBD..
437        glDrawArrays(GL_POINTS, 0, _pointCount);
438        glPointSize(1);
439
440        glDisableClientState(GL_VERTEX_ARRAY);
441        glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
442        glDisable(GL_POINT_SPRITE_ARB);
443
444        _particleShader.disableVPTextureParameter("vfield");
445        _particleShader.disableFPTextureParameter("arrows");
446        _particleShader.unbind();
447
448        glActiveTexture(GL_TEXTURE0);
449        glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_FALSE);
450        _arrowsTex->deactivate();
451    }
452
453    glPopMatrix();
454    glPopAttrib();
455}
456
457void
458VelocityArrowsSlice::setVectorField(unsigned int vfGraphicsID, const Vector3f& origin,
459                                    float xScale, float yScale, float zScale, float max)
460{
461    _vectorFieldGraphicsID = vfGraphicsID;
462    _vfXscale = xScale;
463    _vfYscale = yScale;
464    _vfZscale = zScale;
465
466    _dirty = true;
467}
468
469void VelocityArrowsSlice::computeSamplingTicks()
470{
471    if (_vfXscale < _vfYscale) {
472        if (_vfXscale < _vfZscale || _vfZscale == 0.0) {
473            // vfXscale
474            _tickCountX = _tickCountForMinSizeAxis;
475
476            float step = _vfXscale / (_tickCountX + 1);
477
478            _tickCountY = (int)(_vfYscale/step);
479            _tickCountZ = (int)(_vfZscale/step);
480        } else {
481            // vfZscale
482            _tickCountZ = _tickCountForMinSizeAxis;
483
484            float step = _vfZscale / (_tickCountZ + 1);
485            _tickCountX = (int)(_vfXscale/step);
486            _tickCountY = (int)(_vfYscale/step);
487        }
488    } else {
489        if (_vfYscale < _vfZscale || _vfZscale == 0.0) {
490            // _vfYscale
491            _tickCountY = _tickCountForMinSizeAxis;
492
493            float step = _vfYscale / (_tickCountY + 1);
494            _tickCountX = (int)(_vfXscale/step);
495            _tickCountZ = (int)(_vfZscale/step);
496        } else {
497            // vfZscale
498            _tickCountZ = _tickCountForMinSizeAxis;
499
500            float step = _vfZscale / (_tickCountZ + 1);
501            _tickCountX = (int)(_vfXscale/step);
502            _tickCountY = (int)(_vfYscale/step);
503        }
504    }
505
506    switch (_axis) {
507    case 0:
508        _tickCountX = 1;
509        _renderTargetWidth = _tickCountY;
510        _renderTargetHeight = _tickCountZ;
511        break;
512    case 1:
513        _tickCountY = 1;
514        _renderTargetWidth = _tickCountX;
515        _renderTargetHeight = _tickCountZ;
516        break;
517    default:
518    case 2:
519        _tickCountZ = 1;
520        _renderTargetWidth = _tickCountX;
521        _renderTargetHeight = _tickCountY;
522        break;
523    }
524
525    _maxVelocityScale.x = (1.0f / _tickCountX) * 0.8f;
526    _maxVelocityScale.y = (1.0f / _tickCountY) * 0.8f;
527    _maxVelocityScale.z = (1.0f / _tickCountZ) * 0.8f;
528
529    TRACE("Tick counts: %d %d %d", _tickCountX, _tickCountY, _tickCountZ);
530
531    int pointCount = _tickCountX * _tickCountY * _tickCountZ;
532    if (_pointCount != pointCount) {
533        _samplingPositions.clear();
534        _samplingPositions.reserve(pointCount);
535        _pointCount = pointCount;
536    }
537
538    createRenderTarget();
539
540    Vector3f pos;
541    Vector3f *pinfo = NULL;
542    if (_renderMode == GLYPHS) {
543        glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vertexBufferGraphicsID);
544        pinfo = (Vector3f *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
545    }
546
547    if (_axis == 2) {
548        for (int y = 1; y <= _tickCountY; ++y) {
549            for (int x = 1; x <= _tickCountX; ++x) {
550                pos.x = (1.0f / (_tickCountX + 1)) * x;
551                pos.y = (1.0f / (_tickCountY + 1)) * y;
552                pos.z = _slicePos;
553                if (_renderMode == LINES) {
554                    _samplingPositions.push_back(pos);
555                } else {
556                    *pinfo = pos;
557                    ++pinfo;
558                }
559            }
560        }
561    } else if (_axis == 1) {
562        for (int z = 1; z <= _tickCountZ; ++z) {
563            for (int x = 1; x <= _tickCountX; ++x) {
564                pos.x = (1.0f / (_tickCountX + 1)) * x;
565                pos.y = _slicePos;
566                pos.z = (1.0f / (_tickCountZ + 1)) * z;
567                if (_renderMode == LINES) {
568                    _samplingPositions.push_back(pos);
569                } else {
570                    *pinfo = pos;
571                    ++pinfo;
572                }
573            }
574        }
575    } else if (_axis == 0) {
576        for (int z = 1; z <= _tickCountZ; ++z) {
577            for (int y = 1; y <= _tickCountY; ++y) {
578                pos.x = _slicePos;
579                pos.y = (1.0f / (_tickCountY + 1)) * y;
580                pos.z = (1.0f / (_tickCountZ + 1)) * z;
581                if (_renderMode == LINES) {
582                    _samplingPositions.push_back(pos);
583                } else {
584                    *pinfo = pos;
585                    ++pinfo;
586                }
587            }
588        }
589    }
590
591    if (_renderMode == GLYPHS) {
592        glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
593    }
594}
Note: See TracBrowser for help on using the repository browser.