OpenGL ES教程十二.docx
- 文档编号:11046014
- 上传时间:2023-02-24
- 格式:DOCX
- 页数:16
- 大小:176.71KB
OpenGL ES教程十二.docx
《OpenGL ES教程十二.docx》由会员分享,可在线阅读,更多相关《OpenGL ES教程十二.docx(16页珍藏版)》请在冰豆网上搜索。
OpenGLES教程十二
OpenGLES13–在3D中移动
(译者:
那个。
其实,实际上,我又跳了一章,12节,如何判断在2d世界里点中一个物体,因为我觉得我们这大部分的游戏开发者都已经使用了花生大大的代码,也比较容易的在2d世界里开发游戏了,这个章节对我们的用处不大。
所以我又偷懒了。
)
禽流感,忙碌,母亲节,和其他一些东西,这就意味着,我不在此博客一段时间。
所以,现在是时候做事情了。
3D中的移动
我的时间很紧迫,所以今天会是一个真正的快速入门。
我们将开始建立一个“真正的”3d世界,从地板开始建立一切的东西。
然而,在我开始之前,我像先介绍如何在3d中移动。
今天,我们将开始一些新的代码,围绕着地板,进行触摸及移动。
在使用触摸,我们可以转左,转右,前进及后退。
没有跑,没有抬头看,仅仅是走,因为这更加的容易。
我不要实现他们是为了没有iPod及iPhone的朋友也可以在模拟器上实现它。
在开始之前,你先下载下面的开始函数:
OpenGLES13-Starter
这里没有太多的代码,只是让我们知道我们要做什么。
虚拟的照相机
我想我跟你提过了,人们用照相机在3d世界中观察事物,虽然OpenGL中实际上不存在照相机的。
所以你在屏幕中移动的时候,你实际在移动所有的对象,运动的感觉的产生不是因为创建了一个照相机来看电影,而是因为将世界中的所有对象以(0,0,0)为相对坐标移动。
听上去好像这样的工作量非常的大,其实没有。
因为根据你的应用,会执行很多的优化工作,即使很大的世界也没有太多的工作量。
我以后会提到它。
为了工作更方便,我为本教程带来了帮手,来自于OpenGLES的大哥GLU的library中的函数:
gluLookAt()。
通常我不提及OpenGL的优点,但我想大部分的人都知道什么是GLUlibrary。
遗憾的是OpenGLES不支持这个函数库,这意味了我们少了很多有用的功能。
移植这些功能不需要移植整个library,只需要实现少许我们需要的功能。
我找到了gluLookAt()的源代码,所以这些的代码的版权不是我的。
使用gluLookAt()
这个函数是如此的简单使用,以至于你只要了解它就能使用,让我们来看看原型:
voidgluLookAt(GLfloateyex,
GLfloateyey,
GLfloateyez,
GLfloatcenterx,
GLfloatcentery,
GLfloatcenterz,
GLfloatupx,
GLfloatupy,
GLfloatupz)
我知道9个参数看起来有点令人生畏,但你可以分解。
前3个是指眼睛的位置,在这里你要找的,只是x,y,z的坐标。
这第2组3个参数是指你想看哪里,又一个x,y,z的坐标。
最后,我们看最后3个“up”的向量。
前2个坐标就是我想要的效果。
所以,眼睛的坐标就是神秘的照相机的位置,它们在你的世界坐标里。
从这里看你的世界。
那个“中心”坐标就是你面向那里。
如果中心的y坐标高于你眼睛的y坐标,那么你就朝上看,如果低于呢,你就朝下看。
所以,在我们开始的工程里,我们就已经准备号设置如何移动了。
现在我们看看绘制好的地板。
首先让我们使用下glLookAt()。
到drawView,添加下面函数:
glLoadIdentity();
gluLookAt(5.0,1.5,2.0, //Eyelocation,look“from”
-5.0,1.5,-10.0, //Targetlocation,look“to”
0.0,1.0,0.0); //Ignorefornow
单一的功能,我们从一个地方,看到另一个地方,改变参数,看看会发生什么。
3D中的运动
现在你又把握处理gluLookAt(),让我们用它来模拟在地板上行走,我们只能移动(X,Z),也就是说,不要移动y,就是高度。
所以,思路会到gluLookAt(),想想,在3d世界中移动,你需要什么信息?
你需要:
你观察的位置或者说眼
你面向的位置或者说“中心”
一旦你知道了这两项,你就要准备好用户输入,以让用户控制移动。
设置以下变量来改变眼睛及中心
GLfloateye[3];//Whereweareviewingfrom
GLfloatcenter[3];//Wherewearelookingtowards
回到initWithCoder:
在调用gluLookAt()之前,初始化下:
eye[0]=5.0;
eye[1]=1.5;
eye[2]=2.0;
center[0]=-5.0;
center[1]=1.5;
center[2]=-10.0;
到drawView:
调用gluLookAt():
gluLookAt(eye[0],eye[1],eye[2],center[0],center[1],center[2],
0.0,1.0,0.0);
为运动做的准备
在我们开始执行触摸事件并在世界中移动之前,我们需要在头文件中设置一些东西。
来到头文件,我们需要创建一个新的枚举类型。
首先,设置我们的步行速度及转身速度:
#defineWALK_SPEED0.005
#defineTURN_SPEED0.01
下一步,我们创建一个枚举,来表示我们正在做什么,如下:
typedefenum__MOVMENT_TYPE{
MTNone=0,
MTWalkForward,
MTWAlkBackward,
MTTurnLeft,
MTTurnRight
}MovementType;
所以,在我们运行app的时候,我们可以一直是站着,或者前面,或者后退,或者转左,或者转右。
最后,我们定义个变量保存但前的运动状态:
MovementTypecurrentMovement;
别忘了到initWithCoder:
函数里面去设置currentMovement的默认值:
currentMovement=MTNone;
获得触摸
好的,我们已经进行了基本的介绍,让我们开始实际的处理工作。
如果你还记得我之前的教程,你应该知道触摸状态四种,今天我们使用
touchesBegan和touchesEnded.
为了确定行动的种类,我们把屏幕分为四部分。
开始进行触摸的函数:
-(void)touchesBegan:
(NSSet*)toucheswithEvent:
(UIEvent*)event{
UITouch*t=[[touchesallObjects]objectAtIndex:
0];
CGPointtouchPos=[tlocationInView:
t.view];
//Determinethelocationonthescreen.WeareinterestediniPhone
//Screenco-ordinatesonly,nottheworldco-ordinates
// becausewearejusttryingtohandlemovement.
//
//(0,0)
// +-----------+
// | |
// | 160 |
// |-----------|160
// | | |
// | | |
// |-----------|320
// | |
// | |
// +-----------+(320,480)
//
if(touchPos.y<160){
//Wearemovingforward
currentMovement=MTWalkForward;
}elseif(touchPos.y>320){
//Wearemovingbackward
currentMovement=MTWAlkBackward;
}elseif(touchPos.x<160){
//Turnleft
currentMovement=MTTurnLeft;
}else{
//TurnRight
currentMovement=MTTurnRight;
}
}
在玩家点击屏幕的任意位置后,就会将运动状态设置为指定的状态,同时,在松手时释放这样的状态:
-(void)touchesEnded:
(NSSet*)toucheswithEvent:
(UIEvent*)event{
currentMovement=MTNone;
}
这些时方法的实现。
最后,我们需要一个来处理这些触摸事件,这一次,我们需要添加一个方法声明的接口,回到头文件,添加下面的方法:
-(void)handleTouches;
然后,切换回来,实现这个方法,就是这个方法,我们要通过计算来执行我们运动的3d世界。
3D空间的移动理论
让我们来看看第一次走路。
当用户告诉我们向前走,我们需要了解的不仅是我们朝向的位置,同时还要了解我们的目标位置。
这个朝向位置就是我们的当前位置,而看到的目标就是我们的目标位置,我们需要从当前位置向目标位置移动。
一图胜千言,下面的图片很好的说明了我们的当前位置和我们预定的目标位置。
在运动函数里面,我们知道这两点之间,x及z坐标的距离。
我们要做的就是,将当前坐标乘以”速度”获得新的x,z坐标。
像这样:
我们可以很容易的得到红色点的坐标.
我们先设计目标位置的相对坐标deltaX和deltaZ:
deltaX=1.5-1.0=0.5
deltaZ=-10-(-5.0)=-5.0
所以现在乘上我们的步行速度:
xDisplacement=deltaX*WALK_SPEED
=0.5*0.01
=0.005
zDisplacement=deltaZ*WALK_SPEED
=-5.0*0.01
=0.05
因此,那个红色的新点位置就是:
eyeC+CDisplacement
(eyex+xDisplacement,eyey,eyez+zDisplacement)
=(0.005+1.0,eyey,(-10)+0.05)
=(1.005,eyey,-9.95)
现在,这种方法不是没有缺点。
主要的问题是,如果目标与当前位置距离越远,那么“步行速度”也就越快。
现在,让我们看下转左和转右。
因为我们在模拟旋转。
实际上目标位置就是在一个圆上移动。
这里的关键在于,你要明白我说的是什么。
你可以把当前所在位置想像为圆心,目标位置是圆边。
转向就是在圆边上移动。
换句话说,这就是:
newX=eyeX+radius*cos(TURN_SPEED)*deltaX-
sin(TURN_SPEED)*deltaZ
newZ=eyeZ+radius*sin(TURN_SPEED)*deltaX+
cos(TURN_SPEED)*deltaZ
处理触摸及涉及到运动
现在,让我们把这个转化为实践。
首先,实现开始的方法和一些基本知识:
-(void)handleTouches{
if(currentMovement==MTNone){
//We'regoingnowhere,nothingtodohere
return;
}
首先,看看我们是不是在移动,如果没有操作,就什么事情也不做。
然后,无论我们是在移动还是转弯,我们都需要知道相对距离deltaX和deltaZ的值。
我找一个临时数组把我们保存起来。
GLfloatvector[3];
vector[0]=center[0]-eye[0];
vector[1]=center[1]-eye[1];
vector[2]=center[2]-eye[2];
我没有计算y的相对值,因为是没有意义的。
现在我们用一个switch来判断当前状态并进行处理
switch(currentMovement){
caseMTWalkForward:
eye[0]+=vector[0]*WALK_SPEED;
eye[2]+=vector[2]*WALK_SPEED;
center[0]+=vector[0]*WALK_SPEED;
center[2]+=vector[2]*WALK_SPEED;
break;
caseMTWAlkBackward:
eye[0]-=vector[0]*WALK_SPEED;
eye[2]-=vector[2]*WALK_SPEED;
center[0]-=vector[0]*WALK_SPEED;
center[2]-=vector[2]*WALK_SPEED;
break;
caseMTTurnLeft:
center[0]=eye[0]+cos(-TURN_SPEED)*vector[0]-
sin(-TURN_SPEED)*vector[2];
center[2]=eye[2]+sin(-TURN_SPEED)*vector[0]+
cos(-TURN_SPEED)*vector[2];
break;
caseMTTurnRight:
center[0]=eye[0]+cos(TURN_SPEED)*vector[0]-sin(TURN_SPEED)*vector[2];
center[2]=eye[2]+sin(TURN_SPEED)*vector[0]+cos(TURN_SPEED)*vector[2];
break;
}
}
这里实现的算法就是我刚才说的。
使这一切关联起来
回到drawView函数,并在gluLookAt()函数下面添加这行:
[selfhandleTouches];
Andthat’sit,we’redone!
Hit“BuildandGo”now!
Rightnow!
!
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- OpenGL ES教程十二 ES 教程 十二
![提示](https://static.bdocx.com/images/bang_tan.gif)