From b523cb15c1876da624019835ba821555f7fbaa7a Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 26 Nov 2010 18:19:28 +0000 Subject: [PATCH] From Tomas Holgarth and Stephan Huber, " attached you'll find the second part of the IOS-submission. It contains * GraphicsWindowIOS, which supports external and "retina" displays, multisample-buffers (for IOS > 4.0) and multi-touch-events * an ios-specific implementation of the imageio-plugin * an iphone-viewer example * cMake support for creating a xcode-project * an updated ReadMe-file describing the necessary steps to get a working xcode-project-file from CMake Please credit Thomas Hogarth and Stephan Huber for these changes. This brings the ios-support in line with the git-fork on github. It needs some more testing and some more love, the cmake-process is still a little complicated. You'll need a special version of the freetype lib compiled for IOS, there's one bundled in the OpenFrameworks-distribution, which can be used." Notes, from Robert Osfield, modified CMakeLists.txt files so that the IOS specific paths are within IF(APPLE) blocks. --- CMakeLists.txt | 131 ++- README.txt | 31 + examples/CMakeLists.txt | 6 + examples/osgviewerIPhone/CMakeLists.txt | 13 + .../osgviewerIPhone/iphoneViewerAppDelegate.h | 32 + .../iphoneViewerAppDelegate.mm | 191 ++++ examples/osgviewerIPhone/main.m | 17 + .../osgIPhoneViewer-Info.plist | 28 + examples/osgviewerIPhone/osgPlugins.h | 19 + include/osgViewer/api/IOS/GraphicsWindowIOS | 209 ++++ .../imageio/ReaderWriterImageIO_IOS.cpp | 361 ++++++ src/osgViewer/CMakeLists.txt | 76 +- src/osgViewer/GraphicsWindowIOS.mm | 1016 +++++++++++++++++ src/osgViewer/IOSUtils.h | 114 ++ src/osgViewer/IOSUtils.mm | 288 +++++ 15 files changed, 2478 insertions(+), 54 deletions(-) create mode 100644 examples/osgviewerIPhone/CMakeLists.txt create mode 100755 examples/osgviewerIPhone/iphoneViewerAppDelegate.h create mode 100755 examples/osgviewerIPhone/iphoneViewerAppDelegate.mm create mode 100755 examples/osgviewerIPhone/main.m create mode 100755 examples/osgviewerIPhone/osgIPhoneViewer-Info.plist create mode 100755 examples/osgviewerIPhone/osgPlugins.h create mode 100755 include/osgViewer/api/IOS/GraphicsWindowIOS create mode 100755 src/osgPlugins/imageio/ReaderWriterImageIO_IOS.cpp create mode 100755 src/osgViewer/GraphicsWindowIOS.mm create mode 100755 src/osgViewer/IOSUtils.h create mode 100755 src/osgViewer/IOSUtils.mm diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e40b0199..94c7973cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,9 +141,43 @@ ENDIF(OSG_MAINTAINER) # Find OpenGL FIND_PACKAGE(OpenGL) + IF(APPLE) + # Trying to get CMake to generate an XCode IPhone project, current efforts are to get iphoneos sdk 3.1 working + # Added option which needs manually setting to select the IPhone SDK for building. We can only have one of the below + # set to true. Should realy have an OSG_BUILD_PLATFORM variable that we set to our desired platform + OPTION(OSG_BUILD_PLATFORM_IPHONE "Enable IPhoneSDK Device support" OFF) + OPTION(OSG_BUILD_PLATFORM_IPHONE_SIMULATOR "Enable IPhoneSDK Simulator support" OFF) + + IF(OSG_BUILD_PLATFORM_IPHONE OR OSG_BUILD_PLATFORM_IPHONE_SIMULATOR) + + #you need to manually set the default sdk version here + SET (IPHONE_SDKVER "3.2") + + #the below is taken from ogre, it states the gcc stuff needs to happen before PROJECT() is called. I've no clue if we even need it + # Force gcc <= 4.2 on iPhone + include(CMakeForceCompiler) + CMAKE_FORCE_C_COMPILER(gcc-4.2 GNU) + CMAKE_FORCE_CXX_COMPILER(gcc-4.2 GNU) + SET(GCC_THUMB_SUPPORT NO) + + #set either the device sdk or the simulator sdk. Can't find away to separate these in the same project + IF(OSG_BUILD_PLATFORM_IPHONE) + SET (IPHONE_DEVROOT "/Developer/Platforms/iPhoneOS.platform/Developer") + SET (IPHONE_SDKROOT "${IPHONE_DEVROOT}/SDKs/iPhoneOS${IPHONE_SDKVER}.sdk") + ELSE() + SET (IPHONE_DEVROOT "/Developer/Platforms/iPhoneSimulator.platform/Developer") + SET (IPHONE_SDKROOT "${IPHONE_DEVROOT}/SDKs/iPhoneSimulator${IPHONE_SDKVER}.sdk") + ENDIF() + ENDIF () + FIND_LIBRARY(CARBON_LIBRARY Carbon) FIND_LIBRARY(COCOA_LIBRARY Cocoa) + + IF(OSG_BUILD_PLATFORM_IPHONE) + FIND_LIBRARY(OPENGLES_LIBRARY OpenGLES) + ENDIF() + OPTION(OSG_COMPILE_FRAMEWORKS "compile frameworks instead of dylibs (experimental)" OFF) SET(OSG_COMPILE_FRAMEWORKS_INSTALL_NAME_DIR "@executable_path/../Frameworks" CACHE STRING "install name dir for compiled frameworks") ENDIF() @@ -663,43 +697,70 @@ IF (BUILD_OSG_EXAMPLES) ENDIF() -# Set defaults for Universal Binaries. We want 32-bit Intel/PPC on 10.4 -# and 32/64-bit Intel/PPC on >= 10.5. Anything <= 10.3 doesn't support. IF(APPLE) - # These are just defaults/recommendations, but how we want to build - # out of the box. But the user needs to be able to change these options. - # So we must only set the values the first time CMake is run, or we - # will overwrite any changes the user sets. - # FORCE is used because the options are not reflected in the UI otherwise. - # Seems like a good place to add version specific compiler flags too. - IF(NOT OSG_CONFIG_HAS_BEEN_RUN_BEFORE) - # This is really fragile, but CMake doesn't provide the OS system - # version information we need. (Darwin versions can be changed - # independently of OS X versions.) - # It does look like CMake handles the CMAKE_OSX_SYSROOT automatically. - IF(EXISTS /Developer/SDKs/MacOSX10.6.sdk) - SET(CMAKE_OSX_ARCHITECTURES "i386;x86_64" CACHE STRING "Build architectures for OSX" FORCE) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.6 -ftree-vectorize -fvisibility-inlines-hidden" CACHE STRING "Flags used by the compiler during all build types." FORCE) - SET(OSG_WINDOWING_SYSTEM "Cocoa" CACHE STRING "Forced Cocoa windowing system in 64 bits snow leopard" FORCE) - SET(OSG_DEFAULT_IMAGE_PLUGIN_FOR_OSX "imageio " CACHE STRING "Forced imageio default image plugin for OSX in 64 bits snow leopard" FORCE) - ELSEIF(EXISTS /Developer/SDKs/MacOSX10.5.sdk) - # 64-bit compiles are not supported with Carbon. We should enable - # 64-bit compilation by default once osgviewer has been - # rewritten with Cocoa. - #SET(CMAKE_OSX_ARCHITECTURES "ppc;i386;ppc64;x86_64" CACHE STRING "Build architectures for OSX" FORCE) - SET(CMAKE_OSX_ARCHITECTURES "ppc;i386" CACHE STRING "Build architectures for OSX" FORCE) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.5 -ftree-vectorize -fvisibility-inlines-hidden" CACHE STRING "Flags used by the compiler during all build types." FORCE) - ELSEIF(EXISTS /Developer/SDKs/MacOSX10.4u.sdk) - SET(CMAKE_OSX_ARCHITECTURES "ppc;i386" CACHE STRING "Build architectures for OSX" FORCE) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.4 -ftree-vectorize -fvisibility-inlines-hidden" CACHE STRING "Flags used by the compiler during all build types." FORCE) - ELSE() - # No Universal Binary support - # Should break down further to set the -mmacosx-version-min, - # but the SDK detection is too unreliable here. - ENDIF() - ENDIF(NOT OSG_CONFIG_HAS_BEEN_RUN_BEFORE) - OPTION(OSG_BUILD_APPLICATION_BUNDLES "Enable the building of applications and examples as OSX Bundles" OFF) + #Here we check if the user specified IPhone SDK + IF(OSG_BUILD_PLATFORM_IPHONE OR OSG_BUILD_PLATFORM_IPHONE_SIMULATOR) + + #set iphone arch and flags taken from http://sites.google.com/site/michaelsafyan/coding/resources/how-to-guides/cross-compile-for-the-iphone/how-to-cross-compile-for-the-iphone-using-cmake + IF(OSG_BUILD_PLATFORM_IPHONE) + SET(CMAKE_OSX_ARCHITECTURES "armv6;armv7" CACHE STRING "Build architectures for iOS" FORCE) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -miphoneos-version-min=3.1 -mno-thumb -arch armv6 -pipe -no-cpp-precomp" CACHE STRING "Flags used by the compiler during all build types." FORCE) + ELSE() + #simulator uses i386 architectures + SET(CMAKE_OSX_ARCHITECTURES "i386;x86_64" CACHE STRING "Build architectures for iOS Simulator" FORCE) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -miphoneos-version-min=3.1 -mno-thumb -arch i386 -pipe -no-cpp-precomp" CACHE STRING "Flags used by the compiler during all build types." FORCE) + ENDIF() + + #here we set the specific iphone sdk version. We can only set either device or simulator sdk. So if you want both you currently have to have two seperate projects + SET(CMAKE_OSX_SYSROOT "${IPHONE_SDKROOT}" CACHE STRING "System root for iOS" FORCE) + + #hack, force link to opengles + set(CMAKE_EXE_LINKER_FLAGS "-framework Foundation -framework OpenGLES") + + #use the IPhone windowing system + SET(OSG_WINDOWING_SYSTEM "IOS" CACHE STRING "Forced IPhone windowing system on iOS" FORCE) + SET(OSG_DEFAULT_IMAGE_PLUGIN_FOR_OSX "imageio " CACHE STRING "Forced imageio default image plugin for iOS" FORCE) + + #I think this or similar will be required for IPhone apps + OPTION(OSG_BUILD_APPLICATION_BUNDLES "Enable the building of applications and examples as OSX Bundles" ON) + + ELSE() + + # Set defaults for Universal Binaries. We want 32-bit Intel/PPC on 10.4 + # and 32/64-bit Intel/PPC on >= 10.5. Anything <= 10.3 doesn't support. + + # These are just defaults/recommendations, but how we want to build + # out of the box. But the user needs to be able to change these options. + # So we must only set the values the first time CMake is run, or we + # will overwrite any changes the user sets. + # FORCE is used because the options are not reflected in the UI otherwise. + # Seems like a good place to add version specific compiler flags too. + IF(NOT OSG_CONFIG_HAS_BEEN_RUN_BEFORE) + # This is really fragile, but CMake doesn't provide the OS system + # version information we need. (Darwin versions can be changed + # independently of OS X versions.) + # It does look like CMake handles the CMAKE_OSX_SYSROOT automatically. + IF(EXISTS /Developer/SDKs/MacOSX10.5.sdk) + # 64-bit compiles are not supported with Carbon. We should enable + # 64-bit compilation by default once osgviewer has been + # rewritten with Cocoa. + #SET(CMAKE_OSX_ARCHITECTURES "ppc;i386;ppc64;x86_64" CACHE STRING "Build architectures for OSX" FORCE) + SET(CMAKE_OSX_ARCHITECTURES "ppc;i386" CACHE STRING "Build architectures for OSX" FORCE) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.5 -ftree-vectorize -fvisibility-inlines-hidden" CACHE STRING "Flags used by the compiler during all build types." FORCE) + ELSEIF(EXISTS /Developer/SDKs/MacOSX10.4u.sdk) + SET(CMAKE_OSX_ARCHITECTURES "ppc;i386" CACHE STRING "Build architectures for OSX" FORCE) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.4 -ftree-vectorize -fvisibility-inlines-hidden" CACHE STRING "Flags used by the compiler during all build types." FORCE) + ELSE() + # No Universal Binary support + # Should break down further to set the -mmacosx-version-min, + # but the SDK detection is too unreliable here. + ENDIF() + ENDIF(NOT OSG_CONFIG_HAS_BEEN_RUN_BEFORE) + + OPTION(OSG_BUILD_APPLICATION_BUNDLES "Enable the building of applications and examples as OSX Bundles" OFF) + + ENDIF() ENDIF(APPLE) diff --git a/README.txt b/README.txt index 7f1f9cc28..61fb98971 100644 --- a/README.txt +++ b/README.txt @@ -145,3 +145,34 @@ jpeg, tiff, png, and gif will not work, nor will animations dependent on Quicktime. A new ImageIO-based plugin is being developed to handle the still images, and a QTKit plugin will need to be developed to handle animations. + + +-- Release notes on IOS build, by Thomas Hoghart + +* Manually set the relevant OSG_BUILD_PLATFORM_IPHONE... option in root + CMakeLists file. Can only have one or the other at the moment. +* Run CMake +* Disable all OpenGL types accodrding to OSG_GLES1_AVALIABLE or + OSG_GLES2_AVALIABLE. Also disable OSG_GLU_AVAILABLE +* Disable OSG_GL_DISPLAYLISTS_AVALIABLE +* Ensure OSG_WINDOWING_SYSTEM is set to IOS +* Change FREETYPE include and library paths to an IPhone version + (OpenFrameworks has one bundled with its distribution) +* Under DYNAMIC ensure you untick DYNAMIC_OPENSCENEGRAPH and + DYNAMIC_OPENTHREADS. This will give us the static build we need + for IPhone +* Under CMake ensure the CMake_OSX_SYSROOT points to your + IOS SDK. Also check that the architecture is armv6/7 for + device or i386 for Simulator. +* Generate the XCode project +* Find osgDB FileUtis.cpp, open the 'Get Info' panel, change File Type + to source.cpp.objcpp +* When Linking final app against ive plugin, you need to add -lz to + the 'Other linker flags' list. + +known Issues: +* Apps and exes don't get created +* You can only select Simulator, or Device projects. In the XCode + project you will see both types but the sdk they link will + be the same. + diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index df8bceb96..eb54ffe3b 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -240,6 +240,12 @@ ELSE(DYNAMIC_OPENSCENEGRAPH) ADD_DEFINITIONS(-DOSG_LIBRARY_STATIC) ADD_SUBDIRECTORY(osgstaticviewer) + + # IPHONE_PORT@tom + IF(OSG_BUILD_PLATFORM_IPHONE || OSG_BUILD_PLATFORM_IPHONE_SIMULATOR) + ADD_SUBDIRECTORY(osgViewerIPhone) + ENDIF() + # IPHONE_PORT@tom ENDIF(DYNAMIC_OPENSCENEGRAPH) diff --git a/examples/osgviewerIPhone/CMakeLists.txt b/examples/osgviewerIPhone/CMakeLists.txt new file mode 100644 index 000000000..caf96be59 --- /dev/null +++ b/examples/osgviewerIPhone/CMakeLists.txt @@ -0,0 +1,13 @@ +SET(TARGET_SRC + iphoneViewerAppDelegate.h + iphoneViewerAppDelegate.mm + main.m + osgPlugins.h + osgIPhoneViewer-Info.plist +) + +#INCLUDE_DIRECTORIES( ${GLUT_INCLUDE_DIR} ) +SET(TARGET_LIBRARIES_VARS Foundation.framework QuartzCore.framework UIKit.framework) + +#### end var setup ### +SETUP_EXAMPLE(osgViewerIPhone) diff --git a/examples/osgviewerIPhone/iphoneViewerAppDelegate.h b/examples/osgviewerIPhone/iphoneViewerAppDelegate.h new file mode 100755 index 000000000..cb3038afc --- /dev/null +++ b/examples/osgviewerIPhone/iphoneViewerAppDelegate.h @@ -0,0 +1,32 @@ +//Created by Thomas Hogarth 2009 + +//force the link to our desired osgPlugins +#include "osgPlugins.h" + +#include +#include +#include +#include +#include + + +#import + + +@interface iphoneViewerAppDelegate : NSObject { + + UIWindow* _window; //main application window + + UIAccelerationValue accel[3]; + + osg::ref_ptr _viewer; + osg::ref_ptr _root; + +} + +@property (nonatomic, retain) /*IBOutlet*/ UIWindow *_window; + +- (void)updateScene; + +@end + diff --git a/examples/osgviewerIPhone/iphoneViewerAppDelegate.mm b/examples/osgviewerIPhone/iphoneViewerAppDelegate.mm new file mode 100755 index 000000000..3433400a6 --- /dev/null +++ b/examples/osgviewerIPhone/iphoneViewerAppDelegate.mm @@ -0,0 +1,191 @@ +//Created by Thomas Hogarth 2009 + +// +//This exampe shows how to render osg into an existing windw. Apple recommends apps only have one window on IPhone so this +// will be your best bet. +// + +#import "iphoneViewerAppDelegate.h" +#include +#include +//inckude the iphone specific windowing stuff +#include + + +#define kAccelerometerFrequency 30.0 // Hz +#define kFilteringFactor 0.1 + +@implementation iphoneViewerAppDelegate + +@synthesize _window; + + +// +//Called once app has finished launching, create the viewer then realize. Can't call viewer->run as will +//block the final inialization of the windowing system +// +- (void)applicationDidFinishLaunching:(UIApplication *)application { + + std::string test_string; + test_string = "huhu"; + + //get the screen size + CGRect lFrame = [[UIScreen mainScreen] bounds]; + unsigned int w = lFrame.size.width; + unsigned int h = lFrame.size.height; + + // create the main window at screen size + self._window = [[UIWindow alloc] initWithFrame: lFrame]; + + //show window + [_window makeKeyAndVisible]; + + +//create our graphics context directly so we can pass our own window + osg::ref_ptr traits = new osg::GraphicsContext::Traits; + + // Init the Windata Variable that holds the handle for the Window to display OSG in. + osg::ref_ptr windata = new osgViewer::GraphicsWindowIOS::WindowData(_window); + + // Setup the traits parameters + traits->x = 0; + traits->y = 0; + traits->width = w; + traits->height = h; + traits->depth = 16; //keep memory down, default is currently 24 + //traits->alpha = 8; + //traits->stencil = 8; + traits->windowDecoration = false; + traits->doubleBuffer = true; + traits->sharedContext = 0; + traits->setInheritedWindowPixelFormat = true; + //traits->windowName = "osgViewer"; + + traits->inheritedWindowData = windata; + + // Create the Graphics Context + osg::ref_ptr graphicsContext = osg::GraphicsContext::createGraphicsContext(traits.get()); + + //create the viewer + _viewer = new osgViewer::Viewer(); + //if the context was created then attach to our viewer + if(graphicsContext) + { + _viewer->getCamera()->setGraphicsContext(graphicsContext); + _viewer->getCamera()->setViewport(new osg::Viewport(0, 0, traits->width, traits->height)); + } + + //create scene and attch to viewer + + //create root + _root = new osg::MatrixTransform(); + + //load and attach scene model + osg::ref_ptr model = (osgDB::readNodeFile("hog.osg")); + _root->addChild(model); + + osg::Geode* geode = new osg::Geode(); + osg::ShapeDrawable* drawable = new osg::ShapeDrawable(new osg::Box(osg::Vec3(1,1,1), 1)); + geode->addDrawable(drawable); + _root->addChild(geode); + + + //create and attach ortho camera for hud text + osg::ref_ptr _hudCamera = new osg::CameraNode; + + // set the projection matrix + _hudCamera->setProjectionMatrix(osg::Matrix::ortho2D(0,w,0,h)); + + // set the view matrix + _hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); + _hudCamera->setViewMatrix(osg::Matrix::identity()); + + // only clear the depth buffer + _hudCamera->setClearMask(GL_DEPTH_BUFFER_BIT); + + // draw subgraph after main camera view. + _hudCamera->setRenderOrder(osg::CameraNode::POST_RENDER); + _root->addChild(_hudCamera.get()); + + //attcg text to hud + /*osg::ref_ptr text = new osgText::Text; + osg::ref_ptr textGeode = new osg::Geode(); + osg::StateSet* stateset = textGeode->getOrCreateStateSet(); + stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + + textGeode->addDrawable( text ); + _hudCamera->addChild(textGeode.get()); + std::string timesFont("arial.ttf"); + osg::Vec3 position = osg::Vec3(w/2.0f, h/2.0f, 0.0f); + osg::Vec3 delta(0.0f,-120.0f,0.0f); + + + text->setFont(timesFont); + text->setCharacterSize(20.0,1.0); + text->setColor(osg::Vec4(0.8,0.8,0.8,1.0)); + text->setPosition(position); + text->setMaximumHeight(480); + text->setMaximumWidth(320); + text->setAlignment(osgText::Text::CENTER_CENTER ); + text->setText("It's a Hogs life...");*/ + + + _viewer->setSceneData(_root.get()); + _viewer->setCameraManipulator(new osgGA::TrackballManipulator); + _viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);//SingleThreaded DrawThreadPerContext + + // + //_viewer->realize(); + + osg::setNotifyLevel(osg::DEBUG_FP); + + [NSTimer scheduledTimerWithTimeInterval:1.0/30.0 target:self selector:@selector(updateScene) userInfo:nil repeats:YES]; + + //Configure and start accelerometer + [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kAccelerometerFrequency)]; + [[UIAccelerometer sharedAccelerometer] setDelegate:self]; +} + + +// +//Timer called function to update our scene and render the viewer +// +- (void)updateScene { + _viewer->frame(); +} + + +- (void)applicationWillResignActive:(UIApplication *)application { + +} + + +- (void)applicationDidBecomeActive:(UIApplication *)application { + +} + + +-(void)applicationWillTerminate:(UIApplication *)application{ + _root = NULL; + _viewer = NULL; +} + +// +//Accelorometer +// +- (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration +{ + //Use a basic low-pass filter to only keep the gravity in the accelerometer values + accel[0] = acceleration.x * kFilteringFactor + accel[0] * (1.0 - kFilteringFactor); + accel[1] = acceleration.y * kFilteringFactor + accel[1] * (1.0 - kFilteringFactor); + accel[2] = acceleration.z * kFilteringFactor + accel[2] * (1.0 - kFilteringFactor); +} + + +- (void)dealloc { + _root = NULL; + _viewer = NULL; + [super dealloc]; +} + +@end diff --git a/examples/osgviewerIPhone/main.m b/examples/osgviewerIPhone/main.m new file mode 100755 index 000000000..724f97c7f --- /dev/null +++ b/examples/osgviewerIPhone/main.m @@ -0,0 +1,17 @@ +// +// main.m +// iphoneViewer +// +// Created by Thomas Hogarth on 10/05/2009. +// Copyright HogBox 2009. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) { + + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + UIApplicationMain(argc, argv, nil, @"iphoneViewerAppDelegate"); + [pool release]; + return 0; +} diff --git a/examples/osgviewerIPhone/osgIPhoneViewer-Info.plist b/examples/osgviewerIPhone/osgIPhoneViewer-Info.plist new file mode 100755 index 000000000..36d13ed89 --- /dev/null +++ b/examples/osgviewerIPhone/osgIPhoneViewer-Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + icon.png + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + + diff --git a/examples/osgviewerIPhone/osgPlugins.h b/examples/osgviewerIPhone/osgPlugins.h new file mode 100755 index 000000000..229d91afb --- /dev/null +++ b/examples/osgviewerIPhone/osgPlugins.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +//windowing system +USE_GRAPICSWINDOW_IMPLEMENTATION(IOS) + + +//plugins + +//USE_OSGPLUGIN(obj) +//USE_OSGPLUGIN(ive) +USE_OSGPLUGIN(osg) + +USE_OSGPLUGIN(imageio) + +USE_OSGPLUGIN(freetype) + diff --git a/include/osgViewer/api/IOS/GraphicsWindowIOS b/include/osgViewer/api/IOS/GraphicsWindowIOS new file mode 100755 index 000000000..84302a2e8 --- /dev/null +++ b/include/osgViewer/api/IOS/GraphicsWindowIOS @@ -0,0 +1,209 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +/* Note, elements of GraphicsWindowX11 have used Prodcer/RenderSurface_X11.cpp as both + * a guide to use of X11/GLX and copiying directly in the case of setBorder(). + * These elements are license under OSGPL as above, with Copyright (C) 2001-2004 Don Burns. + */ + +#ifndef OSGVIEWER_GRAPHICSWINDOWCOCOA +#define OSGVIEWER_GRAPHICSWINDOWCOCOA 1 + +#ifdef __APPLE__ + +#ifdef __OBJC__ +@class GraphicsWindowIOSWindow; +@class GraphicsWindowIOSGLView; +@class GraphicsWindowIOSGLViewController; +@class EAGLContext; +@class UIWindow; +@class UIView; +#else +class GraphicsWindowIOSGLView; +class GraphicsWindowIOSWindow; +class GraphicsWindowIOSGLViewController; +class EAGLContext; +class UIWindow; +class UIView; +#endif + +#include + +// we may not include any cocoa-header here, because this will pollute the name-sapce and tend to compile-errors + +namespace osgViewer +{ + +class GraphicsWindowIOS : public osgViewer::GraphicsWindow +{ + public: + class Implementation; + + GraphicsWindowIOS(osg::GraphicsContext::Traits* traits) + : GraphicsWindow(), + _valid(false), + _initialized(false), + _realized(false), + _ownsWindow(true), + _adaptToDeviceOrientation(true), + _viewContentScaleFactor(-1.0f), + _window(NULL), + _context(NULL) + { + _traits = traits; + + init(); + + if (valid()) + { + setState( new osg::State ); + getState()->setGraphicsContext(this); + + if (_traits.valid() && _traits->sharedContext) + { + getState()->setContextID( _traits->sharedContext->getState()->getContextID() ); + incrementContextIDUsageCount( getState()->getContextID() ); + } + else + { + getState()->setContextID( osg::GraphicsContext::createNewContextID() ); + } + } + } + + virtual bool isSameKindAs(const Object* object) const { return dynamic_cast(object)!=0; } + virtual const char* libraryName() const { return "osgViewer"; } + virtual const char* className() const { return "GraphicsWindowCarbon"; } + + virtual bool valid() const { return _valid; } + + /** Realise the GraphicsContext.*/ + virtual bool realizeImplementation(); + + /** Return true if the graphics context has been realised and is ready to use.*/ + virtual bool isRealizedImplementation() const { return _realized; } + + /** Close the graphics context.*/ + virtual void closeImplementation(); + + /** Make this graphics context current.*/ + virtual bool makeCurrentImplementation(); + + /** Release the graphics context.*/ + virtual bool releaseContextImplementation(); + + /** Swap the front and back buffers.*/ + virtual void swapBuffersImplementation(); + + /** Check to see if any events have been generated.*/ + virtual void checkEvents(); + + /** Set Window decoration.*/ + virtual bool setWindowDecorationImplementation(bool flag); + + /** Get focus.*/ + virtual void grabFocus(); + + /** Get focus on if the pointer is in this window.*/ + virtual void grabFocusIfPointerInWindow(); + + /** Raise the window to the top.*/ + virtual void raiseWindow(); + + bool requestClose() {return false; } + + virtual void resizedImplementation(int x, int y, int width, int height); + + virtual bool setWindowRectangleImplementation(int x, int y, int width, int height); + + virtual void setWindowName (const std::string & name); + virtual void useCursor(bool cursorOn); + virtual void setCursor(MouseCursor mouseCursor); + + // WindowData is used to pass in the an existing UIWindow to be used to display our glView + class WindowData : public osg::Referenced + { + public: + WindowData(UIWindow* window = NULL, bool adaptToDeviceOrientation = true, float scaleFactor = -1.0f) + : _window(window), + _adaptToDeviceOrientation(adaptToDeviceOrientation), + _viewContentScaleFactor(scaleFactor) + { + } + + void setAdaptToDeviceOrientation(bool flag) { _adaptToDeviceOrientation = flag; } + + void setViewContentScaleFactor(float scaleFactor) { _viewContentScaleFactor = scaleFactor; } + + private: + + UIWindow* _window; + bool _adaptToDeviceOrientation; + float _viewContentScaleFactor; + + friend class GraphicsWindowIOS; + + }; + + EAGLContext* getContext() { return _context; } + GraphicsWindowIOSWindow* getWindow() { return _window; } + + void setVSync(bool f); + + /** adapts a resize / move of the window, coords in global screen space */ + void adaptResize(int x, int y, int w, int h); + + + bool adaptToDeviceOrientation() const { return _adaptToDeviceOrientation; } + + void setAdaptToDeviceOrientation(bool flag) { _adaptToDeviceOrientation = flag; } + + + // + //helper funs for converting points to pixels + osg::Vec2 pointToPixel(const osg::Vec2& point); + osg::Vec2 pixelToPoint(const osg::Vec2& pixel); + + protected: + + void init(); + + void transformMouseXY(float& x, float& y); + + virtual ~GraphicsWindowIOS(); + + + bool _valid; + bool _initialized; + bool _realized; + bool _useWindowDecoration; + + + private: + + GraphicsWindowIOSWindow* _window; + GraphicsWindowIOSGLView* _view; + GraphicsWindowIOSGLViewController* _viewController; + EAGLContext* _context; + bool _updateContext; + + bool _ownsWindow, _adaptToDeviceOrientation; + + float _viewContentScaleFactor; + +}; + +} + +#endif +#endif diff --git a/src/osgPlugins/imageio/ReaderWriterImageIO_IOS.cpp b/src/osgPlugins/imageio/ReaderWriterImageIO_IOS.cpp new file mode 100755 index 000000000..13657c290 --- /dev/null +++ b/src/osgPlugins/imageio/ReaderWriterImageIO_IOS.cpp @@ -0,0 +1,361 @@ +#pragma once +#include +#include +#include + +#include +#include +#include + +#include // for istream +#include // for ios:: + +#import +#import +#import +//#include "CoreGraphicsLoader.h" + +static NSString* toNSString(const std::string& text, NSStringEncoding nsse) +{ + NSString* nstr = nil; + + if (!text.empty()) + { + nstr = [NSString stringWithCString:text.c_str() encoding:nsse]; + //nstr = [NSString stringWithUTF8String:text.c_str()];// encoding:nsse] + } + + if (nstr == nil) + { + nstr = @""; + } + + return nstr; +} + +// std::string to NSString with the UTF8 encoding + +static NSString* toNSString(const std::string& text) +{ + return toNSString(text, NSUTF8StringEncoding); +} + + +// +//really basic image io for IOS +// +osg::Image* ReadCoreGraphicsImageFromFile(std::string file) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + //chop the extension off + std::string strExt = osgDB::getFileExtension(file); + std::string strPath = osgDB::getFilePath(file); + std::string strName = osgDB::getStrippedName(file); + std::string strFile = strPath+"/"+strName; + + NSString* path = [NSString stringWithCString:strName.c_str() length:strlen(strName.c_str())]; + NSString* ext = [NSString stringWithCString:strExt.c_str() length:strlen(strExt.c_str())]; + + //CGImageRef textureImage = [UIImage imageNamed:path].CGImage; + CGImageRef textureImage = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:path ofType:ext]].CGImage; + + if (textureImage == nil) { + + NSLog(@"imageio: failed to load CGImageRef image '%@'", path ); + return NULL; + } + + + NSInteger texWidth = CGImageGetWidth(textureImage); + NSInteger texHeight = CGImageGetHeight(textureImage); + + GLubyte *textureData = (GLubyte *)malloc(texWidth * texHeight * 4); + + CGContextRef textureContext = CGBitmapContextCreate(textureData, + texWidth, texHeight, + 8, texWidth * 4, + CGColorSpaceCreateDeviceRGB(), + kCGImageAlphaPremultipliedLast); + + //copy into texturedata + CGContextDrawImage(textureContext, + CGRectMake(0.0, 0.0, (float)texWidth, (float)texHeight), + textureImage); + + CGContextRelease(textureContext); + + + //create the osg image + unsigned int dataType = GL_UNSIGNED_BYTE; + int s = texWidth; + int t = texHeight; + + + osg::Image* image = new osg::Image(); + image->setImage(s, t, 1, + GL_RGBA, + GL_RGBA, + GL_UNSIGNED_BYTE, + textureData, + osg::Image::USE_MALLOC_FREE); + + //flip vertical + image->flipVertical(); + + // + // Reverse the premultiplied alpha for avoiding unexpected darker edges + // by Tatsuhiro Nishioka (based on SDL's workaround on the similar issue) + // http://bugzilla.libsdl.org/show_bug.cgi?id=868 + // + + + int i, j; + GLubyte *pixels = (GLubyte *)image->data(); + for (i = image->t() * image->s(); i--; ) { + + GLubyte alpha = pixels[3]; + if (alpha && (alpha < 255)) { + for (j = 0; j < 3; ++j) { + pixels[j] = (static_cast(pixels[j]) * 255) / alpha; + } + } + pixels += 4; + } + + + [pool release]; + return image; + + +} + + +class ReaderWriterImageIO : public osgDB::ReaderWriter + +{ +public: + ReaderWriterImageIO() + { + + supportsExtension("jpg", "jpg image file"); + supportsExtension("jpeg", "jpeg image file"); + supportsExtension("jpe", "jpe image file"); + supportsExtension("jp2", "jp2 image file"); + supportsExtension("tiff", "tiff image file"); + supportsExtension("tif", "tif image file"); + supportsExtension("gif", "gif image file"); + supportsExtension("png", "png image file"); + supportsExtension("pict", "pict image file"); + supportsExtension("pct", "pct image file"); + supportsExtension("pic", "pic image file"); + supportsExtension("bmp", "bmp image file"); + supportsExtension("BMPf", "BMPf image file"); + supportsExtension("ico", "ico image file"); + supportsExtension("icns", "icns image file"); + supportsExtension("tga", "tga image file"); + supportsExtension("targa", "targa image file"); + supportsExtension("psd", "psd image file"); + + supportsExtension("pdf", "pdf image file"); + supportsExtension("eps", "eps image file"); + supportsExtension("epi", "epi image file"); + supportsExtension("epsf", "epsf image file"); + supportsExtension("epsi", "epsi image file"); + supportsExtension("ps", "postscript image file"); + + supportsExtension("dng", "dng image file"); + supportsExtension("cr2", "cr2 image file"); + supportsExtension("crw", "crw image file"); + supportsExtension("fpx", "fpx image file"); + supportsExtension("fpxi", "fpxi image file"); + supportsExtension("raf", "raf image file"); + supportsExtension("dcr", "dcr image file"); + supportsExtension("ptng", "ptng image file"); + supportsExtension("pnt", "pnt image file"); + supportsExtension("mac", "mac image file"); + supportsExtension("mrw", "mrw image file"); + supportsExtension("nef", "nef image file"); + supportsExtension("orf", "orf image file"); + supportsExtension("exr", "exr image file"); + supportsExtension("qti", "qti image file"); + supportsExtension("qtif", "qtif image file"); + supportsExtension("hdr", "hdr image file"); + supportsExtension("sgi", "sgi image file"); + supportsExtension("srf", "srf image file"); + supportsExtension("cur", "cur image file"); + supportsExtension("xbm", "xbm image file"); + + supportsExtension("raw", "raw image file"); + } + + virtual const char* className() const { return "Mac OS X ImageIO based Image Reader/Writer"; } + + + virtual bool acceptsExtension(const std::string& extension) const + { + // ImageIO speaks in UTIs. + // http://developer.apple.com/graphicsimaging/workingwithimageio.html + // The Cocoa drawing guide lists these and says to use the + // imageFileTypes class method of NSImage to get a complete + // list of extensions. But remember ImageIO may support more formats + // than Cocoa. + // http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaDrawingGuide/Images/chapter_7_section_3.html + // Apple's UTI guide: + // http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis/utilist/chapter_4_section_1.html + return + osgDB::equalCaseInsensitive(extension,"jpg") || + osgDB::equalCaseInsensitive(extension,"jpeg") || + osgDB::equalCaseInsensitive(extension,"jpe") || + osgDB::equalCaseInsensitive(extension,"jp2") || + osgDB::equalCaseInsensitive(extension,"tiff") || + osgDB::equalCaseInsensitive(extension,"tif") || + osgDB::equalCaseInsensitive(extension,"gif") || + osgDB::equalCaseInsensitive(extension,"png") || + osgDB::equalCaseInsensitive(extension,"pict") || + osgDB::equalCaseInsensitive(extension,"pct") || + osgDB::equalCaseInsensitive(extension,"pic") || + osgDB::equalCaseInsensitive(extension,"bmp") || + osgDB::equalCaseInsensitive(extension,"BMPf") || + osgDB::equalCaseInsensitive(extension,"ico") || + osgDB::equalCaseInsensitive(extension,"icns") || + osgDB::equalCaseInsensitive(extension,"tga") || + osgDB::equalCaseInsensitive(extension,"targa") || + osgDB::equalCaseInsensitive(extension,"psd") || + + osgDB::equalCaseInsensitive(extension,"pdf") || + osgDB::equalCaseInsensitive(extension,"eps") || + osgDB::equalCaseInsensitive(extension,"epi") || + osgDB::equalCaseInsensitive(extension,"epsf") || + osgDB::equalCaseInsensitive(extension,"epsi") || + osgDB::equalCaseInsensitive(extension,"ps") || + + osgDB::equalCaseInsensitive(extension,"dng") || + osgDB::equalCaseInsensitive(extension,"cr2") || + osgDB::equalCaseInsensitive(extension,"crw") || + osgDB::equalCaseInsensitive(extension,"fpx") || + osgDB::equalCaseInsensitive(extension,"fpxi") || + osgDB::equalCaseInsensitive(extension,"raf") || + osgDB::equalCaseInsensitive(extension,"dcr") || + osgDB::equalCaseInsensitive(extension,"ptng") || + osgDB::equalCaseInsensitive(extension,"pnt") || + osgDB::equalCaseInsensitive(extension,"mac") || + osgDB::equalCaseInsensitive(extension,"mrw") || + osgDB::equalCaseInsensitive(extension,"nef") || + osgDB::equalCaseInsensitive(extension,"orf") || + osgDB::equalCaseInsensitive(extension,"exr") || + osgDB::equalCaseInsensitive(extension,"qti") || + osgDB::equalCaseInsensitive(extension,"qtif") || + osgDB::equalCaseInsensitive(extension,"hdr") || + osgDB::equalCaseInsensitive(extension,"sgi") || + osgDB::equalCaseInsensitive(extension,"srf") || + osgDB::equalCaseInsensitive(extension,"cur") || + osgDB::equalCaseInsensitive(extension,"xbm") || + + osgDB::equalCaseInsensitive(extension,"raw"); + } + + + + ReadResult readImageStream(std::istream& fin) const + { + /*// Call ImageIO to load the image. + CGImageRef cg_image_ref = CreateCGImageFromDataStream(fin); + if (NULL == cg_image_ref) return ReadResult::FILE_NOT_FOUND; + */ + // Create an osg::Image from the CGImageRef. + osg::Image* osg_image = NULL; //CreateOSGImageFromCGImage(cg_image_ref); + + //CFRelease(cg_image_ref); + return osg_image; + } + + virtual ReadResult readImage(std::istream& fin, const osgDB::ReaderWriter::Options* the_options = NULL) const + { + ReadResult read_result = readImageStream(fin); + return read_result; + } + + ReadResult readImageFile(const std::string& file_name) const + { + //osg::notify(osg::INFO) << "imageio readImageFile: " << file_name << std::endl; + + // Create an osg::Image from the CGImageRef. + osg::Image* osg_image = ReadCoreGraphicsImageFromFile(file_name); + + return osg_image; + } + + virtual ReadResult readImage(const std::string& file_name, const osgDB::ReaderWriter::Options* the_options) const + { + std::string ext = osgDB::getLowerCaseFileExtension(file_name); + if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; + + std::string full_file_name = osgDB::findDataFile( file_name, the_options ); + if (full_file_name.empty()) return ReadResult::FILE_NOT_FOUND; + +#if 1 + ReadResult read_result = readImageFile(full_file_name); +#else + // Only here to help test istream backend. The file version is better because + // the filenname.extension could potentially be used by ImageIO to hint what the format type is. + std::ifstream istream(full_file_name.c_str(), std::ios::in | std::ios::binary); + if(!istream) return ReadResult::FILE_NOT_HANDLED; + ReadResult read_result = readImage(istream); +#endif + + if(read_result.validImage()) + { + read_result.getImage()->setFileName(full_file_name); + } + return read_result; + } + + + WriteResult writeImageStream(const osg::Image& osg_image, std::ostream& fout, const osgDB::ReaderWriter::Options* the_options) const + { + WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE; + + return WriteResult::FILE_SAVED; + } + + virtual WriteResult writeImage(const osg::Image& osg_image, std::ostream& fout, const osgDB::ReaderWriter::Options* the_options) const + { + WriteResult write_result = writeImageStream(osg_image, fout, the_options); + return write_result; + } + + WriteResult writeImageFile(const osg::Image& osg_image, const std::string& full_file_name, const osgDB::ReaderWriter::Options* the_options) const + { + WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE; + + return WriteResult::FILE_SAVED; + } + + virtual WriteResult writeImage(const osg::Image& osg_image, const std::string& file_name, const osgDB::ReaderWriter::Options* the_options) const + { + std::string ext = osgDB::getFileExtension(file_name); + if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; + +#if 1 + // FIXME: Something may need to provide a proper writable location for the files. + std::string full_file_name; + full_file_name = file_name; + return writeImageFile(osg_image, full_file_name, the_options); +#else + // Only here to help test ostream backend. The file version is better because + // the filenname.extension could potentially be used by ImageIO to hint what the format type is. + std::ofstream fout(file_name.c_str(), std::ios::out | std::ios::binary); + if(!fout) return WriteResult::ERROR_IN_WRITING_FILE; + return writeImage(osg_image, fout, the_options); +#endif + } + +}; + +// now register with Registry to instantiate the above +// reader/writer. +REGISTER_OSGPLUGIN(imageio, ReaderWriterImageIO) + + + + diff --git a/src/osgViewer/CMakeLists.txt b/src/osgViewer/CMakeLists.txt index 7a65cca68..8358ed29e 100644 --- a/src/osgViewer/CMakeLists.txt +++ b/src/osgViewer/CMakeLists.txt @@ -63,11 +63,17 @@ IF(WIN32) ) ELSE() IF(APPLE) - SET(OSG_WINDOWING_SYSTEM "Carbon" CACHE STRING "Windowing system type for graphics window creation, options Carbon, Cocoa or X11.") + + IF(OSG_BUILD_PLATFORM_IPHONE OR OSG_BUILD_PLATFORM_IPHONE_SIMULATOR) + SET(OSG_WINDOWING_SYSTEM "IOS" CACHE STRING "Windowing system type for graphics window creation, options only IOS.") + ELSE() + SET(OSG_WINDOWING_SYSTEM "Carbon" CACHE STRING "Windowing system type for graphics window creation, options Carbon, Cocoa or X11.") + ENDIF() + ELSE() SET(OSG_WINDOWING_SYSTEM "X11" CACHE STRING "Windowing system type for graphics window creation. options only X11") ENDIF() - + IF(${OSG_WINDOWING_SYSTEM} STREQUAL "Cocoa") ADD_DEFINITIONS(-DUSE_DARWIN_COCOA_IMPLEMENTATION) @@ -95,6 +101,7 @@ ELSE() PixelBufferCocoa.mm ) SET(LIB_EXTRA_LIBS ${COCOA_LIBRARY} ${LIB_EXTRA_LIBS}) + ELSEIF(${OSG_WINDOWING_SYSTEM} STREQUAL "Carbon") ADD_DEFINITIONS(-DUSE_DARWIN_CARBON_IMPLEMENTATION) @@ -113,16 +120,42 @@ ELSE() ${HEADER_PATH}/api/Carbon/GraphicsWindowCarbon ${HEADER_PATH}/api/Carbon/PixelBufferCarbon ) - ENDIF() - + ENDIF() + SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} GraphicsWindowCarbon.cpp DarwinUtils.h DarwinUtils.mm PixelBufferCarbon.cpp ) - + SET(LIB_EXTRA_LIBS ${COCOA_LIBRARY} ${LIB_EXTRA_LIBS}) + + ELSEIF(${OSG_WINDOWING_SYSTEM} STREQUAL "IOS") + + ADD_DEFINITIONS(-DUSE_IOS_IMPLEMENTATION) + + IF(OSG_COMPILE_FRAMEWORKS) + SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} + ${HEADER_PATH}/api/IOS/GraphicsWindowIOS + ) + + SET_PROPERTY(SOURCE ${HEADER_PATH}/api/IOS/GraphicsWindowIOS PROPERTY MACOSX_PACKAGE_LOCATION Headers/api/IOS) + ELSE() + SET(LIB_PUBLIC_HEADERS ${LIB_PUBLIC_HEADERS} + ${HEADER_PATH}/api/IOS/GraphicsWindowIOS + #${HEADER_PATH}/api/IOS/PixelBufferIOS + ) + ENDIF() + + SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} + GraphicsWindowIOS.mm + IOSUtils.h + IOSUtils.mm + ) + + SET(LIB_EXTRA_LIBS ${COCOA_LIBRARY} ${LIB_EXTRA_LIBS}) + ELSE() # X11 for everybody else INCLUDE(FindPkgConfig OPTIONAL) @@ -161,21 +194,26 @@ ELSE() # X11 on Apple requires X11 library plus OpenGL linking hack on Leopard IF(APPLE) - # Find GL/glx.h - IF(EXISTS ${CMAKE_OSX_SYSROOT}/usr/X11/include/GL/glx.h) - SET(OPENGL_INCLUDE_DIR /usr/X11/include) - SET(OPENGL_LIBRARIES /usr/X11/lib/libGL.dylib) - ELSEIF(EXISTS ${CMAKE_OSX_SYSROOT}/usr/X11R6/include/GL/glx.h) - SET(OPENGL_INCLUDE_DIR /usr/X11R6/include) - SET(OPENGL_LIBRARIES /usr/X11R6/lib/libGL.dylib) - ENDIF() - INCLUDE_DIRECTORIES(BEFORE SYSTEM ${OPENGL_INCLUDE_DIR}) + # hack for finding the iphone opengl es lib + IF(OSG_BUILD_PLATFORM_IOS) + SET(OPENGL_INCLUDE_DIR ${IPHONE_SDKROOT}System/Library/Frameworks) + SET(OPENGL_LIBRARIES ${IPHONE_SDKROOT}System/Library/Frameworks/OpenGLES) + ELSE() + # Find GL/glx.h + IF(EXISTS ${CMAKE_OSX_SYSROOT}/usr/X11/include/GL/glx.h) + SET(OPENGL_INCLUDE_DIR /usr/X11/include) + SET(OPENGL_LIBRARIES /usr/X11/lib/libGL.dylib) + ELSEIF(EXISTS ${CMAKE_OSX_SYSROOT}/usr/X11R6/include/GL/glx.h) + SET(OPENGL_INCLUDE_DIR /usr/X11R6/include) + SET(OPENGL_LIBRARIES /usr/X11R6/lib/libGL.dylib) + ENDIF() + INCLUDE_DIRECTORIES(BEFORE SYSTEM ${OPENGL_INCLUDE_DIR}) - SET(LIB_EXTRA_LIBS ${X11_X11_LIB} ${OPENGL_LIBRARIES} ${LIB_EXTRA_LIBS}) - SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-dylib_file,/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:${CMAKE_OSX_SYSROOT}/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib") - ELSE() - SET(LIB_EXTRA_LIBS ${X11_X11_LIB} ${LIB_EXTRA_LIBS}) - ENDIF() + SET(LIB_EXTRA_LIBS ${X11_X11_LIB} ${OPENGL_LIBRARIES} ${LIB_EXTRA_LIBS}) + SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-dylib_file,/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:${CMAKE_OSX_SYSROOT}/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib") + ENDIF() + + ENDIF(APPLE) ENDIF() ENDIF() diff --git a/src/osgViewer/GraphicsWindowIOS.mm b/src/osgViewer/GraphicsWindowIOS.mm new file mode 100755 index 000000000..8711c31fe --- /dev/null +++ b/src/osgViewer/GraphicsWindowIOS.mm @@ -0,0 +1,1016 @@ + + +#include +#include + +#import +#import + +#if OSG_GLES1_FEATURES + #import +#else + #import + // in GLES2, the OES suffix if dropped from function names (from rti) + #define glGenFramebuffersOES glGenFramebuffers + #define glGenRenderbuffersOES glGenRenderbuffers + #define glBindFramebufferOES glBindFramebuffer + #define glBindRenderbufferOES glBindRenderbuffer + #define glFramebufferRenderbufferOES glFramebufferRenderbuffer + #define glGetRenderbufferParameterivOES glGetRenderbufferParameteriv + #define glRenderbufferStorageOES glRenderbufferStorage + #define glDeleteRenderbuffersOES glDeleteRenderbuffers + #define glDeleteFramebuffersOES glDeleteFramebuffers + #define glCheckFramebufferStatusOES glCheckFramebufferStatus + + #define GL_FRAMEBUFFER_OES GL_FRAMEBUFFER + #define GL_RENDERBUFFER_OES GL_RENDERBUFFER + #define GL_RENDERBUFFER_WIDTH_OES GL_RENDERBUFFER_WIDTH + #define GL_RENDERBUFFER_HEIGHT_OES GL_RENDERBUFFER_HEIGHT + #define GL_COLOR_ATTACHMENT0_OES GL_COLOR_ATTACHMENT0 + #define GL_DEPTH_ATTACHMENT_OES GL_DEPTH_ATTACHMENT + #define GL_DEPTH_COMPONENT16_OES GL_DEPTH_COMPONENT16 + #define GL_STENCIL_INDEX8_OES GL_STENCIL_INDEX8 + #define GL_FRAMEBUFFER_COMPLETE_OES GL_FRAMEBUFFER_COMPLETE + #define GL_STENCIL_ATTACHMENT_OES GL_STENCIL_ATTACHMENT + + #define GL_RGB5_A1_OES GL_RGB5_A1 +#endif + +#include "IOSUtils.h" + + + + +#pragma mark GraphicsWindowIOSWindow + +// ---------------------------------------------------------------------------------------------------------- +// GraphicsWindowIOSWindow, implements canBecomeKeyWindow + canBecomeMainWindow +// ---------------------------------------------------------------------------------------------------------- + +@interface GraphicsWindowIOSWindow : UIWindow +{ +} + +- (BOOL) canBecomeKeyWindow; +- (BOOL) canBecomeMainWindow; + +@end + +@implementation GraphicsWindowIOSWindow + +// +//Implement dealloc +// +- (void) dealloc +{ + [super dealloc]; +} + +- (BOOL) canBecomeKeyWindow +{ + return YES; +} + +- (BOOL) canBecomeMainWindow +{ + return YES; +} + +@end + +#pragma mark GraphicsWindowIOSGLView + +// ---------------------------------------------------------------------------------------------------------- +// GraphicsWindowIOSGLView +// custom UIView-class handling creation and display of frame/render buffers plus receives touch input +// ---------------------------------------------------------------------------------------------------------- + +@interface GraphicsWindowIOSGLView : UIView +{ + @private + osgViewer::GraphicsWindowIOS* _win; + EAGLContext* _context; + + /* The pixel dimensions of the backbuffer */ + GLint _backingWidth; + GLint _backingHeight; + + //the pixel buffers for the video + /* OpenGL names for the renderbuffer and framebuffers used to render to this view */ + GLuint _viewRenderbuffer, _viewFramebuffer; + + /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */ + GLuint _depthRenderbuffer; + + /* OpenGL name for the stencil buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */ + GLuint _stencilBuffer; + + // for multisampled antialiased rendering + GLuint _msaaFramebuffer, _msaaRenderBuffer, _msaaDepthBuffer; + +} + +- (void)setGraphicsWindow: (osgViewer::GraphicsWindowIOS*) win; +- (osgViewer::GraphicsWindowIOS*) getGraphicsWindow; +- (void)setOpenGLContext: (EAGLContext*) context; + +- (BOOL)createFramebuffer; +- (void)destroyFramebuffer; +- (void)swapBuffers; +- (void)bindFrameBuffer; + +- (BOOL)acceptsFirstResponder; +- (BOOL)becomeFirstResponder; +- (BOOL)resignFirstResponder; + +- (osgGA::GUIEventAdapter::TouchPhase) convertTouchPhase: (UITouchPhase) phase; +- (osg::Vec2) convertPointToPixel: (osg::Vec2) point; + +@end + +@implementation GraphicsWindowIOSGLView + +- (osgGA::GUIEventAdapter::TouchPhase) convertTouchPhase: (UITouchPhase) phase +{ + switch(phase) { + + case UITouchPhaseBegan: + return osgGA::GUIEventAdapter::TOUCH_BEGAN; + break; + case UITouchPhaseMoved: + return osgGA::GUIEventAdapter::TOUCH_MOVED; + break; + + case UITouchPhaseStationary: + return osgGA::GUIEventAdapter::TOUCH_STATIONERY; + break; + + case UITouchPhaseEnded: + case UITouchPhaseCancelled: + return osgGA::GUIEventAdapter::TOUCH_ENDED; + break; + } + + return osgGA::GUIEventAdapter::TOUCH_ENDED; + +} + +- (osg::Vec2) convertPointToPixel: (osg::Vec2) point +{ + //get the views contentscale factor and multiply the point by it + float scale = 1.0f; + +#ifdef __IPHONE_4_0 && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) + scale = self.contentScaleFactor; +#endif + return osg::Vec2(point.x()*scale, point.y()*scale); + +} + +-(void) setGraphicsWindow: (osgViewer::GraphicsWindowIOS*) win +{ + _win = win; +} + +- (osgViewer::GraphicsWindowIOS*) getGraphicsWindow { + return _win; +} + +-(void) setOpenGLContext: (EAGLContext*) context +{ + _context = context; +} + +// You must implement this method ++ (Class)layerClass { + return [CAEAGLLayer class]; +} + +// +//Called when the view is created using a frame for dimensions +// +- (id)initWithFrame:(CGRect)frame : (osgViewer::GraphicsWindowIOS*)win{ + + _win = win; + + if ((self = [super initWithFrame:frame])) { + // Get the layer + CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; + + eaglLayer.opaque = YES;//need to look into this, can't remember why it's here, i.e. do I set it to no for alphaed window? + if(_win->getTraits()->alpha > 0) + { + //create layer with alpha channel RGBA8 + eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; + }else{ + //else no alpha, IOS uses RBG565 + eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGB565, kEAGLDrawablePropertyColorFormat, nil]; + + } + } + self.multipleTouchEnabled = YES; + + return self; +} + +// +//Implement dealloc to destory our frame buffer +// +- (void) dealloc +{ + //[self destroyFramebuffer]; + //[_context release];//OBJC_TEST + //_context = nil; + //_win = NULL; + [super dealloc]; +} + +- (void)layoutSubviews { + /* + [EAGLContext setCurrentContext:_context]; + [self destroyFramebuffer]; + [self createFramebuffer]; + */ +} + + +- (BOOL)createFramebuffer { + + _msaaFramebuffer = _msaaRenderBuffer = 0; + + glGenFramebuffersOES(1, &_viewFramebuffer); + glGenRenderbuffersOES(1, &_viewRenderbuffer); + + // set the default id for osg to switch back after using fbos. + _win->setDefaultFboId(_viewFramebuffer); + + glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); + [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer]; + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _viewRenderbuffer); + + glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &_backingWidth); + glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &_backingHeight); + + osg::notify(osg::DEBUG_INFO) << "GraphicsWindowIOS::createFramebuffer INFO: Created GL RenderBuffer of size " << _backingWidth << ", " << _backingHeight << " ." << std::endl; + + //add depth if requested + if(_win->getTraits()->depth > 0) { + glGenRenderbuffersOES(1, &_depthRenderbuffer); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, _depthRenderbuffer); + if(_win->getTraits()->depth == 16) + { + glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, _backingWidth, _backingHeight); + }else if(_win->getTraits()->depth == 24){ + glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT24_OES, _backingWidth, _backingHeight); + } + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _depthRenderbuffer); + } + + //add stencil if requested + if(_win->getTraits()->stencil > 0) { + glGenRenderbuffersOES(1, &_stencilBuffer); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, _stencilBuffer); + glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_STENCIL_INDEX8_OES, _backingWidth, _backingHeight); + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _stencilBuffer); + } + + //MSAA only available for >= 4.0 sdk + +#ifdef __IPHONE_4_0 && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) + + if(_win->getTraits()->sampleBuffers > 0) + { + glGenFramebuffersOES(1, &_msaaFramebuffer); + glGenRenderbuffersOES(1, &_msaaRenderBuffer); + + _win->setDefaultFboId(_msaaFramebuffer); + + glBindFramebufferOES(GL_FRAMEBUFFER_OES, _msaaFramebuffer); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, _msaaRenderBuffer); + + // Samples is the amount of pixels the MSAA buffer uses to make one pixel on the render // buffer. Use a small number like 2 for the 3G and below and 4 or more for newer models + + glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, _win->getTraits()->samples, GL_RGB5_A1_OES, _backingWidth, _backingHeight); + + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _msaaRenderBuffer); + glGenRenderbuffersOES(1, &_msaaDepthBuffer); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, _msaaDepthBuffer); + + glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, _win->getTraits()->samples, ( _win->getTraits()->depth == 16) ? GL_DEPTH_COMPONENT16_OES : GL_DEPTH_COMPONENT24_OES, _backingWidth , _backingHeight); + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _msaaDepthBuffer); + + } +#endif + + if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { + OSG_FATAL << "GraphicsWindowIOS::createFramebuffer ERROR: Failed to create a GL RenderBuffer, glCheckFramebufferStatusOES returned '" + << glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) << "'." << std::endl; + return NO; + } + + return YES; +} + + +- (void)destroyFramebuffer { + + if(_viewFramebuffer) + { + glDeleteFramebuffersOES(1, &_viewFramebuffer); + _viewFramebuffer = 0; + } + if(_viewRenderbuffer) + { + glDeleteRenderbuffersOES(1, &_viewRenderbuffer); + _viewRenderbuffer = 0; + } + + if(_depthRenderbuffer) { + glDeleteRenderbuffersOES(1, &_depthRenderbuffer); + _depthRenderbuffer = 0; + } + + if(_stencilBuffer) { + glDeleteFramebuffersOES(1, &_stencilBuffer); + _stencilBuffer = 0; + } + + if(_msaaRenderBuffer) { + glDeleteFramebuffersOES(1, &_msaaRenderBuffer); + _msaaRenderBuffer = 0; + } + + if(_msaaDepthBuffer) { + glDeleteFramebuffersOES(1, &_msaaDepthBuffer); + _msaaDepthBuffer = 0; + } + + if(_msaaFramebuffer) { + glDeleteFramebuffersOES(1, &_msaaFramebuffer); + _msaaFramebuffer = 0; + } +} + +// +//Swap the view and render buffers +// +- (void)swapBuffers { + + +#ifdef __IPHONE_4_0 && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) + if(_msaaFramebuffer) + { + glBindFramebufferOES(GL_FRAMEBUFFER_OES, _msaaFramebuffer); + + glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, _msaaFramebuffer); + glBindFramebufferOES(GL_DRAW_FRAMEBUFFER_APPLE, _viewFramebuffer); + + glResolveMultisampleFramebufferAPPLE(); + + GLenum attachments[] = {GL_DEPTH_ATTACHMENT_OES, GL_COLOR_ATTACHMENT0_OES}; + glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 2, attachments); + } +#endif + + + //swap buffers (sort of i think?) + glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); + + //display render in context + [_context presentRenderbuffer:GL_RENDERBUFFER_OES]; + + //re bind the frame buffer for next frames renders + glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer); + +#ifdef __IPHONE_4_0 && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) + if (_msaaFramebuffer) + glBindFramebufferOES(GL_FRAMEBUFFER_OES, _msaaFramebuffer);; +#endif +} + +// +//bind view buffer as current for new render pass +// +- (void)bindFrameBuffer { + + //bind the frame buffer + glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer); + +#ifdef __IPHONE_4_0 && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) + if (_msaaFramebuffer) + glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, _msaaFramebuffer); +#endif +} + + +- (BOOL)acceptsFirstResponder +{ + return YES; +} + +- (BOOL)becomeFirstResponder +{ + return YES; +} + +- (BOOL)resignFirstResponder +{ + return YES; +} + +// +//Touch input callbacks +// +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + + NSSet *allTouches = [event allTouches]; + + osg::ref_ptr osg_event(NULL); + + for(int i=0; i<[allTouches count]; i++) + { + + UITouch *touch = [[allTouches allObjects] objectAtIndex:i]; + CGPoint pos = [touch locationInView:touch.view]; + osg::Vec2 pixelPos = [self convertPointToPixel: osg::Vec2(pos.x,pos.y)]; + + if (!osg_event) { + osg_event = _win->getEventQueue()->touchBegan(i, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); + } else { + osg_event->addTouchPoint(i, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); + } + } + +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + + NSSet *allTouches = [event allTouches]; + + osg::ref_ptr osg_event(NULL); + + for(int i=0; i<[allTouches count]; i++) + { + UITouch *touch = [[allTouches allObjects] objectAtIndex:i]; + CGPoint pos = [touch locationInView:touch.view]; + osg::Vec2 pixelPos = [self convertPointToPixel: osg::Vec2(pos.x,pos.y)]; + + if (!osg_event) { + osg_event = _win->getEventQueue()->touchMoved(i, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); + } else { + osg_event->addTouchPoint(i, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); + } + + + } +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event + +{ + NSSet *allTouches = [event allTouches]; + + osg::ref_ptr osg_event(NULL); + + for(int i=0; i<[allTouches count]; i++) + { + UITouch *touch = [[allTouches allObjects] objectAtIndex:i]; + CGPoint pos = [touch locationInView:touch.view]; + osg::Vec2 pixelPos = [self convertPointToPixel: osg::Vec2(pos.x,pos.y)]; + + if (!osg_event) { + osg_event = _win->getEventQueue()->touchEnded(i, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y(), [touch tapCount]); + } else { + osg_event->addTouchPoint(i, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y(), [touch tapCount]); + } + + } +} + + +@end + + + +@interface GraphicsWindowIOSGLViewController : UIViewController +{ + +} +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation; +- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration; + +@end + +@implementation GraphicsWindowIOSGLViewController + + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + osgViewer::GraphicsWindowIOS* win = [(GraphicsWindowIOSGLView*)(self.view) getGraphicsWindow]; + + if ((win) && (win->adaptToDeviceOrientation() == false)) + return NO; + + BOOL result(NO); + + switch (interfaceOrientation) { + case UIDeviceOrientationPortrait: + case UIDeviceOrientationPortraitUpsideDown: + result = YES; + break; + default: + { + result = (win) ? (win->getTraits()->supportsResize) ? YES : NO : NO; + } + break; + } + OSG_INFO << "shouldAutorotateToInterfaceOrientation for " << interfaceOrientation << ": " << ((result==YES) ? "YES" : "NO") << std::endl; + return result; +} + + +- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration +{ + osgViewer::GraphicsWindowIOS* win = [(GraphicsWindowIOSGLView*)(self.view) getGraphicsWindow]; + if (win) { + CGRect frame = self.view.bounds; + osg::Vec2 pointOrigin = osg::Vec2(frame.origin.x,frame.origin.y); + osg::Vec2 pointSize = osg::Vec2(frame.size.width,frame.size.height); + osg::Vec2 pixelOrigin = [(GraphicsWindowIOSGLView*)(self.view) convertPointToPixel:pointOrigin]; + osg::Vec2 pixelSize = [(GraphicsWindowIOSGLView*)(self.view) convertPointToPixel:pointSize]; + OSG_INFO << "willAnimateRotationToInterfaceOrientation, resize to " + << pixelOrigin.x() << " " << pixelOrigin.y() << " " + << pixelSize.x() << " " << pixelSize.y() + << std::endl; + win->resized(pixelOrigin.x(), pixelOrigin.y(), pixelSize.x(), pixelSize.y()); + } + +} + + + +@end + + + +using namespace osgIOS; +namespace osgViewer { + + + +#pragma mark GraphicsWindowIOS + + + +// ---------------------------------------------------------------------------------------------------------- +// init +// ---------------------------------------------------------------------------------------------------------- + +void GraphicsWindowIOS::init() +{ + if (_initialized) return; + + _ownsWindow = false; + _context = NULL; + _window = NULL; + _updateContext = true; + //if -1.0 we use the screens scale factor + _viewContentScaleFactor = -1.0f; + _valid = _initialized = true; +} + + +// ---------------------------------------------------------------------------------------------------------- +// realizeImplementation, creates the window + context +// ---------------------------------------------------------------------------------------------------------- + +bool GraphicsWindowIOS::realizeImplementation() +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + BOOL bar_hidden = (_traits->windowDecoration) ? NO: YES; + #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED + #if __IPHONE_OS_VERSION_MIN_REQUIRED > 30100 + [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden withAnimation:UIStatusBarAnimationNone]; + #else + [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden animated:NO]; + #endif + #endif + + //Get info about the requested screen + IOSWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); + osg::Vec2 screenSizePoints; + osg::Vec2 screenSizePixels; + float screenScaleFactor = 1.0f; + UIScreen* screen = nil; + osg::GraphicsContext::ScreenSettings screenSettings; + if (wsi) { + wsi->getScreenContentScaleFactor((*_traits), screenScaleFactor); + wsi->getScreenSizeInPoints((*_traits), screenSizePoints); + screenSizePixels = osg::Vec2(screenSettings.width, screenSettings.height); + wsi->getScreenSettings((*_traits), screenSettings); + screen = wsi->getUIScreen((*_traits)); + }else{ + OSG_FATAL << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create IOS windowing system, OSG will be unable to create a vaild gl context and will not be able to render." << std::endl; + return false; + } + + _ownsWindow = true; + + // see if an existing inherited window was passed in + WindowData* windowData = _traits->inheritedWindowData ? dynamic_cast(_traits->inheritedWindowData.get()) : NULL; + if (windowData) + { + if (windowData->_window) + { + _ownsWindow = false; + _window = windowData->_window; + } + + _adaptToDeviceOrientation = windowData->_adaptToDeviceOrientation; + _viewContentScaleFactor = windowData->_viewContentScaleFactor; + } + + //if the user hasn't specified a viewScaleFactor we will use the screens scale factor + //so we get a full res buffer + if(_viewContentScaleFactor < 0.0f) + {_viewContentScaleFactor = screenScaleFactor;} + + + OSG_DEBUG << "GraphicsWindowIOS::realizeImplementation / ownsWindow: " << _ownsWindow << std::endl; + + + //Here's the confusing bit, the default traits use the screen res which is in pixels and the user will want to use pixels also + //but we need to create our views and windows in points. By default we create a full res buffer across all devices. This + //means that for backward compatibility you need to set the windowData _viewContentScaleFactor to 1.0f and set the screen res to the + //res of the older gen device. + CGRect viewBounds; + osg::Vec2 pointsOrigin = this->pixelToPoint(osg::Vec2(_traits->x, _traits->y)); + osg::Vec2 pointsSize = this->pixelToPoint(osg::Vec2(_traits->width, _traits->height)); + + viewBounds.origin.x = pointsOrigin.x(); + viewBounds.origin.y = pointsOrigin.y(); + viewBounds.size.width = pointsSize.x(); + viewBounds.size.height = pointsSize.y(); + + + //if we own the window we need to create one + if (_ownsWindow) + { + //create the IOS window object using the viewbounds (in points) required for our context size + _window = [[GraphicsWindowIOSWindow alloc] initWithFrame: viewBounds];// styleMask: style backing: NSBackingStoreBuffered defer: NO]; + + if (!_window) { + OSG_WARN << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create GraphicsWindowIOSWindow can not display gl view" << std::endl; + return false; + } + + OSG_DEBUG << "GraphicsWindowIOS::realizeImplementation: INFO: Created UIWindow with bounds '" << viewBounds.size.width << ", " << viewBounds.size.height << "' (points)." << std::endl; + + //if the user has requested a differnet screenNum from default 0 get the UIScreen object and + //apply to our window (this is for IPad external screens, I don't have one, so I've no idea if it works) + //I'm also not sure if we should apply this to external windows also? + if(_traits->screenNum > 0 && screen != nil) + { + _window.screen = screen; + } + } + + //create the desired OpenGLES context type +#if OSG_GLES1_FEATURES + _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; +#elif OSG_GLES2_FEATURES + _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; +#endif + + if (!_context || ![EAGLContext setCurrentContext:_context]) { + + #if OSG_GLES1_FEATURES + OSG_FATAL << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create a valid OpenGLES1 context" << std::endl; + #elif OSG_GLES2_FEATURES + OSG_FATAL << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create a valid OpenGLES2 context" << std::endl; + #endif + return false; + } + + //create the view to display our context in our window + GraphicsWindowIOSGLView* theView = [[ GraphicsWindowIOSGLView alloc ] initWithFrame:[ _window frame ] : this ]; + if(!theView) + { + OSG_FATAL << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create GraphicsWindowIOSGLView, can not create frame buffers." << std::endl; + return false; + } + + [theView setAutoresizingMask: ( UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight) ]; + + //Apply our content scale factor to our view, this is what converts the views points + //size to our desired context size. +#ifdef __IPHONE_4_0 && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) + theView.contentScaleFactor = _viewContentScaleFactor; + +#endif + [theView setGraphicsWindow: this]; + [theView setOpenGLContext:_context]; + _view = theView; + + OSG_DEBUG << "GraphicsWindowIOS::realizeImplementation / view: " << theView << std::endl; + + // + _viewController = [[GraphicsWindowIOSGLViewController alloc] init]; + _viewController.view = _view; + + + // Attach view to window + [_window addSubview: _view]; + [theView release]; + + //if we own the window also make it visible + if (_ownsWindow) { + //show window + [_window makeKeyAndVisible]; + } + + [pool release]; + + // IOSs origin is top/left: + getEventQueue()->getCurrentEventState()->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS); + + _valid = _initialized = _realized = true; + return _valid; +} + + + + +// ---------------------------------------------------------------------------------------------------------- +// closeImplementation +// ---------------------------------------------------------------------------------------------------------- +void GraphicsWindowIOS::closeImplementation() +{ + OSG_ALWAYS << "close IOS window" << std::endl; + _valid = false; + _realized = false; + + + if (_view) { + [_view setGraphicsWindow: NULL]; + [_view release]; + } + + if (_viewController) { + [_viewController release]; + _viewController = NULL; + } + + if (_window && _ownsWindow) { + [_window release]; + //[glView release]; + } + + + _window = NULL; + _view = NULL; +} + + +// ---------------------------------------------------------------------------------------------------------- +// makeCurrentImplementation +// ---------------------------------------------------------------------------------------------------------- + +bool GraphicsWindowIOS:: makeCurrentImplementation() +{ + + + //bind the context + [EAGLContext setCurrentContext:_context]; + + if (_updateContext) + { + [_view destroyFramebuffer]; + [_view createFramebuffer]; + + _updateContext = false; + } + //i think we also want to bind the frame buffer here + //[_view bindFrameBuffer]; + + return true; +} + + +// ---------------------------------------------------------------------------------------------------------- +// releaseContextImplementation +// ---------------------------------------------------------------------------------------------------------- + +bool GraphicsWindowIOS::releaseContextImplementation() +{ + if ([EAGLContext currentContext] == _context) { + [EAGLContext setCurrentContext:nil]; + } + return true; +} + + +// ---------------------------------------------------------------------------------------------------------- +// swapBuffersImplementation +// ---------------------------------------------------------------------------------------------------------- + +void GraphicsWindowIOS::swapBuffersImplementation() +{ + //[_context flushBuffer]; + [_view swapBuffers]; +} + + + +// ---------------------------------------------------------------------------------------------------------- +// setWindowDecorationImplementation +// +// We will use this to toggle the status bar on IPhone, nearest thing to window decoration +// ---------------------------------------------------------------------------------------------------------- + +bool GraphicsWindowIOS::setWindowDecorationImplementation(bool flag) +{ + if (!_realized || !_ownsWindow) return false; + + BOOL bar_hidden = (flag) ? NO: YES; + #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED + #if __IPHONE_OS_VERSION_MIN_REQUIRED > 30100 + [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden withAnimation:UIStatusBarAnimationNone]; + #else + [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden animated:NO]; + #endif + #endif + + return true; +} + + +// ---------------------------------------------------------------------------------------------------------- +// grabFocus +// ---------------------------------------------------------------------------------------------------------- +void GraphicsWindowIOS::grabFocus() +{ + //i think make key is the equivalent of focus on iphone + [_window makeKeyWindow]; +} + + +// ---------------------------------------------------------------------------------------------------------- +// grabFocusIfPointerInWindow +// ---------------------------------------------------------------------------------------------------------- +void GraphicsWindowIOS::grabFocusIfPointerInWindow() +{ + OSG_INFO << "GraphicsWindowIOS :: grabFocusIfPointerInWindow not implemented yet " << std::endl; +} + +// ---------------------------------------------------------------------------------------------------------- +// raiseWindow +// Raise the window to the top. +// ---------------------------------------------------------------------------------------------------------- +void GraphicsWindowIOS::raiseWindow() +{ + [_window bringSubviewToFront:_view]; +} + +// ---------------------------------------------------------------------------------------------------------- +// resizedImplementation +// ---------------------------------------------------------------------------------------------------------- + +void GraphicsWindowIOS::resizedImplementation(int x, int y, int width, int height) +{ + GraphicsContext::resizedImplementation(x, y, width, height); + + _updateContext = true; + + getEventQueue()->windowResize(x,y,width, height, getEventQueue()->getTime()); +} + + + + +// ---------------------------------------------------------------------------------------------------------- +// setWindowRectangleImplementation +// ---------------------------------------------------------------------------------------------------------- +bool GraphicsWindowIOS::setWindowRectangleImplementation(int x, int y, int width, int height) +{ + OSG_INFO << "GraphicsWindowIOS :: setWindowRectangleImplementation not implemented yet " << std::endl; + if (!_ownsWindow) + return false; + + return true; +} + + +void GraphicsWindowIOS::checkEvents() +{ + + +} + + + +// ---------------------------------------------------------------------------------------------------------- +// setWindowName +// ---------------------------------------------------------------------------------------------------------- + +void GraphicsWindowIOS::setWindowName (const std::string & name) +{ + OSG_INFO << "GraphicsWindowIOS :: setWindowName not implemented yet " << std::endl; +} + + +// ---------------------------------------------------------------------------------------------------------- +// useCursor, no cursor on IOS +// ---------------------------------------------------------------------------------------------------------- + +void GraphicsWindowIOS::useCursor(bool cursorOn) +{ + OSG_INFO << "GraphicsWindowIOS :: useCursor not implemented yet " << std::endl; +} + + +// ---------------------------------------------------------------------------------------------------------- +// setCursor, no cursor on IOS +// ---------------------------------------------------------------------------------------------------------- + +void GraphicsWindowIOS::setCursor(MouseCursor mouseCursor) +{ + OSG_INFO << "GraphicsWindowIOS :: setCursor not implemented yet " << std::endl; +} + + +// ---------------------------------------------------------------------------------------------------------- +// setVSync, no vsync on IOS +// ---------------------------------------------------------------------------------------------------------- + +void GraphicsWindowIOS::setVSync(bool f) +{ + OSG_INFO << "GraphicsWindowIOS :: setVSync not implemented yet " << std::endl; +} + + +// ---------------------------------------------------------------------------------------------------------- +// helper funcs for converting points to pixels taking into account the views contents scale factor +// ---------------------------------------------------------------------------------------------------------- + +osg::Vec2 GraphicsWindowIOS::pointToPixel(const osg::Vec2& point) +{ + return point * _viewContentScaleFactor; +} + +osg::Vec2 GraphicsWindowIOS::pixelToPoint(const osg::Vec2& pixel) +{ + float scaler = 1.0f / _viewContentScaleFactor; + return pixel * scaler; +} + + +// ---------------------------------------------------------------------------------------------------------- +// d'tor +// ---------------------------------------------------------------------------------------------------------- + +GraphicsWindowIOS::~GraphicsWindowIOS() +{ + close(); +} + + + +class ConcreteIOSWindowingSystemInterface : public IOSWindowingSystemInterface { +public: + ConcreteIOSWindowingSystemInterface() + : IOSWindowingSystemInterface() + { + } + + virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits) + { + if (traits->pbuffer) + { + // pbuffers not supported on iOS + return 0; + } + else + { + osg::ref_ptr window = new GraphicsWindowIOS(traits); + if (window->valid()) return window.release(); + else return 0; + } + } +}; + +}//end namspace + + +RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy; + + +// declare C entry point for static compilation. +extern "C" void graphicswindow_IOS(void) +{ + osg::GraphicsContext::setWindowingSystemInterface(new osgViewer::ConcreteIOSWindowingSystemInterface()); +} diff --git a/src/osgViewer/IOSUtils.h b/src/osgViewer/IOSUtils.h new file mode 100755 index 000000000..0bf186e8b --- /dev/null +++ b/src/osgViewer/IOSUtils.h @@ -0,0 +1,114 @@ +/* + * IOSUtils.h + * OpenSceneGraph + * + * Created by Thomas Hogarth on 25.11.09. + * + * By default we create a full res buffer across all devices and if now viewContentScaleFator is given We use the screens ScaleFactor. + * This means that for backward compatibility you need to set the windowData _viewContentScaleFactor to 1.0f and set the screen res to the + * res that of the older gen device. + * http://developer.apple.com/library/ios/documentation/IOS/Conceptual/IOSOSProgrammingGuide/SupportingResolutionIndependence/SupportingResolutionIndependence.html#//apple_ref/doc/uid/TP40007072-CH10-SW11 + * + */ + +#ifdef __APPLE__ + +#ifndef IOS_UTILS_HEADER_ +#define IOS_UTILS_HEADER_ + +#ifdef __OBJC__ +@class UIScreen; +#else +class UIScreen; +#endif + +#include +#include +#include + +namespace osgIOS { + + + +struct IOSWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface +{ +public: + IOSWindowingSystemInterface(); + + /** dtor */ + ~IOSWindowingSystemInterface(); + + + /** @return count of attached screens */ + virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si) ; + + virtual void getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution); + + virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, osg::GraphicsContext::ScreenSettingsList & resolutionList); + + virtual bool setScreenSettings (const osg::GraphicsContext::ScreenIdentifier & si, const osg::GraphicsContext::ScreenSettings & settings); + + /** returns screen-ndx containing rect x,y,w,h, NOT_TESTED@tom */ + unsigned int getScreenContaining(int x, int y, int w, int h); + + //IOS specific + + // + //return the UIScreen object asscoiated with the passed ScreenIdentifier + //returns nil if si isn't found + UIScreen* getUIScreen(const osg::GraphicsContext::ScreenIdentifier& si); + + // + //Get the contents scale factor of the screen, this is the scale factor required + //to convert points to pixels on this screen + bool getScreenContentScaleFactor(const osg::GraphicsContext::ScreenIdentifier& si, float& scaleFactor); + + // + //Get the screens size in points, docs state a point is roughly 1/160th of an inch + bool getScreenSizeInPoints(const osg::GraphicsContext::ScreenIdentifier& si, osg::Vec2& pointSize); + +protected: + + /** implementation of setScreenResolution */ + //IPad can have extenal screens which we can request a res for + //the main screen screenNum 0 can not currently have its res changed + //as it only has one mode (might change though and this should still handle it) + bool setScreenResolutionImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, unsigned int width, unsigned int height); + + /** implementation of setScreenRefreshRate, currently can't set refresh rate of IOS*/ + bool setScreenRefreshRateImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, double refreshRate); + + +private: + + + +}; + +template +struct RegisterWindowingSystemInterfaceProxy +{ + RegisterWindowingSystemInterfaceProxy() + { + osg::GraphicsContext::setWindowingSystemInterface(new WSI); + } + + ~RegisterWindowingSystemInterfaceProxy() + { + if (osg::Referenced::getDeleteHandler()) + { + osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); + osg::Referenced::getDeleteHandler()->flushAll(); + } + + osg::GraphicsContext::setWindowingSystemInterface(0); + } +}; + + + +} + +#endif + +#endif // __APPLE__ diff --git a/src/osgViewer/IOSUtils.mm b/src/osgViewer/IOSUtils.mm new file mode 100755 index 000000000..42e19ad06 --- /dev/null +++ b/src/osgViewer/IOSUtils.mm @@ -0,0 +1,288 @@ +/* + * DarwinUtils.cpp + * OpenSceneGraph + * + * Created by Stephan Huber on 27.06.08. + * Copyright 2008 Stephan Maximilian Huber, digital mind. All rights reserved. + * + */ + +#include +#include +#include +#import +#include "IOSUtils.h" + + +namespace osgIOS { + + +class AutoReleasePoolHelper { +public: + AutoReleasePoolHelper() { + pool = [[NSAutoreleasePool alloc] init]; + } + + ~AutoReleasePoolHelper() { [pool release]; } +private: + NSAutoreleasePool* pool; +}; + + +/** ctor, get a list of all attached displays */ +IOSWindowingSystemInterface::IOSWindowingSystemInterface() +: osg::GraphicsContext::WindowingSystemInterface() +{ +} + +/** dtor */ +IOSWindowingSystemInterface::~IOSWindowingSystemInterface() +{ + if (osg::Referenced::getDeleteHandler()) + { + osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); + osg::Referenced::getDeleteHandler()->flushAll(); + } + +} + + +/** @return count of attached screens */ +unsigned int IOSWindowingSystemInterface::getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si) +{ + AutoReleasePoolHelper auto_release_pool_helper; + return [[UIScreen screens] count]; +} + +void IOSWindowingSystemInterface::getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution) +{ + AutoReleasePoolHelper auto_release_pool_helper; + + if(si.screenNum >= [[UIScreen screens] count]){return;} + + + + //get the screens array from the UIScreen class + NSArray* screens = [UIScreen screens]; + //iterate to the desired screen num + UIScreen* screen = [screens objectAtIndex:si.screenNum]; + + if (si.screenNum == 0) + { + //internal display supports only one mode, UiScreenMode reports wrong sizes for internal display at least for iOS 3.2 + float scale = 1.0f; + + #ifdef __IPHONE_4_0 && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) + scale = [screen scale]; + #endif + + + resolution.width = [screen bounds].size.width * scale; + resolution.height = [screen bounds].size.height * scale; + resolution.colorDepth = 24; + resolution.refreshRate = 60; //i've read 60 is max, not sure if thats true + } + else + { + //get the screen mode + NSArray* modesArray = [screen availableModes]; + + if(modesArray) + { + //for this method we copy the first mode (default) then return + UIScreenMode* mode = [modesArray objectAtIndex:0]; + + CGSize size = [mode size]; + resolution.width = size.width; + resolution.height = size.height; + resolution.colorDepth = 24; + resolution.refreshRate = 60; //i've read 60 is max, not sure if thats true + + OSG_INFO << "new resolution for screen " << si.screenNum << ": " << size.width << "x" << size.height << std::endl; + } + } +} + +// +//Due to the weird +void IOSWindowingSystemInterface::enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, + osg::GraphicsContext::ScreenSettingsList & resolutionList) +{ + AutoReleasePoolHelper auto_release_pool_helper; + + if(si.screenNum >= [[UIScreen screens] count]){return;} + + //get the screens array from the UIScreen class + NSArray* screens = [UIScreen screens]; + //get the desired screen num + UIScreen* screen = [screens objectAtIndex:si.screenNum]; + + if (si.screenNum == 0) + { + //internal display supports only one mode, UiScreenMode reports wrong sizes for internal screen at least for iOS 3.2 + osg::GraphicsContext::ScreenSettings resolution; + + float scale = 1.0f; + #ifdef __IPHONE_4_0 && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) + scale = [screen scale]; + #endif + + resolution.width = [screen bounds].size.width * scale; + resolution.height = [screen bounds].size.height * scale; + resolution.colorDepth = 24; + resolution.refreshRate = 60; //i've read 60 is max, not sure if thats true + resolutionList.push_back(resolution); + + + } + else + { + // external display may support more resolutions: + + //get the screen mode + NSArray* modesArray = [screen availableModes]; + NSEnumerator* modesEnum = [modesArray objectEnumerator]; + UIScreenMode* mode; + //iterate over modes and get their size property + while ( mode = [modesEnum nextObject] ) { + + osg::GraphicsContext::ScreenSettings resolution; + CGSize size = [mode size]; + resolution.width = size.width; + resolution.height = size.height; + resolution.colorDepth = 24; + resolution.refreshRate = 60; //i've read 60 is max, not sure if thats true + resolutionList.push_back(resolution); + + OSG_INFO << "new resolution: " << size.width << "x" << size.height << std::endl; + } + + } +} + + + +bool IOSWindowingSystemInterface::setScreenSettings(const osg::GraphicsContext::ScreenIdentifier &si, const osg::GraphicsContext::ScreenSettings & settings) +{ + bool result = setScreenResolutionImpl(si, settings.width, settings.height); + if (result) + setScreenRefreshRateImpl(si, settings.refreshRate); + + return result; +} + + + +/** implementation of setScreenResolution */ +//IPad can have extenal screens which we can request a res for +//the main screen screenNum 0 can not currently have its res changed +//as it only has one mode (might change though and this should still handle it) +// +bool IOSWindowingSystemInterface::setScreenResolutionImpl(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height) +{ + AutoReleasePoolHelper auto_release_pool_helper; + + if(si.screenNum >= [[UIScreen screens] count]){return false;} + + + //get the screens array from the UIScreen class + NSArray* screens = [UIScreen screens]; + + //iterate to the desired screen num + UIScreen* screen = [screens objectAtIndex:si.screenNum]; + + //get the screen mode + NSArray* modesArray = [screen availableModes]; + NSEnumerator* modesEnum = [modesArray objectEnumerator]; + UIScreenMode* mode; + //iterate over modes and get their size property + while ( mode = [modesEnum nextObject] ) { + + osg::GraphicsContext::ScreenSettings resolution; + CGSize size = [mode size]; + + //if the modes size/resolution matches the passed width/height then assign this + //mode as the screens current mode + if(size.width == width && size.height == height) + { + screen.currentMode = mode; + OSG_INFO << "IOSWindowingSystemInterface::setScreenResolutionImpl: Set resolution of screen '" << si.screenNum << "', to '" << width << ", " << height << "'." << std::endl; + return true; + } + + } + + OSG_WARN << "IOSWindowingSystemInterface::setScreenResolutionImpl: Failed to set resolution of screen '" << si.screenNum << "', to '" << width << ", " << height << "'." << std::endl; + return false; +} + +/** implementation of setScreenRefreshRate, don't think you can do this on IOS */ +bool IOSWindowingSystemInterface::setScreenRefreshRateImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, double refreshRate) { + + return true; +} + + +unsigned int IOSWindowingSystemInterface::getScreenContaining(int x, int y, int w, int h) +{ + return 1; +} + +// +//return the UIScreen object asscoiated with the passed ScreenIdentifier +//returns nil if si isn't found +// +UIScreen* IOSWindowingSystemInterface::getUIScreen(const osg::GraphicsContext::ScreenIdentifier& si) +{ + AutoReleasePoolHelper auto_release_pool_helper; + + if(si.screenNum >= [[UIScreen screens] count]){return nil;} + + UIScreen* screen = [[UIScreen screens] objectAtIndex:si.screenNum]; + return screen; +} + +// +//Returns the contents scale factor of the screen, this is the scale factor required +//to convert points to pixels on this screen +// +bool IOSWindowingSystemInterface::getScreenContentScaleFactor(const osg::GraphicsContext::ScreenIdentifier& si, float& scaleFactor) +{ + AutoReleasePoolHelper auto_release_pool_helper; + + if(si.screenNum >= [[UIScreen screens] count]){return false;} + + UIScreen* screen = this->getUIScreen(si); + if(screen != nil) + { + scaleFactor = 1.0f; +#ifdef __IPHONE_4_0 && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) + CGFloat scale = [screen scale]; + scaleFactor = scale; +#endif + return true; + } + return false; +} + +// +//Returns the screens size in points, docs state a point is roughly 1/160th of an inch +// +bool IOSWindowingSystemInterface::getScreenSizeInPoints(const osg::GraphicsContext::ScreenIdentifier& si, osg::Vec2& pointSize) +{ + AutoReleasePoolHelper auto_release_pool_helper; + + if(si.screenNum >= [[UIScreen screens] count]){return false;} + + UIScreen* screen = this->getUIScreen(si); + if(screen != nil) + { + CGRect bounds = [screen bounds]; + pointSize.x() = bounds.size.width; + pointSize.y() = bounds.size.height; + return true; + } + return false; +} + +}