source: nanovis/branches/1.1/ParticleRenderer.cpp @ 4904

Last change on this file since 4904 was 4904, checked in by ldelgass, 10 years ago

Merge serveral changes from trunk. Does not include threading, world space
changes, etc.

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