【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 2341|回复: 7

[脚本] Unity3D 陀螺仪控制摄像头脚本 GyroController

[复制链接]
发表于 2015-2-6 22:35:52 | 显示全部楼层 |阅读模式
[mw_shl_code=csharp,true]// ***********************************************************

// Written by Heyworks Unity Studio http://unity.heyworks.com/

// ***********************************************************

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 readonly Quaternion landscapeRight = Quaternion.Euler(0, 0, 90);

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

    private readonly Quaternion upsideDown = Quaternion.Euler(0, 0, 180);



    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 = true;



    #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);

        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(100)))
        {

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

        }



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

            if (gyroEnabled)
            {

                DetachGyro();

            }

            else
            {

                AttachGyro();

            }

        }



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

            UpdateCalibration(true);

        }



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

            UpdateCameraBaseRotation(true);

        }



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

            ResetBaseOrientation();

        }



        if (GUILayout.Button("Reset camera rotation", GUILayout.Height(80)))
        {

            transform.rotation = Quaternion.identity;

        }

    }


    #endregion



    #region [Public methods]



    /// <summary>

    /// Attaches gyro controller to the transform.

    /// </summary>

    private void AttachGyro()
    {

        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

}[/mw_shl_code]
发表于 2015-2-9 23:23:17 | 显示全部楼层
不明觉厉害~  楼主看起来很厉害
发表于 2015-4-29 13:24:29 | 显示全部楼层
请问如何从陀螺仪中获得数据?
发表于 2015-5-13 21:10:39 | 显示全部楼层
有效果图吗?用来干什么?
发表于 2015-6-5 14:14:52 | 显示全部楼层

有效果图吗?用来干什么?
发表于 2015-8-25 22:37:01 | 显示全部楼层
学习学习   
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2024-11-24 00:14

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表