Part I 空气曲棍球 Chapter7(7.4 Creating a New Class Structure for Our Vertex Data)

7.4 创建新类结构(Creating a New Class Structure for Our Vertex Data)

    首先我们将会建立不同的类,每个类代表一个物理实体;其中一个类代表桌面,另一个代表小球,中心线则不需要,因为在纹理图片中已经包含了。
    我们还会专门创建一个类包装实际的顶点数据并减少代码重复,最终的类结构将会如下:

    我们将会创建类Mallet管理小球顶点数据,Table类管理桌面顶点数据;每一个类都会包含一个用来存储FloatBuffer类型数组的实例VertexArray,在VertexArray中添加如下代码:

//AirHockeyTextured/src/com/airhockey/android/data/VertexArray.java
private final FloatBuffer floatBuffer;
public VertexArray(float[] vertexData) {
    floatBuffer = ByteBuffer
        .allocateDirect(vertexData.length * BYTES_PER_FLOAT)
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer()
        .put(vertexData);
}
public void setVertexAttribPointer(int dataOffset, int attributeLocation,
    int componentCount, int stride) {
    floatBuffer.position(dataOffset);
    glVertexAttribPointer(attributeLocation, componentCount, GL_FLOAT,
        false, stride, floatBuffer);
    glEnableVertexAttribArray(attributeLocation);
    floatBuffer.position(0);
}

    代码中包含一个FloatBuffer类型的变量,就像之前描述过的一样该变量将会用来存储native代码中的顶点数据,构造函数接收float类型的顶点数据然后再写入buffer中;我们同时还创建了一个用来关联着色器属性与顶点数据的方法。
    代码中还用到了一个新的成员BYTES_PER_FLOAT,在包 com.airhockey.android中创建类Constants ,并增加如下代码:

//AirHockeyTextured/src/com/airhockey/android/Constants.java
package com.airhockey.android;
public class Constants {
    public static final int BYTES_PER_FLOAT = 4;
}

    现在代码中其它地方都可以引用该常量了。

7.4.1 增加桌面顶点(Adding the Table Data)

    这里将会定义一个类来保存桌面顶点数据,同时也会增加纹理坐标对桌面进行纹理贴图。
7.4.1.1 增加类常量(Adding the Class Constants)
    新建包com.airhockey.android.objects,并在下面添加类Table,然后添加如下代码:

//AirHockeyTextured/src/com/airhockey/android/objects/Table.java
private static final int POSITION_COMPONENT_COUNT = 2;
private static final int TEXTURE_COORDINATES_COMPONENT_COUNT = 2;
private static final int STRIDE = (POSITION_COMPONENT_COUNT
+ TEXTURE_COORDINATES_COMPONENT_COUNT) * BYTES_PER_FLOAT;

    这里定义了位置通道数量、纹理通道数量、以及步长。
7.4.1.2 增加顶点数据(Adding the Vertex Data)
    下一步是定义桌面顶点坐标数据,代码如下:

private static final float[] VERTEX_DATA = {
// Order of coordinates: X, Y, S, T
// Triangle Fan
   0f,   0f, 0.5f, 0.5f,
-0.5f, -0.8f,  0f, 0.9f,
 0.5f, -0.8f,  1f, 0.9f,
 0.5f,  0.8f,  1f, 0.1f,
-0.5f,  0.8f,  0f, 0.1f,
-0.5f, -0.8f,  0f, 0.9f };

    这个数组包含了桌面顶点位置数据,我们定义了x、y位置坐标以及S、T纹理坐标,你或许注意到了T分量与y分量的方向是相反的,这样的话纹理图片就是正常映射,不过当我们使用的图片是对称的时候这并不是什么问题,但是在其它情况下则会有影响,因此我们最好留意下这种情况。

7.4.1.3 纹理裁剪(Clipping the Texture)

    这里的T坐标分别使用了0.1f和0.9f,为什么呢?我们知道绘制的桌面是1个单位宽,1.6单位高,纹理图片的分辨率是512x1024,因此如果宽度对应于1那么高度则对应于2;为了避免纹理被压扁,我们使用了范围0.1到0.9裁剪掉边缘而不是0到1,这样的话仅仅只绘制纹理的中心部分,可以参考下图方便理解:

    当然也可以保持纹理坐标为0到1,此时我们只需要预先缩放纹理图片以保证贴图到桌面后正常显示即可,如下图所示:

7.4.1.4 初始化及绘制(Initializing and Drawing the Data)

    首先创建Table构造函数,该函数将会使用VertexArray把数据拷贝到FloatBuffer里面,代码如下:

//AirHockeyTextured/src/com/airhockey/android/objects/Table.java
private final VertexArray vertexArray;
public Table() {
    vertexArray = new VertexArray(VERTEX_DATA);
}

    同时添加一个方法把顶点数据与着色器绑定,代码如下:

//AirHockeyTextured/src/com/airhockey/android/objects/Table.java
public void bindData(TextureShaderProgram textureProgram) {
vertexArray.setVertexAttribPointer(0, textureProgram.getPositionAttributeLocation(),
    POSITION_COMPONENT_COUNT, STRIDE);
vertexArray.setVertexAttribPointer(POSITION_COMPONENT_COUNT,
textureProgram.getTextureCoordinatesAttributeLocation(),TEXTURE_COORDINATES_COMPONENT_COUN,
    STRIDE);
}

    该方法针对每个从着色器中获得的属性位置调用函数setVertexAttribPointer() ,这里会把顶点数据与从着色器程序中通过函数getPositionAttributeLocation()获取的属性索引绑定,同时也会把纹理坐标与通过函数getTextureCoordinatesAttributeLocation()获取的属性索引绑定,后面在定义着色器java类的时候将会定义这些方法。
    最后添加如下代码,这样的话我们在需要绘制桌面的时候只需要调用draw()函数就可以了。

//AirHockeyTextured/src/com/airhockey/android/objects/Table.java
public void draw() {
    glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
}

7.4.2 增加小球位置数据(Adding the Mallet Data)    

    在相同包下创建类Mallet,并添加如下代码:

//AirHockeyTextured/src/com/airhockey/android/objects/Mallet.java
private static final int POSITION_COMPONENT_COUNT = 2;
private static final int COLOR_COMPONENT_COUNT = 3;
private static final int STRIDE = (POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT)* BYTES_PER_FLOAT;
private static final float[] VERTEX_DATA = {
    // Order of coordinates: X, Y, R, G, B
    0f, -0.4f, 0f, 0f, 1f,
    0f,  0.4f, 1f, 0f, 0f };
private final VertexArray vertexArray;
public Mallet() {
    vertexArray = new VertexArray(VERTEX_DATA);
}
public void bindData(ColorShaderProgram colorProgram) {
    vertexArray.setVertexAttribPointer(0, colorProgram.getPositionAttributeLocation(), 
        POSITION_COMPONENT_COUNT, STRIDE);
    vertexArray.setVertexAttribPointer(POSITION_COMPONENT_COUNT, colorProgram.getColorAttributeLocation(), 
        COLOR_COMPONENT_COUNT, STRIDE);
}
public void draw() {
    glDrawArrays(GL_POINTS, 0, 2);
}

    这部分代码采用与Table相同的模式,小球也是作为点进行绘制。
    现在我们的顶点数据已经定义好了,一个类代表桌面,一个类代表小球,第三个类用于管理顶点数据;下一步是针对 着色器定义相关类(点击进入下一章)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值