source: nanovis/branches/1.1/ParticleSystem.cpp @ 5722

Last change on this file since 5722 was 4904, checked in by ldelgass, 10 years ago

Merge serveral changes from trunk. Does not include threading, world space
changes, etc.

File size: 59.8 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (c) 2004-2013  HUBzero Foundation, LLC
4 *
5 */
6
7#include <time.h>
8#include <stdlib.h>
9#include <stdio.h>
10#include <math.h>
11#include <pthread.h>
12
13#include <GL/glew.h>
14#include <Cg/cgGL.h>
15
16#include <util/FilePath.h>
17
18#include <Image.h>
19#include <ImageLoader.h>
20#include <ImageLoaderFactory.h>
21
22#include <vrmath/Matrix4x4d.h>
23#include <vrmath/Vector3f.h>
24#include <vrmath/Vector4f.h>
25
26#include "ParticleSystem.h"
27#include "ParticleEmitter.h"
28#include "Texture2D.h"
29#include "Texture3D.h"
30#include "Shader.h"
31#include "Trace.h"
32
33using namespace nv;
34using namespace nv::util;
35
36#define USE_RGBA_ARROW
37
38//#define TEST
39
40inline float randomRange(float rangeMin, float rangeMax)
41{
42    return ((float)rand() / RAND_MAX) * (rangeMax - rangeMin) + rangeMin ;
43}
44
45inline int logd(int value)
46{
47    int l;
48    for (l = 0; value >> l; l++);
49    return l - 1;
50}
51
52inline void swap(int& x, int& y)
53{
54    if (x != y) {
55        x ^= y;
56        y ^= x;
57        x ^= y;
58    }
59}
60
61void *ParticleSystem::dataLoadMain(void *data)
62{
63    ParticleSystem *particleSystem = (ParticleSystem *)data;
64    CircularFifo<float*, 10>& queue = particleSystem->_queue;
65
66    // TBD..
67    //float min = particleSystem->_time_series_vel_mag_min;
68    //float max = particleSystem->_time_series_vel_mag_max;
69
70    int startIndex = particleSystem->_flowFileStartIndex;
71    int endIndex = particleSystem->_flowFileEndIndex;
72
73    int curIndex = startIndex;
74    int flowWidth = particleSystem->_flowWidth;
75    int flowHeight = particleSystem->_flowHeight;
76    int flowDepth = particleSystem->_flowDepth;
77
78    const char* fileNameFormat = particleSystem->_fileNameFormat.c_str();
79    char buff[256];
80
81    bool done = false;
82    while (!done) {
83        if (curIndex > endIndex) {
84            curIndex = startIndex;
85        }
86
87        if (!queue.isFull()) {
88            int tail = queue.tailIndex();
89            if (tail != -1) {
90                sprintf(buff, fileNameFormat, curIndex);
91                //std::string path = FilePath::getInstance()->getPath(buff);
92#ifdef WANT_TRACE
93                float t = clock() /(float) CLOCKS_PER_SEC;
94#endif
95                LoadProcessedFlowRaw(buff, flowWidth, flowHeight, flowDepth, queue.array[tail]);
96#ifdef WANT_TRACE
97                float ti = clock() / (float) CLOCKS_PER_SEC;
98                TRACE("LoadProcessedFlowRaw time: %f", ti - t);
99#endif
100                queue.push();
101                TRACE("%d loaded", curIndex);
102                ++curIndex;
103            }
104        }
105    }
106
107    return 0;
108}
109
110CGcontext ParticleSystem::_context = 0;
111
112unsigned int SpotTexID = 0;
113
114void MakeSphereTexture()
115{
116    const int DIM = 128;
117    const int DIM2 = 63;
118    //const float TEX_SCALE = 6.0;
119
120    glGenTextures(1, (GLuint *)&SpotTexID);
121    glBindTexture(GL_TEXTURE_2D, SpotTexID);
122
123    float col[4] = {1.f, 1.f, 1.f, 1.f};
124    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, col);
125    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
126
127    float *img = new float[DIM*DIM];
128
129    vrmath::Vector3f light(1,1,3);
130    light = light.normalize();
131
132    for (int y = 0; y < DIM; y++) {
133        for (int x = 0; x < DIM; x++) {
134            // Clamping the edges to zero allows Nvidia's blend optimizations to do their thing.
135            if (x == 0 || x == DIM-1 || y == 0 || y == DIM-1) {
136                img[y*DIM+x] = 0;
137            } else {
138                vrmath::Vector3f p(x, y, 0);
139                p = p - vrmath::Vector3f(DIM2, DIM2, 0);
140                float len = p.length();
141                float z = sqrt(DIM2*DIM2 - len*len);
142                p.z = z;
143                if (len >= DIM2) {
144                    img[y*DIM+x] = 0.0;
145                    continue;
146                }
147
148                p = p.normalize();
149                float v = p.dot(light);
150                if(v < 0) v = 0;
151
152                img[y*DIM+x] = v;
153            }
154        }
155    }
156
157    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
158    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
159    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
160    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
161
162    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA16, DIM, DIM, GL_ALPHA, GL_FLOAT, img);
163}
164
165//extern void algorithm_test(vrmath::Vector4f* data, int flowWidth, int flowHeight, int flowDepth);
166//extern std::vector<vrmath::Vector3f>* find_critical_points(vrmath::Vector4f* data, int flowWidth, int flowHeight, int flowDepth);
167ParticleSystem::ParticleSystem(int width, int height,
168                               const std::string& fileName,
169                               int fieldWidth, int fieldHeight, int fieldDepth,
170                               bool timeVaryingData,
171                               int flowFileStartIndex, int flowFileEndIndex) :
172    _width(width),
173    _height(height)
174{
175    ////////////////////////////////
176    // TIME-VARYING SERIES
177    _isTimeVaryingField = timeVaryingData;
178    _flowFileStartIndex = flowFileStartIndex;
179    _flowFileEndIndex = flowFileEndIndex;
180    _userDefinedParticleMaxCount = width * height;
181
182    _skipByte = 0;
183
184    _screenWidth = _screenHeight = 1;
185    _fov = 60.0f;
186
187    _particleMaxCount = _width * _height;
188
189    _pointSize = 10.0f;
190    _camx = 0.0f;
191    _camy = 0.0f;
192    _camz = 0.0f;
193
194    _scalex = _scaley = _scalez = 1.0f;
195    _currentSortIndex = 0;
196    _destSortIndex = 1;
197
198    _currentPosIndex = 0;
199    _destPosIndex = 1;
200
201    _currentSortPass = 0;
202    // TBD
203    //_sortPassesPerFrame = 5;
204    _sortPassesPerFrame = 4;
205    _maxSortPasses = 0;
206
207    _sortBegin = 0;
208    _sortEnd = _sortPassesPerFrame;
209    _currentTime = 0;
210    _sortEnabled = false;
211    _glyphEnabled = false;
212    _advectionEnabled = false;
213    _streamlineEnabled = false;
214    _particles = new Particle[_particleMaxCount];
215    memset(_particles, 0, sizeof(Particle) * _particleMaxCount);
216
217    _colorBuffer = new color4[_particleMaxCount];
218    memset(_colorBuffer, 0, sizeof(color4) * _particleMaxCount);
219
220    _positionBuffer = new vrmath::Vector3f[_particleMaxCount];
221    _vertices = new RenderVertexArray(_particleMaxCount, 3, GL_FLOAT);
222
223    srand(time(0));
224
225    /*
226    // TBD..
227    glGenBuffersARB(1, &_colorBufferID);
228    glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
229    glBufferDataARB(GL_ARRAY_BUFFER, _width * _height * 4, _colorBuffer, GL_STREAM_DRAW_ARB); // undefined data
230    glBindBufferARB(GL_ARRAY_BUFFER, 0);
231    */
232
233    _flowWidth = fieldWidth;
234    _flowHeight = fieldHeight;
235    _flowDepth = fieldDepth;
236
237    float min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ;
238    int index = fileName.rfind('.');
239    std::string ext = fileName.substr(index + 1, fileName.size() - (index + 1));
240    float *data = 0;
241
242    if (this->isTimeVaryingField()) {
243        axisScaleX = _flowWidth;
244        axisScaleY = _flowHeight;
245        axisScaleZ = _flowDepth;
246        _fileNameFormat = fileName;
247        for (int i = 0; i < CircularFifo<float*, 10>::Capacity; ++i) {
248            _queue.array[i] = new float[_flowWidth * _flowHeight * _flowDepth * 4];
249        }
250
251        // INSOO
252        // TBD
253        min = 0;
254        max = 234.99;
255    } else {
256        if (ext == "dx") {
257            data = (float*) LoadFlowDx(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ);
258        } else if (ext == "raw") {
259            data = (float*) LoadFlowRaw(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ, 0, false);
260            //data = (float*) LoadProcessedFlowRaw(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, axisScaleX, axisScaleY, axisScaleZ);
261#ifdef notdef
262        } else if (ext == "raws") {
263            data = (float*) LoadFlowRaw(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ, 5 * sizeof(int), true);
264        } else if (ext == "data") {
265            data = (float*) LoadFlowRaw(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ, 0, true);
266#endif
267        }
268        //_criticalPoints = find_critical_points((vrmath::Vector4f*) data, _flowWidth,  _flowHeight,  _flowDepth);
269        //algorithm_test((vrmath::Vector4f*) data,  _flowWidth,  _flowHeight,  _flowDepth);
270    }
271
272    _scalex = 1;
273    _scaley = axisScaleY / axisScaleX;
274    _scalez = axisScaleZ / axisScaleX;
275    _maxVelocityScale = max;
276
277    if (!this->isTimeVaryingField()) {
278        Texture3D *flow = new Texture3D(_flowWidth, _flowHeight, _flowDepth,
279                                        GL_FLOAT, GL_LINEAR, 4, data);
280        _curVectorFieldID = flow->id();
281        _vectorFieldIDs.push_back(_curVectorFieldID);
282    } else {
283        for (int i = 0; i < 3; ++i) {
284            Texture3D *flow = new Texture3D(_flowWidth, _flowHeight, _flowDepth,
285                                            GL_FLOAT, GL_LINEAR, 4, data);
286            _vectorFields.push_back(flow);
287            _vectorFieldIDs.push_back(flow->id());
288        }
289        _curVectorFieldID = _vectorFieldIDs[0];
290    }
291
292    std::string path = FilePath::getInstance()->getPath("arrows.bmp");
293
294    if (!path.empty()) {
295        ImageLoader *loader = ImageLoaderFactory::getInstance()->createLoader("bmp");
296        if (loader != NULL) {
297#ifdef USE_RGBA_ARROW
298            Image *image = loader->load(path.c_str(), Image::IMG_RGBA);
299#else
300            Image *image = loader->load(path.c_str(), Image::IMG_RGB);
301#endif
302            if (image != NULL) {
303                unsigned char *bytes = (unsigned char *)image->getImageBuffer();
304                if (bytes != NULL) {
305#ifdef USE_RGBA_ARROW
306                    _arrows = new Texture2D(image->getWidth(), image->getHeight(),
307                                            GL_UNSIGNED_BYTE, GL_LINEAR, 4, NULL);
308#else
309                    _arrows = new Texture2D(image->getWidth(), image->getHeight(),
310                                            GL_UNSIGNED_BYTE, GL_LINEAR, 3, NULL);
311#endif
312                    _arrows->setWrapS(GL_MIRRORED_REPEAT);
313                    _arrows->setWrapT(GL_MIRRORED_REPEAT);
314                    _arrows->initialize(image->getImageBuffer());
315                }
316                delete image;
317            } else {
318                ERROR("Failed to load image: arrows.bmp");
319            }
320            delete loader;
321        } else {
322            ERROR("Couldn't find loader for arrows.bmp");
323        }
324    } else {
325        ERROR("Couldn't find path to arrows.bmp");
326    }
327
328#ifdef TEST
329    MakeSphereTexture();
330#endif
331
332    glGenBuffersARB(1, &_particleInfoBufferID);
333    glBindBufferARB(GL_ARRAY_BUFFER_ARB, _particleInfoBufferID);
334    glBufferDataARB(GL_ARRAY_BUFFER_ARB, _particleMaxCount * 4 * sizeof(float), 0, GL_DYNAMIC_DRAW);
335    glVertexAttribPointerARB(8, 4, GL_FLOAT, GL_FALSE, 0, 0);  // 8 = texcoord0
336    glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
337
338    // TBD..
339    initStreamlines(_width, _height);
340    initInitPosTex();
341
342    initShaders();
343    createRenderTargets();
344    createSortRenderTargets();
345    createStreamlineRenderTargets();
346
347    if (this->isTimeVaryingField()) {
348        pthread_t _threads;
349        pthread_attr_t pthread_custom_attr;
350        pthread_attr_init(&pthread_custom_attr);
351        pthread_create(&_threads, &pthread_custom_attr, dataLoadMain, (void *) this);
352    }
353}
354
355void ParticleSystem::initInitPosTex()
356{
357    glGenFramebuffersEXT(1, &_initPos_fbo);
358    glGenTextures(1, &_initPosTex);
359
360    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _initPos_fbo);
361
362    glViewport(0, 0, _width, _height);
363    glMatrixMode(GL_PROJECTION);
364    glLoadIdentity();
365    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
366    glMatrixMode(GL_MODELVIEW);
367    glLoadIdentity();
368
369    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _initPosTex);
370    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
371    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
372    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
373    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
374    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB32F_ARB,
375                 _width, _height, 0, GL_RGB, GL_FLOAT, NULL);
376    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
377
378    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
379                              GL_TEXTURE_RECTANGLE_ARB, _initPosTex, 0);
380
381    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
382}
383
384void ParticleSystem::initStreamlines(int width, int height)
385{
386    _atlas_x = 32;
387    _atlas_y = 32;
388
389    _atlasWidth = width * _atlas_x;
390    _atlasHeight = height * _atlas_y;
391    _maxAtlasCount = _atlas_x * _atlas_y;
392
393    _stepSizeStreamline = 1;
394    _curStepCount = 0;
395    _particleCount = width * height;
396
397    _currentStreamlineOffset = 0;
398    _currentStreamlineIndex = 0;
399    _streamVertices = new RenderVertexArray(_atlasWidth*_atlasHeight * 2, 3, GL_FLOAT);
400
401    _maxIndexBufferSize = _width * _height * _atlas_x * _atlas_y;
402    _indexBuffer = new unsigned int[_maxIndexBufferSize * 2];
403    unsigned int* pindex = _indexBuffer;
404    int ax, ay, old_ax = 0, old_ay = 0;
405    for (unsigned int i = 1; i < _maxAtlasCount; ++i) {
406        ax = (i % _atlas_x) * width;
407        ay = (i / _atlas_x) * height;
408
409        for (int y = 0; y < height ; ++y) {
410            for (int x = 0; x < width; ++x) {
411                *pindex = (old_ay + y) * _atlasWidth + old_ax + x; ++pindex;
412                *pindex = (ay + y) * _atlasWidth + ax + x; ++pindex;
413            }
414        }
415
416        old_ax = ax;
417        old_ay = ay;
418    }
419}
420
421void ParticleSystem::initShaders()
422{
423    // TBD...
424    _context = Shader::getCgContext();
425
426    std::string path = FilePath::getInstance()->getPath("distance.cg");
427    _distanceInitFP = 
428        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
429                                CG_PROFILE_FP40, "initSortIndex", NULL);
430    cgGLLoadProgram(_distanceInitFP);
431
432    _distanceSortFP =
433        cgCreateProgramFromFile(_context, CG_SOURCE,  path.c_str(),
434                                CG_PROFILE_FP40, "computeDistance", NULL);
435    _viewPosParam = cgGetNamedParameter(_distanceSortFP, "viewerPosition");
436    cgGLLoadProgram(_distanceSortFP);
437
438    _distanceSortLookupFP =
439        cgCreateProgramFromFile(_context, CG_SOURCE,  path.c_str(),
440                                CG_PROFILE_FP40, "lookupPosition", NULL);
441    cgGLLoadProgram(_distanceSortLookupFP);
442
443    path = FilePath::getInstance()->getPath("mergesort.cg");
444    _sortRecursionFP =
445        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
446                                CG_PROFILE_FP40, "mergeSortRecursion", NULL);
447    cgGLLoadProgram(_sortRecursionFP);
448
449    _srSizeParam = cgGetNamedParameter(_sortRecursionFP, "_Size");
450    _srStepParam = cgGetNamedParameter(_sortRecursionFP, "_Step");
451    _srCountParam = cgGetNamedParameter(_sortRecursionFP, "_Count");
452
453    _sortEndFP =
454        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
455                                CG_PROFILE_FP40, "mergeSortEnd", NULL);
456    cgGLLoadProgram(_sortEndFP);
457
458    _seSizeParam = cgGetNamedParameter(_sortEndFP, "size");
459    _seStepParam = cgGetNamedParameter(_sortEndFP, "step");
460
461    path = FilePath::getInstance()->getPath("passthrough.cg");
462    _passthroughFP =
463        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
464                                CG_PROFILE_FP40, "main", NULL);
465    cgGLLoadProgram(_passthroughFP);
466
467    _scaleParam = cgGetNamedParameter(_passthroughFP, "scale");
468    _biasParam = cgGetNamedParameter(_passthroughFP, "bias");
469
470    path = FilePath::getInstance()->getPath("moveparticles.cg");
471    _moveParticlesFP =
472        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
473                                CG_PROFILE_FP40, "main", NULL);
474    cgGLLoadProgram(_moveParticlesFP);
475    _mpTimeScale = cgGetNamedParameter(_moveParticlesFP, "timeStep");
476    _mpVectorField = cgGetNamedParameter(_moveParticlesFP, "vfield");
477    _mpUseInitTex= cgGetNamedParameter(_moveParticlesFP, "useInitPos");
478    _mpCurrentTime= cgGetNamedParameter(_moveParticlesFP, "currentTime");
479    _mpMaxScale = cgGetNamedParameter(_moveParticlesFP, "maxScale");
480    _mpScale= cgGetNamedParameter(_moveParticlesFP, "scale");
481
482    path = FilePath::getInstance()->getPath("particlevp.cg");
483    _particleVP =
484        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
485                                CG_PROFILE_VP40, "vpmain", NULL);
486    cgGLLoadProgram(_particleVP);
487    _mvpParticleParam = cgGetNamedParameter(_particleVP, "mvp");
488    _mvParticleParam = cgGetNamedParameter(_particleVP, "modelview");
489    _mvTanHalfFOVParam = cgGetNamedParameter(_particleVP, "tanHalfFOV");
490    _mvCurrentTimeParam =  cgGetNamedParameter(_particleVP, "currentTime");
491
492    path = FilePath::getInstance()->getPath("particlefp.cg");
493    _particleFP =
494        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
495                                CG_PROFILE_FP40, "fpmain", NULL);
496    cgGLLoadProgram(_particleFP);
497    _vectorParticleParam = cgGetNamedParameter(_particleVP, "vfield");
498
499    path = FilePath::getInstance()->getPath("moveparticles.cg");
500    _initParticlePosFP =
501        cgCreateProgramFromFile(_context, CG_SOURCE, path.c_str(),
502                                CG_PROFILE_FP40, "initParticlePosMain", NULL);
503    cgGLLoadProgram(_initParticlePosFP);
504    _ipVectorFieldParam = cgGetNamedParameter(_moveParticlesFP, "vfield");
505}
506
507void ParticleSystem::passThoughPositions()
508{
509    cgGLBindProgram(_passthroughFP);
510    cgGLEnableProfile(CG_PROFILE_FP40);
511
512    cgGLSetParameter4f(_scaleParam, 1.0, 1.0, 1.0, 1.0);
513    cgGLSetParameter4f(_biasParam, 0.0, 0.0, 0.0, 0.0);
514
515    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB32F_ARB,
516                 _width, _height, 0, GL_RGB, GL_FLOAT, (GLfloat *) _positionBuffer);
517
518    drawQuad();
519
520    cgGLDisableProfile(CG_PROFILE_FP40);
521}
522
523void ParticleSystem::resetStreamlines()
524{
525    _currentStreamlineIndex = 0;
526    _currentStreamlineOffset = 0;
527    _curStepCount = 0;
528}
529
530void ParticleSystem::reset()
531{
532    _currentTime = 0.0f;
533    _sortBegin = 0;
534    _sortEnd = _sortPassesPerFrame;
535
536    glPushAttrib(GL_VIEWPORT_BIT);
537    glMatrixMode(GL_PROJECTION);
538    glPushMatrix();
539    glMatrixMode(GL_MODELVIEW);
540
541    resetStreamlines();
542
543    unsigned int maxsize = _userDefinedParticleMaxCount;
544
545    while (!_availableIndices.empty())
546        _availableIndices.pop();
547    while (!_activeParticles.empty())
548        _activeParticles.pop();
549
550    _activeParticles.reserve(maxsize);
551    _availableIndices.reserve(maxsize);
552
553    for (unsigned int i = 0; i < maxsize; i++)
554        _availableIndices.push(i);
555
556    for (int i = 0; i < _particleMaxCount; i++) {
557        _particles[i].timeOfBirth = -1.0f;
558        _particles[i].lifeTime = 0.0f;
559        _particles[i].attributeType = 0.0f;
560        _particles[i].index = (float)i;
561    }
562
563    glBindBufferARB(GL_ARRAY_BUFFER_ARB, _particleInfoBufferID);
564    Particle* pinfo = (Particle*) glMapBufferARB(GL_ARRAY_BUFFER, GL_WRITE_ONLY_ARB);
565
566    for (int i = 0; i < _particleMaxCount; i++) {
567        pinfo[i] = _particles[i];
568    }
569
570    glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
571
572    // POSITION
573    memset(_positionBuffer, 0, sizeof(vrmath::Vector3f) * _width * _height);
574    for (int y = 0; y < _height; y++) {
575        for (int x = 0; x < _width; x++) {
576            _positionBuffer[_width * y + x].x = (float)rand() / (float) RAND_MAX;
577            //_positionBuffer[_width * y + x].x = 0.9;
578            _positionBuffer[_width * y + x].y = (float)rand() / (float) RAND_MAX;
579            _positionBuffer[_width * y + x].z = (float)rand() / (float) RAND_MAX;
580        }
581    }
582
583    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _initPosTex);
584    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB32F_ARB,
585                 _width, _height, 0, GL_RGB, GL_FLOAT, (float*)_positionBuffer);
586    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
587
588    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_currentPosIndex]);
589    glViewport(0, 0, _width, _height);
590    glMatrixMode(GL_PROJECTION);
591    glLoadIdentity();
592    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
593    glMatrixMode(GL_MODELVIEW);
594    glLoadIdentity();
595    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
596    passThoughPositions();
597    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
598
599    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, velocity_fbo[_currentPosIndex]);
600    glViewport(0, 0, _width, _height);
601    glMatrixMode(GL_PROJECTION);
602    glLoadIdentity();
603    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
604    glMatrixMode(GL_MODELVIEW);
605    glLoadIdentity();
606    glClearColor(0, 0, 0, 0);
607    glClear(GL_COLOR_BUFFER_BIT);
608    // TBD..
609    // velocity
610    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
611
612
613    /// TBD...
614    //DeathTimePBuffer->BeginCapture();
615    //glClear(GL_COLOR_BUFFER_BIT);
616    //DeathTimePBuffer->EndCapture();
617
618    if (_sortEnabled) {
619        glDisable(GL_BLEND);
620        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_currentSortIndex]);
621        glViewport(0, 0, _width, _height);
622        glMatrixMode(GL_PROJECTION);
623        glLoadIdentity();
624        glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
625        glMatrixMode(GL_MODELVIEW);
626        glLoadIdentity();
627
628        cgGLBindProgram(_distanceInitFP);
629        cgGLEnableProfile(CG_PROFILE_FP40);
630
631        drawQuad();
632
633        cgGLDisableProfile(CG_PROFILE_FP40);
634        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);           
635
636        _currentSortPass = 0;
637        this->_maxSortPasses = 100000;
638    }
639
640    glMatrixMode(GL_PROJECTION);
641    glPopMatrix();
642    glMatrixMode(GL_MODELVIEW);
643    glPopAttrib();
644}
645
646void ParticleSystem::createRenderTargets()
647{
648    glGenFramebuffersEXT(2, psys_fbo);
649    glGenTextures(2, psys_tex);
650
651    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[0]);
652
653    glViewport(0, 0, _width, _height);
654    glMatrixMode(GL_PROJECTION);
655    glLoadIdentity();
656    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
657    glMatrixMode(GL_MODELVIEW);
658    glLoadIdentity();
659
660    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[0]);
661    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
662    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
663    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
664    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
665
666    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB,
667                 _width, _height, 0, GL_RGBA, GL_FLOAT, NULL);
668
669    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
670                              GL_TEXTURE_RECTANGLE_ARB, psys_tex[0], 0);
671
672    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[1]);
673
674    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[1]);
675    glViewport(0, 0, _width, _height);
676    glMatrixMode(GL_PROJECTION);
677    glLoadIdentity();
678    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
679    glMatrixMode(GL_MODELVIEW);
680    glLoadIdentity();
681
682    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
683    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
684    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
685    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
686
687    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB,
688                 _width, _height, 0, GL_RGBA, GL_FLOAT, NULL);
689
690    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
691                              GL_TEXTURE_RECTANGLE_ARB, psys_tex[1], 0);
692 
693    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
694}
695
696//#define ATLAS_TEXTURE_TARGET GL_TEXTURE_RECTANGLE_ARB
697//#define ATLAS_INTERNAL_TYPE GL_RGBA32F_ARB
698#define ATLAS_TEXTURE_TARGET GL_TEXTURE_2D
699#define ATLAS_INTERNAL_TYPE GL_RGBA
700
701void ParticleSystem::createStreamlineRenderTargets()
702{
703    glGenFramebuffersEXT(1, &_atlas_fbo);
704    glGenTextures(1, &_atlas_tex);
705    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _atlas_fbo);
706    glViewport(0, 0, _atlasWidth, _atlasHeight);
707    glMatrixMode(GL_PROJECTION);
708    glLoadIdentity();
709    glOrtho(0, _atlasWidth, 0, _atlasHeight, -10.0f, 10.0f);
710    glMatrixMode(GL_MODELVIEW);
711    glLoadIdentity();
712
713    glBindTexture(ATLAS_TEXTURE_TARGET, _atlas_tex);
714    glTexParameterf(ATLAS_TEXTURE_TARGET, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
715    glTexParameterf(ATLAS_TEXTURE_TARGET, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
716    //glTexParameteri(ATLAS_TEXTURE_TARGET, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
717    //glTexParameteri(ATLAS_TEXTURE_TARGET, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
718
719    glTexImage2D(ATLAS_TEXTURE_TARGET, 0, ATLAS_INTERNAL_TYPE,
720                 _atlasWidth, _atlasHeight, 0, GL_RGBA, GL_FLOAT, NULL);
721
722    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
723                              ATLAS_TEXTURE_TARGET, _atlas_tex, 0);
724 
725    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
726}
727
728//#define SORT_TEXTURE_FORMAT  GL_LUMINANCE_ALPHA
729//#define SORT_TEXTURE_INNER_FORMAT GL_LUMINANCE_ALPHA_FLOAT32_ATI
730#define SORT_TEXTURE_FORMAT  GL_RGB
731#define SORT_TEXTURE_INNER_FORMAT GL_RGB32F_ARB
732
733void ParticleSystem::createSortRenderTargets()
734{
735    glGenFramebuffersEXT(2, sort_fbo);
736    glGenTextures(2, sort_tex);
737
738    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[0]);
739    glViewport(0, 0, _width, _height);
740    glMatrixMode(GL_PROJECTION);
741    glLoadIdentity();
742    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
743    glMatrixMode(GL_MODELVIEW);
744    glLoadIdentity();
745
746    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sort_tex[0]);
747    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
748    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
749    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
750    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
751    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, SORT_TEXTURE_INNER_FORMAT,
752                 _width, _height, 0, SORT_TEXTURE_FORMAT, GL_FLOAT, NULL);
753
754    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
755                              GL_TEXTURE_RECTANGLE_ARB, sort_tex[0], 0);
756
757    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[1]);
758    glViewport(0, 0, _width, _height);
759    glMatrixMode(GL_PROJECTION);
760    glLoadIdentity();
761    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
762    glMatrixMode(GL_MODELVIEW);
763    glLoadIdentity();
764
765    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sort_tex[1]);
766    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
767    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
768    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
769    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
770    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, SORT_TEXTURE_INNER_FORMAT,
771                 _width, _height, 0, SORT_TEXTURE_FORMAT, GL_FLOAT, NULL);
772
773    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
774                              GL_TEXTURE_RECTANGLE_ARB, sort_tex[1], 0);
775
776    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
777}
778
779ParticleSystem::~ParticleSystem()
780{
781    std::vector<ParticleEmitter*>::iterator iter;
782    for (iter = _emitters.begin(); iter != _emitters.end(); ++iter)
783        delete (*iter);
784
785    // Particle Position
786    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[0]);
787    glDeleteTextures(1, psys_tex);
788    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[1]);
789    glDeleteTextures(1, psys_tex+1);
790    glDeleteFramebuffersEXT(2, psys_fbo);
791
792    // Sort
793    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[0]);
794    glDeleteTextures(1, sort_tex);
795    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[1]);
796    glDeleteTextures(1, sort_tex+1);
797    glDeleteFramebuffersEXT(2, sort_fbo);
798
799    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, velocity_fbo[0]);
800    glDeleteTextures(1, velocity_tex);
801    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, velocity_fbo[1]);
802    glDeleteTextures(1, velocity_tex+1);
803    glDeleteFramebuffersEXT(2, velocity_fbo);
804
805    if (_vertices) delete _vertices;
806
807    delete [] _particles;
808    delete [] _positionBuffer;
809    delete [] _colorBuffer;
810
811    if (_arrows) delete _arrows;
812
813    // STREAM LINE
814    if (_streamVertices) delete _streamVertices;
815    if (_indexBuffer) delete _indexBuffer;
816
817    cgDestroyProgram(_distanceInitFP);
818
819    cgDestroyParameter(_viewPosParam);
820    cgDestroyProgram(_distanceSortFP);
821
822    cgDestroyProgram(_distanceSortLookupFP);
823
824    cgDestroyParameter(_scaleParam);
825    cgDestroyParameter(_biasParam);
826    cgDestroyProgram(_passthroughFP);
827
828    cgDestroyParameter(_srSizeParam);
829    cgDestroyParameter(_srStepParam);
830    cgDestroyParameter(_srCountParam);
831
832    cgDestroyProgram(_sortRecursionFP);
833
834    cgDestroyParameter(_seSizeParam);
835    cgDestroyParameter(_seStepParam);
836    cgDestroyProgram(_sortEndFP);
837
838    cgDestroyParameter(_mpTimeScale);
839    cgDestroyParameter(_mpVectorField);
840    cgDestroyParameter(_mpUseInitTex);
841    cgDestroyParameter(_mpCurrentTime);
842    cgDestroyProgram(_moveParticlesFP);
843
844    cgDestroyParameter(_ipVectorFieldParam);
845    cgDestroyProgram(_initParticlePosFP);
846
847    cgDestroyParameter(_mvpParticleParam);
848    cgDestroyParameter(_mvParticleParam);
849    cgDestroyParameter(_mvTanHalfFOVParam);
850    cgDestroyParameter(_mvCurrentTimeParam);
851    cgDestroyProgram(_particleFP);
852
853    cgDestroyParameter(_vectorParticleParam);
854    cgDestroyProgram(_particleVP);
855}
856
857bool ParticleSystem::isEnabled(EnableEnum enabled)
858{
859    switch (enabled) {
860    case PS_SORT :
861        return _sortEnabled;
862        break;
863    case PS_GLYPH :
864        return _glyphEnabled;
865        break;
866    case PS_DRAW_BBOX :
867        return _drawBBoxEnabled;
868        break;
869    case PS_ADVECTION :
870        return _advectionEnabled;
871    case PS_STREAMLINE :
872        return _streamlineEnabled;
873    }
874    return false;
875}
876
877void ParticleSystem::enable(EnableEnum enabled)
878{
879    switch (enabled) {
880    case PS_SORT :
881        _sortEnabled = true;
882        break;
883    case PS_GLYPH :
884        _glyphEnabled = true;
885        break;
886    case PS_DRAW_BBOX :
887        _drawBBoxEnabled = true;
888        break;
889    case PS_ADVECTION :
890        _advectionEnabled = true;
891        break;
892    case PS_STREAMLINE :
893        _streamlineEnabled = true;
894        break;
895    }
896}
897
898void ParticleSystem::disable(EnableEnum enabled)
899{
900    switch (enabled) {
901    case PS_SORT :
902        _sortEnabled = false;
903        break;
904    case PS_GLYPH :
905        _glyphEnabled = false;
906        break;
907    case PS_DRAW_BBOX :
908        _drawBBoxEnabled = false;
909        break;
910    case PS_ADVECTION :
911        _advectionEnabled = false;
912        break;
913    case PS_STREAMLINE :
914        _streamlineEnabled = false;
915        break;
916    }
917}
918
919void ParticleSystem::advectStreamlines()
920{
921    glDisable(GL_BLEND);
922    glDisable(GL_DEPTH_TEST);
923
924    //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
925    //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
926
927    glPushAttrib(GL_VIEWPORT_BIT);
928    glViewport(0, 0, _width, _height);
929    glMatrixMode(GL_PROJECTION);
930    glPushMatrix();
931    glLoadIdentity();
932    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
933    glMatrixMode(GL_MODELVIEW);
934    glPushMatrix();
935    glLoadIdentity();
936
937    glEnable(GL_TEXTURE_RECTANGLE_ARB);
938
939    cgGLBindProgram(_moveParticlesFP);
940    cgGLEnableProfile(CG_PROFILE_FP40);
941    cgGLSetParameter1f(_mpTimeScale, 0.005);
942    cgGLSetParameter1f(_mpUseInitTex, 1.0);
943    cgGLSetParameter1f(_mpCurrentTime, _currentTime);
944    cgGLSetParameter3f(_mpScale, _scalex, _scaley, _scalez);
945    cgGLSetParameter1f(_mpMaxScale, _maxVelocityScale);
946    cgGLSetTextureParameter(_mpVectorField, _curVectorFieldID);
947    cgGLEnableTextureParameter(_mpVectorField);
948
949    for (int i = 0; i < _stepSizeStreamline; ++i) {
950        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
951        glClear(GL_COLOR_BUFFER_BIT);
952        glActiveTextureARB(GL_TEXTURE0_ARB);
953        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_currentPosIndex]);
954        glActiveTextureARB(GL_TEXTURE1_ARB);
955        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _initPosTex);
956        drawQuad();
957        swap(_currentPosIndex, _destPosIndex);
958    }
959
960    cgGLDisableTextureParameter(_mpVectorField);
961    glDisable(GL_TEXTURE_RECTANGLE_ARB);
962    cgGLDisableProfile(CG_PROFILE_FP40);
963
964    glMatrixMode(GL_PROJECTION);
965    glPopMatrix();
966    glMatrixMode(GL_MODELVIEW);
967    glPopMatrix();
968    glPopAttrib();
969    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
970
971    if (_currentStreamlineIndex < _maxAtlasCount) {
972        int xoffset = (_currentStreamlineIndex % _atlas_x) * _width;
973        int yoffset = (_currentStreamlineIndex / _atlas_x) * _height;
974
975        glActiveTextureARB(GL_TEXTURE0_ARB);
976        glEnable(ATLAS_TEXTURE_TARGET);
977        glBindTexture(ATLAS_TEXTURE_TARGET, _atlas_tex);
978
979        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
980        //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_currentPosIndex]);
981        glCopyTexSubImage2D(ATLAS_TEXTURE_TARGET, 0, xoffset, yoffset,
982                            0, 0, _width, _height);
983        glActiveTextureARB(GL_TEXTURE0_ARB);
984        glBindTexture(ATLAS_TEXTURE_TARGET, 0);
985        glDisable(ATLAS_TEXTURE_TARGET);
986
987        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _atlas_fbo);
988        _streamVertices->read(_atlasWidth, _atlasHeight);
989        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
990        _currentStreamlineIndex++;
991
992        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
993    }
994}
995
996bool ParticleSystem::advect(float deltaT, float camx, float camy, float camz)
997{
998    static bool firstLoad = true;
999    if (this->isTimeVaryingField()) {
1000        static float oldTime = (float)clock()/(float)CLOCKS_PER_SEC;
1001#ifdef WANT_TRACE
1002        static int index = 0;
1003#endif
1004        float time = (float)clock()/(float)CLOCKS_PER_SEC;
1005        if ((time - oldTime) > 2.0) {
1006            if (!_queue.isEmpty()) {
1007                float *data = NULL;
1008                if (_queue.top(data)) {
1009#ifdef WANT_TRACE
1010                    float t = clock() /(float) CLOCKS_PER_SEC;
1011#endif
1012                    _vectorFields[0]->update(data);
1013#ifdef WANT_TRACE
1014                    float ti = clock() / (float) CLOCKS_PER_SEC;
1015                    TRACE("updatePixels time: %f", ti - t);
1016#endif
1017                    _queue.pop();
1018                    oldTime = time;
1019
1020                    firstLoad = false;
1021                    TRACE("%d bound", index++);
1022                }
1023            }           
1024        }
1025        if (firstLoad) return false;
1026    }
1027
1028    if (!_advectionEnabled) return true;
1029    if (this->_streamlineEnabled) {
1030        advectStreamlines();
1031        _currentTime += deltaT;
1032    } else {
1033        _camx = camx;
1034        _camy = camy;
1035        _camz = camz;
1036
1037        glDisable(GL_BLEND);
1038        glDisable(GL_DEPTH_TEST);
1039
1040        glPushAttrib(GL_VIEWPORT_BIT);
1041        glViewport(0, 0, _width, _height);
1042        glMatrixMode(GL_PROJECTION);
1043        glPushMatrix();
1044        glLoadIdentity();
1045        glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1046        glMatrixMode(GL_MODELVIEW);
1047        glPushMatrix();
1048        glLoadIdentity();
1049
1050        glEnable(GL_TEXTURE_RECTANGLE_ARB);
1051
1052        cgGLBindProgram(_moveParticlesFP);
1053        cgGLEnableProfile(CG_PROFILE_FP40);
1054
1055        // INSOO
1056        // TIME SCALE
1057
1058        cgGLSetParameter1f(_mpTimeScale, 0.005);
1059
1060        //////////////////////////////////////////////////////
1061        // UPDATE POS
1062        cgGLSetTextureParameter(_mpVectorField, _curVectorFieldID);
1063        cgGLEnableTextureParameter(_mpVectorField);
1064        cgGLSetParameter3f(_mpScale, _scalex, _scaley, _scalez);
1065        cgGLSetParameter1f(_mpMaxScale, _maxVelocityScale);
1066        for (int i = 0; i < _stepSizeStreamline; ++i) {
1067            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
1068            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1069            glActiveTextureARB(GL_TEXTURE0_ARB);
1070            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_currentPosIndex]);
1071            glActiveTextureARB(GL_TEXTURE1_ARB);
1072            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _initPosTex);
1073            drawQuad();
1074            swap(_currentPosIndex, _destPosIndex);
1075        }
1076        cgGLDisableTextureParameter(_mpVectorField);
1077
1078        glActiveTextureARB(GL_TEXTURE1_ARB);
1079        glDisable(GL_TEXTURE_RECTANGLE_ARB);
1080        glActiveTextureARB(GL_TEXTURE0_ARB);
1081        glDisable(GL_TEXTURE_RECTANGLE_ARB);
1082
1083        glDisable(GL_TEXTURE_RECTANGLE_ARB);
1084        cgGLDisableProfile(CG_PROFILE_FP40);
1085
1086        glMatrixMode(GL_PROJECTION);
1087        glPopMatrix();
1088        glMatrixMode(GL_MODELVIEW);
1089        glPopMatrix();
1090        glPopAttrib();
1091        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1092
1093        if (_sortEnabled) {
1094            sort();
1095
1096            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
1097            _vertices->read(_width, _height);
1098            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1099        } else {
1100            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_currentPosIndex]);
1101            _vertices->read(_width, _height);
1102            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1103        }
1104
1105        // NEW PARTICLES
1106        for (unsigned int i = 0; i < _emitters.size(); ++i) {
1107            // TBD..
1108            unsigned int numOfNewParticles = (unsigned int)(randomRange(_emitters[i]->_minNumOfNewParticles, _emitters[i]->_maxNumOfNewParticles) * deltaT);
1109            for (unsigned int k = 0; k < numOfNewParticles; ++k) {
1110                vrmath::Vector3f position = _emitters[i]->_position;
1111                position +=
1112                    _emitters[i]->_maxPositionOffset.scale(vrmath::Vector3f(randomRange(-1.0f, 1.0f),
1113                                                                            randomRange(-1.0f, 1.0f),
1114                                                                            randomRange(-1.0f, 1.0f)));
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            glTexEnvi(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            glTexEnvi(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.