source: nanovis/trunk/ParticleRenderer.cpp

Last change on this file was 5587, checked in by ldelgass, 4 years ago

Some fixes from release branch

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