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

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

Add basic VTK structured points reader to nanovis, update copyright dates.

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