Android开发学习教程Android3D游戏教程第五部份.docx
- 文档编号:9364011
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:22
- 大小:161.57KB
Android开发学习教程Android3D游戏教程第五部份.docx
《Android开发学习教程Android3D游戏教程第五部份.docx》由会员分享,可在线阅读,更多相关《Android开发学习教程Android3D游戏教程第五部份.docx(22页珍藏版)》请在冰豆网上搜索。
Android开发学习教程Android3D游戏教程第五部份
程序更新与Android2.0.1兼容。
若是你是第一次接触那个系列文章,请先阅读。
那个系列的第五部份将讲述如何创建一个3D的物体。
本实例中是一个具有四个面的三角锥。
为了使咱们尔后的开发更简单,需要做一些预备。
咱们需要能够动态地计算缓冲区大小和创建数组。
privateint_nrOfVertices=0;
privatevoidinitTriangle(){
float[]coords={
//坐标
};
_nrOfVertices=coords.length;
float[]colors={
//颜色
};
short[]indices=newshort[]{
//索引
};
//floathas4bytes,coordinate*4bytes
ByteBuffervbb=ByteBuffer.allocateDirect(coords.length*4);
vbb.order(ByteOrder.nativeOrder());
_vertexBuffer=vbb.asFloatBuffer();
//shorthas2bytes,indices*2bytes
ByteBufferibb=ByteBuffer.allocateDirect(indices.length*2);
ibb.order(ByteOrder.nativeOrder());
_indexBuffer=ibb.asShortBuffer();
//floathas4bytes,colors(RGBA)*4bytes
ByteBuffercbb=ByteBuffer.allocateDirect(colors.length*4);
cbb.order(ByteOrder.nativeOrder());
_colorBuffer=cbb.asFloatBuffer();
_vertexBuffer.put(coords);
_indexBuffer.put(indices);
_colorBuffer.put(colors);
_vertexBuffer.position(0);
_indexBuffer.position(0);
_colorBuffer.position(0);
}
为了更动态一些,咱们需要改变一些变量:
在第一行能够看到咱们给_nrOfVertices的初值为0因为它的值取决于第七行坐标数组的大小。
另外咱们将成员变量_indiceArray改成局部变量,该局部变量叫做indices,在第十三行初始化。
缓冲区的创建移到了坐标数组,颜色数组和索引数组下面,因为缓冲区的大小依托于这些数组的大小。
请阅读相关的第17~18行,第22~23行,第27~28行,在注释中我说明清楚了其中的数学表示含义。
如此修改的益处是,咱们能够创建更多的极点而没必要手动来修改关于极点数量,数组缓和冲区大小等值。
下一步,你必需明白得OpenGL是如何绘制咱们所看到的图形的。
OpenGLES相较OpenGL的一个缺点确实是它只支持三角形。
因此为了创建多边形咱们必需由三角形来搭建。
下面我将引用来自的一篇博客,同时也要推荐他的相关文章。
有一些关于绘制三角形的情形咱们必需了解。
在OpenGL中,有一个围绕(winding)的概念,即点被绘制的顺序是重要的。
不像真实世界中的物体,OpenGL中的多边形没有两个面。
他们只有一个面,即前面,若是一个三角形能够被看到的话,那么它的前面应该面对着观看者。
尽管使得OpenGL能够将多边形看做是双面的是可能的,可是默许情形下,三角形只有一个能够被观看到的面。
通过了解多边形的哪一面是能够被观看到的,OpenGL就能够够只做一半的计算量就将多边形绘制出来。
尽管许多情形下多边形是独立的,你可能希望能够绘制它的反面。
通常情形下三角形是一个物体的一部份,三角形的一面将面对这物体的内部而且这一面可不能被观看到。
那个不需要绘制的面就能够够称之为反面,OpenGL通过绘制那个图形的点的顺序来判定哪一面是前面哪一面是反面。
若是绘制图形的点的顺序是逆时针的,那么那个面确实是朝外的面(能够修改)。
既然OpenGL能够容易的决定哪个三角形是能够被观看到的,它能够利用一个叫做BackfaceCulling的进程来幸免绘制并非需要在视窗中被观看到的多边形。
下一个文章我会讨论视窗,固然你能够以为它是一个虚拟的窗口来帮忙你观看OpenGL的世界。
在上面的演示中,左侧的蓝绿色的三角形确实是一个反面因为它的极点的绘制顺序关于观看者来讲是顺时针的。
而右边的三角形确实是一个前面因为关于观看者来讲它的极点绘制顺序是逆时针的。
此刻咱们想要创建一个多彩的三角锥,第一需要使依托咱们触摸事件的glClearColor()函数再也不工作。
因此咱们需要移除变量_red,_green,_blue和setColor()函数。
咱们也要改变转动的方向,因此咱们把旋转分解到x,y两个轴上。
publicclassVortexRendererimplementsGLSurfaceView.Renderer{
privatestaticfinalStringLOG_TAG=VortexRenderer.class.getSimpleName();
//一个缓冲区来保留画图极点的索引值
privateShortBuffer_indexBuffer;
//一个缓冲区来保留极点坐标
privateFloatBuffer_vertexBuffer;
//一个缓冲区来存储颜色
privateFloatBuffer_colorBuffer;
privateint_nrOfVertices=0;
privatefloat_xAngle;
privatefloat_yAngle;
@Override
publicvoidonSurfaceCreated(GL10gl,EGLConfigconfig){
//codesnipped
}
@Override
publicvoidonSurfaceChanged(GL10gl,intw,inth){
gl.glViewport(0,0,w,h);
}
publicvoidsetXAngle(floatangle){
_xAngle=angle;
}
publicfloatgetXAngle(){
return_xAngle;
}
publicvoidsetYAngle(floatangle){
_yAngle=angle;
}
publicfloatgetYAngle(){
return_yAngle;
}
//codesnipped
确保你的工程中有与我在类的开始概念的相同名称的变量。
那个地址有两个float型变量来记录角度,xAngle,和_yAngle和它们相应的设置函数和获取函数。
//codesnipped
privatefloat_x=0;
privatefloat_y=0;
//codesnipped
publicbooleanonTouchEvent(finalMotionEventevent){
if(event.getAction()==MotionEvent.ACTION_DOWN){
_x=event.getX();
_y=event.getY();
}
if(event.getAction()==MotionEvent.ACTION_MOVE){
finalfloatxdiff=(_x-event.getX());
finalfloatydiff=(_y-event.getY());
queueEvent(newRunnable(){
publicvoidrun(){
_renderer.setXAngle(_renderer.getXAngle()+ydiff);
_renderer.setYAngle(_renderer.getYAngle()+xdiff);
}
});
_x=event.getX();
_y=event.getY();
}
returntrue;
}
在第3~4行咱们用两个变量来存储坐标x,y的值。
当ACTION_DOWN事件发生时咱们会设置它们的值,因此一旦咱们在屏幕上移动手指,当前坐标与之前坐标的差值会计算出来。
以后把那个差值添加到咱们对象的角度变量中。
第18~19行,你能够想象到,若是咱们打算在x方向移动手指时物体会转动,那么它应该是围绕y轴进行旋转。
在y方向移动手指,那么它应该是围绕x轴进行旋转。
若是咱们将手指移动到最左侧或最上边,xdiff或ydiff的值会是负值因此旋转会是逆向的。
到此为止咱们已经能够轻松是想2个坐标轴的旋转了。
下面是最有趣的部份:
三角锥。
正如咱们上面引用的那一部份所提到的一样,围绕(winding)需要一些设置。
一些可能是默许的,可是咱们仍然对它们进行设置以保证每一个方面都按咱们假想的进行。
@Override
publicvoidonSurfaceCreated(GL10gl,EGLConfigconfig){
//preparation
//保证多边形只有一面能够被观看到
gl.glEnable(GL10.GL_CULL_FACE);
//决定能够被观看到的那一面的极点的绘制顺序(逆时针)
gl.glFrontFace(GL10.GL_CCW);
//哪一面不用被观看到
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
initTriangle();
}
在第5行咱们使能cullingface以便老是显示一个面。
在第7行咱们概念前面(front)的画图极点顺序。
设置为GL_CCW就意味着逆时针顺序。
在第9行,咱们概念哪一面为cullface,即不能够被观看到。
咱们设置为GL10.GL_BACK,如此前面就能够够显示出来。
可能有些混乱,若是你尝试用GL_FRONT_AND_BACK就能够够看到什么都可不能显示出来。
@Override
publicvoidonDrawFrame(GL10gl){
//概念背景颜色
gl.glClearColor(0f,0f,0f,1.0f);
//重置矩阵
gl.glLoadIdentity();
//清除颜色缓冲区
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
//设置旋转
gl.glRotatef(_xAngle,1f,0f,0f);
gl.glRotatef(_yAngle,0f,1f,0f);
//gl.glColor4f(0.5f,0f,0f,0.5f);
gl.glVertexPointer(3,GL10.GL_FLOAT,0,_vertexBuffer);
gl.glColorPointer(4,GL10.GL_FLOAT,0,_colorBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES,_nrOfVertices,GL10.GL_UNSIGNED_SHORT,_indexBuffer);
}
在第4行你能够看到咱们的背景颜色是黑色的。
在第13~14行是实现旋转的部份。
剩下的部份和之前的部份类似。
最后一个需要改动确实是initTriangle()函数中的颜色数组,坐标数组和索引数组。
咱们的三角锥是如此的:
privatevoidinitTriangle(){
float[]coords={
-0.5f,-0.5f,0.5f,//0
0.5f,-0.5f,0.5f,//1
0f,-0.5f,-0.5f,//2
0f,0.5f,0f,//3
};
_nrOfVertices=coords.length;
float[]colors={
1f,0f,0f,1f,//point0red
0f,1f,0f,1f,//point1green
0f,0f,1f,1f,//point2blue
1f,1f,1f,1f,//point3white
};
short[]indices=newshort[]{
0,1,3,//rwg
0,2,1,//rbg
0,3,2,//rbw
1,2,3,//bwg
};
//codesnipped
}
在图中你能够看到,咱们的三角锥有4个拐角。
每一个拐角有它自己的坐标因此咱们需要4个极点。
那个是在2~7行概念的。
每一个极点都有它自己的颜色,在10~15行概念。
要紧的部份是咱们的索引矩阵,它概念了咱们打算绘制的三角形。
从它们的围绕方向来看,三角形0,1,3会显示出来。
编译而且运行那个程序,你能够尝试改变索引数组点的顺序或将GL_CCW更改成GL_CW来测试运行结果。
Eclipse项目源文件:
点击进入
原文链接:
原文:
Androidtutorial–PartV
UpdatedtobeAndroid2.0.1compatible.
Youarenewtothisseries?
Pleasestartwiththe.
Thefifthpartofthisserieswillshowyouhowyoucancreateyourfirstfull3dobject.Inthiscasea4sidedpyramid.
Somepreparationwillbeneededtomakeourfuturedevelopmentmucheasier.
Wehavetobemoredynamicincalculatingourbuffersandcreatingarrayswiththecorrectsize.
privateint_nrOfVertices=0;
privatevoidinitTriangle(){
float[]coords={
//coodinates
};
_nrOfVertices=coords.length;
float[]colors={
//colors
};
short[]indices=newshort[]{
//indices
};
//floathas4bytes,coordinate*4bytes
ByteBuffervbb=ByteBuffer.allocateDirect(coords.length*4);
vbb.order(ByteOrder.nativeOrder());
_vertexBuffer=vbb.asFloatBuffer();
//shorthas2bytes,indices*2bytes
ByteBufferibb=ByteBuffer.allocateDirect(indices.length*2);
ibb.order(ByteOrder.nativeOrder());
_indexBuffer=ibb.asShortBuffer();
//floathas4bytes,colors(RGBA)*4bytes
ByteBuffercbb=ByteBuffer.allocateDirect(colors.length*4);
cbb.order(ByteOrder.nativeOrder());
_colorBuffer=cbb.asFloatBuffer();
_vertexBuffer.put(coords);
_indexBuffer.put(indices);
_colorBuffer.put(colors);
_vertexBuffer.position(0);
_indexBuffer.position(0);
_colorBuffer.position(0);
}
Tobemoredynamically,wehavetochangesomevariablesandtheorderwedosomething.Letstakeacloserlook:
Online1youseeweinitializedour_nrOfVerticeswith0becausewewilldetermineitdependingonthesizeofourcoordinatesarrayonline7.
Wealsochangedtheobjectvariableknownas_indicesArraytoalocalvariablecalledindicesandinitializedonline13.
Thebuffercreationismovedbelowthearraysforcoordinates,colorsandindicesbecausethebuffersizedependsdirectlyonthearrays.Sopleasetakealookatlines17-18,22-23,27-28.InthecommentsIexplainthemath.
Themainadvantageis,thatwecancreatemoreverticeswithoutmanuallyrecalculatethenumberofvertices,sizesofarraysorbuffers.
Nextstep:
YouhavetounderstandhowOpenGLdrawsanddetermineswhatwesee.
AgreatdisadvantageofOpenGLEScomparedtoOpenGListhelackofmorethanjusttrianglesasprimitivetypes.Wedon’thavepolygons,soeveryobjectwewanttocreatehavetobemadeoftriangles.
Asthisishardertoexplainforme(asanonnativespeaker),Iwanttoquotefromablogpostofanandalsorecommendhis,too.
Thereareafewmorethingsyouneedtoknowabouttriangles,however.InOpenGL,thereisaconceptknownaswinding,whichjustmeansthattheorderinwhichtheverticesaredrawnmatters.Unlikeobjectsintherealworld,polygonsinOpenGLdonotgenerallyhavetwosidestothem.Theyhaveoneside,whichisconsideredthefrontface,andatrianglecanonlybeseenifitsfrontfaceiffacingtheviewer.WhileitispossibletoconfigureOpenGLtotreatpolygonsastwo-sided,bydefault,triangleshaveonlyonevisibleside.Byknowingwhichisthefrontorvisiblesideofthepolygon,OpenGLisabletodohalftheamountofcalculationsperpolygonthatitwouldhavetodoifbothsideswerevisible.
Althoughtherearetimeswhenapolygonwillstandonitsown,andyoumightverywellwantthebackdrawn,usuallyatriangleispartofalargerobject,andonesideofthepolygonwillbefacingtheinsideoftheobjectandwillneverbeseen.Thesidethatisn’tdrawniscalledabackface,andOpenGLdetermineswhichisthefrontfacetobedrawnandwhichisthebackfacebylookingatthedrawingorderofthevertices.Thefrontfaceistheonethatwouldbedrawnbyfollowingtheverticesincounter-clockwiseorder(bydefault,itcanbechanged).SinceOpenGLcandetermineeasilywhichtrianglesarevisib
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 开发 学习 教程 Android3D 游戏 第五 部份