1. 程式人生 > >幾何向量:點與直線

幾何向量:點與直線

       這一篇是幾何向量的擴充套件篇之一,因為後面要講到的CG技術需要這一篇的數學基礎,所以額外開一篇進行講解。

       這次我們就觀察學習二維中點與直線的重要關係,垂線或者說圖形學中的法線,因為這和後續的反射向量、光追計算、鏡面計算等有很大依賴關係,比如說我們有一個頂點P處於一塊二維鏡面前,求這個頂點P在二維鏡面中的倒影頂點P',這就需要求出頂點P到鏡面所處的直線L的垂線及距離了,如下圖:

       

首先確定鏡面直線L的方程:A*x+B*y+C = 0,這個方程怎麼來的呢?無非就是一元一次方程y = K*x+B的另一種寫法形式,具體如下:

       

       那麼接下來我們已知一個頂點P(x0,y0),想求出頂點P在鏡面直線L中的倒影P'(x',y'),我們連線P和P'得到的新直線垂直於直線L,同時相交點為P1(x1,y1),那麼我們先起碼得求出新直線L'的方程,求法如下:

       

       這裡有一個關鍵的斜率的問題,我們把直線L方程y = K*x + B中K稱為斜率,意思就是以單位圓為參考,直線與x座標軸的夾角θ的正切值,也就是tanθ,那麼直線L的垂線L'的斜率就是-1/k,如下圖:

       我們拋開平移不談,只談y和x的比例K也就是斜率符合三角函式中正切值tan的定義。

       這裡我們就總結一下,我們已經把垂線L'方程和相交點P1得到了,如下圖:

       

       接下來就是求解倒影點P'的座標公式了,無非就是根據向量相等去計算,如下圖:

       

       推到這裡基本沒什麼問題了,最後為了程式實現,我們順便寫上根據兩已知頂點求直線的公式,這裡我們通過上面講的斜率方法推導,如下圖:

       

       求直線的方程無非就是求動點P的座標公式。

       最後我們就來程式模擬了,假設我有一條隨時變化的鏡面直線L,鏡面直線L前方有一個物體P,求物體P在鏡面中倒影P',模擬程式如下:

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

public class ReflectObject : MonoBehaviour
{
    public LineRenderer mLineRender;

    public Transform mMirrorPosA;
    public Transform mMirrorPosB;

    public Transform mObjectP;
    public Transform mObjectPInvert;

    private float mA;
    private float mB;
    private float mC;
    private Vector3 mInvertPos;

    void Start()
    {

    }

    void Update()
    {
        //計算鏡面直線的方程引數,A*x + B*y + C = 0
        //根據之前推導的方程我們可以得出
        mA = mMirrorPosB.position.y - mMirrorPosA.position.y;
        mB = mMirrorPosA.position.x - mMirrorPosB.position.x;
        mC = mMirrorPosB.position.x * mMirrorPosA.position.y - mMirrorPosA.position.x * mMirrorPosB.position.y;
        //同樣根據之前推導的倒影點P'座標公式計算出座標引數
        float x0 = mObjectP.position.x;
        float y0 = mObjectP.position.y;
        float x = (mB * mB * x0 - 2 * mA * mB * y0 - 2 * mA * mC - mA * mA * x0) / (mA * mA + mB * mB);
        float y = (mA * mA * y0 - 2 * mA * mB * x0 - 2 * mB * mC - mB * mB * y0) / (mA * mA + mB * mB);
        float z = 0;
        mInvertPos = new Vector3(x, y, z);
        mObjectPInvert.position = mInvertPos;
        //給鏡面直線畫個linerender方便顯示
        mLineRender.positionCount = 2;
        mLineRender.SetWidth(0.2f, 0.2f);
        mLineRender.SetPosition(0, mMirrorPosA.position);
        mLineRender.SetPosition(1, mMirrorPosB.position);
    }
}

    程式碼很簡單,我只進行了簡單的註釋,無非就是通過上面推導的公式進行模擬,效果圖如下:

   

    講到這裡,這一篇部落格的目的就達到了,後面我們繼續深入,在立體幾何中進行講解點與面的關係,最終實現我們想要的真實反射和光追。

   so,我們接下來繼續。