Fixed all OpenGL issues for Macos (via objective-C++ layer)
authorAnatoly Baksheev <no@mail>
Sat, 8 Feb 2014 15:31:24 +0000 (19:31 +0400)
committerAnatoly Baksheev <no@email>
Mon, 10 Feb 2014 11:45:46 +0000 (15:45 +0400)
cmake/OpenCVModule.cmake
modules/viz/src/precomp.hpp
modules/viz/src/vizimpl.cpp
modules/viz/src/vtk/vtkCocoaInteractorFix.mm [new file with mode: 0644]

index 86a9d0c..6f727af 100644 (file)
@@ -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})
 
index 8329f52..f77da5a 100644 (file)
@@ -312,6 +312,8 @@ namespace cv
                 return transform_filter->GetOutput();
             }
         };
+
+        vtkSmartPointer<vtkRenderWindowInteractor> vtkCocoaRenderWindowInteractorNew();
     }
 }
 
index cf7a251..3e852dd 100644 (file)
@@ -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<vtkRenderWindowInteractor>::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<vtkRenderWindowInteractor>::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 (file)
index 0000000..0e55aeb
--- /dev/null
@@ -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 <Cocoa/Cocoa.h>
+#include <vtkCocoaRenderWindow.h>
+#include <vtkCocoaRenderWindowInteractor.h>
+#include <vtkObjectFactory.h>
+#include <vtkSmartPointer.h>
+
+//----------------------------------------------------------------------------
+@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<NSWindow*> (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<vtkRenderWindowInteractor> vtkCocoaRenderWindowInteractorNew();
+}}
+
+void cv::viz::vtkCocoaRenderWindowInteractorFix::Start ()
+{
+    vtkCocoaRenderWindow* renWin = vtkCocoaRenderWindow::SafeDownCast(this->GetRenderWindow ());
+    if (renWin != NULL)
+    {
+        vtkCocoaServerFix *server = reinterpret_cast<vtkCocoaServerFix*> (this->GetCocoaServer ());
+        if (!this->GetCocoaServer ())
+        {
+            server = [vtkCocoaServerFix cocoaServerWithRenderWindow:renWin];
+            this->SetCocoaServer (reinterpret_cast<void*> (server));
+        }
+
+        [server start];
+    }
+}
+
+void cv::viz::vtkCocoaRenderWindowInteractorFix::TerminateApp ()
+{
+    vtkCocoaRenderWindow *renWin = vtkCocoaRenderWindow::SafeDownCast (this->RenderWindow);
+    if (renWin)
+    {
+        vtkCocoaServerFix *server = reinterpret_cast<vtkCocoaServerFix*> (this->GetCocoaServer ());
+        [server stop];
+    }
+}
+
+vtkSmartPointer<vtkRenderWindowInteractor> cv::viz::vtkCocoaRenderWindowInteractorNew()
+{
+    return vtkSmartPointer<vtkCocoaRenderWindowInteractorFix>::New();
+}
+