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

Last change on this file since 2844 was 2831, checked in by ldelgass, 12 years ago

Refactor texture classes, misc. cleanups, cut down on header pollution -- still
need to fix header deps in Makefile.in

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