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

Revision 13277, 39.3 kB (checked in by robert, 11 days ago)

Moved widgets from VolumeEditorWidget? to TransferFunctionWidget?, and widget utilities into WidgetUtils?.

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