00001 #include <glew.h>
00002
00003 #include "flowvis_canvas.h"
00004
00005
00006 #include <wx/dcclient.h>
00007 #include <wx/image.h>
00008
00009 #include <algorithm>
00010 #include <stdexcept>
00011
00012 BEGIN_EVENT_TABLE(FlowVisCanvas, wxGLCanvas)
00013 EVT_PAINT(FlowVisCanvas::OnPaint)
00014 EVT_SIZE(FlowVisCanvas::OnSize)
00015 EVT_ERASE_BACKGROUND(FlowVisCanvas::OnEraseBackground)
00016 END_EVENT_TABLE()
00017
00018 namespace
00019 {
00020 int attrib_list[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
00021
00022 std::pair<float, float> ComputeScaleFactors(float a1, float a2)
00023 {
00024 const float x = a2 / a1;
00025 if (x > 1.0f) return std::make_pair(1.0f, 1.0f / x);
00026 else return std::make_pair(x, 1.0f);
00027 }
00028 }
00029
00030 FlowVisCanvas::FlowVisCanvas(wxWindow *parent, wxWindowID id)
00031 : wxGLCanvas(parent, id, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE, wxGLCanvasName, attrib_list)
00032 , m_mode(FVC_SCREEN)
00033 , m_glstatus(GLS_INIT_PENDING)
00034 , m_data(0)
00035 , m_background_set(-1)
00036 , m_plot_background(true)
00037 {
00038 if (!CheckGL()) throw std::runtime_error("OpenGL Initialization failed");
00039
00040 LoadGlyphTexture();
00041
00042 m_program = std::auto_ptr<FlowVisProgram>(new FlowVisProgram("flow_prog"));
00043 LoadArrowTexture();
00044
00045 m_arrow_data.nr_x = 10;
00046 m_arrow_data.nr_y = 10;
00047 m_arrow_data.plot = false;
00048 }
00049
00050 void FlowVisCanvas::SetData(std::auto_ptr<FlowVisData> data)
00051 {
00052 if(!data.get()) return;
00053 m_data = data;
00054 m_background_set = 0;
00055
00056 InitTextures();
00057 Render_ValueInter(0);
00058 Render_ValueInter(1);
00059 SetArrows(30, 30);
00060 Prepare_Streamlines();
00061
00062 Refresh();
00063 }
00064
00065 void FlowVisCanvas::OnPaint(wxPaintEvent &event )
00066 {
00067 wxPaintDC dc(this);
00068 if (!CheckGL()) return;
00069
00070 GetClientSize(&m_viewport_width, &m_viewport_height);
00071
00072 m_line_base_thickness = 2.0f;
00073
00074 Render();
00075 SwapBuffers();
00076 }
00077
00078 void FlowVisCanvas::OnSize(wxSizeEvent &event)
00079 {
00080 wxGLCanvas::OnSize(event);
00081
00082 Update();
00083 }
00084
00085 void FlowVisCanvas::OnEraseBackground(wxEraseEvent &event)
00086 {
00087
00088 }
00089
00090 void FlowVisCanvas::LoadArrowTexture()
00091 {
00092 wxImage img;
00093 img.AddHandler(new wxPNGHandler());
00094 if(img.LoadFile(wxT("images/arrow.png")))
00095 {
00096 unsigned char *orig_data = img.GetData();
00097
00098 std::vector<unsigned char> data(16 * 16 * 4);
00099
00100 for(int i = 0; i < 16 * 16; i++)
00101 {
00102 data[i * 4] = orig_data[i * 3];
00103 data[i * 4 + 1] = orig_data[i * 3 + 1];
00104 data[i * 4 + 2] = orig_data[i * 3 + 2];
00105 data[i * 4 + 3] = orig_data[i * 3];
00106 }
00107
00108 glGenTextures(1, &(m_arrow_data.arrow_texture));
00109 glBindTexture(GL_TEXTURE_2D, m_arrow_data.arrow_texture);
00110 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00114
00115 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(data[0]));
00116 }else
00117 {
00118 throw std::runtime_error("Could not load arrow texture from filesystem!");
00119 }
00120 }
00121
00122 void FlowVisCanvas::LoadGlyphTexture()
00123 {
00124 wxImage img;
00125 img.AddHandler(new wxPNGHandler());
00126 if(img.LoadFile(wxT("images/glyph2.png")))
00127 {
00128 unsigned char *orig_data = img.GetData();
00129
00130 int h = img.GetHeight();
00131 int w = img.GetWidth();
00132
00133 std::vector<unsigned char> data(h * w * 4);
00134
00135 for(int i = 0; i < h * w; i++)
00136 {
00137 data[i * 4] = orig_data[i * 3];
00138 data[i * 4 + 1] = orig_data[i * 3 + 1];
00139 data[i * 4 + 2] = orig_data[i * 3 + 2];
00140 data[i * 4 + 3] = orig_data[i * 3];
00141 }
00142
00143 glGenTextures(1, &(m_sl_settings.glyph_texture));
00144 glBindTexture(GL_TEXTURE_2D, m_sl_settings.glyph_texture);
00145 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00146 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00147 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00148 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00149
00150 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, h, w, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(data[0]));
00151 }else
00152 {
00153 throw std::runtime_error("Could not load glyph texture from filesystem!");
00154 }
00155 }
00156
00157 namespace
00158 {
00159 struct TEST_S
00160 {
00161 TEST_S(float x_, float y_, int grad_ = -1)
00162 : x(x_)
00163 , y(y_)
00164 , grad(grad_)
00165 {
00166 }
00167 float x;
00168 float y;
00169 int grad;
00170 };
00171 }
00172
00173 void FlowVisCanvas::Render()
00174 {
00175 std::vector<TEST_S> test;
00176 float pi = 3.14159265f;
00177
00178 float test1 = AngleR(vec3(0, 1));
00179
00180 for(float i = -1; i <= 1; i+= 0.1f)
00181 {
00182 for(float j = -1; j < 1; j+=0.1f)
00183 {
00184 test.push_back(TEST_S(i, j, AngleR(vec3(i, j)) / pi * 180));
00185 }
00186 }
00187
00188 if(m_data.get())
00189 {
00190 Render_ToScreen();
00191 }
00192 }
00193
00194 void FlowVisCanvas::Render_Background()
00195 {
00196 glEnable(GL_TEXTURE_2D);
00197
00198 glBindTexture(GL_TEXTURE_2D, m_tex_background[m_background_set]);
00199
00200 m_program->SetMode(FlowVisProgram::M_BG_INTER);
00201 m_program->SetBGDataTexture(m_tex_background[m_background_set]);
00202 m_program->SetTransferFunctionTexture(m_tex_bg_trafu[m_background_set]);
00203 m_program->Use();
00204
00205 glBegin(GL_QUADS);
00206 glTexCoord2f(0, 0);
00207 glVertex2f(-1, -1);
00208 glTexCoord2f(1, 0);
00209 glVertex2f(1, -1);
00210 glTexCoord2f(1, 1);
00211 glVertex2f(1, 1);
00212 glTexCoord2f(0, 1);
00213 glVertex2f(-1, 1);
00214 glEnd();
00215
00216 m_program->Stop();
00217
00218 glDisable(GL_TEXTURE_2D);
00219 }
00220
00221 void FlowVisCanvas::Render_Streamlines()
00222 {
00223 float w_max = -999999;
00224 float w_min = 999999;
00225
00226
00227 glPointSize( 8.0f );
00228 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
00229 glEnable( GL_POINT_SPRITE_ARB );
00230
00231 glEnable(GL_TEXTURE_2D);
00232
00233 m_program->SetMode(FlowVisProgram::M_TEXTURE_ROTATION);
00234 m_program->SetGlyphTexture(m_sl_settings.glyph_texture);
00235 m_program->Prepare();
00236 glBindTexture(GL_TEXTURE_2D, m_sl_settings.glyph_texture);
00237
00238 glDisable(GL_TEXTURE_2D);
00239
00240 Streamline::iterator last_point;
00241
00242 glEnable(GL_LINE_SMOOTH);
00243
00244 glColor3f(m_sl_settings.color.red,m_sl_settings.color.green,m_sl_settings.color.blue);
00245
00246 for(std::vector<Streamline>::iterator lines_iter = m_streamlines.begin();
00247 lines_iter != m_streamlines.end();
00248 ++lines_iter)
00249 {
00250 int i = 0;
00251 last_point = lines_iter->end();
00252 if(m_sl_settings.plot_tapering)
00253 glLineWidth(m_line_base_thickness * lines_iter->begin()->thickness);
00254 else
00255 glLineWidth(1.0f);
00256 glBegin(GL_LINE_STRIP);
00257 for(Streamline::iterator iter = lines_iter->begin();
00258 iter != lines_iter->end();
00259 ++iter)
00260 {
00261 if(m_sl_settings.plot_tapering && last_point != lines_iter->end())
00262 {
00263 if(last_point->thickness != iter->thickness)
00264 {
00265 glEnd();
00266 if(m_sl_settings.plot_tapering)
00267 glLineWidth(m_line_base_thickness * iter->thickness);
00268 glBegin(GL_LINE_STRIP);
00269 }
00270 glVertex2f(last_point->pos.x, last_point->pos.y);
00271 }
00272 glVertex2f(iter->pos.x, iter->pos.y);
00273 last_point = iter;
00274
00275 if((m_sl_settings.plot_glyphs) && !(i++ % (110 - m_sl_settings.glyph_density)))
00276 {
00277 glEnd();
00278
00279 glEnable(GL_TEXTURE_2D);
00280 m_program->Start();
00281
00282 float pi = 3.14159265f;
00283 float my_winkel = pi - AngleR(m_data->GetVelocityAt(iter->pos.x, iter->pos.y));
00284 if(my_winkel < 0)
00285 {
00286 my_winkel = 2 * pi + my_winkel;
00287 }
00288
00289 my_winkel = my_winkel / (2 * pi);
00290
00291
00292 glBegin(GL_POINTS);
00293 glColor4f(m_sl_settings.color.red,
00294 m_sl_settings.color.green,
00295 m_sl_settings.color.blue,
00296 my_winkel);
00297 glVertex2f(iter->pos.x, iter->pos.y);
00298 glColor3f(m_sl_settings.color.red,m_sl_settings.color.green,m_sl_settings.color.blue);
00299 glEnd();
00300 m_program->Stop();
00301
00302 glDisable(GL_TEXTURE_2D);
00303
00304 glBegin(GL_LINE_STRIP);
00305 }
00306 }
00307 glEnd();
00308 }
00309
00310 glDisable( GL_POINT_SPRITE_ARB );
00311
00312 glDisable(GL_LINE_SMOOTH);
00313 }
00314
00315 void FlowVisCanvas::Render_Arrows()
00316 {
00317
00318
00319
00320
00321
00322
00323 glEnable( GL_BLEND );
00324 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00325
00326
00327 glEnable(GL_TEXTURE_2D);
00328 glBindTexture(GL_TEXTURE_2D, m_arrow_data.arrow_texture);
00329
00330 glMatrixMode(GL_MODELVIEW);
00331
00332 float data_width = m_data->m_grid_max.v[0] - m_data->m_grid_min.v[0];
00333 float data_height = m_data->m_grid_max.v[1] - m_data->m_grid_min.v[1];
00334
00335 float aspect = static_cast<float> (m_viewport_width) / m_viewport_height;
00336 std::pair<float, float> scale = ComputeScaleFactors(aspect, static_cast<float> (data_width) / data_height);
00337
00338 float min_length = 99999;
00339 float max_length = -99999;
00340
00341 for(ArrowPoints_T::const_iterator citer = m_arrow_data.arrow_points.begin();
00342 citer != m_arrow_data.arrow_points.end();
00343 ++citer)
00344 {
00345 glPushMatrix();
00346
00347 float length = citer->length / m_data->m_max_velocity_length;
00348 glTranslatef(citer->x, citer->y, 0.0f);
00349 glScalef(1 / scale.first, 1 / scale.second, 1.0f);
00350 glRotatef(citer->rotation, 0.0f, 0.0f, 1.0f);
00351
00352 glColor3f(1.0f, 1.0f, 1.0f);
00353
00354 min_length = std::min(min_length, length);
00355 max_length = std::max(max_length, length);
00356
00357 glPushMatrix();
00358 glScalef(0.2f + 0.8f * length, 0.2f + 0.8f * length, 1.0f);
00359
00360 glBegin(GL_QUADS);
00361 glTexCoord2f(0.0f, 0.0f);
00362 glVertex2f(-0.04f, -0.04f);
00363 glTexCoord2f(1.0f, 0.0f);
00364 glVertex2f(0.04f, -0.04f);
00365 glTexCoord2f(1.0f, 1.0f);
00366 glVertex2f(0.04f, 0.04f);
00367 glTexCoord2f(0.0f, 1.0f);
00368 glVertex2f(-0.04f, 0.04f);
00369 glEnd();
00370
00371 glPopMatrix();
00372
00373 glPopMatrix();
00374 }
00375
00376 glDisable( GL_POINT_SPRITE_ARB );
00377
00378 glDisable(GL_TEXTURE_2D);
00379
00380
00381 }
00382
00383
00384 void FlowVisCanvas::Render_ToScreen()
00385 {
00386 glMatrixMode(GL_PROJECTION);
00387 glLoadIdentity();
00388 glMatrixMode(GL_MODELVIEW);
00389 glLoadIdentity();
00390
00391 glViewport(0, 0, m_viewport_width, m_viewport_height);
00392 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
00393 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00394
00395 float data_width = m_data->m_grid_max.v[0] - m_data->m_grid_min.v[0];
00396 float data_height = m_data->m_grid_max.v[1] - m_data->m_grid_min.v[1];
00397
00398 float aspect = static_cast<float> (m_viewport_width) / m_viewport_height;
00399 std::pair<float, float> scale = ComputeScaleFactors(aspect, static_cast<float> (data_width) / data_height);
00400 glScalef(scale.first, scale.second, 1.0f);
00401
00402 glEnable(GL_BLEND);
00403 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00404
00405 if(m_plot_background) Render_Background();
00406
00407 if(m_sl_settings.plot) Render_Streamlines();
00408
00409 if(m_arrow_data.plot) Render_Arrows();
00410 }
00411
00412 void FlowVisCanvas::Render_ValueInter(int set)
00413 {
00414 glMatrixMode(GL_PROJECTION);
00415 glLoadIdentity();
00416 glMatrixMode(GL_MODELVIEW);
00417 glLoadIdentity();
00418
00419 glEnable(GL_TEXTURE_2D);
00420
00421 int size = 512;
00422
00423 glViewport(0, 0, size, size);
00424 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
00425 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00426
00427
00428 glEnableClientState(GL_VERTEX_ARRAY);
00429 glEnableClientState(GL_COLOR_ARRAY);
00430
00431 VertexData_T vdata = m_data->GetVertexData();
00432 ColorData_T cdata = m_data->GetColorData(0, set);
00433 IndexData_T idata = m_data->GetIndexData();
00434
00435 glVertexPointer(2, GL_FLOAT, 0, &(vdata[0]));
00436 glColorPointer(3, GL_FLOAT, 0, &(cdata[0]));
00437 int cells = (m_data->GetWidth() - 1) * (m_data->GetHeight() - 1) * 4;
00438
00439 glDrawElements(GL_QUADS, cells, GL_UNSIGNED_INT, &(idata[0]));
00440
00441 glDisableClientState(GL_VERTEX_ARRAY);
00442 glDisableClientState(GL_COLOR_ARRAY);
00443
00444 glBindTexture(GL_TEXTURE_2D, m_tex_background[set]);
00445 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_FLOAT, NULL);
00446 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, size, size, 0);
00447 }
00448
00449 bool FlowVisCanvas::InitGL()
00450 {
00451 if (glewInit() != GLEW_NO_ERROR) return false;
00452
00453
00454 return true;
00455 }
00456
00457 bool FlowVisCanvas::CheckGL()
00458 {
00459 #ifndef __WXMOTIF__
00460 if (!GetContext()) return false;
00461 #endif
00462
00463 SetCurrent();
00464 if (m_glstatus == GLS_INIT_PENDING) m_glstatus = InitGL() ? GLS_OK : GLS_INIT_FAILED;
00465 if (m_glstatus != GLS_OK) return false;
00466 return true;
00467 }
00468
00469 void FlowVisCanvas::SetBackgroundSet(int set_nr)
00470 {
00471 m_background_set = set_nr;
00472 }
00473
00474 void FlowVisCanvas::InitTextures()
00475 {
00476
00477 for(unsigned int i = 0; i < m_tex_background.size(); i++)
00478 {
00479 glDeleteTextures(1, &m_tex_background[i]);
00480 }
00481
00482 m_tex_background.clear();
00483
00484 for(int i = 0; i < m_data->GetNrSets(); i++)
00485 {
00486 GLuint id;
00487 glGenTextures(1, &id);
00488 glBindTexture(GL_TEXTURE_2D, id);
00489 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00490 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00491 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00492
00493 m_tex_background.push_back(id);
00494 }
00495
00496
00497 for(unsigned int i = 0; i < m_tex_bg_trafu.size(); i++)
00498 {
00499 glDeleteTextures(1, &m_tex_bg_trafu[i]);
00500 }
00501
00502 m_tex_bg_trafu.clear();
00503
00504 for(int i = 0; i < m_data->GetNrSets(); i++)
00505 {
00506 GLuint id;
00507 glGenTextures(1, &id);
00508 glBindTexture(GL_TEXTURE_1D, id);
00509 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00510 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00511 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00512
00513 m_tex_bg_trafu.push_back(id);
00514 }
00515 }
00516
00517 void FlowVisCanvas::UpdateTransferFunction(TransferFunctionSampler *sampler, int set_to_update)
00518 {
00519 std::vector<float> data;
00520
00521
00522 data.push_back(0.0f);
00523 data.push_back(0.0f);
00524 data.push_back(0.0f);
00525 data.push_back(0.0f);
00526
00527 for (int i = 1; i < 4096; ++i) {
00528 const TransferFunctionSampler::Color c = sampler->MapDensity(i / 4095.0f);
00529 data.push_back(c.r);
00530 data.push_back(c.g);
00531 data.push_back(c.b);
00532 data.push_back(c.a);
00533 }
00534
00535 glBindTexture(GL_TEXTURE_1D, m_tex_bg_trafu[set_to_update]);
00536 glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 4096, 0, GL_RGBA, GL_FLOAT, &data[0]);
00537
00538 Refresh();
00539 }
00540
00541 void FlowVisCanvas::CreateEvenlySpacedArrows()
00542 {
00543
00544
00545 float space_x = 2.0f / m_arrow_data.nr_x;
00546 float space_y = 2.0f / m_arrow_data.nr_y;
00547 float x, y;
00548 vec3 velocity;
00549
00550 vec3 m_grid_size = m_data->m_grid_max - m_data->m_grid_min;
00551
00552 m_arrow_data.arrow_points.clear();
00553
00554 m_arrow_data.arrow_points.reserve(m_arrow_data.nr_x * m_arrow_data.nr_y);
00555
00556 for(int i = 0; i < m_arrow_data.nr_x; i++)
00557 {
00558 for(int j = 0; j < m_arrow_data.nr_y; j++)
00559 {
00560 x = space_x * i - 1 + space_x / 2;
00561 y = space_y * j - 1 + space_y / 2;
00562 velocity = m_data->GetVelocityAt(x, y);
00563 m_arrow_data.arrow_points.push_back(ArrowPoint(x,
00564 y,
00565 velocity));
00566 }
00567 }
00568 }
00569
00570 void FlowVisCanvas::SetArrows(int x, int y)
00571 {
00572 m_arrow_data.nr_x = x;
00573 m_arrow_data.nr_y = y;
00574 CreateEvenlySpacedArrows();
00575 Refresh();
00576 }
00577
00578 void FlowVisCanvas::SetArrowPlot(bool plot_arrows)
00579 {
00580 m_arrow_data.plot = plot_arrows;
00581 Refresh();
00582 }
00583
00584 void FlowVisCanvas::SetStreamlinePlot(bool plot_streamlines)
00585 {
00586 m_sl_settings.plot = plot_streamlines;
00587 }
00588
00589 void FlowVisCanvas::SetBackgroundPlot(bool plot_background)
00590 {
00591 m_plot_background = plot_background;
00592 Refresh();
00593 }
00594
00595 void FlowVisCanvas::Prepare_Streamlines()
00596 {
00597 const SL_Rectangle domain(-1.0f, -1.0f, 1.0f, 1.0f);
00598 const int maxiter = m_sl_algorithm.maxiter;
00599 const float stepsize = m_sl_algorithm.stepsize;
00600 const float dsep = m_sl_algorithm.dsep;
00601 const float dtest = m_sl_algorithm.dtest;
00602 const SLIterAlg alg = m_sl_algorithm.interploation;
00603 StreamlineGenerator sgl(domain, dsep, dtest, stepsize, maxiter, VelocityFunctor(m_data.get()), alg);
00604 m_streamlines.clear();
00605 m_streamlines = sgl.GetStreamlines();
00606 }
00607
00608 void FlowVisCanvas::SetLineColor(wxColour new_color)
00609 {
00610 m_sl_settings.color = new_color;
00611 }
00612
00613 void FlowVisCanvas::SetLineTapering(bool plot_tapering)
00614 {
00615 m_sl_settings.plot_tapering = plot_tapering;
00616 }
00617
00618 void FlowVisCanvas::SetLineGlyphs(bool plot_glyphs)
00619 {
00620 m_sl_settings.plot_glyphs = plot_glyphs;
00621 }
00622
00623 void FlowVisCanvas::SetGlyphDensity(int new_density)
00624 {
00625 m_sl_settings.glyph_density = new_density;
00626 }
00627
00628 void FlowVisCanvas::SetDsep(float dsep)
00629 {
00630 m_sl_algorithm.dsep = dsep;
00631 }
00632
00633 void FlowVisCanvas::SetDtest(float dtest)
00634 {
00635 m_sl_algorithm.dtest = dtest;
00636 }
00637
00638 void FlowVisCanvas::SetIntegType(int integ_index)
00639 {
00640 m_sl_algorithm.interploation = (integ_index)?(ITER_EULER):(ITER_RK);
00641 }
00642
00643 void FlowVisCanvas::SetMaxIter(int maxiter)
00644 {
00645 m_sl_algorithm.maxiter = maxiter;
00646 }
00647
00648 void FlowVisCanvas::SetStepSize(float step_size)
00649 {
00650 m_sl_algorithm.stepsize = step_size;
00651 }
00652
00653 void FlowVisCanvas::RenderToFile(const wxString& file_name, int width, int height)
00654 {
00655
00656
00657 if (!CheckGL()) return;
00658
00659 GLuint id_rbf;
00660 GLuint id_fbo;
00661
00662
00663 glGenFramebuffersEXT(1, &id_fbo);
00664 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id_fbo);
00665
00666
00667 glGenRenderbuffersEXT(1, &id_rbf);
00668 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, id_rbf);
00669
00670 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, width, height);
00671
00672
00673 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, id_rbf);
00674
00675
00676 if (GL_FRAMEBUFFER_COMPLETE_EXT == glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT))
00677 {
00678 m_viewport_width = width;
00679 m_viewport_height = height;
00680
00681 Render_ToScreen();
00682
00683 unsigned char *rgb = (unsigned char*)malloc(width * height * 3);
00684 unsigned char *alpha = (unsigned char*)malloc(width * height);
00685
00686 glPixelStorei(GL_PACK_ALIGNMENT, 1);
00687 glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, rgb);
00688 glReadPixels(0, 0, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha);
00689 glPixelStorei(GL_PACK_ALIGNMENT, 4);
00690
00691 wxImage img(width, height);
00692 img.SetData(rgb);
00693 img.SetAlpha(alpha);
00694 img = img.Mirror(false);
00695
00696 if (!img.SaveFile(file_name)) {
00697
00698 }
00699 } else {
00700
00701 }
00702
00703
00704 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00705
00706
00707 glDeleteRenderbuffersEXT(1, &id_rbf);
00708
00709
00710 glDeleteFramebuffersEXT(1, &id_fbo);
00711
00712 GetClientSize(&m_viewport_width, &m_viewport_height);
00713 }