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

Last change on this file since 3502 was 3502, checked in by ldelgass, 7 years ago

Add basic VTK structured points reader to nanovis, update copyright dates.

File size: 59.7 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 "DataLoader.h"
30#include "Texture2D.h"
31#include "Texture3D.h"
32#include "NvShader.h"
33#include "Trace.h"
34
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 = NvShader::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 += _emitters[i]->_maxPositionOffset * 
1113                    vrmath::Vector3f(randomRange(-1.0f, 1.0f), randomRange(-1.0f, 1.0f), randomRange(-1.0f, 1.0f));
1114
1115                float lifetime = randomRange(_emitters[i]->_minLifeTime, _emitters[i]->_maxLifeTime);
1116
1117                // TBD..
1118                allocateParticle(position, vrmath::Vector3f(0.0f, 0.0f, 0.0f),  lifetime, 1 - (float) k / numOfNewParticles);
1119            }
1120        }
1121
1122        initNewParticles();
1123
1124        _currentTime += deltaT;
1125
1126        cleanUpParticles();
1127    }
1128
1129    return true;
1130}
1131
1132void ParticleSystem::allocateParticle(const vrmath::Vector3f& position, const vrmath::Vector3f& velocity,
1133                                      float lifeTime, float initTimeStep)
1134{
1135    if (_availableIndices.empty()) {
1136        return;
1137    }
1138
1139    int index = _availableIndices.top(); 
1140    _availableIndices.pop();
1141
1142    ActiveParticle p;
1143    p.index = index;
1144    p.timeOfDeath = _currentTime + lifeTime;
1145    _activeParticles.push(p);
1146
1147    NewParticle newParticle;
1148    newParticle.index = index;
1149    newParticle.position = position;
1150    newParticle.velocity = velocity;
1151    newParticle.timeOfDeath = p.timeOfDeath;
1152    newParticle.initTimeStep = initTimeStep;
1153
1154    _newParticles.push_back(newParticle);
1155
1156    _particles[index].timeOfBirth = _currentTime;
1157    _particles[index].lifeTime = lifeTime;
1158}
1159
1160void ParticleSystem::initNewParticles()
1161{
1162    /////////////////////////////
1163    // INIT NEW PARTICLE
1164    glBindBufferARB(GL_ARRAY_BUFFER_ARB, _particleInfoBufferID);
1165    Particle* pinfo = (Particle*) glMapBufferARB(GL_ARRAY_BUFFER, GL_WRITE_ONLY_ARB);
1166
1167    std::vector<NewParticle>::iterator iter;
1168    for (iter = _newParticles.begin(); iter != _newParticles.end(); ++iter) {
1169        pinfo[iter->index] = _particles[iter->index];
1170    }
1171
1172    glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
1173
1174    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_currentPosIndex]);
1175
1176    glPushAttrib(GL_VIEWPORT_BIT);
1177    glViewport(0, 0, _width, _height);
1178    glMatrixMode(GL_PROJECTION);
1179    glPushMatrix();
1180    glLoadIdentity();
1181    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1182    glMatrixMode(GL_MODELVIEW);
1183    glPushMatrix();
1184    glLoadIdentity();
1185
1186    cgGLBindProgram(_initParticlePosFP);
1187    cgGLEnableProfile(CG_PROFILE_FP40);
1188    cgGLSetTextureParameter(_ipVectorFieldParam, _curVectorFieldID);
1189    cgGLEnableTextureParameter(_ipVectorFieldParam);
1190    // TBD..
1191    //glActiveTextureARB(GL_TEXTURE0_ARB);
1192    //VelocityPBuffers[VelocityCurrent]->Bind();
1193
1194    glActiveTextureARB(GL_TEXTURE0_ARB);
1195    glEnable(GL_TEXTURE_RECTANGLE_ARB);
1196    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_destPosIndex]);
1197
1198    glBegin(GL_POINTS);
1199    for (iter = _newParticles.begin(); iter != _newParticles.end(); iter++) {
1200        //TRACE("[%d] %f %f %f", iter->index, iter->position.x,iter->position.y,iter->position.z);
1201        glMultiTexCoord3f(GL_TEXTURE0, iter->position.x,iter->position.y,iter->position.z);
1202
1203        // TBD..
1204        //glMultiTexCoord2f(GL_TEXTURE1_ARB, (float)(i->Index % Width), (float)(i->Index / Height));
1205        //glMultiTexCoord1f(GL_TEXTURE2_ARB, iter->initTimeStep);
1206
1207        glVertex2f((float)(iter->index % _width),
1208                   (float)(iter->index / _height) + 1/* + offsetY*/ /* + offsetY shouldn't be */);
1209        //TRACE("%f %f", (float) (iter->index % _width), (float)(iter->index / _width));
1210    }
1211    glEnd();
1212
1213    glDisable(GL_TEXTURE_RECTANGLE_ARB);
1214    cgGLDisableTextureParameter(_ipVectorFieldParam);
1215    cgGLDisableProfile(CG_PROFILE_FP40);
1216
1217    glMatrixMode(GL_PROJECTION);
1218    glPopMatrix();
1219    glMatrixMode(GL_MODELVIEW);
1220    glPopMatrix();
1221    glPopAttrib();
1222
1223    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1224
1225    // INIT NEW END
1226    /////////////////////////////
1227#if 1
1228    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _initPos_fbo);
1229    glPushAttrib(GL_VIEWPORT_BIT);
1230    glViewport(0, 0, _width, _height);
1231    glMatrixMode(GL_PROJECTION);
1232    glPushMatrix();
1233    glLoadIdentity();
1234    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1235    glMatrixMode(GL_MODELVIEW);
1236    glPushMatrix();
1237    glLoadIdentity();
1238
1239    cgGLBindProgram(_initParticlePosFP);
1240    cgGLEnableProfile(CG_PROFILE_FP40);
1241    cgGLSetTextureParameter(_ipVectorFieldParam, _curVectorFieldID);
1242    cgGLEnableTextureParameter(_ipVectorFieldParam);
1243    // TBD..
1244    //glActiveTextureARB(GL_TEXTURE0_ARB);
1245    //VelocityPBuffers[VelocityCurrent]->Bind();
1246
1247    glActiveTextureARB(GL_TEXTURE0_ARB);
1248    glEnable(GL_TEXTURE_RECTANGLE_ARB);
1249    //glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _initPosTex);
1250    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_destPosIndex]);
1251
1252    glBegin(GL_POINTS);
1253    for (iter = _newParticles.begin(); iter != _newParticles.end(); iter++) {
1254        //TRACE("[%d] %f %f %f", iter->index, iter->position.x,iter->position.y,iter->position.z);
1255        glMultiTexCoord3f(GL_TEXTURE0, iter->position.x,iter->position.y,iter->position.z);
1256
1257        // TBD..
1258        //glMultiTexCoord2f(GL_TEXTURE1_ARB, (float)(i->Index % Width), (float)(i->Index / Height));
1259        //glMultiTexCoord1f(GL_TEXTURE2_ARB, iter->initTimeStep);
1260
1261        glVertex2f((float)(iter->index % _width),
1262                   (float)(iter->index / _height) + 1/* + offsetY*/ /* + offsetY shouldn't be */);
1263        //TRACE("%f %f", (float) (iter->index % _width), (float)(iter->index / _width));
1264    }
1265    glEnd();
1266
1267    glDisable(GL_TEXTURE_RECTANGLE_ARB);
1268    cgGLDisableTextureParameter(_ipVectorFieldParam);
1269    cgGLDisableProfile(CG_PROFILE_FP40);
1270
1271    glMatrixMode(GL_PROJECTION);
1272    glPopMatrix();
1273    glMatrixMode(GL_MODELVIEW);
1274    glPopMatrix();
1275    glPopAttrib();
1276
1277    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1278#endif
1279
1280    // Free array.
1281    _newParticles.clear();
1282}
1283
1284void ParticleSystem::cleanUpParticles()
1285{
1286    if (! _activeParticles.empty()) {
1287        while (_activeParticles.top().timeOfDeath < _currentTime) {
1288            unsigned int i = _activeParticles.top().index;
1289            _activeParticles.pop();
1290            _availableIndices.push(i);
1291            //_usedIndices[i] = false;
1292
1293            //if (i >= _maxUsedIndex)
1294            //    while (!_usedIndices[_maxUsedIndex])
1295            //        _maxUsedIndex--;
1296        }
1297    }
1298}
1299
1300void ParticleSystem::sort()
1301{
1302    ///////////////////////////////////////////////////////////
1303    // BEGIN - COMPUTE DISTANCE
1304    vrmath::Vector3f pos;
1305    vrmath::Matrix4x4d mat;
1306    glPushMatrix();
1307    glLoadIdentity();
1308    glScalef(_scalex, _scaley, _scalez);
1309    glTranslatef(-0.5f, -0.5f, -0.5f);
1310    glGetDoublev(GL_MODELVIEW_MATRIX, mat.get());
1311    glPopMatrix();
1312    mat.invert();
1313    mat.getTranslation(pos);
1314
1315    cgGLBindProgram(_distanceSortFP);
1316    cgGLEnableProfile(CG_PROFILE_FP40);
1317
1318    glActiveTextureARB(GL_TEXTURE0_ARB);
1319    glEnable(GL_TEXTURE_RECTANGLE_ARB);
1320    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sort_tex[_currentSortIndex]);
1321
1322    glActiveTextureARB(GL_TEXTURE1_ARB);
1323    glEnable(GL_TEXTURE_RECTANGLE_ARB);
1324    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_currentPosIndex]);
1325
1326    cgGLSetParameter3f(_viewPosParam, pos.x, pos.y, pos.z);
1327
1328    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_destSortIndex]);
1329    glPushAttrib(GL_VIEWPORT_BIT);
1330    glViewport(0, 0, _width, _height);
1331    glMatrixMode(GL_PROJECTION);
1332    glPushMatrix();
1333    glLoadIdentity();
1334    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1335    glMatrixMode(GL_MODELVIEW);
1336    glPushMatrix();
1337    glLoadIdentity();
1338
1339    drawQuad();
1340
1341    cgGLDisableProfile(CG_PROFILE_FP40);
1342
1343    glMatrixMode(GL_PROJECTION);
1344    glPopMatrix();
1345    glMatrixMode(GL_MODELVIEW);
1346    glPopMatrix();
1347    glPopAttrib();
1348    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1349
1350    // _DEBUG
1351    /*
1352    {
1353        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_destSortIndex]);
1354        static float debug[256];
1355        glReadPixels(0, 0, _width, _height, GL_RGB, GL_FLOAT, (float*)debug);
1356        TRACE("[%d]", _currentSortIndex);
1357        for (int i = 0; i < _width * _height * 3; i += 3)
1358            TRACE("%.2f, %.2f, %.2f", debug[i], debug[i+1], debug[i+2]);
1359        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1360    }
1361    */
1362
1363    // _DEBUG
1364    /*
1365    {
1366        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_currentPosIndex]);
1367        static float debug[256];
1368        glReadPixels(0, 0, _width, _height, GL_RGB, GL_FLOAT, (float*)debug);
1369        TRACE("currentPos[%d]", _currentPosIndex);
1370        for (int i = 0; i < _width * _height * 3; i += 3)
1371            TRACE("%.2f, %.2f, %.2f", debug[i], debug[i+1], debug[i+2]);
1372        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1373    }
1374    */
1375
1376    // compute distance
1377    swap(_currentSortIndex, _destSortIndex);
1378
1379    // END - COMPUTE DISTANCE
1380    ///////////////////////////////////////////////////////////
1381
1382    ///////////////////////////////////////////////////////////
1383    // BEGIN - MERGE SORT
1384    _currentSortPass = 0;
1385
1386    int logdSize = logd(_particleMaxCount);
1387    _maxSortPasses = (logdSize + 1) * logdSize / 2;
1388
1389    _sortBegin = _sortEnd;
1390    _sortEnd = (_sortBegin + _sortPassesPerFrame) % _maxSortPasses;
1391
1392    cgGLSetParameter2f(_srSizeParam, (float)_width, (float)_height);
1393    cgGLSetParameter2f(_seSizeParam, (float)_width, (float)_height);
1394
1395    mergeSort(this->_particleMaxCount);
1396
1397    // _DEBUG
1398    /*
1399    {
1400        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_currentSortIndex]);
1401        static float debug[256];
1402        glReadPixels(0, 0, _width, _height, GL_RGB, GL_FLOAT, (float*)debug);
1403        TRACE("[%d]", _currentSortIndex);
1404        for (int i = 0; i < _width * _height * 3; i += 3)
1405            TRACE("%.2f, %.2f, %.2f", debug[i], debug[i+1], debug[i+2]);
1406        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1407    }
1408    */
1409
1410    // END - MERGE SORT
1411    ///////////////////////////////////////////////////////////
1412
1413    ///////////////////////////////////////////////////////////
1414    // POSITION LOOKUP
1415    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
1416    cgGLBindProgram(_distanceSortLookupFP);
1417    cgGLEnableProfile(CG_PROFILE_FP40);
1418
1419    glActiveTextureARB(GL_TEXTURE0_ARB);
1420    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sort_tex[_currentSortIndex]);
1421
1422    glActiveTextureARB(GL_TEXTURE1_ARB);
1423    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_currentPosIndex]);
1424
1425    glPushAttrib(GL_VIEWPORT_BIT);
1426    glViewport(0, 0, _width, _height);
1427    glMatrixMode(GL_PROJECTION);
1428    glPushMatrix();
1429    glLoadIdentity();
1430    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1431    glMatrixMode(GL_MODELVIEW);
1432    glPushMatrix();
1433    glLoadIdentity();
1434
1435    drawQuad();
1436
1437    glMatrixMode(GL_PROJECTION);
1438    glPopMatrix();
1439    glMatrixMode(GL_MODELVIEW);
1440    glPopMatrix();
1441    glPopAttrib();
1442
1443    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1444    cgGLDisableProfile(CG_PROFILE_FP40);
1445
1446    // POSITION LOOKUP
1447    ///////////////////////////////////////////////////////////
1448    glActiveTextureARB(GL_TEXTURE1_ARB);
1449    glDisable(GL_TEXTURE_RECTANGLE_ARB);
1450
1451    glActiveTextureARB(GL_TEXTURE0_ARB);
1452    glDisable(GL_TEXTURE_RECTANGLE_ARB);
1453
1454    // _DEBUG
1455    /*
1456    {
1457        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
1458        static float debug[256];
1459        glReadPixels(0, 0, _width, _height, GL_RGB, GL_FLOAT, (float*)debug);
1460        TRACE("[%d]", _currentSortIndex);
1461        for (int i = 0; i < _width * _height * 3; i += 3)
1462            TRACE("%.2f, %.2f, %.2f", debug[i], debug[i+1], debug[i+2]);
1463        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1464    }
1465    */
1466}
1467
1468void ParticleSystem::mergeSort(int count)
1469{
1470    if (count > 1) {
1471        mergeSort(count >> 1);
1472        merge(count, 1);
1473    }
1474}
1475
1476void ParticleSystem::merge(int count, int step)
1477{
1478    if (count > 2) {
1479        merge(count >> 1, step << 1);
1480
1481        ++_currentSortPass;
1482
1483        if (_sortBegin < _sortEnd) {
1484            if (_currentSortPass < _sortBegin || _currentSortPass >= _sortEnd)
1485                return;
1486        } else {
1487            if (_currentSortPass < _sortBegin && _currentSortPass >= _sortEnd)
1488                return;
1489        }
1490
1491        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_destSortIndex]);
1492        cgGLBindProgram(_sortRecursionFP);
1493        cgGLEnableProfile(CG_PROFILE_FP40);
1494
1495        glActiveTextureARB(GL_TEXTURE0_ARB);
1496        glBindTexture(GL_TEXTURE_RECTANGLE_ARB , sort_tex[_currentSortIndex]);
1497
1498        cgGLSetParameter1f(_srStepParam, (float)step);
1499        cgGLSetParameter1f(_srCountParam, (float)count);
1500
1501        glPushAttrib(GL_VIEWPORT_BIT);
1502        glViewport(0, 0, _width, _height);
1503        glMatrixMode(GL_PROJECTION);
1504        glPushMatrix();
1505        glLoadIdentity();
1506        glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1507        glMatrixMode(GL_MODELVIEW);
1508        glPushMatrix();
1509        glLoadIdentity();
1510
1511        drawQuad();
1512
1513        glMatrixMode(GL_PROJECTION);
1514        glPopMatrix();
1515        glMatrixMode(GL_MODELVIEW);
1516        glPopMatrix();
1517        glPopAttrib();
1518
1519        cgGLDisableProfile(CG_PROFILE_FP40);
1520
1521        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1522        glBindTexture(GL_TEXTURE_RECTANGLE_ARB , 0);
1523    } else {
1524        _currentSortPass++;
1525
1526        if (_sortBegin < _sortEnd) {
1527            if (_currentSortPass < _sortBegin || _currentSortPass >= _sortEnd)
1528                return;
1529        } else {
1530            if (_currentSortPass < _sortBegin && _currentSortPass >= _sortEnd)
1531                return;
1532        }
1533
1534        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_destSortIndex]);
1535        cgGLBindProgram(_sortEndFP);
1536        cgGLEnableProfile(CG_PROFILE_FP40);
1537
1538        glActiveTextureARB(GL_TEXTURE0_ARB);
1539        glBindTexture(GL_TEXTURE_RECTANGLE_ARB , sort_tex[_currentSortIndex]);
1540
1541        cgGLSetParameter1f(_seStepParam, (float)step);
1542
1543        glPushAttrib(GL_VIEWPORT_BIT);
1544        glViewport(0, 0, _width, _height);
1545        glMatrixMode(GL_PROJECTION);
1546        glPushMatrix();
1547        glLoadIdentity();
1548        glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1549        glMatrixMode(GL_MODELVIEW);
1550        glPushMatrix();
1551        glLoadIdentity();
1552
1553        drawQuad();
1554
1555        glMatrixMode(GL_PROJECTION);
1556        glPopMatrix();
1557        glMatrixMode(GL_MODELVIEW);
1558        glPopMatrix();
1559        glPopAttrib();
1560
1561        cgGLDisableProfile(CG_PROFILE_FP40);
1562
1563        glBindTexture(GL_TEXTURE_RECTANGLE_ARB , 0);
1564        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1565    }
1566
1567    swap(_currentSortIndex, _destSortIndex);
1568}
1569
1570void ParticleSystem::renderStreamlines()
1571{
1572    if (_currentStreamlineIndex > 2) {
1573        glPushMatrix();
1574        glScalef(_scalex, _scaley, _scalez);
1575        glTranslatef(-0.5f, -0.5f, -0.5f);
1576
1577        if (_drawBBoxEnabled) drawUnitBox();
1578
1579        glColor3f(1.0f, 0.0f, 0.0f);
1580        glEnableClientState(GL_VERTEX_ARRAY);
1581        //glEnableClientState(GL_COLOR_ARRAY);
1582
1583        _streamVertices->SetPointer(0);
1584        //glColorPointer(4, GL_FLOAT, 0, 0);
1585
1586        ::glDrawElements(GL_LINES, _particleCount * 2 * (_currentStreamlineIndex - 1),
1587                         GL_UNSIGNED_INT, _indexBuffer);
1588        glDisableClientState(GL_VERTEX_ARRAY);
1589        glPopMatrix();
1590    }
1591}
1592
1593void ParticleSystem::render()
1594{
1595    glPushMatrix();
1596
1597    if (_streamlineEnabled) {
1598        renderStreamlines();
1599    } else {
1600        glScalef(_scalex, _scaley, _scalez);
1601        glTranslatef(-0.5f, -0.5f, -0.5f);
1602        if (_glyphEnabled) {
1603            if (_drawBBoxEnabled) drawUnitBox();
1604            glColor3f(1, 1, 1);
1605
1606            glDepthMask(GL_FALSE);
1607            glEnable(GL_BLEND);
1608
1609#ifndef USE_RGBA_ARROW
1610            glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1611#else
1612            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1613#endif
1614            glEnable(GL_ALPHA_TEST);
1615            glAlphaFunc(GL_GREATER, 0.6);
1616
1617            glEnable(GL_POINT_SPRITE_ARB);
1618            glPointSize(_pointSize);
1619
1620            glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
1621
1622#ifndef TEST
1623            _arrows->activate();
1624            glEnable(GL_TEXTURE_2D);
1625            glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 0.0f);
1626
1627            glPointParameterfARB(GL_POINT_SIZE_MIN_ARB, 1.0f);
1628            glPointParameterfARB(GL_POINT_SIZE_MAX_ARB, 100.0f);
1629            glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
1630
1631            cgGLBindProgram(_particleVP);
1632            cgGLBindProgram(_particleFP);
1633            cgGLEnableProfile(CG_PROFILE_VP40);
1634            cgGLEnableProfile(CG_PROFILE_FP40);
1635
1636            cgSetParameter1f(_mvCurrentTimeParam, _currentTime);
1637            //TRACE("%f %f, %f %d", _fov, tan(_fov), tan(_fov / 2.0), _screenHeight);
1638            //cgSetParameter1f(_mvTanHalfFOVParam, -tan(_fov * M_PI / 180 * 0.5) * _screenHeight * 0.5);
1639            //float v = tan(_fov * M_PI / 180 * 0.5) * _screenHeight * 0.5;
1640            cgSetParameter1f(_mvTanHalfFOVParam, tan(_fov * M_PI / 180 * 0.5) * _screenHeight * 0.5);
1641            //cgSetParameter1f(_mvTanHalfFOVParam,  _screenHeight * 0.5 / tan(_fov * M_PI / 180 * 0.5));
1642
1643            cgGLSetStateMatrixParameter(_mvpParticleParam,
1644                                        CG_GL_MODELVIEW_PROJECTION_MATRIX,
1645                                        CG_GL_MATRIX_IDENTITY);
1646            cgGLSetStateMatrixParameter(_mvParticleParam,
1647                                        CG_GL_MODELVIEW_MATRIX,
1648                                        CG_GL_MATRIX_IDENTITY);
1649
1650            // TBD..
1651            glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);                     
1652            glEnableVertexAttribArrayARB(8);
1653            glEnableClientState(GL_VERTEX_ARRAY);
1654            //glEnableClientState(GL_COLOR_ARRAY);
1655            _vertices->SetPointer(0);
1656            //glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
1657            //glColorPointer(4, GL_FLOAT, 0, 0);
1658            //glBindBufferARB(GL_ARRAY_BUFFER, 0);
1659
1660            // TBD...
1661            glDrawArrays(GL_POINTS, 0, this->_particleMaxCount);
1662            glPointSize(1);
1663
1664            glDisableClientState(GL_VERTEX_ARRAY);
1665            //glDisableClientState(GL_COLOR_ARRAY);
1666
1667            // TBD...
1668            ::glDisableVertexAttribArray(8);
1669            glPopClientAttrib();
1670
1671            cgGLDisableProfile(CG_PROFILE_VP40);
1672            cgGLDisableProfile(CG_PROFILE_FP40);
1673
1674            glDepthMask(GL_TRUE);
1675
1676            glDisable(GL_POINT_SPRITE_ARB);
1677            glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
1678
1679            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1680            glDisable(GL_BLEND);
1681#else
1682            glBindTexture(GL_TEXTURE_2D, ::SpotTexID);
1683            glEnable(GL_TEXTURE_2D);
1684            //glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 60.0f );
1685            glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 0.0f );
1686
1687            glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 1.0f);
1688            glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, 100.0f);
1689            glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
1690
1691            glEnableClientState(GL_VERTEX_ARRAY);
1692            //glEnableClientState(GL_COLOR_ARRAY);
1693            _vertices->SetPointer(0);
1694            //glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
1695            //glColorPointer(4, GL_FLOAT, 0, 0);
1696            //glBindBufferARB(GL_ARRAY_BUFFER, 0);
1697
1698            // TBD...
1699            glDrawArrays(GL_POINTS, 0, this->_particleMaxCount);
1700            glPointSize(1);
1701            glDrawArrays(GL_POINTS, 0, this->_particleMaxCount);
1702
1703            glDisableClientState(GL_VERTEX_ARRAY);
1704
1705            glDepthMask(GL_TRUE);
1706
1707            glDisable(GL_POINT_SPRITE_ARB);
1708            glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
1709
1710            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1711            glDisable(GL_BLEND);
1712#endif
1713        } else {
1714            if (_drawBBoxEnabled) drawUnitBox();
1715
1716            glColor3f(1, 1, 1);
1717            glEnableClientState(GL_VERTEX_ARRAY);
1718            //glEnableClientState(GL_COLOR_ARRAY);
1719            glPointSize(10);
1720            _vertices->SetPointer(0);
1721            //glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
1722            //glColorPointer(4, GL_FLOAT, 0, 0);
1723            //glBindBufferARB(GL_ARRAY_BUFFER, 0);
1724            glDrawArrays(GL_POINTS, 0, _particleMaxCount);
1725
1726            glPointSize(1);
1727            _vertices->SetPointer(0);
1728            //glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
1729            //glColorPointer(4, GL_FLOAT, 0, 0);
1730            //glBindBufferARB(GL_ARRAY_BUFFER, 0);
1731            glDrawArrays(GL_POINTS, 0, _particleMaxCount);
1732
1733            glDisableClientState(GL_VERTEX_ARRAY);
1734        }
1735
1736#ifdef notdef
1737        if (_criticalPoints && _criticalPoints->size()) {
1738            std::vector<vrmath::Vector3f>::iterator iter;
1739            glColor4f(1, 1, 1, 1);
1740            glPointSize(10);
1741            glBegin(GL_POINTS);
1742            for (iter = _criticalPoints->begin(); iter != _criticalPoints->end(); ++iter) {
1743                glVertex3f((*iter).x, (*iter).y, (*iter).z);
1744            }
1745            glEnd();
1746            glPointSize(1);
1747        }
1748#endif
1749    }
1750
1751    glPopMatrix();
1752}
1753
1754void ParticleSystem::drawQuad(int x1, int y1, int x2, int y2)
1755{
1756    glBegin(GL_QUADS);
1757
1758    glTexCoord2f(x1, y1);
1759    glVertex2f(x1, y1);
1760
1761    glTexCoord2f(x2, y1);
1762    glVertex2f(x2, y1);
1763
1764    glTexCoord2f(x2, y2); 
1765    glVertex2f(x2, y2);
1766
1767    glTexCoord2f(x1, y2);
1768    glVertex2f(x1, y2);
1769
1770    glEnd();
1771}
1772
1773void ParticleSystem::drawQuad()
1774{
1775    glBegin(GL_QUADS);
1776
1777    glTexCoord2f(0, 0);
1778    glVertex2f(0, 0);
1779
1780    glTexCoord2f((float)_width, 0);
1781    glVertex2f((float)_width, 0);
1782
1783    glTexCoord2f((float)_width, (float)_height); 
1784    glVertex2f((float)_width, (float)_height);
1785
1786    glTexCoord2f(0, (float)_height);
1787    glVertex2f(0, (float)_height);
1788
1789    glEnd();
1790}
1791
1792void ParticleSystem::addEmitter(ParticleEmitter* emitter)
1793{
1794    _emitters.push_back(emitter);
1795}
1796
1797void ParticleSystem::removeEmitter(int index)
1798{
1799    // TBD...
1800}
1801
1802void ParticleSystem::removeAllEmitters()
1803{
1804    std::vector<ParticleEmitter*>::iterator iter;
1805    for (iter = _emitters.begin(); iter != _emitters.end(); ++iter) {
1806        delete *iter;
1807    }
1808    _emitters.clear();
1809}
1810
1811void ParticleSystem::drawUnitBox()
1812{
1813    float x0 = 0.0f, y0 = 0.0f, z0 = 0.0f;
1814    float x1 = 1.0f, y1 = 1.0f, z1 = 1.0f;
1815    float r = 1.0f, g = 1.0f, b = 0.0f;
1816    float line_width = 2.0f;
1817    glEnable(GL_DEPTH_TEST);
1818    glDisable(GL_TEXTURE_2D);
1819    glEnable(GL_BLEND);
1820
1821    glColor4d(r, g, b, 1.0);
1822    glLineWidth(line_width);
1823
1824    glBegin(GL_LINE_LOOP);
1825    {
1826        glVertex3d(x0, y0, z0);
1827        glVertex3d(x1, y0, z0);
1828        glVertex3d(x1, y1, z0);
1829        glVertex3d(x0, y1, z0);
1830    }
1831    glEnd();
1832
1833    glBegin(GL_LINE_LOOP);
1834    {
1835        glVertex3d(x0, y0, z1);
1836        glVertex3d(x1, y0, z1);
1837        glVertex3d(x1, y1, z1);
1838        glVertex3d(x0, y1, z1);
1839    }
1840    glEnd();
1841
1842    glBegin(GL_LINE_LOOP);
1843    {
1844        glVertex3d(x0, y0, z0);
1845        glVertex3d(x0, y0, z1);
1846        glVertex3d(x0, y1, z1);
1847        glVertex3d(x0, y1, z0);
1848    }
1849    glEnd();
1850
1851    glBegin(GL_LINE_LOOP);
1852    {
1853        glVertex3d(x1, y0, z0);
1854        glVertex3d(x1, y0, z1);
1855        glVertex3d(x1, y1, z1);
1856        glVertex3d(x1, y1, z0);
1857    }
1858    glEnd();
1859    glLineWidth(1.0f);
1860}
1861
1862void ParticleSystem::setUserDefinedNumOfParticles(int numParticles)
1863{
1864    if (numParticles < _particleMaxCount)
1865        _userDefinedParticleMaxCount = numParticles;
1866    else
1867        _userDefinedParticleMaxCount = _particleMaxCount;
1868    reset();
1869}
Note: See TracBrowser for help on using the repository browser.