效果图:。。。。。。
编写Dad.java
*在Dad构造器中创建和设置场景渲染器为主动渲染,并设置重写触屏时间回调方法以记录触控笔坐标,改变三角形坐标系的位置,使三角形能够在场景中转动
*为声明场景渲染类,在该类中首先设置场景属性,移动坐标系可以绘制三角形
*定义生成纹理ID的方法initTexture,该方法通过接受图片ID和gl引用,将图片转换成Bitmap
package com.scout.eeeeeee;
/**
* Created by liuguodong on 2017/10/28.
*/
import java.io.IOException;
import java.io.InputStream;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.view.MotionEvent;
public class dad extends GLSurfaceView{
private SceneRenderer mRenderer;//场景渲染器
private float mPreviousY;//上次的触控位置Y坐标
private float mPreviousX;//上次的触控位置X坐标
private float TOUCH_SCALE_FACTOR=180.0f/320;;//角度缩放比例
public int textureId;//纹理的名称ID
public dad(Context context) {
super(context);
// TODO Auto-generated constructor stub
mRenderer = new SceneRenderer(); //创建场景渲染器
setRenderer(mRenderer); //设置渲染器
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染
}
@Override
public boolean onTouchEvent(MotionEvent e)
{
float y = e.getY();
float x = e.getX();
switch (e.getAction()) {
case MotionEvent.ACTION_MOVE:
float dy = y - mPreviousY;//计算触控笔Y位移
float dx = x - mPreviousX;//计算触控笔Y位移
mRenderer.texTri.jiaoY += dy * TOUCH_SCALE_FACTOR;//设置沿x轴旋转角度
mRenderer.texTri.mAngleZ += dx * TOUCH_SCALE_FACTOR;//设置沿z轴旋转角度
requestRender();//重绘画面
}
mPreviousY = y;//记录触控笔位置
mPreviousX = x;//记录触控笔位置
return true;
}
private class SceneRenderer implements GLSurfaceView.Renderer
{
yisuo texTri;
int textureId;
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
//清除颜色缓存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
//设置当前矩阵为模式矩阵
gl.glMatrixMode(GL10.GL_MODELVIEW);
//设置当前矩阵为单位矩阵
gl.glLoadIdentity();
gl.glTranslatef(0, 0f, -2.5f);
texTri.drawSelf(gl);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
//设置视窗大小及位置
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, 20);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
//关闭抗抖动
gl.glDisable(GL10.GL_DITHER);
//设置特定Hint项目的模式,这里为设置为使用快速模式
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST);
//设置屏幕背景色黑色RGBA
gl.glClearColor(0,255,255,0);
//打开背面剪裁
//gl.glEnable(GL10.GL_CULL_FACE);
//设置着色模型为平滑着色
gl.glShadeModel(GL10.GL_SMOOTH);//GL10.GL_SMOOTH GL10.GL_FLAT
//启用深度测试
gl.glEnable(GL10.GL_DEPTH_TEST);
//初始化纹理
textureId=initTexture(gl,R.drawable.su);
texTri=new yisuo(textureId);
}
}
public int initTexture(GL10 gl,int textureId)//textureId
{
int[] textures = new int[1];
gl.glGenTextures(1, textures, 0);
int currTextureId=textures[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, currTextureId);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,GL10.GL_REPEAT);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,GL10.GL_REPEAT);
InputStream is = this.getResources().openRawResource(textureId);
Bitmap bitmapTmp;
try
{
bitmapTmp = BitmapFactory.decodeStream(is);
}
finally
{
try
{
is.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmapTmp, 0);
bitmapTmp.recycle();
return currTextureId;
}
}
编写yisuo.java,定义三角形类Texture
*创建顶点数组,并将顶点数组放入顶点缓冲区内,为绘制三角形做好准备
*创建纹理坐标数组,并将纹理数组放入纹理坐标缓冲区内,为绘三角形做好准备
*绘制三角形
package com.scout.eeeeeee;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.microedition.khronos.opengles.GL10;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.microedition.khronos.opengles.GL10;
public class yisuo {
private IntBuffer mVertexBuffer;//顶点坐标数据缓冲
private FloatBuffer mTextureBuffer;//顶点纹理数据缓冲
public float jiaoY;//沿y轴旋转角度
public float mAngleZ;//沿z轴旋转角度
int vCount=0;//顶点数量
int textureId;
public yisuo(int textureId)
{
this.textureId=textureId;
//顶点坐标数据的初始化
final int UNIT_SIZE=30000;
vCount=3;//顶点的数量
int vertices[]=new int[]//顶点坐标数据数组
{
2*UNIT_SIZE,0,0,
-2*UNIT_SIZE,0,0,
0,4*UNIT_SIZE,0
};
//创建顶点坐标数据缓冲
//vertices.length*4是因为一个整数四个字节
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序
mVertexBuffer = vbb.asIntBuffer();//转换为int型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
//初始化顶点纹理数据的
float textureCoors[]=new float[]//顶点纹理S、T坐标值数组
{
0,1,
1,1,
0.5f,0
};
//创建顶点纹理数据缓冲
ByteBuffer cbb = ByteBuffer.allocateDirect(textureCoors.length*4);
cbb.order(ByteOrder.nativeOrder());//设置字节顺序
mTextureBuffer = cbb.asFloatBuffer();//转换为int型缓冲
mTextureBuffer.put(textureCoors);//向缓冲区中放入顶点着色数据
mTextureBuffer.position(0);//设置缓冲区起始位置
}
public void drawSelf(GL10 gl)
{
gl.glRotatef(mAngleZ, 0, 0, 1);//沿Z轴旋转
gl.glRotatef(jiaoY, 0, 1, 0);//沿Y轴旋转
//顶点坐标,允许使用顶点数组
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//为画笔指定顶点坐标数据
gl.glVertexPointer
(
3, //每个顶点的坐标数量为3 xyz
GL10.GL_FIXED, //顶点坐标值的类型为 GL_FIXED
0, //连续顶点坐标数据之间的间隔
mVertexBuffer //顶点坐标数据
);
//开启纹理
gl.glEnable(GL10.GL_TEXTURE_2D);
//允许使用纹理数组
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//为画笔指定纹理uv坐标数据
gl.glTexCoordPointer
(
2, //每个顶点两个纹理坐标数据 S、T
GL10.GL_FLOAT, //数据类型
0, //连续纹理坐标数据之间的间隔
mTextureBuffer //纹理坐标数据
);
//为画笔绑定指定名称ID纹理
gl.glBindTexture(GL10.GL_TEXTURE_2D,textureId);
//绘制图形
gl.glDrawArrays
(
GL10.GL_TRIANGLES,
0,
vCount
);
gl.glDisable(GL10.GL_TEXTURE_2D);//关闭纹理
}
}
wenCH.java
package com.scout.eeeeeee; import android.app.Activity; import android.os.Bundle; import android.app.Activity; import android.os.Bundle; public class wenCH extends Activity { /** Called when the activity is first created. */ dad mGLSurfaceView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mGLSurfaceView = new dad(this); setContentView(mGLSurfaceView); mGLSurfaceView.requestFocus();//获取焦点 mGLSurfaceView.setFocusableInTouchMode(true);//设置为可触控 } @Override protected void onResume() { super.onResume(); mGLSurfaceView.onResume(); } @Override protected void onPause() { super.onPause(); mGLSurfaceView.onPause(); } }