From 5dc17f5d587b866aaee676c723a2bd30e1f710e2 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 8 Feb 2014 19:31:24 +0400 Subject: [PATCH] Fixed all OpenGL issues for Macos (via objective-C++ layer) --- cmake/OpenCVModule.cmake | 10 +- modules/viz/src/precomp.hpp | 2 + modules/viz/src/vizimpl.cpp | 11 +- modules/viz/src/vtk/vtkCocoaInteractorFix.mm | 213 +++++++++++++++++++++++++++ 4 files changed, 233 insertions(+), 3 deletions(-) create mode 100644 modules/viz/src/vtk/vtkCocoaInteractorFix.mm diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 86a9d0c..6f727af 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -484,6 +484,10 @@ macro(ocv_glob_module_sources) file(GLOB_RECURSE lib_int_hdrs "src/*.hpp" "src/*.h") file(GLOB lib_hdrs "include/opencv2/${name}/*.hpp" "include/opencv2/${name}/*.h") file(GLOB lib_hdrs_detail "include/opencv2/${name}/detail/*.hpp" "include/opencv2/${name}/detail/*.h") + file(GLOB_RECURSE lib_srcs_apple "src/*.m*") + if (APPLE) + list(APPEND lib_srcs ${lib_srcs_apple}) + endif() file(GLOB lib_cuda_srcs "src/cuda/*.cu") set(cuda_objs "") @@ -745,7 +749,11 @@ function(ocv_add_accuracy_tests) get_native_precompiled_header(${the_target} test_precomp.hpp) - add_executable(${the_target} ${OPENCV_TEST_${the_module}_SOURCES} ${${the_target}_pch}) + if(APPLE AND ${the_target} STREQUAL "opencv_test_viz") + add_executable(${the_target} MACOSX_BUNDLE ${OPENCV_TEST_${the_module}_SOURCES} ${${the_target}_pch}) + else() + add_executable(${the_target} ${OPENCV_TEST_${the_module}_SOURCES} ${${the_target}_pch}) + endif() target_link_libraries(${the_target} ${OPENCV_MODULE_${the_module}_DEPS} ${test_deps} ${OPENCV_LINKER_LIBS}) add_dependencies(opencv_tests ${the_target}) diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 8329f52..f77da5a 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -312,6 +312,8 @@ namespace cv return transform_filter->GetOutput(); } }; + + vtkSmartPointer vtkCocoaRenderWindowInteractorNew(); } } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index cf7a251..3e852dd 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -111,7 +111,7 @@ void cv::viz::Viz3d::VizImpl::close() void cv::viz::Viz3d::VizImpl::recreateRenderWindow() { -#if !defined _MSC_VER +#if !defined _MSC_VER && !defined __APPLE__ //recreating is workaround for Ubuntu -- a crash in x-server Vec2i window_size(window_->GetSize()); int fullscreen = window_->GetFullScreen(); @@ -127,12 +127,15 @@ void cv::viz::Viz3d::VizImpl::recreateRenderWindow() #endif } - ///////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::spin() { recreateRenderWindow(); +#if defined __APPLE__ + interactor_ = vtkCocoaRenderWindowInteractorNew(); +#else interactor_ = vtkSmartPointer::New(); +#endif interactor_->SetRenderWindow(window_); interactor_->SetInteractorStyle(style_); window_->AlphaBitPlanesOff(); @@ -154,7 +157,11 @@ void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw) { spin_once_state_ = true; recreateRenderWindow(); +#if defined __APPLE__ + interactor_ = vtkCocoaRenderWindowInteractorNew(); +#else interactor_ = vtkSmartPointer::New(); +#endif interactor_->SetRenderWindow(window_); interactor_->SetInteractorStyle(style_); interactor_->AddObserver(vtkCommand::TimerEvent, timer_callback_); diff --git a/modules/viz/src/vtk/vtkCocoaInteractorFix.mm b/modules/viz/src/vtk/vtkCocoaInteractorFix.mm new file mode 100644 index 0000000..0e55aeb --- /dev/null +++ b/modules/viz/src/vtk/vtkCocoaInteractorFix.mm @@ -0,0 +1,213 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +// OpenCV Viz module is complete rewrite of +// PCL visualization module (www.pointclouds.org) +// +//M*/ + +#import +#include +#include +#include +#include + +//---------------------------------------------------------------------------- +@interface vtkCocoaServerFix : NSObject +{ + vtkCocoaRenderWindow* renWin; +} + ++ (id)cocoaServerWithRenderWindow:(vtkCocoaRenderWindow*)inRenderWindow; + +- (void)start; +- (void)stop; +- (void)breakEventLoop; + +@end + +//---------------------------------------------------------------------------- +@implementation vtkCocoaServerFix + +//---------------------------------------------------------------------------- +- (id)initWithRenderWindow:(vtkCocoaRenderWindow *)inRenderWindow +{ + self = [super init]; + if (self) + renWin = inRenderWindow; + return self; +} + +//---------------------------------------------------------------------------- ++ (id)cocoaServerWithRenderWindow:(vtkCocoaRenderWindow *)inRenderWindow +{ + vtkCocoaServerFix *server = [[[vtkCocoaServerFix alloc] initWithRenderWindow:inRenderWindow] autorelease]; + return server; +} + +//---------------------------------------------------------------------------- +- (void)start +{ + // Retrieve the NSWindow. + NSWindow *win = nil; + if (renWin) + { + win = reinterpret_cast (renWin->GetRootWindow ()); + + // We don't want to be informed of every window closing, so check for nil. + if (win != nil) + { + // Register for the windowWillClose notification in order to stop the run loop if the window closes. + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification object:win]; + } + } + // Start the NSApplication's run loop + NSApplication* application = [NSApplication sharedApplication]; + [application run]; +} + +//---------------------------------------------------------------------------- +- (void)stop +{ + [self breakEventLoop]; +} + +//---------------------------------------------------------------------------- +- (void)breakEventLoop +{ + NSApplication* application = [NSApplication sharedApplication]; + [application stop:application]; + + NSEvent *event = [NSEvent otherEventWithType:NSApplicationDefined + location:NSMakePoint(0.0,0.0) + modifierFlags:0 + timestamp:0 + windowNumber:-1 + context:nil + subtype:0 + data1:0 + data2:0]; + [application postEvent:event atStart:YES]; +} + +//---------------------------------------------------------------------------- +- (void)windowWillClose:(NSNotification*)aNotification +{ + (void)aNotification; + + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc removeObserver:self name:NSWindowWillCloseNotification object:nil]; + + if (renWin) + { + int windowCreated = renWin->GetWindowCreated (); + if (windowCreated) + { + [self breakEventLoop]; + + // The NSWindow is closing, so prevent anyone from accidently using it + renWin->SetRootWindow(NULL); + } + } +} + +@end + +//---------------------------------------------------------------------------- + +namespace cv { namespace viz +{ + class vtkCocoaRenderWindowInteractorFix : public vtkCocoaRenderWindowInteractor + { + public: + static vtkCocoaRenderWindowInteractorFix *New (); + vtkTypeMacro (vtkCocoaRenderWindowInteractorFix, vtkCocoaRenderWindowInteractor) + + virtual void Start (); + virtual void TerminateApp (); + + protected: + vtkCocoaRenderWindowInteractorFix () {} + ~vtkCocoaRenderWindowInteractorFix () {} + + private: + vtkCocoaRenderWindowInteractorFix (const vtkCocoaRenderWindowInteractorFix&); // Not implemented. + void operator = (const vtkCocoaRenderWindowInteractorFix&); // Not implemented. + }; + + vtkStandardNewMacro (vtkCocoaRenderWindowInteractorFix) + + vtkSmartPointer vtkCocoaRenderWindowInteractorNew(); +}} + +void cv::viz::vtkCocoaRenderWindowInteractorFix::Start () +{ + vtkCocoaRenderWindow* renWin = vtkCocoaRenderWindow::SafeDownCast(this->GetRenderWindow ()); + if (renWin != NULL) + { + vtkCocoaServerFix *server = reinterpret_cast (this->GetCocoaServer ()); + if (!this->GetCocoaServer ()) + { + server = [vtkCocoaServerFix cocoaServerWithRenderWindow:renWin]; + this->SetCocoaServer (reinterpret_cast (server)); + } + + [server start]; + } +} + +void cv::viz::vtkCocoaRenderWindowInteractorFix::TerminateApp () +{ + vtkCocoaRenderWindow *renWin = vtkCocoaRenderWindow::SafeDownCast (this->RenderWindow); + if (renWin) + { + vtkCocoaServerFix *server = reinterpret_cast (this->GetCocoaServer ()); + [server stop]; + } +} + +vtkSmartPointer cv::viz::vtkCocoaRenderWindowInteractorNew() +{ + return vtkSmartPointer::New(); +} + -- 2.7.4