source: nanovis/trunk/ParticleRenderer.cpp @ 5303

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

Refactor names in particle renderer to match other classes

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