Android下利用min3D引擎实现增强现实的简单例子

     前段时间研究了一下Min3D游戏开发引擎,发现这个引擎很好用,例子非常细,使用起来很方便,尤其给的最后一

个例子“ExampleAccelerometer”,很有意思,结合重力感应,这对于最近在做的增强现实项目有一点启发,

于是这里把自己探索的过程和大家分享一下。

      这里对于min3D我就不详细介绍了,以后我会在写篇关于min3D的文章,  大家可以先

http://code.google.com/p/min3d/去了解,在这里为了更好地理解我的意思,建议大家把我提到的那个例子运行一下,体验一下效果.

      我先把做好的效果说明一下,先上图:


背景是手机的摄像头,作为实时的预览,在预览图层的上面利用min3D绘制一个三维图像,而且这是一个md2文件

,当第一次点击屏幕时,3D人物会“跳舞”,再次点击屏幕时,停止动画。另外,我还结合了加速度传感器,这样,当

屏幕向左倾斜时,人物向右移动,向右倾斜时,任务向左移动。

好了,下面该说说原理了。

总的来说,实现步骤有四个:

1、开启摄像头,并将预览图像作为底层;
2、利用min3D在预览图层上绘制或者导入一个虚拟人物;
3、添加触屏事件,在触屏时播放动画;
4、获得传感器数据,动态设置虚拟人物的位置。


下面该是分解动作了:
一、开启摄像头,并将预览图像作为底层
直接上代码:下面是Screen类,专门用来定义摄像头视图的
package com.example.animalar;
 
import java.io.IOException;
import android.content.Context;
import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
//这个类是用来开启摄像头的
public class Screen extends SurfaceView implements SurfaceHolder.Callback {
         
        public Screen(Context context) {
                super(context);
                // Install a SurfaceHolder.Callback so we get notified when the
                // underlying surface is created and destroyed.
                previewHolder = this.getHolder();
                previewHolder.addCallback(this);
                //************
                previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }
         
 
 
        /**
         * Initialize the hardware camera. holder The holder
         */
        public void surfaceCreated(SurfaceHolder holder) {
                //************
                if(!isPreviewRunning)
                        mCamera = Camera.open();
                else
                        mCamera.stopPreview();
 
         
        }
 
        public void surfaceDestroyed(SurfaceHolder holder) {
                // Surface will be destroyed when we return, so stop the preview.
                // Because the CameraDevice object is not a shared resource, it's very
                // important to release it when the activity is paused.
                try {
                        if (mCamera!=null) {
                                //**********
                                mCamera.setPreviewCallback(null);
                                mCamera.stopPreview();  
                                mCamera.release();
                                //**********
                                mCamera=null;
                                isPreviewRunning=false;
                        }
                } catch (Exception e) {
 
                }
        }
 
        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
                if(mCamera!=null&&isPreviewRunning!=true)
                {
                        try{
                                Camera.Parameters p = mCamera.getParameters();  
                                p.setPreviewSize(w, h);
                                mCamera.setPreviewDisplay(holder);
                                //mCamera.setParameters(p);
                                mCamera.setPreviewCallback(null);
                                mCamera.startPreview();
                        }
                        catch (IOException e) {
                                e.printStackTrace();
                        }
 
 
                        isPreviewRunning = true;
                }
 
        }
 
 
        private Camera mCamera;
        private SurfaceHolder previewHolder;
        private boolean isPreviewRunning=false;
        //private Camera.PreviewCallback imageCaptureCallback;
 
}

这个类是用来开启摄像头的,继承自surfaceview,要注意出现"//********"的地方,这些地方很容易导致错误。
这个只是一个SurfaceView定义,还没有加到图层中去,所以别急  
哦,对了,忘了说布局文件了,看代码吧:
<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > 
        
        <FrameLayout android:id="@+id/abc1"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content"
        />
         <FrameLayout android:id="@+id/abc2"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content"
        />
 
<div align="\"left\""></FrameLayout> </div>
总共有三个FrameLayout,分别是总体布局、摄像头预览图层和min3D绘制图层。
绘制图形的部分就体现出min3D的优势了,很短的函数就能把完整的md2文件导入进去,这里再次建议大家看一看
min3D的代码,有助于下面的理解。
二、利用min3D在预览图层上绘制或者导入一个虚拟人物
public void initScene() {
                scene.backgroundColor().setAll(0x00000000);        
                scene.lights().add(new Light()); // 添加光源        
                IParser parser = Parser.createParser(Parser.Type.MD2, getResources(),
                                "com.example.animalar:raw/ogro", false);
                parser.parse();
                ogre = parser.getParsedAnimationObject();
                ogre.scale().x = ogre.scale().y = ogre.scale().z = .07f;
                ogre.rotation().z = -90;
                ogre.rotation().x = -90;
                ogre.position().z = -4f;
                ogre.position().y = -2f;
                scene.addChild(ogre);
                mSensorManager.registerListener(this, mAccelerometer,
                                SensorManager.SENSOR_DELAY_UI);
        }


绘制图形的部分就体现出min3D的优势了,很短的函数就能把完整的md2文件导入进去,这里再次建议大家看一看
min3D的代码,有助于下面的理解。

三、添加触屏事件,在触屏时播放动画;
public boolean onTouchEvent(MotionEvent e) {
                if (e.getAction() == MotionEvent.ACTION_DOWN) {
                        if (twice == false) {
                                ogre.setFps(30);
                                ogre.play();
                                twice = true;
                        } else {
                                ogre.pause();
                                twice = false;
                        }
                }
                return true;
        }

注意boolean twice这个变量,当twice=false,判定为第一次触摸屏幕,播放动画。

当twice=true时,判定为再次触摸屏幕,此时停止播放动画



四、获得传感器数据,动态设置虚拟人物的位置。
public void onSensorChanged(SensorEvent event) {
                if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
                        return;
                //float Acc_Z = (float) event.values[2];
 
                mAccVals.x = (float) (-event.values[1] * FILTERING_FACTOR + mAccVals.x
                                * (1.0 - FILTERING_FACTOR));
                mAccVals.y = (float) (event.values[0] * FILTERING_FACTOR + mAccVals.y
                                * (1.0 - FILTERING_FACTOR));
                // mAccVals.x=-event.values[1];
                scene.camera().position.x = mAccVals.x * .5f;
                scene.camera().position.y = mAccVals.y * .2f;
                scene.camera().target.x = scene.camera().position.x;
 
        }
 
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
                // TODO Auto-generated method stub
        }

关于Android下传感器的使用方法这里就不在赘述了,网上的教程挺多的。其实这里的代码是min3D引擎中的

ExampleAccelerometer例子的源代码

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值