00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef WIN32
00020 #include <windows.h>
00021 #endif
00022
00023
00024 #include <cv.h>
00025 #include <cxtypes.h>
00026 #include <highgui.h>
00027 #include <cvaux.h>
00028
00029
00030 #include "OmniGCardConverter.hh"
00031
00032
00033 void OmniGCardConverter::angle_type_conversion( const OmniAngle<double> &angle_in,
00034 OmniAngle<int> &angle_out )
00035 {
00036 int theta, steps;
00037 double rad_angle_start, rad_angle_end;
00038
00039 rad_angle_start = angle_in.angle_start;
00040 rad_angle_end = angle_in.angle_end;
00041
00042
00043 if ( !is_initialized () )
00044 return;
00045
00046
00047
00048 if ( rad_angle_start < 0 )
00049 rad_angle_start = 2 * CV_PI + rad_angle_start;
00050
00051 if ( rad_angle_end < 0 )
00052 rad_angle_end = 2 * CV_PI + rad_angle_end;
00053
00054
00055 if ( rad_angle_end < rad_angle_start ) {
00056 theta = (int)ceil( rad_angle_start * (_max_radius - _min_radius) );
00057
00058
00059 steps = (int)ceil( rad_angle_end *(_max_radius - _min_radius) ) +
00060 (_pano_width - theta);
00061 }
00062 else if ( rad_angle_end > rad_angle_start ) {
00063 theta = (int)ceil( rad_angle_start * (_max_radius - _min_radius) );
00064 steps = (int)ceil( rad_angle_end * (_max_radius - _min_radius) ) - theta;
00065 }
00066 else {
00067 steps = _pano_width;
00068 theta = 0;
00069 }
00070
00071
00072 angle_out.range = steps;
00073 angle_out.angle_start = theta;
00074 angle_out.angle_end = (theta + steps) % _pano_width;
00075 }
00076
00077
00078 IplImage* OmniGCardConverter::omni2pano( IplImage *omni_frame, const OmniAngle<int> &IN_interval )
00079 {
00080 assert( omni_frame->width == _video_width );
00081 assert( omni_frame->height == _video_height );
00082
00083
00084 glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, omni_frame->width, omni_frame->height,
00085 GL_BGR_EXT, GL_UNSIGNED_BYTE, omni_frame->imageData);
00086
00087
00088 float slide_par = (float)IN_interval.angle_start / (float)_pano_width;
00089
00090
00091 gl_paint ( slide_par );
00092
00093
00094
00095
00096
00097
00098 int adjusted_range = IN_interval.range;
00099 int tmp_val = IN_interval.range % 32;
00100
00101 if ( tmp_val != 0 )
00102 adjusted_range -= tmp_val;
00103
00104
00105 IplImage *res_image;
00106 res_image = cvCreateImage( cvSize( adjusted_range, _pano_height ), IPL_DEPTH_8U, 3 );
00107
00108 glReadPixels ( 0, 0, adjusted_range,
00109 res_image->height, GL_BGR_EXT, GL_UNSIGNED_BYTE, res_image->imageData );
00110
00111
00112 if ( _flipped_mode )
00113 cvFlip( res_image, res_image, 0);
00114 return res_image;
00115 }
00116
00117
00118 OmniGCardConverter::OmniGCardConverter( double min_radius,
00119 double max_radius,
00120 double omni_center_x,
00121 double omni_center_y,
00122 unsigned int video_width,
00123 unsigned int video_height,
00124 char *program_name ,
00125 char *vertex_program_file_name ,
00126 char *vertex_program_name ,
00127 char *fragment_program_file_name ,
00128 char *fragment_program_name ,
00129 bool flipped_mode ) :
00130 _min_radius( min_radius ),
00131 _max_radius( max_radius ),
00132 _omni_center_x( omni_center_x ),
00133 _omni_center_y( omni_center_y ),
00134 _video_width( video_width ),
00135 _video_height( video_height ),
00136 _flipped_mode( flipped_mode )
00137 {
00138 GLuint texture;
00139
00140 _initialized = false;
00141
00142
00143 if ( (int)_max_radius % 2 != 0 )
00144 _max_radius++;
00145 if ( (int)_min_radius % 2 != 0 )
00146 _min_radius++;
00147
00148
00149 _pano_width = (int)ceil( (_max_radius - _min_radius ) * 2 * CV_PI );
00150 _pano_height = (int)ceil( _max_radius - _min_radius );
00151
00152 #ifdef WIN32
00153 wgl_init( &_g_window, &_g_application, &_g_keys, _pano_width, _pano_height );
00154 #else // LINUX
00155 _dpy = XOpenDisplay(NULL);
00156 if ( !_dpy ) {
00157 DEBUG_PRINT ("Error: XOpenDisplay failed\n");
00158 return;
00159 }
00160
00161 if ( _pano_width == 0 || _pano_height == 0 ) {
00162 DEBUG_PRINT("WARNING: _pano_width == 0 || _pano_height == 0\n");
00163 }
00164
00165 _win = glx_init( _dpy, _pano_width, _pano_height );
00166 if ( _win == 0 ) {
00167 DEBUG_PRINT ("Error making window\n");
00168 return;
00169 }
00170 #endif
00171
00172 _hw_video_height = _hw_video_width = get_texturized_video_size( _video_width, _video_height );
00173
00174
00175 _program_name = strdup( program_name );
00176
00177 _vertex_program_file_name = strdup( vertex_program_file_name );
00178 _vertex_program_name = strdup ( vertex_program_name );
00179
00180 _fragment_program_file_name = strdup( fragment_program_file_name );
00181 _fragment_program_name = strdup( fragment_program_name );
00182
00183 glGenTextures(1, &texture);
00184 glBindTexture (GL_TEXTURE_2D, texture);
00185
00186
00187 glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
00188
00189 #ifdef WIN32
00190 setVSync(0);
00191 #endif
00192
00193
00194 glEnable( GL_TEXTURE_2D );
00195
00196 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
00197 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
00198
00199 _cg_context = cgCreateContext();
00200 if ( _cg_context == NULL || check_for_cg_error( "creating context", _program_name, _cg_context) < 0 )
00201 return;
00202
00203
00204
00205
00206
00207 _cg_vertex_profile = cgGLGetLatestProfile( CG_GL_VERTEX );
00208 cgGLSetOptimalOptions( _cg_vertex_profile );
00209 if ( check_for_cg_error("selecting vertex profile", _program_name, _cg_context) < 0 )
00210 return;
00211
00212 _cg_vertex_program =
00213 cgCreateProgramFromFile(
00214 _cg_context,
00215 CG_SOURCE,
00216 _vertex_program_file_name,
00217 _cg_vertex_profile,
00218 _vertex_program_name,
00219 NULL );
00220
00221 if ( check_for_cg_error("creating vertex program from file", _program_name, _cg_context) < 0)
00222 return;
00223
00224 cgGLLoadProgram( _cg_vertex_program );
00225 if ( check_for_cg_error("loading vertex program", _program_name, _cg_context) < 0 )
00226 return;
00227
00228
00229
00230
00231 _cg_vertex_param_min_radius_on_max_radius = cgGetNamedParameter( _cg_vertex_program, "min_radius_on_max_radius" );
00232 cgGLSetParameter1f( _cg_vertex_param_min_radius_on_max_radius, (float)(_min_radius / _max_radius) );
00233
00234
00235
00236
00237
00238 _cg_fragment_profile = cgGLGetLatestProfile( CG_GL_FRAGMENT );
00239 cgGLSetOptimalOptions( _cg_fragment_profile );
00240 if ( check_for_cg_error("selecting fragment profile", _program_name, _cg_context) < 0 )
00241 return;
00242
00243 _cg_fragment_program =
00244 cgCreateProgramFromFile(
00245 _cg_context,
00246 CG_SOURCE,
00247 _fragment_program_file_name,
00248 _cg_fragment_profile,
00249 _fragment_program_name,
00250 NULL);
00251
00252 if ( check_for_cg_error("creating fragment program from file", _program_name, _cg_context) < 0 )
00253 return;
00254
00255 cgGLLoadProgram( _cg_fragment_program );
00256 if ( check_for_cg_error("loading fragment program", _program_name, _cg_context) < 0 )
00257 return;
00258
00259 _cg_fragment_param_omni_tex = cgGetNamedParameter( _cg_fragment_program, "omni_tex" );
00260 _cg_fragment_param_center_x = cgGetNamedParameter( _cg_fragment_program, "center_x" );
00261 _cg_fragment_param_center_y = cgGetNamedParameter( _cg_fragment_program, "center_y" );
00262 _cg_fragment_param_width_on_height = cgGetNamedParameter( _cg_fragment_program, "width_on_height" );
00263 _cg_fragment_param_slide = cgGetNamedParameter( _cg_fragment_program, "slide" );
00264
00265 unsigned char *empty_texture = new unsigned char[_hw_video_height * _hw_video_width * 3];
00266
00267
00268 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _hw_video_width, _hw_video_height,
00269 0, GL_RGB, GL_UNSIGNED_BYTE, empty_texture );
00270 delete empty_texture;
00271
00272 cgGLSetTextureParameter( _cg_fragment_param_omni_tex, texture );
00273 cgGLSetParameter1f( _cg_fragment_param_center_x, (float)_omni_center_x / (float)_hw_video_width );
00274 cgGLSetParameter1f( _cg_fragment_param_center_y, (float)_omni_center_y / (float)_hw_video_height );
00275 cgGLSetParameter1f( _cg_fragment_param_width_on_height, (float)_video_width / (float)_video_height );
00276 cgGLSetParameter1f( _cg_fragment_param_slide, 0.0f );
00277
00278 _initialized = true;
00279 }
00280
00281 OmniGCardConverter::~OmniGCardConverter()
00282 {
00283 if ( _program_name )
00284 free( _program_name );
00285 if ( _vertex_program_file_name )
00286 free( _vertex_program_file_name );
00287 if ( _vertex_program_name )
00288 free( _vertex_program_name );
00289 if ( _fragment_program_file_name )
00290 free( _fragment_program_file_name );
00291 if ( _fragment_program_name )
00292 free( _fragment_program_name );
00293
00294 #ifdef WIN32
00295 wgl_deinit (&_g_window, &_g_application, &_g_keys);
00296 #else
00297 glx_deinit( _dpy );
00298 #endif
00299
00300 }
00301
00302 #ifdef WIN32
00303 void OmniGCardConverter::setVSync( int interval )
00304 {
00305 const char *extensions = (const char*)glGetString( GL_EXTENSIONS );
00306
00307 if( strstr( extensions, "WGL_EXT_swap_control" ) == 0 )
00308 return;
00309 else {
00310 _wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress( "wglSwapIntervalEXT" );
00311
00312 if( _wglSwapIntervalEXT )
00313 _wglSwapIntervalEXT( interval );
00314 }
00315 }
00316 #endif
00317
00318 int OmniGCardConverter::check_for_cg_error( const char *situation, char *prg_name, CGcontext cg_ctx )
00319 {
00320 CGerror error;
00321 const char *string = cgGetLastErrorString(&error);
00322
00323 if (error != CG_NO_ERROR) {
00324 DEBUG_PRINT("%s: %s: %s\n",
00325 prg_name, situation, string);
00326
00327 if (error == CG_COMPILER_ERROR) {
00328 DEBUG_PRINT("%s\n", cgGetLastListing( cg_ctx ));
00329 }
00330 return -1;
00331 }
00332
00333 return 0;
00334 }
00335
00336 int OmniGCardConverter::get_texturized_video_size( int video_width, int video_height )
00337 {
00338 int mask=0;
00339 int value;
00340
00341 value = (video_width >= video_height ? video_width : video_height);
00342
00343 while( (mask & value) != value ) {
00344 mask = ( mask << 1 ) +1;
00345 }
00346
00347 return mask +1;
00348 }
00349
00350 double OmniGCardConverter::get_min_radius ()
00351 {
00352 return _min_radius;
00353 }
00354
00355 double OmniGCardConverter::get_max_radius ()
00356 {
00357 return _max_radius;
00358 }
00359
00360 double OmniGCardConverter::get_omni_center_y ()
00361 {
00362 return _omni_center_y;
00363 }
00364
00365 double OmniGCardConverter::get_omni_center_x ()
00366 {
00367 return _omni_center_x;
00368 }
00369
00370 bool OmniGCardConverter::is_initialized ()
00371 {
00372 return _initialized;
00373 }
00374
00375 void OmniGCardConverter::gl_paint ( float slide )
00376 {
00377 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00378
00379 cgGLBindProgram( _cg_vertex_program );
00380 cgGLEnableProfile( _cg_vertex_profile );
00381
00382 cgGLBindProgram( _cg_fragment_program );
00383 cgGLEnableProfile( _cg_fragment_profile );
00384
00385 cgGLSetParameter1f( _cg_fragment_param_slide, slide);
00386
00387 cgGLEnableTextureParameter( _cg_fragment_param_omni_tex );
00388 cgGLEnableClientState ( _cg_fragment_param_center_x );
00389 cgGLEnableClientState ( _cg_fragment_param_center_y );
00390 cgGLEnableClientState ( _cg_fragment_param_slide );
00391
00392
00393 glBegin(GL_QUADS);
00394
00395 glTexCoord2f(0, 0);
00396 glVertex2f(-1, -1);
00397
00398 glTexCoord2f(1, 0);
00399 glVertex2f(1, -1);
00400
00401 glTexCoord2f(1, 1);
00402 glVertex2f(1, 1);
00403
00404 glTexCoord2f(0, 1);
00405 glVertex2f(-1, 1);
00406
00407
00408 glEnd();
00409
00410
00411 cgGLDisableProfile( _cg_vertex_profile );
00412 cgGLDisableProfile( _cg_fragment_profile );
00413 cgGLDisableTextureParameter( _cg_fragment_param_omni_tex );
00414
00415
00416 glFlush();
00417 }
00418
00419
00420 IplImage* OmniGCardConverter::omni2pano( IplImage *omni_frame, const OmniAngle<double> &IN_interval )
00421 {
00422 DEBUG_PRINT ("unused function omni2pano with double angle\n");
00423 return NULL;
00424 }
00425
00426
00427 void OmniGCardConverter::pano2omni_xy( CvPoint *pano_point, double theta_start,
00428 CvPoint *omni_point )
00429 {
00430 omni_point->x = (int)((pano_point->y + _min_radius ) *
00431 cos((theta_start + pano_point->x) / _max_radius ));
00432
00433 omni_point->y = (int)((pano_point->y + _min_radius ) *
00434 sin((theta_start + pano_point->x) / _max_radius ));
00435
00436 omni_point->x += (int)_omni_center_x;
00437 omni_point->y += (int)_omni_center_y;
00438 }
00439
00440
00441
00442 bool OmniGCardConverter::check_for_3d_gcard_availability ()
00443 {
00444
00445
00446 #ifdef WIN32
00447 Application g_application;
00448 GL_Window g_window;
00449 Keys g_keys;
00450
00451 wgl_init( &g_window, &g_application, &g_keys, 0, 0 );
00452 #else
00453 Display *dpy_tmp;
00454 Window win_tmp;
00455
00456 dpy_tmp = XOpenDisplay (NULL);
00457 if ( !dpy_tmp ) {
00458 DEBUG_PRINT ("Error: XOpenDisplay failed\n");
00459 return false;
00460 }
00461
00462 win_tmp = glx_init( dpy_tmp, 1, 1 );
00463
00464 if ( win_tmp == 0 ) {
00465 DEBUG_PRINT ("Error making window\n");
00466 return false;
00467 }
00468
00469 #endif
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 CGcontext cg_context_tmp;
00481 CGprofile cg_vertex_profile_tmp, cg_fragment_profile_tmp;
00482
00483 cg_context_tmp = cgCreateContext();
00484 if ( cg_context_tmp == NULL || check_for_cg_error("creating context", NULL, cg_context_tmp) < 0 ) {
00485 #ifdef WIN32
00486 wgl_deinit( &g_window, &g_application, &g_keys);
00487 #else
00488 glx_deinit( dpy_tmp );
00489 #endif
00490 return false;
00491 }
00492
00493
00494
00495 cg_vertex_profile_tmp = cgGLGetLatestProfile( CG_GL_VERTEX );
00496 cgGLSetOptimalOptions( cg_vertex_profile_tmp );
00497 if ( check_for_cg_error("selecting vertex profile", NULL, cg_context_tmp) < 0 ) {
00498 #ifdef WIN32
00499 wgl_deinit( &g_window, &g_application, &g_keys);
00500 #else
00501 glx_deinit( dpy_tmp );
00502 #endif
00503 return false;
00504 }
00505
00506
00507 cg_fragment_profile_tmp = cgGLGetLatestProfile( CG_GL_FRAGMENT );
00508 cgGLSetOptimalOptions( cg_fragment_profile_tmp );
00509 if ( check_for_cg_error("selecting fragment profile", NULL, cg_context_tmp) < 0 ) {
00510 #ifdef WIN32
00511 wgl_deinit( &g_window, &g_application, &g_keys);
00512 #else
00513 glx_deinit( dpy_tmp );
00514 #endif
00515
00516 return false;
00517 }
00518
00519 #ifdef WIN32
00520 wgl_deinit( &g_window, &g_application, &g_keys);
00521 #else
00522 glx_deinit( dpy_tmp );
00523 #endif
00524
00525 return true;
00526 }