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

Revision 13429, 39.6 kB (checked in by robert, 27 minutes ago)

Added support for scaling widgets via the scoll wheel.

  • 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    // make sure the event queue has the correct window rectangle size and input range
732    getEventQueue()->syncWindowRectangleWithGraphcisContext();
733}
734
735
736// ----------------------------------------------------------------------------------------------------------
737// realizeImplementation, creates the window + context
738// ----------------------------------------------------------------------------------------------------------
739
740bool GraphicsWindowIOS::realizeImplementation()
741{
742    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
743   
744    BOOL bar_hidden = (_traits->windowDecoration) ? NO: YES;
745    #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
746    #if __IPHONE_OS_VERSION_MIN_REQUIRED > 30100
747        [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden withAnimation:UIStatusBarAnimationNone];
748    #else
749        [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden animated:NO];
750    #endif
751    #endif
752   
753    //Get info about the requested screen
754    IOSWindowingSystemInterface* wsi = dynamic_cast<IOSWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
755    osg::Vec2 screenSizePoints;
756    osg::Vec2 screenSizePixels;
757    float screenScaleFactor = 1.0f;
758    UIScreen* screen = nil;
759    osg::GraphicsContext::ScreenSettings screenSettings;
760    if (wsi) {
761        wsi->getScreenContentScaleFactor((*_traits), screenScaleFactor);
762        wsi->getScreenSizeInPoints((*_traits), screenSizePoints);
763        screenSizePixels = osg::Vec2(screenSettings.width, screenSettings.height);
764        wsi->getScreenSettings((*_traits), screenSettings);
765        screen = wsi->getUIScreen((*_traits));
766    }else{
767        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;
768        return false;
769    }
770   
771    _ownsWindow = true;
772   
773    // see if an existing inherited window was passed in
774    WindowData* windowData = _traits->inheritedWindowData ? dynamic_cast<WindowData*>(_traits->inheritedWindowData.get()) : NULL;
775    if (windowData)
776    {
777        if (windowData->getWindowOrParentView())
778        {
779            _ownsWindow = false;       
780            _window = windowData->getWindowOrParentView();
781        }
782       
783        _deviceOrientationFlags = windowData->_deviceOrientationFlags;
784        _viewContentScaleFactor = windowData->_viewContentScaleFactor;
785    }
786   
787    //if the user hasn't specified a viewScaleFactor we will use the screens scale factor
788    //so we get a full res buffer
789    if(_viewContentScaleFactor < 0.0f)
790    {_viewContentScaleFactor = screenScaleFactor;}
791   
792
793    OSG_DEBUG << "GraphicsWindowIOS::realizeImplementation / ownsWindow: " << _ownsWindow << std::endl;
794
795   
796    //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
797    //but we need to create our views and windows in points. By default we create a full res buffer across all devices. This
798    //means that for backward compatibility you need to set the windowData _viewContentScaleFactor to 1.0f and set the screen res to the
799    //res of the older gen device.
800    CGRect window_bounds;
801    osg::Vec2 pointsOrigin = this->pixelToPoint(osg::Vec2(_traits->x, _traits->y));
802    osg::Vec2 pointsSize = this->pixelToPoint(osg::Vec2(_traits->width, _traits->height));
803
804    window_bounds.origin.x = pointsOrigin.x();
805    window_bounds.origin.y = pointsOrigin.y();
806    window_bounds.size.width = pointsSize.x();
807    window_bounds.size.height = pointsSize.y();
808   
809   
810    //if we own the window we need to create one
811    if (_ownsWindow)
812    {
813        //create the IOS window object using the viewbounds (in points) required for our context size
814        _window = [[GraphicsWindowIOSWindow alloc] initWithFrame: window_bounds];// styleMask: style backing: NSBackingStoreBuffered defer: NO];
815       
816        if (!_window) {
817            OSG_WARN << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create GraphicsWindowIOSWindow can not display gl view" << std::endl;
818            return false;
819        }
820       
821        OSG_DEBUG << "GraphicsWindowIOS::realizeImplementation: INFO: Created UIWindow with bounds '" << window_bounds.size.width << ", " << window_bounds.size.height << "' (points)." << std::endl;
822       
823        //if the user has requested a differnet screenNum from default 0 get the UIScreen object and
824        //apply to our window (this is for IPad external screens, I don't have one, so I've no idea if it works)
825        //I'm also not sure if we should apply this to external windows also?
826        if(_traits->screenNum > 0 && screen != nil)
827        {
828            _window.screen = screen;
829        }
830    }
831           
832    //create the desired OpenGLES context type
833#if OSG_GLES1_FEATURES
834    _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
835#elif OSG_GLES2_FEATURES
836    _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
837#endif
838   
839    if (!_context || ![EAGLContext setCurrentContext:_context]) {
840       
841        #if OSG_GLES1_FEATURES
842        OSG_FATAL << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create a valid OpenGLES1 context" << std::endl;
843        #elif OSG_GLES2_FEATURES
844        OSG_FATAL << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create a valid OpenGLES2 context" << std::endl;
845        #endif
846        return false;
847    }
848
849    //create the view to display our context in our window
850    CGRect gl_view_bounds = (_ownsWindow) ? [_window frame] : window_bounds;
851    GraphicsWindowIOSGLView* theView = [[ GraphicsWindowIOSGLView alloc ] initWithFrame: gl_view_bounds : this ];
852    if(!theView)
853    {
854        OSG_FATAL << "GraphicsWindowIOS::realizeImplementation: ERROR: Failed to create GraphicsWindowIOSGLView, can not create frame buffers." << std::endl;
855        return false;
856    }
857   
858    [theView setAutoresizingMask:  ( UIViewAutoresizingFlexibleWidth |  UIViewAutoresizingFlexibleHeight) ];
859   
860    //Apply our content scale factor to our view, this is what converts the views points
861    //size to our desired context size.
862#if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0)
863    theView.contentScaleFactor = _viewContentScaleFactor;
864#endif   
865    [theView setGraphicsWindow: this];
866    [theView setOpenGLContext:_context];
867    _view = theView;
868   
869    OSG_DEBUG << "GraphicsWindowIOS::realizeImplementation / view: " << theView << std::endl;
870
871    if (getDeviceOrientationFlags() != WindowData::IGNORE_ORIENTATION)
872    {
873        _viewController = [[GraphicsWindowIOSGLViewController alloc] init];
874        _viewController.view = _view;
875    }
876   
877    // Attach view to window
878    [_window addSubview: _view];
879    if ([_window isKindOfClass:[UIWindow class]])
880        _window.rootViewController = _viewController;
881    [theView release];
882   
883    //if we own the window also make it visible
884    if (_ownsWindow)
885    {
886       
887        //show window
888        [_window makeKeyAndVisible];
889    }
890
891    [pool release];
892   
893    // IOSs origin is top/left:
894    getEventQueue()->getCurrentEventState()->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS);
895
896    // make sure the event queue has the correct window rectangle size and input range
897    getEventQueue()->syncWindowRectangleWithGraphcisContext();
898   
899    _valid = _initialized = _realized = true;
900    return _valid;
901}
902
903
904
905
906// ----------------------------------------------------------------------------------------------------------
907// closeImplementation
908// ----------------------------------------------------------------------------------------------------------
909void GraphicsWindowIOS::closeImplementation()
910{
911    OSG_INFO << "close IOS window" << std::endl;
912    _valid = false;
913    _realized = false;
914   
915   
916    if (_view)
917    {
918        [_view setOpenGLContext: NULL];
919        [_context release];
920        [_view removeFromSuperview];
921        [_view setGraphicsWindow: NULL];
922    }
923   
924    if (_viewController)
925    {
926        [_viewController release];
927        _viewController = NULL;
928    }
929       
930    if (_window && _ownsWindow)
931    { 
932        [_window release];
933        //[glView release];
934    }
935
936   
937    _window = NULL;
938    _view = NULL; 
939    _context = NULL; 
940}
941
942
943// ----------------------------------------------------------------------------------------------------------
944// makeCurrentImplementation
945// ----------------------------------------------------------------------------------------------------------
946
947bool GraphicsWindowIOS:: makeCurrentImplementation()
948{
949   
950   
951    //bind the context
952    [EAGLContext setCurrentContext:_context];
953   
954    if (_updateContext)
955    {
956        [_view destroyFramebuffer];
957        [_view createFramebuffer];
958
959        _updateContext = false;
960    }
961    //i think we also want to bind the frame buffer here
962    //[_view bindFrameBuffer];
963
964    return true;
965}
966
967
968// ----------------------------------------------------------------------------------------------------------
969// releaseContextImplementation
970// ----------------------------------------------------------------------------------------------------------
971
972bool GraphicsWindowIOS::releaseContextImplementation()
973{
974    if ([EAGLContext currentContext] == _context) {
975        [EAGLContext setCurrentContext:nil];
976    }
977    return true;
978}
979
980
981// ----------------------------------------------------------------------------------------------------------
982// swapBuffersImplementation
983// ----------------------------------------------------------------------------------------------------------
984
985void GraphicsWindowIOS::swapBuffersImplementation()
986{
987    //[_context flushBuffer];
988    [_view swapBuffers];
989}
990
991
992
993// ----------------------------------------------------------------------------------------------------------
994// setWindowDecorationImplementation
995//
996// We will use this to toggle the status bar on IPhone, nearest thing to window decoration
997// ----------------------------------------------------------------------------------------------------------
998
999bool GraphicsWindowIOS::setWindowDecorationImplementation(bool flag)
1000{
1001    if (!_realized || !_ownsWindow) return false;
1002
1003    BOOL bar_hidden = (flag) ? NO: YES;
1004    #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
1005    #if __IPHONE_OS_VERSION_MIN_REQUIRED > 30100
1006        [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden withAnimation:UIStatusBarAnimationNone];
1007    #else
1008        [[UIApplication sharedApplication] setStatusBarHidden: bar_hidden animated:NO];
1009    #endif
1010    #endif
1011   
1012    return true;
1013}
1014
1015
1016// ----------------------------------------------------------------------------------------------------------
1017// grabFocus
1018// ----------------------------------------------------------------------------------------------------------
1019void GraphicsWindowIOS::grabFocus()
1020{
1021    //i think make key is the equivalent of focus on iphone
1022    [_window makeKeyWindow];
1023}
1024
1025
1026// ----------------------------------------------------------------------------------------------------------
1027// grabFocusIfPointerInWindow
1028// ----------------------------------------------------------------------------------------------------------
1029void GraphicsWindowIOS::grabFocusIfPointerInWindow()
1030{
1031    OSG_INFO << "GraphicsWindowIOS :: grabFocusIfPointerInWindow not implemented yet " << std::endl;
1032}
1033
1034// ----------------------------------------------------------------------------------------------------------
1035// raiseWindow
1036// Raise the window to the top.
1037// ----------------------------------------------------------------------------------------------------------
1038void GraphicsWindowIOS::raiseWindow()
1039{
1040    [_window bringSubviewToFront:_view];
1041}
1042
1043// ----------------------------------------------------------------------------------------------------------
1044// resizedImplementation
1045// ----------------------------------------------------------------------------------------------------------
1046
1047void GraphicsWindowIOS::resizedImplementation(int x, int y, int width, int height)
1048{
1049    GraphicsContext::resizedImplementation(x, y, width, height);
1050   
1051    _updateContext = true;
1052   
1053    getEventQueue()->windowResize(x,y,width, height, getEventQueue()->getTime());
1054}
1055
1056
1057
1058
1059// ----------------------------------------------------------------------------------------------------------
1060// setWindowRectangleImplementation
1061// ----------------------------------------------------------------------------------------------------------
1062bool GraphicsWindowIOS::setWindowRectangleImplementation(int x, int y, int width, int height)
1063{
1064    OSG_INFO << "GraphicsWindowIOS :: setWindowRectangleImplementation not implemented yet " << std::endl;
1065    if (!_ownsWindow)
1066        return false;
1067           
1068    return true;
1069}
1070
1071   
1072bool GraphicsWindowIOS::checkEvents()
1073{
1074
1075    return !(getEventQueue()->empty());
1076}
1077
1078
1079
1080// ----------------------------------------------------------------------------------------------------------
1081// setWindowName
1082// ----------------------------------------------------------------------------------------------------------
1083
1084void GraphicsWindowIOS::setWindowName (const std::string & name)
1085{
1086    OSG_INFO << "GraphicsWindowIOS :: setWindowName not implemented yet " << std::endl;
1087}
1088
1089
1090// ----------------------------------------------------------------------------------------------------------
1091// useCursor, no cursor on IOS
1092// ----------------------------------------------------------------------------------------------------------
1093
1094void GraphicsWindowIOS::useCursor(bool cursorOn)
1095{
1096    OSG_INFO << "GraphicsWindowIOS :: useCursor not implemented yet " << std::endl;
1097}
1098
1099
1100// ----------------------------------------------------------------------------------------------------------
1101// setCursor, no cursor on IOS
1102// ----------------------------------------------------------------------------------------------------------
1103
1104void GraphicsWindowIOS::setCursor(MouseCursor mouseCursor)
1105{
1106    OSG_INFO << "GraphicsWindowIOS :: setCursor not implemented yet " << std::endl;
1107}
1108
1109
1110// ----------------------------------------------------------------------------------------------------------
1111// setVSync, no vsync on IOS
1112// ----------------------------------------------------------------------------------------------------------
1113
1114void GraphicsWindowIOS::setVSync(bool f)
1115{
1116    OSG_INFO << "GraphicsWindowIOS :: setVSync not implemented yet " << std::endl;
1117}
1118   
1119   
1120// ----------------------------------------------------------------------------------------------------------
1121// helper funcs for converting points to pixels taking into account the views contents scale factor
1122// ----------------------------------------------------------------------------------------------------------
1123
1124osg::Vec2 GraphicsWindowIOS::pointToPixel(const osg::Vec2& point)
1125{
1126    return point * _viewContentScaleFactor;
1127}
1128   
1129osg::Vec2 GraphicsWindowIOS::pixelToPoint(const osg::Vec2& pixel)
1130{
1131    float scaler = 1.0f / _viewContentScaleFactor;
1132    return pixel * scaler;
1133}
1134
1135
1136// ----------------------------------------------------------------------------------------------------------
1137// d'tor
1138// ----------------------------------------------------------------------------------------------------------
1139
1140GraphicsWindowIOS::~GraphicsWindowIOS()
1141{
1142    close();
1143}
1144
1145
1146
1147class ConcreteIOSWindowingSystemInterface : public  IOSWindowingSystemInterface {
1148public:
1149    ConcreteIOSWindowingSystemInterface()
1150    :    IOSWindowingSystemInterface()
1151    {
1152    }
1153   
1154    virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)
1155    {
1156        if (traits->pbuffer)
1157        {
1158            // pbuffers not supported on iOS
1159            return 0;
1160        }
1161        else
1162        {
1163            osg::ref_ptr<GraphicsWindowIOS> window = new GraphicsWindowIOS(traits);
1164            if (window->valid()) return window.release();
1165            else return 0;
1166        }
1167    }
1168};
1169
1170}//end namspace
1171
1172
1173RegisterWindowingSystemInterfaceProxy<osgViewer::ConcreteIOSWindowingSystemInterface> createWindowingSystemInterfaceProxy;
1174
1175
1176// declare C entry point for static compilation.
1177extern "C" void graphicswindow_IOS(void)
1178{
1179    osg::GraphicsContext::setWindowingSystemInterface(new osgViewer::ConcreteIOSWindowingSystemInterface());
1180}
Note: See TracBrowser for help on using the browser.