2015-10-23 15:51:55 a117653909 阅读数 4321

我觉得要真正地理解四元数是把Unity3D里四元数函数都上手测试一下其功能。
四元数在Unity3D中的作用就是拿来表示旋转。

AngleAxis
创建一个旋转,绕着某个轴旋转,返回结果是一个四元数。
跟ToAngleAxis实现的是相反的功能。

Angle
返回两个旋转值(四元数)之间的角度,返回值是float类型的角度值。
(不知道这个值算出来后有什么用)

Dot
点乘,我也不太理解其意义。
参见

eulerAngles
返回表示旋转的欧拉角度(Vector3 即3个值)
(如果调用的是某个物体,则表示该物体当前位置是从原始位置怎么旋转过来的,
其实就是Inspector里的Rotation的3个值)

Euler
感觉跟eulerAngles是相反的操作(经测试,确实是)
输入的是欧拉角的3个值,返回的是一个旋转(四元数)

FromToRotation
参数是两个Direction(Vector3),返回一个Quaternion
我觉得主要是用在要把A物体的朝向转成跟B物体的朝向一样时所需要的旋转值(Quaternion)
然后再调用Transform.Rotate就可以把A旋转成跟B一样了。

identity
可以理解为单位四元数

Inverse
就是一个旋转的反旋转,其实就是把刚才的那个旋转转回去。

Lerp
插值,可以理解为可以把一个物体的朝向转向跟另一个物体一样,跟时间配合可以慢慢地旋转。

LookRotation
可以让A物体一直朝向B物体。
参照下面这篇文章的做法,导入ThirdPersonController
http://blog.csdn.net/lijing_hi/article/details/7272089

Quaternion
构造函数,参数是4个float值

RotateTowards
跟Slerp类似

SetFromToRotation
跟FromToRotation功能一样,只是调用方式不一样。

SetLookRotation
跟LookRotation功能一样,只是调用方式不一样。

Slerp
旋转一个角度从from到to。

this[int index]
像数组那样调用x, y, z, w,感觉还不如直接用.x来调用。
可能是为了循环方便。

ToAngleAxis
把一个rotation 转成 angle-axis 形式。跟AngleAxis实现的是相反的功能。
用引用的方式传入 angle和 axis 。
这跟transform.localEulerAngles很类似。
输入:transform.localEulerAngles=(0,0,0);
输出:angle=0, axis=(1,0,0);
输入:transform.localEulerAngles=(0,90,0);
输出:angle=90,axis=(0,1,0);
输入:transform.localEulerAngles=(270,0,0);
输出:angle=90,axis=(-1,0,0)

ToString
格式化成一个字符串

参考:http://blog.csdn.net/yustarg/article/details/8623687

2016-10-13 21:11:00 dongfushu7972 阅读数 4

在unity中四元数和向量相乘可以变换旋转。四元数之间相乘类似矩阵之间相乘的效果。

矩阵相乘的顺序不可互换,只有特殊条件矩阵才可互换。四元数相乘类似,今天就因为这个问题掉进坑里了,记录一下

 

问题大致是,有一个cube,它会看向左边的板,用角轴旋转,但我想要y轴看向它

Quaternion.AngleAxis(-90, Vector3.forward);

 

以下代码就是没有注意相乘顺序导致的结果

var quat1 = Quaternion.AngleAxis(-90, Vector3.forward);
var quat2 = Quaternion.AngleAxis(Time.time * 180, referenceTransform.forward);
transform.rotation = quat1 * quat2;

 

修改后正确结果如下

transform.rotation = quat2 * quat1;

 

 

所以在处理四元数或者矩阵相乘操作时,注意顺序,并且避免xxx*=quat这样的操作,尽量用直观写法

 

转载于:https://www.cnblogs.com/hont/p/5958167.html

2018-09-16 17:07:47 capricorn1245 阅读数 2450

作用:四元数和向量相乘表示这个向量按照这个四元数进行旋转之后得到的新的向量。

比如:向量vector3(0,0,10),绕着Y轴旋转90度,得到新的向量是vector3(10,0,0)。

在unity中表示为:

运行结果为:

复合旋转就是四元数依次相乘,最后乘以向量

多来几例:

 

想了解其中的运算过程的可以往下看。

 

将四元数的四个值分别计为:(w,x,y,z),unity中的四元数中的四个数字是(x,y,z,w),不影响下面的计算过程。

绕任意轴旋转任意角度的四元数为:

