Unity编程笔录--实现AR与3D场景结合效果

时间:2022-09-10 22:17:54

前言:大家都知道AR通过扫描识别图来显示3D效果,也可通过Vuforia扩展追踪来实现物体在空间中显示(效果不是很好),本文来实现一个AR和3D场景相结合产生的效果。具体可看效果:

Unity编程笔录--实现AR与3D场景结合效果

准备资料:

      AR使用的是插件Vuforia:下载地址:https://developer.vuforia.com/downloads/sdk

        控制陀螺仪脚本:
using UnityEngine;



/// <summary>

/// Gyroscope controller that works with any device orientation.

/// </summary>

public class GyroController : MonoBehaviour
{

#region [Private fields]



private bool gyroEnabled = true;

private const float lowPassFilterFactor = 0.2f;



private readonly Quaternion baseIdentity = Quaternion.Euler(90, 0, 0);




private Quaternion cameraBase = Quaternion.identity;

private Quaternion calibration = Quaternion.identity;

private Quaternion baseOrientation = Quaternion.Euler(90, 0, 0);

private Quaternion baseOrientationRotationFix = Quaternion.identity;



private Quaternion referanceRotation = Quaternion.identity;

private bool debug = false;



#endregion



#region [Unity events]



protected void Start()
{

AttachGyro();

}



protected void Update()
{


if (!gyroEnabled)

return;

transform.rotation = Quaternion.Slerp(transform.rotation,

cameraBase * (ConvertRotation(referanceRotation * Input.gyro.attitude) * GetRotFix()), lowPassFilterFactor);

}



protected void OnGUI()
{

if (!debug)

return;

GUILayout.Label("Orientation: " + Screen.orientation + "addasdasdas" + gyroEnabled);

GUILayout.Label("Calibration: " + calibration);

GUILayout.Label("Camera base: " + cameraBase);

GUILayout.Label("input.gyro.attitude: " + Input.gyro.attitude);

GUILayout.Label("transform.rotation: " + transform.rotation);



if (GUILayout.Button("On/off gyro: " + Input.gyro.enabled, GUILayout.Height(50)))
{

Input.gyro.enabled = !Input.gyro.enabled;

}



if (GUILayout.Button("On/off gyro controller: " + gyroEnabled, GUILayout.Height(50)))
{

if (gyroEnabled)
{

DetachGyro();

}

else
{

AttachGyro();

}

}



if (GUILayout.Button("Update gyro calibration (Horizontal only)", GUILayout.Height(40)))
{

UpdateCalibration(true);

}



if (GUILayout.Button("Update camera base rotation (Horizontal only)", GUILayout.Height(40)))
{

UpdateCameraBaseRotation(true);

}



if (GUILayout.Button("Reset base orientation", GUILayout.Height(40)))
{

ResetBaseOrientation();

}


//��λ��ͷ�Ƕ�
if (GUILayout.Button("Reset camera rotation", GUILayout.Height(40)))
{

transform.rotation = Quaternion.identity;

}

}



#endregion



#region [Public methods]



/// <summary>

/// Attaches gyro controller to the transform.

/// </summary>

private void AttachGyro()
{
//VRע�Ϳ���
//gyroEnabled = true;

ResetBaseOrientation();

UpdateCalibration(true);

UpdateCameraBaseRotation(true);

RecalculateReferenceRotation();

}



/// <summary>

/// Detaches gyro controller from the transform

/// </summary>

private void DetachGyro()
{

gyroEnabled = false;

}



#endregion



#region [Private methods]



/// <summary>

/// Update the gyro calibration.

/// </summary>

private void UpdateCalibration(bool onlyHorizontal)
{

if (onlyHorizontal)
{

var fw = (Input.gyro.attitude) * (-Vector3.forward);

fw.z = 0;

if (fw == Vector3.zero)
{

calibration = Quaternion.identity;

}

else
{

calibration = (Quaternion.FromToRotation(baseOrientationRotationFix * Vector3.up, fw));

}

}

else
{

calibration = Input.gyro.attitude;

}

}



/// <summary>

/// Update the camera base rotation.

/// </summary>

/// <param name='onlyHorizontal'>

/// Only y rotation.

/// </param>

private void UpdateCameraBaseRotation(bool onlyHorizontal)
{

if (onlyHorizontal)
{

var fw = transform.forward;

fw.y = 0;

if (fw == Vector3.zero)
{

cameraBase = Quaternion.identity;

}

else
{

cameraBase = Quaternion.FromToRotation(Vector3.forward, fw);

}

}

else
{

cameraBase = transform.rotation;

}

}



/// <summary>

/// Converts the rotation from right handed to left handed.

/// </summary>

/// <returns>

/// The result rotation.

/// </returns>

/// <param name='q'>

/// The rotation to convert.

/// </param>

private static Quaternion ConvertRotation(Quaternion q)
{

return new Quaternion(q.x, q.y, -q.z, -q.w);

}



/// <summary>

/// Gets the rot fix for different orientations.

/// </summary>

/// <returns>

/// The rot fix.

/// </returns>

private Quaternion GetRotFix()
{

#if UNITY_3_5

if (Screen.orientation == ScreenOrientation.Portrait)

return Quaternion.identity;



if (Screen.orientation == ScreenOrientation.LandscapeLeft || Screen.orientation == ScreenOrientation.Landscape)

return landscapeLeft;



if (Screen.orientation == ScreenOrientation.LandscapeRight)

return landscapeRight;



if (Screen.orientation == ScreenOrientation.PortraitUpsideDown)

return upsideDown;

return Quaternion.identity;

#else

return Quaternion.identity;

#endif

}



/// <summary>

/// Recalculates reference system.

/// </summary>

private void ResetBaseOrientation()
{

baseOrientationRotationFix = GetRotFix();

baseOrientation = baseOrientationRotationFix * baseIdentity;

}



/// <summary>

/// Recalculates reference rotation.

/// </summary>

private void RecalculateReferenceRotation()
{

referanceRotation = Quaternion.Inverse(baseOrientation) * Quaternion.Inverse(calibration);

}



#endregion

}

正文:



       创建Unity工程,并把导入下载好的Vuforia插件,然后新创建一个场景并保存,拖Vuforia的ARCamera预设到场景中, Unity编程笔录--实现AR与3D场景结合效果


然后在场景中创建一个Cube的3D物体,调整好摄像机能看到的位置
Unity编程笔录--实现AR与3D场景结合效果


然后把准备资料上的陀螺仪脚本挂在到MainCamera摄像机上,并且同时创建一个Test.cs脚本来启动陀螺仪
Unity编程笔录--实现AR与3D场景结合效果

using UnityEngine;
using System.Collections;

public class test : MonoBehaviour
{

// Use this for initialization
void Start()
{
Input.gyro.enabled = true;
}

// Update is called once per frame
void Update()
{
GameObject obj = GameObject.Find("Cube");

obj.transform.Rotate(Vector3.up,Time.deltaTime*20);

}
}



然后只要设置Vuforia的App License Key即可打包测试了。不需要配置AndroidManifest.xml文件