source: trunk/packages/vizservers/nanovis/ParticleRenderer.cpp @ 3612

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

Remove Nv prefix from shader classes now that they are in nv namespace.

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