之前的博客中,我们绘制了三角形、正方形、圆形、立方体,今天我们将绘制圆锥、圆柱和球体。能够绘制这些基本的常规几何形体后,其他的常见几何形体的绘制对于我们来说就基本没问题了。

绘制圆锥

由之前的博客,我们大家也应该都知道了,OpenGL ES2.0中物体的绘制重点就是在于把这个物体表面分解成三角形,分解成功后,绘制自然就不成问题了。圆锥我们很容易就能想到把它拆解成一个圆形和一个锥面,锥面的顶点与圆形的顶点,除了锥面的中心点的坐标有了“高度”,其他的完全相同。圆形在【我的安卓进阶之旅】Opengl Es绘制多边形及圆形(附Github地址)中我们已经绘制过,那么锥面其实对于我们来说也是小case了:

ArrayList<Float> pos=new ArrayList<>();
pos.add(0.0f);
pos.add(0.0f);
pos.add(height);        //给圆心相对圆边增加高度,使之形成锥面
float angDegSpan=360f/n;
for(float i=0;i<360+angDegSpan;i+=angDegSpan){pos.add((float) (radius*Math.sin(i*Math.PI/180f)));pos.add((float)(radius*Math.cos(i*Math.PI/180f)));pos.add(0.0f);
}
float[] d=new float[pos.size()];    //所有的顶点
for (int i=0;i<d.length;i++){d[i]=pos.get(i);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

我们按照绘制圆形的方式,绘制出锥面,然后再在这个锥面的底部绘制一个圆形,这样我们就得到了一个圆锥了:

主要的代码变化

    @Overridepublic void onDrawFrame(GL10 gl) {//GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT);//告知OpenGL所要使用的ProgramGLES20.glUseProgram(mProgramId);//启用指向三角形顶点数据的句柄GLES20.glEnableVertexAttribArray(mPositionId);drawStep1();drawStep2();//禁用指向三角形的顶点数据GLES20.glDisableVertexAttribArray(mPositionId);}//绘制锥面public void  drawStep1(){//绑定三角形的坐标数据GLES20.glVertexAttribPointer(mPositionId, COORDS_PER_VERTEX,GLES20.GL_FLOAT, false,VERTEX_STRID, vertexBuffer);//绑定颜色数据GLES20.glUniform4fv(mColorId, 1,color , 0);//指定vMatrix的值GLES20.glUniformMatrix4fv(mMatrixHandler,1,false,mMVPMatrix,0);//索引法绘制正方形GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, shapePos.length/3);}//绘制底面public void  drawStep2(){//绑定三角形的坐标数据GLES20.glVertexAttribPointer(mPositionId, COORDS_PER_VERTEX,GLES20.GL_FLOAT, false,VERTEX_STRID, vertexBuffer2);//绑定颜色数据GLES20.glUniform4fv(mColorId, 1,color , 0);//指定vMatrix的值GLES20.glUniformMatrix4fv(mMatrixHandler,1,false,mMVPMatrix,0);//索引法绘制正方形GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, circlePos.length/3);}

运行程序

从图中我们可以看到,我们绘制的是同样的颜色,很难看出圆锥的立体效果。要达到立体效果,我们来修改它的着色器:

    private final String VERTEX_SHADER ="attribute vec4 vPosition;" +"uniform mat4 vMatrix;"+"varying vec4 vColor;"+"void main() {" +"  gl_Position = vMatrix*vPosition;" +"   if(vPosition.z!=0.0){\n" +"        vColor=vec4(1,1,1,1.0);\n" +"    }else{\n" +"        vColor=vec4(1,1,1,1.0);\n" +"    }"+"}";

在顶点着色器中,并没有传入颜色,而是在程序中直接判断进行赋值的,当然也有可以顶点颜色和定边颜色由外面传入。在着色器中,我们不再是简单的赋值,而是加入了流程控制。之后,我们在学习下GLSL语言。 我们看下修改后的效果

怎么样,看起来是不是更真实了?

绘制圆柱

圆柱的与圆锥类似,我们可以把圆柱拆解成上下两个圆面,加上一个圆筒。圆筒我们之前也没画过,它怎么拆解成三角形呢?我们可以如同拆圆的思路来理解圆柱,想想正三菱柱、正八菱柱、正一百菱柱……菱越多,就越圆滑与圆柱越接近了,然后再把每个菱面(矩形)拆解成两个三角形就OK了,拆解的顶点为:

ArrayList<Float> pos=new ArrayList<>();
float angDegSpan=360f/n;
for(float i=0;i<360+angDegSpan;i+=angDegSpan){pos.add((float) (radius*Math.sin(i*Math.PI/180f)));pos.add((float)(radius*Math.cos(i*Math.PI/180f)));pos.add(height);pos.add((float) (radius*Math.sin(i*Math.PI/180f)));pos.add((float)(radius*Math.cos(i*Math.PI/180f)));pos.add(0.0f);
}
float[] d=new float[pos.size()];
for (int i=0;i<d.length;i++){d[i]=pos.get(i);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

这样我们就可以绘制出一个圆筒了,只需要在顶部绘制一个圆,底部绘制一个圆,就得到了一个圆柱了:

绘制球体

相对于圆锥圆柱来说,球体的拆解就复杂了许多,比较常见的拆解方法是将按照经纬度拆解和按照正多面体拆解,下图分别为正多面体示意和经纬度拆解示意:

  • 正多面体的方法拆解:
  • 经纬度的方法拆解(每一个小块看做一个矩形,再拆成三角形。PS:人懒,不想做图。):

由图我们也能看出来,多面体虽然看起来好看点,但是还是按照经纬度的方式来拆解计算容易点,毕竟规律那么明显。

球上点的坐标

无论是按照经纬度拆还是按照多面体拆,都需要知道球上面点的坐标,这算是基本的几何知识了。以球的中心为坐标中心,球的半径为R的话,那么球上点的坐标则为:

(R∗cos(ψ)∗sin(λ),R∗sin(ψ),R∗cos(ψ)∗cos(λ))(R∗cos(ψ)∗sin(λ),R∗sin(ψ),R∗cos(ψ)∗cos(λ))

其中,ψ为圆心到点的线段与xz平面的夹角,λ为圆心到点的线段在xz平面的投影与z轴的夹角。用图形表示如下:

拆解顶点

按照经纬度方式拆解球体,得到球体的顶点数组:

ArrayList<Float> data=new ArrayList<>();
float r1,r2;
float h1,h2;
float sin,cos;
for(float i=-90;i<90+step;i+=step){r1 = (float)Math.cos(i * Math.PI / 180.0);r2 = (float)Math.cos((i + step) * Math.PI / 180.0);h1 = (float)Math.sin(i * Math.PI / 180.0);h2 = (float)Math.sin((i + step) * Math.PI / 180.0);// 固定纬度, 360 度旋转遍历一条纬线float step2=step*2;for (float j = 0.0f; j <360.0f+step; j +=step2 ) {cos = (float) Math.cos(j * Math.PI / 180.0);sin = -(float) Math.sin(j * Math.PI / 180.0);data.add(r2 * cos);data.add(h2);data.add(r2 * sin);data.add(r1 * cos);data.add(h1);data.add(r1 * sin);}
}
float[] f=new float[data.size()];
for(int i=0;i<f.length;i++){f[i]=data.get(i);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

得到顶点后,剩下的工作就和之前绘制其他图形一样了。

修改着色器

如果继续使用圆锥的着色器,我们会得到这样一个球:

看起来都不太像个球了,要不是有条白线,这是不是个球就不好说了。我们需要修改下顶点着色器,让它有立体感。把顶点着色器修改为:

uniform mat4 vMatrix;
varying vec4 vColor;
attribute vec4 vPosition;void main(){gl_Position=vMatrix*vPosition;float color;if(vPosition.z>0.0){color=vPosition.z;}else{color=-vPosition.z;}vColor=vec4(color,color,color,1.0);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

运行一下,我们得到的运行结果如下,这样才好意思说是个球嘛。

源码

OK,绘制各种简单的几何物体到这里就结束了,现在应该各种常规的几何形体都拦不到我们了。后面开始讲解其他内容了。

源码

附上github下载地址

【我的安卓进阶之旅】Opengl Es(5)三维图形绘制圆锥、圆柱和球体(附Github地址)相关推荐

  1. OpenGL ES基础教程,绘制三角形(补充,附代码)

    简介 OpenGL OpenGL(全写Open Graphics Library)是指定义了一个跨编程语言.跨平台的编程接口规格的专业的图形程序接口.它用于三维图像(二维亦可),是一个功能强大,调用方 ...

  2. viewpager初始化fragment没有绘制_NDK OpenGL ES渲染系列 之 绘制三角形

    前言 新的知识学习都是循序渐进的,从基础到复杂.前面OpenGL ES概念 已经介绍了OpenGL ES的相关概念,这篇文章开始我们就正式开始OpenGL ES渲染系列第一站---绘制三角形.绘制三角 ...

  3. Android OpenGL ES 学习(二) -- 图形渲染管线和GLSL

    OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学 ...

  4. 【OpenGL ES】入门及绘制一个三角形

    本文首发于个人博客:Lam's Blog - [OpenGL ES]入门及绘制一个三角形,文章由MarkDown语法编写,可能不同平台渲染效果不一,如果有存在排版错误图片无法显示等问题,烦请移至个人博 ...

  5. android 特效相机实现,安卓特效相机(三) OpenGL ES 特效渲染

    系列文章: 特效的实现原理 接下来这篇文章我们讲下特效的具体实现原理. 由于预览画面的渲染是将Surface传给CameraDevice由它去绘制的,而且我没有找到什么可以接管或者添加渲染效果的接口, ...

  6. Android OpenGL ES(十一)绘制一个20面体 .

    前面介绍了OpenGL ES所有能够绘制的基本图形,点,线段和三角形.其它所有复杂的2D或3D图形都是由这些基本图形构成. 本例介绍如何使用三角形构造一个正20面体.一个正20面体,有12个顶点,20 ...

  7. Android OpenGL ES(十)绘制三角形Triangle .

    三角形为OpenGL ES支持的面,同样创建一个DrawTriangle Activity,定义6个顶点使用三种不同模式来绘制三角形: float vertexArray[] = {-0.8f, -0 ...

  8. Android OpenGL ES(十一):绘制一个20面体

    前面介绍了OpenGL ES所有能够绘制的基本图形,点,线段和三角形.其它所有复杂的2D或3D图形都是由这些基本图形构成. 本例介绍如何使用三角形构造一个正20面体.一个正20面体,有12个顶点,20 ...

  9. 【我的渲染技术进阶之旅】基于Filament渲染引擎绘制一个不停旋转的彩色矩形

    一.绘制三角形回顾 在上一篇博客 [我的渲染技术进阶之旅]Google开源的基于物理的实时渲染引擎Filament源码分析:Android版本的Filament第一个示例:sample-hello-t ...

最新文章

  1. drugbank下载XML文件解析
  2. hotmail在outlook2007中的设置
  3. IE下iframe跨域session和cookie失效问题的解决方案
  4. java多线程编程—高级主题_Java day20 高级编程【第一章】Java多线程编程
  5. cf #213 Matrix
  6. mysql 读取oracle_RobotFramework读取mysql和oracle数据库
  7. ListView一些特殊属性
  8. 基于python的图书管理系统设计与实现论文_基于JAVA的图书馆管理系统设计[毕业论文_].doc...
  9. IOUtils工具类的依赖maven
  10. 资深HR告诉你到底怎么写一份好的简历(非常全面)
  11. 两台计算机传输文件速度,两台电脑间如何快速传输几百个G的文件?使用这2个方法,方便极了...
  12. python 菜鸟联盟快递查询_快递单号查询接口-物流轨迹信息快递鸟api对接教程
  13. textview是否超过一行_Android TextView 判断文字内容是否超出显示省略号
  14. ar5418无线网卡驱动
  15. 尝试CornerNet-Lite进行目标识别并嵌入ROS
  16. 金秋发布会·实在里程碑,从RPA 向 IPA 进军!
  17. iOS总结-Runtime篇之用途及面试题的总结一黑魔法Method Swizzling
  18. Inventor冲压加强筋_inventor 加强筋教程
  19. java操作redis简单示例
  20. python 搭建登陆系统,用Python连接操作MySQL数据库,做一个简单的用户登录注册系统...

热门文章

  1. 企业如何制定数字采购战略?
  2. 高频交易与量化交易到底有什么区别?
  3. 磁盘显示未分配怎么办?丢失的数据这样恢复
  4. win7系统32位( 联想)台式电脑自动开机、关机图文详细解(二)
  5. Java语言实现支持视频点播的WEB服务器
  6. JavaScript 原型链常用方法
  7. c语言维吉尼亚密码实验报告,维吉尼亚密码的C语言实现.doc
  8. 2019CCPC网络赛 1002 HDU 6703(权值线段树)
  9. openfire服务器的配置
  10. jq获取id变量值(Ajax)