root/OpenSceneGraph/trunk/src/osgViewer/GraphicsWindowIOS.mm @ 13277

Revision 13277, 39.3 kB (checked in by robert, 4 hours ago)

From Mattias Helsing, "Seems I was only half right given what you asked for. CMP0017 only
says that modules that are found and ran from cmake modules dir should
prefer cmake-provided modules. find_package() and include() still look
in CMAKE_MODULE_PATH first.

After some investigating I've come up with a proposal examplified in
the attached FindGDAL.cmake script. It simply calls the cmake provided
FindGDAL.cmake if it exists and returns if it succeeds in finding GDAL
using that, otherwise continue with our local cmake code.
Pro: Wont clutter our root CMakeLists.txt
Con: If we begin to write more advanced Findxxx modules (using
COMPONENTS, REQUIRED etc.) we may have to revise this scheme.
"

  • Property svn:eol-style set to native
Line 
1
2
3#include <iostream>
4#include <osgViewer/api/IOS/GraphicsWindowIOS>
5
6#import <QuartzCore/QuartzCore.h>
7#import <UIKit/UIKit.h>
8
9#if OSG_GLES1_FEATURES
10    #import <OpenGLES/ES1/glext.h>
11#else
12    #import <OpenGLES/ES2/glext.h>
13    // in GLES2, the OES suffix if dropped from function names (from rti)
14    #define glGenFramebuffersOES glGenFramebuffers
15    #define glGenRenderbuffersOES glGenRenderbuffers
16    #define glBindFramebufferOES glBindFramebuffer
17    #define glBindRenderbufferOES glBindRenderbuffer
18    #define glFramebufferRenderbufferOES glFramebufferRenderbuffer
19    #define glGetRenderbufferParameterivOES glGetRenderbufferParameteriv
20    #define glRenderbufferStorageOES glRenderbufferStorage
21    #define glDeleteRenderbuffersOES glDeleteRenderbuffers
22    #define glDeleteFramebuffersOES glDeleteFramebuffers
23    #define glCheckFramebufferStatusOES glCheckFramebufferStatus
24
25    #define GL_FRAMEBUFFER_OES GL_FRAMEBUFFER
26    #define GL_RENDERBUFFER_OES GL_RENDERBUFFER
27    #define GL_RENDERBUFFER_WIDTH_OES GL_RENDERBUFFER_WIDTH
28    #define GL_RENDERBUFFER_HEIGHT_OES GL_RENDERBUFFER_HEIGHT
29    #define GL_COLOR_ATTACHMENT0_OES GL_COLOR_ATTACHMENT0
30    #define GL_DEPTH_ATTACHMENT_OES GL_DEPTH_ATTACHMENT
31    #define GL_DEPTH_COMPONENT16_OES GL_DEPTH_COMPONENT16
32    #define GL_STENCIL_INDEX8_OES GL_STENCIL_INDEX8
33    #define GL_FRAMEBUFFER_COMPLETE_OES GL_FRAMEBUFFER_COMPLETE
34    #define GL_STENCIL_ATTACHMENT_OES GL_STENCIL_ATTACHMENT
35
36    #define GL_RGB5_A1_OES GL_RGB5_A1
37#endif 
38
39#include "IOSUtils.h"
40
41
42
43
44#pragma mark GraphicsWindowIOSWindow
45
46// ----------------------------------------------------------------------------------------------------------
47// GraphicsWindowIOSWindow, implements canBecomeKeyWindow + canBecomeMainWindow
48// ----------------------------------------------------------------------------------------------------------
49
50@interface GraphicsWindowIOSWindow : UIWindow
51{
52}
53
54- (BOOL) canBecomeKeyWindow;
55- (BOOL) canBecomeMainWindow;
56
57@end
58
59@implementation GraphicsWindowIOSWindow
60
61//
62//Implement dealloc
63//
64- (void) dealloc
65{
66    [super dealloc];
67}
68
69- (BOOL) canBecomeKeyWindow
70{
71    return YES;
72}
73
74- (BOOL) canBecomeMainWindow
75{
76    return YES;
77}
78
79@end
80
81#pragma mark GraphicsWindowIOSGLView
82
83// ----------------------------------------------------------------------------------------------------------
84// GraphicsWindowIOSGLView
85// custom UIView-class handling creation and display of frame/render buffers plus receives touch input
86// ----------------------------------------------------------------------------------------------------------
87
88typedef std::map<void*, unsigned int> TouchPointsIdMapping;
89
90@interface GraphicsWindowIOSGLView : UIView
91{
92    @private
93        osgViewer::GraphicsWindowIOS* _win;
94        EAGLContext* _context;
95   
96        /* The pixel dimensions of the backbuffer */
97        GLint _backingWidth;
98        GLint _backingHeight;
99   
100        //the pixel buffers for the video
101        /* OpenGL names for the renderbuffer and framebuffers used to render to this view */
102        GLuint _viewRenderbuffer, _viewFramebuffer;
103       
104        /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
105        GLuint _depthRenderbuffer;
106   
107        /* OpenGL name for the stencil buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
108        GLuint _stencilBuffer;
109       
110        // for multisampled antialiased rendering
111        GLuint _msaaFramebuffer, _msaaRenderBuffer, _msaaDepthBuffer;
112       
113        TouchPointsIdMapping* _touchPointsIdMapping;
114        unsigned int _lastTouchPointId;
115
116
117   
118}
119
120- (void)setGraphicsWindow: (osgViewer::GraphicsWindowIOS*) win;
121- (osgViewer::GraphicsWindowIOS*) getGraphicsWindow;
122- (void)setOpenGLContext: (EAGLContext*) context;
123- (void)updateDimensions;
124- (BOOL)createFramebuffer;
125- (void)destroyFramebuffer;
126- (void)swapBuffers;
127- (void)bindFrameBuffer;
128
129- (BOOL)acceptsFirstResponder;
130- (BOOL)becomeFirstResponder;
131- (BOOL)resignFirstResponder;
132
133- (osgGA::GUIEventAdapter::TouchPhase) convertTouchPhase: (UITouchPhase) phase;
134- (osg::Vec2) convertPointToPixel: (osg::Vec2) point;
135- (void) dealloc;
136@end
137
138@implementation GraphicsWindowIOSGLView 
139
140- (osgGA::GUIEventAdapter::TouchPhase) convertTouchPhase: (UITouchPhase) phase 
141{
142    switch(phase) {
143   
144        case UITouchPhaseBegan:
145            return osgGA::GUIEventAdapter::TOUCH_BEGAN;
146            break;
147        case UITouchPhaseMoved:
148            return osgGA::GUIEventAdapter::TOUCH_MOVED;
149            break;
150
151        case UITouchPhaseStationary:
152            return osgGA::GUIEventAdapter::TOUCH_STATIONERY;
153            break;
154
155        case UITouchPhaseEnded:
156        case UITouchPhaseCancelled:
157            return osgGA::GUIEventAdapter::TOUCH_ENDED;
158            break;
159    }
160   
161    return osgGA::GUIEventAdapter::TOUCH_ENDED;
162
163}
164
165
166- (unsigned int)computeTouchId: (UITouch*) touch 
167{
168    unsigned int result(0);
169   
170    if (!_touchPointsIdMapping) {
171        _lastTouchPointId = 0;
172        _touchPointsIdMapping = new TouchPointsIdMapping();
173    }
174   
175    switch([touch phase])
176    {
177   
178        case UITouchPhaseBegan:
179            {
180                TouchPointsIdMapping::iterator itr = _touchPointsIdMapping->find(touch);
181                // std::cout << "new: " << touch << " num: " << _touchPointsIdMapping->size() << " found: " << (itr != _touchPointsIdMapping->end()) << std::endl;
182                 
183                if (itr == _touchPointsIdMapping->end())
184                {
185                    (*_touchPointsIdMapping)[touch] = result = _lastTouchPointId;
186                    _lastTouchPointId++;
187                    break;
188                }
189               
190            }
191            // missing "break" by intention!
192       
193        case UITouchPhaseMoved:
194        case UITouchPhaseStationary:
195            {
196                result = (*_touchPointsIdMapping)[touch];
197            }
198            break;
199       
200        case UITouchPhaseEnded:
201        case UITouchPhaseCancelled:
202            {
203                TouchPointsIdMapping::iterator itr = _touchPointsIdMapping->find(touch);
204                // std::cout<< "remove: " << touch << " num: " << _touchPointsIdMapping->size() << " found: " << (itr != _touchPointsIdMapping->end()) << std::endl;
205               
206                if (itr != _touchPointsIdMapping->end()) {
207                    result = itr->second;
208                    _touchPointsIdMapping->erase(itr);
209                }
210                if(_touchPointsIdMapping->size() == 0) {
211                    _lastTouchPointId = 0;
212                }
213                // std::cout<< "remove: " << touch << " num: " << _touchPointsIdMapping->size() << std::endl;
214            }
215            break;
216           
217        default:
218            break;
219    }
220       
221    return result;
222}
223
224
225- (osg::Vec2) convertPointToPixel: (osg::Vec2) point
226{
227    //get the views contentscale factor and multiply the point by it
228    float scale = 1.0f;
229   
230#if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0)
231    scale = self.contentScaleFactor;
232#endif
233    return osg::Vec2(point.x()*scale, point.y()*scale);
234   
235}
236
237-(void) setGraphicsWindow: (osgViewer::GraphicsWindowIOS*) win
238{
239    _win = win;
240    _touchPointsIdMapping = new TouchPointsIdMapping();
241    _lastTouchPointId = 0;
242}
243
244- (osgViewer::GraphicsWindowIOS*) getGraphicsWindow {
245    return _win;
246}
247
248-(void) setOpenGLContext: (EAGLContext*) context
249{
250    _context = context;
251}
252
253
254// You must implement this method
255+ (Class)layerClass {
256    return [CAEAGLLayer class];
257}
258
259//
260//Called when the view is created using a frame for dimensions
261//
262- (id)initWithFrame:(CGRect)frame : (osgViewer::GraphicsWindowIOS*)win{
263   
264    _win = win;
265
266    if ((self = [super initWithFrame:frame])) {
267        // Get the layer
268        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
269       
270        osgViewer::GraphicsWindowIOS::WindowData* win_data(NULL);
271        if (_win->getTraits()->inheritedWindowData.valid())
272            win_data = dynamic_cast<osgViewer::GraphicsWindowIOS::WindowData*>(_win->getTraits()->inheritedWindowData.get());
273       
274        eaglLayer.opaque = win_data ? !win_data->getCreateTransparentView() : YES;
275        bool retained_backing = win_data ? win_data->getUseRetainedBacking() : NO;
276
277        if(_win->getTraits()->alpha > 0)
278        {
279            //create layer with alpha channel RGBA8
280            eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
281                                            [NSNumber numberWithBool:retained_backing], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
282        }else{
283            //else no alpha, IOS uses RBG565
284            eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
285                                            [NSNumber numberWithBool:retained_backing], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGB565, kEAGLDrawablePropertyColorFormat, nil];
286
287        }
288    }
289    self.multipleTouchEnabled = YES;
290   
291    return self;
292}
293
294//
295//Implement dealloc to destory our frame buffer
296//
297- (void) dealloc
298{
299    OSG_INFO << "GraphicsWindowIOSGLView::dealloc" << std::endl;
300    if(_touchPointsIdMapping)
301        delete _touchPointsIdMapping;
302    _touchPointsIdMapping = NULL;
303    [super dealloc];
304}
305
306- (void)layoutSubviews {
307    [super layoutSubviews];
308    [self updateDimensions];
309}
310
311
312- (void) setFrame:(CGRect)frame
313{
314    [super setFrame:frame];
315    [self updateDimensions];
316}
317
318
319- (void) updateDimensions
320{
321    if (_win)
322    {
323        CGRect frame = self.bounds;
324        osg::Vec2 pointOrigin = osg::Vec2(frame.origin.x,frame.origin.y);
325        osg::Vec2 pointSize = osg::Vec2(frame.size.width,frame.size.height);
326        osg::Vec2 pixelOrigin = [(GraphicsWindowIOSGLView*)(self) convertPointToPixel:pointOrigin];
327        osg::Vec2 pixelSize = [(GraphicsWindowIOSGLView*)(self) convertPointToPixel:pointSize];
328       
329        OSG_INFO << "updateDimensions, resize to "
330            <<  pixelOrigin.x() << " " << pixelOrigin.y() << " " 
331            << pixelSize.x() << " " << pixelSize.y()
332            << std::endl;
333        _win->resized(pixelOrigin.x(), pixelOrigin.y(), pixelSize.x(), pixelSize.y());
334    }
335}
336
337- (BOOL)createFramebuffer {
338
339    _msaaFramebuffer = _msaaRenderBuffer = 0;
340   
341    glGenFramebuffersOES(1, &_viewFramebuffer);
342    glGenRenderbuffersOES(1, &_viewRenderbuffer);
343   
344    // set the default id for osg to switch back after using fbos.
345    _win->setDefaultFboId(_viewFramebuffer);
346   
347    glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer);
348    glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer);
349    [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
350    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _viewRenderbuffer);
351   
352    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &_backingWidth);
353    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &_backingHeight);
354   
355    osg::notify(osg::DEBUG_INFO) << "GraphicsWindowIOS::createFramebuffer INFO: Created GL RenderBuffer of size " << _backingWidth << ", " << _backingHeight << " ." << std::endl;
356
357#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
358    //on ios 5 we have to use a packed depth stencil buffer if we want stencil
359    if(_win->getTraits()->depth > 0) {
360        //add stencil if requested
361        if(_win->getTraits()->stencil > 0) {
362            // Create a packed depth stencil buffer.
363            glGenRenderbuffersOES(1, &_depthRenderbuffer);
364            glBindRenderbufferOES(GL_RENDERBUFFER_OES, _depthRenderbuffer);
365           
366            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH24_STENCIL8_OES, _backingWidth, _backingHeight);
367           
368            glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES,
369                                         GL_RENDERBUFFER_OES, _depthRenderbuffer);
370            glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES,
371                                         GL_RENDERBUFFER_OES, _depthRenderbuffer);
372        }else{
373            //normal depth buffer
374            glGenRenderbuffersOES(1, &_depthRenderbuffer);
375            glBindRenderbufferOES(GL_RENDERBUFFER_OES, _depthRenderbuffer);
376            if(_win->getTraits()->depth == 16)
377            {
378                glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, _backingWidth, _backingHeight);
379            }else if(_win->getTraits()->depth == 24){
380                glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT24_OES, _backingWidth, _backingHeight);
381            }
382
383            glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _depthRenderbuffer);
384        }
385    }
386   
387#else
388    //add depth if requested
389    if(_win->getTraits()->depth > 0) {
390        glGenRenderbuffersOES(1, &_depthRenderbuffer);
391        glBindRenderbufferOES(GL_RENDERBUFFER_OES, _depthRenderbuffer);
392        if(_win->getTraits()->depth == 16)
393        {
394            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, _backingWidth, _backingHeight);
395        }else if(_win->getTraits()->depth == 24){
396            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT24_OES, _backingWidth, _backingHeight);
397        }
398
399#if defined(GL_DEPTH_COMPONENT32_OES)
400        else if(_win->getTraits()->depth == 32){
401            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT32_OES, _backingWidth, _backingHeight);
402        }
403#endif
404
405        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _depthRenderbuffer);
406    }
407   
408    //add stencil if requested
409    if(_win->getTraits()->stencil > 0) {
410        glGenRenderbuffersOES(1, &_stencilBuffer);
411        glBindRenderbufferOES(GL_RENDERBUFFER_OES, _stencilBuffer);
412        glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_STENCIL_INDEX8_OES, _backingWidth, _backingHeight);
413        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _stencilBuffer);
414    } 
415#endif
416   
417    //MSAA only available for >= 4.0 sdk
418   
419#if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0)
420   
421    if(_win->getTraits()->sampleBuffers > 0)
422    {
423        glGenFramebuffersOES(1, &_msaaFramebuffer);
424        glGenRenderbuffersOES(1, &_msaaRenderBuffer);
425       
426        _win->setDefaultFboId(_msaaFramebuffer);
427       
428        glBindFramebufferOES(GL_FRAMEBUFFER_OES, _msaaFramebuffer);
429        glBindRenderbufferOES(GL_RENDERBUFFER_OES, _msaaRenderBuffer);
430       
431        // 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
432       
433        glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, _win->getTraits()->samples, GL_RGB5_A1_OES, _backingWidth, _backingHeight);
434       
435        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _msaaRenderBuffer);
436        glGenRenderbuffersOES(1, &_msaaDepthBuffer);
437        glBindRenderbufferOES(GL_RENDERBUFFER_OES, _msaaDepthBuffer);
438       
439        glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, _win->getTraits()->samples, ( _win->getTraits()->depth == 16) ? GL_DEPTH_COMPONENT16_OES : GL_DEPTH_COMPONENT24_OES, _backingWidth , _backingHeight);
440        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _msaaDepthBuffer);
441   
442    }
443#endif
444   
445    if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
446        OSG_FATAL << "GraphicsWindowIOS::createFramebuffer ERROR: Failed to create a GL RenderBuffer, glCheckFramebufferStatusOES returned '" 
447                  << glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) << "'." << std::endl;
448        return NO;
449    }
450   
451    return YES;
452}
453
454
455- (void)destroyFramebuffer {
456   
457    if(_viewFramebuffer)
458    {
459        glDeleteFramebuffersOES(1, &_viewFramebuffer);
460        _viewFramebuffer = 0;
461    }
462    if(_viewRenderbuffer)
463    {
464        glDeleteRenderbuffersOES(1, &_viewRenderbuffer);
465        _viewRenderbuffer = 0;
466    }
467   
468    if(_depthRenderbuffer) {
469        glDeleteRenderbuffersOES(1, &_depthRenderbuffer);
470        _depthRenderbuffer = 0;
471    }
472   
473    if(_stencilBuffer) {
474        glDeleteRenderbuffersOES(1, &_stencilBuffer);
475        _stencilBuffer = 0;
476    }
477   
478    if(_msaaRenderBuffer) {
479        glDeleteRenderbuffersOES(1, &_msaaRenderBuffer);
480        _msaaRenderBuffer = 0;
481    }
482   
483    if(_msaaDepthBuffer) {
484        glDeleteRenderbuffersOES(1, &_msaaDepthBuffer);
485        _msaaDepthBuffer = 0;
486    }
487
488    if(_msaaFramebuffer) {
489        glDeleteFramebuffersOES(1, &_msaaFramebuffer);
490        _msaaFramebuffer = 0;
491    }
492}
493
494//
495//Swap the view and render buffers
496//
497- (void)swapBuffers {
498
499
500#if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0)   
501    if(_msaaFramebuffer)
502    {
503        glBindFramebufferOES(GL_FRAMEBUFFER_OES, _msaaFramebuffer);
504       
505        glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, _msaaFramebuffer);
506        glBindFramebufferOES(GL_DRAW_FRAMEBUFFER_APPLE, _viewFramebuffer);
507       
508        glResolveMultisampleFramebufferAPPLE();
509       
510        GLenum attachments[] = {GL_DEPTH_ATTACHMENT_OES, GL_COLOR_ATTACHMENT0_OES};
511        glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 2, attachments);
512    }
513#endif
514
515
516      //swap buffers (sort of i think?)
517    glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer);
518   
519    //display render in context
520    [_context presentRenderbuffer:GL_RENDERBUFFER_OES];
521   
522    //re bind the frame buffer for next frames renders
523    glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer);
524   
525#if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0)
526    if (_msaaFramebuffer)
527        glBindFramebufferOES(GL_FRAMEBUFFER_OES, _msaaFramebuffer);;
528#endif
529}
530
531//
532//bind view buffer as current for new render pass
533//
534- (void)bindFrameBuffer {
535
536    //bind the frame buffer
537    glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer);
538   
539#if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0)
540    if (_msaaFramebuffer)
541        glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, _msaaFramebuffer);
542#endif
543}
544
545
546- (BOOL)acceptsFirstResponder
547{
548  return YES;
549}
550
551- (BOOL)becomeFirstResponder
552{
553  return YES;
554}
555
556- (BOOL)resignFirstResponder
557{
558  return YES;
559}
560
561//
562//Touch input callbacks
563//
564- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
565   
566    NSSet *allTouches = [event allTouches];
567   
568    osg::ref_ptr<osgGA::GUIEventAdapter> osg_event(NULL);
569
570    for(int i=0; i<[allTouches count]; i++)
571    {
572       
573        UITouch *touch = [[allTouches allObjects] objectAtIndex:i];
574        CGPoint pos = [touch locationInView:touch.view];
575        osg::Vec2 pixelPos = [self convertPointToPixel: osg::Vec2(pos.x,pos.y)];
576        unsigned int touch_id = [self computeTouchId: touch];
577       
578        if (!osg_event) {
579            osg_event = _win->getEventQueue()->touchBegan(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y());
580        } else {
581            osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y());
582        }
583    }
584   
585}
586
587- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
588   
589    NSSet *allTouches = [event allTouches];
590   
591    osg::ref_ptr<osgGA::GUIEventAdapter> osg_event(NULL);
592
593    for(int i=0; i<[allTouches count]; i++)
594    {
595        UITouch *touch = [[allTouches allObjects] objectAtIndex:i];
596        CGPoint pos = [touch locationInView:touch.view];
597        osg::Vec2 pixelPos = [self convertPointToPixel: osg::Vec2(pos.x,pos.y)];
598        unsigned int touch_id = [self computeTouchId: touch];
599
600        if (!osg_event) {
601            osg_event = _win->getEventQueue()->touchMoved(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y());
602        } else {
603            osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y());
604        }
605
606
607    }
608}
609
610- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
611
612{   
613    NSSet *allTouches = [event allTouches];
614   
615    osg::ref_ptr<osgGA::GUIEventAdapter> osg_event(NULL);
616   
617    for(int i=0; i<[allTouches count]; i++)
618    {
619        UITouch *touch = [[allTouches allObjects] objectAtIndex:i];
620        CGPoint pos = [touch locationInView:touch.view];
621        osg::Vec2 pixelPos = [self convertPointToPixel: osg::Vec2(pos.x,pos.y)];
622        unsigned int touch_id = [self computeTouchId: touch];
623        if (!osg_event) {
624            osg_event = _win->getEventQueue()->touchEnded(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y(), [touch tapCount]);
625        } else {
626            osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y(), [touch tapCount]);
627        }
628
629    }
630}
631
632-(void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 
633{
634    [self touchesEnded: touches withEvent:event];
635}
636
637@end
638
639
640
641@interface GraphicsWindowIOSGLViewController : UIViewController
642{
643
644}
645- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
646- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration;
647
648@end
649
650@implementation GraphicsWindowIOSGLViewController
651
652
653- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
654{
655    osgViewer::GraphicsWindowIOS* win = [(GraphicsWindowIOSGLView*)(self.view) getGraphicsWindow];
656    if(!win){return  NO;}
657   
658    osgViewer::GraphicsWindowIOS::WindowData::DeviceOrientationFlags flags = win->getDeviceOrientationFlags();
659   
660 
661    BOOL result(NO);
662   
663    switch (interfaceOrientation) {
664        case UIDeviceOrientationPortrait:
665            if(flags & osgViewer::GraphicsWindowIOS::WindowData::PORTRAIT_ORIENTATION){
666                result = YES;
667            }
668            break;
669        case UIDeviceOrientationPortraitUpsideDown:
670            if(flags & osgViewer::GraphicsWindowIOS::WindowData::PORTRAIT_UPSIDEDOWN_ORIENTATION){
671                result = YES;
672            }
673            break;
674        case UIInterfaceOrientationLandscapeLeft:
675            if(win->getTraits()->supportsResize && flags & osgViewer::GraphicsWindowIOS::WindowData::LANDSCAPE_LEFT_ORIENTATION){
676                result = YES;
677            }
678            break;
679        case UIInterfaceOrientationLandscapeRight:
680            if(win->getTraits()->supportsResize && flags & osgViewer::GraphicsWindowIOS::WindowData::LANDSCAPE_RIGHT_ORIENTATION){
681                result = YES;
682            }
683            break;
684        default:
685            break;
686    }
687    OSG_INFO << "shouldAutorotateToInterfaceOrientation for " << interfaceOrientation << ": " << ((result==YES) ? "YES" : "NO") << std::endl;
688    return result;
689}
690
691
692- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration 
693{
694    [(GraphicsWindowIOSGLView*)(self.view) updateDimensions];
695}
696
697
698
699@end
700
701
702
703using namespace osgIOS;
704namespace osgViewer {
705
706   
707   
708#pragma mark GraphicsWindowIOS
709
710
711
712// ----------------------------------------------------------------------------------------------------------
713// init
714// ----------------------------------------------------------------------------------------------------------
715
716void GraphicsWindowIOS::init()
717{
718    if (_initialized) return;
719
720    _ownsWindow = false;
721    _context = NULL;
722    _window = NULL;
723    _view = NULL;
724    _viewController = NULL;
725   
726    _updateContext = true;
727    //if -1.0 we use the screens scale factor
728    _viewContentScaleFactor = -1.0f;
729    _valid = _initialized = true;
730}
731
732
733// ----------------------------------------------------------------------------------------------------------
734// realizeImplementation, creates the window + context
735// ----------------------------------------------------------------------------------------------------------
736
737bool GraphicsWindowIOS::realizeImplementation()
738{
739    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
740   
741    BOOL bar_hidden = (_traits->windowDecoration) ? NO: YES;
742    #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
743    #if __IPHONE_OS_VERSION_MIN_REQUIRED > 30100
744        [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden withAnimation:UIStatusBarAnimationNone];
745    #else
746        [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden animated:NO];
747    #endif
748    #endif
749   
750    //Get info about the requested screen
751    IOSWindowingSystemInterface* wsi = dynamic_cast<IOSWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
752    osg::Vec2 screenSizePoints;
753    osg::Vec2 screenSizePixels;
754    float screenScaleFactor = 1.0f;
755    UIScreen* screen = nil;
756    osg::GraphicsContext::ScreenSettings screenSettings;
757    if (wsi) {
758        wsi->getScreenContentScaleFactor((*_traits), screenScaleFactor);
759        wsi->getScreenSizeInPoints((*_traits), screenSizePoints);
760        screenSizePixels = osg::Vec2(screenSettings.width, screenSettings.height);
761        wsi->getScreenSettings((*_traits), screenSettings);
762        screen = wsi->getUIScreen((*_traits));
763    }else{
764        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;
765        return false;
766    }
767   
768    _ownsWindow = true;
769   
770    // see if an existing inherited window was passed in
771    WindowData* windowData = _traits->inheritedWindowData ? dynamic_cast<WindowData*>(_traits->inheritedWindowData.get()) : NULL;
772    if (windowData)
773    {
774        if (windowData->getWindowOrParentView())
775        {
776            _ownsWindow = false;       
777            _window = windowData->getWindowOrParentView();
778        }
779       
780        _deviceOrientationFlags = windowData->_deviceOrientationFlags;
781        _viewContentScaleFactor = windowData->_viewContentScaleFactor;
782    }
783   
784    //if the user hasn't specified a viewScaleFactor we will use the screens scale factor
785    //so we get a full res buffer
786    if(_viewContentScaleFactor < 0.0f)
787    {_viewContentScaleFactor = screenScaleFactor;}
788   
789
790    OSG_DEBUG << "GraphicsWindowIOS::realizeImplementation / ownsWindow: " << _ownsWindow << std::endl;
791
792   
793    //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
794    //but we need to create our views and windows in points. By default we create a full res buffer across all devices. This
795    //means that for backward compatibility you need to set the windowData _viewContentScaleFactor to 1.0f and set the screen res to the
796    //res of the older gen device.
797    CGRect window_bounds;
798    osg::Vec2 pointsOrigin = this->pixelToPoint(osg::Vec2(_traits->x, _traits->y));
799    osg::Vec2 pointsSize = this->pixelToPoint(osg::Vec2(_traits->width, _traits->height));
800
801    window_bounds.origin.x = pointsOrigin.x();
802    window_bounds.origin.y = pointsOrigin.y();
803    window_bounds.size.width = pointsSize.x();
804    window_bounds.size.height = pointsSize.y();
805   
806   
807    //if we own the window we need to create one
808    if (_ownsWindow)
809    {
810        //create the IOS window object using the viewbounds (in points) required for our context size
811        _window = [[GraphicsWindowIOSWindow alloc] initWithFrame: window_bounds];// styleMask: style backing: NSBackingStoreBuffered defer: NO];
812       
813        if (!_window) {
814            OSG_WARN << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create GraphicsWindowIOSWindow can not display gl view" << std::endl;
815            return false;
816        }
817       
818        OSG_DEBUG << "GraphicsWindowIOS::realizeImplementation: INFO: Created UIWindow with bounds '" << window_bounds.size.width << ", " << window_bounds.size.height << "' (points)." << std::endl;
819       
820        //if the user has requested a differnet screenNum from default 0 get the UIScreen object and
821        //apply to our window (this is for IPad external screens, I don't have one, so I've no idea if it works)
822        //I'm also not sure if we should apply this to external windows also?
823        if(_traits->screenNum > 0 && screen != nil)
824        {
825            _window.screen = screen;
826        }
827    }
828           
829    //create the desired OpenGLES context type
830#if OSG_GLES1_FEATURES
831    _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
832#elif OSG_GLES2_FEATURES
833    _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
834#endif
835   
836    if (!_context || ![EAGLContext setCurrentContext:_context]) {
837       
838        #if OSG_GLES1_FEATURES
839        OSG_FATAL << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create a valid OpenGLES1 context" << std::endl;
840        #elif OSG_GLES2_FEATURES
841        OSG_FATAL << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create a valid OpenGLES2 context" << std::endl;
842        #endif
843        return false;
844    }
845
846    //create the view to display our context in our window
847    CGRect gl_view_bounds = (_ownsWindow) ? [_window frame] : window_bounds;
848    GraphicsWindowIOSGLView* theView = [[ GraphicsWindowIOSGLView alloc ] initWithFrame: gl_view_bounds : this ];
849    if(!theView)
850    {
851        OSG_FATAL << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create GraphicsWindowIOSGLView, can not create frame buffers." << std::endl;
852        return false;
853    }
854   
855    [theView setAutoresizingMask:  ( UIViewAutoresizingFlexibleWidth |  UIViewAutoresizingFlexibleHeight) ];
856   
857    //Apply our content scale factor to our view, this is what converts the views points
858    //size to our desired context size.
859#if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0)
860    theView.contentScaleFactor = _viewContentScaleFactor;
861#endif   
862    [theView setGraphicsWindow: this];
863    [theView setOpenGLContext:_context];
864    _view = theView;
865   
866    OSG_DEBUG << "GraphicsWindowIOS::realizeImplementation / view: " << theView << std::endl;
867
868    if (getDeviceOrientationFlags() != WindowData::IGNORE_ORIENTATION)
869    {
870        _viewController = [[GraphicsWindowIOSGLViewController alloc] init];
871        _viewController.view = _view;
872    }
873   
874    // Attach view to window
875    [_window addSubview: _view];
876    if ([_window isKindOfClass:[UIWindow class]])
877        _window.rootViewController = _viewController;
878    [theView release];
879   
880    //if we own the window also make it visible
881    if (_ownsWindow)
882    {
883       
884        //show window
885        [_window makeKeyAndVisible];
886    }
887
888    [pool release];
889   
890    // IOSs origin is top/left:
891    getEventQueue()->getCurrentEventState()->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS);
892   
893    _valid = _initialized = _realized = true;
894    return _valid;
895}
896
897
898
899
900// ----------------------------------------------------------------------------------------------------------
901// closeImplementation
902// ----------------------------------------------------------------------------------------------------------
903void GraphicsWindowIOS::closeImplementation()
904{
905    OSG_INFO << "close IOS window" << std::endl;
906    _valid = false;
907    _realized = false;
908   
909   
910    if (_view)
911    {
912        [_view setOpenGLContext: NULL];
913        [_context release];
914        [_view removeFromSuperview];
915        [_view setGraphicsWindow: NULL];
916    }
917   
918    if (_viewController)
919    {
920        [_viewController release];
921        _viewController = NULL;
922    }
923       
924    if (_window && _ownsWindow)
925    { 
926        [_window release];
927        //[glView release];
928    }
929
930   
931    _window = NULL;
932    _view = NULL; 
933    _context = NULL; 
934}
935
936
937// ----------------------------------------------------------------------------------------------------------
938// makeCurrentImplementation
939// ----------------------------------------------------------------------------------------------------------
940
941bool GraphicsWindowIOS:: makeCurrentImplementation()
942{
943   
944   
945    //bind the context
946    [EAGLContext setCurrentContext:_context];
947   
948    if (_updateContext)
949    {
950        [_view destroyFramebuffer];
951        [_view createFramebuffer];
952
953        _updateContext = false;
954    }
955    //i think we also want to bind the frame buffer here
956    //[_view bindFrameBuffer];
957
958    return true;
959}
960
961
962// ----------------------------------------------------------------------------------------------------------
963// releaseContextImplementation
964// ----------------------------------------------------------------------------------------------------------
965
966bool GraphicsWindowIOS::releaseContextImplementation()
967{
968    if ([EAGLContext currentContext] == _context) {
969        [EAGLContext setCurrentContext:nil];
970    }
971    return true;
972}
973
974
975// ----------------------------------------------------------------------------------------------------------
976// swapBuffersImplementation
977// ----------------------------------------------------------------------------------------------------------
978
979void GraphicsWindowIOS::swapBuffersImplementation()
980{
981    //[_context flushBuffer];
982    [_view swapBuffers];
983}
984
985
986
987// ----------------------------------------------------------------------------------------------------------
988// setWindowDecorationImplementation
989//
990// We will use this to toggle the status bar on IPhone, nearest thing to window decoration
991// ----------------------------------------------------------------------------------------------------------
992
993bool GraphicsWindowIOS::setWindowDecorationImplementation(bool flag)
994{
995    if (!_realized || !_ownsWindow) return false;
996
997    BOOL bar_hidden = (flag) ? NO: YES;
998    #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
999    #if __IPHONE_OS_VERSION_MIN_REQUIRED > 30100
1000        [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden withAnimation:UIStatusBarAnimationNone];
1001    #else
1002        [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden animated:NO];
1003    #endif
1004    #endif
1005   
1006    return true;
1007}
1008
1009
1010// ----------------------------------------------------------------------------------------------------------
1011// grabFocus
1012// ----------------------------------------------------------------------------------------------------------
1013void GraphicsWindowIOS::grabFocus()
1014{
1015    //i think make key is the equivalent of focus on iphone
1016    [_window makeKeyWindow];
1017}
1018
1019
1020// ----------------------------------------------------------------------------------------------------------
1021// grabFocusIfPointerInWindow
1022// ----------------------------------------------------------------------------------------------------------
1023void GraphicsWindowIOS::grabFocusIfPointerInWindow()
1024{
1025    OSG_INFO << "GraphicsWindowIOS :: grabFocusIfPointerInWindow not implemented yet " << std::endl;
1026}
1027
1028// ----------------------------------------------------------------------------------------------------------
1029// raiseWindow
1030// Raise the window to the top.
1031// ----------------------------------------------------------------------------------------------------------
1032void GraphicsWindowIOS::raiseWindow()
1033{
1034    [_window bringSubviewToFront:_view];
1035}
1036
1037// ----------------------------------------------------------------------------------------------------------
1038// resizedImplementation
1039// ----------------------------------------------------------------------------------------------------------
1040
1041void GraphicsWindowIOS::resizedImplementation(int x, int y, int width, int height)
1042{
1043    GraphicsContext::resizedImplementation(x, y, width, height);
1044   
1045    _updateContext = true;
1046   
1047    getEventQueue()->windowResize(x,y,width, height, getEventQueue()->getTime());
1048}
1049
1050
1051
1052
1053// ----------------------------------------------------------------------------------------------------------
1054// setWindowRectangleImplementation
1055// ----------------------------------------------------------------------------------------------------------
1056bool GraphicsWindowIOS::setWindowRectangleImplementation(int x, int y, int width, int height)
1057{
1058    OSG_INFO << "GraphicsWindowIOS :: setWindowRectangleImplementation not implemented yet " << std::endl;
1059    if (!_ownsWindow)
1060        return false;
1061           
1062    return true;
1063}
1064
1065   
1066void GraphicsWindowIOS::checkEvents()
1067{
1068   
1069   
1070}
1071
1072
1073
1074// ----------------------------------------------------------------------------------------------------------
1075// setWindowName
1076// ----------------------------------------------------------------------------------------------------------
1077
1078void GraphicsWindowIOS::setWindowName (const std::string & name)
1079{
1080    OSG_INFO << "GraphicsWindowIOS :: setWindowName not implemented yet " << std::endl;
1081}
1082
1083
1084// ----------------------------------------------------------------------------------------------------------
1085// useCursor, no cursor on IOS
1086// ----------------------------------------------------------------------------------------------------------
1087
1088void GraphicsWindowIOS::useCursor(bool cursorOn)
1089{
1090    OSG_INFO << "GraphicsWindowIOS :: useCursor not implemented yet " << std::endl;
1091}
1092
1093
1094// ----------------------------------------------------------------------------------------------------------
1095// setCursor, no cursor on IOS
1096// ----------------------------------------------------------------------------------------------------------
1097
1098void GraphicsWindowIOS::setCursor(MouseCursor mouseCursor)
1099{
1100    OSG_INFO << "GraphicsWindowIOS :: setCursor not implemented yet " << std::endl;
1101}
1102
1103
1104// ----------------------------------------------------------------------------------------------------------
1105// setVSync, no vsync on IOS
1106// ----------------------------------------------------------------------------------------------------------
1107
1108void GraphicsWindowIOS::setVSync(bool f)
1109{
1110    OSG_INFO << "GraphicsWindowIOS :: setVSync not implemented yet " << std::endl;
1111}
1112   
1113   
1114// ----------------------------------------------------------------------------------------------------------
1115// helper funcs for converting points to pixels taking into account the views contents scale factor
1116// ----------------------------------------------------------------------------------------------------------
1117
1118osg::Vec2 GraphicsWindowIOS::pointToPixel(const osg::Vec2& point)
1119{
1120    return point * _viewContentScaleFactor;
1121}
1122   
1123osg::Vec2 GraphicsWindowIOS::pixelToPoint(const osg::Vec2& pixel)
1124{
1125    float scaler = 1.0f / _viewContentScaleFactor;
1126    return pixel * scaler;
1127}
1128
1129
1130// ----------------------------------------------------------------------------------------------------------
1131// d'tor
1132// ----------------------------------------------------------------------------------------------------------
1133
1134GraphicsWindowIOS::~GraphicsWindowIOS()
1135{
1136    close();
1137}
1138
1139
1140
1141class ConcreteIOSWindowingSystemInterface : public  IOSWindowingSystemInterface {
1142public:
1143    ConcreteIOSWindowingSystemInterface()
1144    :    IOSWindowingSystemInterface()
1145    {
1146    }
1147   
1148    virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)
1149    {
1150        if (traits->pbuffer)
1151        {
1152            // pbuffers not supported on iOS
1153            return 0;
1154        }
1155        else
1156        {
1157            osg::ref_ptr<GraphicsWindowIOS> window = new GraphicsWindowIOS(traits);
1158            if (window->valid()) return window.release();
1159            else return 0;
1160        }
1161    }
1162};
1163
1164}//end namspace
1165
1166
1167RegisterWindowingSystemInterfaceProxy<osgViewer::ConcreteIOSWindowingSystemInterface> createWindowingSystemInterfaceProxy;
1168
1169
1170// declare C entry point for static compilation.
1171extern "C" void graphicswindow_IOS(void)
1172{
1173    osg::GraphicsContext::setWindowingSystemInterface(new osgViewer::ConcreteIOSWindowingSystemInterface());
1174}
Note: See TracBrowser for help on using the browser.