zoukankan      html  css  js  c++  java
  • 3D数学提炼总结-向量、矩阵几何意义

    1 向量


    1.1 点-向量-二者关系

    :二维、三维空间一个点的坐标,描述位置。如a(ax, ay, az)

    向量:二维、三维空间中向量描述原点到相对于某个点的位移移动,具有方向长度(大小)属性。描述位移。如a(ax, ay, az)

    向量大小:|v| = √(a2+b2+c2+…+n2),表示向量的长度。

    向量标准化vnorm = v/|v| , v不能为零向量,如下图,a(ax, ay)归一化运算:clip_image001[4]

    1-1. 归一化(标准化)

    关系:向量描述位移,包括相对位置。点描述位置。把向量比喻为一个箭头,头是点,尾是原点,整个向量就是点相对于原点的偏移。


    1.2 零向量与负向量

    零向量:[0,0,…,0],是一个没有位移、没有方向的向量。加性单位元。

    负向量:任何向量都有负向量。-[x, y, z] = [-x, -y, -z]。加性逆元。几何解释:改变方向


    1.3 向量的加法、减法运算

    加法几何解释一:三角形法则

    image_thumb15

    1-2. 加法三角形法则

    加法几何解释二:平行四边形法则

    平移图1-1中绿色线至ab的交点(不再移动a),组成平行四边形,求半角向量,如下图:

    image_thumb28

    1-3. 平半角向量

    减法几何解释:一个点到另一个点的向量。

    减法:先把向量转为负向量再做加法。本职还是加法,继续使用三角形法则

    image  image

    1-4. 右图对左图减法的详细拆解


    1.4 标量与向量乘法:

    放大kk · a = k · (ax, ay, az) = (kax, kay, kaz

    缩小kclip_image005[4] 

    1.5 向量与向量乘法-点积

    a·b = clip_image002[8]  ---满足交换律

    点积结果返回标量值.

    //unity vector3点积计算
    public static float Dot(Vector3 lhs, Vector3 rhs)
    {
        return (float) (
            (double) lhs.x * (double) rhs.x +
            (double) lhs.y * (double) rhs.y +
            (double) lhs.z * (double) rhs.z
        );
    }
    

    点积的几何解释一:角度

    点积等于向量大小与向量的夹角:(同一平面)

    a·b = |a| |b| cos θ

    θ = arccos(a·b / (|a| b|) )

    如果ab是单位向量,则分母为1,简化:

    θ = arccos(a·b)

     image

    1-5. a、b向量夹角

    a·b > 0,θ∈[0°, 90°)

    a·b = 0,θ = 90°

    a·b > 0,θ∈(90°, 180°]

    Unity实际应用方位判断

    //判断a、b方位。求b在a的前后左右相对位置:
    Transform a, b;
    Vector3 diffVec  = a.position – b.position;
    float front_back = Vector3.Dot(a.position.forward, diffVec);
    float left_right = Vector3.Dot(a.position.right, diffVec);
    if(front_back > 0) 前方
    else 后方
    if(left_right > 0) 右方
    else 左方
    


    点积的几何解释二:投影向量

    image

    1-6. 向量投影

    V可以拆分:V是垂直向量,V||是投影向量

    V = V + V||

    如何求投影向量V||

    用三角函数求V||的模:

    image


    带入计算求得向量V||

    image 

    最后也可方便求V

    image

    Unity的Vector3.Project分析:

    public static Vector3 Project(Vector3 vector, Vector3 onNormal)
    {
        //pow(onNormal, 2)
        float num1 = Vector3.Dot(onNormal, onNormal);
        if ((double) num1 < (double) Mathf.Epsilon)
            return Vector3.zero;
        float num2 = Vector3.Dot(vector, onNormal);
        return new Vector3(
            onNormal.x * num2 / num1,
            onNormal.y * num2 / num1,
            onNormal.z * num2 / num1
        );
    }

    实战如何用Vector3.Project算出V||

    image

    1-6. 事例

    求投影向量和垂直向量,以及投影交点坐标:

        public Transform m_from_p;
    
        //一般为法线
        public Transform m_to_p;
    
        //相对于from_p和to_p而言
        public Transform m_origin_p;
        private Vector3  m_projects = Vector3.zero;
    
        void Update()
        {
            //warning: 要统一坐标空间
            //Vector3 toP_foDirect = m_to_p.InverseTransformDirection(m_from_p.position - m_origin_p.position);
            Vector3 toP_foDirect = m_from_p.position - m_origin_p.position;
            Vector3 toP_toDirect = m_to_p.position - m_origin_p.position;
            //求出投影向量 V_ii
            m_projects           = Vector3.Project(toP_foDirect, toP_toDirect);
    
            //from到原点连线
            Debug.DrawLine(m_origin_p.position, m_from_p.position, Color.blue);
            //绘制投影向量线
            Debug.DrawLine(m_origin_p.position, m_origin_p.position + m_projects, Color.black);
    
            //投影点坐标, 对project_P求模可以知道from_p到to_p所在轴的最短距离
            Vector3 project_P    = m_origin_p.position + m_projects;
            //float minDis       = project_P.magnitude;
            //垂直向量
            Vector3 V_T          = project_P - m_from_p.position;
    
            //绘制垂直向量线
            Debug.DrawLine(m_from_p.position, m_from_p.position + V_T.normalized * 100f, Color.green);
        }

    果一个向量v在自身投影,就是v·v = vx2 + vy2 + vz2 = |v|2,继而可以求出v的模


    1.6 向量与向量乘法-叉积

    向量a与向量b的叉积结果向量nn垂直于向量ab组成的平面,可把其看作平面法线

    image

    1-7. 叉乘示意图

    image

    1-8. 叉积计算公式

    几何解释一:平行四边形面积

    几何解释二:顺时针和逆时针方向

    a = (x1, y1, z1), b = (x2, y2, z2);
    
    //a x b = (y1 * z2 - y2 * z1, z1 * x2 - x1 * z2, x1 * y2 - y1 * x2)
    double ans = (y1 * z2 - y2 * z1)+(z1 * x2 - x1 * z2)+( x1 * y2 - y1 * x2)
    
    if(ans>0)
        cout<<"逆时针"<<endl;
    if(ans<0)
        cout<<"顺时针"<<endl;
    if(ans==0)
        cout<<"共线"<<endl;

    几何dot、cross:求点到点的角度

        // 通过 Dot、Cross 结合获取到 a 到 b, b 到 a 的不同夹角
        private void GetAngle(Vector3 a, Vector3 b)
        {
            /*ab叉积求得时针方向,点积求得*/
    
            Vector3 c = Vector3.Cross(a, b);
            float angle = Vector3.Angle(a, b);//只能返回[0°, 180°]
    
            // b 到 a 的夹角
            float sign = Mathf.Sign(Vector3.Dot(c.normalized, Vector3.Cross(a.normalized, b.normalized)));
            float signed_angle = angle * sign;
    
            Debug.Log("b -> a :" + signed_angle);
    
            // a 到 b 的夹角
            sign = Mathf.Sign(Vector3.Dot(c.normalized, Vector3.Cross(b.normalized, a.normalized)));
            signed_angle = angle * sign;
    
            Debug.Log("a -> b :" + signed_angle);
        }

    shader中叉积计算写法

    //shader中叉积计算写法
    float crossProduct = a.yzx * b.zxy - a.zxy * b.yzx;


    2 矩阵

    行矩阵

    M1m =clip_image010[4]


    列矩阵

    M1mT = Mm1clip_image011[4]


    对角矩阵

    也是方块矩阵,行与列相同

    除了对角线以外的元素都为0,称为方块矩阵

    clip_image012[4]


    单位矩阵-一种特殊的对角矩阵

    默认用 I 表示单位矩阵

    对角线元素全为1,其余元素都为0

    任何矩阵与单位矩阵相乘,结果任为其本身

    clip_image013[4]


    转置矩阵---转置运算

    • MijT = Mji
    • 矩阵的行变为列,列变为行
    • (A·B)T = BT·AT,具有反向串接各矩阵

     

    逆矩阵

    • 必须为方阵才有逆矩阵行列相等(n=m)
    • M-1·M = I                      //必须满足
    • (M-1)-1 = M                 
    • I-1 = I                          //单位矩阵的逆矩阵=自身
    • (MT)-1 = (M-1)T             //转置矩阵的逆矩阵等于逆矩阵的转置
    • (A·B·C)-1 = C-1 ·B-1·A-1//反向串接各矩阵

    Unity提供了相关的矩阵函数

     

    正交矩阵

    • M·MT = MT·M = I
    • 任何正交矩阵行列式值:|A|= 1或 -1
    • https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/pic/item/0d338744ebf81a4c55f1e2e1da2a6059242da6d2.jpg

     

    线性变换

    缩放、旋转、平移

    缩放:clip_image014[4]

    只需要改变单位矩阵对角线元素值,(其中w分量为1===> 目标矩阵(行矩阵S(q)

     

    旋转:clip_image015[4] clip_image016[4] clip_image017[4]


    平移一:clip_image018[4] 


    平移二:T(p) =clip_image019[4]


    基础变换矩阵clip_image020[4] 

    M3x3看作缩放旋转,t3x1看作平移,1w分量

    将一个矩阵进行缩放、旋转、平移的复合变换先后顺序不一样,其结果也不一样。绝大多数情况下都是采用前述顺序。

     

    矩阵的几何意义

    为了进一步研究多元方程组,将多元方程组的系数组合在一个矩形数表,形成了矩阵。例如把三元方程组转化为三阶矩阵

    clip_image021[4]

    clip_image022[4]

    例如,已知子坐标空间C3个坐标轴在父坐标空间P下的表示xc, yc, zc,以及其原点位置Oc。当给定一个子坐标空间中的一点Ac = (a,b,c),按照下面4个步骤求出Ac在父坐标空间下的位置。

    1从坐标空间原点开始Oc

    2x轴方向移动x个单位:Oc + axc

    3y轴方向移动y个单位:Oc + axc + byc

    4z轴方向移动z个单位:Oc + axc + byc + czc

    Ap = Oc + axc +byc + czc


    = (xoc, yoc ,zoc) + a(xxc, yxc, zxc) + b(xyc , yyc, zyc) + c(xzc, yzc, zzc)


    = (xoc, yoc ,zoc) + clip_image024[4] clip_image026[6]


    = (xoc, yoc ,zoc) + clip_image028[4] clip_image026[7]


    = (xoc, yoc ,zoc,1) + clip_image030[6] clip_image032[10]


    = clip_image034[4] clip_image030[7] clip_image032[11]  //笔误:O33应该=1


    = clip_image036[4] clip_image032[12]


    = clip_image038[6] clip_image032[13]


    MA->p = clip_image038[7]


     

    透视投影矩阵:

    近裁剪面高度:clip_image040[4]

    远裁剪面高度:clip_image042[4]

    横纵比:摄像机的ViewPortRect中的WH属性决定着Game视图横纵比

    clip_image044[4]


    clip_image046[4]


    clip_image048[4]


    计算某一点是否在裁剪区域内,只需将该点与clip_image050[4],由观察空间变换到裁剪空间。


    clip_image052[4]

    =clip_image054[4]






    注意此时的W分量,可能<0为负数。如果一个点在视锥体内,必须满足

    clip_image056[6]

     

    正交投影矩阵

     

    近裁剪面高度:clip_image058[4]

    远裁剪面高度:clip_image060[4]

    横纵比:clip_image062[4]

    clip_image064[4]


    那么将顶点带入该矩阵相乘:


    clip_image066[4]


    =clip_image068[4]






    判断条件如下

    clip_image0567


    法线变换

    image

    MA->B 顶点变换矩阵, N是法线,T是切线, G是法线变换矩阵

    根据点积性质变换前垂直:(TA)T·NA = 0

    变换后也应该垂直:(TA->B)T·NA->B = 0

    切线公式:TB = (MA->B · TA)T

    切线变换步骤:

    TB · NB = (MA->B · TA)T ·(G · NA)

    = (TA)T ·MA->BT·(G · NA)  = (TA)T · NA ·(MA->BT·G)

    由于TAT·NA = 0

    如果(MA->BT·G) = 0G = (MA->B-1)T

    如果MA->B是正交矩阵,变换包含旋转和系数k统一缩放,MA->B的逆转置矩阵 = (MA->BT)-1 = (MA->B-1)T

    如果MA->B是正交矩阵,变换包含旋转和系数k统一缩放,则(MA->B)-1=clip_image002[22], 简要推导如下

    设MA->B = k·M(M为正交矩阵),

    等式左边:(MA->B)-1=(K·M)-1 = 1/k · M-1

    等式右边:1/K2 · (K·M)T = 1/k2 · k · MT = 1/K · M-1

    如果MA->B是正交矩阵,变换包含旋转和系数k统一缩放,可得MA->B的逆转置矩阵  (MA->BT)-1 = clip_image002[24]

  • 相关阅读:
    Hive Left Join 中 On 与 Where 的区别
    Matplotlib 中文显示方框 最简单解决方案
    Pandas DataFrame 取消科学计数法打印
    Hive中小表与大表关联(join)的性能分析
    ceiling和floor转化
    Tensorflow 错误:The flag 'xxx' is defined twice
    移动端测试
    Selenium处理alert/confirm/prompt提示框,无头浏览器,规避网站监测
    selenium关于断言的使用和获取input的值
    Selenium之用例流程设计
  • 原文地址:https://www.cnblogs.com/baolong-chen/p/11639158.html
Copyright © 2011-2022 走看看