HelloArrow项目
现在看了大部分的代码和资料,还有部分细节还没有仔细实践,以及此项目中涉及Apple官方提供的库尚未仔细阅读外,还是可以从实践的角度,写哈当前对项目的设计。
{PS,如果按照书中的讲解去设计一个项目是痛苦的,书中站的角度是一步步为初学者从各方面去分析和指导,开发者的角度是从项目的本身立意出发,摒弃语法和细节【所以开发者至少对语法熟悉且对库有整体的学习】}
1、HelloArrow本意是任何时候,箭头的方向都是固定的,犹如指南针一般
这就是立意,这就是项目开发的目标
2、再次确定,HelloArrow是一个3D开发的一个样例,故新建项目的模版应该与OpenGL有关,在XCode4上,OpenGL ES Application
反过来思考,项目HelloArrow使用图形方式来展示指南针效果。
3、确定了项目的开发类型,就需要思考如何做
3.1、设计指南针引擎接口
项目中考虑6种设备物理方向的枚举
绘画引擎接口包括:
初始化
呈现
更新动画(定时刷新动画)
旋转事件函数
析构函数
另外,使用工厂模式生成一个引擎接口
从上述接口的函数名称,你可以明白此引擎接口所设计的公开函数都跟实现指南针效果有密切联系
引擎需要初始化,初始化后要呈现并定时刷新,等待一个旋转请求触发旋转事件的处理。
这一系列的过程都体现在此接口的定义
【也许,你现在还不能做到一步到位的设计,但可以尝试编写接口,不断重构和提升】
3.2、引擎的实现
引擎接口已定义了,但没有具体的实现
在这里,文中介绍两个版本,通过头文件<OpenGLES/ES1/gl.h>和<OpenGLES/ES2/gl.h>可以清晰知道各自使用的版本
对于这两个版本的区别我暂时没有阅读官方资料,无从明白彼此的差异
阅读代码,你可以知道,此文件继承接口,看下声明部分:
1 class RenderingEngine1 : public IRenderingEngine {
2 public:
3 RenderingEngine1();
4 void Initialize(int width, int height);
5 void Render() const;
6 void UpdateAnimation(float timeStep);
7 void OnRotate(DeviceOrientation newOrientation);
8 private:
9 float RotationDirection() const;
10 float m_desiredAngle;
11 float m_currentAngle;
12 GLuint m_framebuffer;
13 GLuint m_renderbuffer;
14 };
另一个类似
【这里才实现接口的功能】
【关于3.1,3.2这部分,按我过往设计来说,此部分实现的业务处理。业务层】
3.3、视图的设计
在iOS中,视图一般都继承UIView类
项目中的视图,是应用引擎,并使用OpenGL的已知来综合实现项目的目的
这里,此视图的作用:调用引擎,绑定事件和通知,通过通知来告知引擎进行相关的处理
看看头文件:
1 #import "IRenderingEngine.hpp"
2 #import <QuartzCore/QuartzCore.h>
3
4 @interface GLView : UIView {
5 @private
6 EAGLContext* m_context;
7 IRenderingEngine* m_renderingEngine;
8 float m_timestamp;
9 }
10
11 - (void) drawView: (CADisplayLink*) displayLink;
12 - (void) didRotate: (NSNotification*) notification;
13
14 @end
实现代码:
1 #import "GLView.h"
2 #import <OpenGLES/ES2/gl.h> // <-- for GL_RENDERBUFFER only
3
4 const bool ForceES1 = false;
5
6 @implementation GLView
7
8 + (Class) layerClass
9 {
10 return [CAEAGLLayer class];
11 }
12
13 - (id) initWithFrame: (CGRect) frame
14 {
15 if (self = [super initWithFrame:frame]) {
16 CAEAGLLayer* eaglLayer = (CAEAGLLayer*) super.layer;
17 eaglLayer.opaque = YES;
18
19 EAGLRenderingAPI api = kEAGLRenderingAPIOpenGLES2;
20 m_context = [[EAGLContext alloc] initWithAPI:api];
21
22 if (!m_context || ForceES1) {
23 api = kEAGLRenderingAPIOpenGLES1;
24 m_context = [[EAGLContext alloc] initWithAPI:api];
25 }
26
27 if (!m_context || ![EAGLContext setCurrentContext:m_context]) {
28 [self release];
29 return nil;
30 }
31
32 if (api == kEAGLRenderingAPIOpenGLES1) {
33 NSLog(@"Using OpenGL ES 1.1");
34 m_renderingEngine = CreateRenderer1();
35 } else {
36 NSLog(@"Using OpenGL ES 2.0");
37 m_renderingEngine = CreateRenderer2();
38 }
39
40 [m_context
41 renderbufferStorage:GL_RENDERBUFFER
42 fromDrawable: eaglLayer];
43
44 m_renderingEngine->Initialize(CGRectGetWidth(frame), CGRectGetHeight(frame));
45
46 [self drawView: nil];
47 m_timestamp = CACurrentMediaTime();
48
49 CADisplayLink* displayLink;
50 displayLink = [CADisplayLink displayLinkWithTarget:self
51 selector:@selector(drawView:)];
52
53 [displayLink addToRunLoop:[NSRunLoop currentRunLoop]
54 forMode:NSDefaultRunLoopMode];
55
56 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
57
58 [[NSNotificationCenter defaultCenter]
59 addObserver:self
60 selector:@selector(didRotate:)
61 name:UIDeviceOrientationDidChangeNotification
62 object:nil];
63 }
64 return self;
65 }
66
67 - (void) didRotate: (NSNotification*) notification
68 {
69 UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
70 m_renderingEngine->OnRotate((DeviceOrientation) orientation);
71 [self drawView: nil];
72 }
73
74 - (void) drawView: (CADisplayLink*) displayLink
75 {
76 if (displayLink != nil) {
77 float elapsedSeconds = displayLink.timestamp - m_timestamp;
78 m_timestamp = displayLink.timestamp;
79 m_renderingEngine->UpdateAnimation(elapsedSeconds);
80 }
81
82 m_renderingEngine->Render();
83 [m_context presentRenderbuffer:GL_RENDERBUFFER];
84 }
85
86 @end
从上面代码你就看到,此如何运用了引擎接口
3.4、这个是一个main的入口,实现对UIApplicationDelegate委托,当然,此处要初始化GLView了
到这里,简单画下各个部分的关系调用如下
main
HelloArrowDelegate
GLView
IRenderingEngine
RenderingEngine1 RenderingEngine2
OpenGLES Cocoa等
阅读到此,HelloArrow项目设计思路大体就是这样的,
从上图,可以看出关键在GLView\IRenderingEngine\RenderingEngine1\RenderingEngine2的设计,此部分就是业务层的主要代码
从这个角度来说,设计的中心在于业务层,其次UI层
我的设计思路一般都是从上向下思考,从下向上设计
我还得对代码中设计到的库需要仔细阅读官网资料
good luck
2011-9-1
根据努力查找网络资料,找到一些官方涉及的文档,学习了下代码中3D部分函数的调用;
现在再次整理一张图,看看主要UIView如何调用接口以及对应的实现,以RenderingEngine1为例
关于引擎部分的调用,看来全是由UIView初始化函数进行处理的,处理方式:直接调用,绑定事件间接调用
good luck
2011-9-13