線性代數:空間點與平面

       這一篇作爲線性代數欄目的擴展篇之一,是因爲隨着學習的深入,必須提前學習一些具有應用針對性的數學計算方法,這次我們就來觀察立體幾何空間中點和麪的關係,主要還是爲了CG中着色應用,比如真實反射和光追計算。

       好接下來進入正題,首先觀察一下空間中一個質點和平面的關係,如下圖:

       

       三維空間中頂點D(x0,y0,z0)在平面鏡面P(Ax+By+Cz+D = 0)的倒影點D'(x',y',z'),這一篇的主要內容就是學習整個求法過程和程序驗證了。

       首先來看一下三維空間中平面的方程表達式Ax+By+Cz+D = 0,爲什麼寫成這樣?前面雖然我們講解過直線和平面,這裏爲了保證思維的step by step,我們繼續學習一遍,如下圖:

       

       上面咋一看就存在一個先有雞還是先有蛋的問題。

       ①.比如我們是先存在平面G,然後在已存在的平面G上取一點A,再做出以A爲起點的平面G的單位法向量AN,接着單位法向量AN與平面G內任意一點P構成垂直關係,所以AN與AP的點積就等於0。

       ②.再比如我們先假定三維空間內存在一點A,以A爲起點做一條單位向量AN,再使用一個直角三角形的尺子(一條直角邊重合於AN)做出AN的任意長度的垂直向量AP,動點P就構成了平面G。

       其實這兩種都對,在計算機三維世界中,我們生成一個平面,如果以第一種情況來講,首先我們肯定要隨意選取三維空間內不重合不共線的三個座標點X Y Z(這三個座標點組成三角形就是一個平面G了),那麼我們通過向量XY和XZ的叉積就能得到平面G的法向量N了,再使N單位化得到單位法向量n,隨後我們通過假定平面任意點P(x,y,z),通過向量XP與單位法向量n的點積等於0就能得到平面G內任意點P的方程,也就是平面方程了(順便再次強調,不瞭解點積和叉積的同學一定要回到前面幾何向量進行詳細理解),順便繪製一個示意圖,如下:

       

      第二種情況就稍微簡單一點,先確定三維空間內一點A,然後做任意單位向量AN,隨後假設一動點P(x,y,z),同時向量AP與單位向量AN的點積等於0,求P點的方程,也就是平面方程,示意圖如下:

      

      上面就是對平面方程比較詳細的理解了,主要還是點叉積的應用之一。

      那麼接下來就開始求解平面一側空間任意點P在平面中的倒影點(對稱點)P'了,如下圖:

      

      推導過程無非就是建立平面G和空間點P以及對稱點P'和相交點P0,根據向量P0P爲K倍的平面單位法向量n以及P0處於平面計算出P0點的座標,然後通過向量P'P0等於向量P0P算出對稱點P'的座標。

      接下來我們就是程序模擬驗證了,畢竟推導出公式得實際用得上才能說學以致用,如下:

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

public class PlaneRefl : MonoBehaviour
{
    public MeshFilter mMeshFilter;

    public Transform mPA;
    public Transform mPB;
    public Transform mPC;
    public Transform mObjP;
    public Transform mObjPRefl;

    private Vector3 mX;
    private Vector3 mY;
    private Vector3 mZ;

    private Vector3 mP;
    private Vector3 mPRefl;

    private Mesh mesh;

    void Start()
    {
        mesh = new Mesh();
        mMeshFilter.mesh = mesh;
    }

    void Update()
    {
        //根據pa pb pc三個頂點構建三角形平面
        Vector3[] vertices = new Vector3[]
        {
            mPA.position,
            mPB.position,
            mPC.position
        };
        int[] triangles = new int[]
        {
            0,1,2
        };
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        //構建平面三點和空間點座標
        mP = mObjP.position;
        mX = mPA.position;
        mY = mPB.position;
        mZ = mPC.position;
        //首先把平面公式計算出來
        //優先根據叉積計算平面的單位法向量
        Vector3 XY = mY - mX;
        Vector3 XZ = mZ - mX;
        Vector3 n = Vector3.Normalize(Vector3.Cross(XZ, XY));
        //根據推導公式得到A*x + B*y +C*z +D = 0
        float A = n.x;
        float B = n.y;
        float C = n.z;
        float D = -n.x * mX.x - n.y * mX.y - n.z * mX.z;
        //繼續根據推導出的公式算出對稱點的座標
        float X = mP.x;
        float Y = mP.y;
        float Z = mP.z;

        float K = (A * X + B * Y + C * Z + D) / (A * A + B * B + C * C);
        float xRefl = X - 2 * K * A;
        float yRefl = Y - 2 * K * B;
        float zRefl = Z - 2 * K * C;

        mPRefl = new Vector3(xRefl, yRefl, zRefl);
        mObjPRefl.position = mPRefl;
    }
}

      上面註釋也算是詳細,先創建一個任意三角形平面G,計算ObjP相對於平面G的對稱座標,實時賦予ObjRefl,效果如下:

 

      講到這裏大致學習完空間中點與平面的一些關係了,後續我們就根據學習到的數學只是來一些着色效果。

      so,我們接下來繼續。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章