第四章 矩阵变换
这一章主要讲变换,所以能物体的外观什么的就不在乎了。前面三章的演示程序里面,视角视线都是固定死的。
既然视线和视角都要运动,那么就需要一个变量因子随时间变化而变化,然后动态修改每一次渲染的时候我们的视角和视线。这一章的演示不需要法线和材质,把相关代码全部删掉(最后我们贴完整代码)
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
initOpenGLVertexs() ;
}
private FloatBuffer vertexBuffer = null ;
private int vertexCount = 0 ;
private FloatBuffer coodsBuffer = null ;
private void initOpenGLVertexs(){
int slices = 60 ;
int stacks = 30 ;
float radius = 50f ;
double perAngleW = 2 * Math.PI / slices;
double perAngleH = Math.PI / stacks;
float[] vertexArray = new float[slices*stacks*2*3*3];
int vertexIndex = 0 ;
for (int a = 0; a < stacks; a++) {
for (int b = 0; b < slices; b++) {
float x1 = (float) (radius * Math.sin(a * perAngleW) * Math.cos(b* perAngleH));
float z1 = (float) (radius * Math.sin(a * perAngleW) * Math.sin(b* perAngleH));
float y1 = (float) (radius * Math.cos(a * perAngleW));
float x2 = (float) (radius * Math.sin((a + 1) * perAngleW) * Math.cos(b * perAngleH));
float z2 = (float) (radius * Math.sin((a + 1) * perAngleW) * Math.sin(b * perAngleH));
float y2 = (float) (radius * Math.cos((a + 1) * perAngleW));
float x3 = (float) (radius * Math.sin((a + 1) * perAngleW) * Math.cos((b + 1) * perAngleH));
float z3 = (float) (radius * Math.sin((a + 1) * perAngleW) * Math.sin((b + 1) * perAngleH));
float y3 = (float) (radius * Math.cos((a + 1) * perAngleW));
float x4 = (float) (radius * Math.sin(a * perAngleW) * Math.cos((b + 1) * perAngleH));
float z4 = (float) (radius * Math.sin(a * perAngleW) * Math.sin((b + 1) * perAngleH));
float y4 = (float) (radius * Math.cos(a * perAngleW));
vertexArray[vertexIndex++] = (x1);
vertexArray[vertexIndex++] = (y1);
vertexArray[vertexIndex++] = (z1);
vertexArray[vertexIndex++] = (x2);
vertexArray[vertexIndex++] = (y2);
vertexArray[vertexIndex++] = (z2);
vertexArray[vertexIndex++] = (x3);
vertexArray[vertexIndex++] = (y3);
vertexArray[vertexIndex++] = (z3);
vertexArray[vertexIndex++] = (x3);
vertexArray[vertexIndex++] = (y3);
vertexArray[vertexIndex++] = (z3);
vertexArray[vertexIndex++] = (x4);
vertexArray[vertexIndex++] = (y4);
vertexArray[vertexIndex++] = (z4);
vertexArray[vertexIndex++] = (x1);
vertexArray[vertexIndex++] = (y1);
vertexArray[vertexIndex++] = (z1);
}
}
vertexCount = vertexArray.length / 3;
vertexBuffer = ByteBuffer.allocateDirect(vertexArray.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuffer.put(vertexArray);
vertexBuffer.position(0);
float[] coodsArray = new float[]{
-1000, 0, 0,
1000, 0, 0, /*两个点,x轴-1000到1000连成直线*/
0,-1000, 0,
0, 1000, 0, /*两个点,y轴-1000到1000连成直线*/
0, 0,-1000,
0, 0, 1000, /*两个点,z轴-1000到1000连成直线*/
};
coodsBuffer = ByteBuffer.allocateDirect(coodsArray.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
coodsBuffer.put(coodsArray);
coodsBuffer.position(0);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES10.glViewport(0, 0, width, height); // 设置视口宽度高度。
GLES10.glEnable(GLES10.GL_DEPTH_TEST); // 开启深度测试
// {修改投影矩阵
GLES10.glMatrixMode(GLES10.GL_PROJECTION); // 修改投影矩阵
GLES10.glLoadIdentity(); // 复位,将投影矩阵归零
GLU.gluPerspective(gl, 60.0f, ((float) width) / height, 0.1f, 400f);
// }
//{
GLES10.glMatrixMode(GLES10.GL_MODELVIEW);
GLES10.glLoadIdentity();//归零模型视图
GLU.gluLookAt(gl, 0, 0, 300, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
//}
}
public void onDrawFrame(GL10 gl) {
GLES10.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 清空场景为黑色。
GLES10.glClear(GLES10.GL_COLOR_BUFFER_BIT | GLES10.GL_DEPTH_BUFFER_BIT);// 清空相关缓存。
//No.1 画出坐标轴的线
GLES10.glEnableClientState(GLES10.GL_VERTEX_ARRAY);
GLES10.glDisableClientState(GLES10.GL_NORMAL_ARRAY); //由于我们画轴的时候没有法线数据输入,所以禁用法线数组功能。
GLES10.glVertexPointer(3, GLES10.GL_FLOAT, 0, coodsBuffer);
//1,画X轴
GLES10.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);//使用红色,OpenGL中颜色以浮点数表示,1.0表示红色满色
GLES10.glDrawArrays(GLES10.GL_LINE_STRIP, 0, 2); //连接两个顶点
//2,画Y轴
GLES10.glColor4f(0.0f, 1.0f, 0.0f, 1.0f);//使用绿色
GLES10.glDrawArrays(GLES10.GL_LINE_STRIP, 2, 2); //连接两个顶点
//3,画Z轴
GLES10.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);//使用绿色
GLES10.glDrawArrays(GLES10.GL_LINE_STRIP, 4, 2); //连接两个顶点
GLES10.glEnableClientState(GLES10.GL_VERTEX_ARRAY);
GLES10.glVertexPointer(3, GLES10.GL_FLOAT, 0, vertexBuffer);
//No.2 画球,给球画上颜色,黄色
GLES10.glColor4f(1.0f, 1.0f, 0.0f, 1.0f);//使用黄色
GLES10.glDrawArrays(GLES10.GL_TRIANGLES, 0, vertexCount);
GLES10.glFlush();
}
运行截图如下:
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
initOpenGLVertexs() ;
}
private FloatBuffer vertexBuffer = null ;
private int vertexCount = 0 ;
private FloatBuffer coodsBuffer = null ;
private void initOpenGLVertexs(){
int slices = 60 ;
int stacks = 30 ;
float radius = 50f ;
double perAngleW = 2 * Math.PI / slices;
double perAngleH = Math.PI / stacks;
float[] vertexArray = new float[slices*stacks*2*3*3];
int vertexIndex = 0 ;
for (int a = 0; a < stacks; a++) {
for (int b = 0; b < slices; b++) {
float x1 = (float) (radius * Math.sin(a * perAngleW) * Math.cos(b* perAngleH));
float z1 = (float) (radius * Math.sin(a * perAngleW) * Math.sin(b* perAngleH));
float y1 = (float) (radius * Math.cos(a * perAngleW));
float x2 = (float) (radius * Math.sin((a + 1) * perAngleW) * Math.cos(b * perAngleH));
float z2 = (float) (radius * Math.sin((a + 1) * perAngleW) * Math.sin(b * perAngleH));
float y2 = (float) (radius * Math.cos((a + 1) * perAngleW));
float x3 = (float) (radius * Math.sin((a + 1) * perAngleW) * Math.cos((b + 1) * perAngleH));
float z3 = (float) (radius * Math.sin((a + 1) * perAngleW) * Math.sin((b + 1) * perAngleH));
float y3 = (float) (radius * Math.cos((a + 1) * perAngleW));
float x4 = (float) (radius * Math.sin(a * perAngleW) * Math.cos((b + 1) * perAngleH));
float z4 = (float) (radius * Math.sin(a * perAngleW) * Math.sin((b + 1) * perAngleH));
float y4 = (float) (radius * Math.cos(a * perAngleW));
vertexArray[vertexIndex++] = (x1);
vertexArray[vertexIndex++] = (y1);
vertexArray[vertexIndex++] = (z1);
vertexArray[vertexIndex++] = (x2);
vertexArray[vertexIndex++] = (y2);
vertexArray[vertexIndex++] = (z2);
vertexArray[vertexIndex++] = (x3);
vertexArray[vertexIndex++] = (y3);
vertexArray[vertexIndex++] = (z3);
vertexArray[vertexIndex++] = (x3);
vertexArray[vertexIndex++] = (y3);
vertexArray[vertexIndex++] = (z3);
vertexArray[vertexIndex++] = (x4);
vertexArray[vertexIndex++] = (y4);
vertexArray[vertexIndex++] = (z4);
vertexArray[vertexIndex++] = (x1);
vertexArray[vertexIndex++] = (y1);
vertexArray[vertexIndex++] = (z1);
}
}
vertexCount = vertexArray.length / 3;
vertexBuffer = ByteBuffer.allocateDirect(vertexArray.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuffer.put(vertexArray);
vertexBuffer.position(0);
float[] coodsArray = new float[]{
-1000, 0, 0,
1000, 0, 0, /*两个点,x轴-1000到1000连成直线*/
0,-1000, 0,
0, 1000, 0, /*两个点,y轴-1000到1000连成直线*/
0, 0,-1000,
0, 0, 1000, /*两个点,z轴-1000到1000连成直线*/
};
coodsBuffer = ByteBuffer.allocateDirect(coodsArray.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
coodsBuffer.put(coodsArray);
coodsBuffer.position(0);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES10.glViewport(0, 0, width, height); // 设置视口宽度高度。
GLES10.glEnable(GLES10.GL_DEPTH_TEST); // 开启深度测试
// {修改投影矩阵
GLES10.glMatrixMode(GLES10.GL_PROJECTION); // 修改投影矩阵
GLES10.glLoadIdentity(); // 复位,将投影矩阵归零
GLU.gluPerspective(gl, 60.0f, ((float) width) / height, 0.1f, 1000f);
// }
}
private float angle = 0.0f ;
private float[] rotateMatrix = new float[16];
public void onDrawFrame(GL10 gl) {
GLES10.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 清空场景为黑色。
GLES10.glClear(GLES10.GL_COLOR_BUFFER_BIT | GLES10.GL_DEPTH_BUFFER_BIT);// 清空相关缓存。
//{
GLES10.glMatrixMode(GLES10.GL_MODELVIEW);
GLES10.glLoadIdentity();//归零模型视图
GLU.gluLookAt(gl, 100, 100, 300, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
//}
angle += 0.4f ; //随时间递增
//创建一个矩阵,然后承载着旋转的参数,然后再加入到OpenGL矩阵链中,后面绘制的物体就会附加上这个矩阵的旋转效果了
Matrix.setIdentityM(rotateMatrix, 0);//矩阵归位,类似 glLoadIdentity()
Matrix.rotateM(rotateMatrix, 0, angle, 0, 1, 0); //以Y轴为准,旋转angle弧度,将这个变换设置到矩阵中,矩阵就代表了这个变换了。
GLES10.glMultMatrixf(rotateMatrix, 0);//将这个矩阵加入矩阵链中。
//Matrix这只是一个工具类,它提供的所有函数都不会直接修改OpenGL状态,只会产生中间值。
//No.1 画出坐标轴的线
GLES10.glEnableClientState(GLES10.GL_VERTEX_ARRAY);
GLES10.glDisableClientState(GLES10.GL_NORMAL_ARRAY); //由于我们画轴的时候没有法线数据输入,所以禁用法线数组功能。
GLES10.glVertexPointer(3, GLES10.GL_FLOAT, 0, coodsBuffer);
//1,画X轴
GLES10.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);//使用红色,OpenGL中颜色以浮点数表示,1.0表示红色满色
GLES10.glDrawArrays(GLES10.GL_LINE_STRIP, 0, 2); //连接两个顶点
//2,画Y轴
GLES10.glColor4f(0.0f, 1.0f, 0.0f, 1.0f);//使用绿色
GLES10.glDrawArrays(GLES10.GL_LINE_STRIP, 2, 2); //连接两个顶点
//3,画Z轴
GLES10.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);//使用绿色
GLES10.glDrawArrays(GLES10.GL_LINE_STRIP, 4, 2); //连接两个顶点
GLES10.glEnableClientState(GLES10.GL_VERTEX_ARRAY);
GLES10.glVertexPointer(3, GLES10.GL_FLOAT, 0, vertexBuffer);
//No.2 画球,给球画上颜色,黄色
GLES10.glColor4f(1.0f, 1.0f, 0.0f, 1.0f);//使用黄色
GLES10.glDrawArrays(GLES10.GL_TRIANGLES, 0, vertexCount);
GLES10.glFlush();
}
public void onDrawFrame(GL10 gl) {
GLES10.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 清空场景为黑色。
GLES10.glClear(GLES10.GL_COLOR_BUFFER_BIT | GLES10.GL_DEPTH_BUFFER_BIT);// 清空相关缓存。
//{
GLES10.glMatrixMode(GLES10.GL_MODELVIEW);
GLES10.glLoadIdentity();//归零模型视图
//}
angle += 1.0f ; //随时间递增
//创建一个矩阵,然后承载着旋转的参数,然后再加入到OpenGL矩阵链中,后面绘制的物体就会附加上这个矩阵的旋转效果了
Matrix.setIdentityM(rotateMatrix, 0);//矩阵归位,类似 glLoadIdentity()
Matrix.rotateM(rotateMatrix, 0, angle, 0, 1, 0); //以Y轴为准,旋转angle弧度,将这个变换设置到矩阵中,矩阵就代表了这个变换了。
GLES10.glMultMatrixf(rotateMatrix, 0);//将这个矩阵加入矩阵链中。
//Matrix这只是一个工具类,它提供的所有函数都不会直接修改OpenGL状态,只会产生中间值。
//gluLookAt的代码位置变到这里来了
GLU.gluLookAt(gl, 100, 100, 300, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
//No.1 画出坐标轴的线
GLES10.glEnableClientState(GLES10.GL_VERTEX_ARRAY);
GLES10.glDisableClientState(GLES10.GL_NORMAL_ARRAY); //由于我们画轴的时候没有法线数据输入,所以禁用法线数组功能。
GLES10.glVertexPointer(3, GLES10.GL_FLOAT, 0, coodsBuffer);
//1,画X轴
GLES10.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);//使用红色,OpenGL中颜色以浮点数表示,1.0表示红色满色
GLES10.glDrawArrays(GLES10.GL_LINE_STRIP, 0, 2); //连接两个顶点
//2,画Y轴
GLES10.glColor4f(0.0f, 1.0f, 0.0f, 1.0f);//使用绿色
GLES10.glDrawArrays(GLES10.GL_LINE_STRIP, 2, 2); //连接两个顶点
//3,画Z轴
GLES10.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);//使用绿色
GLES10.glDrawArrays(GLES10.GL_LINE_STRIP, 4, 2); //连接两个顶点
GLES10.glEnableClientState(GLES10.GL_VERTEX_ARRAY);
GLES10.glVertexPointer(3, GLES10.GL_FLOAT, 0, vertexBuffer);
//No.2 画球,给球画上颜色,黄色
GLES10.glColor4f(1.0f, 1.0f, 0.0f, 1.0f);//使用黄色
GLES10.glDrawArrays(GLES10.GL_TRIANGLES, 0, vertexCount);
GLES10.glFlush();
}
接下来演示一个复杂的变换。
完整代码如下,改动比较多,直接贴上去运行吧,效果OK,经过本人验证。解释都在注释里。
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
initOpenGLVertexs() ;
}
private FloatBuffer coodsBuffer = null ;
private FloatBuffer vertexBuffer = null ;
private FloatBuffer squareBuffer = null ; //正方形的顶点buffer
private FloatBuffer triangleBuffer = null ; //三角形顶点的buffer
private int vertexCount = 0 ;
private void initOpenGLVertexs(){
int slices = 60 ;
int stacks = 30 ;
float radius = 20f ;
double perAngleW = 2 * Math.PI / slices;
double perAngleH = Math.PI / stacks;
float[] vertexArray = new float[slices*stacks*2*3*3];
int vertexIndex = 0 ;
for (int a = 0; a < stacks; a++) {
for (int b = 0; b < slices; b++) {
float x1 = (float) (radius * Math.sin(a * perAngleW) * Math.cos(b* perAngleH));
float z1 = (float) (radius * Math.sin(a * perAngleW) * Math.sin(b* perAngleH));
float y1 = (float) (radius * Math.cos(a * perAngleW));
float x2 = (float) (radius * Math.sin((a + 1) * perAngleW) * Math.cos(b * perAngleH));
float z2 = (float) (radius * Math.sin((a + 1) * perAngleW) * Math.sin(b * perAngleH));
float y2 = (float) (radius * Math.cos((a + 1) * perAngleW));
float x3 = (float) (radius * Math.sin((a + 1) * perAngleW) * Math.cos((b + 1) * perAngleH));
float z3 = (float) (radius * Math.sin((a + 1) * perAngleW) * Math.sin((b + 1) * perAngleH));
float y3 = (float) (radius * Math.cos((a + 1) * perAngleW));
float x4 = (float) (radius * Math.sin(a * perAngleW) * Math.cos((b + 1) * perAngleH));
float z4 = (float) (radius * Math.sin(a * perAngleW) * Math.sin((b + 1) * perAngleH));
float y4 = (float) (radius * Math.cos(a * perAngleW));
vertexArray[vertexIndex++] = (x1);
vertexArray[vertexIndex++] = (y1);
vertexArray[vertexIndex++] = (z1);
vertexArray[vertexIndex++] = (x2);
vertexArray[vertexIndex++] = (y2);
vertexArray[vertexIndex++] = (z2);
vertexArray[vertexIndex++] = (x3);
vertexArray[vertexIndex++] = (y3);
vertexArray[vertexIndex++] = (z3);
vertexArray[vertexIndex++] = (x3);
vertexArray[vertexIndex++] = (y3);
vertexArray[vertexIndex++] = (z3);
vertexArray[vertexIndex++] = (x4);
vertexArray[vertexIndex++] = (y4);
vertexArray[vertexIndex++] = (z4);
vertexArray[vertexIndex++] = (x1);
vertexArray[vertexIndex++] = (y1);
vertexArray[vertexIndex++] = (z1);
}
}
vertexCount = vertexArray.length / 3;
vertexBuffer = ByteBuffer.allocateDirect(vertexArray.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuffer.put(vertexArray);
vertexBuffer.position(0);
float[] coodsArray = new float[]{
-1000, 0, 0,
1000, 0, 0, /*两个点,x轴-1000到1000连成直线*/
0,-1000, 0,
0, 1000, 0, /*两个点,y轴-1000到1000连成直线*/
0, 0,-1000,
0, 0, 1000, /*两个点,z轴-1000到1000连成直线*/
};
coodsBuffer = ByteBuffer.allocateDirect(coodsArray.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
coodsBuffer.put(coodsArray);
coodsBuffer.position(0);
//构造正方形的顶点
float[]squareArray = new float[]{
/*第一个三角形*/
-10, 10, 0, /*注意,这里我正方形z轴全为0,也就是正方形位于x-y的平面上*/
10,-10, 0,
10, 10, 0,
/*第二个三角形*/
-10, 10, 0,
-10,-10, 0,
10,-10, 0,
};
squareBuffer = ByteBuffer.allocateDirect(squareArray.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
squareBuffer.put(squareArray);
squareBuffer.position(0);
//构造三角形的顶点
float[]triangleArray = new float[]{
-15, 15, 0, /*注意,这里我正方形z轴全为0,也就是正方形位于x-y的平面上*/
15,-15, 0,
15, 15, 0,
};
triangleBuffer = ByteBuffer.allocateDirect(triangleArray.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
triangleBuffer.put(triangleArray);
triangleBuffer.position(0);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES10.glViewport(0, 0, width, height); // 设置视口宽度高度。
GLES10.glEnable(GLES10.GL_DEPTH_TEST); // 开启深度测试
// {修改投影矩阵
GLES10.glMatrixMode(GLES10.GL_PROJECTION); // 修改投影矩阵
GLES10.glLoadIdentity(); // 复位,将投影矩阵归零
GLU.gluPerspective(gl, 60.0f, ((float) width) / height, 0.1f, 1500f);
// }
}
private float squareMaxAngle = 0.0f ; //正方形公转旋转弧度
private float triangleMaxAngle = 0.0f ; //三角形公转旋转弧度
private float squareMinAngle = 0.0f ; //正方形自转旋转弧度
private float triangleMinAngle = 0.0f ; //三角形自转旋转弧度
private float squareRadius = 100f ; //正方形公转半径
private float triangleRadius = 150f ; //三角形公转半径
//设置几个运算临时矩阵,因为运算过程很多,不能在onDrawFrame里面new任何东西.
//java GC 回收速度绝对没有 绘制的速度快的。
private float[] tempMatrix1 = new float[16]; //运算临时矩阵1。
private float[] tempMatrix2 = new float[16]; //运算临时矩阵2。
private float[] tempMatrix3 = new float[16]; //运算临时矩阵3。
private float[] tempMatrix4 = new float[16]; //运算临时矩阵3。
public void onDrawFrame(GL10 gl) {
//改变旋转因子,并且速度不一样。
squareMaxAngle += 0.2f ;
triangleMaxAngle += 0.3f ;
squareMinAngle += 1.0f ;
triangleMinAngle += 1.5f ;
GLES10.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 清空场景为黑色。
GLES10.glClear(GLES10.GL_COLOR_BUFFER_BIT | GLES10.GL_DEPTH_BUFFER_BIT);// 清空相关缓存。
//归零模型转换矩阵,则默认物体不进行任何平移旋转。
GLES10.glMatrixMode(GLES10.GL_MODELVIEW);
GLES10.glLoadIdentity();//归零模型视图
//设置视角(必须在任何绘制之前,因为任何物体都必须满足视角的切换)
GLU.gluLookAt(gl, 100, 100, 300, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
//先画不动的物体,坐标线和中间的太阳
GLES10.glEnableClientState(GLES10.GL_VERTEX_ARRAY); //启用坐标数组输入
{//坐标线
GLES10.glVertexPointer(3, GLES10.GL_FLOAT, 0, coodsBuffer);
//1,画X轴
GLES10.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);//使用红色,OpenGL中颜色以浮点数表示,1.0表示红色满色
GLES10.glDrawArrays(GLES10.GL_LINE_STRIP, 0, 2); //连接两个顶点
//2,画Y轴
GLES10.glColor4f(0.0f, 1.0f, 0.0f, 1.0f);//使用绿色
GLES10.glDrawArrays(GLES10.GL_LINE_STRIP, 2, 2); //连接两个顶点
//3,画Z轴
GLES10.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);//使用蓝色
GLES10.glDrawArrays(GLES10.GL_LINE_STRIP, 4, 2); //连接两个顶点
}
{//画太阳
GLES10.glVertexPointer(3, GLES10.GL_FLOAT, 0, vertexBuffer);
GLES10.glColor4f(1.0f, 1.0f, 0.0f, 1.0f);//使用黄色
GLES10.glDrawArrays(GLES10.GL_TRIANGLES, 0, vertexCount);
}
{//画正方形
//首先要进行的是将正方形和三角形平移到公转半径指定的位置上去
//因为从正方形和三角形的初始坐标来看,它们中心在原点位置上。
Matrix.setIdentityM(tempMatrix1, 0);
Matrix.translateM(tempMatrix1, 0, squareRadius, 0, 0);//产生平移变换的矩阵,squareRadius设置给x或者y都可以,但是不能是z。
//上面两句代码已经产生了平移矩阵了,接下来是公转旋转矩阵
Matrix.setIdentityM(tempMatrix2, 0);
Matrix.rotateM(tempMatrix2, 0, squareMaxAngle, 0, 1, 0);//公转以Y轴为中心
//接下来是自传旋转矩阵
Matrix.setIdentityM(tempMatrix3, 0);
Matrix.rotateM(tempMatrix3, 0, squareMinAngle, 0, 0, 1);//自转以Z轴为中心
//分析下我们需要的顺序,旋转和平移的顺序处理不好的话,就会结果不是我们期望的
//从上面代码可以看到,后面公转和自传的代码调用的函数都是一样的,所以要倍加小心
//对于公转的结果,公转必须是在平移之后。而自传必须是在平移之前。
//因为你首先要把一个物体从中心(原点),拉出来,再旋转才会是公转。否则它就是在原地打转
//反过来如果想要自转,就必须保证先在原地转了再拉出来,否则它就变成了公转。
//所以顺序是 先自转,再平移,再公转
Matrix.multiplyMM(tempMatrix4, 0, tempMatrix1, 0, tempMatrix3, 0);//右边的是最先的
Matrix.multiplyMM(tempMatrix4, 0, tempMatrix2, 0, tempMatrix4, 0);//右边的是最先的
//tempMatrix4就是最后的矩阵,同时拥有这些所有变换。
GLES10.glPushMatrix();
GLES10.glMultMatrixf(tempMatrix4, 0);
GLES10.glVertexPointer(3, GLES10.GL_FLOAT, 0, squareBuffer);
GLES10.glColor4f(0.0f, 1.0f, 1.0f, 1.0f);
GLES10.glDrawArrays(GLES10.GL_TRIANGLES, 0, 6);
GLES10.glPopMatrix();
/*
glPushMatrix的含义是将当前系统OpenGL矩阵链,保存一个副本,临时存起来
然后后面调用glMultMatrixf的时候,会修改系统的矩阵,
然后绘制正方形的时候,应用的是新的修改之后的矩阵变换。但是我不希望这个矩阵变换对后面的其他物体起作用
所以到最后glPopMatrix,表示我恢复保存的那个副本,将我刚刚glMultMatrixf的操作还原。
*/
}
{//画三角形,这里就不写注释了,代码调用关系都和上面是一样的。
Matrix.setIdentityM(tempMatrix1, 0);
Matrix.translateM(tempMatrix1, 0, triangleRadius, 0, 0);
Matrix.setIdentityM(tempMatrix2, 0);
Matrix.rotateM(tempMatrix2, 0, triangleMaxAngle, 0, 1, 0);
Matrix.setIdentityM(tempMatrix3, 0);
Matrix.rotateM(tempMatrix3, 0, triangleMinAngle, 0, 0, 1);
Matrix.multiplyMM(tempMatrix4, 0, tempMatrix1, 0, tempMatrix3, 0);
Matrix.multiplyMM(tempMatrix4, 0, tempMatrix2, 0, tempMatrix4, 0);
GLES10.glPushMatrix();
GLES10.glMultMatrixf(tempMatrix4, 0);
GLES10.glVertexPointer(3, GLES10.GL_FLOAT, 0, triangleBuffer);
GLES10.glColor4f(1.0f, 0.0f, 1.0f, 1.0f);
GLES10.glDrawArrays(GLES10.GL_TRIANGLES, 0, 3);
GLES10.glPopMatrix();
}
GLES10.glFlush();
}