OpenGL ES2.0开发经验(一) :
为了写一个平行投影六角星,有一个MatrixState类,用于把图形进行适当的变换,然后将最终变换矩阵,顶点位置数据,顶点颜色数据传入渲染管线,最后渲染。
但运行出来后:
有异常一出现:
01-19 19:07:54.122: E/AndroidRuntime(17419): Caused by: android.util.AndroidRuntimeException: requestFeature()
must be called before adding content
原因:在主类MainActivity里面,
public class MainActivity extends Activity {
public MySurfaceView suv ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
> setContentView(R.layout.activity_main);
requestWindowFeature(Window. FEATURE_NO_TITLE); //设为全屏
getWindow().setFlags
(WindowManager.LayoutParams. FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN );
setRequestedOrientation(ActivityInfo. SCREEN_ORIENTATION_PORTRAIT);
suv = new MySurfaceView( this);
setContentView( suv);
suv.requestFocus();
suv.setFocusableInTouchMode( true);
}
…………
}
我们可以看到加标志的那一行: *
setContentView(R.layout.activity_main);
在这里,因为已经设定了ContentView,所以导致下面的:
setContentView( suv);
无法执行,所以导致闪退。
解决方法:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
> setContentView(R.layout.activity_main);
requestWindowFeature(Window. FEATURE_NO_TITLE); //设为全屏
getWindow().setFlags
把标志的这句话注释或者去掉即可。
解决以上问题后,重新运行程序,有以下画面异常:
可以看到只有背景色,无画面。
原因是因为:在MatrixState类里面:
private static float[ ] mProjMatrix = new float[16]; //4x4矩阵 投影用
private static float[ ] mVMatrix = new float[16]; //摄像机位置朝向9参数矩阵
private static float[ ] mMVPMatrix; //最后起作用的总变换矩阵
public static void setCamera(float cx, float cy, float cz, float tx, float ty, float tz,
float upx, float upy, float upz) {
// TODO 自动生成的方法存根
Matrix. setLookAtM(mVMatrix, 0, cx, cy, cz, tx, ty, tz, upx, upy, upz);
}
//设置正交投影的方法
public static void setProjectOrtho(float left, float right, float bottom, float top,
float near, float far) {
// TODO 自动生成的方法存根
Matrix. orthoM(mProjMatrix, 0, left, right, bottom, top, near, far);
}
//生成物体总变换矩阵的方法
public static float[] getFinalMatrix(float[] spec) {
// TODO 自动生成的方法存根
//创建用来存放最终变换矩阵的数组
mMVPMatrix = new float[16];
Matrix. multiplyMM(mMVPMatrix, 0, mVMatrix, 0, spec, 0); //将摄像机矩阵乘以变换矩阵
Matrix. multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
//将投影矩阵乘以上一步的结果 //得到最终变换矩阵
> return mVMatrix ;
}
这一句是错误的:return mVMatrix ;
不应该返回 mVMatrix,因为他只是存放摄像机的矩阵,应该返回的是最后起作用的总变换矩阵
mMVPMatrix;
所以,解决方法为:
return mVMatrix ; —> return mMVPMatrix;
当这个问题解决后,再次运行,有以下画面:
成了不规则图形;
经排查,原因如下,在绘制六角星的类SixPointedStar中:
public void initVertexData(float R, float r, float z) {
// TODO 自动生成的方法存根
List<Float> flist = new ArrayList<Float>();
float tempAngle = 360/6;
for( float angle = 0; angle < 360; angle+= tempAngle)
{
//第一个三角形
//第一个中心点
flist.add(0f);
flist.add(0f);
flist.add(z);
//第二个点
flist.add(( float)(R*UNIT_SIZE*Math.cos(Math.toRadians(angle))));
flist.add(( float)(R*UNIT_SIZE*Math.sin(Math.toRadians(angle))));
flist.add(z);
//第三个点
flist.add(( float) (r * UNIT_SIZE * Math.cos(Math.toRadians(angle + tempAngle/2))));
flist.add(( float) (r * UNIT_SIZE * Math.sin(Math.toRadians(angle + tempAngle/2))));
flist.add(z);
//第二个三角形
//第一个中心点
flist.add(0f);
flist.add(0f);
flist.add(z);
//第二个点
flist.add(( float) (r * UNIT_SIZE * Math.cos(Math.toRadians(angle + tempAngle/2))));
flist.add(( float) (r * UNIT_SIZE * Math.sin(Math.toRadians(angle + tempAngle/2))));
//第三个点
flist.add(( float) (R * UNIT_SIZE * Math.cos(Math.toRadians(angle + tempAngle))));
flist.add(( float) (R * UNIT_SIZE * Math.sin(Math.toRadians(angle + tempAngle))));
flist.add(z);
}
vCount = flist.size()/3;
float [ ] vertexArray = new float [flist.size()];
for( int i = 0; i< vCount; i++)
{
vertexArray[i*3] = flist.get(i*3 );
vertexArray[i*3+1] = flist.get(i*3+1 );
vertexArray[i*3+2] = flist.get(i*3+2 );
}
ByteBuffer vbb = ByteBuffer.allocateDirect(vertexArray. length * 4);
vbb.order(ByteOrder. nativeOrder()); //设置字节为本地OS顺序
mVertexBuffer = vbb.asFloatBuffer();
mVertexBuffer.put(vertexArray);
mVertexBuffer.position(0);
…………
}
看上面的第二个三角形的第二个点的代码:
//第二个点
flist.add(( float) (r * UNIT_SIZE * Math.cos(Math.toRadians(angle + tempAngle/2))));
flist.add(( float) (r * UNIT_SIZE * Math.sin(Math.toRadians(angle + tempAngle/2))));
与第二个三角形对的第三个点的代码的差别:
//第三个点
flist.add(( float) (R * UNIT_SIZE * Math.cos(Math.toRadians(angle + tempAngle))));
flist.add(( float) (R * UNIT_SIZE * Math.sin(Math.toRadians(angle + tempAngle))));
flist.add(z);
我们可以发现少了一句:
flist.add(z);
也就是说,之所以绘制出不规则图形的原因是因为第二个三角形的第二个点并没有
被添加进绘制图形的
List<Float> flist = new ArrayList<Float>();
当中,所以,
解决方法:
只要在:
//第二个点
flist.add(( float) (r * UNIT_SIZE * Math.cos(Math.toRadians(angle + tempAngle/2))));
flist.add(( float) (r * UNIT_SIZE * Math.sin(Math.toRadians(angle + tempAngle/2))));
下方添加:
flist.add(z);
即可。
重新运行,有如下画面:
至此,调试完毕。
以下是扩展:
同样的,在绘制六角星的类SixPointedStar中,我们只需要把绘制点的代码:
//第一个三角形
//第一个中心点
flist.add(0f);
flist.add(0f);
flist.add(z);
//第二个点
flist.add(( float) (R * UNIT_SIZE * Math.cos(Math.toRadians(angle))));
flist.add(( float) (R * UNIT_SIZE * Math.sin(Math.toRadians(angle))));
flist.add(z);
//第三个点
flist.add(( float) (r * UNIT_SIZE * Math.cos(Math.toRadians(angle + tempAngle/2))));
flist.add(( float) (r * UNIT_SIZE * Math.sin(Math.toRadians(angle + tempAngle/2))));
flist.add(z);
//第二个三角形
//第一个中心点
flist.add(0f);
list.add(0f);
flist.add(z);
//第二个点
flist.add(( float) (r * UNIT_SIZE * Math.cos(Math.toRadians(angle + tempAngle/2))));
flist.add(( float) (r * UNIT_SIZE * Math.sin(Math.toRadians(angle + tempAngle/2))));
flist.add(z);
//第三个点
flist.add(( float) (R * UNIT_SIZE * Math.cos(Math.toRadians(angle + tempAngle))));
flist.add(( float) (R * UNIT_SIZE * Math.sin(Math.toRadians(angle + tempAngle))));
flist.add(z);
> ***里面第二个三角形的点的代码变换一下,r—>R,R—>r,如下:***
//第二个三角形
//第一个中心点
flist.add(0f);
list.add(0f);
flist.add(z);
//第二个点
flist.add(( float) (R * UNIT_SIZE * Math.cos(Math.toRadians(angle + tempAngle/2))));
flist.add(( float) (R * UNIT_SIZE * Math.sin(Math.toRadians(angle + tempAngle/2))));
flist.add(z);
//第三个点
flist.add(( float) (r * UNIT_SIZE * Math.cos(Math.toRadians(angle + tempAngle))));
flist.add(( float) (r * UNIT_SIZE * Math.sin(Math.toRadians(angle + tempAngle))));
flist.add(z);
就可以得到以下画面:
至此,本次笔记完毕。