source: trunk/packages/vizservers/nanovis/ParticleSystem.cpp @ 3492

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

Fix camera reset for nanovis. Includes refactoring of vector/matrix classes
in nanovis to consolidate into vrmath library. Also add preliminary canonical
view control to clients for testing.

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