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.
This commit is contained in:
Robert Osfield
2010-11-26 18:19:28 +00:00
parent d8d47199f2
commit b523cb15c1
15 changed files with 2478 additions and 54 deletions

View File

@@ -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)

View File

@@ -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.

View File

@@ -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)

View File

@@ -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)

View File

@@ -0,0 +1,32 @@
//Created by Thomas Hogarth 2009
//force the link to our desired osgPlugins
#include "osgPlugins.h"
#include <osgDB/ReadFile>
#include <osg/MatrixTransform>
#include <osg/CameraNode>
#include <osgText/Text>
#include <osgViewer/Viewer>
#import <UIKit/UIKit.h>
@interface iphoneViewerAppDelegate : NSObject <UIApplicationDelegate, UIAccelerometerDelegate> {
UIWindow* _window; //main application window
UIAccelerationValue accel[3];
osg::ref_ptr<osgViewer::Viewer> _viewer;
osg::ref_ptr<osg::MatrixTransform> _root;
}
@property (nonatomic, retain) /*IBOutlet*/ UIWindow *_window;
- (void)updateScene;
@end

View File

@@ -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 <osgGA/TrackballManipulator>
#include <osg/ShapeDrawable>
//inckude the iphone specific windowing stuff
#include <osgViewer/api/IOS/GraphicsWindowIOS>
#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<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
// Init the Windata Variable that holds the handle for the Window to display OSG in.
osg::ref_ptr<osg::Referenced> 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<osg::GraphicsContext> 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<osg::Node> 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<osg::CameraNode> _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<osgText::Text> text = new osgText::Text;
osg::ref_ptr<osg::Geode> 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

17
examples/osgviewerIPhone/main.m Executable file
View File

@@ -0,0 +1,17 @@
//
// main.m
// iphoneViewer
//
// Created by Thomas Hogarth on 10/05/2009.
// Copyright HogBox 2009. All rights reserved.
//
#import <UIKit/UIKit.h>
int main(int argc, char *argv[]) {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
UIApplicationMain(argc, argv, nil, @"iphoneViewerAppDelegate");
[pool release];
return 0;
}

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string>icon.png</string>
<key>CFBundleIdentifier</key>
<string>com.yourcompany.${PRODUCT_NAME:identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,19 @@
#pragma once
#include <osgViewer/GraphicsWindow>
#include <osgDB/Registry>
//windowing system
USE_GRAPICSWINDOW_IMPLEMENTATION(IOS)
//plugins
//USE_OSGPLUGIN(obj)
//USE_OSGPLUGIN(ive)
USE_OSGPLUGIN(osg)
USE_OSGPLUGIN(imageio)
USE_OSGPLUGIN(freetype)

View File

@@ -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 <osgViewer/GraphicsWindow>
// 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<const GraphicsWindowIOS*>(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

View File

@@ -0,0 +1,361 @@
#pragma once
#include <osg/GL>
#include <osg/Notify>
#include <osg/Image>
#include <osgDB/Registry>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <sstream> // for istream
#include <iostream> // for ios::
#import <UIKit/UIImage.h>
#import <CoreGraphics/CoreGraphics.h>
#import <Foundation/Foundation.h>
//#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<int>(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)

View File

@@ -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()

1016
src/osgViewer/GraphicsWindowIOS.mm Executable file

File diff suppressed because it is too large Load Diff

114
src/osgViewer/IOSUtils.h Executable file
View File

@@ -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 <osg/DeleteHandler>
#include <osg/GraphicsContext>
#include <osgViewer/GraphicsWindow>
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 <class WSI>
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__

288
src/osgViewer/IOSUtils.mm Executable file
View File

@@ -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 <osg/Referenced>
#include <osg/DeleteHandler>
#include <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#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;
}
}