FlowVis 1.0

FlowVis/RenderWidget.cpp

00001 #include "RenderWidget.h"
00002 #include "Framework/vec3.h"
00003 
00004 #include <QtGui/QFileDialog>
00005 #include <iostream>
00006 #include <cmath>
00007 
00008 RenderWidget::RenderWidget(QWidget *parent)
00009 : QGLWidget(parent),textures(NULL),channelCount(0),PI(3.14159265358979323846)
00010 {
00011         QSizePolicy policy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00012         policy.setHeightForWidth(true);
00013 
00014         setSizePolicy(policy );
00015 
00016         this->setSizeIncrement(30,30);
00017         arrowCount = 35;
00018         textureSize = 100;
00019         d_sep_val = 1.f / 100.f;
00020         d_sep = d_sep_val * (float)textureSize;
00021         d_test_val = 0.8f;
00022         d_test = d_test_val * d_sep;
00023         dt = 0.5f;
00024         sl_num_samples = 50;
00025         xdata = NULL;
00026         ydata = NULL;
00027         integration_mode = EULER;
00028         streamline_mode = NORMAL;
00029         arrowSize = 2.5;
00030 }
00031 
00032 RenderWidget::~RenderWidget()
00033 {
00034         delete simple;
00035         delete arrows;
00036         delete slines;
00037         delete sltexture;
00038         delete textures;
00039         delete xdata;
00040         delete ydata;
00041 
00042         simple = NULL;
00043         arrows = NULL;
00044         slines = NULL;
00045         sltexture = NULL;
00046 
00047         glDeleteLists(disp_lists[0], 1);
00048         glDeleteLists(disp_lists[1], 1);
00049         delete[] disp_lists;
00050 
00051         for (int i=0; i < streamlines.size(); i++)
00052         {
00053                 delete streamlines[i];
00054         }
00055 }
00056 
00057 void RenderWidget::loadChannels(FlowData* dataset)
00058 {
00059         //Anzahl von channels sollt gleich bleiben sonst gibts hier fehler
00060         //alte texturen loeschen
00061         if(channelCount != 0)
00062                 glDeleteTextures(channelCount, textures);
00063         
00064         if (textures != NULL)
00065                 delete textures;
00066         
00067         channelCount = dataset->getNumChannels();
00068         textures = new GLuint[channelCount];
00069         
00070         //Texturen generieren
00071         glGenTextures(channelCount, textures);
00072         
00073         GLenum glError = GL_NO_ERROR;
00074         glError = glGetError();
00075         if (glError != GL_NO_ERROR)
00076         {
00077                 std::cerr<<"Error generating texture: "<<gluErrorString(glError)<<std::endl;
00078         } 
00079 
00080         int w,h;
00081         dataset->getGeometry(w,h);
00082         
00083         textureWidth = (w < h) ? textureSize: (int)( (float)textureSize*(float)w/(float)h );
00084         textureHeight = (w < h) ? (int)( (float)textureSize*(float)h/(float)w ) : textureSize ;
00085 
00086         sl_num_samples = (float)textureSize/2.f;
00087 
00088         //int size = textureSize;
00089         float* vdata = new float[textureWidth*textureHeight];
00090         if (xdata != NULL)
00091                 delete xdata;
00092         if (ydata != NULL)
00093                 delete ydata;
00094         xdata = new float[textureWidth*textureHeight];
00095         ydata = new float[textureWidth*textureHeight];
00096         
00097         //create channels
00098 
00099         int vel = dataset->createChannelVectorLength(0,1,2);
00100         
00101         //range for velocity
00102         float range = dataset->getChannel(vel)->getRange();
00103         float min = dataset->getChannel(vel)->getMin();
00104 
00105         std::cout << "Texture size: " << textureWidth <<"x"<<textureHeight << std::endl;
00106 
00107         for(int x=0; x<textureWidth; x++)
00108         {
00109                 for(int y=0; y<textureHeight; y++)
00110                 {
00111                         float velocity = dataset->getChannel(vel)->getValueNormPos(vec3(((float)x)/(float)textureWidth,((float)y)/(float)textureHeight));
00112                         //float xd = dataset->getChannel(chX)->getValueNormPos(vec3(((float)x)/(float)size,((float)y)/(float)size));
00113                         //float yd = dataset->getChannel(chY)->getValueNormPos(vec3(((float)x)/(float)size,((float)y)/(float)size));
00114                         float xd = dataset->getChannel(0)->getValueNormPos(vec3(((float)x)/(float)textureWidth,((float)y)/(float)textureHeight));
00115                         float yd = dataset->getChannel(1)->getValueNormPos(vec3(((float)x)/(float)textureWidth,((float)y)/(float)textureHeight));
00116 
00117                         float vel = sqrtf(xd*xd+yd*yd);
00118                         xdata[x+y*textureWidth] = xd/vel/2.0+0.5;
00119                         ydata[x+textureWidth*y] = yd/vel/2.0+0.5;
00120                         
00121                         //if(xdata[x*size+y] > 1.0 || xdata[x*size+y] < 0.0 || ydata[x*size+y] > 1.0 || ydata[x*size+y] < 0.0)
00122                         //      std::cout << "Fehler, out of range" << std::endl;
00123                         vdata[x+y*textureWidth] = (velocity-min)/range;
00124                 }
00125                 std::cout << "\r- Calculating x,y channel textures (" << (float)x*100.f/(float)(textureWidth - 1) << "%) ...";
00126         }       
00127         std::cout << std::endl;
00128 
00129 
00130         computeStreamlines();
00131 
00132 
00133         //glClientActiveTexture(GL_TEXTURE0);
00134         glBindTexture(GL_TEXTURE_2D,textures[CHANNEL_VELOCITY]);
00135         glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE32F_ARB,textureWidth,textureHeight,0,GL_LUMINANCE,GL_FLOAT,vdata);
00136         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00137         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00138         glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
00139 
00140         //glClientActiveTexture(GL_TEXTURE1);
00141         glBindTexture(GL_TEXTURE_2D,textures[CHANNEL_X]);
00142         glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE32F_ARB,textureWidth,textureHeight,0,GL_LUMINANCE,GL_FLOAT,xdata);
00143         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00144         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00145 
00146 
00147         //glClientActiveTexture(GL_TEXTURE2);
00148         glBindTexture(GL_TEXTURE_2D,textures[CHANNEL_Y]);
00149         glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE32F_ARB,textureWidth,textureHeight,0,GL_LUMINANCE,GL_FLOAT,ydata);
00150         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00151         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00152 
00153         delete vdata;
00154         //delete xdata;
00155         //delete ydata;
00156 
00157         float* data = new float[textureWidth*textureHeight];
00158         
00159         //int count = dataset->getNumChannels()-3;
00160         for(int i=3; i <channelCount; i++)              //Restliche channels einlesen
00161         {
00162                 range = dataset->getChannel(i)->getRange();
00163                 min = dataset->getChannel(i)->getMin();
00164 
00165                 for(int x=0; x<textureWidth; x++)
00166                 {
00167                         for(int y=0; y<textureHeight; y++)
00168                         {
00169                                 float d = dataset->getChannel(i)->getValueNormPos(vec3(((float)x)/(float)textureWidth,((float)y)/(float)textureHeight));
00170                                 data[x+y*textureWidth] = (d-min)/range;
00171                         }
00172 
00173                         std::cout << "\r- Calculating channel"<<i<<" textures (" << (float)x*100.f/(float)(textureWidth - 1) << "%) ...";
00174                 }
00175                 std::cout << std::endl;
00176                 glBindTexture(GL_TEXTURE_2D,textures[i]);
00177                 glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE32F_ARB,textureWidth,textureHeight,0,GL_LUMINANCE,GL_FLOAT,data);
00178                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00179                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00180         }
00181         
00182         delete data;
00183         
00184         glActiveTexture(GL_TEXTURE1);
00185         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00186         
00187         glActiveTexture(GL_TEXTURE2);
00188         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00189         
00190         glActiveTexture(GL_TEXTURE0);
00191 
00192         initArrows(arrowCount,(float)textureWidth/(float)textureHeight);
00193 }
00194 
00195 void RenderWidget::computeStreamlines()
00196 {
00197         streamlines.clear();
00198         // calculate streamlines
00199         d_sep = d_sep_val * (float)textureWidth;
00200         d_test = d_test_val * d_sep;
00201         int gridwidth = (int)( (float)(textureWidth) / d_sep );
00202         int gridheight = (int)( (float)(textureHeight) / d_sep );
00203         vector<vec3>* grid = new vector<vec3>[gridwidth*gridheight];
00204 
00205         vec3 seed(0.5 * textureWidth, 0.5 * textureHeight);
00206 
00207         Streamline *s = calculateStreamline(&seed, gridwidth, gridheight, &grid);
00208         streamlines.push_back(s);
00209         queue<Streamline*> lines;
00210         lines.push(s);
00211 
00212         Streamline *currentS = (lines.front());
00213         vector<vec3> *samplepoints = (currentS->getSamplePointsPtr(false));
00214         int i=0;
00215         bool found_candidate = false;
00216         bool finished_front = false;
00217 
00218         queue<vec3> cands;
00219 
00220         // seed point of current streamline is not taken into consideration for new seedpoints!!
00221 
00222         while (true) {
00223                 vec3 candidate;
00224 
00225                 while (i < samplepoints->size() && cands.empty()) {
00226                         vec3 p = (*samplepoints)[i];
00227                         i++;
00228                         int ind = (int)(p[0]) + ((int)p[1] * textureWidth);
00229                         vec3 dir(-(ydata[ind] - 0.5), xdata[ind] - 0.5);
00230                         dir = !dir * d_sep;
00231 
00232                         candidate = p + dir;
00233 
00234                         if (candidate[0] >= 0 && candidate[1] >= 0 && 
00235                                 candidate[0] < textureWidth && candidate[1] < textureHeight && 
00236                                 gridAroundOkay(grid, gridwidth, gridheight, candidate, NULL)) {
00237                                         cands.push(candidate);
00238                         }
00239 
00240                         candidate = p - dir;
00241 
00242                         if (candidate[0] >= 0 && candidate[1] >= 0 && 
00243                                 candidate[0] < textureWidth && candidate[1] < textureHeight && 
00244                                 gridAroundOkay(grid, gridwidth, gridheight, candidate, NULL)) {
00245                                         cands.push(candidate);
00246                         }
00247 
00248                         //set to back list
00249                         if (!finished_front && i == samplepoints->size()) {
00250                                 samplepoints = (currentS->getSamplePointsPtr(true));
00251                                 i=0;
00252                                 finished_front = true;
00253                         }
00254                 }
00255 
00256                 if (!cands.empty()) {
00257 
00258                         try {
00259                                 // compute new streamline
00260                                 Streamline *snext = calculateStreamline(&cands.front(), gridwidth, gridheight, &grid);
00261                                 streamlines.push_back(snext);
00262 
00263                                 // add streamline to queue
00264                                 lines.push(snext);
00265                         } catch (std::exception e) {
00266                                 //std::cerr << "streamline \"NULL\"" << std::endl;
00267                         }
00268                         cands.pop();
00269                 } else {
00270                         lines.pop();    // deletes the streamline!
00271 
00272                         if (lines.empty())
00273                                 break;
00274                         else {
00275                                 currentS = (lines.front());
00276                                 samplepoints = (currentS->getSamplePointsPtr(false));
00277                                 if (samplepoints->size() == 0)
00278                                         samplepoints = currentS->getSamplePointsPtr(true);
00279                                 i=0;
00280                                 finished_front = false;
00281                         }
00282                 }
00283         }
00284 
00285         switch (streamline_mode) {
00286         case NORMAL:
00287                 generateNormalStreamlineList();
00288                 break;
00289         case TAPERING:
00290                 generateTaperingStreamlineList();
00291                 break;
00292         case GLYPH:
00293                 generateGlyphStreamlineList();
00294                 break;
00295         case TEXTURE:
00296                 generateTextureStreamlineList();
00297                 break;
00298         }
00299 }
00300 
00301 Streamline* RenderWidget::calculateStreamline(vec3* seed, int gridWidth, int gridHeight, vector<vec3>** grid)
00302 {
00303         Streamline *s = new Streamline(*seed);
00304         const int QUEUE_SIZE = d_sep/dt + 1.f;
00305         queue<vec3>* lastones = new queue<vec3>;
00306         float dist;
00307 
00308         try     {
00309                 if ((dist = minGridDistance(*grid, gridWidth, gridHeight, *seed, lastones)) > d_test)
00310                 {
00311                         gridAddAt(*grid, gridWidth, gridHeight, *seed);
00312                         if (dist < d_sep)
00313                                 s->setSeedPointThickness((dist - d_test) / (d_sep - d_test));
00314                         else
00315                                 s->setSeedPointThickness(1.f);
00316                 } else
00317                         throw std::exception("Index out of bounds");
00318         } catch (std::exception e) {
00319                 //std::cerr << "Grid around seed point not ok" << std::endl;
00320                 throw std::exception("Grid around seed point not ok");
00321         }
00322 
00323         // go back and forth
00324         vec3 *current = seed;
00325         vec3 *newpoint;
00326         lastones->push(s->getSeedPoint());
00327         try
00328         {       // forth
00329                 vec3 pf;
00330                 while (true) {
00331                         switch (integration_mode)
00332                         {
00333                         case EULER:
00334                                 pf = getNextEulerPoint(*current, false);
00335                                 break;
00336                         case RK2:
00337                                 pf = getNextRungeKutta2Point(*current, false);
00338                                 break;
00339                         case RK4:
00340                                 pf = getNextRungeKutta4Point(*current, false);
00341                                 break;
00342                         }
00343                         if (pf.v[0] >= textureWidth || pf.v[1] >= textureHeight || pf.v[0] < 0 || pf.v[1] < 0)
00344                                 break;
00345                         if ((dist = minGridDistance(*grid, gridWidth, gridHeight, pf, lastones)) > d_test)
00346                         {
00347                                 gridAddAt(*grid, gridWidth, gridHeight, pf);
00348                                 newpoint = s->addSamplePoint(pf, false);
00349                                 if (dist < d_sep)
00350                                         s->addSamplePointThickness((dist - d_test) / (d_sep - d_test), false);
00351                                 else
00352                                         s->addSamplePointThickness(1.f, false);
00353 
00354                                 if (lastones->size() == QUEUE_SIZE) lastones->pop();
00355                                 lastones->push(*newpoint);
00356                         }
00357                         else
00358                                 break;
00359                         current = &pf;
00360                 }
00361         }
00362         catch (std::exception e)
00363         {
00364                 //std::cerr << "Next point is outside the texture" << std::endl;
00365         }
00366 
00367         current = seed;
00368         if (lastones->size() == QUEUE_SIZE) lastones->pop();
00369         lastones->push(s->getSeedPoint());
00370         try
00371         {       // back
00372                 vec3 pb;
00373                 while (true) {
00374                         switch (integration_mode)
00375                         {
00376                         case EULER:
00377                                 pb = getNextEulerPoint(*current, true);
00378                                 break;
00379                         case RK2:
00380                                 pb = getNextRungeKutta2Point(*current, true);
00381                                 break;
00382                         case RK4:
00383                                 pb = getNextRungeKutta4Point(*current, true);
00384                                 break;
00385                         }
00386                         if (pb.v[0] >= textureWidth || pb.v[1] >= textureHeight || pb.v[0] < 0 || pb.v[1] < 0)
00387                                 break;
00388                         //if ((int)pb[0] == 54 && (int)pb[1] == 54)
00389                         //      cout << endl;   // for box debug
00390                         if ((dist = minGridDistance(*grid, gridWidth, gridHeight, pb, lastones)) > d_test)
00391                         {
00392                                 gridAddAt(*grid, gridWidth, gridHeight, pb);
00393                                 newpoint = s->addSamplePoint(pb, true);
00394                                 if (dist < d_sep)
00395                                         s->addSamplePointThickness((dist - d_test) / (d_sep - d_test), true);
00396                                 else
00397                                         s->addSamplePointThickness(1.f, true);
00398 
00399                                 if (lastones->size() == QUEUE_SIZE) lastones->pop();
00400                                 lastones->push(*newpoint);
00401                         }
00402                         else
00403                                 break;
00404                         current = &pb;
00405                 }
00406         }
00407         catch (std::exception e)
00408         {
00409                 //std::cerr << "Next point is outside the texture" << std::endl;
00410         }
00411 
00412         delete lastones;
00413 
00414         return s;
00415 }
00416 
00417 void RenderWidget::gridAddAt(vector<vec3>* grid, int gridwidth, int gridheight, vec3 pos)
00418 {
00419         vec3 gpos = pos / d_sep;
00420         int ind = (int)(gpos.v[0]) + ((int)gpos.v[1] * gridwidth);
00421         if (ind >= gridwidth * gridheight) 
00422                 throw std::exception("Index out of bounds");
00423         grid[ind].push_back(pos);
00424 }
00425 
00426 bool RenderWidget::gridAroundOkay(vector<vec3>* grid, int gridwidth, int gridheight, vec3 pos, queue<vec3>* lastones) // grid als pointer?
00427 {
00428         vec3 gpos = pos / d_sep;
00429         int gridmax = gridwidth * gridheight;
00430 
00431         for (int i=-1; i < 2; i++) {
00432                 for (int j=-1; j < 2; j++) {
00433                         int x = (int)(gpos.v[0] + i);
00434                         int y = (((int)gpos.v[1] + j) * gridwidth);
00435                         int ind = x + y;
00436                         if (x < 0 || y < 0 || ind >= gridmax)
00437                                 continue;
00438                         vector<vec3> list = grid[ind];
00439                         for (int k=0; k < list.size(); k++) {
00440                                 if (!distanceOkay(pos, (list[k]))) {
00441                                         if (lastones == NULL) 
00442                                                 return false;
00443                                         bool cont = false;
00444                                         for (int l=0; l < lastones->size(); l++) {
00445                                                 if (list[k][0] == lastones->_Get_container()[l].v[0] &&
00446                                                         list[k][1] == lastones->_Get_container()[l].v[1]) {
00447                                                         cont = true;
00448                                                         break;
00449                                                 }
00450                                         }
00451                                         if (cont) continue;
00452 
00453                                         return false;
00454                                 }
00455                         }
00456                 }
00457         }
00458         return true;
00459 }
00460 
00461 float RenderWidget::minGridDistance(vector<vec3>* grid, int gridwidth, int gridheight, vec3 pos, queue<vec3>* lastones)
00462 {
00463         float minDist = d_sep;
00464         float dis = d_sep;
00465         vec3 gpos = pos / d_sep;
00466         int gridmax = gridwidth * gridheight;
00467 
00468         for (int i=-1; i < 2; i++) {
00469                 for (int j=-1; j < 2; j++) {
00470                         int x = (int)(gpos.v[0] + i);
00471                         int y = (((int)gpos.v[1] + j) * gridwidth);
00472                         int ind = x + y;
00473                         if (x < 0 || y < 0 || ind >= gridmax)
00474                                 continue;
00475                         vector<vec3> list = grid[ind];
00476                         for (int k=0; k < list.size(); k++) {
00477                                 if (!distanceOkay(pos, (list[k]))) {
00478                                         if (lastones == NULL) 
00479                                                 return pos.dist(list[k]);
00480                                         bool cont = false;
00481                                         for (int l=0; l < lastones->size(); l++) {
00482                                                 if (list[k][0] == lastones->_Get_container()[l].v[0] &&
00483                                                         list[k][1] == lastones->_Get_container()[l].v[1]) {
00484                                                                 cont = true;
00485                                                                 break;
00486                                                 }
00487                                         }
00488                                         if (cont) continue;
00489 
00490                                         return pos.dist(list[k]);
00491                                 } else if ((dis = pos.dist(list[k])) < minDist) {
00492                                         minDist = dis;
00493                                 }
00494                         }
00495                 }
00496         }
00497         return minDist;
00498 }
00499 
00500 bool RenderWidget::distanceOkay(vec3 from, vec3 to)
00501 {
00502         return from.dist(to) > d_test;
00503 }
00504 
00505 vec3 RenderWidget::getNextEulerPoint(vec3 sample_point, bool backward)
00506 {
00507         float signed_dt = backward ? -dt : dt;
00508         int ind = (int)(sample_point.v[0]) + ((int)sample_point.v[1] * textureWidth);
00509         if (ind >= textureWidth * textureHeight) 
00510                 throw std::exception("Index out of bounds");
00511         vec3 dir((xdata)[ind] - 0.5, ((ydata)[ind] - 0.5));
00512         // break at undef values (box)
00513         if (!(dir[0] > -100 && dir[0] < 100 && dir[1] > -100 && dir[1] < 100))
00514                 throw std::exception("Hopefully INDEF error");
00515         vec3 ret = sample_point + (!dir * signed_dt);
00516         return ret;
00517 }
00518 
00519 vec3 RenderWidget::getNextRungeKutta2Point(vec3 sample_point, bool backward)
00520 {
00521         float signed_dt = backward ? -dt : dt;
00522         int ind = (int)(sample_point[0]) + ((int)sample_point[1]) * textureWidth;
00523         if (ind >= textureWidth * textureHeight) 
00524                 throw std::exception("Index out of bounds");
00525         vec3 dir((xdata)[ind] - 0.5, ((ydata)[ind] - 0.5));
00526         // break at undef values (box)
00527         if (!(dir[0] > -100 && dir[0] < 100 && dir[1] > -100 && dir[1] < 100))
00528                 throw std::exception("Hopefully INDEF error");
00529         vec3 step1 = sample_point + (!dir * signed_dt / 2.f);
00530 
00531         ind = (int)(step1[0]) + ((int)step1[1]) * textureWidth;
00532         if (ind >= textureWidth * textureHeight) 
00533                 throw std::exception("Index out of bounds");
00534         vec3 newdir((xdata)[ind] - 0.5, ((ydata)[ind] - 0.5));
00535         // break at undef values (box)
00536         if (!(newdir[0] > -100 && newdir[0] < 100 && newdir[1] > -100 && newdir[1] < 100))
00537                 throw std::exception("Hopefully INDEF error");
00538         vec3 ret = sample_point + (!newdir * signed_dt);
00539 
00540         return ret;
00541 }
00542 
00543 vec3 RenderWidget::getNextRungeKutta4Point(vec3 sample_point, bool backward)
00544 {
00545         float signed_dt = backward ? -dt : dt;
00546         int ind = (int)(sample_point[0]) + ((int)sample_point[1]) * textureWidth;
00547         if (ind >= textureWidth * textureHeight) 
00548                 throw std::exception("Index out of bounds");
00549         vec3 adir((xdata)[ind] - 0.5, ((ydata)[ind] - 0.5));
00550         // break at undef values (box)
00551         if (!(adir[0] > -100 && adir[0] < 100 && adir[1] > -100 && adir[1] < 100))
00552                 throw std::exception("Hopefully INDEF error");
00553         vec3 a = (!adir * signed_dt);
00554 
00555         vec3 step1 = sample_point + a / 2.f;
00556         ind = (int)(step1[0]) + ((int)step1[1]) * textureWidth;
00557         if (ind >= textureWidth * textureHeight) 
00558                 throw std::exception("Index out of bounds");
00559         vec3 bdir((xdata)[ind] - 0.5, ((ydata)[ind] - 0.5));
00560         // break at undef values (box)
00561         if (!(bdir[0] > -100 && bdir[0] < 100 && bdir[1] > -100 && bdir[1] < 100))
00562                 throw std::exception("Hopefully INDEF error");
00563         vec3 b = (!bdir * signed_dt);
00564 
00565         vec3 step2 = sample_point + b / 2.f;
00566         ind = (int)(step2[0]) + ((int)step2[1]) * textureWidth;
00567         if (ind >= textureWidth * textureHeight) 
00568                 throw std::exception("Index out of bounds");
00569         vec3 cdir((xdata)[ind] - 0.5, ((ydata)[ind] - 0.5));
00570         // break at undef values (box)
00571         if (!(cdir[0] > -100 && cdir[0] < 100 && cdir[1] > -100 && cdir[1] < 100))
00572                 throw std::exception("Hopefully INDEF error");
00573         vec3 c = (!cdir * signed_dt);
00574 
00575         vec3 step3 = sample_point + c;
00576         ind = (int)(step3[0]) + ((int)step3[1]) * textureWidth;
00577         if (ind >= textureWidth * textureHeight) 
00578                 throw std::exception("Index out of bounds");
00579         vec3 ddir((xdata)[ind] - 0.5, ((ydata)[ind] - 0.5));
00580         // break at undef values (box)
00581         if (!(ddir[0] > -100 && ddir[0] < 100 && ddir[1] > -100 && ddir[1] < 100))
00582                 throw std::exception("Hopefully INDEF error");
00583         vec3 d = (!ddir * signed_dt);
00584 
00585         vec3 ret = sample_point + (a + b * 2.f + c * 2.f + d) / 6.f;
00586 
00587         return ret;
00588 }
00589 
00590 void RenderWidget::printGLError()
00591 {
00592         GLenum glError = GL_NO_ERROR;
00593         glError = glGetError();
00594         if (glError != GL_NO_ERROR)
00595         {
00596                 std::cerr<<"GLError: "<<gluErrorString(glError)<<std::endl;
00597         } 
00598 }
00599 
00600 void RenderWidget::loadData(std::string filename)
00601 {
00602         FlowData* dataset = new FlowData();
00603         //load a dataset, an example path is given
00604         bool result = dataset->loadDataset(filename,false);
00605         //exit if the loading was not successful
00606         if (!result) { std::cout << "Loading failed" << std::endl; return;}
00607         
00608 
00609         loadChannels(dataset);
00610         emit dataLoaded(channelCount-2);
00611         //memory clean up
00612         delete dataset;
00613 
00614 }
00615 
00616 void RenderWidget::initializeGL()
00617 {
00618         GLint num;
00619         glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &num);
00620         printGLError();
00621         std::cout << "max num of image units: " << num << std::endl;
00622 
00623         disp_lists = new GLuint[2];
00624 
00625         initGlew();
00626         loadData("data/hurricane_p_tc_singletime10");
00627 
00628         Shader::get_errors();
00629 
00630         // Load and compile Shader files
00631         simple = new Shader("Shader/simple");
00632 
00633         if (!simple) {
00634                 cerr << "Could not compile simple shader program." << endl;
00635         }
00636 
00637         arrows = new Shader("Shader/arrows", true, GL_POINTS, GL_TRIANGLE_STRIP, 10);
00638 
00639         if (!arrows) {
00640                 cerr << "Could not compile arrow shader program." << endl;
00641         }
00642 
00643         slines = new Shader("Shader/streamlines");
00644 
00645         if (!slines)
00646                 cerr << "Could not compile streamline shader program." << endl;
00647 
00648         sltexture = new Shader("Shader/sltexture");
00649 
00650         if (!sltexture)
00651                 cerr << "Could not compile streamline texture shader." << endl;
00652 
00653         shaders.append(simple);
00654         shaders.append(arrows);
00655         shaders.append(slines);
00656         shaders.append(sltexture);
00657 
00658         slines->bind();
00659         glUniform1i(slines->get_uniform_location("data"), UNIT_DATA);
00660         glUniform1i(slines->get_uniform_location("transfer_function"), UNIT_TRANSFER);
00661         slines->unbind();
00662         
00663         arrows->bind();
00664         glUniform1i(arrows->get_uniform_location("data"), UNIT_DATA);
00665         glUniform1i(arrows->get_uniform_location("xchannel"), UNIT_X);
00666         glUniform1i(arrows->get_uniform_location("ychannel"), UNIT_Y);
00667         glUniform1i(arrows->get_uniform_location("transfer_function"), UNIT_TRANSFER);
00668         glUniform1f(arrows->get_uniform_location("size"),arrowSize);
00669         arrows->unbind();
00670         
00671         simple->bind();
00672         glUniform1i(simple->get_uniform_location("data"), UNIT_DATA);
00673         glUniform1i(simple->get_uniform_location("transfer_function"), UNIT_TRANSFER);
00674         simple->unbind();
00675 
00676         sltexture->bind();
00677         glUniform1i(sltexture->get_uniform_location("transfer_function"), UNIT_TRANSFER);
00678         sltexture->unbind();
00679         
00680 
00681         layers.append(new LayerRenderable());
00682 
00683         glEnable( GL_LINE_SMOOTH );
00684         glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00685 
00686         glEnable (GL_BLEND);
00687         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00688 
00689         glGenTextures(1,&testTransferTexture);
00690 
00691         settingsEmitSliderValue(0);
00692         settingsEmitSliderValue(1);
00693         settingsEmitSliderValue(2);
00694         settingsEmitSliderValue(3);
00695         settingsEmitSliderValue(4);
00696         settingsEmitSliderValue(5);
00697 }
00698 
00699 void RenderWidget::initArrows(int n, float aspect)
00700 {
00701         float w = (aspect > 1.f) ? 1.f : aspect;
00702         float h = (aspect > 1.f) ? 1.f/aspect : 1.f;
00703 
00704         float x = -w;
00705         float y = -h;
00706 
00707         float widthX = (int)(w * (float)n);
00708         float widthY = (int)(h * (float)n);
00709 
00710         disp_lists[0] = glGenLists(1);
00711 
00712         glNewList(disp_lists[0], GL_COMPILE);
00713         glColor4f(1.0,1.0,1.0,1.0);
00714         glBegin(GL_POINTS);
00715 
00716         float diffX = 2.f*w/(widthX+2);
00717         float diffY = 2.f*h/(widthY+2);
00718 
00719         for(int i=1; i <=widthX+1; i++)
00720                 for(int j=1; j<=widthY+1; j++)
00721                 {
00722                         glVertex2f(x+(float)i*diffX, y+(float)j*diffY);
00723                 }
00724 
00725         glEnd();
00726         glEndList();
00727 }
00728 
00729 void RenderWidget::generateNormalStreamlineList()
00730 {
00731         float aspect = (float)textureWidth/(float)textureHeight;
00732 
00733         float w = (aspect > 1.f) ? 1.f : aspect;
00734         float h = (aspect > 1.f) ? 1.f/aspect : 1.f;
00735 
00736         if (0 != disp_lists[1])
00737                 glDeleteLists(disp_lists[1], 1);
00738         disp_lists[1] = glGenLists(1);
00739 
00740         glNewList(disp_lists[1], GL_COMPILE);
00741 
00742         for (int i=0; i < streamlines.size(); i++) {
00743                 glBegin(GL_LINE_STRIP);
00744                 vec3 p;
00745                 vector<vec3> points = streamlines[i]->getSamplePoints(true);
00746                 for (int j = points.size() - 1; j >= 0; j--) {
00747                         p = (
00748                                 vec3(points[j][0] / (float)textureWidth, 
00749                                 points[j][1] / (float)textureHeight)
00750                                 - vec3(0.5, 0.5)) * 2.f;
00751                         glVertex2f(p[0] * w, p[1] * h);
00752                 }
00753 
00754                 p = (
00755                         vec3(streamlines[i]->getSeedPoint()[0] / (float)textureWidth, 
00756                         streamlines[i]->getSeedPoint()[1] / (float)textureHeight)
00757                         - vec3(0.5, 0.5)
00758                         ) * 2.f;
00759                 glVertex2f(p[0] * w, p[1] * h);
00760 
00761                 points = streamlines[i]->getSamplePoints(false);
00762                 for (int j=0; j < points.size(); j++) {
00763                         p = (
00764                                 vec3(points[j][0] / (float)textureWidth, 
00765                                 points[j][1] / (float)textureHeight)
00766                                 - vec3(0.5, 0.5)) * 2.f;
00767                         glVertex2f(p[0] * w, p[1] * h);
00768                 }
00769                 
00770                 glEnd();
00771         }
00772 
00773         glEndList();
00774 }
00775 
00776 void RenderWidget::generateTaperingStreamlineList()
00777 {
00778         float aspect = (float)textureWidth/(float)textureHeight;
00779 
00780         float w = (aspect > 1.f) ? 1.f : aspect;
00781         float h = (aspect > 1.f) ? 1.f/aspect : 1.f;
00782 
00783         if (0 != disp_lists[1])
00784                 glDeleteLists(disp_lists[1], 1);
00785         disp_lists[1] = glGenLists(1);
00786 
00787         glNewList(disp_lists[1], GL_COMPILE);
00788 
00789         float line_width = 3.f;
00790         
00791         for (int i=0; i < streamlines.size(); i++) {
00792                 glLineWidth(line_width * streamlines[i]->getSeedPointThickness());
00793                 glBegin(GL_LINES);
00794                 vec3 p = (
00795                         vec3(streamlines[i]->getSeedPoint()[0] / (float)textureWidth, 
00796                         streamlines[i]->getSeedPoint()[1] / (float)textureHeight)
00797                         - vec3(0.5, 0.5)
00798                         ) * 2.f;
00799                 glVertex2f(p[0] * w, p[1] * h);
00800                 vector<vec3> points = streamlines[i]->getSamplePoints(false);
00801                 vector<float> thicknessess = streamlines[i]->getSamplePointThicknesses(false);
00802                 for (int j=0; j < points.size(); j++) {
00803                         p = (
00804                                 vec3(points[j][0] / (float)textureWidth, 
00805                                 points[j][1] / (float)textureHeight)
00806                                 - vec3(0.5, 0.5)) * 2.f;
00807                         glVertex2f(p[0] * w, p[1] * h);
00808 
00809                         glEnd();
00810                         glLineWidth(line_width * thicknessess[j]);
00811                         glBegin(GL_LINES);
00812 
00813                         glVertex2f(p[0] * w, p[1] * h);
00814                 }
00815                 glEnd();
00816 
00817                 glLineWidth(line_width * streamlines[i]->getSeedPointThickness());
00818                 glBegin(GL_LINES);
00819                 p = (
00820                         vec3(streamlines[i]->getSeedPoint()[0] / (float)textureWidth, 
00821                         streamlines[i]->getSeedPoint()[1] / (float)textureHeight)
00822                         - vec3(0.5, 0.5)
00823                         ) * 2.f;
00824                 glVertex2f(p[0] * w, p[1] * h);
00825                 points = streamlines[i]->getSamplePoints(true);
00826                 thicknessess = streamlines[i]->getSamplePointThicknesses(true);
00827                 for (int j=0; j < points.size(); j++) {
00828                         p = (
00829                                 vec3(points[j][0] / (float)textureWidth, 
00830                                 points[j][1] / (float)textureHeight)
00831                                 - vec3(0.5, 0.5)) * 2.f;
00832                         glVertex2f(p[0] * w, p[1] * h);
00833 
00834                         glEnd();
00835                         glLineWidth(line_width * thicknessess[j]);
00836                         glBegin(GL_LINES);
00837 
00838                         glVertex2f(p[0] * w, p[1] * h);
00839                 }
00840                 glEnd();
00841         }
00842         glLineWidth(1.f);
00843 
00844         glEndList();
00845 }
00846 
00847 void RenderWidget::generateGlyphStreamlineList()
00848 {
00849         float factor = (float)textureSize/100.f;
00850         int step = (int)(5.f * factor);
00851 
00852         float aspect = (float)textureWidth/(float)textureHeight;
00853 
00854         float w = (aspect > 1.f) ? 1.f : aspect;
00855         float h = (aspect > 1.f) ? 1.f/aspect : 1.f;
00856 
00857         if (0 != disp_lists[1])
00858                 glDeleteLists(disp_lists[1], 1);
00859         disp_lists[1] = glGenLists(1);
00860 
00861         glNewList(disp_lists[1], GL_COMPILE);
00862 
00863         for (int i=0; i < streamlines.size(); i++) {
00864                 glBegin(GL_POINTS);
00865                 vec3 p = (
00866                         vec3(streamlines[i]->getSeedPoint()[0] / (float)textureWidth, 
00867                         streamlines[i]->getSeedPoint()[1] / (float)textureHeight)
00868                         - vec3(0.5, 0.5)
00869                         ) * 2.f;
00870                 glVertex2f(p[0] * w, p[1] * h);
00871 
00872                 vector<vec3> points = streamlines[i]->getSamplePoints(false);
00873                 for (int j=0; j < points.size(); j += step) {
00874                         p = (
00875                                 vec3(points[j][0] / (float)textureWidth, 
00876                                 points[j][1] / (float)textureHeight)
00877                                 - vec3(0.5, 0.5)) * 2.f;
00878                         glVertex2f(p[0] * w, p[1] * h);
00879                 }
00880 
00881                 points = streamlines[i]->getSamplePoints(true);
00882                 for (int j=0; j < points.size(); j += step) {
00883                         p = (
00884                                 vec3(points[j][0] / (float)textureWidth, 
00885                                 points[j][1] / (float)textureHeight)
00886                                 - vec3(0.5, 0.5)) * 2.f;
00887                         glVertex2f(p[0] * w, p[1] * h);
00888                 }
00889                 glEnd();
00890         }
00891 
00892         glEndList();
00893 }
00894 
00895 void RenderWidget::generateTextureStreamlineList()
00896 {
00897         float aspect = (float)textureWidth/(float)textureHeight;
00898 
00899         float w = (aspect > 1.f) ? 1.f : aspect;
00900         float h = (aspect > 1.f) ? 1.f/aspect : 1.f;
00901 
00902         if (0 != disp_lists[1])
00903                 glDeleteLists(disp_lists[1], 1);
00904         disp_lists[1] = glGenLists(1);
00905 
00906         glNewList(disp_lists[1], GL_COMPILE);
00907 
00908         for (int i=0; i < streamlines.size(); i++) {
00909                 int rank = 0;
00910                 vec3 p;
00911                 float intensity = 1.f;
00912 
00913                 glBegin(GL_LINE_STRIP);
00914                 vector<vec3> points = streamlines[i]->getSamplePoints(true);
00915                 for (int j = points.size() - 1; j >= 0; j--) {
00916                         p = (
00917                                 vec3(points[j][0] / (float)textureWidth, 
00918                                 points[j][1] / (float)textureHeight)
00919                                 - vec3(0.5, 0.5)) * 2.f;
00920                         intensity = getSLIntensityForRank(rank, 1);
00921                         glColor3f(intensity, intensity, intensity);
00922                         glVertex2f(p[0] * w, p[1] * h);
00923                         rank++;
00924                 }
00925 
00926                 p = (
00927                         vec3(streamlines[i]->getSeedPoint()[0] / (float)textureWidth, 
00928                         streamlines[i]->getSeedPoint()[1] / (float)textureHeight)
00929                         - vec3(0.5, 0.5)
00930                         ) * 2.f;
00931                 intensity = getSLIntensityForRank(rank, 1);
00932                 glColor3f(intensity, intensity, intensity);
00933                 glVertex2f(p[0] * w, p[1] * h);
00934                 rank++;
00935 
00936                 points = streamlines[i]->getSamplePoints(false);
00937                 for (int j=0; j < points.size(); j++) {
00938                         p = (
00939                                 vec3(points[j][0] / (float)textureWidth, 
00940                                 points[j][1] / (float)textureHeight)
00941                                 - vec3(0.5, 0.5)) * 2.f;
00942                         intensity = getSLIntensityForRank(rank, 1);
00943                         glColor3f(intensity, intensity, intensity);
00944                         glVertex2f(p[0] * w, p[1] * h);
00945                         rank++;
00946                 }
00947                 glEnd();
00948         }
00949 
00950         glEndList();
00951 }
00952 
00953 float RenderWidget::getSLIntensityForRank(int rank, int function_type)
00954 {
00955         switch (function_type) {
00956         case 0:
00957                 return (1.f + sin(2.f * PI * (float)rank / (float)sl_num_samples) ) / 2.f;
00958         case 1:
00959                 return (float)(rank % sl_num_samples) / (float)(sl_num_samples - 1);
00960         }
00961         return 0.f;
00962 }
00963 
00964 void RenderWidget::resizeGL(int w, int h)
00965 {
00966         glViewport(0,0,w,h);
00967         glMatrixMode(GL_PROJECTION);
00968         glLoadIdentity();
00969         glOrtho(-1,1,-1,1,1,100);
00970         glMatrixMode(GL_MODELVIEW);
00971         glLoadIdentity();
00972 }
00973 
00974 void RenderWidget::paintGL()
00975 {
00976         glClear(GL_COLOR_BUFFER_BIT);
00977         //glEnable(GL_TEXTURE);
00978         glEnable(GL_TEXTURE_2D);
00979         glLoadIdentity();
00980         gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
00981 
00982         for(int i=0; i< layers.count(); i++)
00983                 layers[i]->draw(textures, shaders, disp_lists,(float)textureWidth/(float)textureHeight, 
00984                                                 streamline_mode == GLYPH, streamline_mode == TEXTURE);
00985 }
00986 
00987 void RenderWidget::initGlew()
00988 {
00989         // Initialize GLEW
00990         std::cout << "- Initializing GLEW ..." << std::endl;
00991          GLenum err = glewInit();
00992         if (err != GLEW_OK)
00993         {
00994                 // glewInit failed, something is seriously wrong
00995                 std::cerr << "Error initializing GLEW: " << glewGetErrorString(err) << std::endl;
00996         } 
00997         
00998         std::cout << "- GLEW initialized." << std::endl << std::endl;
00999 
01000 }
01001 
01002 int RenderWidget::heightForWidth(int w) const
01003 {
01004         return w;
01005 }
01006 
01007 void RenderWidget::layerChannelChanged(int channel, int layer)
01008 {
01009         
01010         if(layer < layers.count())
01011                 layers[layer]->setChannel((channel == -1)?channel:channel+2);
01012 
01013         updateGL();
01014 }
01015 
01016 void RenderWidget::layerTypeChanged(int type, int layer)
01017 {
01018         if(layer < layers.count())
01019                 layers[layer]->setType(type);
01020         updateGL();
01021 
01022 }
01023 
01024 void RenderWidget::layerTransferImageChanged(const QImage& image, int layer)
01025 {
01026         if(layer < layers.count())
01027                 layers[layer]->setTransferFunction(image);
01028 
01029         updateGL();
01030 }
01031 
01032 void RenderWidget::layerAdd(int layer)  
01033 {
01034         layers.append(new LayerRenderable());
01035         
01036         updateGL();
01037 }
01038 
01039 void RenderWidget::layerMove(int layer, int newPos) //checks done in gui.but...
01040 {
01041         LayerRenderable* l = layers[layer];
01042         
01043         layers.remove(layer);
01044         layers.insert(newPos,l);
01045         
01046         updateGL();
01047 }
01048 
01049 void RenderWidget::layerRemove(int layer) //checks done in gui.but...
01050 {
01051         LayerRenderable* l = layers[layer];
01052         layers.remove(layer);
01053         delete l;
01054 
01055         updateGL();
01056 }
01057 
01058 void RenderWidget::settingsSliderChanged(int value, int slider)
01059 {
01060         //std::cout << "Slider "<<slider <<" changed to "<<value << std::endl;
01061 
01062         //Reihenfolge wie im GUI
01063         switch(slider)
01064         {
01065         case 0:         //Arrows Count
01066                 glDeleteLists(disp_lists[0], 1);
01067                 arrowCount = value/2+10;
01068                 initArrows(arrowCount,(float)textureWidth/(float)textureHeight);
01069                 break;
01070 
01071         case 1:         //Arrows Size
01072                 shaders[SHADER_ARROWS]->bind();
01073                 arrowSize = (float)value/25.f+0.5f;
01074                 glUniform1f(shaders[SHADER_ARROWS]->get_uniform_location("size"),arrowSize);
01075                 shaders[SHADER_ARROWS]->unbind();
01076                 break;
01077 
01078         case 2:         //Texture Resolution
01079                 textureSize = 100+value*10;
01080                 break;
01081 
01082         case 3:         //Streamlines dsep
01083                 d_sep_val = min((float)value / 10.f + 0.1, 10) / 100.f;
01084                 break;
01085 
01086         case 4:         //Streamlines dtest
01087                 d_test_val = min((float)value / 100.f + 0.05, 0.95);
01088                 break;
01089 
01090         case 5:         //Streamlines dt
01091                 dt = min((float)value / 100.f + 0.05, 1);
01092                 break;
01093         }
01094 
01095         updateGL();
01096 }
01097 
01098 void RenderWidget::settingsEmitSliderValue(int slider)
01099 {
01100         std::cout << "Renderer emit slider " << slider << std::endl;
01101         switch(slider)
01102         {
01103         case 0:
01104                 emit emitSettingValues((arrowCount-10)*2,0);
01105                 break;
01106                 
01107         case 1:
01108                 emit emitSettingValues((int)((arrowSize-0.5f)*25.f),1);
01109                 break;
01110 
01111         case 2:
01112                 emit emitSettingValues((int)( ((float)textureSize - 100.0) / 10.0 ),2);
01113                 break;
01114 
01115         case 3:         //Streamlines dsep
01116                 emit emitSettingValues(min((int)(d_sep_val * 1000), 100), slider);
01117                 break;
01118 
01119         case 4:         //Streamlines dtest
01120                 emit emitSettingValues((int)min((d_test_val - 0.05f) * 1000.f / 9.f, 100), slider);
01121                 break;
01122 
01123         case 5:         //Streamlines dt
01124                 emit emitSettingValues((int)min((dt - 0.05f) * 10000.f / 95.f, 100), slider);
01125                 break;
01126         }
01127 }
01128 
01129 void RenderWidget::settingsSLModeChanged(int value)
01130 {
01131         std::cout << "SLMode changed to "<< value << std::endl;
01132 
01133         switch(value)
01134         {
01135         case 0:         //standard
01136                 streamline_mode = NORMAL;
01137                 generateNormalStreamlineList();
01138                 break;
01139 
01140         case 1:         //tapering
01141                 streamline_mode = TAPERING;
01142                 generateTaperingStreamlineList();
01143                 break;
01144 
01145         case 2:         //glyph
01146                 streamline_mode = GLYPH;
01147                 generateGlyphStreamlineList();
01148                 break;
01149         case 3:         //texture
01150                 streamline_mode = TEXTURE;
01151                 generateTextureStreamlineList();
01152                 break;
01153         }
01154 
01155         updateGL();
01156 }
01157 
01158 
01159 void RenderWidget::settingsSLCompute()
01160 {
01161         std::cout << "SLCompute clicked" << std::endl;
01162 
01163         computeStreamlines();
01164 
01165         updateGL();
01166 }
01167 
01168 void RenderWidget::settingsSLInverpolationChanged(int value)
01169 {
01170         std::cout << "SLInterpolation changed to " << value << std::endl;
01171 
01172         switch (value) {
01173         case 0:
01174                 integration_mode = EULER;
01175                 break;
01176         case 1:
01177                 integration_mode = RK2;
01178                 break;
01179         case 2:
01180                 integration_mode = RK4;
01181                 break;
01182         }
01183 
01184         computeStreamlines();
01185 
01186         updateGL();
01187 }
01188 
01189 void RenderWidget::loadDataFile() {
01190         QString fileName = QFileDialog::getOpenFileName(this, tr("Open Input File"), ".", tr("Data Files (*.dat)"));
01191 
01192         fileName.remove(".dat");                //.dat wegmachen
01193 
01194         loadData(fileName.toStdString());
01195         
01196         updateGL();
01197 }
01198 
 All Classes Functions Variables Friends