Android OpenGL出错,IllegalArgumentException: Must use a native order direct Buffer

来源:互联网 发布:淘宝退款申请介入处理 编辑:程序博客网 时间:2024/06/06 05:28

一、问题:

在学android opengl 的时候,运行一个书上的例子,程序却报如下的错误:

06-13 04:43:13.606: E/OpenGLES(447): Application com.ayj.myopengl (SDK target 17) called a GL11 Pointer method with an indirect Buffer.

06-13 04:43:13.656: W/dalvikvm(447): threadid=9: thread exiting with uncaught exception (group=0x40015560)
06-13 04:43:13.656: E/AndroidRuntime(447): FATAL EXCEPTION: GLThread 10
06-13 04:43:13.656: E/AndroidRuntime(447): java.lang.IllegalArgumentException: Must use a native order direct Buffer
06-13 04:43:13.656: E/AndroidRuntime(447):at com.google.android.gles_jni.GLImpl.glVertexPointerBounds(Native Method)
06-13 04:43:13.656: E/AndroidRuntime(447): at com.google.android.gles_jni.GLImpl.glVertexPointer(GLImpl.java:1121)
06-13 04:43:13.656: E/AndroidRuntime(447): at com.ayj.myopengl.MainActivity$MyRenderer.onDrawFrame(MainActivity.java:163)
06-13 04:43:13.656: E/AndroidRuntime(447): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1363)

06-13 04:43:13.656: E/AndroidRuntime(447): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1118)


二、问题分析:

本人的源码如下:


public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
GLSurfaceView glView = new GLSurfaceView(this);
MyRenderer myRender = new MyRenderer();
glView.setRenderer(myRender);
setContentView(glView);

}

public class MyRenderer implements Renderer
{
// 定义三棱椎的4个顶点
float[] taperVertices = new float[] {
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, -0.2f,
0.5f, -0.5f, -0.2f, 
0.0f, -0.2f, 0.2f
};
// 定义三棱椎的4个顶点的颜色
int[] taperColors = new int[]{
65535, 0, 0, 0,  // 红色
0, 65535, 0, 0,// 绿色
0, 0, 65535, 0,  // 蓝色
65535, 65535, 0, 0 //黄色
};
// 定义三棱椎的4个三角面
private byte[] taperFacets = new byte[]{
0, 1, 2, //0、1、2三个顶点组成一个面
0, 1, 3, //0、1、3三个顶点组成一个面
1, 2, 3, //1、2、3三个顶点组成一个面
0, 2, 3  //0、2、3三个顶点组成一个面
};
// 定义立方体的8个顶点
float[] cubeVertices = new float[] {
// 上顶面正方形的四个顶点
0.5f, 0.5f, 0.5f, 
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f, 
// 下底面正方形的四个顶点
0.5f, 0.5f, -0.5f, 
0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f
};
// 定义立方体所需要的6个面(一共是12个三角形所需的顶点)
private byte[] cubeFacets = new byte[]{ 
0, 1, 2,
0, 2, 3,
2, 3, 7,
2, 6, 7, 
0, 3, 7, 
0, 4, 7,
4, 5, 6, 
4, 6, 7, 
0, 1, 4, 
1, 4, 5, 
1, 2, 6,
1, 5, 6
};

FloatBuffer taperVerticesBuffer;
IntBuffer taperColorsBuffer;
ByteBuffer taperFacetsBuffer;
FloatBuffer cubeVerticesBuffer;
ByteBuffer cubeFacetsBuffer;
// 控制旋转的角度
private float rotate;
public MyRenderer()
{
// 将三棱椎的顶点位置数据数组包装成FloatBuffer;
taperVerticesBuffer = FloatBuffer.wrap(taperVertices);
// 将三棱椎的四个面的数组包装成ByteBuffer
taperFacetsBuffer = ByteBuffer.wrap(taperFacets);
// 将三棱椎的四个定点的颜色数组包装成IntBuffer
taperColorsBuffer = IntBuffer.wrap(taperColors);
// 将立方体的顶点位置数据数组包装成FloatBuffer;
cubeVerticesBuffer = FloatBuffer.wrap(cubeVertices);
// 将立方体的6个面(12个三角形)的数组包装成ByteBuffer
cubeFacetsBuffer = ByteBuffer.wrap(cubeFacets);
}


@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
// 关闭抗抖动
gl.glDisable(GL10.GL_DITHER);
// 设置系统对透视进行修正
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glClearColor(0, 0, 0, 0);
// 设置阴影平滑模式
gl.glShadeModel(GL10.GL_SMOOTH);
// 启用深度测试
gl.glEnable(GL10.GL_DEPTH_TEST);
// 设置深度测试的类型
gl.glDepthFunc(GL10.GL_LEQUAL);
}


@Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
// 设置3D视窗的大小及位置
gl.glViewport(0, 0, width, height);
// 将当前矩阵模式设为投影矩阵
gl.glMatrixMode(GL10.GL_PROJECTION);
// 初始化单位矩阵
gl.glLoadIdentity();
// 计算透视视窗的宽度、高度比
float ratio = (float) width / height;
// 调用此方法设置透视视窗的空间大小。
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
}


// 绘制图形的方法
@Override
public void onDrawFrame(GL10 gl)
{
// 清除屏幕缓存和深度缓存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 启用顶点座标数据
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// 启用顶点颜色数据
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
// 设置当前矩阵模式为模型视图。
gl.glMatrixMode(GL10.GL_MODELVIEW);
// --------------------绘制第一个图形---------------------
// 重置当前的模型视图矩阵
gl.glLoadIdentity();
gl.glTranslatef(-0.6f, 0.0f, -1.5f);
// 沿着Y轴旋转
gl.glRotatef(rotate, 0f, 0.2f, 0f);
// 设置顶点的位置数据
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, taperVerticesBuffer);
// 设置顶点的颜色数据
gl.glColorPointer(4, GL10.GL_FIXED, 0, taperColorsBuffer);
// 按taperFacetsBuffer指定的面绘制三角形
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP
, taperFacetsBuffer.remaining(),
GL10.GL_UNSIGNED_BYTE, taperFacetsBuffer);
// --------------------绘制第二个图形---------------------
// 重置当前的模型视图矩阵
gl.glLoadIdentity();
gl.glTranslatef(0.7f, 0.0f, -2.2f);
// 沿着Y轴旋转
gl.glRotatef(rotate, 0f, 0.2f, 0f);
// 沿着X轴旋转
gl.glRotatef(rotate, 1f, 0f, 0f);
// 设置顶点的位置数据
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, cubeVerticesBuffer);
// 不设置顶点的颜色数据,还用以前的颜色数据
// 按cubeFacetsBuffer指定的面绘制三角形
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP
, cubeFacetsBuffer.remaining(),
GL10.GL_UNSIGNED_BYTE, cubeFacetsBuffer);

// 绘制结束
gl.glFinish();
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
// 旋转角度增加1
rotate+=1;
}
}
}


提示的错误at com.ayj.myopengl.MainActivity$MyRenderer.onDrawFrame(MainActivity.java:163)对应的代码是:

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, taperVerticesBuffer);

原因是taperVerticesBuffer有问题,具体理论上为啥出出这问题,我也不懂,有知道的高手请指点哈!

根据我在网上找的一些答案,给出下面的解决办法。


三、解决办法:

将MyRenderer的构造函数内容改成如下:

public MyRenderer()
{
// 将三棱椎的顶点位置数据数组包装成FloatBuffer;
//taperVerticesBuffer = FloatBuffer.wrap(taperVertices);
ByteBuffer qbb = ByteBuffer.allocateDirect(taperVertices.length * 4);
        qbb.order(ByteOrder.nativeOrder());
        taperVerticesBuffer = qbb.asFloatBuffer();
        taperVerticesBuffer.put(taperVertices);
        taperVerticesBuffer.position(0);

// 将三棱椎的四个面的数组包装成ByteBuffer
taperFacetsBuffer = ByteBuffer.wrap(taperFacets);

// 将三棱椎的四个定点的颜色数组包装成IntBuffer
//taperColorsBuffer = IntBuffer.wrap(taperColors);
ByteBuffer buf2 = ByteBuffer.allocateDirect(taperColors.length * 4);
buf2.order(ByteOrder.nativeOrder());
taperColorsBuffer = buf2.asIntBuffer();
taperColorsBuffer.put(taperColors);
taperColorsBuffer.position(0);

// 将立方体的顶点位置数据数组包装成FloatBuffer;
//cubeVerticesBuffer = FloatBuffer.wrap(cubeVertices);
ByteBuffer buf3 = ByteBuffer.allocateDirect(cubeVertices.length * 4);
buf3.order(ByteOrder.nativeOrder());
cubeVerticesBuffer = buf3.asFloatBuffer();
cubeVerticesBuffer.put(cubeVertices);
cubeVerticesBuffer.position(0);

// 将立方体的6个面(12个三角形)的数组包装成ByteBuffer
cubeFacetsBuffer = ByteBuffer.wrap(cubeFacets);
}


再次运行,一切正常!