package com.macrocheng.cubeopengl;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.view.MotionEvent;
public class GLTutorialCube extends GLTutorialBase {
float lightAmbient[] = new float[] { 0.6f, 0.6f, 0.6f, 1.0f }; // 环境光、阴影
float lightDiffuse[] = new float[] { 0.6f, 0.6f, 0.6f, 1.0f }; // 扩散漫射光、漫反射光
float[] lightPos = new float[] {0,0,3,1}; // 光源位置
float matAmbient[] = new float[] { 1f, 1f, 1f, 1.0f };
float matDiffuse[] = new float[] { 1f, 1f, 1f, 1.0f };
int tex; // 纹理
Bitmap[] bmp = new Bitmap[6]; // 纹理图片
int[] tmp_tex = new int[6];
float box[][] = 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,
},
{
-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,
},
{
-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,
},
};
/* 纹理映射数组---其实就是每个面的左上角对应一张图片的左上角,面右上角对应图片的右上角(也可以左上角对应右上角,反正只要对应好就OK)*/
float texCoords[][] = new float[][] {
{
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
},
{
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
},
{
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
},
{
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
},
{
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
},
{
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
}
};
FloatBuffer[] texBuff = new FloatBuffer[6]; // 顶点数组的buffer
FloatBuffer[] cubeBuff = new FloatBuffer[6]; // 纹理数组的buffer
public GLTutorialCube(Context c) { // 构造方法
super(c, 20); // 第二个参数是 帧每秒
for(int i = 0;i<box.length;i++)
{
cubeBuff[i] = makeFloatBuffer(box[i]); // 将顶点的float数组转到floatbuffer中
texBuff[i] = makeFloatBuffer(texCoords[i]); // 将纹理的float数组转到floatbuffer中
}
bmp[0] = BitmapFactory.decodeResource(c.getResources(), R.drawable.icon1);
bmp[1] = BitmapFactory.decodeResource(c.getResources(), R.drawable.icon2);
bmp[2] = BitmapFactory.decodeResource(c.getResources(), R.drawable.icon3);
bmp[3] = BitmapFactory.decodeResource(c.getResources(), R.drawable.icon4);
bmp[4] = BitmapFactory.decodeResource(c.getResources(), R.drawable.icon5);
bmp[5] = BitmapFactory.decodeResource(c.getResources(), R.drawable.icon6);
// 加载纹理图片资源
setFocusable(true);
}
protected void init(GL10 gl) {
gl.glEnable(GL10.GL_LIGHTING);
/* 使用我们当前设定的光照参数计算每个点的颜色---(如果去掉这句,那么默认的白色漫反射光源会代替我们之前设定好的光源,
* 如果我们是画的一个单独的立体球的话,你将看见一个白色的没有立体感的球)*/
gl.glEnable(GL10.GL_LIGHT0); // 启用GL_LIGHT0光源---GL_LIGHT0为光源的名称,是第一个光源
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, matAmbient, 0);
/* glMaterialfv设置物体的材质,也就是物体的颜色
* 参数一:当前材质映射到哪个面上(OPENGL目前只支持前后);参数二:材质的属性(这边指定使用材质的环境反射光),用第三个参数来具体设置
* 参数三:包括了实际属性或元素的GL_FLOAT数组的指针*/
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, matDiffuse, 0);
//GL_DIFFUSE---漫反射光
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuse, 0);
// 设置光源属性---参数一:光源名称;参数二:光源类型;参数三:具体光源参数;参数四:偏移量
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPos, 0);
// 设置光源属性---参数一:光源名称;参数二:说明一下后面指定的是光源的位置;参数三:光源位置
gl.glEnable(GL10.GL_BLEND); // 启用融合处理
// gl.glDisable(GL10.GL_DEPTH_TEST); // 关闭深度测试
//
// gl.glEnable(GL10.GL_TEXTURE_2D); // 启用二维处理
//
// gl.glShadeModel(GL10.GL_SMOOTH); // 阴影使用平滑处理模式
// gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 黑色刷屏
// gl.glClearDepthf(1.0f); // 深度基值
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // 清除颜色和深度缓存
gl.glMatrixMode(GL10.GL_MODELVIEW); // 把当前矩阵转换为指定的矩阵类型(这边是转换成视点坐标系)
gl.glLoadIdentity();
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); // 启用顶点数组
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // 启用纹理数组
gl.glEnable(GL10.GL_TEXTURE_2D); // 启用二维处理
gl.glShadeModel(GL10.GL_SMOOTH); // 阴影使用平滑处理模式
gl.glClearColor(0.3f, 0.4f, 0.5f, 0.5f); // 刷屏颜色RGBA设置
gl.glClearDepthf(1.0f); //深度基值
gl.glEnable(GL10.GL_DEPTH_TEST); // 开启深度测试
gl.glDepthFunc(GL10.GL_LEQUAL); // 小于或等于深度基值的点会被绘制
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
/* 这个方法主要用于消除图形走样---GL_PERSPECTIVE_CORRECTION_HINT:用以纠正单纯线性插值带来的观察错误;GL_NICEST:最高质量的弥补*/
gl.glGenTextures(6, tmp_tex, 0);
// 根据第一个参数(纹理参数)返回6个纹理索引,存储在tmp_tex中
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
/* 告诉OpenGL在显示图像时,当它缩小得比原始得纹理小( GL_TEXTURE_MIN_FILTER )『或放大得比原始的纹理大 ( GL_TEXTURE_MAG_FILTER )』时,
* OpenGL采用的滤波方式。通常这两种情况下我都采用GL_LINEAR 。这使得纹理从很远处到离屏幕很近时都平滑显示。
* 使用 GL_LINEAR 需要CPU和显卡做更多的运算。如果你的机器很慢,你最好应该采用 GL_NEAREST 。但是过滤的纹理在放大的时候,看起来马赛克的很。
* 您也可以结合这两种滤波方式。在近处时使用 GL_LINEAR ,远处时 GL_NEAREST 。*/
for(int i = 0; i < 6; i++)
{
gl.glBindTexture(GL10.GL_TEXTURE_2D, tmp_tex[i]); // 循环绑定6张纹理图片
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp[i], 0);
/* 参数一:说明纹理是一个2D纹理 ( GL_TEXTURE_2D );参数二:代表图像的详细程度,通常就由它为零去了。
* 参数三是数据的成分数(即内容);参数四是边框的值,一般就是“0”。据说openggl_es不支持纹理边界,所以必须设置为0。*/
}
}
float xrot = 0.0f;
float yrot = 0.0f; // 程序运行开始时x、y方向的旋转角度
protected void drawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 清除颜色和深度缓存
gl.glMatrixMode(GL10.GL_MODELVIEW); // 把当前矩阵转换为指定的矩阵类型(这边是转换成视点坐标系)
gl.glLoadIdentity();
GLU.gluLookAt(gl, 0, 0, 3, 0, 0, 0, 0, 1, 0);
/* 后面9个参数分别是眼睛的位置,眼睛朝向的位置(反的???),以及相片朝上的方向(都是xyz)*/
gl.glRotatef(xrot, 1, 0, 0);
gl.glRotatef(yrot, 0, 1, 0);
// 以上三句让物体旋转一个角度(也只是程序运行最初的角度,后面动画中的角度跟这个无关的啦~~~)
for(int i = 0; i < 6; i++) {
gl.glBindTexture(GL10.GL_TEXTURE_2D, tmp_tex[i]);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, cubeBuff[i]);
// 指定数组顶点用glVertexPointer,指定完了就可以用glDrawArray()来把指定的数组中的顶点绘制出来了
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuff[i]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
}
// if(flag == 1) {
// xrot += 2.0f;
// }else if(flag == 2) {
// xrot -= 2.0f;
// }else if(flag == 3) {
// yrot += 2.0f;
// }else if(flag
- 1
- 2
- 3
前往页