android3D物体的碰撞——正方体的碰撞

      3D物体的碰撞和2D类似,都是根据坐标来计算物体的距离,判断是否碰撞。下面举个简单的列子吧,我这个列子比较局限,简单,只是为了说明这个方法而已,大家可以参照方法进行改进,下面看看代码吧。

 

 

 

 

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:id="@+id/main_liner"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
</LinearLayout>


 

 

 

 

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.KeyEvent;
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;
    }
	
	public boolean onKeyDown(int keyCode,KeyEvent event){
		if(keyCode==KeyEvent.KEYCODE_DPAD_UP)
		{
			mRenderer.x +=0.5f;
		}
		if(keyCode==KeyEvent.KEYCODE_DPAD_DOWN){
			mRenderer.x -=0.5f;
		}
		if(keyCode==KeyEvent.KEYCODE_DPAD_LEFT){
			 mRenderer.angle+=90;
		}
		if(keyCode==KeyEvent.KEYCODE_DPAD_RIGHT){
			 mRenderer.angle+=90;
		}
		return super.onKeyDown(keyCode, event);
	}
	

	private class SceneRenderer implements GLSurfaceView.Renderer 
    {   
    	Cube cube=new Cube();//立方体
    	float angle=45;//总旋转角度
    	float x=0,y=0,z=0;
        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(x, y, z);
            cube.drawSelf(gl);
            gl.glPopMatrix();
            
            
            gl.glPushMatrix();
            gl.glTranslatef(2, 0, 0);
            cube.drawSelf(gl);
            gl.glPopMatrix();
            if(x>1.0f&&x<3.0f){
            	ColorRect.flag=false;
            }else{
            	ColorRect.flag=true;
            }

        }
        
        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 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, 0, -UNIT_SIZE*SCALE);
		gl.glRotatef(180, 0, 1, 0);
		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(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, 1, 0, 0);
		gl.glRotatef(-90, 0, 1, 0);
		cr.drawSelf(gl);
		gl.glPopMatrix();
		
		gl.glPopMatrix();
	}
	

}


 

   

 

 

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,mColorBuffer1,mColor;//顶点着色数据缓冲
    int vCount=0;//顶点数量
    static boolean flag=true;
    public ColorRect(float width,float height)
    {
    	//顶点坐标数据的初始化================begin============================
        vCount=6;
        final float UNIT_SIZE=1.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);//设置缓冲区起始位置
        
        
        int colors1[]=new int[]
                             {
        		                    0,0,one,0,
         		                    0,0,one,0,      	
         		                    0,0,one,0,
                             		one,one,one,0,
                             		0,0,one,0,
                             		0,0,one,0,
                             };
                             ByteBuffer cbb1 = ByteBuffer.allocateDirect(colors1.length*4);
                             cbb1.order(ByteOrder.nativeOrder());
                             mColorBuffer1 = cbb1.asIntBuffer();//转换为int型缓冲
                             mColorBuffer1.put(colors1);//向缓冲区中放入顶点着色数据
                             mColorBuffer1.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	//顶点坐标数据
        );
		
        
        
        if(flag){
        	mColor=mColorBuffer;
        }else{
        	mColor=mColorBuffer1;
        }
        //为画笔指定顶点着色数据
        gl.glColorPointer
        (
        		4, 				//设置颜色的组成成分,必须为4—RGBA
        		GL10.GL_FIXED, 	//顶点颜色值的类型为 GL_FIXED
        		0, 				//连续顶点着色数据之间的间隔
        		mColor	//顶点着色数据
        );
        
		
        //绘制图形
        gl.glDrawArrays
        (
        		GL10.GL_TRIANGLE_FAN, 		//以三角形方式填充
        		0, 			 			//开始点编号
        		vCount					//顶点的数量
        );
    }

}


 

 

 

 

package yy.cal;

public class Constant {

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


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值