TuttleOFX
1
|
00001 #include <GL/glew.h> // need to be included before gl.h 00002 00003 #include "CloudPointData.hpp" 00004 00005 #include <tuttle/plugin/opengl/gl.h> 00006 00007 #include <terry/algorithm/transform_pixels.hpp> 00008 00009 00010 namespace tuttle { 00011 namespace plugin { 00012 namespace colorCubeViewer { 00013 00014 CloudPointData::CloudPointData(const OfxPointI& size, OfxTime time): 00015 _averageColor(time) //Selection average constructor (current time is needed) 00016 { 00017 _size = size; //define first size (current clip number of pixels) 00018 _time = time; //get current time 00019 00020 // cloud point VBO 00021 int imgSize = size.x*size.y; // number of pixel in the image 00022 _imgCopy.reserve( imgSize * 0.5 ); //reserve memory for buffer 00023 00024 //selection buffer 00025 _selectionCopy.reserve( imgSize * 0.5); //reserve memory for color selection buffer 00026 _spillCopy.reserve( imgSize * 0.5); //reserve memory for spill selection buffer 00027 00028 //VBO are not built at this time 00029 _isVBOBuilt = false; //cloud point VBO is not built 00030 _isSelectionVBOBuilt = false; //color selection VBO is not built 00031 _isSpillSelectionVBOBuilt = false; //spill selection VBO is not built 00032 } 00033 00034 /** 00035 * Open src clip return if opening has been done (y or n) 00036 * @param clipSrc source of the plugin 00037 * @param renderScale current renderScale 00038 */ 00039 bool CloudPointData::generateVBOData( OFX::Clip* clipSrc, const OfxPointD& renderScale, const bool vboWithDiscretization, const int discretizationStep) 00040 { 00041 _isVBOBuilt = false; //VBO is not built anymore 00042 // connection test 00043 if( ! clipSrc->isConnected() ) 00044 { 00045 return false; 00046 } 00047 boost::scoped_ptr<OFX::Image> src( clipSrc->fetchImage(_time, clipSrc->getCanonicalRod(_time)) ); //scoped pointer of current source clip 00048 // Compatibility tests 00049 if( !src.get() ) // source isn't accessible 00050 { 00051 std::cout << "src is not accessible (cloud point)" << std::endl; 00052 return false; 00053 } 00054 if( src->getRowDistanceBytes() == 0 )//if source is wrong 00055 { 00056 BOOST_THROW_EXCEPTION( exception::WrongRowBytes() ); 00057 return false; 00058 } 00059 const OfxRectI srcPixelRod = clipSrc->getPixelRod( _time, renderScale ); //get current RoD 00060 if( (clipSrc->getPixelDepth() != OFX::eBitDepthFloat) || 00061 (clipSrc->getPixelComponents() == OFX::ePixelComponentNone) ) 00062 { 00063 BOOST_THROW_EXCEPTION( exception::Unsupported() << exception::user() + "Can't compute histogram data with the actual input clip format." ); 00064 return false; 00065 } 00066 00067 if( srcPixelRod != src->getBounds() )// the host does bad things ! 00068 { 00069 // remove overlay... but do not crash. 00070 TUTTLE_LOG_WARNING( "Image RoD and image bounds are not the same (rod=" << srcPixelRod << " , bounds:" << src->getBounds() << ")." ); 00071 return false; 00072 } 00073 // Compute if source is OK 00074 SView srcView = tuttle::plugin::getGilView<SView>( src.get(), srcPixelRod, eImageOrientationIndependant ); // get current view from source clip 00075 00076 _imgCopy.clear(); //clear buffer 00077 if( vboWithDiscretization ) //does user want to discretize the VBO 00078 { 00079 generateDiscretizedVBOData( srcView, discretizationStep); //create data and return buffer size 00080 } 00081 else 00082 { 00083 generateAllPointsVBOData( srcView ); // create data and return buffer size 00084 } 00085 _isVBOBuilt = true; //VBO has been built 00086 return true; 00087 } 00088 00089 /** 00090 * create the VBO from VBO data (draw function) 00091 */ 00092 void CloudPointData::updateVBO() 00093 { 00094 //point cloud VBO 00095 _imgVBO.createVBO( &(_imgCopy.front()), _imgCopy.size() / 3 ); //generate VBO to draw 00096 _imgVBO._color = true; //activate color for VBO 00097 //color selection VBO 00098 _selectionColorVBO._colorDifferent = true; //color buffer is not the same than vertex buffer 00099 _selectionColorVBO._color = false; //disable color for VBO 00100 _selectionColorVBO.createVBO(&(_selectionCopy.front()), _selectionCopy.size()/3,GL_STATIC_DRAW ,&(_selectionCopy.front())); //generate color selection VBO to draw 00101 //spill selection VBO 00102 _selectionSpillVBO._colorDifferent = true; //color buffer is not the same than vertex buffer 00103 _selectionSpillVBO._color = false; //disable color for VBO 00104 _selectionSpillVBO.createVBO(&(_spillCopy.front()), _spillCopy.size()/3,GL_STATIC_DRAW ,&(_spillCopy.front())); //generate spill selection VBO to draw 00105 } 00106 00107 /* 00108 * Copy RGB channels of the clip source into a buffer 00109 */ 00110 int CloudPointData::generateAllPointsVBOData(SView srcView) 00111 { 00112 //compute buffer size 00113 int size = (int)(srcView.height()*srcView.width()); //return size : full image here 00114 00115 //copy full image into buffer 00116 Pixel_copy funct( _imgCopy ); //functor declaration 00117 //treatment 00118 terry::algorithm::transform_pixels( srcView, funct ); //transform pixel did with functor reference 00119 return size; 00120 } 00121 00122 /* 00123 * Copy discretization RGB channels of the clip source into a buffer 00124 */ 00125 int CloudPointData::generateDiscretizedVBOData(SView srcView, const int& discretizationStep ) 00126 { 00127 //compute buffer size 00128 int size = (int)(srcView.height()*srcView.width()); //return size : full image here 00129 00130 //Create and use functor to get discretize data (functor with template) 00131 Pixel_copy_discretization<SPixel> funct(_imgCopy,discretizationStep); //functor declaration 00132 terry::algorithm::transform_pixels( srcView, funct); //with functor reference 00133 funct.convertSetDataToVectorData(); //copy functor data to _imgCopy data 00134 size = _imgCopy.size(); //change size 00135 return size; 00136 } 00137 00138 /* 00139 * 00140 */ 00141 bool CloudPointData::generateColorSelectionVBO(OFX::Clip* clipColor, const OfxPointD& renderScale, bool vboWithDiscretization, int discretizationStep) 00142 { 00143 _isSelectionVBOBuilt = false; // selection VBO is not built 00144 // connection test 00145 if( ! clipColor->isConnected() ) 00146 { 00147 return false; 00148 } 00149 00150 boost::scoped_ptr<OFX::Image> src( clipColor->fetchImage(_time, clipColor->getCanonicalRod(_time)) ); //scoped pointer of current color clip 00151 00152 // Compatibility tests 00153 if( !src.get() ) // color clip source isn't accessible 00154 { 00155 std::cout << "src is not accessible (color clip)" << std::endl; 00156 return false; 00157 } 00158 if( src->getRowDistanceBytes() == 0 )//if source is wrong 00159 { 00160 BOOST_THROW_EXCEPTION( exception::WrongRowBytes() ); 00161 return false; 00162 } 00163 const OfxRectI srcPixelRod = clipColor->getPixelRod( _time, renderScale ); //get current RoD 00164 if( (clipColor->getPixelDepth() != OFX::eBitDepthFloat) || 00165 (clipColor->getPixelComponents() == OFX::ePixelComponentNone) ) 00166 { 00167 BOOST_THROW_EXCEPTION( exception::Unsupported() << exception::user() + "Can't compute histogram data with the actual input clip format." ); 00168 return false; 00169 } 00170 if( srcPixelRod != src->getBounds() )// the host does bad things ! 00171 { 00172 // remove overlay... but do not crash. 00173 TUTTLE_LOG_WARNING( "Image RoD and image bounds are not the same (rod=" << srcPixelRod << " , bounds:" << src->getBounds() << ")." ); 00174 return false; 00175 } 00176 // Compute if source is OK 00177 SView srcView = tuttle::plugin::getGilView<SView>( src.get(), srcPixelRod, eImageOrientationIndependant ); // get current view from source clip 00178 00179 if(vboWithDiscretization) //there is discretization on VBO 00180 { 00181 //treatment VBO discretization (maybe) 00182 } 00183 //VBO without discretization 00184 generateAllPointsSelectionVBOData(srcView); //generate a selection VBO without discretization 00185 00186 _isSelectionVBOBuilt = true; // selection VBO is not built 00187 return true; // treatment has been done correctly 00188 } 00189 00190 /* 00191 * Copy RGB channels of the selected pixels in clip source into a buffer 00192 */ 00193 int CloudPointData::generateAllPointsSelectionVBOData(SView srcView) 00194 { 00195 //compute buffer size 00196 int size; //returned size 00197 bool isSelection = true; //current operations are on selected pixels 00198 00199 //clear selection copy 00200 _selectionCopy.clear(); //clear selection VBO data 00201 00202 //copy full image into buffer 00203 Pixel_copy funct(_selectionCopy, isSelection); //functor declaration creation 00204 //treatment 00205 terry::algorithm::transform_pixels( srcView, funct ); //transform pixel did with functor reference 00206 size = _selectionCopy.size(); //get current size of VBO 00207 00208 return size; //return size of VBO buffers (same color and vertex) 00209 } 00210 00211 /* 00212 * 00213 */ 00214 bool CloudPointData::generateSpillSelectionVBO(OFX::Clip* clipSpill, const OfxPointD& renderScale, bool vboWithDiscretization, int discretizationStep) 00215 { 00216 _isSpillSelectionVBOBuilt = false; // selection VBO is not built 00217 // connection test 00218 if( ! clipSpill->isConnected() ) 00219 { 00220 return false; 00221 } 00222 00223 boost::scoped_ptr<OFX::Image> src( clipSpill->fetchImage(_time, clipSpill->getCanonicalRod(_time)) ); //scoped pointer of current color clip 00224 00225 // Compatibility tests 00226 if( !src.get() ) // color clip source isn't accessible 00227 { 00228 std::cout << "src is not accessible (spill clip)" << std::endl; 00229 return false; 00230 } 00231 if( src->getRowDistanceBytes() == 0 )//if source is wrong 00232 { 00233 BOOST_THROW_EXCEPTION( exception::WrongRowBytes() ); 00234 return false; 00235 } 00236 const OfxRectI srcPixelRod = clipSpill->getPixelRod( _time, renderScale ); //get current RoD 00237 if( (clipSpill->getPixelDepth() != OFX::eBitDepthFloat) || 00238 (clipSpill->getPixelComponents() == OFX::ePixelComponentNone) ) 00239 { 00240 BOOST_THROW_EXCEPTION( exception::Unsupported() << exception::user() + "Can't compute histogram data with the actual input clip format." ); 00241 return false; 00242 } 00243 if( srcPixelRod != src->getBounds() )// the host does bad things ! 00244 { 00245 // remove overlay... but do not crash. 00246 TUTTLE_LOG_WARNING( "Image RoD and image bounds are not the same (rod=" << srcPixelRod << " , bounds:" << src->getBounds() << ")." ); 00247 return false; 00248 } 00249 // Compute if source is OK 00250 SView srcView = tuttle::plugin::getGilView<SView>( src.get(), srcPixelRod, eImageOrientationIndependant ); // get current view from source clip 00251 00252 if( vboWithDiscretization ) //there is discretization on VBO 00253 { 00254 //treatment VBO discretization (maybe) 00255 } 00256 //VBO without discretization 00257 generateAllPointsSpillVBOData( srcView ); //generate a selection VBO without discretization 00258 _isSpillSelectionVBOBuilt = true; // selection VBO is not built 00259 return true; // treatment has been done correctly 00260 } 00261 00262 /* 00263 * Copy RGB channels of the selected pixels in clip source into a buffer 00264 */ 00265 int CloudPointData::generateAllPointsSpillVBOData(SView srcView) 00266 { 00267 //compute buffer size 00268 int size; //returned size 00269 bool isSelection = true; //current operations are on selected pixels 00270 00271 //clear selection copy 00272 _spillCopy.clear(); //clear selection VBO data 00273 00274 //copy full image into buffer 00275 Pixel_copy funct(_spillCopy, isSelection); //functor declaration creation 00276 //treatment 00277 terry::algorithm::transform_pixels( srcView, funct ); //transform pixel did with functor reference 00278 00279 size = _spillCopy.size(); //get current size of VBO 00280 return size; //return size of VBO buffers (same color and vertex) 00281 } 00282 00283 00284 //////////////////////////////////////////////////////////////////////////////// 00285 // CloudPoint::VBO // 00286 //////////////////////////////////////////////////////////////////////////////// 00287 00288 /** 00289 * Constructor 00290 * @param data data used to create VBO 00291 * @param size size of VBO 00292 * @param usage usage of VBO 00293 */ 00294 void CloudPointData::VBO::createVBO( const void* data, int size, GLenum usage, const void* dataColor ) 00295 { 00296 _size = size; 00297 genBuffer( _id, data, size, GL_ARRAY_BUFFER, usage ); 00298 } 00299 00300 /** 00301 * destroy a VBO 00302 * If VBO id is not valid or zero, then OpenGL ignores it silently. 00303 */ 00304 void CloudPointData::VBO::deleteVBO( ) 00305 { 00306 if( _id != 0 ) //if VBO exists 00307 { 00308 glDeleteBuffers( 1, &_id ); 00309 _id = 0; // 0 is reserved, glGenBuffersARB() will return non-zero id if success 00310 } 00311 if( _idColor != 0) 00312 { 00313 glDeleteBuffers(1, &_idColor); //delete color buffer 00314 _idColor = 0; //reset color id 00315 } 00316 } 00317 00318 /** 00319 * generate vertex buffer object and bind it with its data 00320 * You must give 2 hints about data usage; target and mode, so that OpenGL can 00321 * decide which data should be stored and its location. 00322 * VBO works with 2 different targets; GL_ARRAY_BUFFER for vertex arrays 00323 * and GL_ELEMENT_ARRAY_BUFFER for index array in glDrawElements(). 00324 * The default target is GL_ARRAY_BUFFER. 00325 * By default, usage mode is set as GL_STATIC_DRAW. 00326 * Other usages are GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY, 00327 * GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY, 00328 * GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, GL_DYNAMIC_COPY. 00329 */ 00330 void CloudPointData::VBO::genBuffer( unsigned int& id, const void* data, int size, GLenum target, GLenum usage ) 00331 { 00332 //Test if buffer is not already existing 00333 if( id != 0 ) //if id is not null 00334 deleteVBO( ); //delete current VBO 00335 00336 const int dataSize = size * 3 * sizeof(float); //current size of data 00337 00338 //Buffer creation 00339 glGenBuffers( 1, &(_id) ); // create a VBO 00340 glBindBuffer( target, _id ); // activate VBO id to use 00341 glBufferData( target, dataSize, data, usage ); // upload data to video card 00342 00343 00344 // check data size in VBO is same as input array, if not return 0 and delete VBO 00345 int bufferSize = 0; 00346 glGetBufferParameteriv( target, GL_BUFFER_SIZE, &bufferSize ); 00347 if( dataSize != bufferSize ) //mismatch between data size and input array (control) 00348 { 00349 deleteVBO( ); 00350 std::cout << "[createVBO()] Mismatch between Data size and input array" << std::endl; 00351 } 00352 } 00353 00354 void CloudPointData::VBO::genBufferColor( unsigned int& idColor, const void* data, int size, GLenum target, GLenum usage ) 00355 { 00356 //test if current VBO is already existing 00357 if( idColor != 0 ) //if idColor is not null 00358 deleteVBO( ); //delete current VBO 00359 00360 const int dataSize = size * 3 * sizeof(float); 00361 00362 glGenBuffers( 1, &(_idColor) ); // create a VBO 00363 glBindBuffer( target, _idColor ); // activate VBO id to use 00364 glBufferData( target, dataSize, data, usage ); // upload data to video card 00365 00366 // check data size in VBO is same as input array, if not return 0 and delete VBO 00367 int bufferSize = 0; 00368 glGetBufferParameteriv( target, GL_BUFFER_SIZE, &bufferSize ); 00369 if( dataSize != bufferSize ) //mismatch between data size and input array (control) 00370 { 00371 deleteVBO( ); 00372 std::cout << "[createVBO()] Mismatch between Data size and input array" << std::endl; 00373 } 00374 } 00375 00376 /* 00377 * Draw the current VBO on screen 00378 */ 00379 void CloudPointData::VBO::draw() 00380 { 00381 if( _id && _size ) 00382 { 00383 // bind VBOs with IDs and set the buffer offsets of the bound VBOs 00384 // When buffer object is bound with its ID, all pointers in gl*Pointer() 00385 // are treated as offset instead of real pointer. 00386 glBindBuffer( GL_ARRAY_BUFFER, _id ); 00387 glVertexPointer( 3, GL_FLOAT, 0, 0 ); 00388 glEnableClientState( GL_VERTEX_ARRAY ); // enable vertex arrays 00389 00390 if( _color ) //draw vector using color 00391 { 00392 if(_colorDifferent) //color and vertex buffers are not the same 00393 { 00394 glBindBuffer(GL_ARRAY_BUFFER, _idColor); //bind new color buffer 00395 } 00396 glColorPointer( 3, GL_FLOAT, 0, 0 ); //point buffer which is used for colors (same than vertex or not) 00397 glEnableClientState( GL_COLOR_ARRAY ); 00398 } 00399 00400 glDrawArrays( GL_POINTS, 0, _size ); 00401 00402 glDisableClientState( GL_VERTEX_ARRAY ); // disable vertex arrays 00403 00404 if( _color ) 00405 glDisableClientState( GL_COLOR_ARRAY ); 00406 00407 00408 // it is good idea to release VBOs with ID 0 after use. 00409 // Once bound with 0, all pointers in gl*Pointer() behave as real 00410 // pointer, so, normal vertex array operations are re-activated 00411 glBindBuffer( GL_ARRAY_BUFFER, 0 ); 00412 } 00413 } 00414 00415 00416 } 00417 } 00418 }