Android3D游戏开发之为三角形添加纹理

 

 Android3D游戏开发之为三角形添加纹理

 

今天,来为大家演示的是三角形纹理贴图。在看之前,有必要回头去看下我的另一篇Android OpenGL es 纹理坐标设定与贴图规则一文。呵呵,下面开始我们得开发之旅;

首先,还是先来看下运行效果:

这里还实现了另一个功能:当我们点击图片,移动旋转,图片会改变形状,截图如下:

下面来一起开发这个简单的项目吧。

1、创建一个Android项目,在这里我命名为StripTexture。

2、在res/drawable-mdpi文件中导入一张图片,这里我是导入一张hao.png.如上面效果图。

3、我们在原有的包下新建一个Texture.java类,该类的主要目的是绘制三角形,具体代码如下:

public class Texture {
	private IntBuffer vertexBuffer;
	private FloatBuffer textureBuffer;
	public float mAngleY;
	public float mAngleZ;
	int vCount=0;
	int textureId;
	int one = 0x10000;
	public Texture(int textureId){
		this.textureId=textureId;
		//顶点坐标数据的初始化================begin============================
		vCount=3;
		int vertices[]=new int[]{
				0,one,0,		//上顶点
				-one,-one,0,    //左下点
				one,-one,0
		};
		//vertices.length*4是因为一个整数有四个字节
		ByteBuffer vbb=ByteBuffer.allocateDirect(vertices.length*4);
		vbb.order(ByteOrder.nativeOrder());//设置字节顺序
		vertexBuffer=vbb.asIntBuffer();//转换为int型缓存
		vertexBuffer.put(vertices);//向缓存区中放入顶点坐标数据
		vertexBuffer.position(0);//设置缓冲区起始位置
		
		float textureCoors[]=new float[]{//顶点纹理S、T坐标值数组
				0,1,
	        	1,1,
	        	0.5f,0
		};
		//创建顶点纹理数据缓冲
		//textureCoors.length*4是因为一个float型数为四个字节
		ByteBuffer cbb=ByteBuffer.allocateDirect(textureCoors.length*4);
		cbb.order(ByteOrder.nativeOrder());//设置字节顺序
		textureBuffer=cbb.asFloatBuffer();//转换为float型缓冲
		textureBuffer.put(textureCoors);//向缓冲区中放入顶点着色数据
		textureBuffer.position(0);//设置缓冲区起始位置
	}
	public void drawSelf(GL10 gl){
		//沿Z轴旋转
		gl.glRotatef(mAngleZ, 0, 0, 1);
		//沿Y轴旋转
		gl.glRotatef(mAngleY, 0, 1, 0);
		//允许设置顶点
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		/*为顶点指定坐标数据,其中第一个参数每个顶点的坐标数量为3  xyz ,
		 * 第二个参数顶点坐标值的类型为 GL_FIXED(固定),第三个参数
		 * 连续顶点坐标数据之间的间隔,第四个参数顶点坐标数据*/
		gl.glVertexPointer(3, GL10.GL_FIXED, 0, vertexBuffer);
		//开启纹理
		gl.glEnable(GL10.GL_TEXTURE_2D);
		//允许使用纹理数组
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		//为纹理指定坐标数据
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
		//帮顶指定名称ID纹理
		gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
		//绘制图形
		gl.glDrawArrays(GL10.GL_TRIANGLES, 0, vCount);
		//关闭纹理设置
		gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		//关闭顶点设置
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
	}
}

4、在原有的包下面在新建一个名叫MySurfaceView的类,该类继承GLSurfaceView,并实现了onTouchEvent屏幕触摸单击事件,用于显示绘制的图形,在该类地内部,有一内部类,该内部类继承了Readerer用于为三角形贴上纹理。具体代码如下:

public class MySurfaceView extends GLSurfaceView{
	private SceneRenderer mRenderer;//场景渲染器	
    private float mPreviousY;//上次的触控位置Y坐标
    private float mPreviousX;//上次的触控位置X坐标
    private float TOUCH_SCALE_FACTOR=180.0f/320;;//角度缩放比例

	public MySurfaceView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		 mRenderer = new SceneRenderer();	//创建场景渲染器
	     setRenderer(mRenderer);				//设置渲染器		
	     setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染  
	}
	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.mAngleY += 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{
		Texture texTri;
		int textureId;//纹理ID
		@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();
			//移入屏幕2.5个单位
			gl.glTranslatef(0.0f, 0.0f, -2.5f);
			//绘制图形
			texTri.drawSelf(gl);
		}
		@Override
		public void onSurfaceChanged(GL10 gl, int width, int height) {
			// TODO Auto-generated method stub
			//计算透视投影的比例
			float ratio=(float)width/height;
			//设置视窗大小及位置
			gl.glViewport(0, 0, width, height);
			//设置当前矩阵为投影矩阵
			gl.glMatrixMode(GL10.GL_PROJECTION);
			//重置投影矩阵
			gl.glLoadIdentity();
			//调用此方法计算产生透视投影矩阵
			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, 0, 0, 0);
			//设置着色模型为平滑着色  
			gl.glShadeModel(GL10.GL_SMOOTH);
			//启用深度测试
			gl.glEnable(GL10.GL_DEPTH_TEST);
			//初始化纹理
			textureId=initTexture(gl,R.drawable.hao);
			texTri=new Texture(textureId);
		}
	}
	public int initTexture(GL10 gl,int id){
		//创建纹理,这里指定一个纹理
		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);
        //为纹理指定图片
        Bitmap bitmap=BitmapFactory.decodeResource(getResources(), id);
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
        bitmap.recycle();
        return currTextureId;//返回纹理ID
	}
}
5、在Activity中创建MySurfaceView对象,并把Activity中的内容设置为显示SurfaceView,如下:
package com.wyf.wpf;

import android.app.Activity;
import android.os.Bundle;

public class MyActivity extends Activity {
	MySurfaceView mGLSurfaceView;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mGLSurfaceView = new MySurfaceView(this);
        setContentView(mGLSurfaceView);
        mGLSurfaceView.requestFocus();//获取焦点
        mGLSurfaceView.setFocusableInTouchMode(true);//设置为可触控   
    }
}
6、至此,整个项目已开发完毕,单击执行,便会得到上面效果;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值