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

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

Remove unused Event logging, move init/exit service routines to nanovis.cpp

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