source: nanovis/trunk/ParticleRenderer.cpp @ 5722

Last change on this file since 5722 was 5587, checked in by ldelgass, 9 years ago

Some fixes from release branch

  • Property svn:eol-style set to native
File size: 9.4 KB
RevLine 
[2798]1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
[3611]2/*
[3502]3 *  Copyright (c) 2004-2013  HUBzero Foundation, LLC
[1028]4 *
[3611]5 *  Authors:
6 *    Wei Qiao <qiaow@purdue.edu>
[1028]7 */
8
9#include <assert.h>
10#include <string.h>
[2831]11#include <stdlib.h>
[1028]12
[2958]13#include <GL/glew.h>
14
[3630]15#include <vrmath/Vector3f.h>
[3627]16#include <vrmath/Color4f.h>
17
[3611]18#include "ParticleRenderer.h"
[5587]19#include "ParticleAdvectionShader.h"
[3630]20#include "Volume.h"
[2870]21#include "define.h"
[2831]22#include "Trace.h"
[1028]23
[3630]24using namespace vrmath;
[3611]25using namespace nv;
[1478]26
[3611]27ParticleRenderer::ParticleRenderer(int w, int h) :
[2883]28    _initPosTex(0),
29    _data(NULL),
30    _psysFrame(0),
31    _reborn(true),
32    _flip(true),
33    _maxLife(500),
[1497]34    _particleSize(1.2),
[2883]35    _vertexArray(NULL),
36    _scale(1, 1, 1),
37    _origin(0, 0, 0),
38    _activate(false),
39    _slicePos(0.0),
[3630]40    _sliceAxis(AXIS_Z),
[2883]41    _color(0.2, 0.2, 1.0, 1.0),
42    _psysWidth(w),
43    _psysHeight(h)
[1028]44{
[2883]45    _data = new Particle[w * h];
[1028]46
[2883]47    _vertexArray = new RenderVertexArray(_psysWidth * _psysHeight, 3, GL_FLOAT);
[1370]48
[1429]49    assert(CheckGL(AT));
[1028]50
[2883]51    glGenFramebuffersEXT(2, _psysFbo);
52    glGenTextures(2, _psysTex);
[1028]53
[2921]54    int fboOrig;
55    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fboOrig);
56
[2883]57    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _psysFbo[0]);
[1028]58
[2884]59    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _psysTex[0]);
60    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
61    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
[1028]62
[2883]63#ifdef HAVE_FLOAT_TEXTURES
[2884]64    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB,
[2883]65                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, NULL);
[1028]66#else
[2884]67    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
[2883]68                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, NULL);
[1028]69#endif
[1362]70    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
[2884]71                              GL_TEXTURE_RECTANGLE_ARB, _psysTex[0], 0);
[1028]72
[2956]73    CHECK_FRAMEBUFFER_STATUS();
[1331]74
[2883]75    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _psysFbo[1]);
[1028]76
[2884]77    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _psysTex[1]);
78    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
79    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
[2883]80#ifdef HAVE_FLOAT_TEXTURES
[2884]81    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB,
[2883]82                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, NULL);
[1028]83#else
[2884]84    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
[2883]85                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, NULL);
[1028]86#endif
[1362]87    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
[2884]88                              GL_TEXTURE_RECTANGLE_ARB, _psysTex[1], 0);
[1331]89 
[2956]90    CHECK_FRAMEBUFFER_STATUS();
91
[2921]92    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig);
[1028]93
[2883]94    glGenTextures(1, &_initPosTex);
[2884]95    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _initPosTex);
96    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
97    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
[2883]98#ifdef HAVE_FLOAT_TEXTURES
[2884]99    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB,
[2883]100                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, NULL);
[1331]101#else
[2884]102    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
[2883]103                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, NULL);
[1331]104#endif
105
[3630]106    _advectionShader = new ParticleAdvectionShader();
[1028]107}
108
[3611]109ParticleRenderer::~ParticleRenderer()
[1028]110{
[2883]111    glDeleteTextures(1, &_initPosTex);
[1481]112
[2883]113    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _psysFbo[0]);
114    glDeleteTextures(1, _psysTex);
[1028]115
[2883]116    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _psysFbo[1]);
117    glDeleteTextures(1, _psysTex+1);
[1028]118
[2883]119    glDeleteFramebuffersEXT(2, _psysFbo);
[1028]120
[3630]121    delete _advectionShader;
[2883]122    delete _vertexArray;
123    delete [] _data;
[1028]124}
125
[3611]126void
127ParticleRenderer::initializeDataArray()
[1028]128{
[3630]129    TRACE("Enter axis: %d pos: %g", _sliceAxis, _slicePos);
[1370]130
[3630]131    memset(_data, 0, sizeof(Particle) * _psysWidth * _psysHeight);
[5404]132
[3630]133    bool hasParticle;
[2883]134    for (int i = 0; i < _psysWidth; i++) {
135        for (int j = 0; j < _psysHeight; j++) {
[3630]136            Particle *p = &_data[i + _psysHeight*j];
137            hasParticle = (rand() % 256) > 150;
[5404]138            if (hasParticle) {
[1370]139                //assign any location (x,y,z) in range [0,1]
[2883]140                switch (_sliceAxis) {
[3630]141                case AXIS_X:
142                    p->x = _slicePos;
143                    p->y = j/float(_psysHeight);
144                    p->z = i/float(_psysWidth);
[2883]145                    break;
[3630]146                case AXIS_Y:
147                    p->x = j/float(_psysHeight);
148                    p->y = _slicePos;
149                    p->z = i/float(_psysWidth);
[2883]150                    break;
[3630]151                case AXIS_Z:
152                    p->x = j/float(_psysHeight);
153                    p->y = i/float(_psysWidth);
154                    p->z = _slicePos;
[2883]155                    break;
156                default:
[3630]157                    ERROR("Unknown axis");
[2883]158                }
159                //shorter life span, quicker iterations
[5483]160                p->life = rand() / ((float) RAND_MAX) * 0.5  + 0.5f;
[2883]161            }
[1370]162        }
163    }
164}
165
[3611]166void
167ParticleRenderer::initialize()
[1370]168{
[3630]169    TRACE("Enter");
170
[1370]171    initializeDataArray();
172
[2884]173    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _psysTex[0]);
[2883]174#ifdef HAVE_FLOAT_TEXTURES
[2884]175    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB,
[2883]176                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, (float*)_data);
[1028]177#else
[2884]178    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
[2883]179                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, (float*)_data);
[1028]180#endif
[2884]181    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
[1028]182
[2883]183    _flip = true;
184    _reborn = false;
[3630]185    _psysFrame = 0;
[2883]186
[2884]187    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _initPosTex);
[2883]188#ifdef HAVE_FLOAT_TEXTURES
[2884]189    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB,
[2883]190                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, (float*)_data);
[1331]191#else
[2884]192    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
[2883]193                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, (float*)_data);
[1331]194#endif
[2884]195    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
[1331]196
[3452]197    TRACE("Leave");
[1028]198}
199
[3611]200void
201ParticleRenderer::reset()
[1028]202{
[2884]203    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _psysTex[0]);
[2883]204#ifdef HAVE_FLOAT_TEXTURES
[2884]205    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB,
[2883]206                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, (float*)_data);
[1028]207#else
[2884]208    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
[2883]209                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, (float*)_data);
[1028]210#endif
[2884]211    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
[2883]212    _flip = true;
213    _reborn = false;
214    _psysFrame = 0;
[1028]215}
216
[3611]217void
218ParticleRenderer::advect()
[1028]219{
[3630]220    TRACE("Enter");
221
[2883]222    if (_reborn)
[1028]223        reset();
[2883]224
[2921]225    glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);
226
227    int fboOrig;
228    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fboOrig);
229
[1028]230    glDisable(GL_BLEND);
231    glDisable(GL_DEPTH_TEST);
[2837]232
[2921]233    int fbo, tex;
[2883]234    if (_flip) {
[2921]235        fbo = 1;
236        tex = 0;
237    } else {
238        fbo = 0;
239        tex = 1;
240    }
[2883]241
[2921]242    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _psysFbo[fbo]);
243    glEnable(GL_TEXTURE_RECTANGLE_ARB);
244    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _psysTex[tex]);
[2883]245
[2921]246    glClear(GL_COLOR_BUFFER_BIT);
[2883]247
[2921]248    glViewport(0, 0, _psysWidth, _psysHeight);
249    glMatrixMode(GL_PROJECTION);
250    glPushMatrix();
251    glLoadIdentity();
252    glOrtho(0, _psysWidth, 0, _psysHeight, -10.0f, 10.0f);
253    glMatrixMode(GL_MODELVIEW);
254    glPushMatrix();
255    glLoadIdentity();
[2883]256
[3630]257    _advectionShader->bind(_psysTex[tex], _initPosTex, _psysFrame == 0);
[2883]258
[2921]259    draw_quad(_psysWidth, _psysHeight, _psysWidth, _psysHeight);
[2883]260
[2921]261    _advectionShader->unbind();
[2883]262
[2921]263    glMatrixMode(GL_PROJECTION);
264    glPopMatrix();
[2883]265
[2921]266    glMatrixMode(GL_MODELVIEW);
267    glPopMatrix();
[2883]268
[2921]269    glDisable(GL_TEXTURE_RECTANGLE_ARB);
[2837]270
[2883]271    updateVertexBuffer();
[2837]272
[2883]273    _flip = (!_flip);
[2837]274
[2883]275    _psysFrame++;
276    if (_psysFrame == _maxLife) {
[3630]277        //_psysFrame = 0;
278        //_reborn = true;
[1362]279    }
[2921]280    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig);
281
282    glPopAttrib();
[1028]283}
284
[2883]285void
[3611]286ParticleRenderer::updateVertexBuffer()
[1028]287{
[2921]288    _vertexArray->read(_psysWidth, _psysHeight);
[1028]289}
290
[3611]291void
292ParticleRenderer::render()
[1028]293{
[3630]294    if (_psysFrame == 0) {
295        TRACE("Initializing vertex array");
296        advect();
297    }
298
[2921]299    glPushAttrib(GL_ENABLE_BIT);
[1028]300    glDisable(GL_TEXTURE_2D);
301    glDisable(GL_BLEND);
302    glEnable(GL_DEPTH_TEST);
303
304    glEnable(GL_COLOR_MATERIAL);
305
[2921]306    glMatrixMode(GL_MODELVIEW);
[1028]307    glPushMatrix();
308
[2883]309    glTranslatef(_origin.x, _origin.y, _origin.z);
310    glScaled(_scale.x, _scale.y, _scale.z);
[1028]311
[1497]312    glPointSize(_particleSize);
[1370]313    glColor4f(_color.x, _color.y, _color.z, _color.w);
[2956]314
[1028]315    glEnableClientState(GL_VERTEX_ARRAY);
[2921]316    _vertexArray->setPointer(0);
[2883]317    glDrawArrays(GL_POINTS, 0, _psysWidth * _psysHeight);
[1028]318    glDisableClientState(GL_VERTEX_ARRAY);
319
320    glPopMatrix();
[2921]321    glPopAttrib();
[1028]322}
323
[1362]324void
[3630]325ParticleRenderer::setVectorField(Volume *volume)
[1028]326{
[3630]327    Vector3f bmin, bmax;
328    volume->getBounds(bmin, bmax);
329    _origin = bmin;
330    Vector3f scale(bmax.x-bmin.x, bmax.y-bmin.y, bmax.z-bmin.z);
331    _scale.set(scale.x, scale.y, scale.z);
[2883]332    _advectionShader->setScale(_scale);
[3630]333    _advectionShader->setVelocityVolume(volume->textureID(),
334                                        volume->wAxis.max());
[1028]335}
[1370]336
[3611]337void
[3631]338ParticleRenderer::setSliceAxis(FlowSliceAxis axis)
[1370]339{
[3630]340    if (axis != _sliceAxis) {
341        _sliceAxis = axis;
342        initialize();
343    }
[1370]344}
345
[3611]346void
[3631]347ParticleRenderer::setSlicePosition(float pos)
[1370]348{
[3630]349    if (pos != _slicePos) {
350        _slicePos = pos;
351        initialize();
352    }
[1370]353}
Note: See TracBrowser for help on using the repository browser.