source: trunk/packages/vizservers/nanovis/VelocityArrowsSlice.cpp @ 3362

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

Merge nanovis2 branch to trunk

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