android绘制过程3d图形 android实现3d建模_android

相信大家都会画矩形了,下面我们来画一个房间,大家想想怎么画了,我以前想用索引法把每个面都画出来,但是遇到了很多问题,画不出我想要的结果,其实还有种方法,那就是通过旋转,和位移变换,把矩形旋转和位移到长方体的各个面,再加工一下,这样就变成小房间了,下面我们来看看效果和代码吧。 

package yy.cal;

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

public class GLSurfaceViewActivity extends Activity {
	private MySurfaceView mSurfaceView;//声明MySurfaceView对象
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);     
        mSurfaceView=new MySurfaceView(this);//创建MySurfaceView对象
        mSurfaceView.requestFocus();//获取焦点
        mSurfaceView.setFocusableInTouchMode(true);//设置为可触控
        LinearLayout ll=(LinearLayout)this.findViewById(R.id.main_liner);//获得线性布局的引用
        ll.addView(mSurfaceView);
    }
	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		mSurfaceView.onPause();
	}
	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		mSurfaceView.onResume();
	}  
}


package yy.cal;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.view.MotionEvent;

public class MySurfaceView extends GLSurfaceView{
	private final float TOUCH_SCALE_FACTOR = 180.0f/320;//角度缩放比例
    private SceneRenderer mRenderer;//场景渲染器	

    private float mPreviousX;//上次的触控位置X坐标
	
	public MySurfaceView(Context context) {
        super(context);
        mRenderer = new SceneRenderer();	//创建场景渲染器
        setRenderer(mRenderer);				//设置渲染器		
        setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染   
    }
	
	//触摸事件回调方法
    @Override 
    public boolean onTouchEvent(MotionEvent e) {
        float x = e.getX();
        switch (e.getAction()) {
        case MotionEvent.ACTION_MOVE:
            float dx = x - mPreviousX;//计算触控笔X位移
            mRenderer.angle += dx * TOUCH_SCALE_FACTOR;//设置沿x轴旋转角度
            
            requestRender();//重绘画面
        }   
        mPreviousX = x;//记录触控笔位置
        return true;
    }

	private class SceneRenderer implements GLSurfaceView.Renderer 
    {   
    	Cube cube=new Cube();//立方体
    	float angle=45;//总旋转角度
    	
        public void onDrawFrame(GL10 gl) {
    		//设置为打开背面剪裁
    		gl.glEnable(GL10.GL_CULL_FACE);

    		//设置着色模型为平滑着色   
            gl.glShadeModel(GL10.GL_SMOOTH);
        	
        	//清除颜色缓存于深度缓存
        	gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        	//设置当前矩阵为模式矩阵
            gl.glMatrixMode(GL10.GL_MODELVIEW);
            //设置当前矩阵为单位矩阵
            gl.glLoadIdentity();    
            
            GLU.gluLookAt//不太可能变形的视角——小视角
            (
            		gl, 
            		0f,   //人眼位置的X
            		10f, 	//人眼位置的Y
            		15.0f,   //人眼位置的Z
            		0, 	//人眼球看的点X
            		0f,   //人眼球看的点Y
            		0,   //人眼球看的点Z
            		0, 
            		1, 
            		0
            );  
            
            //旋转总坐标系
            gl.glRotatef(angle, 0, 1, 0);
            
            //绘制右立方体
            gl.glPushMatrix();
           // gl.glTranslatef(2, 0, 0);
            cube.drawSelf(gl);
            gl.glPopMatrix();
            
        }

        public void onSurfaceChanged(GL10 gl, int width, int height) {
            //设置视窗大小及位置 
        	gl.glViewport(0, 0, width, height);
        	//设置当前矩阵为投影矩阵
            gl.glMatrixMode(GL10.GL_PROJECTION);
            //设置当前矩阵为单位矩阵
            gl.glLoadIdentity();
            //计算透视投影的比例
            float ratio = (float) height/width ;
            //调用此方法计算产生透视投影矩阵
            //gl.glFrustumf( -1, 1,-ratio, ratio, 1, 100);   //可能变形的视角——大视角  
            gl.glFrustumf( -1, 1,-ratio, ratio, 8f, 100);     //不太可能变形的视角——小视角
        }

        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            //关闭抗抖动 
        	gl.glDisable(GL10.GL_DITHER);
        	//设置特定Hint项目的模式,这里为设置为使用快速模式
            gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST);
            //设置屏幕背景色黑色RGBA
            gl.glClearColor(0,0,0,0);            
            //启用深度测试
            gl.glEnable(GL10.GL_DEPTH_TEST);
        }
    }

}

package yy.cal;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.microedition.khronos.opengles.GL10;

public class ColorRect {
	private FloatBuffer   mVertexBuffer;//顶点坐标数据缓冲
    private IntBuffer   mColorBuffer;//顶点着色数据缓冲
    int vCount=0;//顶点数量
    
