TuttleOFX  1
ColorSpaceKeyerOverlay.cpp
Go to the documentation of this file.
00001 #include <tuttle/common/system/windows/windows.h>
00002 
00003 #include <GL/glew.h>
00004 #include <tuttle/plugin/opengl/gl.h>
00005 
00006 
00007 #include "ColorSpaceKeyerOverlay.hpp"
00008 
00009 
00010 namespace tuttle {
00011 namespace plugin {
00012 namespace colorSpaceKeyer {
00013         
00014 /*
00015  * Constructor
00016  * @param handle
00017  * @param effect
00018  */
00019 ColorSpaceKeyerOverlay::ColorSpaceKeyerOverlay(OfxInteractHandle handle,OFX::ImageEffect* effect)
00020 : OFX::OverlayInteract(handle)
00021 , _infos(effect)
00022 {       
00023         _plugin = static_cast<ColorSpaceKeyerPlugin*>(_effect); //get plugin
00024         _plugin->addRefCloudPointData();                                //create pointer to overlay data
00025         
00026         _isPenDown = false;                                                             //mouse is not under control by default
00027         _isCtrlKeyDown = false;                                                 //Ctrl key is not pressed by default
00028         _rotateX = _rotateY = 0.0;                                              //initialize rotation to 0
00029         _rotateXForm = _rotateYForm = 0.0;                              //initialize rotation centered to geodesic form to 0
00030         _origin.x = _origin.y = _end.x = _end.y = 0;    //initialize mouse positions to 0
00031         
00032         setToIdentity(_modelViewMatrix);                                //set model view matrix to identity
00033         
00034         ///HACK : to initialize correctly overlay display data
00035         OFX::InstanceChangedArgs args;                                  //create instance changed arguments
00036         _plugin->changedParam(args,kPointCloudDisplay); //call changed parameters function to initialize overlay data
00037 }
00038 
00039 /*
00040  * Destructor
00041  */
00042 ColorSpaceKeyerOverlay::~ColorSpaceKeyerOverlay() 
00043 {
00044         _plugin->releaseCloudPointData();       //release Overlay data
00045 }
00046 
00047 /*
00048  * Prepare the OpenGL scene for drawing (projection and frustrum settings)
00049  */
00050 void ColorSpaceKeyerOverlay::prepareOpenGLScene(const OFX::DrawArgs& args)
00051 {       
00052         //reset OpenGL scene (remove previous image)
00053         glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00054         //change background color to gray
00055         glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
00056         
00057         //get projection matrix
00058         GLdouble proj_matrix[16];
00059         glGetDoublev(GL_PROJECTION_MATRIX, proj_matrix);
00060         //initialize model-view and projection matrixes to identity
00061         glMatrixMode( GL_PROJECTION );                                                          // load standard mode
00062         glLoadIdentity();                                                                       // projection to identity
00063         glMatrixMode( GL_MODELVIEW );                                                           // load standard mode
00064         glLoadIdentity();                                                                       // model-view to identity
00065         
00066         //get current viewport size     
00067         GLint viewport[4] = { 0, 0, 0, 0 };                                                     // define result array
00068         glGetIntegerv(GL_VIEWPORT,viewport);                                                    // get current viewport size
00069         const double ratio = (viewport[2]-viewport[0]) / (double)(viewport[3]-viewport[1]);     // compute ratio
00070         //define new coordinates
00071         glOrtho( 0.0, 1.0, 0.0, 1.0, -1.0, 1.0 );                                               // set coordinates to 0-1
00072         
00073         if(args.time != getData()._time || args.time != getData()._averageColor._time)          // if current overlay has not been updated
00074         {
00075                 //display warning sign on screen
00076                 Ofx3DPointD warningPoint;                                                       // initialize warning drawing point
00077                 warningPoint.x = 0.15;                                                          // x == viewport width/7;
00078                 warningPoint.y = 0.2;                                                           // y == viewport height/5;
00079                 drawWarning(warningPoint, ratio);                                               // draw warning sign
00080         }
00081         
00082         //define openGL scene frustrum
00083         glMatrixMode( GL_PROJECTION );                                                          // load standard mode
00084         glLoadMatrixd( proj_matrix );                                                           // reload previous projection matrix
00085                         
00086         const GLdouble vleft   = - 0.5;                                                          //frustrum left
00087         const GLdouble vright  =   1.5;                                                          //frustrum right
00088         const GLdouble vbottom = - 0.5;                                                          //frustrum bottom
00089         const GLdouble vtop    =   1.5;                                                          //frustrum top
00090         const GLdouble vnear   =  10.0;                                                          //frustrum near
00091         const GLdouble vfar    = -10.0;                                                          //frustrum far
00092         glOrtho( vleft, vright, vbottom, vtop, vnear, vfar);                                          //define new frustrum for overlay data
00093         
00094         glMatrixMode( GL_MODELVIEW );                                                           //load standard mode
00095         //initialize double* modelViewMatrix
00096         double modelViewMatrix[16];                                                             //initialize
00097         for(unsigned int i=0; i<16; ++i)
00098                 modelViewMatrix[i] = _modelViewMatrix[i];       //recopy Matrix4 into double*
00099         glLoadMatrixd(modelViewMatrix);//load modelView matrix (first time is equal to identity)
00100 }
00101 
00102 /*
00103  * Draw the x,Y and Z axes into the OpenGL scene
00104  */
00105 void ColorSpaceKeyerOverlay::drawAxes()
00106 {
00107         glBegin(GL_LINES);
00108         //X axis (black => red)
00109         glColor3f(0.0f,0.0f,0.0f); glVertex2i(0,0);             //color and direction (0,0,0)
00110     glColor3f(1.0f,0.0f,0.0f); glVertex2i(1,0);         //color and direction (1,0,0)
00111         //Y axis (black => green)
00112         glColor3f(0.0f,0.0f,0.0f); glVertex2i(0,0);             //color and direction (0,0,0)
00113     glColor3f(0.0f,1.0f,0.0f); glVertex2i(0,1);         //color and direction (0,1,0)
00114     //Z axis (black => blue)
00115         glColor3f(0.0f,0.0f,0.0f); glVertex2i(0,0);             //color and direction (0,0,0)
00116         glColor3f(0.0f,0.0f,1.0f); glVertex3i(0,0,1);   //color and direction (0,0,1)
00117         //axis (red => yellow)
00118         glColor3f(1.0f,0.0f,0.0f); glVertex2i(1,0);             //red
00119         glColor3f(1.0f,1.0f,0.0f); glVertex2i(1,1);             //yellow
00120         //axis (red => yellow)
00121         glColor3f(0.0f,1.0f,0.0f); glVertex2i(0,1);             //green
00122         glColor3f(1.0f,1.0f,0.0f); glVertex2i(1,1);             //yellow
00123         //axis (green => cyan)
00124         glColor3f(0.0f,1.0f,0.0f); glVertex2i(0,1);             //green
00125         glColor3f(0.0f,1.0f,1.0f); glVertex3i(0,1,1);   //cyan
00126         //axis (blue => cyan)
00127         glColor3f(0.0f,0.0f,1.0f); glVertex3i(0,0,1);   //blue
00128         glColor3f(0.0f,1.0f,1.0f); glVertex3i(0,1,1);   //cyan
00129         //axis (cyan => white)
00130         glColor3f(1.0f,1.0f,1.0f); glVertex3i(1,1,1);   //white
00131         glColor3f(0.0f,1.0f,1.0f); glVertex3i(0,1,1);   //cyan
00132         //axis (yellow => white)
00133         glColor3f(1.0f,1.0f,1.0f); glVertex3i(1,1,1);   //white
00134         glColor3f(1.0f,1.0f,0.0f); glVertex2i(1,1);             //yellow
00135         //axis (magenta => white)
00136         glColor3f(1.0f,1.0f,1.0f); glVertex3i(1,1,1);   //white
00137         glColor3f(1.0f,0.0f,1.0f); glVertex3i(1,0,1);   //magenta
00138         //axis (magenta => blue)
00139         glColor3f(0.0f,0.0f,1.0f); glVertex3i(0,0,1);   //blue
00140         glColor3f(1.0f,0.0f,1.0f); glVertex3i(1,0,1);   //magenta
00141         //axis (magenta => red)
00142         glColor3f(1.0f,0.0f,0.0f); glVertex2i(1,0);             //red
00143         glColor3f(1.0f,0.0f,1.0f); glVertex3i(1,0,1);   //magenta
00144         //axis (white => black)
00145         glColor3f(1.0f,1.0f,1.0f); glVertex3i(1,1,1);   //white
00146         glColor3f(0.0f,0.0f,0.0f); glVertex2i(0,0);             //black
00147         glEnd();
00148         
00149         glPointSize(6.0f);
00150         glBegin(GL_POINTS);
00151         glColor3f(0.0f,0.0f,0.0f); glVertex2i(0,0);             //black 
00152         glColor3f(1.0f,0.0f,0.0f); glVertex2i(1,0);             //red
00153         glColor3f(0.0f,1.0f,0.0f); glVertex2i(0,1);             //green
00154         glColor3f(0.0f,0.0f,1.0f); glVertex3i(0,0,1);   //blue
00155         glColor3f(1.0f,1.0f,1.0f); glVertex3i(1,1,1);   //white
00156         glColor3f(1.0f,0.0f,1.0f); glVertex3i(1,0,1);   //magenta
00157         glColor3f(0.0f,1.0f,1.0f); glVertex3i(0,1,1);   //cyan
00158         glColor3f(1.0f,1.0f,0.0f); glVertex2i(1,1);             //yellow
00159         
00160         glPointSize(1.0f);
00161         glEnd();
00162 }
00163 
00164 /*
00165  * Main display of the ColorSpaceKeyerOverlay class
00166  * @param args current arg (time/renderScale/pixelScale....
00167  * @return if there is something drawed by the function (y or n)
00168  */
00169 bool ColorSpaceKeyerOverlay::draw( const OFX::DrawArgs& args )
00170 {
00171         bool displaySomethings = false;
00172         if( _plugin->_paramBoolPointCloudDisplay->getValue() ) //Is CloudPointData displayed ? (GUI)
00173         {
00174                 glPushMatrix();                                                         //new transformation
00175                 prepareOpenGLScene(args);                                       //prepare frustum and projection settings
00176                 if(_plugin->_updateVBO )                                        //VBO need to be updated
00177                 {
00178                         //update VBO
00179                         getData().updateVBO();                                  //update VBO from VBO data (already computed)
00180                         _plugin->_updateVBO = false;                    //VBO has been recomputed
00181                 }
00182                 if(_plugin->_resetViewParameters)                       //View parameters need to be reseted
00183                 {
00184                         _rotateX = _rotateY = 0;                                //reset parameters
00185                         _rotateXForm = _rotateYForm = 0;                //reset geodesic form center rotation parameters
00186                         _plugin->_resetViewParameters = false;  //view parameters has been changed
00187                         setToIdentity(_modelViewMatrix);                //reset model-view matrix to identity
00188                 }
00189                 //OpenGL parameters
00190                 glEnable(GL_DEPTH_TEST);                                        //active depth (better for understand results)
00191                 
00192                 //drawing Axes
00193                 drawAxes();                                                                     //draw the X, Y and Z axes
00194                 //drawing VBO
00195                 if(getData()._isVBOBuilt)                                       //if VBO has already been built
00196                         getData()._imgVBO.draw();                               //draw VBO
00197                 
00198                 //drawing color selection VBO
00199                 if(getData()._isSelectionVBOBuilt && _plugin->_paramBoolSeeSelection->getValue())       //color selection VBO data is built
00200                 {
00201                         glColor3f(1.0f,1.0f,1.0f);                                                                                                              //color is white
00202                         getData()._selectionColorVBO.draw();                                                                                    //draw selection VBO
00203                 }
00204                 //drawing spill selection VBO
00205                 if(getData()._isSpillSelectionVBOBuilt && _plugin->_paramBoolSeeSpillSelection->getValue()) //spill selection VBO data is built
00206                 {
00207                         glColor3f(.3f,.3f,.3f);                                                                                                         //color is white
00208                         getData()._selectionSpillVBO.draw();                                                                            //draw selection VBO
00209                 }
00210                 
00211                 //drawing average
00212                 getData()._averageColor.draw();                                                         //draw average (cross)
00213                 //drawing geodesic form
00214                 if(_plugin->_paramBoolDisplayGeodesicForm->getValue())          //does user want to display color geodesic form
00215                         getData()._geodesicFormColor.draw(false);                               //draw geodesic form on screen without alpha
00216                 if(_plugin->_paramBoolDisplaySpillGF->getValue())                       //does user want to display spill geodesic form
00217                         getData()._geodesicFormSpill.draw(true);                                //draw spill geodesic form on screen with alpha
00218                 
00219                 //OpenGL end of parameters
00220                 glDisable(GL_DEPTH_TEST);       //disable deep
00221                 glPopMatrix();                          //pop matrix
00222                 displaySomethings = true;       //something has been drown on screen
00223         }
00224         return displaySomethings;               //return if overlay has displayed something (y or n)
00225 }
00226 
00227 /*
00228  * Capture and treat click down event
00229  * @param args current argument (time/renderScale/pixelScale....
00230  * @return if the event has been treated (y or n)
00231  */
00232 bool ColorSpaceKeyerOverlay::penDown( const OFX::PenArgs& args )
00233 {
00234         if(!_isPenDown)                                                                 //is mouse is not already selected
00235         {
00236                 _isPenDown = true;                                                      //active mouse operation (for penMotion)
00237                 _origin.x = _end.x = args.penPosition.x;        //capture x position of current click
00238                 _origin.y = _end.y = args.penPosition.y;        //capture y position of current click
00239                 return true;                                                            //event has been captured
00240         }
00241         return false;                                                                   //event has not been captured
00242 }
00243 
00244 /*
00245  * Capture and treat click up event (release mouse)
00246  * @param args current argument (time/renderScale/pixelScale....
00247  * @return if the event has been treated (y or n)
00248  */
00249 bool ColorSpaceKeyerOverlay::penUp( const OFX::PenArgs& args )
00250 {
00251         if(_isPenDown)                                          //is mouse is already selected
00252         {
00253                 _isPenDown = false;                             //mouse is no more selected
00254                 _end.x = args.penPosition.x;    //capture mouse current position x
00255                 _end.y = args.penPosition.y;    //capture mouse current position y
00256                 
00257                 if(_origin.x == _end.x && _origin.y == _end.y)
00258                         return false;                           //basic click (there is nothing to do in this case)
00259                 return true;                                    //event has been captured
00260         }
00261         return false;                                           //event has not been captured
00262 }
00263 
00264 /*
00265  * Treat if mouse/pen is under motion (drawing on screen for example)
00266  * @param args current arg (time/renderScale/pixelScale....
00267  * @return if the event has been treated (y or n)
00268  */
00269 bool ColorSpaceKeyerOverlay::penMotion( const OFX::PenArgs& args )
00270 {
00271         if(_isPenDown)                                                                                                          //if mouse is already selected
00272         {
00273                 _end.x = args.penPosition.x;                                                                    //capture mouse current position x
00274                 _end.y = args.penPosition.y;                                                                    //capture mouse current position y
00275                 
00276                 int deltaX = _end.x - _origin.x;                                                                //compute delta for rotation on Y axis (horizontal)
00277                 int deltaY = _end.y - _origin.y;                                                                //compute delta for rotation on X axis (vertical)
00278                 if(_isCtrlKeyDown)                                                                                              //rotation center is current color selection average
00279                 {
00280                         _rotateXForm = (deltaX/args.pixelScale.x)/kRotationSpeed;       //add delta to geodesic center rotation (X axis)
00281                         _rotateYForm = (deltaY/args.pixelScale.y)/kRotationSpeed;       //add delta to geodesic center rotation (Y axis)
00282                         
00283                         //update model-View matrix
00284                         Ofx3DPointD rotationCenter = getData()._geodesicFormColor._center;      //get current rotation center
00285                         updateModelView(rotationCenter);                                                                //update model-view
00286                 }
00287                 else                                                                                                                    //rotation center is reference center (0.5,0.5,0.5 in cube reference)
00288                 {
00289                         _rotateX = (deltaX/args.pixelScale.x)/kRotationSpeed;           //add delta to cube rotation (X axis)
00290                         _rotateY = (deltaY/args.pixelScale.y)/kRotationSpeed;           //add delta to cube rotation (Y axis)
00291                         
00292                         //update model-View matrix
00293                         Ofx3DPointD rotationCenter;                                                                     //create rotation center
00294                         rotationCenter.x = 0.5;                                                                         //set rotation center X value 0 by default
00295                         rotationCenter.y = 0.5;                                                                         //set rotation center Y value
00296                         rotationCenter.z = 0.5;                                                                         //set rotation center Z value
00297                         updateModelView(rotationCenter);                                                        //update model-view
00298                 }
00299                 _origin.x = args.penPosition.x;                                                                 //change origin X (prepare next penMotion)
00300                 _origin.y = args.penPosition.y;                                                                 //change origin Y (prepare next penMotion)
00301                 
00302                 return true;                                                                                                    //event has been captured
00303         }
00304         return false;
00305 }
00306 
00307 /*
00308  * Treat the Ctrl key pressed (down)
00309  * @param args current arg (time/rendeerScale/...)
00310  * @return  if the event has been treated (y or n)
00311  */
00312 bool ColorSpaceKeyerOverlay::keyDown( const OFX::KeyArgs& args )
00313 {
00314         if(args.keySymbol==kOfxKey_Control_L||args.keySymbol==kOfxKey_Control_R) //if the pressed key is Ctrl key (left or right)
00315         {
00316                 _isCtrlKeyDown = true;  //Ctrl key is pressed
00317                 return true;                    //event has been treated
00318         }
00319         return false;                           //event has not been treated (key pressed is not Ctrl)
00320 }
00321 
00322 /*
00323  * Treat the Ctrl key pressed (up)
00324  * @param args current arg (time/rendeerScale/...)
00325  * @return  if the event has been treated (y or n)
00326  */
00327 bool ColorSpaceKeyerOverlay::keyUp( const OFX::KeyArgs& args )
00328 {
00329         if(args.keySymbol==kOfxKey_Control_L||args.keySymbol==kOfxKey_Control_R) //if the pressed key is Ctrl key (left or right)
00330         {
00331                 if(_isCtrlKeyDown)
00332                         _isCtrlKeyDown = false; //Ctrl key is not pressed anymore
00333                 return true;                            //event has been treated
00334         }
00335         return false;                                   //event has not been treated (key pressed is not Ctrl)
00336 }
00337 
00338 /*
00339  * Get cloud point data from ColorSpaceKeyerPlugin
00340  * @return 
00341  */
00342 CloudPointData& ColorSpaceKeyerOverlay::getData()
00343 {
00344         return _plugin->getCloudPointData();    //return CloudPointData initialized at constructor (by scoped pointer)
00345 }
00346 
00347 
00348 
00349 /*
00350  * Update the average coordinates with center rotation
00351  */
00352 void ColorSpaceKeyerOverlay::updateModelView(const Ofx3DPointD& rotationCenter)
00353 {       
00354         //Define and create new transformation matrix
00355         Matrix4 newTransformationMatrix;                                                                                                                                        //initialize new transformation matrix
00356         if(rotationCenter.x == 0.5 && rotationCenter.y == 0.5 && rotationCenter.z == 0.5)                                       //if current rotation center is reference center
00357                 newTransformationMatrix = constructRotationMatrix(rotationCenter,_rotateY,_rotateX,0);                  //construct new transformation matrix
00358         else                                                                                                                                                                                            //current rotation center is geodesic form center
00359                 newTransformationMatrix = constructRotationMatrix(rotationCenter,_rotateYForm,_rotateXForm,0);  //construct new transformation matrix
00360         //X and Y angles are inverted (better to control view)
00361         //Add current transformation to model-view matrix
00362         multMatrixBtoMatrixA(_modelViewMatrix,newTransformationMatrix);                                                                         //add current transformation to model-view matrix
00363 }
00364 
00365 /*
00366  * Draw a warning sign on the openGL scene
00367  */
00368 void ColorSpaceKeyerOverlay::drawWarning(const Ofx3DPointD& centerPoint, const double ratio)
00369 {
00370         float size = 5.0f;                                                                                              //define size
00371         glColor3f(1.0f,.7f,0);                                                                                  //color orange
00372         glLineWidth(size);                                                                                              //change line width (bigger)
00373         //draw triangle
00374         glBegin(GL_LINE_STRIP);                                                                                 //draw exterior triangle
00375         glVertex2d((centerPoint.x - 0.025*ratio),centerPoint.y);                //first point of triangle
00376         glVertex2d((centerPoint.x + 0.025*ratio),centerPoint.y);                //second point of triangle
00377         glVertex2d(centerPoint.x,(centerPoint.y+0.085*ratio));                  //third point of triangle
00378         glVertex2d((centerPoint.x - 0.025*ratio),centerPoint.y);                //first point of triangle (boucle)
00379         glEnd();                                                                                                                //end of drawing
00380         //draw !
00381         glBegin(GL_LINES);                                                                                              //draw ! sign
00382         glVertex2d(centerPoint.x, (centerPoint.y+0.07*ratio));                  //first point
00383         glVertex2d(centerPoint.x, (centerPoint.y+0.03*ratio));                  //second point
00384         glEnd();                                                                                                                //end of drawing
00385         glBegin(GL_POINTS);                                                                                             //draw ! point
00386         glPointSize(size);                                                                                              //change point size (bigger)
00387         glVertex2d(centerPoint.x, (centerPoint.y + 0.02*ratio));                //point of !
00388         glEnd();                                                                                                                //end of drawing
00389         //reset basic parameters
00390         glLineWidth(1.0f);                                                                                              //reset line width (normal)
00391         glPointSize(1.0f);                                                                                              //reset point size (normal)
00392 }
00393 
00394 
00395 }
00396 }
00397 }
00398