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

Last change on this file since 3492 was 3492, checked in by ldelgass, 6 years ago

Fix camera reset for nanovis. Includes refactoring of vector/matrix classes
in nanovis to consolidate into vrmath library. Also add preliminary canonical
view control to clients for testing.

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