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

Last change on this file since 3612 was 3612, checked in by ldelgass, 11 years ago

Remove Nv prefix from shader classes now that they are in nv namespace.

File size: 59.7 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (c) 2004-2013  HUBzero Foundation, LLC
4 *
5 */
6#include "nvconf.h"
7
8#include <time.h>
9#include <stdlib.h>
10#include <stdio.h>
11#include <math.h>
12#include <pthread.h>
13
14#include <GL/glew.h>
15#include <Cg/cgGL.h>
16
17#include <util/FilePath.h>
18
19#include <Image.h>
20#include <ImageLoader.h>
21#include <ImageLoaderFactory.h>
22
23#include <vrmath/Matrix4x4d.h>
24#include <vrmath/Vector3f.h>
25#include <vrmath/Vector4f.h>
26
27#include "ParticleSystem.h"
28#include "ParticleEmitter.h"
29#include "DataLoader.h"
30#include "Texture2D.h"
31#include "Texture3D.h"
32#include "Shader.h"
33#include "Trace.h"
34
35using namespace nv::util;
36
37#define USE_RGBA_ARROW
38
39//#define TEST
40
41inline float randomRange(float rangeMin, float rangeMax)
42{
43    return ((float)rand() / RAND_MAX) * (rangeMax - rangeMin) + rangeMin ;
44}
45
46inline int logd(int value)
47{
48    int l;
49    for (l = 0; value >> l; l++);
50    return l - 1;
51}
52
53inline void swap(int& x, int& y)
54{
55    if (x != y) {
56        x ^= y;
57        y ^= x;
58        x ^= y;
59    }
60}
61
62void *ParticleSystem::dataLoadMain(void *data)
63{
64    ParticleSystem *particleSystem = (ParticleSystem *)data;
65    CircularFifo<float*, 10>& queue = particleSystem->_queue;
66
67    // TBD..
68    //float min = particleSystem->_time_series_vel_mag_min;
69    //float max = particleSystem->_time_series_vel_mag_max;
70
71    int startIndex = particleSystem->_flowFileStartIndex;
72    int endIndex = particleSystem->_flowFileEndIndex;
73
74    int curIndex = startIndex;
75    int flowWidth = particleSystem->_flowWidth;
76    int flowHeight = particleSystem->_flowHeight;
77    int flowDepth = particleSystem->_flowDepth;
78
79    const char* fileNameFormat = particleSystem->_fileNameFormat.c_str();
80    char buff[256];
81
82    bool done = false;
83    while (!done) {
84        if (curIndex > endIndex) {
85            curIndex = startIndex;
86        }
87
88        if (!queue.isFull()) {
89            int tail = queue.tailIndex();
90            if (tail != -1) {
91                sprintf(buff, fileNameFormat, curIndex);
92                //std::string path = FilePath::getInstance()->getPath(buff);
93#ifdef WANT_TRACE
94                float t = clock() /(float) CLOCKS_PER_SEC;
95#endif
96                LoadProcessedFlowRaw(buff, flowWidth, flowHeight, flowDepth, queue.array[tail]);
97#ifdef WANT_TRACE
98                float ti = clock() / (float) CLOCKS_PER_SEC;
99                TRACE("LoadProcessedFlowRaw time: %f", ti - t);
100#endif
101                queue.push();
102                TRACE("%d loaded", curIndex);
103                ++curIndex;
104            }
105        }
106    }
107
108    return 0;
109}
110
111CGcontext ParticleSystem::_context = 0;
112
113unsigned int SpotTexID = 0;
114
115void MakeSphereTexture()
116{
117    const int DIM = 128;
118    const int DIM2 = 63;
119    //const float TEX_SCALE = 6.0;
120
121    glGenTextures(1, (GLuint *)&SpotTexID);
122    glBindTexture(GL_TEXTURE_2D, SpotTexID);
123
124    float col[4] = {1.f, 1.f, 1.f, 1.f};
125    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, col);
126    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
127
128    float *img = new float[DIM*DIM];
129
130    vrmath::Vector3f light(1,1,3);
131    light = light.normalize();
132
133    for (int y = 0; y < DIM; y++) {
134        for (int x = 0; x < DIM; x++) {
135            // Clamping the edges to zero allows Nvidia's blend optimizations to do their thing.
136            if (x == 0 || x == DIM-1 || y == 0 || y == DIM-1) {
137                img[y*DIM+x] = 0;
138            } else {
139                vrmath::Vector3f p(x, y, 0);
140                p = p - vrmath::Vector3f(DIM2, DIM2, 0);
141                float len = p.length();
142                float z = sqrt(DIM2*DIM2 - len*len);
143                p.z = z;
144                if (len >= DIM2) {
145                    img[y*DIM+x] = 0.0;
146                    continue;
147                }
148
149                p = p.normalize();
150                float v = p.dot(light);
151                if(v < 0) v = 0;
152
153                img[y*DIM+x] = v;
154            }
155        }
156    }
157
158    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
159    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
160    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
161    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
162
163    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA16, DIM, DIM, GL_ALPHA, GL_FLOAT, img);
164}
165
166//extern void algorithm_test(vrmath::Vector4f* data, int flowWidth, int flowHeight, int flowDepth);
167//extern std::vector<vrmath::Vector3f>* find_critical_points(vrmath::Vector4f* data, int flowWidth, int flowHeight, int flowDepth);
168ParticleSystem::ParticleSystem(int width, int height,
169                               const std::string& fileName,
170                               int fieldWidth, int fieldHeight, int fieldDepth,
171                               bool timeVaryingData,
172                               int flowFileStartIndex, int flowFileEndIndex) :
173    _width(width),
174    _height(height)
175{
176    ////////////////////////////////
177    // TIME-VARYING SERIES
178    _isTimeVaryingField = timeVaryingData;
179    _flowFileStartIndex = flowFileStartIndex;
180    _flowFileEndIndex = flowFileEndIndex;
181    _userDefinedParticleMaxCount = width * height;
182
183    _skipByte = 0;
184
185    _screenWidth = _screenHeight = 1;
186    _fov = 60.0f;
187
188    _particleMaxCount = _width * _height;
189
190    _pointSize = 10.0f;
191    _camx = 0.0f;
192    _camy = 0.0f;
193    _camz = 0.0f;
194
195    _scalex = _scaley = _scalez = 1.0f;
196    _currentSortIndex = 0;
197    _destSortIndex = 1;
198
199    _currentPosIndex = 0;
200    _destPosIndex = 1;
201
202    _currentSortPass = 0;
203    // TBD
204    //_sortPassesPerFrame = 5;
205    _sortPassesPerFrame = 4;
206    _maxSortPasses = 0;
207
208    _sortBegin = 0;
209    _sortEnd = _sortPassesPerFrame;
210    _currentTime = 0;
211    _sortEnabled = false;
212    _glyphEnabled = false;
213    _advectionEnabled = false;
214    _streamlineEnabled = false;
215    _particles = new Particle[_particleMaxCount];
216    memset(_particles, 0, sizeof(Particle) * _particleMaxCount);
217
218    _colorBuffer = new color4[_particleMaxCount];
219    memset(_colorBuffer, 0, sizeof(color4) * _particleMaxCount);
220
221    _positionBuffer = new vrmath::Vector3f[_particleMaxCount];
222    _vertices = new RenderVertexArray(_particleMaxCount, 3, GL_FLOAT);
223
224    srand(time(0));
225
226    /*
227    // TBD..
228    glGenBuffersARB(1, &_colorBufferID);
229    glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
230    glBufferDataARB(GL_ARRAY_BUFFER, _width * _height * 4, _colorBuffer, GL_STREAM_DRAW_ARB); // undefined data
231    glBindBufferARB(GL_ARRAY_BUFFER, 0);
232    */
233
234    _flowWidth = fieldWidth;
235    _flowHeight = fieldHeight;
236    _flowDepth = fieldDepth;
237
238    float min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ;
239    int index = fileName.rfind('.');
240    std::string ext = fileName.substr(index + 1, fileName.size() - (index + 1));
241    float *data = 0;
242
243    if (this->isTimeVaryingField()) {
244        axisScaleX = _flowWidth;
245        axisScaleY = _flowHeight;
246        axisScaleZ = _flowDepth;
247        _fileNameFormat = fileName;
248        for (int i = 0; i < CircularFifo<float*, 10>::Capacity; ++i) {
249            _queue.array[i] = new float[_flowWidth * _flowHeight * _flowDepth * 4];
250        }
251
252        // INSOO
253        // TBD
254        min = 0;
255        max = 234.99;
256    } else {
257        if (ext == "dx") {
258            data = (float*) LoadFlowDx(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ);
259        } else if (ext == "raw") {
260            data = (float*) LoadFlowRaw(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ, 0, false);
261            //data = (float*) LoadProcessedFlowRaw(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, axisScaleX, axisScaleY, axisScaleZ);
262#ifdef notdef
263        } else if (ext == "raws") {
264            data = (float*) LoadFlowRaw(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ, 5 * sizeof(int), true);
265        } else if (ext == "data") {
266            data = (float*) LoadFlowRaw(fileName.c_str(), _flowWidth, _flowHeight, _flowDepth, min, max, nonzero_min, axisScaleX, axisScaleY, axisScaleZ, 0, true);
267#endif
268        }
269        //_criticalPoints = find_critical_points((vrmath::Vector4f*) data, _flowWidth,  _flowHeight,  _flowDepth);
270        //algorithm_test((vrmath::Vector4f*) data,  _flowWidth,  _flowHeight,  _flowDepth);
271    }
272
273    _scalex = 1;
274    _scaley = axisScaleY / axisScaleX;
275    _scalez = axisScaleZ / axisScaleX;
276    _maxVelocityScale = max;
277
278    if (!this->isTimeVaryingField()) {
279        Texture3D *flow = new Texture3D(_flowWidth, _flowHeight, _flowDepth,
280                                        GL_FLOAT, GL_LINEAR, 4, data);
281        _curVectorFieldID = flow->id();
282        _vectorFieldIDs.push_back(_curVectorFieldID);
283    } else {
284        for (int i = 0; i < 3; ++i) {
285            Texture3D *flow = new Texture3D(_flowWidth, _flowHeight, _flowDepth,
286                                            GL_FLOAT, GL_LINEAR, 4, data);
287            _vectorFields.push_back(flow);
288            _vectorFieldIDs.push_back(flow->id());
289        }
290        _curVectorFieldID = _vectorFieldIDs[0];
291    }
292
293    std::string path = FilePath::getInstance()->getPath("arrows.bmp");
294
295    if (!path.empty()) {
296        ImageLoader *loader = ImageLoaderFactory::getInstance()->createLoader("bmp");
297        if (loader != NULL) {
298#ifdef USE_RGBA_ARROW
299            Image *image = loader->load(path.c_str(), Image::IMG_RGBA);
300#else
301            Image *image = loader->load(path.c_str(), Image::IMG_RGB);
302#endif
303            if (image != NULL) {
304                unsigned char *bytes = (unsigned char *)image->getImageBuffer();
305                if (bytes != NULL) {
306#ifdef USE_RGBA_ARROW
307                    _arrows = new Texture2D(image->getWidth(), image->getHeight(),
308                                            GL_UNSIGNED_BYTE, GL_LINEAR, 4, NULL);
309#else
310                    _arrows = new Texture2D(image->getWidth(), image->getHeight(),
311                                            GL_UNSIGNED_BYTE, GL_LINEAR, 3, NULL);
312#endif
313                    _arrows->setWrapS(GL_MIRRORED_REPEAT);
314                    _arrows->setWrapT(GL_MIRRORED_REPEAT);
315                    _arrows->initialize(image->getImageBuffer());
316                }
317                delete image;
318            } else {
319                ERROR("Failed to load image: arrows.bmp");
320            }
321            delete loader;
322        } else {
323            ERROR("Couldn't find loader for arrows.bmp");
324        }
325    } else {
326        ERROR("Couldn't find path to arrows.bmp");
327    }
328
329#ifdef TEST
330    MakeSphereTexture();
331#endif
332
333    glGenBuffersARB(1, &_particleInfoBufferID);
334    glBindBufferARB(GL_ARRAY_BUFFER_ARB, _particleInfoBufferID);
335    glBufferDataARB(GL_ARRAY_BUFFER_ARB, _particleMaxCount * 4 * sizeof(float), 0, GL_DYNAMIC_DRAW);
336    glVertexAttribPointerARB(8, 4, GL_FLOAT, GL_FALSE, 0, 0);  // 8 = texcoord0
337    glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
338
339    // TBD..
340    initStreamlines(_width, _height);
341    initInitPosTex();
342
343    initShaders();
344    createRenderTargets();
345    createSortRenderTargets();
346    createStreamlineRenderTargets();
347
348    if (this->isTimeVaryingField()) {
349        pthread_t _threads;
350        pthread_attr_t pthread_custom_attr;
351        pthread_attr_init(&pthread_custom_attr);
352        pthread_create(&_threads, &pthread_custom_attr, dataLoadMain, (void *) this);
353    }
354}
355
356void ParticleSystem::initInitPosTex()
357{
358    glGenFramebuffersEXT(1, &_initPos_fbo);
359    glGenTextures(1, &_initPosTex);
360
361    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _initPos_fbo);
362
363    glViewport(0, 0, _width, _height);
364    glMatrixMode(GL_PROJECTION);
365    glLoadIdentity();
366    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
367    glMatrixMode(GL_MODELVIEW);
368    glLoadIdentity();
369
370    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _initPosTex);
371    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
372    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
373    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
374    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
375    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB32F_ARB,
376                 _width, _height, 0, GL_RGB, GL_FLOAT, NULL);
377    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
378
379    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
380                              GL_TEXTURE_RECTANGLE_ARB, _initPosTex, 0);
381
382    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
383}
384
385void ParticleSystem::initStreamlines(int width, int height)
386{
387    _atlas_x = 32;
388    _atlas_y = 32;
389
390    _atlasWidth = width * _atlas_x;
391    _atlasHeight = height * _atlas_y;
392    _maxAtlasCount = _atlas_x * _atlas_y;
393
394    _stepSizeStreamline = 1;
395    _curStepCount = 0;
396    _particleCount = width * height;
397
398    _currentStreamlineOffset = 0;
399    _currentStreamlineIndex = 0;
400    _streamVertices = new RenderVertexArray(_atlasWidth*_atlasHeight * 2, 3, GL_FLOAT);
401
402    _maxIndexBufferSize = _width * _height * _atlas_x * _atlas_y;
403    _indexBuffer = new unsigned int[_maxIndexBufferSize * 2];
404    unsigned int* pindex = _indexBuffer;
405    int ax, ay, old_ax = 0, old_ay = 0;
406    for (unsigned int i = 1; i < _maxAtlasCount; ++i) {
407        ax = (i % _atlas_x) * width;
408        ay = (i / _atlas_x) * height;
409
410        for (int y = 0; y < height ; ++y) {
411            for (int x = 0; x < width; ++x) {
412                *pindex = (old_ay + y) * _atlasWidth + old_ax + x; ++pindex;
413                *pindex = (ay + y) * _atlasWidth + ax + x; ++pindex;
414            }
415        }
416
417        old_ax = ax;
418        old_ay = ay;
419    }
420}
421
422void ParticleSystem::initShaders()
423{
424    // TBD...
425    _context = 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 += _emitters[i]->_maxPositionOffset *
1113                    vrmath::Vector3f(randomRange(-1.0f, 1.0f), randomRange(-1.0f, 1.0f), randomRange(-1.0f, 1.0f));
1114
1115                float lifetime = randomRange(_emitters[i]->_minLifeTime, _emitters[i]->_maxLifeTime);
1116
1117                // TBD..
1118                allocateParticle(position, vrmath::Vector3f(0.0f, 0.0f, 0.0f),  lifetime, 1 - (float) k / numOfNewParticles);
1119            }
1120        }
1121
1122        initNewParticles();
1123
1124        _currentTime += deltaT;
1125
1126        cleanUpParticles();
1127    }
1128
1129    return true;
1130}
1131
1132void ParticleSystem::allocateParticle(const vrmath::Vector3f& position, const vrmath::Vector3f& velocity,
1133                                      float lifeTime, float initTimeStep)
1134{
1135    if (_availableIndices.empty()) {
1136        return;
1137    }
1138
1139    int index = _availableIndices.top();
1140    _availableIndices.pop();
1141
1142    ActiveParticle p;
1143    p.index = index;
1144    p.timeOfDeath = _currentTime + lifeTime;
1145    _activeParticles.push(p);
1146
1147    NewParticle newParticle;
1148    newParticle.index = index;
1149    newParticle.position = position;
1150    newParticle.velocity = velocity;
1151    newParticle.timeOfDeath = p.timeOfDeath;
1152    newParticle.initTimeStep = initTimeStep;
1153
1154    _newParticles.push_back(newParticle);
1155
1156    _particles[index].timeOfBirth = _currentTime;
1157    _particles[index].lifeTime = lifeTime;
1158}
1159
1160void ParticleSystem::initNewParticles()
1161{
1162    /////////////////////////////
1163    // INIT NEW PARTICLE
1164    glBindBufferARB(GL_ARRAY_BUFFER_ARB, _particleInfoBufferID);
1165    Particle* pinfo = (Particle*) glMapBufferARB(GL_ARRAY_BUFFER, GL_WRITE_ONLY_ARB);
1166
1167    std::vector<NewParticle>::iterator iter;
1168    for (iter = _newParticles.begin(); iter != _newParticles.end(); ++iter) {
1169        pinfo[iter->index] = _particles[iter->index];
1170    }
1171
1172    glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
1173
1174    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_currentPosIndex]);
1175
1176    glPushAttrib(GL_VIEWPORT_BIT);
1177    glViewport(0, 0, _width, _height);
1178    glMatrixMode(GL_PROJECTION);
1179    glPushMatrix();
1180    glLoadIdentity();
1181    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1182    glMatrixMode(GL_MODELVIEW);
1183    glPushMatrix();
1184    glLoadIdentity();
1185
1186    cgGLBindProgram(_initParticlePosFP);
1187    cgGLEnableProfile(CG_PROFILE_FP40);
1188    cgGLSetTextureParameter(_ipVectorFieldParam, _curVectorFieldID);
1189    cgGLEnableTextureParameter(_ipVectorFieldParam);
1190    // TBD..
1191    //glActiveTextureARB(GL_TEXTURE0_ARB);
1192    //VelocityPBuffers[VelocityCurrent]->Bind();
1193
1194    glActiveTextureARB(GL_TEXTURE0_ARB);
1195    glEnable(GL_TEXTURE_RECTANGLE_ARB);
1196    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_destPosIndex]);
1197
1198    glBegin(GL_POINTS);
1199    for (iter = _newParticles.begin(); iter != _newParticles.end(); iter++) {
1200        //TRACE("[%d] %f %f %f", iter->index, iter->position.x,iter->position.y,iter->position.z);
1201        glMultiTexCoord3f(GL_TEXTURE0, iter->position.x,iter->position.y,iter->position.z);
1202
1203        // TBD..
1204        //glMultiTexCoord2f(GL_TEXTURE1_ARB, (float)(i->Index % Width), (float)(i->Index / Height));
1205        //glMultiTexCoord1f(GL_TEXTURE2_ARB, iter->initTimeStep);
1206
1207        glVertex2f((float)(iter->index % _width),
1208                   (float)(iter->index / _height) + 1/* + offsetY*/ /* + offsetY shouldn't be */);
1209        //TRACE("%f %f", (float) (iter->index % _width), (float)(iter->index / _width));
1210    }
1211    glEnd();
1212
1213    glDisable(GL_TEXTURE_RECTANGLE_ARB);
1214    cgGLDisableTextureParameter(_ipVectorFieldParam);
1215    cgGLDisableProfile(CG_PROFILE_FP40);
1216
1217    glMatrixMode(GL_PROJECTION);
1218    glPopMatrix();
1219    glMatrixMode(GL_MODELVIEW);
1220    glPopMatrix();
1221    glPopAttrib();
1222
1223    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1224
1225    // INIT NEW END
1226    /////////////////////////////
1227#if 1
1228    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _initPos_fbo);
1229    glPushAttrib(GL_VIEWPORT_BIT);
1230    glViewport(0, 0, _width, _height);
1231    glMatrixMode(GL_PROJECTION);
1232    glPushMatrix();
1233    glLoadIdentity();
1234    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1235    glMatrixMode(GL_MODELVIEW);
1236    glPushMatrix();
1237    glLoadIdentity();
1238
1239    cgGLBindProgram(_initParticlePosFP);
1240    cgGLEnableProfile(CG_PROFILE_FP40);
1241    cgGLSetTextureParameter(_ipVectorFieldParam, _curVectorFieldID);
1242    cgGLEnableTextureParameter(_ipVectorFieldParam);
1243    // TBD..
1244    //glActiveTextureARB(GL_TEXTURE0_ARB);
1245    //VelocityPBuffers[VelocityCurrent]->Bind();
1246
1247    glActiveTextureARB(GL_TEXTURE0_ARB);
1248    glEnable(GL_TEXTURE_RECTANGLE_ARB);
1249    //glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _initPosTex);
1250    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_destPosIndex]);
1251
1252    glBegin(GL_POINTS);
1253    for (iter = _newParticles.begin(); iter != _newParticles.end(); iter++) {
1254        //TRACE("[%d] %f %f %f", iter->index, iter->position.x,iter->position.y,iter->position.z);
1255        glMultiTexCoord3f(GL_TEXTURE0, iter->position.x,iter->position.y,iter->position.z);
1256
1257        // TBD..
1258        //glMultiTexCoord2f(GL_TEXTURE1_ARB, (float)(i->Index % Width), (float)(i->Index / Height));
1259        //glMultiTexCoord1f(GL_TEXTURE2_ARB, iter->initTimeStep);
1260
1261        glVertex2f((float)(iter->index % _width),
1262                   (float)(iter->index / _height) + 1/* + offsetY*/ /* + offsetY shouldn't be */);
1263        //TRACE("%f %f", (float) (iter->index % _width), (float)(iter->index / _width));
1264    }
1265    glEnd();
1266
1267    glDisable(GL_TEXTURE_RECTANGLE_ARB);
1268    cgGLDisableTextureParameter(_ipVectorFieldParam);
1269    cgGLDisableProfile(CG_PROFILE_FP40);
1270
1271    glMatrixMode(GL_PROJECTION);
1272    glPopMatrix();
1273    glMatrixMode(GL_MODELVIEW);
1274    glPopMatrix();
1275    glPopAttrib();
1276
1277    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1278#endif
1279
1280    // Free array.
1281    _newParticles.clear();
1282}
1283
1284void ParticleSystem::cleanUpParticles()
1285{
1286    if (! _activeParticles.empty()) {
1287        while (_activeParticles.top().timeOfDeath < _currentTime) {
1288            unsigned int i = _activeParticles.top().index;
1289            _activeParticles.pop();
1290            _availableIndices.push(i);
1291            //_usedIndices[i] = false;
1292
1293            //if (i >= _maxUsedIndex)
1294            //    while (!_usedIndices[_maxUsedIndex])
1295            //        _maxUsedIndex--;
1296        }
1297    }
1298}
1299
1300void ParticleSystem::sort()
1301{
1302    ///////////////////////////////////////////////////////////
1303    // BEGIN - COMPUTE DISTANCE
1304    vrmath::Vector3f pos;
1305    vrmath::Matrix4x4d mat;
1306    glPushMatrix();
1307    glLoadIdentity();
1308    glScalef(_scalex, _scaley, _scalez);
1309    glTranslatef(-0.5f, -0.5f, -0.5f);
1310    glGetDoublev(GL_MODELVIEW_MATRIX, mat.get());
1311    glPopMatrix();
1312    mat.invert();
1313    mat.getTranslation(pos);
1314
1315    cgGLBindProgram(_distanceSortFP);
1316    cgGLEnableProfile(CG_PROFILE_FP40);
1317
1318    glActiveTextureARB(GL_TEXTURE0_ARB);
1319    glEnable(GL_TEXTURE_RECTANGLE_ARB);
1320    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sort_tex[_currentSortIndex]);
1321
1322    glActiveTextureARB(GL_TEXTURE1_ARB);
1323    glEnable(GL_TEXTURE_RECTANGLE_ARB);
1324    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_currentPosIndex]);
1325
1326    cgGLSetParameter3f(_viewPosParam, pos.x, pos.y, pos.z);
1327
1328    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_destSortIndex]);
1329    glPushAttrib(GL_VIEWPORT_BIT);
1330    glViewport(0, 0, _width, _height);
1331    glMatrixMode(GL_PROJECTION);
1332    glPushMatrix();
1333    glLoadIdentity();
1334    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1335    glMatrixMode(GL_MODELVIEW);
1336    glPushMatrix();
1337    glLoadIdentity();
1338
1339    drawQuad();
1340
1341    cgGLDisableProfile(CG_PROFILE_FP40);
1342
1343    glMatrixMode(GL_PROJECTION);
1344    glPopMatrix();
1345    glMatrixMode(GL_MODELVIEW);
1346    glPopMatrix();
1347    glPopAttrib();
1348    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1349
1350    // _DEBUG
1351    /*
1352    {
1353        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_destSortIndex]);
1354        static float debug[256];
1355        glReadPixels(0, 0, _width, _height, GL_RGB, GL_FLOAT, (float*)debug);
1356        TRACE("[%d]", _currentSortIndex);
1357        for (int i = 0; i < _width * _height * 3; i += 3)
1358            TRACE("%.2f, %.2f, %.2f", debug[i], debug[i+1], debug[i+2]);
1359        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1360    }
1361    */
1362
1363    // _DEBUG
1364    /*
1365    {
1366        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_currentPosIndex]);
1367        static float debug[256];
1368        glReadPixels(0, 0, _width, _height, GL_RGB, GL_FLOAT, (float*)debug);
1369        TRACE("currentPos[%d]", _currentPosIndex);
1370        for (int i = 0; i < _width * _height * 3; i += 3)
1371            TRACE("%.2f, %.2f, %.2f", debug[i], debug[i+1], debug[i+2]);
1372        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1373    }
1374    */
1375
1376    // compute distance
1377    swap(_currentSortIndex, _destSortIndex);
1378
1379    // END - COMPUTE DISTANCE
1380    ///////////////////////////////////////////////////////////
1381
1382    ///////////////////////////////////////////////////////////
1383    // BEGIN - MERGE SORT
1384    _currentSortPass = 0;
1385
1386    int logdSize = logd(_particleMaxCount);
1387    _maxSortPasses = (logdSize + 1) * logdSize / 2;
1388
1389    _sortBegin = _sortEnd;
1390    _sortEnd = (_sortBegin + _sortPassesPerFrame) % _maxSortPasses;
1391
1392    cgGLSetParameter2f(_srSizeParam, (float)_width, (float)_height);
1393    cgGLSetParameter2f(_seSizeParam, (float)_width, (float)_height);
1394
1395    mergeSort(this->_particleMaxCount);
1396
1397    // _DEBUG
1398    /*
1399    {
1400        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_currentSortIndex]);
1401        static float debug[256];
1402        glReadPixels(0, 0, _width, _height, GL_RGB, GL_FLOAT, (float*)debug);
1403        TRACE("[%d]", _currentSortIndex);
1404        for (int i = 0; i < _width * _height * 3; i += 3)
1405            TRACE("%.2f, %.2f, %.2f", debug[i], debug[i+1], debug[i+2]);
1406        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1407    }
1408    */
1409
1410    // END - MERGE SORT
1411    ///////////////////////////////////////////////////////////
1412
1413    ///////////////////////////////////////////////////////////
1414    // POSITION LOOKUP
1415    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
1416    cgGLBindProgram(_distanceSortLookupFP);
1417    cgGLEnableProfile(CG_PROFILE_FP40);
1418
1419    glActiveTextureARB(GL_TEXTURE0_ARB);
1420    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sort_tex[_currentSortIndex]);
1421
1422    glActiveTextureARB(GL_TEXTURE1_ARB);
1423    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, psys_tex[_currentPosIndex]);
1424
1425    glPushAttrib(GL_VIEWPORT_BIT);
1426    glViewport(0, 0, _width, _height);
1427    glMatrixMode(GL_PROJECTION);
1428    glPushMatrix();
1429    glLoadIdentity();
1430    glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1431    glMatrixMode(GL_MODELVIEW);
1432    glPushMatrix();
1433    glLoadIdentity();
1434
1435    drawQuad();
1436
1437    glMatrixMode(GL_PROJECTION);
1438    glPopMatrix();
1439    glMatrixMode(GL_MODELVIEW);
1440    glPopMatrix();
1441    glPopAttrib();
1442
1443    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1444    cgGLDisableProfile(CG_PROFILE_FP40);
1445
1446    // POSITION LOOKUP
1447    ///////////////////////////////////////////////////////////
1448    glActiveTextureARB(GL_TEXTURE1_ARB);
1449    glDisable(GL_TEXTURE_RECTANGLE_ARB);
1450
1451    glActiveTextureARB(GL_TEXTURE0_ARB);
1452    glDisable(GL_TEXTURE_RECTANGLE_ARB);
1453
1454    // _DEBUG
1455    /*
1456    {
1457        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, psys_fbo[_destPosIndex]);
1458        static float debug[256];
1459        glReadPixels(0, 0, _width, _height, GL_RGB, GL_FLOAT, (float*)debug);
1460        TRACE("[%d]", _currentSortIndex);
1461        for (int i = 0; i < _width * _height * 3; i += 3)
1462            TRACE("%.2f, %.2f, %.2f", debug[i], debug[i+1], debug[i+2]);
1463        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1464    }
1465    */
1466}
1467
1468void ParticleSystem::mergeSort(int count)
1469{
1470    if (count > 1) {
1471        mergeSort(count >> 1);
1472        merge(count, 1);
1473    }
1474}
1475
1476void ParticleSystem::merge(int count, int step)
1477{
1478    if (count > 2) {
1479        merge(count >> 1, step << 1);
1480
1481        ++_currentSortPass;
1482
1483        if (_sortBegin < _sortEnd) {
1484            if (_currentSortPass < _sortBegin || _currentSortPass >= _sortEnd)
1485                return;
1486        } else {
1487            if (_currentSortPass < _sortBegin && _currentSortPass >= _sortEnd)
1488                return;
1489        }
1490
1491        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_destSortIndex]);
1492        cgGLBindProgram(_sortRecursionFP);
1493        cgGLEnableProfile(CG_PROFILE_FP40);
1494
1495        glActiveTextureARB(GL_TEXTURE0_ARB);
1496        glBindTexture(GL_TEXTURE_RECTANGLE_ARB , sort_tex[_currentSortIndex]);
1497
1498        cgGLSetParameter1f(_srStepParam, (float)step);
1499        cgGLSetParameter1f(_srCountParam, (float)count);
1500
1501        glPushAttrib(GL_VIEWPORT_BIT);
1502        glViewport(0, 0, _width, _height);
1503        glMatrixMode(GL_PROJECTION);
1504        glPushMatrix();
1505        glLoadIdentity();
1506        glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1507        glMatrixMode(GL_MODELVIEW);
1508        glPushMatrix();
1509        glLoadIdentity();
1510
1511        drawQuad();
1512
1513        glMatrixMode(GL_PROJECTION);
1514        glPopMatrix();
1515        glMatrixMode(GL_MODELVIEW);
1516        glPopMatrix();
1517        glPopAttrib();
1518
1519        cgGLDisableProfile(CG_PROFILE_FP40);
1520
1521        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1522        glBindTexture(GL_TEXTURE_RECTANGLE_ARB , 0);
1523    } else {
1524        _currentSortPass++;
1525
1526        if (_sortBegin < _sortEnd) {
1527            if (_currentSortPass < _sortBegin || _currentSortPass >= _sortEnd)
1528                return;
1529        } else {
1530            if (_currentSortPass < _sortBegin && _currentSortPass >= _sortEnd)
1531                return;
1532        }
1533
1534        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sort_fbo[_destSortIndex]);
1535        cgGLBindProgram(_sortEndFP);
1536        cgGLEnableProfile(CG_PROFILE_FP40);
1537
1538        glActiveTextureARB(GL_TEXTURE0_ARB);
1539        glBindTexture(GL_TEXTURE_RECTANGLE_ARB , sort_tex[_currentSortIndex]);
1540
1541        cgGLSetParameter1f(_seStepParam, (float)step);
1542
1543        glPushAttrib(GL_VIEWPORT_BIT);
1544        glViewport(0, 0, _width, _height);
1545        glMatrixMode(GL_PROJECTION);
1546        glPushMatrix();
1547        glLoadIdentity();
1548        glOrtho(0, _width, 0, _height, -10.0f, 10.0f);
1549        glMatrixMode(GL_MODELVIEW);
1550        glPushMatrix();
1551        glLoadIdentity();
1552
1553        drawQuad();
1554
1555        glMatrixMode(GL_PROJECTION);
1556        glPopMatrix();
1557        glMatrixMode(GL_MODELVIEW);
1558        glPopMatrix();
1559        glPopAttrib();
1560
1561        cgGLDisableProfile(CG_PROFILE_FP40);
1562
1563        glBindTexture(GL_TEXTURE_RECTANGLE_ARB , 0);
1564        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1565    }
1566
1567    swap(_currentSortIndex, _destSortIndex);
1568}
1569
1570void ParticleSystem::renderStreamlines()
1571{
1572    if (_currentStreamlineIndex > 2) {
1573        glPushMatrix();
1574        glScalef(_scalex, _scaley, _scalez);
1575        glTranslatef(-0.5f, -0.5f, -0.5f);
1576
1577        if (_drawBBoxEnabled) drawUnitBox();
1578
1579        glColor3f(1.0f, 0.0f, 0.0f);
1580        glEnableClientState(GL_VERTEX_ARRAY);
1581        //glEnableClientState(GL_COLOR_ARRAY);
1582
1583        _streamVertices->SetPointer(0);
1584        //glColorPointer(4, GL_FLOAT, 0, 0);
1585
1586        ::glDrawElements(GL_LINES, _particleCount * 2 * (_currentStreamlineIndex - 1),
1587                         GL_UNSIGNED_INT, _indexBuffer);
1588        glDisableClientState(GL_VERTEX_ARRAY);
1589        glPopMatrix();
1590    }
1591}
1592
1593void ParticleSystem::render()
1594{
1595    glPushMatrix();
1596
1597    if (_streamlineEnabled) {
1598        renderStreamlines();
1599    } else {
1600        glScalef(_scalex, _scaley, _scalez);
1601        glTranslatef(-0.5f, -0.5f, -0.5f);
1602        if (_glyphEnabled) {
1603            if (_drawBBoxEnabled) drawUnitBox();
1604            glColor3f(1, 1, 1);
1605
1606            glDepthMask(GL_FALSE);
1607            glEnable(GL_BLEND);
1608
1609#ifndef USE_RGBA_ARROW
1610            glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1611#else
1612            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1613#endif
1614            glEnable(GL_ALPHA_TEST);
1615            glAlphaFunc(GL_GREATER, 0.6);
1616
1617            glEnable(GL_POINT_SPRITE_ARB);
1618            glPointSize(_pointSize);
1619
1620            glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
1621
1622#ifndef TEST
1623            _arrows->activate();
1624            glEnable(GL_TEXTURE_2D);
1625            glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 0.0f);
1626
1627            glPointParameterfARB(GL_POINT_SIZE_MIN_ARB, 1.0f);
1628            glPointParameterfARB(GL_POINT_SIZE_MAX_ARB, 100.0f);
1629            glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
1630
1631            cgGLBindProgram(_particleVP);
1632            cgGLBindProgram(_particleFP);
1633            cgGLEnableProfile(CG_PROFILE_VP40);
1634            cgGLEnableProfile(CG_PROFILE_FP40);
1635
1636            cgSetParameter1f(_mvCurrentTimeParam, _currentTime);
1637            //TRACE("%f %f, %f %d", _fov, tan(_fov), tan(_fov / 2.0), _screenHeight);
1638            //cgSetParameter1f(_mvTanHalfFOVParam, -tan(_fov * M_PI / 180 * 0.5) * _screenHeight * 0.5);
1639            //float v = tan(_fov * M_PI / 180 * 0.5) * _screenHeight * 0.5;
1640            cgSetParameter1f(_mvTanHalfFOVParam, tan(_fov * M_PI / 180 * 0.5) * _screenHeight * 0.5);
1641            //cgSetParameter1f(_mvTanHalfFOVParam,  _screenHeight * 0.5 / tan(_fov * M_PI / 180 * 0.5));
1642
1643            cgGLSetStateMatrixParameter(_mvpParticleParam,
1644                                        CG_GL_MODELVIEW_PROJECTION_MATRIX,
1645                                        CG_GL_MATRIX_IDENTITY);
1646            cgGLSetStateMatrixParameter(_mvParticleParam,
1647                                        CG_GL_MODELVIEW_MATRIX,
1648                                        CG_GL_MATRIX_IDENTITY);
1649
1650            // TBD..
1651            glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);                     
1652            glEnableVertexAttribArrayARB(8);
1653            glEnableClientState(GL_VERTEX_ARRAY);
1654            //glEnableClientState(GL_COLOR_ARRAY);
1655            _vertices->SetPointer(0);
1656            //glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
1657            //glColorPointer(4, GL_FLOAT, 0, 0);
1658            //glBindBufferARB(GL_ARRAY_BUFFER, 0);
1659
1660            // TBD...
1661            glDrawArrays(GL_POINTS, 0, this->_particleMaxCount);
1662            glPointSize(1);
1663
1664            glDisableClientState(GL_VERTEX_ARRAY);
1665            //glDisableClientState(GL_COLOR_ARRAY);
1666
1667            // TBD...
1668            ::glDisableVertexAttribArray(8);
1669            glPopClientAttrib();
1670
1671            cgGLDisableProfile(CG_PROFILE_VP40);
1672            cgGLDisableProfile(CG_PROFILE_FP40);
1673
1674            glDepthMask(GL_TRUE);
1675
1676            glDisable(GL_POINT_SPRITE_ARB);
1677            glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
1678
1679            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1680            glDisable(GL_BLEND);
1681#else
1682            glBindTexture(GL_TEXTURE_2D, ::SpotTexID);
1683            glEnable(GL_TEXTURE_2D);
1684            //glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 60.0f );
1685            glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 0.0f );
1686
1687            glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 1.0f);
1688            glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, 100.0f);
1689            glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
1690
1691            glEnableClientState(GL_VERTEX_ARRAY);
1692            //glEnableClientState(GL_COLOR_ARRAY);
1693            _vertices->SetPointer(0);
1694            //glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
1695            //glColorPointer(4, GL_FLOAT, 0, 0);
1696            //glBindBufferARB(GL_ARRAY_BUFFER, 0);
1697
1698            // TBD...
1699            glDrawArrays(GL_POINTS, 0, this->_particleMaxCount);
1700            glPointSize(1);
1701            glDrawArrays(GL_POINTS, 0, this->_particleMaxCount);
1702
1703            glDisableClientState(GL_VERTEX_ARRAY);
1704
1705            glDepthMask(GL_TRUE);
1706
1707            glDisable(GL_POINT_SPRITE_ARB);
1708            glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
1709
1710            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1711            glDisable(GL_BLEND);
1712#endif
1713        } else {
1714            if (_drawBBoxEnabled) drawUnitBox();
1715
1716            glColor3f(1, 1, 1);
1717            glEnableClientState(GL_VERTEX_ARRAY);
1718            //glEnableClientState(GL_COLOR_ARRAY);
1719            glPointSize(10);
1720            _vertices->SetPointer(0);
1721            //glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
1722            //glColorPointer(4, GL_FLOAT, 0, 0);
1723            //glBindBufferARB(GL_ARRAY_BUFFER, 0);
1724            glDrawArrays(GL_POINTS, 0, _particleMaxCount);
1725
1726            glPointSize(1);
1727            _vertices->SetPointer(0);
1728            //glBindBufferARB(GL_ARRAY_BUFFER, _colorBufferID);
1729            //glColorPointer(4, GL_FLOAT, 0, 0);
1730            //glBindBufferARB(GL_ARRAY_BUFFER, 0);
1731            glDrawArrays(GL_POINTS, 0, _particleMaxCount);
1732
1733            glDisableClientState(GL_VERTEX_ARRAY);
1734        }
1735
1736#ifdef notdef
1737        if (_criticalPoints && _criticalPoints->size()) {
1738            std::vector<vrmath::Vector3f>::iterator iter;
1739            glColor4f(1, 1, 1, 1);
1740            glPointSize(10);
1741            glBegin(GL_POINTS);
1742            for (iter = _criticalPoints->begin(); iter != _criticalPoints->end(); ++iter) {
1743                glVertex3f((*iter).x, (*iter).y, (*iter).z);
1744            }
1745            glEnd();
1746            glPointSize(1);
1747        }
1748#endif
1749    }
1750
1751    glPopMatrix();
1752}
1753
1754void ParticleSystem::drawQuad(int x1, int y1, int x2, int y2)
1755{
1756    glBegin(GL_QUADS);
1757
1758    glTexCoord2f(x1, y1);
1759    glVertex2f(x1, y1);
1760
1761    glTexCoord2f(x2, y1);
1762    glVertex2f(x2, y1);
1763
1764    glTexCoord2f(x2, y2);
1765    glVertex2f(x2, y2);
1766
1767    glTexCoord2f(x1, y2);
1768    glVertex2f(x1, y2);
1769
1770    glEnd();
1771}
1772
1773void ParticleSystem::drawQuad()
1774{
1775    glBegin(GL_QUADS);
1776
1777    glTexCoord2f(0, 0);
1778    glVertex2f(0, 0);
1779
1780    glTexCoord2f((float)_width, 0);
1781    glVertex2f((float)_width, 0);
1782
1783    glTexCoord2f((float)_width, (float)_height);
1784    glVertex2f((float)_width, (float)_height);
1785
1786    glTexCoord2f(0, (float)_height);
1787    glVertex2f(0, (float)_height);
1788
1789    glEnd();
1790}
1791
1792void ParticleSystem::addEmitter(ParticleEmitter* emitter)
1793{
1794    _emitters.push_back(emitter);
1795}
1796
1797void ParticleSystem::removeEmitter(int index)
1798{
1799    // TBD...
1800}
1801
1802void ParticleSystem::removeAllEmitters()
1803{
1804    std::vector<ParticleEmitter*>::iterator iter;
1805    for (iter = _emitters.begin(); iter != _emitters.end(); ++iter) {
1806        delete *iter;
1807    }
1808    _emitters.clear();
1809}
1810
1811void ParticleSystem::drawUnitBox()
1812{
1813    float x0 = 0.0f, y0 = 0.0f, z0 = 0.0f;
1814    float x1 = 1.0f, y1 = 1.0f, z1 = 1.0f;
1815    float r = 1.0f, g = 1.0f, b = 0.0f;
1816    float line_width = 2.0f;
1817    glEnable(GL_DEPTH_TEST);
1818    glDisable(GL_TEXTURE_2D);
1819    glEnable(GL_BLEND);
1820
1821    glColor4d(r, g, b, 1.0);
1822    glLineWidth(line_width);
1823
1824    glBegin(GL_LINE_LOOP);
1825    {
1826        glVertex3d(x0, y0, z0);
1827        glVertex3d(x1, y0, z0);
1828        glVertex3d(x1, y1, z0);
1829        glVertex3d(x0, y1, z0);
1830    }
1831    glEnd();
1832
1833    glBegin(GL_LINE_LOOP);
1834    {
1835        glVertex3d(x0, y0, z1);
1836        glVertex3d(x1, y0, z1);
1837        glVertex3d(x1, y1, z1);
1838        glVertex3d(x0, y1, z1);
1839    }
1840    glEnd();
1841
1842    glBegin(GL_LINE_LOOP);
1843    {
1844        glVertex3d(x0, y0, z0);
1845        glVertex3d(x0, y0, z1);
1846        glVertex3d(x0, y1, z1);
1847        glVertex3d(x0, y1, z0);
1848    }
1849    glEnd();
1850
1851    glBegin(GL_LINE_LOOP);
1852    {
1853        glVertex3d(x1, y0, z0);
1854        glVertex3d(x1, y0, z1);
1855        glVertex3d(x1, y1, z1);
1856        glVertex3d(x1, y1, z0);
1857    }
1858    glEnd();
1859    glLineWidth(1.0f);
1860}
1861
1862void ParticleSystem::setUserDefinedNumOfParticles(int numParticles)
1863{
1864    if (numParticles < _particleMaxCount)
1865        _userDefinedParticleMaxCount = numParticles;
1866    else
1867        _userDefinedParticleMaxCount = _particleMaxCount;
1868    reset();
1869}
Note: See TracBrowser for help on using the repository browser.