這一篇作爲線性代數欄目的擴展篇之一,是因爲隨着學習的深入,必須提前學習一些具有應用針對性的數學計算方法,這次我們就來觀察立體幾何空間中點和麪的關係,主要還是爲了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,我們接下來繼續。