source: trunk/packages/vizservers/nanovis/NvParticleRenderer.cpp @ 2956

Last change on this file since 2956 was 2956, checked in by ldelgass, 13 years ago

First batch of converting shaders to use new parameter support in NvShader?.

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