Android OpenGL绘制圆柱体

在之前矩形的项目中,矩形现在被放置在一个更好的角度,并且通过使用纹理,它的外观变得更加吸引人。但是,目前我们的矩形太单调了,这显然是不够的。许多应用程序通过合并简单的图形来构建更复杂的物体,我们即将学习如何进行这样的操作,本篇我们将学习如何构建立体图形,我们先从圆柱体开始。

在这里,我们还需要一个简便的方法来在场景中进行平移、旋转和移动。许多三维应用程序通过使用视图矩阵来实现这些功能;对视图矩阵所做的更改将影响整个场景,就像我们通过一个移动的相机观察事物一样。我们将添加一个视图矩阵,以使旋转和移动变得更加容易。

在本篇的开发计划中,我们将执行以下步骤:

  • 首先,我们将学习如何将三角形组织成三角形带和三角形扇,并将它们合并成一个单一的物体(圆柱体)。
  • 我们还将学习如何定义视图矩阵,并将其集成到我们的矩阵层次结构中。

完成这些后,我们不仅为我们的场景构建了一个圆柱体,而且只需一行代码就能移动整个场景。

构建圆柱体

1.如何构建圆柱体

要创建一个圆柱体,我们需要对圆柱体进行拆分,圆柱体可以被拆分为一个圆形的顶部和一个圆筒形的侧面。顶部的圆形我们可以通过三角形扇来实现,而在OpenGL中为了构建圆柱的侧面,我们可以使用三角形带(Triangle Strip)的概念。三角形带允许我们通过定义一系列的顶点来构建多个三角形,而无需重复定义共用的顶点。通过这种方式,我们可以高效地构建出圆柱体的侧面。

在OpenGL中,三角形扇(Triangle Fan)和三角形带是两种非常有用的技术,它们可以帮助我们以较少的顶点定义复杂的几何形状。例如,通过使用三角形扇,我们可以用六个顶点和四个三角形来构建一个矩形。三角形扇通过围绕一个中心点排列顶点来构建形状,而三角形带则像桥梁的横梁一样排列,每个新的三角形都共享前一个三角形的两个顶点。如下图所示:

正如三角形扇一样,一个三角形带的前三个顶点定义了第一个三角形。这之后的每个额外的顶点都定义了另外的一个三角形。为了使用三角形带定义这个圆柱体的侧面,我们只需要把这个带卷绕成一个管子,并确保最后两个顶点与最前面的两个顶点一致。

对Android来说,已经有很多合适的三维库了,从简单的开源封装二libgdx,再到比较高级的商业化框架,比如Unity3D。这些库能帮助你提高生产率,但只有当你对OpenGL、三维渲染,以及底层是如何把这些东西拼在一起的有了基本的理解后才能体会到;否则这些库没有任何意义,你也许感觉像使用黑箱魔法一样。举个例子,如Spring和Hibernate等框架使Java效率更高,但是如果都不知道Java是如何工作的,就开始使用它们,是不是为时尚早。

研究这些库有助于学习如何开发自己的组件。Java3D和jMonkeyEngine是Java桌面版上广泛使用的框架;因为它们的文档很容易从网上得到,它们是很好的学习起点。

2.添加几何图形类

为了制作圆柱体,我们首先需要确定所需的基本形状。可以通过一个三角形扇形作为顶部和一个三角形带作为侧面来构建。为了简化圆柱体的构建过程,我们计划创建一个名为“Geometry”的几何图形类,这个类将包含一些基本图形的定义,并且我们将使用一个名为ObjectBuilder的工具来实际构建这些形状。

接下来,我们将从创建几何物体类开始。在类内部,我们将添加必要的代码来定义和构建所需的几何形状。这个类将作为构建圆柱体的基础,使得整个过程更加系统化和高效。

class Point(var x: Float = 0f, var y: Float = 0f, var z: Float = 0f) {
    fun translateY(distance:Float):Point{
        return Point(x, y + distance, z)
    }
}

我们已经添加了一个类用来表示三维场景中的一个点,其中有一个辅助函数用于把这个点沿着y轴平移。我们也需要给圆一个定义;在 Point类后面加入如下代码:

class Circle(var center:Point,var radius:Float)

最后是给圆柱体一个定义:

class Cylinder(var center:Point,var radius:Float,var height:Float)

一个圆柱体就像一个扩展的圆,它有一个中心、一个半径和一个高度。

2.添加圆柱体构建器

我们现在可以开始写圆柱体构建器类了。创建一个名为“ObjectBuilder”的类。在类内部,以下面的代码作为开始:

class ObjectBuilder {
    private val FLOAT_PER_VERTEX = 3
    private var vertexData:FloatArray
    private var offset = 0
    
    private constructor(sizeInVertices:Int){
        vertexData = FloatArray(sizeInVertices*FLOAT_PER_VERTEX)
    }

目前为止,没有什么太复杂的。我们定义了一个常量用来表示一个顶点需要多少浮点数,一个数组用于保存这些顶点,以及一个变量用于记录数组中下一个顶点的位置。这个构造函数基于需要的顶点数量初始化了数组。

我们不久将定义一个静态方法用来生成圆柱体。这个静态方法会使用正确的大小创建一个新的ObjectBuilder实例,调用ObjectBuilder实例中的方法给vertexData添加顶点,并把生成的数据返回给调用者。

对于这个物体构建器应该怎样工作,我们给出了一些需求:

  • 调用者可以决定物体应该有多少个点。点越多,圆柱体看上去就越平滑。
  • 物体将被包含在一个浮点数组中。物体被创建后,调用者将有一个绑定到OpenGL的数组和一个绘制物体的命令。
  • 物体将以调用者指定的位置为中心,并平放在x-z平面上,换句话说,物体的顶部要指向正上方。

我们用一个计算圆柱体顶部顶点数量的方法作为开始:

    private fun sizeOfInCircleVertices(numPoints:Int):Int = 1+(numPoints+1)

一个圆柱体的顶部是一个用三角形扇构造的圆;它有一个顶点在圆心,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值