unity3d 尝试 基于地理定位的 增强现实

本文分享了一次基于地理定位的AR全息实景应用开发经历,包括Unity中使用陀螺仪控制相机、WebCamTexture显示摄像头画面、调用高德地图API实现地理定位及搜索周边信息等功能,并探讨了在开发过程中遇到的方向偏移问题及滤波解决方案。
摘要由CSDN通过智能技术生成

首先说,这个尝试失败,属于死在去医院的路上那种。


基于地理定位的增强现实,AR全息实景,是一种高大上的说法,说直白点就是山寨类似随便走这样的应用。

打开应用,搜索周边信息,然后再把信息叠加在摄像头拍摄到的内容上面。



思路:用手机移动来控制unity中的camrea,将摄像头拍摄到的内容作为背景。获取地理信息,将信息转化成文字添加到unity的世界中。


1、用手机移动控制unity中的camrea。

这段代码中unity的论坛中找到,但是时间很久远,改了下发现能用。

http://forum.unity3d.com/threads/sharing-gyroscope-controlled-camera-on-iphone-4.98828/

using UnityEngine;
using System.Collections;

public class CameraManager : MonoBehaviour {



	private bool gyroBool;
	private Gyroscope gyro;
	private Quaternion rotFix;

	public void Start ()
	{
		Transform currentParent = transform.parent;
		GameObject camParent = new GameObject ("GyroCamParent");
		camParent.transform.position = transform.position;
		transform.parent = camParent.transform;
		GameObject camGrandparent = new GameObject ("GyroCamGrandParent");
		camGrandparent.transform.position = transform.position;
		camParent.transform.parent = camGrandparent.transform;
		camGrandparent.transform.parent = currentParent;

		gyroBool = SystemInfo.supportsGyroscope;

		if (gyroBool) {

			gyro = Input.gyro;
			gyro.enabled = true;

			if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
				camParent.transform.eulerAngles = new Vector3 (90, 90, 0);
			} else if (Screen.orientation == ScreenOrientation.Portrait) {
				camParent.transform.eulerAngles = new Vector3 (90, 180, 0);
			} else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
				camParent.transform.eulerAngles = new Vector3 (90, 180, 0);
			} else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
				camParent.transform.eulerAngles = new Vector3 (90, 180, 0);
			} else {
				camParent.transform.eulerAngles = new Vector3 (90, 180, 0);
			}

			if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
				rotFix = new Quaternion (0, 0,0.7071f,0.7071f);
			} else if (Screen.orientation == ScreenOrientation.Portrait) {
				rotFix = new Quaternion (0, 0, 1, 0);
			} else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
				rotFix = new Quaternion (0, 0, 1, 0);
			} else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
				rotFix = new Quaternion (0, 0, 1, 0);
			} else {
				rotFix = new Quaternion (0, 0, 1, 0);
			}

			//Screen.sleepTimeout = 0;
		} else {
			#if UNITY_EDITOR
			print("NO GYRO");
			#endif
		}
	}

	public void Update ()
	{
		if (gyroBool) {
			Quaternion quatMap;
			#if UNITY_IOS
			quatMap = gyro.attitude;
			#elif UNITY_ANDROID
			quatMap = new Quaternion(gyro.attitude.x,gyro.attitude.y,gyro.attitude.z,gyro.attitude.w);
			#endif
			transform.localRotation = quatMap * rotFix;
		}
	}
}


2、背景摄像头显示摄像机内容

摄像头的内容可以显示在guitexure上也可以显示在plan上,但是在guitexrue上显示的时候,方向转了90度,最后只好显示在plan上。

using UnityEngine;
using System.Collections;

public class WebCamManager : MonoBehaviour {

	// Use this for initialization
	void Start () {

		WebCamTexture webcamTexture = new WebCamTexture ();

		//如果有后置摄像头,调用后置摄像头
		for (int i = 0; i < WebCamTexture.devices.Length; i++) {
			if (!WebCamTexture.devices [i].isFrontFacing) {
				webcamTexture.deviceName = WebCamTexture.devices [i].name;
				break;
			}
		}

		Renderer renderer = GetComponent<Renderer>();  
		renderer.material.mainTexture = webcamTexture;  
		webcamTexture.Play();  
	}
}


3、调用高德地图的地理定位和搜索附近

详细内容请看我之前的博客

http://blog.csdn.net/wuyt2008/article/details/50774017

http://blog.csdn.net/wuyt2008/article/details/50789423


4、当搜索到内容以后,将名称信息添加到unity的世界里。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;

public class ARMange : MonoBehaviour {

	public List<PlaceInfo> places = new List<PlaceInfo>();
	public GameObject perfab;
	public PlaceInfo location = new PlaceInfo ();

	public void ShowPlaces(){
		ClearPlace ();

		for (int i = 0; i < places.Count; i++) {

			GameObject newPlace = Instantiate<GameObject> (perfab);
			newPlace.transform.parent = this.transform;

			double posZ = places [i].Latitude - location.Latitude;
			double posX = places [i].Longitude - location.Longitude;

			float z = 0;
			float x = 0;
			float y = 0;

			if (posZ > 0) {
				z = 500f;
			} else {
				z = -500f;
			}

			if (posX > 0) {
				x = 500f;
			} else {
				x = -500f;
			}

			z = z + (float)(posZ * 1000);
			x = x + (float)(posX * 1000);
			y = y + i * 20;

			newPlace.transform.position = new Vector3 (x, y, z);
			newPlace.transform.LookAt (this.transform);
			newPlace.transform.Rotate (new Vector3 (0f, 180f, 0f));

			newPlace.gameObject.GetComponentInChildren<Text> ().text = places [i].Name;
		}
	}

	private void ClearPlace(){
		GameObject[] oldPlaces = GameObject.FindGameObjectsWithTag ("Place");
		for (int i = 0; i < oldPlaces.Length; i++) {
			Destroy (oldPlaces [i].gameObject);
		}
	}

}


5、这个时候显示内容没问题,但是方向会偏移。于是加了个指南针来矫正方向

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class CompassManage : MonoBehaviour {

	public Transform cam;

	void Start () {
		Input.location.Start ();
		Input.compass.enabled = true;
	}
	
	// Update is called once per frame
	void Update () {
		transform.rotation = Quaternion.Euler(0, cam.eulerAngles.y-Input.compass.trueHeading, 0);
	}
}


6、最后遇到的,我无法解决的问题

简单一句话,就是滤波。这个应用需要准确稳定的判断出当前手机方向位置状态,但是,输入的内容,重力,罗盘,加速度都是在不断变化,并且会有偏移的量,需要滤波。

虽然大致知道了是应该用互补滤波和卡尔曼滤波,但是,我的水平只能看懂名字,看不懂内容。

数学无力的我只好放弃。等遇到别人写好的代码再抄下吧。


这是死在半路上的结果的样子




这样的结果呢,当然是不甘心的,但是没时间去仔细研究这个问题了,所以只好放弃。如果哪位大侠知道怎么根据重力,罗盘,加速判断手机状态的,在这里跪求先。

源码和编译的apk:http://download.csdn.net/detail/wuyt2008/9458508

====================



在SearchManage.cs文件中,我把搜索范围限定在了昆明,

			//txtInfo.text = txtInfo.text + "\r\n";
			AndroidJavaObject query = amapHelper.Call<AndroidJavaObject>("getPoiSearch",inputQuery.text,"","0871");
			txtInfo.text = txtInfo.text + "query get...";
将0871改成其他地方的区号就可以了,(为空是全国范围,但是没验证过)
评论 35
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值