00001 #include "TransferFunctionGUI.h"
00002
00003 #include "utility.h"
00004
00005 #include "Colours.h"
00006 #include "TFControlPoint.h"
00007
00008 #include <algorithm>
00009 #include <sstream>
00010
00011 #include "tinyxml.h"
00012
00013 using namespace Colours;
00014
00015 RGBA_Colour* TransferFunctionGUI::transferFunctionPickerData = new RGBA_Colour[g_iTransferFuncPickerHeight * g_iTransferFuncPickerWidth];
00016
00017 int TransferFunctionGUI::g_iTransferFunctionTextureDisplayHeight = 14;
00018 int TransferFunctionGUI::g_iTransferFunctionTextureDisplayYOffset = 8;
00019
00020 std::vector<TFControlPoint> TransferFunctionGUI::controlPoints;
00021
00022 ColourSpace TransferFunctionGUI::transferFunctionTextureColorSpace = COLOURSPACE_LAB;
00023
00024 const int TransferFunctionGUI::g_iTransferFuncPickerWidth = 660;
00025 const int TransferFunctionGUI::g_iTransferFuncPickerHeight = 180;
00026
00027
00028
00029 void TransferFunctionGUI::refreshTransferFuncPicker()
00030 {
00031
00032 if(controlPoints.size() == 0)
00033 {
00034 for(int x = 0; x < g_iTransferFuncPickerWidth; ++x)
00035 for(int y = 0; y < g_iTransferFuncPickerHeight; ++y)
00036 transferFunctionPickerData[(int)g_iTransferFuncPickerWidth * y + x] = RGBA_Colour((GLubyte)0, (GLubyte)0, (GLubyte)0, (GLubyte)0);
00037 }
00038 else
00039 {
00040 refreshTransferFuncPickerData();
00041 }
00042 }
00043
00044 void TransferFunctionGUI::initControlPoints()
00045 {
00046 Lab_Colour colour((GLubyte)255, (GLubyte)0, (GLubyte)0);
00047 controlPoints.push_back(TFControlPoint(0.17f, 0.f, colour));
00048
00049 colour = Lab_Colour((GLubyte)127, (GLubyte)0, (GLubyte)67);
00050 controlPoints.push_back(TFControlPoint(0.75f, 99.f / g_iTransferFuncPickerHeight, colour));
00051
00052 colour = Lab_Colour((GLubyte)127, (GLubyte)127, (GLubyte)0);
00053 controlPoints.push_back(TFControlPoint(0.26f, 180.f / g_iTransferFuncPickerHeight, colour));
00054
00055 colour = Lab_Colour((GLubyte)55, (GLubyte)55, (GLubyte)0);
00056 controlPoints.push_back(TFControlPoint(1.f, 22.f / g_iTransferFuncPickerHeight, colour));
00057
00058 sortControlPoints();
00059 }
00060
00061 void TransferFunctionGUI::drawControlPointsRelative()
00062 {
00063 if(controlPoints.size() > 0)
00064 {
00065
00066 for(std::vector<TFControlPoint>::iterator iter = controlPoints.begin(); iter != controlPoints.end(); ++iter)
00067 {
00068 TFControlPoint& controlPoint = *iter;
00069
00070 if(!controlPoint.isSelected())
00071 controlPoint.drawControlPoint();
00072 }
00073
00074 for(std::vector<TFControlPoint>::iterator iter = controlPoints.begin(); iter != controlPoints.end(); ++iter)
00075 {
00076 TFControlPoint& controlPoint = *iter;
00077
00078 if(controlPoint.isSelected())
00079 controlPoint.drawControlPoint();
00080 }
00081 }
00082 }
00083
00084
00085 void TransferFunctionGUI::drawControlPointsConnection()
00086 {
00087 glLineWidth(1.5f);
00088 glEnable(GL_LINE_SMOOTH);
00089 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00090
00091
00092 glBegin(GL_LINE_STRIP);
00093 glColor3f(0.f,0.f,0.f);
00094 glVertex2i(0, 0);
00095 if(controlPoints.size() > 0)
00096 {
00097 for(std::vector<TFControlPoint>::iterator iter = controlPoints.begin(); iter != controlPoints.end(); ++iter)
00098 {
00099 TFControlPoint& controlPoint = *iter;
00100
00101 glVertex2f(controlPoint.m_pos.x * g_iTransferFuncPickerWidth ,-controlPoint.m_pos.y * g_iTransferFuncPickerHeight);
00102 }
00103 }
00104 glVertex2i(g_iTransferFuncPickerWidth, 0);
00105 glEnd();
00106
00107 glDisable(GL_LINE_SMOOTH);
00108 }
00109
00110
00111 bool TransferFunctionGUI::AABBHitCheck(int mouseX, int mouseY, float AABBSideLength, float AABBCenterX, float AABBCenterY)
00112 {
00113 return (mouseX >= AABBCenterX - AABBSideLength && mouseX <= AABBCenterX + AABBSideLength
00114 && mouseY >= AABBCenterY - AABBSideLength && mouseY <= AABBCenterY + AABBSideLength);
00115 }
00116
00117 void TransferFunctionGUI::setAllControlPointsUndragged()
00118 {
00119 for(std::vector<TFControlPoint>::iterator iter = controlPoints.begin(); iter != controlPoints.end();)
00120 {
00121 TFControlPoint& controlPoint = *iter;
00122
00123 if(controlPoint.isBeingDragged())
00124 {
00125 if(controlPoint.isMarkedForDeletion())
00126 iter = controlPoints.erase(iter);
00127 else
00128 {
00129 ++iter;
00130 controlPoint.draggingEnded();
00131 }
00132 }
00133 else
00134 ++iter;
00135 }
00136 }
00137
00138 void TransferFunctionGUI::setAllControlPointsUnselected()
00139 {
00140 for(std::vector<TFControlPoint>::iterator iter = controlPoints.begin(); iter != controlPoints.end(); ++iter)
00141 {
00142 TFControlPoint& controlPoint = *iter;
00143
00144 controlPoint.setSelected(false);
00145 }
00146 }
00147
00148 bool TransferFunctionGUI::isAnyControlPointBeingDragged()
00149 {
00150 for(std::vector<TFControlPoint>::iterator iter = controlPoints.begin(); iter != controlPoints.end();)
00151 {
00152 TFControlPoint& controlPoint = *iter;
00153
00154 bool dragging = controlPoint.isBeingDragged();
00155
00156 if(dragging)
00157 return dragging;
00158 else
00159 ++iter;
00160 }
00161
00162 return false;
00163 }
00164
00165 bool TransferFunctionGUI::isAnyControlPointSelected()
00166 {
00167 for(std::vector<TFControlPoint>::iterator iter = controlPoints.begin(); iter != controlPoints.end();)
00168 {
00169 TFControlPoint& controlPoint = *iter;
00170
00171 bool selected = controlPoint.isSelected();
00172
00173 if(selected)
00174 return selected;
00175 else
00176 ++iter;
00177 }
00178
00179 return false;
00180 }
00181
00182
00183 TFControlPoint* TransferFunctionGUI::getSelectedControlPoint()
00184 {
00185 for(std::vector<TFControlPoint>::iterator iter = controlPoints.begin(); iter != controlPoints.end();)
00186 {
00187 TFControlPoint& controlPoint = *iter;
00188
00189 bool selected = controlPoint.isSelected();
00190
00191 if(selected)
00192 return &controlPoint;
00193 else
00194 ++iter;
00195 }
00196
00197 return NULL;
00198 }
00199
00200 bool TransferFunctionGUI::checkForControlPointsSelection(int x, int y)
00201 {
00202 bool hit = false;
00203
00204 for(std::vector<TFControlPoint>::iterator iter = controlPoints.begin(); iter != controlPoints.end();)
00205 {
00206 TFControlPoint& controlPoint = *iter;
00207
00208 hit = AABBHitCheck(x, y, (float)TFControlPoint::DrawSize, controlPoint.m_pos.x * g_iTransferFuncPickerWidth, g_iTransferFuncPickerHeight - controlPoint.m_pos.y * g_iTransferFuncPickerHeight);
00209 if(hit)
00210 {
00211 controlPoint.setSelected(true);
00212 iter = controlPoints.end();
00213 }
00214 else
00215 ++iter;
00216 }
00217
00218 return hit;
00219 }
00220
00221 void TransferFunctionGUI::processControlPointHitCheck(bool &hit, int x, int y, TFControlPoint &controlPoint)
00222 {
00223 hit = AABBHitCheck(x, y, (float)TFControlPoint::DrawSize, controlPoint.m_pos.x * g_iTransferFuncPickerWidth, g_iTransferFuncPickerHeight - controlPoint.m_pos.y * g_iTransferFuncPickerHeight);
00224 if(hit)
00225 {
00226 controlPoint.setBeingDragged(true);
00227 setAllControlPointsUnselected();
00228 controlPoint.setSelected(true);
00229 controlPoint.dragMovement(x, y);
00230 }
00231 }
00232
00233 bool TransferFunctionGUI::checkIfMouseInsideTransferFunc(int x, int y)
00234 {
00235 return (x <= g_iTransferFuncPickerWidth && x >= 0
00236 && y <= g_iTransferFuncPickerHeight && y >= 0);
00237 }
00238
00239 void TransferFunctionGUI::createNewControlPoint( int x, int y, const Lab_Colour& colour )
00240 {
00241 float xRel = x / (float)g_iTransferFuncPickerWidth;
00242 float yRel = (g_iTransferFuncPickerHeight - y) / (float)g_iTransferFuncPickerHeight;
00243
00244 setAllControlPointsUnselected();
00245 TFControlPoint newControlPoint = TFControlPoint(xRel, yRel, colour);
00246 newControlPoint.setSelected(true);
00247 controlPoints.push_back(newControlPoint);
00248 }
00249
00250 void TransferFunctionGUI::deleteSelectedControlPoint()
00251 {
00252 TFControlPoint* selectedControlPoint = getSelectedControlPoint();
00253 if(selectedControlPoint)
00254 {
00255 selectedControlPoint->setMarkedForDeletion(true);
00256 selectedControlPoint->setBeingDragged(true);
00257 }
00258 setAllControlPointsUndragged();
00259
00260 }
00261
00262 void TransferFunctionGUI::refreshTransferFuncPickerData()
00263 {
00264 std::vector<TFControlPoint>::iterator currentLeft = controlPoints.begin();
00265 std::vector<TFControlPoint>::iterator currentRight = (controlPoints.begin() + 1);
00266 std::vector<TFControlPoint>::iterator controlPointsEnd = controlPoints.end();
00267
00268 for(int x = 0; x < g_iTransferFuncPickerWidth; ++x)
00269 {
00270
00271 RGB_Colour currentColour = RGB_Colour(0,0,0);
00272
00273
00274 while(currentRight != controlPointsEnd && x > currentRight->m_pos.x * g_iTransferFuncPickerWidth)
00275 {
00276 ++currentRight;
00277 ++currentLeft;
00278 }
00279
00280
00281 if(currentRight == controlPointsEnd && x > currentLeft->m_pos.x * g_iTransferFuncPickerWidth)
00282 {
00283 currentColour = toRGB(currentLeft->getColourLab());
00284 }
00285
00286 else if(currentLeft != controlPointsEnd && x <= currentLeft->m_pos.x * g_iTransferFuncPickerWidth)
00287 {
00288 currentColour = toRGB(currentLeft->getColourLab());
00289 }
00290 else
00291 {
00292 float interPolBalance = calcInterpolationValueBetweenControlPoints(x, currentLeft, currentRight);
00293 currentColour = interpolateControlPointColours(interPolBalance, currentLeft, currentRight);
00294 }
00295
00296
00297 for(int y = 0; y < g_iTransferFuncPickerHeight; ++y)
00298 {
00299 GLubyte alpha = (GLubyte)(255 * y / (float)g_iTransferFuncPickerHeight);
00300
00301 transferFunctionPickerData[(int)g_iTransferFuncPickerWidth * y + x] = RGBA_Colour(currentColour, alpha);
00302 }
00303 }
00304 }
00305
00306
00307
00308 RGB_Colour TransferFunctionGUI::interpolateControlPointColours(float interPolBalance, std::vector<TFControlPoint>::iterator currentLeft, std::vector<TFControlPoint>::iterator currentRight)
00309 {
00310 switch(transferFunctionTextureColorSpace)
00311 {
00312 case COLOURSPACE_RGB:
00313 {
00314
00315 return linearInterpolationRGB(interPolBalance, toRGB(currentLeft->m_colour), toRGB(currentRight->m_colour));
00316 }
00317 break;
00318 case COLOURSPACE_LAB:
00319 {
00320
00321 Lab_Colour& interpolatedLabColour = linearInterpolationLab(interPolBalance, currentLeft->m_colour, currentRight->m_colour);
00322 return toRGB(interpolatedLabColour);
00323 }
00324 break;
00325 default:
00326 return RGB_Colour(0, 0, 0);
00327 }
00328 }
00329
00330 float TransferFunctionGUI::calcInterpolationValueBetweenControlPoints(int x, std::vector<TFControlPoint>::iterator currentLeft, std::vector<TFControlPoint>::iterator currentRight)
00331 {
00332 float leftXAbs = currentLeft->m_pos.x * g_iTransferFuncPickerWidth;
00333 float rightXAbs = currentRight->m_pos.x * g_iTransferFuncPickerWidth;
00334
00335 return (x - leftXAbs) / (rightXAbs - leftXAbs);
00336 }
00337
00338
00339 void TransferFunctionGUI::updateControlPointDragMovement(int mouseX, int mouseY)
00340 {
00341 for(std::vector<TFControlPoint>::iterator iter = controlPoints.begin(); iter != controlPoints.end(); ++iter)
00342 {
00343 TFControlPoint& controlPoint = *iter;
00344
00345 if(controlPoint.isBeingDragged())
00346 controlPoint.dragMovement(mouseX, mouseY);
00347 }
00348 }
00349
00350 bool TransferFunctionGUI::checkForControlPointsAction(int button, int state, int x, int y)
00351 {
00352 bool hit = false;
00353
00354
00355 if(button == 2 && state == 0)
00356 {
00357 hit = checkForControlPointsSelection(x, y);
00358
00359 if(hit)
00360 {
00361 deleteSelectedControlPoint();
00362 }
00363 }
00364 else if(button == 0 && state == 0)
00365 {
00366 TFControlPoint* selectedControlPoint = getSelectedControlPoint();
00367
00368 if(selectedControlPoint != NULL)
00369 {
00370 processControlPointHitCheck(hit, x, y, *selectedControlPoint);
00371 }
00372
00373 if(!hit)
00374 {
00375
00376 for(std::vector<TFControlPoint>::iterator iter = controlPoints.begin(); iter != controlPoints.end();)
00377 {
00378 TFControlPoint& controlPoint = *iter;
00379 processControlPointHitCheck(hit, x, y, controlPoint);
00380
00381 if(hit)
00382 iter = controlPoints.end();
00383 else
00384 ++iter;
00385 }
00386 }
00387 }
00388 else if(button == 0 && state == 1)
00389 {
00390 bool dragging = isAnyControlPointBeingDragged();
00391
00392 if(dragging)
00393 {
00394 setAllControlPointsUndragged();
00395 }
00396 else
00397 {
00398 setAllControlPointsUnselected();
00399 hit = checkForControlPointsSelection(x, y);
00400 }
00401 }
00402 return hit;
00403 }
00404
00405
00406 bool TransferFunctionGUI::checkForControlPointsCreation(int button, int state, int x, int y, const Lab_Colour& colour)
00407 {
00408 bool mouseInsideTransferFuncPanel = checkIfMouseInsideTransferFunc(x, y);
00409
00410 if(getSelectedControlPoint() == NULL)
00411 {
00412 if(button == 0 && state == 0 && mouseInsideTransferFuncPanel)
00413 {
00414 createNewControlPoint(x, y, colour);
00415 }
00416 }
00417
00418 if(button == 2 && state == 0 && mouseInsideTransferFuncPanel)
00419 createNewControlPoint(x, y, colour);
00420
00421
00422
00423 return mouseInsideTransferFuncPanel;
00424 }
00425
00426
00427
00428 void TransferFunctionGUI::sortControlPoints()
00429 {
00430 std::sort(controlPoints.begin(), controlPoints.end());
00431 }
00432
00433 void TransferFunctionGUI::saveTransferFunctionControlPoints(const char* file)
00434 {
00435 TiXmlDocument doc;
00436
00437 TiXmlDeclaration * decl = new TiXmlDeclaration( "2.0beta", "", "" );
00438 doc.LinkEndChild( decl );
00439
00440 for(std::vector<TFControlPoint>::iterator iter = controlPoints.begin(); iter != controlPoints.end(); ++iter)
00441 {
00442 TFControlPoint& controlPoint = *iter;
00443 std::stringstream stream;
00444
00445 TiXmlElement* controlPointElement = new TiXmlElement( "ControlPoint" );
00446 doc.LinkEndChild(controlPointElement);
00447
00448 TiXmlElement* xRel = new TiXmlElement( "xRel" );
00449 TiXmlElement* yRel = new TiXmlElement( "yRel" );
00450 TiXmlElement* colourL = new TiXmlElement( "colourL" );
00451 TiXmlElement* colourA = new TiXmlElement( "colourA" );
00452 TiXmlElement* colourB = new TiXmlElement( "colourB" );
00453
00454 controlPointElement->LinkEndChild(xRel);
00455 controlPointElement->LinkEndChild(yRel);
00456 controlPointElement->LinkEndChild(colourL);
00457 controlPointElement->LinkEndChild(colourA);
00458 controlPointElement->LinkEndChild(colourB);
00459
00460
00461 stream << controlPoint.m_pos.x;
00462 TiXmlText * xRelText = new TiXmlText(stream.str().c_str());
00463 stream.str("");
00464 xRel->LinkEndChild( xRelText );
00465
00466 stream << controlPoint.m_pos.y;
00467 TiXmlText * yRelText = new TiXmlText(stream.str().c_str());
00468 stream.str("");
00469 yRel->LinkEndChild( yRelText );
00470
00471 stream << controlPoint.getColourLab().L;
00472 TiXmlText * colourLText = new TiXmlText(stream.str().c_str());
00473 stream.str("");
00474 colourL->LinkEndChild( colourLText );
00475
00476 stream << controlPoint.getColourLab().a;
00477 TiXmlText * colourAText = new TiXmlText(stream.str().c_str());
00478 stream.str("");
00479 colourA->LinkEndChild( colourAText );
00480
00481 stream << controlPoint.getColourLab().b;
00482 TiXmlText * colourBText = new TiXmlText(stream.str().c_str());
00483 stream.str("");
00484 colourB->LinkEndChild( colourBText );
00485 }
00486
00487
00488 doc.SaveFile(file);
00489 }
00490
00491
00492 void TransferFunctionGUI::loadTransferFunctionControlPoints(std::string file)
00493 {
00494 TiXmlDocument doc(file.c_str());
00495
00496 bool loadOkay = doc.LoadFile();
00497 if (loadOkay)
00498 {
00499 controlPoints.clear();
00500
00501
00502 for (TiXmlNode* pChild = doc.FirstChild(); pChild != 0; pChild = pChild->NextSibling())
00503 {
00504 if(pChild->Type() == TiXmlNode::TINYXML_ELEMENT
00505 && std::string(pChild->Value()).compare("ControlPoint") == 0)
00506 {
00507 float xRel = 0.f;
00508 float yRel = 0.f;
00509 float colourL = 0.f;
00510 float colourA = 0.f;
00511 float colourB = 0.f;
00512
00513 for (TiXmlNode* pChildAttribute = pChild->FirstChild(); pChildAttribute != 0; pChildAttribute = pChildAttribute->NextSibling())
00514 {
00515 if(pChildAttribute->Type() == TiXmlNode::TINYXML_ELEMENT)
00516 {
00517 if( std::string(pChildAttribute->Value()).compare("xRel") == 0)
00518 xRel = (float)atof(pChildAttribute->FirstChild()->Value());
00519
00520 else if( std::string(pChildAttribute->Value()).compare("yRel") == 0)
00521 yRel = (float)atof(pChildAttribute->FirstChild()->Value());
00522
00523 else if( std::string(pChildAttribute->Value()).compare("colourL") == 0)
00524 colourL = (float)atof(pChildAttribute->FirstChild()->Value());
00525
00526 else if( std::string(pChildAttribute->Value()).compare("colourA") == 0)
00527 colourA = (float)atof(pChildAttribute->FirstChild()->Value());
00528
00529 else if( std::string(pChildAttribute->Value()).compare("colourB") == 0)
00530 colourB = (float)atof(pChildAttribute->FirstChild()->Value());
00531 }
00532 }
00533
00534
00535 controlPoints.push_back(TFControlPoint(xRel, yRel, Lab_Colour(colourL, colourA, colourB)));
00536 }
00537 }
00538 }
00539 else
00540 {
00541 printf("Failed to load file \"%s\"\n", file);
00542 }
00543
00544 }