FlowVis 1.0
|
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