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

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

style/formatting cleanups in particle renderer

  • Property svn:eol-style set to native
File size: 12.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 <stdio.h>
18#include <assert.h>
19#include <malloc.h>
20#include <string.h>
21#include <stdlib.h>
22
23#include <R2/R2FilePath.h>
24
25#include "NvParticleRenderer.h"
26#include "define.h"
27#include "Trace.h"
28
29NvParticleAdvectionShader *NvParticleRenderer::_advectionShader = NULL;
30
31class NvParticleAdvectionShaderInstance
32{
33public :
34    NvParticleAdvectionShaderInstance()
35    {}
36
37    ~NvParticleAdvectionShaderInstance()
38    {
39        if (NvParticleRenderer::_advectionShader) {
40            delete NvParticleRenderer::_advectionShader;
41        }
42    }
43};
44
45NvParticleAdvectionShaderInstance shaderInstance;
46
47NvParticleRenderer::NvParticleRenderer(int w, int h) :
48    _initPosTex(0),
49    _data(NULL),
50    _psysFrame(0),
51    _reborn(true),
52    _flip(true),
53    _maxLife(500),
54    _particleSize(1.2),
55    _vertexArray(NULL),
56    _scale(1, 1, 1),
57    _origin(0, 0, 0),
58    _activate(false),
59    _slicePos(0.0),
60    _sliceAxis(0),
61    _color(0.2, 0.2, 1.0, 1.0),
62    _psysWidth(w),
63    _psysHeight(h)
64{
65    _data = new Particle[w * h];
66    memset(_data, 0, sizeof(Particle) * w * h);
67
68    _vertexArray = new RenderVertexArray(_psysWidth * _psysHeight, 3, GL_FLOAT);
69
70    assert(CheckGL(AT));
71
72    glGenFramebuffersEXT(2, _psysFbo);
73    glGenTextures(2, _psysTex);
74
75    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _psysFbo[0]);
76
77    glBindTexture(GL_TEXTURE_RECTANGLE_NV, _psysTex[0]);
78    glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
79    glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
80
81#ifdef HAVE_FLOAT_TEXTURES
82    glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA32F_ARB,
83                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, NULL);
84#else
85    glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA,
86                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, NULL);
87#endif
88    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
89                              GL_TEXTURE_RECTANGLE_NV, _psysTex[0], 0);
90
91
92    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _psysFbo[1]);
93
94    glBindTexture(GL_TEXTURE_RECTANGLE_NV, _psysTex[1]);
95    glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
96    glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
97#ifdef HAVE_FLOAT_TEXTURES
98    glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA32F_ARB,
99                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, NULL);
100#else
101    glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 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_NV, _psysTex[1], 0);
106 
107    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
108
109    glGenTextures(1, &_initPosTex);
110    glBindTexture(GL_TEXTURE_RECTANGLE_NV, _initPosTex);
111    glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
112    glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
113#ifdef HAVE_FLOAT_TEXTURES
114    glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA32F_ARB,
115                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, NULL);
116#else
117    glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA,
118                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, NULL);
119#endif
120
121    CHECK_FRAMEBUFFER_STATUS();
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    //also store the data on main memory for next initialization
198    //memcpy(data, p, psys_width*psys_height*sizeof(Particle));
199
200    glBindTexture(GL_TEXTURE_RECTANGLE_NV, _psysTex[0]);
201#ifdef HAVE_FLOAT_TEXTURES
202    glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA32F_ARB,
203                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, (float*)_data);
204#else
205    glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA,
206                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, (float*)_data);
207#endif
208    glBindTexture(GL_TEXTURE_RECTANGLE_NV, 0);
209
210    _flip = true;
211    _reborn = false;
212
213    glBindTexture(GL_TEXTURE_RECTANGLE_NV, _initPosTex);
214#ifdef HAVE_FLOAT_TEXTURES
215    glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA32F_ARB,
216                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, (float*)_data);
217#else
218    glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA,
219                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, (float*)_data);
220#endif
221    glBindTexture(GL_TEXTURE_RECTANGLE_NV, 0);
222
223    TRACE("init particles\n");
224}
225
226void NvParticleRenderer::reset()
227{
228    glBindTexture(GL_TEXTURE_RECTANGLE_NV, _psysTex[0]);
229#ifdef HAVE_FLOAT_TEXTURES
230    glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA32F_ARB,
231                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, (float*)_data);
232#else
233    glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA,
234                 _psysWidth, _psysHeight, 0, GL_RGBA, GL_FLOAT, (float*)_data);
235#endif
236    glBindTexture(GL_TEXTURE_RECTANGLE_NV, 0);
237    _flip = true;
238    _reborn = false;
239    _psysFrame = 0;
240}
241
242void
243NvParticleRenderer::advect()
244{
245    if (_reborn)
246        reset();
247
248    glDisable(GL_BLEND);
249    glDisable(GL_DEPTH_TEST);
250
251    if (_flip) {
252        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _psysFbo[1]);
253        glEnable(GL_TEXTURE_RECTANGLE_NV);
254        glBindTexture(GL_TEXTURE_RECTANGLE_NV, _psysTex[0]);
255
256        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
257        //glClear(GL_COLOR_BUFFER_BIT);
258
259        glViewport(0, 0, _psysWidth, _psysHeight);
260        glMatrixMode(GL_PROJECTION);
261        glLoadIdentity();
262        //gluOrtho2D(0, _psysWidth, 0, _psysHeight);
263        glOrtho(0, _psysWidth, 0, _psysHeight, -10.0f, 10.0f);
264        glMatrixMode(GL_MODELVIEW);
265        glLoadIdentity();
266
267        _advectionShader->bind(_psysTex[0], _initPosTex);
268
269        draw_quad(_psysWidth, _psysHeight, _psysWidth, _psysHeight);
270
271        glDisable(GL_TEXTURE_RECTANGLE_NV);
272    } else {
273        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _psysFbo[0]);
274        glBindTexture(GL_TEXTURE_RECTANGLE_NV, _psysTex[1]);
275
276        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
277        //glClear(GL_COLOR_BUFFER_BIT);
278
279        glViewport(0, 0, _psysWidth, _psysHeight);
280        glMatrixMode(GL_PROJECTION);
281        glLoadIdentity();
282        //gluOrtho2D(0, _psysWidth, 0, _psysHeight);
283        glOrtho(0, _psysWidth, 0, _psysHeight, -10.0f, 10.0f);
284        glMatrixMode(GL_MODELVIEW);
285        glLoadIdentity();
286
287        _advectionShader->bind(_psysTex[1], _initPosTex);
288
289        draw_quad(_psysWidth, _psysHeight, _psysWidth, _psysHeight);
290    }
291
292    _advectionShader->unbind();
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, 0);
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    displayVertices();
319}
320
321void
322NvParticleRenderer::drawBoundingBox(float x0, float y0, float z0,
323                                    float x1, float y1, float z1,
324                                    float r, float g, float b,
325                                    float line_width)
326{
327    glPushMatrix();
328    glEnable(GL_DEPTH_TEST);
329    glDisable(GL_TEXTURE_2D);
330    glEnable(GL_BLEND);
331
332    glColor4d(r, g, b, 1.0);
333    glLineWidth(line_width);
334   
335    glBegin(GL_LINE_LOOP);
336    {
337        glVertex3d(x0, y0, z0);
338        glVertex3d(x1, y0, z0);
339        glVertex3d(x1, y1, z0);
340        glVertex3d(x0, y1, z0);
341    }
342    glEnd();
343   
344    glBegin(GL_LINE_LOOP);
345    {
346        glVertex3d(x0, y0, z1);
347        glVertex3d(x1, y0, z1);
348        glVertex3d(x1, y1, z1);
349        glVertex3d(x0, y1, z1);
350    }
351    glEnd();
352   
353    glBegin(GL_LINE_LOOP);
354    {
355        glVertex3d(x0, y0, z0);
356        glVertex3d(x0, y0, z1);
357        glVertex3d(x0, y1, z1);
358        glVertex3d(x0, y1, z0);
359    }
360    glEnd();
361   
362    glBegin(GL_LINE_LOOP);
363    {
364        glVertex3d(x1, y0, z0);
365        glVertex3d(x1, y0, z1);
366        glVertex3d(x1, y1, z1);
367        glVertex3d(x1, y1, z0);
368    }
369    glEnd();
370
371    glPopMatrix();
372    glDisable(GL_DEPTH_TEST);
373    glDisable(GL_BLEND);
374    glEnable(GL_TEXTURE_2D);
375}
376
377void
378NvParticleRenderer::displayVertices()
379{
380    glDisable(GL_TEXTURE_2D);
381    glDisable(GL_BLEND);
382    glEnable(GL_DEPTH_TEST);
383
384    glEnable(GL_COLOR_MATERIAL);
385
386    glPushMatrix();
387
388    glTranslatef(_origin.x, _origin.y, _origin.z);
389    glScaled(_scale.x, _scale.y, _scale.z);
390
391    // TBD...
392    /*
393      drawBoundingBox(0, 0, 0,
394      1, 1, 1,
395      1, 1, 1, 2);
396
397      drawBoundingBox(0, 0.5f / 4.5f, 0.5f / 4.5,
398      1, 4.0f / 4.5f, 4.0f / 4.5,
399      1, 0, 0, 2);
400
401      drawBoundingBox(1/3.0f, 1.0f / 4.5f, 0.5f / 4.5,
402      2/3.0f, 3.5f / 4.5f, 3.5f / 4.5,
403      1, 1, 0, 2);
404    */
405
406    glPointSize(_particleSize);
407    //glColor4f(.2,.2,.8,1.);
408    glColor4f(_color.x, _color.y, _color.z, _color.w);
409    glEnableClientState(GL_VERTEX_ARRAY);
410    _vertexArray->SetPointer(0);
411    glDrawArrays(GL_POINTS, 0, _psysWidth * _psysHeight);
412    glDisableClientState(GL_VERTEX_ARRAY);
413
414    glPopMatrix();
415
416    glDisable(GL_DEPTH_TEST);
417
418    //assert(glGetError()==0);
419}
420
421void
422NvParticleRenderer::setVectorField(unsigned int texID, const Vector3& origin,
423                                   float scaleX, float scaleY, float scaleZ,
424                                   float max)
425{
426    _origin = origin;
427    _scale.set(scaleX, scaleY, scaleZ);
428    _advectionShader->setScale(_scale);
429    _advectionShader->setVelocityVolume(texID, max);
430}
431
432void NvParticleRenderer::setAxis(int axis)
433{
434    _sliceAxis = axis;
435    initializeDataArray();
436}
437
438void NvParticleRenderer::setPos(float pos)
439{
440    _slicePos = pos;
441    initializeDataArray();
442}
Note: See TracBrowser for help on using the repository browser.