那么绕着Y轴旋转90度的四元数就是q = (√2/2 , 0 , √2/2 , 0)

unity中这个Quaternion.Euler(0,90,0)打debug的话是(0,√2/2 , 0 , √2/2 ),因为排列顺序是(x,y,z,w),不影响下面的计算过程

 

四元数乘以向量的运算规则为:q * v = (q) *( v) *( q−1);

其中:

q = (√2/2 , 0 , √2/2 , 0);

v,将v向量扩充为四元数(0,v),也就是v = (0 , 0,0 , 10);

q−1是四元数q的逆,求逆过程如下:

  • 共轭四元数:q*=(w,-x,-y,-z),也就是(√2/2 , 0 , -√2/2 , 0)
  • 四元数的模:N(q) = √(x^2 + y^2 + z^2 +w^2),即四元数到原点的距离,计算结果为1
  • 四元数的逆:q−1=q*/N(q),也就是q−1 = (√2/2 , 0 , -√2/2 , 0)

q * v = q * v * q−1 = (√2/2 , 0 , √2/2 , 0) * (0 , 0,0 , 10)*(√2/2 , 0 , -√2/2 , 0);

四元数乘法公式:

按照上述计算公式: q * v = q * v * q−1

 (√2/2 , 0 , √2/2 , 0) * (0 , 0,0 , 10) = (0,5√2,0,5√2)

(0,5√2,0,5√2) * (√2/2 , 0 , -√2/2 , 0)=(0,10,0,0);

 

将最后得到的四元数(0,10,0,0)变为向量(0,newV),就是newV(10,0,0)。

2016-12-08 16:51:35 ccaadd110 阅读数 5767

  1. position = rotation*Vector3(0.0, 0.0, -distance) + target.position;  

这是相机环绕的一段代码,当时无法理解这是怎么实现环绕的尴尬,上网查找了一些资料之后终于明白了,特来记录一下大笑

Unity 里的rotation是四元数,四元数*向量   得到的是经过旋转后的向量,  例如 Quaternion.Euler(0,90,0) *  vector3(0 , 0 , -distance)  得到的是  (-distance,0,0)

实际上就是把(0,0,-distance)绕着y轴旋转90度变成了 (-distance,0,0)   ,在与目标位置相加后就能围绕目标环绕了大笑

2014-08-21 14:02:47 k1246195917 阅读数 1557
   四元数用于旋转,确实很不好理解,但是,有一点好处是不会发生万向锁。 主要用法就是:
   首先,获取你当前的Rotation的四元数和目标Rotation的四元数,相乘即可。
来自前辈的示范:
using UnityEngine;
using System.Collections;

// 暴走武林里主界面的球体的旋转效果
public class SphereRotate : MonoBehaviour
{
    public Camera m_camera = null;

    private bool m_mouseDown = false;
    private Vector3 m_previosMousePosition = Vector3.zero;

    public float m_speed = 0.05f;
    private Quaternion m_targetRot = Quaternion.identity;

    void Start()
    {
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Debug.Log("mouse down");
            m_mouseDown = true;

            m_previosMousePosition = Input.mousePosition;
        }
        else if (Input.GetMouseButtonUp(0))
        {
            if (m_mouseDown)
            {
                Debug.Log("mouse up");
                m_mouseDown = false;
                m_speed = 0.002f;
            }
        }

        if (m_mouseDown)
        {
            Vector3 _dir = Input.mousePosition - m_previosMousePosition;
            if (_dir.sqrMagnitude > 0.1f)
            {
                Vector3 _dir0 = new Vector3(0, 0, -1);
                Vector3 _dir1 = _dir0 + _dir * m_speed;
                // 四元数旋转
                Quaternion _qt = Quaternion.FromToRotation(_dir0, _dir1);
                Quaternion _result = _qt * transform.rotation;
                transform.rotation = _result;
                // 边界限制
                float _angle = Quaternion.Angle(Quaternion.identity, _result);
                Debug.Log(_angle);
                if (_angle > 10)
                {
                    float _lerp = 10 / _angle;
                    m_speed *= _lerp;
                    m_targetRot = Quaternion.Lerp(Quaternion.identity, _result, _lerp);
                }
                else
                {
                    m_targetRot = _result;
                }

                m_previosMousePosition = Input.mousePosition;
            }
        }
        else
        {
            transform.rotation = Quaternion.Lerp(transform.rotation, m_targetRot, 0.2f);
        }
    }
}


没有更多推荐了,返回首页