00001
00022 #include "panoinc_WX.h"
00023 #include "panoinc.h"
00024
00025 #include "PreviewIdentifyTool.h"
00026 #include <config.h>
00027
00028 #include "base_wx/platform.h"
00029 #include "GLPreviewFrame.h"
00030 #include "MainFrame.h"
00031
00032 #include <wx/platform.h>
00033
00034
00035 #if !defined Hugin_shared || !defined _WINDOWS
00036 #define GLEW_STATIC
00037 #endif
00038 #include <GL/glew.h>
00039
00040 #ifdef __WXMAC__
00041 #include <OpenGL/gl.h>
00042 #include <OpenGL/glu.h>
00043 #else
00044 #include <GL/gl.h>
00045 #include <GL/glu.h>
00046 #endif
00047
00048 #include <algorithm>
00049 #include <vector>
00050
00051
00052 #define rect_ts 64
00053
00054
00055 #define circle_ts_multiple 4
00056 #define circle_ts (rect_ts * circle_ts_multiple)
00057 #define circle_middle ((float) (circle_ts - 1) / 2.0)
00058 #define circle_border_outer (circle_middle - 0.5 * (float) circle_ts_multiple)
00059 #define circle_border_inner (circle_middle - 2.5 * (float) circle_ts_multiple)
00060 #define circle_border_peak (circle_middle - 1.5 * (float) circle_ts_multiple)
00061
00062 bool PreviewIdentifyTool::texture_created = false;
00063 unsigned int PreviewIdentifyTool::circle_border_tex;
00064 unsigned int PreviewIdentifyTool::rectangle_border_tex;
00065
00066 PreviewIdentifyTool::PreviewIdentifyTool(ToolHelper *helper,
00067 GLPreviewFrame *owner)
00068 : Tool(helper)
00069 {
00070 holdControl = false;
00071 constantOn = false;
00072 holdLeft = false;
00073 stopUpdating = true;
00074 preview_frame = owner;
00075 if (!texture_created) {
00076
00077
00078 glGenTextures(1, (GLuint*) &rectangle_border_tex);
00079 glGenTextures(1, (GLuint*) &circle_border_tex);
00080
00081
00082
00083
00084 {
00085
00086
00087
00088 unsigned char rect_tex_data[rect_ts][rect_ts][2];
00089
00090 for (unsigned int x = 0; x < rect_ts; x++)
00091 {
00092 for (unsigned int y = 0; y < rect_ts; y++)
00093 {
00094 rect_tex_data[x][y][0] = 255;
00095 }
00096 }
00097
00098 for (unsigned int x = 2; x < rect_ts - 2; x++)
00099 {
00100 for (unsigned int y = 2; y < rect_ts - 2; y++)
00101 {
00102 rect_tex_data[x][y][1] = 63;
00103 }
00104 }
00105
00106 for (unsigned int d = 1; d < rect_ts - 1; d++)
00107 {
00108 rect_tex_data[d][1][1] = 255;
00109 rect_tex_data[d][rect_ts - 2][1] = 255;
00110 rect_tex_data[1][d][1] = 255;
00111 rect_tex_data[rect_ts - 2][d][1] = 255;
00112 }
00113
00114 for (unsigned int d = 0; d < rect_ts; d++)
00115 {
00116 rect_tex_data[d][0][1] = 0;
00117 rect_tex_data[d][rect_ts - 1][1] = 0;
00118 rect_tex_data[0][d][1] = 0;
00119 rect_tex_data[rect_ts - 1][d][1] = 0;
00120 }
00121 glBindTexture(GL_TEXTURE_2D, rectangle_border_tex);
00122 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, rect_ts, rect_ts,
00123 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, rect_tex_data);
00124 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
00125 GL_LINEAR_MIPMAP_LINEAR);
00126
00127 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00128 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00129 }
00130 {
00131
00132
00133
00134
00135 unsigned char circle_tex_data[circle_ts][circle_ts][2];
00136 for (unsigned int x = 0; x < circle_ts; x++)
00137 {
00138 for (unsigned int y = 0; y < circle_ts; y++)
00139 {
00140 float x_offs = (float) x - circle_middle,
00141 y_offs = (float) y - circle_middle,
00142 radius = sqrt(x_offs * x_offs + y_offs * y_offs),
00143 intensity;
00144 if (radius < circle_border_inner)
00145 {
00146 intensity = 63.0;
00147 } else if (radius < circle_border_peak)
00148 {
00149 intensity = (radius - circle_border_inner) /
00150 (float) circle_ts_multiple * 255.0 * 3.0 / 4.0 + 64.0;
00151 } else if (radius < circle_border_outer)
00152 {
00153 intensity = (radius - circle_border_peak) /
00154 (float) circle_ts_multiple * -255.0 + 256.0;
00155 } else
00156 {
00157 intensity = 0.0;
00158 }
00159 circle_tex_data[x][y][0] = 255;
00160 circle_tex_data[x][y][1] = (unsigned char) intensity;
00161 }
00162 }
00163 glBindTexture(GL_TEXTURE_2D, circle_border_tex);
00164 gluBuild2DMipmaps(GL_TEXTURE_2D,
00165 GL_LUMINANCE_ALPHA, circle_ts, circle_ts,
00166 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, circle_tex_data);
00167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
00168 GL_LINEAR_MIPMAP_LINEAR);
00169
00170 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00171 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00172 }
00173 texture_created = true;
00174 }
00175 }
00176 PreviewIdentifyTool::~PreviewIdentifyTool()
00177 {
00178
00179 glDeleteTextures(1, (GLuint*) &rectangle_border_tex);
00180 glDeleteTextures(1, (GLuint*) &circle_border_tex);
00181 }
00182
00183 void PreviewIdentifyTool::Activate()
00184 {
00185
00186 helper->NotifyMe(PreviewToolHelper::MOUSE_MOVE, this);
00187 helper->NotifyMe(PreviewToolHelper::DRAW_OVER_IMAGES, this);
00188 helper->NotifyMe(PreviewToolHelper::IMAGES_UNDER_MOUSE_CHANGE, this);
00189 helper->NotifyMe(PreviewToolHelper::MOUSE_PRESS, this);
00190
00191
00192
00193
00194
00195 image_set.clear();
00196 mouse_is_over_button = false;
00197
00198
00199
00200 ImagesUnderMouseChangedEvent();
00201
00202 helper->SetStatusMessage(_("Move the mouse over the images or image buttons to identify them."));
00203 }
00204
00205 void PreviewIdentifyTool::StopUpdating() {
00206 if (image_set.size() > 0) {
00207 std::set<unsigned int>::iterator iterator;
00208 for (iterator = image_set.begin(); iterator != image_set.end(); iterator++)
00209 {
00210 DEBUG_ASSERT(*iterator < helper->GetPanoramaPtr()->getNrOfImages());
00211
00212 preview_frame->SetImageButtonColour(*iterator, 0, 0, 0);
00213
00214 helper->DoNotNotifyMeBeforeDrawing(*iterator, this);
00215 }
00216 }
00217 image_set.clear();
00218 preview_frame->UpdateIdentifyTools(image_set);
00219 stopUpdating = true;
00220 ForceRedraw();
00221 }
00222
00223 void PreviewIdentifyTool::ContinueUpdating() {
00224 stopUpdating = false;
00225 ImagesUnderMouseChangedEvent();
00226 }
00227
00228 void PreviewIdentifyTool::MouseMoveEvent(double x, double y, wxMouseEvent & e)
00229 {
00230
00231 bool stop = false;
00232 bool start = false;
00233
00234 if (constantOn) {
00235 if (e.Dragging() && !(holdLeft)) {
00236 stop = true;
00237 stopUpdating = true;
00238 }
00239
00240 if (stopUpdating && !e.LeftIsDown() && !e.MiddleIsDown() && !e.RightIsDown()) {
00241 start = true;
00242 }
00243 }
00244
00245 if (holdControl && !e.m_controlDown) {
00246 holdControl = false;
00247 if (!constantOn) {
00248 stop = true;
00249 }
00250 }
00251
00252 if (!holdControl && e.m_controlDown) {
00253 holdControl = true;
00254 stop = false;
00255 if (stopUpdating) {
00256 start = true;
00257 }
00258 }
00259
00260 if (stop) {
00261 this->StopUpdating();
00262 } else if(start) {
00263 this->ContinueUpdating();
00264 }
00265
00266
00267 }
00268
00269 void PreviewIdentifyTool::KeypressEvent(int keycode, int modifierss, int pressed) {
00270
00271 if (keycode == WXK_CONTROL) {
00272 if (pressed) {
00273 holdControl = true;
00274 ContinueUpdating();
00275 } else {
00276 if(holdControl) {
00277 StopUpdating();
00278 }
00279 holdControl = false;
00280 }
00281 }
00282 }
00283
00284 void PreviewIdentifyTool::setConstantOn(bool constant_on_in) {
00285 constantOn = constant_on_in;
00286 if (constant_on_in) {
00287 stopUpdating = false;
00288 ContinueUpdating();
00289 } else {
00290 stopUpdating = true;
00291 StopUpdating();
00292 }
00293
00294 }
00295
00296
00297 void PreviewIdentifyTool::ImagesUnderMouseChangedEvent()
00298 {
00299 if (stopUpdating) {
00300 return;
00301 }
00302
00303 std::set<unsigned int> new_image_set = helper->GetImageNumbersUnderMouse();
00304
00305
00306
00307
00308
00309
00310
00311 preview_frame->UpdateIdentifyTools(new_image_set);
00312
00313
00314 if (image_set.size() == 2)
00315 {
00316 helper->SetStatusMessage(_("Click to create or edit control points here."));
00317 } else {
00318 helper->SetStatusMessage(_("Move the mouse over the images or image buttons to identify them."));
00319 }
00320 }
00321
00322 void PreviewIdentifyTool::AfterDrawImagesEvent()
00323 {
00324
00325
00326
00327 unsigned int num_images = image_set.size();
00328
00329
00330
00331 glMatrixMode(GL_MODELVIEW);
00332 std::set<unsigned int>::reverse_iterator it;
00333 for (it = image_set.rbegin(); it != image_set.rend(); it++)
00334 {
00335 DEBUG_ASSERT(*it < helper->GetPanoramaPtr()->getNrOfImages());
00336 helper->GetViewStatePtr()->GetTextureManager()->
00337 DrawImage(*it,
00338 helper->GetVisualizationStatePtr()->GetMeshDisplayList(*it));
00339 }
00340 glMatrixMode(GL_TEXTURE);
00341
00342
00343 glEnable(GL_BLEND);
00344 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00345 unsigned int image_counter = 0;
00346 for (it = image_set.rbegin(); it != image_set.rend(); it++)
00347 {
00348 glMatrixMode(GL_TEXTURE);
00349
00350
00351 if (helper->GetViewStatePtr()->GetSupportMultiTexture())
00352 {
00353 helper->GetViewStatePtr()->GetTextureManager()->BindTexture(*it);
00354 glActiveTexture(GL_TEXTURE0);
00355 }
00356
00357 glPushMatrix();
00358 HuginBase::SrcPanoImage *src = helper->GetViewStatePtr()->
00359 GetSrcImage(*it);
00360 int width = src->getSize().width(), height = src->getSize().height();
00361 vigra::Rect2D crop_region = src->getCropRect();
00362
00363 switch (src->getCropMode())
00364 {
00365 case HuginBase::SrcPanoImage::CROP_CIRCLE:
00366 glBindTexture(GL_TEXTURE_2D, circle_border_tex);
00367
00368 if (crop_region.width() < crop_region.height())
00369 {
00370
00371 int diff = (crop_region.width() - crop_region.height()) / 2;
00372
00373
00374 crop_region.addBorder(0, diff);
00375 } else if (crop_region.width() > crop_region.height())
00376 {
00377
00378 int diff = (crop_region.height() - crop_region.width()) / 2;
00379 crop_region.addBorder(diff, 0);
00380 }
00381 {
00382 float diameter = (float) crop_region.width();
00383 glScalef((float) width / diameter,
00384 (float) height / diameter, 1.0);
00385 glTranslatef(-(float) crop_region.left() / (float) width,
00386 -(float) crop_region.top() / (float) height,
00387 0.0);
00388 }
00389 break;
00390 case HuginBase::SrcPanoImage::CROP_RECTANGLE:
00391
00392
00393 crop_region &= vigra::Rect2D(src->getSize());
00394 glBindTexture(GL_TEXTURE_2D, rectangle_border_tex);
00395 glScalef((float) width / (float) crop_region.width(),
00396 (float) height / (float) crop_region.height(),
00397 1.0);
00398 glTranslatef(-(float) crop_region.left() / (float) width,
00399 -(float) crop_region.top() / (float) height,
00400 0.0);
00401 break;
00402 case HuginBase::SrcPanoImage::NO_CROP:
00403 glBindTexture(GL_TEXTURE_2D, rectangle_border_tex);
00404 break;
00405 }
00406
00407 glMatrixMode(GL_MODELVIEW);
00408 unsigned char r,g,b;
00409 HighlightColour(image_counter, num_images, r, g, b);
00410 image_counter++;
00411 glColor3ub(r,g,b);
00412 glCallList(helper->GetVisualizationStatePtr()->GetMeshDisplayList(*it));
00413 glMatrixMode(GL_TEXTURE);
00414 glPopMatrix();
00415
00416 preview_frame->SetImageButtonColour(*it, r, g, b);
00417 }
00418
00419 glMatrixMode(GL_MODELVIEW);
00420 glDisable(GL_BLEND);
00421 glColor3ub(255, 255, 255);
00422 }
00423
00424 bool PreviewIdentifyTool::BeforeDrawImageEvent(unsigned int image)
00425 {
00426
00427 DEBUG_ASSERT(image < helper->GetPanoramaPtr()->getNrOfImages());
00428 if (image_set.count(image)) return false;
00429 return true;
00430 }
00431
00432 void PreviewIdentifyTool::ShowImageNumber(unsigned int image)
00433 {
00434 DEBUG_ASSERT(image < helper->GetPanoramaPtr()->getNrOfImages());
00435
00436 if (!image_set.count(image))
00437 {
00438
00439 image_set.insert(image);
00440
00441 helper->NotifyMeBeforeDrawing(image, this);
00442
00443 ForceRedraw();
00444 }
00445 mouse_over_image = image;
00446 mouse_is_over_button = true;
00447 }
00448
00449 void PreviewIdentifyTool::StopShowingImages()
00450 {
00451 if (mouse_is_over_button)
00452 {
00453
00454 preview_frame->SetImageButtonColour(mouse_over_image, 0, 0, 0);
00455 helper->DoNotNotifyMeBeforeDrawing(mouse_over_image, this);
00456 image_set.erase(mouse_over_image);
00457
00458 ForceRedraw();
00459 mouse_is_over_button = false;
00460 }
00461 }
00462
00463
00464 void PreviewIdentifyTool::HighlightColour(unsigned int index,
00465 unsigned int count,
00466 unsigned char &red,
00467 unsigned char &green,
00468 unsigned char &blue)
00469 {
00470 DEBUG_ASSERT(index < count && index >= 0);
00471
00472 float hue = ((float) index / (float) count) * 6.0;
00473 if (hue < 1.0)
00474 {
00475
00476 red = 255;
00477 green = (unsigned char) (hue * 255.0);
00478 blue = 0;
00479 } else if (hue < 2.0) {
00480
00481 red = (unsigned char) ((-hue + 2.0) * 255.0);
00482 green = 255;
00483 blue = 0;
00484 } else if (hue < 3.0) {
00485
00486 red = 0;
00487 green = 255;
00488 blue = (unsigned char) ((hue - 2.0) * 255.0);
00489 } else if (hue < 4.0) {
00490
00491 red = 0;
00492 green = (unsigned char) ((-hue + 4.0) * 255.0);
00493 blue = 255;
00494 } else if (hue < 5.0) {
00495
00496 red = (unsigned char) ((hue - 4.0) * 255.0);
00497 green = 0;
00498 blue = 255;
00499 } else {
00500
00501 red = 255;
00502 green = 0;
00503 blue = (unsigned char) ((-hue + 6.0) * 255.0);
00504 }
00505 }
00506
00507 void PreviewIdentifyTool::MouseButtonEvent(wxMouseEvent & e)
00508 {
00509
00510
00511 if ( e.LeftDown() && helper->IsMouseOverPano())
00512 {
00513 holdLeft = true;
00514 }
00515
00516 if (holdLeft && e.LeftUp() && (image_set.size()==1 || image_set.size() == 2))
00517 {
00518 holdLeft = false;
00519 if (constantOn || e.CmdDown())
00520 {
00521
00522
00523 if(image_set.size()==2)
00524 {
00525 MainFrame::Get()->ShowCtrlPointEditor(*(image_set.begin()),
00526 *(++image_set.begin()));
00527 }
00528 else
00529 {
00530 MainFrame::Get()->ShowMaskEditor(*image_set.begin());
00531 };
00532 MainFrame::Get()->Raise();
00533 }
00534 }
00535
00536 if (holdLeft && !(e.LeftIsDown())) {
00537 holdLeft = false;
00538 }
00539
00540 if (constantOn) {
00541 if (e.ButtonUp() && !e.MiddleIsDown() && !e.RightIsDown()) {
00542 stopUpdating = false;
00543 ImagesUnderMouseChangedEvent();
00544 }
00545 }
00546
00547 }
00548
00549 void PreviewIdentifyTool::UpdateWithNewImageSet(std::set<unsigned int> new_image_set)
00550 {
00551
00552
00553
00554 {
00555 UIntSet difference;
00556 std::set_difference (image_set.begin(), image_set.end(),
00557 new_image_set.begin(), new_image_set.end(),
00558 std::inserter(difference,difference.end()));
00559 if (difference.size()>0)
00560 {
00561 for (UIntSet::iterator iterator = difference.begin(); iterator != difference.end(); iterator++)
00562 {
00563 DEBUG_ASSERT(*iterator < helper->GetPanoramaPtr()->getNrOfImages());
00564
00565 preview_frame->SetImageButtonColour(*iterator, 0, 0, 0);
00566
00567 helper->DoNotNotifyMeBeforeDrawing(*iterator, this);
00568 }
00569 }
00570 }
00571
00572
00573 UIntSet difference;
00574 std::set_difference (new_image_set.begin(), new_image_set.end(),
00575 image_set.begin(), image_set.end(),
00576 std::inserter(difference,difference.end()));
00577 if (difference.size()>0)
00578 {
00579 for (UIntSet::iterator iterator = difference.begin(); iterator != difference.end(); iterator++)
00580 {
00581 DEBUG_ASSERT(*iterator < helper->GetPanoramaPtr()->getNrOfImages());
00582
00583 helper->NotifyMeBeforeDrawing(*iterator, this);
00584 }
00585 }
00586
00587 image_set.swap(new_image_set);
00588
00589
00590
00591
00592 ForceRedraw();
00593 }
00594
00595 void PreviewIdentifyTool::ForceRedraw()
00596 {
00597 helper->GetVisualizationStatePtr()->ForceRequireRedraw();
00598 helper->GetVisualizationStatePtr()->Redraw();
00599 }