    public ColorRect(float width,float height)
    {
    	//顶点坐标数据的初始化================begin============================
        vCount=6;
        final float UNIT_SIZE=4.0f;
        float vertices[]=new float[]
        {
        	0,0,0,
        	width*UNIT_SIZE,height*UNIT_SIZE,0,
        	-width*UNIT_SIZE,height*UNIT_SIZE,0,
        	-width*UNIT_SIZE,-height*UNIT_SIZE,0,
        	width*UNIT_SIZE,-height*UNIT_SIZE,0,
        	width*UNIT_SIZE,height*UNIT_SIZE,0
        };
		
        //创建顶点坐标数据缓冲
        //vertices.length*4是因为一个整数四个字节
        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
        vbb.order(ByteOrder.nativeOrder());//设置字节顺序
        mVertexBuffer = vbb.asFloatBuffer();//转换为Float型缓冲
        mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
        mVertexBuffer.position(0);//设置缓冲区起始位置
        //特别提示:由于不同平台字节顺序不同数据单元不是字节的一定要经过ByteBuffer
        //转换,关键是要通过ByteOrder设置nativeOrder(),否则有可能会出问题
        //顶点坐标数据的初始化================end============================
        
        //顶点着色数据的初始化================begin============================
        final int one = 65535;
        int colors[]=new int[]//顶点颜色值数组,每个顶点4个色彩值RGBA
        {
        		one,one,one,0,
        		0,0,one,0,
        		0,0,one,0,
        		0,0,one,0,
        		0,0,one,0,      	
        		0,0,one,0,
        };

        
        //创建顶点着色数据缓冲
        //vertices.length*4是因为一个int型整数四个字节
        ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
        cbb.order(ByteOrder.nativeOrder());//设置字节顺序
        mColorBuffer = cbb.asIntBuffer();//转换为int型缓冲
        mColorBuffer.put(colors);//向缓冲区中放入顶点着色数据
        mColorBuffer.position(0);//设置缓冲区起始位置
        //特别提示:由于不同平台字节顺序不同数据单元不是字节的一定要经过ByteBuffer
        //转换,关键是要通过ByteOrder设置nativeOrder(),否则有可能会出问题
        //顶点着色数据的初始化================end============================
        
        
    }

    public void drawSelf(GL10 gl)
    {        
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);//启用顶点坐标数组
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);//启用顶点颜色数组

        
		//为画笔指定顶点坐标数据
        gl.glVertexPointer
        (
        		3,				//每个顶点的坐标数量为3  xyz 
        		GL10.GL_FLOAT,	//顶点坐标值的类型为 GL_FIXED
        		0, 				//连续顶点坐标数据之间的间隔
        		mVertexBuffer	//顶点坐标数据
        );
		
        //为画笔指定顶点着色数据
        gl.glColorPointer
        (
        		4, 				//设置颜色的组成成分,必须为4—RGBA
        		GL10.GL_FIXED, 	//顶点颜色值的类型为 GL_FIXED
        		0, 				//连续顶点着色数据之间的间隔
        		mColorBuffer	//顶点着色数据
        );
        
		
        //绘制图形
        gl.glDrawArrays
        (
        		GL10.GL_TRIANGLE_FAN, 		//以三角形方式填充
        		0, 			 			//开始点编号
        		vCount					//顶点的数量
        );
    }

}

package yy.cal;

import javax.microedition.khronos.opengles.GL10;
import static yy.cal.Constant.*;


public class Cube {
	//用于绘制各个面的颜色矩形
	ColorRect cr=new ColorRect(SCALE,SCALE);
	
	public void drawSelf(GL10 gl)
	{
		//总绘制思想:通过把一个颜色矩形旋转移位到立方体每个面的位置
		//绘制立方体的每个面
		
		gl.glPushMatrix();
		

		
		//绘制后小面
		gl.glPushMatrix();		
		gl.glTranslatef(0, 0, -UNIT_SIZE*SCALE);
		cr.drawSelf(gl);		
		gl.glPopMatrix();
		

		
		//绘制下大面
		gl.glPushMatrix();			
		gl.glTranslatef(0,-UNIT_SIZE*SCALE,0);
		gl.glRotatef(-90, 1, 0, 0);
		cr.drawSelf(gl);
		gl.glPopMatrix();
		
		//绘制右大面
		gl.glPushMatrix();			
		gl.glTranslatef(UNIT_SIZE*SCALE,0,0);		
		gl.glRotatef(-90, 1, 0, 0);
		gl.glRotatef(-90, 0, 1, 0);
		cr.drawSelf(gl);
		gl.glPopMatrix();
		
		//绘制左大面
		gl.glPushMatrix();			
		gl.glTranslatef(-UNIT_SIZE*SCALE,0,0);		
		gl.glRotatef(90, 0, 1, 0);
		cr.drawSelf(gl);
		gl.glPopMatrix();
		
		gl.glPopMatrix();
	}
	

}

package yy.cal;

public class Constant {

	 public static final float UNIT_SIZE=4.0f;//单位尺寸
	 public static final float SCALE=0.5f;//尺寸缩放比
}