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

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

Remove XINETD define from nanovis. We only support server mode now, no glut
interaction loop with mouse/keyboard handlers. Fixes for trace logging to make
output closer to vtkvis: inlcude function name for trace messages, remove
newlines from format strings in macros since newlines get added by syslog.

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