source: nanovis/tags/1.2.0/ParticleRenderer.cpp @ 5049

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