source: nanovis/trunk/ParticleSystem.cpp @ 4822

Last change on this file since 4822 was 4167, checked in by ldelgass, 6 years ago

Texture environment is not part of texture object stored state, so don't set
environment mode before loading textures, should be done at render time.

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