android OpenGL ES坐标映射

时间:2011-11-30 00:22:44

标签: android opengl-es

我做了很多搜索,没有解决我的问题。我是android和3d编程的新手。我正在开发一个Android项目,我需要使用opengl es在Android设备上绘制一个3d对象。对于每个像素,我的距离值介于200和9000之间,需要将其映射为Z坐标。对象是320x240。

问题是:

  • 如何从(x,y,z)映射到opengl es坐标系?我创建了一个顶点数组,其值为{50f,50f,400f,50f,51f,290f,...}。每个像素表示为3个浮点数(x,y,z)。
  • 如何在Android上使用opengl绘制这个顶点数组?
  • 是否可以使用OpenGl ES绘制320 * 240像素?

3 个答案:

答案 0 :(得分:1)

OpenGL在大数字方面效果不佳(比如10.0f以上,只是它的设计方式)。最好将坐标转换为介于-1和1之间(即标准化),而不是尝试使用50f或290f的openGL使用坐标。

将坐标归一化到-1和1之间的原因是因为模型坐标仅应相对于彼此而不是指示它们在特定游戏/应用中的实际尺寸。该模型可用于具有不同坐标系的许多不同游戏/应用程序,因此您希望所有模型坐标都采用标准化的标准形式,因此程序员可以按照自己的方式进行解释。

要标准化,您遍历所有坐标并找到距离0最远的值,即

float maxValueX = 0;
float maxValueY = 0;
float maxValueZ = 0;

// find the max value of x, y and z
for(int i=0;i<coordinates.length'i++){
    maxValueX = Math.max(Math.abs(coordinates[i].getX()), maxValueX);
    maxValueY = Math.max(Math.abs(coordinates[i].getY()), maxValueY);
    maxValueZ = Math.max(Math.abs(coordinates[i].getZ()), maxValueZ);
}

// convert all the coordinates to be between -1 and 1
for(int i=0;i<coordinates.length'i++){
    Vector3f coordinate = coordinates[i];
    coordinate.setX(coordinate.getX() / maxValueX);
    coordinate.setY(coordinate.getY() / maxValueY);
    coordinate.setZ(coordinate.getZ() / maxValueZ);
}    

你只需要这样做一次。假设您将数据存储在一个文件中,您可以编写一个小实用程序来执行上述操作并保存它,而不是每次将数据加载到应用程序时都这样做

答案 1 :(得分:0)

查看Android SDK附带的APIDemos中的GLSurfaceView活动。这将为您提供有关Android如何通过OpenGL ES处理渲染的基本入门知识。它位于android-sdk / samples / android-10 / ApiDemos中。确保您已在给定的API级别下载了“Samples for SDK”。

以下是一些可以帮助您入门的资源:

Android Dev Blog on GLSurfaceView

Instructions on OpenGLES

Android Development Documentation on OpenGL

希望有所帮助。

答案 2 :(得分:0)

在James提到的关于归一化为[-1,1]的内容中添加了内容。 一点代码:

假设您使用的顶点着色器类似于:,将平面数组中的数据填充为x,y,z

 "attribute vec3 coord3d;" +
    "uniform mat4 transform;" +
    "void main(void) {" +
    "  gl_Position = transform * vec4(coord3d.xyz, 1.0f);" + // size of 3 with a=1.0f for all points
    "  gl_PointSize = 10.0;"+
    "}"

获取属性:

attribute_coord3d = glGetAttribLocation(program, "coord3d");

创建VBO:

glGenBuffers(1, vbo,0);

绑定

glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);

将数据放入:

glBufferData(GL_ARRAY_BUFFER, size:SIZE_OF_ARRAY, makeFloatBuffer(FlatArray), GL_STATIC_DRAW);

其中makeFloatBuffer是创建缓冲区的函数:

  private FloatBuffer makeFloatBuffer(float[] arr) {
                ByteBuffer bb = ByteBuffer.allocateDirect(arr.length*4);
                bb.order(ByteOrder.nativeOrder());
                FloatBuffer fb = bb.asFloatBuffer();
                fb.put(arr);
                fb.position(0);
                return fb;
            }

绑定并指向缓冲区:

    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    glEnableVertexAttribArray(attribute_coord3d);
    glVertexAttribPointer(attribute_coord3d, 
    size:3,GL_FLOAT,false,stride:vertexStride, 0);

在我们的案例中,vertexStride = num_components*Float.BYTES; num_components = 3 // x,y,z.

绘制:

glDrawArrays(GL_POINTS, 0, NUM_OF_POINTS);

禁用VBO:

glDisableVertexAttribArray(attribute_coord2d);