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

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

Remove XINETD define from nanovis. We only support server mode now, no glut
interaction loop with mouse/keyboard handlers. Fixes for trace logging to make
output closer to vtkvis: inlcude function name for trace messages, remove
newlines from format strings in macros since newlines get added by syslog.

  • 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");
82            }
83            delete loader;
84        } else {
85            ERROR("Couldn't find loader for arrows image");
86        }
87    } else {
88        ERROR("Couldn't find arrows image");
89    }
90
91    GLfloat minMax[2];
92    glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, minMax);
93    TRACE("Aliased point size range: %g %g", minMax[0], minMax[1]);
94    _maxPointSize = minMax[1];
95    glGetFloatv(GL_SMOOTH_POINT_SIZE_RANGE, minMax);
96    TRACE("Smooth point size range: %g %g", minMax[0], minMax[1]);
97    _maxPointSize = minMax[1] > _maxPointSize ? minMax[1] : _maxPointSize;
98    TRACE("Max point size: %g", _maxPointSize);
99
100    TRACE("Leaving VelocityArrowsSlice constructor");
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", _vfXscale,_vfYscale, _vfZscale);
304    TRACE("_maxVelocityScale: %g %g %g",
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***", 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", _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.