source: nanovis/trunk/ParticleSystem.cpp @ 4827

Last change on this file since 4827 was 4167, checked in by ldelgass, 10 years ago

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

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