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

Last change on this file since 4923 was 4904, checked in by ldelgass, 5 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.