source: branches/blt4/packages/vizservers/nanovis/ParticleSystem.cpp @ 2936

Last change on this file since 2936 was 2936, checked in by gah, 12 years ago

sync back with trunk

File size: 60.3 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2#include "nvconf.h"
3
4#include <time.h>
5#include <stdlib.h>
6#include <stdio.h>
7#include <math.h>
8#include <pthread.h>
9
10#include <GL/glew.h>
11#include <Cg/cgGL.h>
12
13#include <vrutil/vrFilePath.h>
14#include <Image.h>
15#include <ImageLoader.h>
16#include <ImageLoaderFactory.h>
17
18#include <vrmath/vrMatrix4x4f.h>
19#include <vrmath/vrVector3f.h>
20#include <vrmath/vrVector4f.h>
21
22#include "ParticleSystem.h"
23#include "ParticleEmitter.h"
24#include "DataLoader.h"
25#include "Texture2D.h"
26#include "Texture3D.h"
27#include "NvShader.h"
28#include "Trace.h"
29
30#define USE_RGBA_ARROW
31
32//#define TEST
33
34inline float randomRange(float rangeMin, float rangeMax)
35{
36    return ((float)rand() / RAND_MAX) * (rangeMax - rangeMin) + rangeMin ;
37}
38
39inline int logd(int value)
40{
41    int l;
42    for (l = 0; value >> l; l++);
43    return l - 1;
44}
45
46inline void swap(int& x, int& y)
47{
48    if (x != y) {
49        x ^= y;
50        y ^= x;
51        x ^= y;
52    }
53}
54
55void *ParticleSystem::dataLoadMain(void *data)
56{
57    ParticleSystem *particleSystem = (ParticleSystem *)data;
58    CircularFifo<float*, 10>& queue = particleSystem->_queue;
59
60    // TBD..
61    //float min = particleSystem->_time_series_vel_mag_min;
62    //float max = particleSystem->_time_series_vel_mag_max;
63
64    int startIndex = particleSystem->_flowFileStartIndex;
65    int endIndex = particleSystem->_flowFileEndIndex;
66
67    int curIndex = startIndex;
68    int flowWidth = particleSystem->_flowWidth;
69    int flowHeight = particleSystem->_flowHeight;
70    int flowDepth = particleSystem->_flowDepth;
71
72    const char* fileNameFormat = particleSystem->_fileNameFormat.c_str();
73    char buff[256];
74
75    bool done = false;
76    while (!done) {
77        if (curIndex > endIndex) {
78            curIndex = startIndex;
79        }
80
81        if (!queue.isFull()) {
82            int tail = queue.tailIndex();
83            if (tail != -1) {
84                sprintf(buff, fileNameFormat, curIndex);
85                //std::string path = vrFilePath::getInstance()->getPath(buff);
86#ifdef WANT_TRACE
87                float t = clock() /(float) CLOCKS_PER_SEC;
88#endif
89                LoadProcessedFlowRaw(buff, flowWidth, flowHeight, flowDepth, queue.array[tail]);
90#ifdef WANT_TRACE
91                float ti = clock() / (float) CLOCKS_PER_SEC;
92                TRACE("LoadProcessedFlowRaw time: %f\n", ti - t);
93#endif
94                queue.push();
95                TRACE("%d loaded\n", curIndex);
96                ++curIndex;
97            }
98        }
99    }
100
101    return 0;
102}
103
104CGcontext ParticleSystem::_context = 0;
105
106unsigned int SpotTexID = 0;
107
108void MakeSphereTexture()
109{
110    const int DIM = 128;
111    const int DIM2 = 63;
112    //const float TEX_SCALE = 6.0;
113
114    glGenTextures(1, (GLuint *)&SpotTexID);
115    glBindTexture(GL_TEXTURE_2D, SpotTexID);
116
117    float col[4] = {1.f, 1.f, 1.f, 1.f};
118    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, col);
119    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
120
121    float *img = new float[DIM*DIM];
122
123    vrVector3f light(1,1,3);
124    light.normalize();
125
126    for (int y = 0; y < DIM; y++) {
127        for (int x = 0; x < DIM; x++) {
128            // Clamping the edges to zero allows Nvidia's blend optimizations to do their thing.
129            if (x == 0 || x == DIM-1 || y == 0 || y == DIM-1) {
130                img[y*DIM+x] = 0;
131            } else {
132                vrVector3f p(x, y, 0);
133                p = p - vrVector3f(DIM2, DIM2, 0);
134                float len = p.length();
135                float z = sqrt(DIM2*DIM2 - len*len);
136                p.z = z;
137                if (len >= DIM2) {
138                    img[y*DIM+x] = 0.0;
139                    continue;
140                }
141
142                p.normalize();
143                float v = p.dot(light);
144                if(v < 0) v = 0;
145
146                img[y*DIM+x] = v;
147            }
148        }
149    }
150
151    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
152    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
153    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
154    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
155
156    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA16, DIM, DIM, GL_ALPHA, GL_FLOAT, img);
157}
158
159//extern void algorithm_test(vrVector4f* data, int flowWidth, int flowHeight, int flowDepth);
160//extern std::vector<vrVector3f>* find_critical_points(vrVector4f* data, int flowWidth, int flowHeight, int flowDepth);
161ParticleSystem::ParticleSystem(int width, int height,
162                               const std::string& fileName,
163                               int fieldWidth, int fieldHeight, int fieldDepth,
164                               bool timeVaryingData,
165                               int flowFileStartIndex, int flowFileEndIndex) :
166    _width(width),
167    _height(height)
168{
169    ////////////////////////////////
170    // TIME-VARYING SERIES
171    _isTimeVaryingField = timeVaryingData;
172    _flowFileStartIndex = flowFileStartIndex;
173    _flowFileEndIndex = flowFileEndIndex;
174    _userDefinedParticleMaxCount = width * height;
175
176    _skipByte = 0;
177
178    _screenWidth = _screenHeight = 1;
179    _fov = 60.0f;
180
181    _particleMaxCount = _width * _height;
182
183    _pointSize = 10.0f;
184    _camx = 0.0f;
185    _camy = 0.0f;
186    _camz = 0.0f;
187
188    _scalex = _scaley = _scalez = 1.0f;
189    _currentSortIndex = 0;
190    _destSortIndex = 1;
191
192    _currentPosIndex = 0;
193    _destPosIndex = 1;
194
195    _currentSortPass = 0;
196    // TBD
197    //_sortPassesPerFrame = 5;
198    _sortPassesPerFrame = 4;
199    _maxSortPasses = 0;
200
201    _sortBegin = 0;
202    _sortEnd = _sortPassesPerFrame;
203    _currentTime = 0;
204    _sortEnabled = false;
205    _glyphEnabled = false;
206    _advectionEnabled = false;
207    _streamlineEnabled = false;
208    _particles = new Particle[_particleMaxCount];
209    memset(_particles, 0, sizeof(Particle) * _particleMaxCount);
210
211    _colorBuffer = new color4[_particleMaxCount];
212    memset(_colorBuffer, 0, sizeof(color4) * _particleMaxCount);
213
214    _positionBuffer = new vrVector3f[_particleMaxCount];
215    _vertices = new RenderVertexArray(_particleMaxCount, 3, GL_FLOAT);
216
217    srand(time(0));
218
219    /*
220    // TBD..
221    glGenBuffersARB(1, &_colorBufferID);
222    glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
223    glBufferDataARB(GL_ARRAY_BUFFER, _width * _height * 4, _colorBuffer, GL_STREAM_DRAW_ARB); // undefined data
224    glBindBufferARB(GL_ARRAY_BUFFER, 0);
225    */
226
227    _flowWidth = fieldWidth;
228    _flowHeight = fieldHeight;
229    _flowDepth = fieldDepth;
230
231    float min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ;
232    int index = fileName.rfind('.');
233    std::string ext = fileName.substr(index + 1, fileName.size() - (index + 1));
234    float *data = 0;
235
236    if (this->isTimeVaryingField()) {
237        axisScaleX = _flowWidth;
238        axisScaleY = _flowHeight;
239        axisScaleZ = _flowDepth;
240        _fileNameFormat = fileName;
241        for (int i = 0; i < CircularFifo<float*, 10>::Capacity; ++i) {
242            _queue.array[i] = new float[_flowWidth * _flowHeight * _flowDepth * 4];
243        }
244
245        // INSOO
246        // TBD
247        min = 0;
248        max = 234.99;
249    } else {
250        if (ext == "dx") {
251            data = (float*) LoadFlowDx(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ);
252        } else if (ext == "raw") {
253            data = (float*) LoadFlowRaw(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ, 0, false);
254            //data = (float*) LoadProcessedFlowRaw(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, axisScaleX, axisScaleY, axisScaleZ);
255#ifdef notdef
256        } else if (ext == "raws") {
257            data = (float*) LoadFlowRaw(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ, 5 * sizeof(int), true);
258        } else if (ext == "data") {
259            data = (float*) LoadFlowRaw(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ, 0, true);
260#endif
261        }
262        //_criticalPoints = find_critical_points((vrVector4f*) data, _flowWidth,  _flowHeight,  _flowDepth);
263        //algorithm_test((vrVector4f*) data,  _flowWidth,  _flowHeight,  _flowDepth);
264    }
265
266    _scalex = 1;
267    _scaley = axisScaleY / axisScaleX;
268    _scalez = axisScaleZ / axisScaleX;
269    _maxVelocityScale = max;
270
271    if (!this->isTimeVaryingField()) {
272        Texture3D *flow = new Texture3D(_flowWidth, _flowHeight, _flowDepth,
273                                        GL_FLOAT, GL_LINEAR, 4, data);
274        _curVectorFieldID = flow->id();
275        _vectorFieldIDs.push_back(_curVectorFieldID);
276    } else {
277        for (int i = 0; i < 3; ++i) {
278            Texture3D *flow = new Texture3D(_flowWidth, _flowHeight, _flowDepth,
279                                            GL_FLOAT, GL_LINEAR, 4, data);
280            _vectorFields.push_back(flow);
281            _vectorFieldIDs.push_back(flow->id());
282        }
283        _curVectorFieldID = _vectorFieldIDs[0];
284    }
285
286#ifdef USE_RGBA_ARROW
287    std::string path = vrFilePath::getInstance()->getPath("arrows_red_bg.bmp");
288#else
289    std::string path = vrFilePath::getInstance()->getPath("arrows.bmp");
290#endif
291    if (!path.empty()) {
292        ImageLoader *loader = ImageLoaderFactory::getInstance()->createLoader("bmp");
293        if (loader != NULL) {
294#ifdef USE_RGBA_ARROW
295            Image *image = loader->load(path.c_str(), Image::IMG_RGBA);
296#else
297            Image *image = loader->load(path.c_str(), Image::IMG_RGB);
298#endif
299            if (image != NULL) {
300                unsigned char *bytes = (unsigned char *)image->getImageBuffer();
301                if (bytes != NULL) {
302#ifdef USE_RGBA_ARROW
303                    for (unsigned int y = 0; y < image->getHeight(); ++y) {
304                        for (unsigned int x = 0; x < image->getWidth(); ++x, bytes += 4) {
305                            bytes[3] = (bytes[0] > 127 &&
306                                        bytes[1] < 127 &&
307                                        bytes[2] < 127) ? 0 : 255;
308                        }
309                    }
310                    _arrows = new Texture2D(image->getWidth(), image->getHeight(),
311                                            GL_UNSIGNED_BYTE, GL_LINEAR, 4, NULL);
312#else
313                    _arrows = new Texture2D(image->getWidth(), image->getHeight(),
314                                            GL_UNSIGNED_BYTE, GL_LINEAR, 3, NULL);
315#endif
316                    _arrows->setWrapS(GL_MIRRORED_REPEAT);
317                    _arrows->setWrapT(GL_MIRRORED_REPEAT);
318                    _arrows->initialize(image->getImageBuffer());
319                }
320                delete image;
321            } else {
322                ERROR("Failed to load image: arrows.bmp\n");
323            }
324            delete loader;
325        } else {
326            ERROR("Couldn't find loader for arrows.bmp\n");
327        }
328    } else {
329        ERROR("Couldn't find path to arrows.bmp\n");
330    }
331
332#ifdef TEST
333    MakeSphereTexture();
334#endif
335
336    glGenBuffersARB(1, &_particleInfoBufferID);
337    glBindBufferARB(GL_ARRAY_BUFFER_ARB, _particleInfoBufferID);
338    glBufferDataARB(GL_ARRAY_BUFFER_ARB, _particleMaxCount * 4 * sizeof(float), 0, GL_DYNAMIC_DRAW);
339    glVertexAttribPointerARB(8, 4, GL_FLOAT, GL_FALSE, 0, 0);  // 8 = texcoord0
340    glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
341
342    // TBD..
343    initStreamlines(_width, _height);
344    initInitPosTex();
345
346    initShaders();
347    createRenderTargets();
348    createSortRenderTargets();
349    createStreamlineRenderTargets();
350
351    if (this->isTimeVaryingField()) {
352        pthread_t _threads;
353        pthread_attr_t pthread_custom_attr;
354        pthread_attr_init(&pthread_custom_attr);
355        pthread_create(&_threads, &pthread_custom_attr, dataLoadMain, (void *) this);
356    }
357}
358
359void ParticleSystem::initInitPosTex()
360{
361    glGenFramebuffersEXT(1, &_initPos_fbo);
362    glGenTextures(1, &_initPosTex);
363
364    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _initPos_fbo);
365
366    glViewport(0, 0, _width, _height);
367    glMatrixMode(GL_PROJECTION);
368    glLoadIdentity();
369    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
370    glMatrixMode(GL_MODELVIEW);
371    glLoadIdentity();
372
373    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _initPosTex);
374    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
375    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
376    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
377    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
378    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB32F_ARB,
379                 _width, _height, 0, GL_RGB, GL_FLOAT, NULL);
380    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
381
382    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
383                              GL_TEXTURE_RECTANGLE_ARB, _initPosTex, 0);
384
385    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
386}
387
388void ParticleSystem::initStreamlines(int width, int height)
389{
390    _atlas_x = 32;
391    _atlas_y = 32;
392
393    _atlasWidth = width * _atlas_x;
394    _atlasHeight = height * _atlas_y;
395    _maxAtlasCount = _atlas_x * _atlas_y;
396
397    _stepSizeStreamline = 1;
398    _curStepCount = 0;
399    _particleCount = width * height;
400
401    _currentStreamlineOffset = 0;
402    _currentStreamlineIndex = 0;
403    _streamVertices = new RenderVertexArray(_atlasWidth*_atlasHeight * 2, 3, GL_FLOAT);
404
405    _maxIndexBufferSize = _width * _height * _atlas_x * _atlas_y;
406    _indexBuffer = new unsigned int[_maxIndexBufferSize * 2];
407    unsigned int* pindex = _indexBuffer;
408    int ax, ay, old_ax = 0, old_ay = 0;
409    for (unsigned int i = 1; i < _maxAtlasCount; ++i) {
410        ax = (i % _atlas_x) * width;
411        ay = (i / _atlas_x) * height;
412
413        for (int y = 0; y < height ; ++y) {
414            for (int x = 0; x < width; ++x) {
415                *pindex = (old_ay + y) * _atlasWidth + old_ax + x; ++pindex;
416                *pindex = (ay + y) * _atlasWidth + ax + x; ++pindex;
417            }
418        }
419
420        old_ax = ax;
421        old_ay = ay;
422    }
423}
424
425void ParticleSystem::initShaders()
426{
427    // TBD...
428    _context = NvShader::getCgContext();
429
430    std::string path = vrFilePath::getInstance()->getPath("distance.cg");
431    _distanceInitFP = 
432        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
433                                CG_PROFILE_FP40, "initSortIndex", NULL);
434    cgGLLoadProgram(_distanceInitFP);
435
436    _distanceSortFP =
437        cgCreateProgramFromFile(_context, CG_SOURCE,  path.c_str(),
438                                CG_PROFILE_FP40, "computeDistance", NULL);
439    _viewPosParam = cgGetNamedParameter(_distanceSortFP, "viewerPosition");
440    cgGLLoadProgram(_distanceSortFP);
441
442    _distanceSortLookupFP =
443        cgCreateProgramFromFile(_context, CG_SOURCE,  path.c_str(),
444                                CG_PROFILE_FP40, "lookupPosition", NULL);
445    cgGLLoadProgram(_distanceSortLookupFP);
446
447    path = vrFilePath::getInstance()->getPath("mergesort.cg");
448    _sortRecursionFP =
449        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
450                                CG_PROFILE_FP40, "mergeSortRecursion", NULL);
451    cgGLLoadProgram(_sortRecursionFP);
452
453    _srSizeParam = cgGetNamedParameter(_sortRecursionFP, "_Size");
454    _srStepParam = cgGetNamedParameter(_sortRecursionFP, "_Step");
455    _srCountParam = cgGetNamedParameter(_sortRecursionFP, "_Count");
456
457    _sortEndFP =
458        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
459                                CG_PROFILE_FP40, "mergeSortEnd", NULL);
460    cgGLLoadProgram(_sortEndFP);
461
462    _seSizeParam = cgGetNamedParameter(_sortEndFP, "size");
463    _seStepParam = cgGetNamedParameter(_sortEndFP, "step");
464
465    path = vrFilePath::getInstance()->getPath("passthrough.cg");
466    _passthroughFP =
467        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
468                                CG_PROFILE_FP40, "main", NULL);
469    cgGLLoadProgram(_passthroughFP);
470
471    _scaleParam = cgGetNamedParameter(_passthroughFP, "scale");
472    _biasParam = cgGetNamedParameter(_passthroughFP, "bias");
473
474    path = vrFilePath::getInstance()->getPath("moveparticles.cg");
475    _moveParticlesFP =
476        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
477                                CG_PROFILE_FP40, "main", NULL);
478    cgGLLoadProgram(_moveParticlesFP);
479    _mpTimeScale = cgGetNamedParameter(_moveParticlesFP, "timeStep");
480    _mpVectorField = cgGetNamedParameter(_moveParticlesFP, "vfield");
481    _mpUseInitTex= cgGetNamedParameter(_moveParticlesFP, "useInitPos");
482    _mpCurrentTime= cgGetNamedParameter(_moveParticlesFP, "currentTime");
483    _mpMaxScale = cgGetNamedParameter(_moveParticlesFP, "maxScale");
484    _mpScale= cgGetNamedParameter(_moveParticlesFP, "scale");
485
486    path = vrFilePath::getInstance()->getPath("particlevp.cg");
487    _particleVP =
488        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
489                                CG_PROFILE_VP40, "vpmain", NULL);
490    cgGLLoadProgram(_particleVP);
491    _mvpParticleParam = cgGetNamedParameter(_particleVP, "mvp");
492    _mvParticleParam = cgGetNamedParameter(_particleVP, "modelview");
493    _mvTanHalfFOVParam = cgGetNamedParameter(_particleVP, "tanHalfFOV");
494    _mvCurrentTimeParam =  cgGetNamedParameter(_particleVP, "currentTime");
495
496    path = vrFilePath::getInstance()->getPath("particlefp.cg");
497    _particleFP =
498        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
499                                CG_PROFILE_FP40, "fpmain", NULL);
500    cgGLLoadProgram(_particleFP);
501    _vectorParticleParam = cgGetNamedParameter(_particleVP, "vfield");
502
503    path = vrFilePath::getInstance()->getPath("moveparticles.cg");
504    _initParticlePosFP =
505        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
506                                CG_PROFILE_FP40, "initParticlePosMain", NULL);
507    cgGLLoadProgram(_initParticlePosFP);
508    _ipVectorFieldParam = cgGetNamedParameter(_moveParticlesFP, "vfield");
509}
510
511void ParticleSystem::passThoughPositions()
512{
513    cgGLBindProgram(_passthroughFP);
514    cgGLEnableProfile(CG_PROFILE_FP40);
515
516    cgGLSetParameter4f(_scaleParam, 1.0, 1.0, 1.0, 1.0);
517    cgGLSetParameter4f(_biasParam, 0.0, 0.0, 0.0, 0.0);
518
519    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB32F_ARB,
520                 _width, _height, 0, GL_RGB, GL_FLOAT, (GLfloat *) _positionBuffer);
521
522    drawQuad();
523
524    cgGLDisableProfile(CG_PROFILE_FP40);
525}
526
527void ParticleSystem::resetStreamlines()
528{
529    _currentStreamlineIndex = 0;
530    _currentStreamlineOffset = 0;
531    _curStepCount = 0;
532}
533
534void ParticleSystem::reset()
535{
536    _currentTime = 0.0f;
537    _sortBegin = 0;
538    _sortEnd = _sortPassesPerFrame;
539
540    glPushAttrib(GL_VIEWPORT_BIT);
541    glMatrixMode(GL_PROJECTION);
542    glPushMatrix();
543    glMatrixMode(GL_MODELVIEW);
544
545    resetStreamlines();
546
547    unsigned int maxsize = _userDefinedParticleMaxCount;
548
549    while (!_availableIndices.empty())
550        _availableIndices.pop();
551    while (!_activeParticles.empty())
552        _activeParticles.pop();
553
554    _activeParticles.reserve(maxsize);
555    _availableIndices.reserve(maxsize);
556
557    for (unsigned int i = 0; i < maxsize; i++)
558        _availableIndices.push(i);
559
560    for (int i = 0; i < _particleMaxCount; i++) {
561        _particles[i].timeOfBirth = -1.0f;
562        _particles[i].lifeTime = 0.0f;
563        _particles[i].attributeType = 0.0f;
564        _particles[i].index = (float)i;
565    }
566
567    glBindBufferARB(GL_ARRAY_BUFFER_ARB, _particleInfoBufferID);
568    Particle* pinfo = (Particle*) glMapBufferARB(GL_ARRAY_BUFFER, GL_WRITE_ONLY_ARB);
569
570    for (int i = 0; i < _particleMaxCount; i++) {
571        pinfo[i] = _particles[i];
572    }
573
574    glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
575
576    // POSITION
577    memset(_positionBuffer, 0, sizeof(vrVector3f) * _width * _height);
578    for (int y = 0; y < _height; y++) {
579        for (int x = 0; x < _width; x++) {
580            _positionBuffer[_width * y + x].x = (float)rand() / (float) RAND_MAX;
581            //_positionBuffer[_width * y + x].x = 0.9;
582            _positionBuffer[_width * y + x].y = (float)rand() / (float) RAND_MAX;
583            _positionBuffer[_width * y + x].z = (float)rand() / (float) RAND_MAX;
584        }
585    }
586
587    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _initPosTex);
588    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB32F_ARB,
589                 _width, _height, 0, GL_RGB, GL_FLOAT, (float*)_positionBuffer);
590    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
591
592    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_currentPosIndex]);
593    glViewport(0, 0, _width, _height);
594    glMatrixMode(GL_PROJECTION);
595    glLoadIdentity();
596    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
597    glMatrixMode(GL_MODELVIEW);
598    glLoadIdentity();
599    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
600    passThoughPositions();
601    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
602
603    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, velocity_fbo[_currentPosIndex]);
604    glViewport(0, 0, _width, _height);
605    glMatrixMode(GL_PROJECTION);
606    glLoadIdentity();
607    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
608    glMatrixMode(GL_MODELVIEW);
609    glLoadIdentity();
610    glClearColor(0, 0, 0, 0);
611    glClear(GL_COLOR_BUFFER_BIT);
612    // TBD..
613    // velocity
614    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
615
616
617    /// TBD...
618    //DeathTimePBuffer->BeginCapture();
619    //glClear(GL_COLOR_BUFFER_BIT);
620    //DeathTimePBuffer->EndCapture();
621
622    if (_sortEnabled) {
623        glDisable(GL_BLEND);
624        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_currentSortIndex]);
625        glViewport(0, 0, _width, _height);
626        glMatrixMode(GL_PROJECTION);
627        glLoadIdentity();
628        glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
629        glMatrixMode(GL_MODELVIEW);
630        glLoadIdentity();
631
632        cgGLBindProgram(_distanceInitFP);
633        cgGLEnableProfile(CG_PROFILE_FP40);
634
635        drawQuad();
636
637        cgGLDisableProfile(CG_PROFILE_FP40);
638        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);           
639
640        _currentSortPass = 0;
641        this->_maxSortPasses = 100000;
642    }
643
644    glMatrixMode(GL_PROJECTION);
645    glPopMatrix();
646    glMatrixMode(GL_MODELVIEW);
647    glPopAttrib();
648}
649
650void ParticleSystem::createRenderTargets()
651{
652    glGenFramebuffersEXT(2, psys_fbo);
653    glGenTextures(2, psys_tex);
654
655    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[0]);
656
657    glViewport(0, 0, _width, _height);
658    glMatrixMode(GL_PROJECTION);
659    glLoadIdentity();
660    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
661    glMatrixMode(GL_MODELVIEW);
662    glLoadIdentity();
663
664    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[0]);
665    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
666    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
667    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
668    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
669
670    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB,
671                 _width, _height, 0, GL_RGBA, GL_FLOAT, NULL);
672
673    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
674                              GL_TEXTURE_RECTANGLE_ARB, psys_tex[0], 0);
675
676    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[1]);
677
678    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[1]);
679    glViewport(0, 0, _width, _height);
680    glMatrixMode(GL_PROJECTION);
681    glLoadIdentity();
682    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
683    glMatrixMode(GL_MODELVIEW);
684    glLoadIdentity();
685
686    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
687    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
688    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
689    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
690
691    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB,
692                 _width, _height, 0, GL_RGBA, GL_FLOAT, NULL);
693
694    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
695                              GL_TEXTURE_RECTANGLE_ARB, psys_tex[1], 0);
696 
697    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
698}
699
700//#define ATLAS_TEXTURE_TARGET GL_TEXTURE_RECTANGLE_ARB
701//#define ATLAS_INTERNAL_TYPE GL_RGBA32F_ARB
702#define ATLAS_TEXTURE_TARGET GL_TEXTURE_2D
703#define ATLAS_INTERNAL_TYPE GL_RGBA
704
705void ParticleSystem::createStreamlineRenderTargets()
706{
707    glGenFramebuffersEXT(1, &_atlas_fbo);
708    glGenTextures(1, &_atlas_tex);
709    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _atlas_fbo);
710    glViewport(0, 0, _atlasWidth, _atlasHeight);
711    glMatrixMode(GL_PROJECTION);
712    glLoadIdentity();
713    glOrtho(0, _atlasWidth, 0, _atlasHeight, -10.0f, 10.0f);
714    glMatrixMode(GL_MODELVIEW);
715    glLoadIdentity();
716
717    glBindTexture(ATLAS_TEXTURE_TARGET, _atlas_tex);
718    glTexParameterf(ATLAS_TEXTURE_TARGET, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
719    glTexParameterf(ATLAS_TEXTURE_TARGET, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
720    //glTexParameteri(ATLAS_TEXTURE_TARGET, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
721    //glTexParameteri(ATLAS_TEXTURE_TARGET, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
722
723    glTexImage2D(ATLAS_TEXTURE_TARGET, 0, ATLAS_INTERNAL_TYPE,
724                 _atlasWidth, _atlasHeight, 0, GL_RGBA, GL_FLOAT, NULL);
725
726    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
727                              ATLAS_TEXTURE_TARGET, _atlas_tex, 0);
728 
729    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
730}
731
732//#define SORT_TEXTURE_FORMAT  GL_LUMINANCE_ALPHA
733//#define SORT_TEXTURE_INNER_FORMAT GL_LUMINANCE_ALPHA_FLOAT32_ATI
734#define SORT_TEXTURE_FORMAT  GL_RGB
735#define SORT_TEXTURE_INNER_FORMAT GL_RGB32F_ARB
736
737void ParticleSystem::createSortRenderTargets()
738{
739    glGenFramebuffersEXT(2, sort_fbo);
740    glGenTextures(2, sort_tex);
741
742    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[0]);
743    glViewport(0, 0, _width, _height);
744    glMatrixMode(GL_PROJECTION);
745    glLoadIdentity();
746    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
747    glMatrixMode(GL_MODELVIEW);
748    glLoadIdentity();
749
750    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sort_tex[0]);
751    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
752    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
753    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
754    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
755    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, SORT_TEXTURE_INNER_FORMAT,
756                 _width, _height, 0, SORT_TEXTURE_FORMAT, GL_FLOAT, NULL);
757
758    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
759                              GL_TEXTURE_RECTANGLE_ARB, sort_tex[0], 0);
760
761    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[1]);
762    glViewport(0, 0, _width, _height);
763    glMatrixMode(GL_PROJECTION);
764    glLoadIdentity();
765    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
766    glMatrixMode(GL_MODELVIEW);
767    glLoadIdentity();
768
769    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sort_tex[1]);
770    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
771    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
772    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
773    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
774    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, SORT_TEXTURE_INNER_FORMAT,
775                 _width, _height, 0, SORT_TEXTURE_FORMAT, GL_FLOAT, NULL);
776
777    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
778                              GL_TEXTURE_RECTANGLE_ARB, sort_tex[1], 0);
779
780    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
781}
782
783ParticleSystem::~ParticleSystem()
784{
785    std::vector<ParticleEmitter*>::iterator iter;
786    for (iter = _emitters.begin(); iter != _emitters.end(); ++iter)
787        delete (*iter);
788
789    // Particle Position
790    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[0]);
791    glDeleteTextures(1, psys_tex);
792    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[1]);
793    glDeleteTextures(1, psys_tex+1);
794    glDeleteFramebuffersEXT(2, psys_fbo);
795
796    // Sort
797    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[0]);
798    glDeleteTextures(1, sort_tex);
799    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[1]);
800    glDeleteTextures(1, sort_tex+1);
801    glDeleteFramebuffersEXT(2, sort_fbo);
802
803    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, velocity_fbo[0]);
804    glDeleteTextures(1, velocity_tex);
805    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, velocity_fbo[1]);
806    glDeleteTextures(1, velocity_tex+1);
807    glDeleteFramebuffersEXT(2, velocity_fbo);
808
809    if (_vertices) delete _vertices;
810
811    delete [] _particles;
812    delete [] _positionBuffer;
813    delete [] _colorBuffer;
814
815    if (_arrows) delete _arrows;
816
817    // STREAM LINE
818    if (_streamVertices) delete _streamVertices;
819    if (_indexBuffer) delete _indexBuffer;
820
821    cgDestroyProgram(_distanceInitFP);
822
823    cgDestroyParameter(_viewPosParam);
824    cgDestroyProgram(_distanceSortFP);
825
826    cgDestroyProgram(_distanceSortLookupFP);
827
828    cgDestroyParameter(_scaleParam);
829    cgDestroyParameter(_biasParam);
830    cgDestroyProgram(_passthroughFP);
831
832    cgDestroyParameter(_srSizeParam);
833    cgDestroyParameter(_srStepParam);
834    cgDestroyParameter(_srCountParam);
835
836    cgDestroyProgram(_sortRecursionFP);
837
838    cgDestroyParameter(_seSizeParam);
839    cgDestroyParameter(_seStepParam);
840    cgDestroyProgram(_sortEndFP);
841
842    cgDestroyParameter(_mpTimeScale);
843    cgDestroyParameter(_mpVectorField);
844    cgDestroyParameter(_mpUseInitTex);
845    cgDestroyParameter(_mpCurrentTime);
846    cgDestroyProgram(_moveParticlesFP);
847
848    cgDestroyParameter(_ipVectorFieldParam);
849    cgDestroyProgram(_initParticlePosFP);
850
851    cgDestroyParameter(_mvpParticleParam);
852    cgDestroyParameter(_mvParticleParam);
853    cgDestroyParameter(_mvTanHalfFOVParam);
854    cgDestroyParameter(_mvCurrentTimeParam);
855    cgDestroyProgram(_particleFP);
856
857    cgDestroyParameter(_vectorParticleParam);
858    cgDestroyProgram(_particleVP);
859}
860
861bool ParticleSystem::isEnabled(EnableEnum enabled)
862{
863    switch (enabled) {
864    case PS_SORT :
865        return _sortEnabled;
866        break;
867    case PS_GLYPH :
868        return _glyphEnabled;
869        break;
870    case PS_DRAW_BBOX :
871        return _drawBBoxEnabled;
872        break;
873    case PS_ADVECTION :
874        return _advectionEnabled;
875    case PS_STREAMLINE :
876        return _streamlineEnabled;
877    }
878    return false;
879}
880
881void ParticleSystem::enable(EnableEnum enabled)
882{
883    switch (enabled) {
884    case PS_SORT :
885        _sortEnabled = true;
886        break;
887    case PS_GLYPH :
888        _glyphEnabled = true;
889        break;
890    case PS_DRAW_BBOX :
891        _drawBBoxEnabled = true;
892        break;
893    case PS_ADVECTION :
894        _advectionEnabled = true;
895        break;
896    case PS_STREAMLINE :
897        _streamlineEnabled = true;
898        break;
899    }
900}
901
902void ParticleSystem::disable(EnableEnum enabled)
903{
904    switch (enabled) {
905    case PS_SORT :
906        _sortEnabled = false;
907        break;
908    case PS_GLYPH :
909        _glyphEnabled = false;
910        break;
911    case PS_DRAW_BBOX :
912        _drawBBoxEnabled = false;
913        break;
914    case PS_ADVECTION :
915        _advectionEnabled = false;
916        break;
917    case PS_STREAMLINE :
918        _streamlineEnabled = false;
919        break;
920    }
921}
922
923void ParticleSystem::advectStreamlines()
924{
925    glDisable(GL_BLEND);
926    glDisable(GL_DEPTH_TEST);
927
928    //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
929    //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
930
931    glPushAttrib(GL_VIEWPORT_BIT);
932    glViewport(0, 0, _width, _height);
933    glMatrixMode(GL_PROJECTION);
934    glPushMatrix();
935    glLoadIdentity();
936    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
937    glMatrixMode(GL_MODELVIEW);
938    glPushMatrix();
939    glLoadIdentity();
940
941    glEnable(GL_TEXTURE_RECTANGLE_ARB);
942
943    cgGLBindProgram(_moveParticlesFP);
944    cgGLEnableProfile(CG_PROFILE_FP40);
945    cgGLSetParameter1f(_mpTimeScale, 0.005);
946    cgGLSetParameter1f(_mpUseInitTex, 1.0);
947    cgGLSetParameter1f(_mpCurrentTime, _currentTime);
948    cgGLSetParameter3f(_mpScale, _scalex, _scaley, _scalez);
949    cgGLSetParameter1f(_mpMaxScale, _maxVelocityScale);
950    cgGLSetTextureParameter(_mpVectorField, _curVectorFieldID);
951    cgGLEnableTextureParameter(_mpVectorField);
952
953    for (int i = 0; i < _stepSizeStreamline; ++i) {
954        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
955        glClear(GL_COLOR_BUFFER_BIT);
956        glActiveTextureARB(GL_TEXTURE0_ARB);
957        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_currentPosIndex]);
958        glActiveTextureARB(GL_TEXTURE1_ARB);
959        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _initPosTex);
960        drawQuad();
961        swap(_currentPosIndex, _destPosIndex);
962    }
963
964    cgGLDisableTextureParameter(_mpVectorField);
965    glDisable(GL_TEXTURE_RECTANGLE_ARB);
966    cgGLDisableProfile(CG_PROFILE_FP40);
967
968    glMatrixMode(GL_PROJECTION);
969    glPopMatrix();
970    glMatrixMode(GL_MODELVIEW);
971    glPopMatrix();
972    glPopAttrib();
973    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
974
975    if (_currentStreamlineIndex < _maxAtlasCount) {
976        int xoffset = (_currentStreamlineIndex % _atlas_x) * _width;
977        int yoffset = (_currentStreamlineIndex / _atlas_x) * _height;
978
979        glActiveTextureARB(GL_TEXTURE0_ARB);
980        glEnable(ATLAS_TEXTURE_TARGET);
981        glBindTexture(ATLAS_TEXTURE_TARGET, _atlas_tex);
982
983        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
984        //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_currentPosIndex]);
985        glCopyTexSubImage2D(ATLAS_TEXTURE_TARGET, 0, xoffset, yoffset,
986                            0, 0, _width, _height);
987        glActiveTextureARB(GL_TEXTURE0_ARB);
988        glBindTexture(ATLAS_TEXTURE_TARGET, 0);
989        glDisable(ATLAS_TEXTURE_TARGET);
990
991        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _atlas_fbo);
992        _streamVertices->Read(_atlasWidth, _atlasHeight);
993        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
994        _currentStreamlineIndex++;
995
996        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
997    }
998}
999
1000bool ParticleSystem::advect(float deltaT, float camx, float camy, float camz)
1001{
1002    static bool firstLoad = true;
1003    if (this->isTimeVaryingField()) {
1004        static float oldTime = (float)clock()/(float)CLOCKS_PER_SEC;
1005#ifdef WANT_TRACE
1006        static int index = 0;
1007#endif
1008        float time = (float)clock()/(float)CLOCKS_PER_SEC;
1009        if ((time - oldTime) > 2.0) {
1010            if (!_queue.isEmpty()) {
1011                float *data = NULL;
1012                if (_queue.top(data)) {
1013#ifdef WANT_TRACE
1014                    float t = clock() /(float) CLOCKS_PER_SEC;
1015#endif
1016                    _vectorFields[0]->update(data);
1017#ifdef WANT_TRACE
1018                    float ti = clock() / (float) CLOCKS_PER_SEC;
1019                    TRACE("updatePixels time: %f\n", ti - t);
1020#endif
1021                    _queue.pop();
1022                    oldTime = time;
1023
1024                    firstLoad = false;
1025                    TRACE("%d bound\n", index++);
1026                }
1027            }           
1028        }
1029        if (firstLoad) return false;
1030    }
1031
1032    if (!_advectionEnabled) return true;
1033    if (this->_streamlineEnabled) {
1034        advectStreamlines();
1035        _currentTime += deltaT;
1036    } else {
1037        _camx = camx;
1038        _camy = camy;
1039        _camz = camz;
1040
1041        glDisable(GL_BLEND);
1042        glDisable(GL_DEPTH_TEST);
1043
1044        glPushAttrib(GL_VIEWPORT_BIT);
1045        glViewport(0, 0, _width, _height);
1046        glMatrixMode(GL_PROJECTION);
1047        glPushMatrix();
1048        glLoadIdentity();
1049        glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1050        glMatrixMode(GL_MODELVIEW);
1051        glPushMatrix();
1052        glLoadIdentity();
1053
1054        glEnable(GL_TEXTURE_RECTANGLE_ARB);
1055
1056        cgGLBindProgram(_moveParticlesFP);
1057        cgGLEnableProfile(CG_PROFILE_FP40);
1058
1059        // INSOO
1060        // TIME SCALE
1061
1062        cgGLSetParameter1f(_mpTimeScale, 0.005);
1063
1064        //////////////////////////////////////////////////////
1065        // UPDATE POS
1066        cgGLSetTextureParameter(_mpVectorField, _curVectorFieldID);
1067        cgGLEnableTextureParameter(_mpVectorField);
1068        cgGLSetParameter3f(_mpScale, _scalex, _scaley, _scalez);
1069        cgGLSetParameter1f(_mpMaxScale, _maxVelocityScale);
1070        for (int i = 0; i < _stepSizeStreamline; ++i) {
1071            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
1072            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1073            glActiveTextureARB(GL_TEXTURE0_ARB);
1074            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_currentPosIndex]);
1075            glActiveTextureARB(GL_TEXTURE1_ARB);
1076            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _initPosTex);
1077            drawQuad();
1078            swap(_currentPosIndex, _destPosIndex);
1079        }
1080        cgGLDisableTextureParameter(_mpVectorField);
1081
1082        glActiveTextureARB(GL_TEXTURE1_ARB);
1083        glDisable(GL_TEXTURE_RECTANGLE_ARB);
1084        glActiveTextureARB(GL_TEXTURE0_ARB);
1085        glDisable(GL_TEXTURE_RECTANGLE_ARB);
1086
1087        glDisable(GL_TEXTURE_RECTANGLE_ARB);
1088        cgGLDisableProfile(CG_PROFILE_FP40);
1089
1090        glMatrixMode(GL_PROJECTION);
1091        glPopMatrix();
1092        glMatrixMode(GL_MODELVIEW);
1093        glPopMatrix();
1094        glPopAttrib();
1095        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1096
1097        if (_sortEnabled) {
1098            sort();
1099
1100            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
1101            _vertices->Read(_width, _height);
1102            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1103        } else {
1104            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_currentPosIndex]);
1105            _vertices->Read(_width, _height);
1106            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1107        }
1108
1109        // NEW PARTICLES
1110        for (unsigned int i = 0; i < _emitters.size(); ++i) {
1111            // TBD..
1112            unsigned int numOfNewParticles = (unsigned int)(randomRange(_emitters[i]->_minNumOfNewParticles, _emitters[i]->_maxNumOfNewParticles) * deltaT);
1113            for (unsigned int k = 0; k < numOfNewParticles; ++k) {
1114                vrVector3f position = _emitters[i]->_position;
1115                position += _emitters[i]->_maxPositionOffset *
1116                    vrVector3f(randomRange(-1.0f, 1.0f), randomRange(-1.0f, 1.0f), randomRange(-1.0f, 1.0f));
1117
1118                float lifetime = randomRange(_emitters[i]->_minLifeTime, _emitters[i]->_maxLifeTime);
1119
1120                // TBD..
1121                allocateParticle(position, vrVector3f(0.0f, 0.0f, 0.0f),  lifetime, 1 - (float) k / numOfNewParticles);
1122            }
1123        }
1124
1125        initNewParticles();
1126
1127        _currentTime += deltaT;
1128
1129        cleanUpParticles();
1130    }
1131
1132    return true;
1133}
1134
1135void ParticleSystem::allocateParticle(const vrVector3f& position, const vrVector3f& velocity,
1136                                      float lifeTime, float initTimeStep)
1137{
1138    if (_availableIndices.empty()) {
1139        return;
1140    }
1141
1142    int index = _availableIndices.top();
1143    _availableIndices.pop();
1144
1145    ActiveParticle p;
1146    p.index = index;
1147    p.timeOfDeath = _currentTime + lifeTime;
1148    _activeParticles.push(p);
1149
1150    NewParticle newParticle;
1151    newParticle.index = index;
1152    newParticle.position = position;
1153    newParticle.velocity = velocity;
1154    newParticle.timeOfDeath = p.timeOfDeath;
1155    newParticle.initTimeStep = initTimeStep;
1156
1157    _newParticles.push_back(newParticle);
1158
1159    _particles[index].timeOfBirth = _currentTime;
1160    _particles[index].lifeTime = lifeTime;
1161}
1162
1163void ParticleSystem::initNewParticles()
1164{
1165    /////////////////////////////
1166    // INIT NEW PARTICLE
1167    glBindBufferARB(GL_ARRAY_BUFFER_ARB, _particleInfoBufferID);
1168    Particle* pinfo = (Particle*) glMapBufferARB(GL_ARRAY_BUFFER, GL_WRITE_ONLY_ARB);
1169
1170    std::vector<NewParticle>::iterator iter;
1171    for (iter = _newParticles.begin(); iter != _newParticles.end(); ++iter) {
1172        pinfo[iter->index] = _particles[iter->index];
1173    }
1174
1175    glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
1176
1177    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_currentPosIndex]);
1178
1179    glPushAttrib(GL_VIEWPORT_BIT);
1180    glViewport(0, 0, _width, _height);
1181    glMatrixMode(GL_PROJECTION);
1182    glPushMatrix();
1183    glLoadIdentity();
1184    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1185    glMatrixMode(GL_MODELVIEW);
1186    glPushMatrix();
1187    glLoadIdentity();
1188
1189    cgGLBindProgram(_initParticlePosFP);
1190    cgGLEnableProfile(CG_PROFILE_FP40);
1191    cgGLSetTextureParameter(_ipVectorFieldParam, _curVectorFieldID);
1192    cgGLEnableTextureParameter(_ipVectorFieldParam);
1193    // TBD..
1194    //glActiveTextureARB(GL_TEXTURE0_ARB);
1195    //VelocityPBuffers[VelocityCurrent]->Bind();
1196
1197    glActiveTextureARB(GL_TEXTURE0_ARB);
1198    glEnable(GL_TEXTURE_RECTANGLE_ARB);
1199    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_destPosIndex]);
1200
1201    glBegin(GL_POINTS);
1202    for (iter = _newParticles.begin(); iter != _newParticles.end(); iter++) {
1203        //TRACE("[%d] %f %f %f\n", iter->index, iter->position.x,iter->position.y,iter->position.z);
1204        glMultiTexCoord3f(GL_TEXTURE0, iter->position.x,iter->position.y,iter->position.z);
1205
1206        // TBD..
1207        //glMultiTexCoord2f(GL_TEXTURE1_ARB, (float)(i->Index % Width), (float)(i->Index / Height));
1208        //glMultiTexCoord1f(GL_TEXTURE2_ARB, iter->initTimeStep);
1209
1210        glVertex2f((float)(iter->index % _width),
1211                   (float)(iter->index / _height) + 1/* + offsetY*/ /* + offsetY shouldn't be */);
1212        //TRACE("%f %f\n", (float) (iter->index % _width), (float)(iter->index / _width));
1213    }
1214    glEnd();
1215
1216    glDisable(GL_TEXTURE_RECTANGLE_ARB);
1217    cgGLDisableTextureParameter(_ipVectorFieldParam);
1218    cgGLDisableProfile(CG_PROFILE_FP40);
1219
1220    glMatrixMode(GL_PROJECTION);
1221    glPopMatrix();
1222    glMatrixMode(GL_MODELVIEW);
1223    glPopMatrix();
1224    glPopAttrib();
1225
1226    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1227
1228    // INIT NEW END
1229    /////////////////////////////
1230#if 1
1231    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _initPos_fbo);
1232    glPushAttrib(GL_VIEWPORT_BIT);
1233    glViewport(0, 0, _width, _height);
1234    glMatrixMode(GL_PROJECTION);
1235    glPushMatrix();
1236    glLoadIdentity();
1237    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1238    glMatrixMode(GL_MODELVIEW);
1239    glPushMatrix();
1240    glLoadIdentity();
1241
1242    cgGLBindProgram(_initParticlePosFP);
1243    cgGLEnableProfile(CG_PROFILE_FP40);
1244    cgGLSetTextureParameter(_ipVectorFieldParam, _curVectorFieldID);
1245    cgGLEnableTextureParameter(_ipVectorFieldParam);
1246    // TBD..
1247    //glActiveTextureARB(GL_TEXTURE0_ARB);
1248    //VelocityPBuffers[VelocityCurrent]->Bind();
1249
1250    glActiveTextureARB(GL_TEXTURE0_ARB);
1251    glEnable(GL_TEXTURE_RECTANGLE_ARB);
1252    //glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _initPosTex);
1253    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_destPosIndex]);
1254
1255    glBegin(GL_POINTS);
1256    for (iter = _newParticles.begin(); iter != _newParticles.end(); iter++) {
1257        //TRACE("[%d] %f %f %f\n", iter->index, iter->position.x,iter->position.y,iter->position.z);
1258        glMultiTexCoord3f(GL_TEXTURE0, iter->position.x,iter->position.y,iter->position.z);
1259
1260        // TBD..
1261        //glMultiTexCoord2f(GL_TEXTURE1_ARB, (float)(i->Index % Width), (float)(i->Index / Height));
1262        //glMultiTexCoord1f(GL_TEXTURE2_ARB, iter->initTimeStep);
1263
1264        glVertex2f((float)(iter->index % _width),
1265                   (float)(iter->index / _height) + 1/* + offsetY*/ /* + offsetY shouldn't be */);
1266        //TRACE("%f %f\n", (float) (iter->index % _width), (float)(iter->index / _width));
1267    }
1268    glEnd();
1269
1270    glDisable(GL_TEXTURE_RECTANGLE_ARB);
1271    cgGLDisableTextureParameter(_ipVectorFieldParam);
1272    cgGLDisableProfile(CG_PROFILE_FP40);
1273
1274    glMatrixMode(GL_PROJECTION);
1275    glPopMatrix();
1276    glMatrixMode(GL_MODELVIEW);
1277    glPopMatrix();
1278    glPopAttrib();
1279
1280    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1281#endif
1282
1283    // Free array.
1284    _newParticles.clear();
1285}
1286
1287void ParticleSystem::cleanUpParticles()
1288{
1289    if (! _activeParticles.empty()) {
1290        while (_activeParticles.top().timeOfDeath < _currentTime) {
1291            unsigned int i = _activeParticles.top().index;
1292            _activeParticles.pop();
1293            _availableIndices.push(i);
1294            //_usedIndices[i] = false;
1295
1296            //if (i >= _maxUsedIndex)
1297            //    while (!_usedIndices[_maxUsedIndex])
1298            //        _maxUsedIndex--;
1299        }
1300    }
1301}
1302
1303void ParticleSystem::sort()
1304{
1305    ///////////////////////////////////////////////////////////
1306    // BEGIN - COMPUTE DISTANCE
1307    vrVector3f pos;
1308    vrMatrix4x4f mat;
1309    glPushMatrix();
1310    glLoadIdentity();
1311    glScalef(_scalex, _scaley, _scalez);
1312    glTranslatef(-0.5f, -0.5f, -0.5f);
1313    glGetFloatv(GL_MODELVIEW_MATRIX, mat.get());
1314    glPopMatrix();
1315    mat.invert();
1316    mat.getTranslation(pos);
1317
1318    cgGLBindProgram(_distanceSortFP);
1319    cgGLEnableProfile(CG_PROFILE_FP40);
1320
1321    glActiveTextureARB(GL_TEXTURE0_ARB);
1322    glEnable(GL_TEXTURE_RECTANGLE_ARB);
1323    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sort_tex[_currentSortIndex]);
1324
1325    glActiveTextureARB(GL_TEXTURE1_ARB);
1326    glEnable(GL_TEXTURE_RECTANGLE_ARB);
1327    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_currentPosIndex]);
1328
1329    cgGLSetParameter3f(_viewPosParam, pos.x, pos.y, pos.z);
1330
1331    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_destSortIndex]);
1332    glPushAttrib(GL_VIEWPORT_BIT);
1333    glViewport(0, 0, _width, _height);
1334    glMatrixMode(GL_PROJECTION);
1335    glPushMatrix();
1336    glLoadIdentity();
1337    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1338    glMatrixMode(GL_MODELVIEW);
1339    glPushMatrix();
1340    glLoadIdentity();
1341
1342    drawQuad();
1343
1344    cgGLDisableProfile(CG_PROFILE_FP40);
1345
1346    glMatrixMode(GL_PROJECTION);
1347    glPopMatrix();
1348    glMatrixMode(GL_MODELVIEW);
1349    glPopMatrix();
1350    glPopAttrib();
1351    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1352
1353    // _DEBUG
1354    /*
1355    {
1356        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_destSortIndex]);
1357        static float debug[256];
1358        glReadPixels(0, 0, _width, _height, GL_RGB, GL_FLOAT, (float*)debug);
1359        TRACE("[%d]", _currentSortIndex);
1360        for (int i = 0; i < _width * _height * 3; i += 3)
1361            TRACE("%.2f, %.2f, %.2f\n", debug[i], debug[i+1], debug[i+2]);
1362        TRACE("\n");
1363        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1364    }
1365    */
1366
1367    // _DEBUG
1368    /*
1369    {
1370        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_currentPosIndex]);
1371        static float debug[256];
1372        glReadPixels(0, 0, _width, _height, GL_RGB, GL_FLOAT, (float*)debug);
1373        TRACE("\n");
1374        TRACE("currentPos[%d]", _currentPosIndex);
1375        for (int i = 0; i < _width * _height * 3; i += 3)
1376            TRACE("%.2f, %.2f, %.2f\n", debug[i], debug[i+1], debug[i+2]);
1377        TRACE("\n");
1378        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1379    }
1380    */
1381
1382    // compute distance
1383    swap(_currentSortIndex, _destSortIndex);
1384
1385    // END - COMPUTE DISTANCE
1386    ///////////////////////////////////////////////////////////
1387
1388    ///////////////////////////////////////////////////////////
1389    // BEGIN - MERGE SORT
1390    _currentSortPass = 0;
1391
1392    int logdSize = logd(_particleMaxCount);
1393    _maxSortPasses = (logdSize + 1) * logdSize / 2;
1394
1395    _sortBegin = _sortEnd;
1396    _sortEnd = (_sortBegin + _sortPassesPerFrame) % _maxSortPasses;
1397
1398    cgGLSetParameter2f(_srSizeParam, (float)_width, (float)_height);
1399    cgGLSetParameter2f(_seSizeParam, (float)_width, (float)_height);
1400
1401    mergeSort(this->_particleMaxCount);
1402
1403    // _DEBUG
1404    /*
1405    {
1406        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_currentSortIndex]);
1407        static float debug[256];
1408        glReadPixels(0, 0, _width, _height, GL_RGB, GL_FLOAT, (float*)debug);
1409        TRACE("\n");
1410        TRACE("[%d]", _currentSortIndex);
1411        for (int i = 0; i < _width * _height * 3; i += 3)
1412            TRACE("%.2f, %.2f, %.2f\n", debug[i], debug[i+1], debug[i+2]);
1413        TRACE("\n");
1414        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1415    }
1416    */
1417
1418    // END - MERGE SORT
1419    ///////////////////////////////////////////////////////////
1420
1421    ///////////////////////////////////////////////////////////
1422    // POSITION LOOKUP
1423    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
1424    cgGLBindProgram(_distanceSortLookupFP);
1425    cgGLEnableProfile(CG_PROFILE_FP40);
1426
1427    glActiveTextureARB(GL_TEXTURE0_ARB);
1428    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sort_tex[_currentSortIndex]);
1429
1430    glActiveTextureARB(GL_TEXTURE1_ARB);
1431    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_currentPosIndex]);
1432
1433    glPushAttrib(GL_VIEWPORT_BIT);
1434    glViewport(0, 0, _width, _height);
1435    glMatrixMode(GL_PROJECTION);
1436    glPushMatrix();
1437    glLoadIdentity();
1438    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1439    glMatrixMode(GL_MODELVIEW);
1440    glPushMatrix();
1441    glLoadIdentity();
1442
1443    drawQuad();
1444
1445    glMatrixMode(GL_PROJECTION);
1446    glPopMatrix();
1447    glMatrixMode(GL_MODELVIEW);
1448    glPopMatrix();
1449    glPopAttrib();
1450
1451    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1452    cgGLDisableProfile(CG_PROFILE_FP40);
1453
1454    // POSITION LOOKUP
1455    ///////////////////////////////////////////////////////////
1456    glActiveTextureARB(GL_TEXTURE1_ARB);
1457    glDisable(GL_TEXTURE_RECTANGLE_ARB);
1458
1459    glActiveTextureARB(GL_TEXTURE0_ARB);
1460    glDisable(GL_TEXTURE_RECTANGLE_ARB);
1461
1462    // _DEBUG
1463    /*
1464    {
1465        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
1466        static float debug[256];
1467        glReadPixels(0, 0, _width, _height, GL_RGB, GL_FLOAT, (float*)debug);
1468        TRACE("\n");
1469        TRACE("[%d]", _currentSortIndex);
1470        for (int i = 0; i < _width * _height * 3; i += 3)
1471            TRACE("%.2f, %.2f, %.2f\n", debug[i], debug[i+1], debug[i+2]);
1472        TRACE("\n");
1473        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1474    }
1475    */
1476}
1477
1478void ParticleSystem::mergeSort(int count)
1479{
1480    if (count > 1) {
1481        mergeSort(count >> 1);
1482        merge(count, 1);
1483    }
1484}
1485
1486void ParticleSystem::merge(int count, int step)
1487{
1488    if (count > 2) {
1489        merge(count >> 1, step << 1);
1490
1491        ++_currentSortPass;
1492
1493        if (_sortBegin < _sortEnd) {
1494            if (_currentSortPass < _sortBegin || _currentSortPass >= _sortEnd)
1495                return;
1496        } else {
1497            if (_currentSortPass < _sortBegin && _currentSortPass >= _sortEnd)
1498                return;
1499        }
1500
1501        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_destSortIndex]);
1502        cgGLBindProgram(_sortRecursionFP);
1503        cgGLEnableProfile(CG_PROFILE_FP40);
1504
1505        glActiveTextureARB(GL_TEXTURE0_ARB);
1506        glBindTexture(GL_TEXTURE_RECTANGLE_ARB , sort_tex[_currentSortIndex]);
1507
1508        cgGLSetParameter1f(_srStepParam, (float)step);
1509        cgGLSetParameter1f(_srCountParam, (float)count);
1510
1511        glPushAttrib(GL_VIEWPORT_BIT);
1512        glViewport(0, 0, _width, _height);
1513        glMatrixMode(GL_PROJECTION);
1514        glPushMatrix();
1515        glLoadIdentity();
1516        glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1517        glMatrixMode(GL_MODELVIEW);
1518        glPushMatrix();
1519        glLoadIdentity();
1520
1521        drawQuad();
1522
1523        glMatrixMode(GL_PROJECTION);
1524        glPopMatrix();
1525        glMatrixMode(GL_MODELVIEW);
1526        glPopMatrix();
1527        glPopAttrib();
1528
1529        cgGLDisableProfile(CG_PROFILE_FP40);
1530
1531        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1532        glBindTexture(GL_TEXTURE_RECTANGLE_ARB , 0);
1533    } else {
1534        _currentSortPass++;
1535
1536        if (_sortBegin < _sortEnd) {
1537            if (_currentSortPass < _sortBegin || _currentSortPass >= _sortEnd)
1538                return;
1539        } else {
1540            if (_currentSortPass < _sortBegin && _currentSortPass >= _sortEnd)
1541                return;
1542        }
1543
1544        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_destSortIndex]);
1545        cgGLBindProgram(_sortEndFP);
1546        cgGLEnableProfile(CG_PROFILE_FP40);
1547
1548        glActiveTextureARB(GL_TEXTURE0_ARB);
1549        glBindTexture(GL_TEXTURE_RECTANGLE_ARB , sort_tex[_currentSortIndex]);
1550
1551        cgGLSetParameter1f(_seStepParam, (float)step);
1552
1553        glPushAttrib(GL_VIEWPORT_BIT);
1554        glViewport(0, 0, _width, _height);
1555        glMatrixMode(GL_PROJECTION);
1556        glPushMatrix();
1557        glLoadIdentity();
1558        glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1559        glMatrixMode(GL_MODELVIEW);
1560        glPushMatrix();
1561        glLoadIdentity();
1562
1563        drawQuad();
1564
1565        glMatrixMode(GL_PROJECTION);
1566        glPopMatrix();
1567        glMatrixMode(GL_MODELVIEW);
1568        glPopMatrix();
1569        glPopAttrib();
1570
1571        cgGLDisableProfile(CG_PROFILE_FP40);
1572
1573        glBindTexture(GL_TEXTURE_RECTANGLE_ARB , 0);
1574        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1575    }
1576
1577    swap(_currentSortIndex, _destSortIndex);
1578}
1579
1580void ParticleSystem::renderStreamlines()
1581{
1582    if (_currentStreamlineIndex > 2) {
1583        glPushMatrix();
1584        glScalef(_scalex, _scaley, _scalez);
1585        glTranslatef(-0.5f, -0.5f, -0.5f);
1586
1587        if (_drawBBoxEnabled) drawUnitBox();
1588
1589        glColor3f(1.0f, 0.0f, 0.0f);
1590        glEnableClientState(GL_VERTEX_ARRAY);
1591        //glEnableClientState(GL_COLOR_ARRAY);
1592
1593        _streamVertices->SetPointer(0);
1594        //glColorPointer(4, GL_FLOAT, 0, 0);
1595
1596        ::glDrawElements(GL_LINES, _particleCount * 2 * (_currentStreamlineIndex - 1),
1597                         GL_UNSIGNED_INT, _indexBuffer);
1598        glDisableClientState(GL_VERTEX_ARRAY);
1599        glPopMatrix();
1600    }
1601}
1602
1603void ParticleSystem::render()
1604{
1605    glPushMatrix();
1606
1607    if (_streamlineEnabled) {
1608        renderStreamlines();
1609    } else {
1610        glScalef(_scalex, _scaley, _scalez);
1611        glTranslatef(-0.5f, -0.5f, -0.5f);
1612        if (_glyphEnabled) {
1613            if (_drawBBoxEnabled) drawUnitBox();
1614            glColor3f(1, 1, 1);
1615            glDepthMask(GL_FALSE);
1616            glEnable(GL_BLEND);
1617
1618#ifndef USE_RGBA_ARROW
1619            glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1620#else
1621            glEnable(GL_ALPHA_TEST);
1622            //glAlphaFunc(GL_GEQUAL, 0.5);
1623            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1624#endif
1625            glEnable(GL_POINT_SPRITE_ARB);
1626            glPointSize(_pointSize);
1627
1628            glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
1629
1630#ifndef TEST
1631            _arrows->activate(); //_arrows->bind(0);
1632            glEnable(GL_TEXTURE_2D);
1633            //glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 60.0f );
1634            glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 0.0f );
1635
1636            glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 1.0f);
1637            glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, 100.0f);
1638            glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
1639
1640            cgGLBindProgram(_particleVP);
1641            cgGLBindProgram(_particleFP);
1642            cgGLEnableProfile(CG_PROFILE_VP40);
1643            cgGLEnableProfile(CG_PROFILE_FP40);
1644
1645            cgSetParameter1f(_mvCurrentTimeParam, _currentTime);
1646            //TRACE("%f %f, %f %d\n", _fov, tan(_fov), tan(_fov / 2.0), _screenHeight);
1647            //cgSetParameter1f(_mvTanHalfFOVParam, -tan(_fov * M_PI / 180 * 0.5) * _screenHeight * 0.5);
1648            //float v = tan(_fov * M_PI / 180 * 0.5) * _screenHeight * 0.5;
1649            cgSetParameter1f(_mvTanHalfFOVParam, tan(_fov * M_PI / 180 * 0.5) * _screenHeight * 0.5);
1650            //cgSetParameter1f(_mvTanHalfFOVParam,  _screenHeight * 0.5 / tan(_fov * M_PI / 180 * 0.5));
1651
1652            cgGLSetStateMatrixParameter(_mvpParticleParam,
1653                                        CG_GL_MODELVIEW_PROJECTION_MATRIX,
1654                                        CG_GL_MATRIX_IDENTITY);
1655            cgGLSetStateMatrixParameter(_mvParticleParam,
1656                                        CG_GL_MODELVIEW_MATRIX,
1657                                        CG_GL_MATRIX_IDENTITY);
1658
1659            // TBD..
1660            glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);                     
1661            glEnableVertexAttribArrayARB(8);
1662            glEnableClientState(GL_VERTEX_ARRAY);
1663            //glEnableClientState(GL_COLOR_ARRAY);
1664            _vertices->SetPointer(0);
1665            //glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
1666            //glColorPointer(4, GL_FLOAT, 0, 0);
1667            //glBindBufferARB(GL_ARRAY_BUFFER, 0);
1668
1669            // TBD...
1670            glDrawArrays(GL_POINTS, 0, this->_particleMaxCount);
1671            glPointSize(1);
1672
1673            glDisableClientState(GL_VERTEX_ARRAY);
1674            //glDisableClientState(GL_COLOR_ARRAY);
1675
1676            // TBD...
1677            ::glDisableVertexAttribArray(8);
1678            glPopClientAttrib();
1679
1680            cgGLDisableProfile(CG_PROFILE_VP40);
1681            cgGLDisableProfile(CG_PROFILE_FP40);
1682
1683            glDepthMask(GL_TRUE);
1684
1685            glDisable(GL_POINT_SPRITE_ARB);
1686            glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
1687
1688            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1689            glDisable(GL_BLEND);
1690#else
1691            glBindTexture(GL_TEXTURE_2D, ::SpotTexID);
1692            glEnable(GL_TEXTURE_2D);
1693            //glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 60.0f );
1694            glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 0.0f );
1695
1696            glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 1.0f);
1697            glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, 100.0f);
1698            glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
1699
1700            glEnableClientState(GL_VERTEX_ARRAY);
1701            //glEnableClientState(GL_COLOR_ARRAY);
1702            _vertices->SetPointer(0);
1703            //glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
1704            //glColorPointer(4, GL_FLOAT, 0, 0);
1705            //glBindBufferARB(GL_ARRAY_BUFFER, 0);
1706
1707            // TBD...
1708            glDrawArrays(GL_POINTS, 0, this->_particleMaxCount);
1709            glPointSize(1);
1710            glDrawArrays(GL_POINTS, 0, this->_particleMaxCount);
1711
1712            glDisableClientState(GL_VERTEX_ARRAY);
1713
1714            glDepthMask(GL_TRUE);
1715
1716            glDisable(GL_POINT_SPRITE_ARB);
1717            glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
1718
1719            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1720            glDisable(GL_BLEND);
1721#endif
1722        } else {
1723            if (_drawBBoxEnabled) drawUnitBox();
1724
1725            glColor3f(1, 1, 1);
1726            glEnableClientState(GL_VERTEX_ARRAY);
1727            //glEnableClientState(GL_COLOR_ARRAY);
1728            glPointSize(10);
1729            _vertices->SetPointer(0);
1730            //glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
1731            //glColorPointer(4, GL_FLOAT, 0, 0);
1732            //glBindBufferARB(GL_ARRAY_BUFFER, 0);
1733            glDrawArrays(GL_POINTS, 0, _particleMaxCount);
1734
1735            glPointSize(1);
1736            _vertices->SetPointer(0);
1737            //glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
1738            //glColorPointer(4, GL_FLOAT, 0, 0);
1739            //glBindBufferARB(GL_ARRAY_BUFFER, 0);
1740            glDrawArrays(GL_POINTS, 0, _particleMaxCount);
1741
1742            glDisableClientState(GL_VERTEX_ARRAY);
1743        }
1744
1745#ifdef notdef
1746        if (_criticalPoints && _criticalPoints->size()) {
1747            std::vector<vrVector3f>::iterator iter;
1748            glColor4f(1, 1, 1, 1);
1749            glPointSize(10);
1750            glBegin(GL_POINTS);
1751            for (iter = _criticalPoints->begin(); iter != _criticalPoints->end(); ++iter) {
1752                glVertex3f((*iter).x, (*iter).y, (*iter).z);
1753            }
1754            glEnd();
1755            glPointSize(1);
1756        }
1757#endif
1758    }
1759
1760    glPopMatrix();
1761}
1762
1763void ParticleSystem::drawQuad(int x1, int y1, int x2, int y2)
1764{
1765    glBegin(GL_QUADS);
1766
1767    glTexCoord2f(x1, y1);
1768    glVertex2f(x1, y1);
1769
1770    glTexCoord2f(x2, y1);
1771    glVertex2f(x2, y1);
1772
1773    glTexCoord2f(x2, y2);
1774    glVertex2f(x2, y2);
1775
1776    glTexCoord2f(x1, y2);
1777    glVertex2f(x1, y2);
1778
1779    glEnd();
1780}
1781
1782void ParticleSystem::drawQuad()
1783{
1784    glBegin(GL_QUADS);
1785
1786    glTexCoord2f(0, 0);
1787    glVertex2f(0, 0);
1788
1789    glTexCoord2f((float)_width, 0);
1790    glVertex2f((float)_width, 0);
1791
1792    glTexCoord2f((float)_width, (float)_height);
1793    glVertex2f((float)_width, (float)_height);
1794
1795    glTexCoord2f(0, (float)_height);
1796    glVertex2f(0, (float)_height);
1797
1798    glEnd();
1799}
1800
1801void ParticleSystem::addEmitter(ParticleEmitter* emitter)
1802{
1803    _emitters.push_back(emitter);
1804}
1805
1806void ParticleSystem::removeEmitter(int index)
1807{
1808    // TBD...
1809}
1810
1811void ParticleSystem::removeAllEmitters()
1812{
1813    std::vector<ParticleEmitter*>::iterator iter;
1814    for (iter = _emitters.begin(); iter != _emitters.end(); ++iter) {
1815        delete *iter;
1816    }
1817    _emitters.clear();
1818}
1819
1820void ParticleSystem::drawUnitBox()
1821{
1822    float x0 = 0.0f, y0 = 0.0f, z0 = 0.0f;
1823    float x1 = 1.0f, y1 = 1.0f, z1 = 1.0f;
1824    float r = 1.0f, g = 1.0f, b = 0.0f;
1825    float line_width = 2.0f;
1826    glEnable(GL_DEPTH_TEST);
1827    glDisable(GL_TEXTURE_2D);
1828    glEnable(GL_BLEND);
1829
1830    glColor4d(r, g, b, 1.0);
1831    glLineWidth(line_width);
1832
1833    glBegin(GL_LINE_LOOP);
1834    {
1835        glVertex3d(x0, y0, z0);
1836        glVertex3d(x1, y0, z0);
1837        glVertex3d(x1, y1, z0);
1838        glVertex3d(x0, y1, z0);
1839    }
1840    glEnd();
1841
1842    glBegin(GL_LINE_LOOP);
1843    {
1844        glVertex3d(x0, y0, z1);
1845        glVertex3d(x1, y0, z1);
1846        glVertex3d(x1, y1, z1);
1847        glVertex3d(x0, y1, z1);
1848    }
1849    glEnd();
1850
1851    glBegin(GL_LINE_LOOP);
1852    {
1853        glVertex3d(x0, y0, z0);
1854        glVertex3d(x0, y0, z1);
1855        glVertex3d(x0, y1, z1);
1856        glVertex3d(x0, y1, z0);
1857    }
1858    glEnd();
1859
1860    glBegin(GL_LINE_LOOP);
1861    {
1862        glVertex3d(x1, y0, z0);
1863        glVertex3d(x1, y0, z1);
1864        glVertex3d(x1, y1, z1);
1865        glVertex3d(x1, y1, z0);
1866    }
1867    glEnd();
1868    glLineWidth(1.0f);
1869}
1870
1871void ParticleSystem::setUserDefinedNumOfParticles(int numParticles)
1872{
1873    if (numParticles < _particleMaxCount)
1874        _userDefinedParticleMaxCount = numParticles;
1875    else
1876        _userDefinedParticleMaxCount = _particleMaxCount;
1877    reset();
1878}
Note: See TracBrowser for help on using the repository browser.