source: nanovis/branches/1.1/NvParticleRenderer.cpp @ 4879

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

Add basic VTK structured points reader to nanovis, update copyright dates.

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