dx12 龙书附录C学习笔记 -- 解析几何学选讲

24 篇文章 10 订阅

本附录中,我们将以向量与点为基石来构建出更为复杂的几何图形。

1.射线、直线以及线段

一条直线可以用线上一点{\color{DarkRed} p_0}以及与此线平行的向量u来表示,所以,此直线的向量直线方程(vector line equation)为:

p(t)=p_0+tu  其中t∈R

通过赋予t不同的值,我们就能获得直线上的不同的点。

如果将t限制为非负数,那么这个向量直线方程的图像就变为射线

线段:假设通过端点p_0 p_1来定义一条线段,那么将u=p_1-p_0,那么原向量直线方程变成:

p(t)=p_0+t(p_1-p_0)  然后t被限定在[0,1]的范围之内。

2.平行四边形

根据向量直线方向的思想:设q为一点,且u和v是两个非平行向量,可以得到平行四边形方程:

p(s,t)=q+su+tv 其中s,t∈[0,1]

如果限制为0~1的话,向量u/v的长度刚好就是边长

 如果u和v相互平行,那么p方程可以转换成直线方程,变成单自由度方程

单自由度(one degree of freedom)方程,双自由度方程。要想获得像平行四边形这样的2D几何形状,必须采取双自由度方程。

3.三角形

三角形的向量方程和平行四边形的差不多,就是进一步限制了s,t的范围:

p(s,t)=q+su+tv 其中s≥0,t≥0,s+t≤1

注意,三角形就是平行四边形的一半,所以≤1就能很好的理解

如果给出三角形的三个点p_0 p_1 p_2,我们能将uv换成对应的向量:

\\p(s,t)=q+su+tv=p_0+s(p_1-p_0)+t(p_2-p_0)=sp_1+tp_2+(1-s-t)p_0

我们就得到了重心坐标(1-s-t,s,t),或者把1-s-t换成r,重心坐标表示了三角形的三个顶点的加权平均值。n=(a,b,c)

4.平面

我们可以把一个平面视为一张无限薄、无限宽以及无限长的“三无”纸。一个平面可以用一个向量{\color{DarkOrange}n }(n不一定具有单位长度)与平面内一点{\color{DarkRed} p_0}来表示

一个平面可以将空间划分为正半空间(positive half-space)与负半空间(negative half-space)。正半空间也为平面前侧的空间,也就是平面法向量指向的一侧。

平面内的点p与p0的连线一定正交于n,所以我们就得到了平面方程(plane equation)

n\cdot (p-p_0)=0

因为在描述一个特定平面的时候,法线n与平面内的点p0都是确定下来的,所以平面方程可以改写为:

n\cdot p - n\cdot p_0 = d\cdot p + d = 0  其中:d=-n\cdot p_0

如果n=(a,b,c)p=(x,y,z),那么平面方程就可以写作:

⭐ {\color{Magenta} ax+by+cz+d=0}

如果平面法向量n为单位长度,那么d表示的就是从坐标新原点至此平面的最短“有符号”(或"有向")距离。-- ||p_0|| \cdot cos\theta 有符号距离意思是θ角度若大于90°,则为负

总结:

平面法向量n=(a,b,c),平面到原点的距离为||d||,那么平面方程:

ax+by+cz+d=0

d具体取正或负取决于平面法线的朝向,如果平面法线朝外(站在原点来看),那么d取正

d = -n·p_0

①DirectX数学库中平面的表示:

存储法向量n与常量d是一件很容易的事,[或者说存储平面方程中abcd四个参数的量很容易,]我们可以把它们表示为(n,d)=(a,b,c,d)。因此我们可以用XMVECTOR类型来存储这个浮点数值四元组。

DirectX数学库也提供了XMVECTOR类型的重载用于表示平面。

②空间点与平面的位置关系:

回顾平面方程:n\cdot (p-p_0)=n\cdot p+d = 0

判断空间点与平面的位置关系:方程表示的是两个向量(平面法向量和平面内某向量)的夹角θ的余弦值cosθ,因为正交所以=0。如果左式>0,代表cosθ>0,说明此时点p0位于平面的前侧空间。同理,左式<0,说明p0位于平面的后侧空间。

DirectX数学库提供函数专门计算特定点的n\cdot p+d

XMVECTOR XMPlaneDotCoord( // 返回每个坐标分量都存有n·p+d计算结果的XMVECTOR
    XMVECTOR P, // (a,b,c,d)表示的平面
    XMVECTOR V // (x,y,z,w=1)来表示的点
);
// n·p+d=ax+by+cz+d

// 使用:判断平面与点的关系:
float x = XMVectorGetX(XMPlaneDotCoord(p, v));
if(x约等于0.f)
else if(x>0)
else if(x<0)

还有类似的函数计算:返回平面法向量与指定的3D向量的点积:

XMVECTOR XMPlaneDotNormal(XMVECTOR Plane, XMVECTOR Vec);

③构建平面:

除了直接指定平面系数(n,d)=(a,b,c,d)之外,还有两种方式来计算这些系数:

  • 给出法线n与平面内一已知点p_0,就能解出d:

d=-n\cdot p_0

// 平面内一点与法线构建对应的平面(n,d)
XMVECTOR XMPlaneFromPointNormal(
    XMVECTOR Point,
    XMVECTOR Normal
);
  • 指定目标平面内3个不共线的点:

\\ u =p_1-p_0, \ v=p_2-p_0, \ n=u\times v,d=-n\cdot p_0

XMVECTOR XMPlaneFromPoints(
    XMVECTOR Point1,
    XMVECTOR Point2,
    XMVECTOR Point3
);

④对平面进行规范化处理:

有些时候,我们可能需要对平面的法向量进行规范化处理。但是注意,d的表示也依赖于法向量n,所以对n除以||n||进行规范化处理时,d也要除以||n||。

XMVECTOR XMPlaneNormalize(XMVECTOR P);

⑤对平面进行变换:

[Lengyel02]证明了:如果要对一个平面(n,d)进行某种变换,可以先将它作为一个4D向量,再令它乘以所需变换矩阵的逆转置矩阵即可。

补充知识:用变换矩阵处理以下数据(不同数据进行矩阵变换):

p'=p\cdot M

点直接乘上变换矩阵即可,然后w=1

向量

??????????????????????????????????????????????????????

在变换之前,首先得保证法向量是规范化的

XMVECTOR XMPlaneTransform(XMVECTOR P, XMMATRIX M);

示例代码:

XMMATRIX T(...); // T初始化为需要的变换矩阵
XMMTARIX invT = XMMatrixInverse(XMMatrixDeterminant(T), T);
XMMATRIX invTransposeT = XMMatrixTranspose(invT);

XMVECTOR p = (...); // 初始化平面
p = XMPlaneNormalize(p); // 确定法线是规范化的

XMVECTOR transformedPlane = XMPlaneTransform(p, &invTransposeT);

⑥平面内离指定点最近的点:

假设空间点p,欲求出平面(n,d)上至点p最近的一点q。

假设||n||=1,因此有proj_n(p-p_0)=[(p-p_0)\cdot n]n

所以:

\\q=p-[(p-p_0)\cdot n]n\\=p-(p\cdot n-p_0 \cdot n)n\\=p-(p\cdot n+d)n

⑦射线与平面的相交检测:

指定一条射线p(t)=p_0+tu与一个平面的方程n\cdot p + d=0,我们就能知道射线与平面是否相交以及相交时的交点。为此,我们要将射线代入平面方程,并解出满足此平面方程的参数t,借入根据参数求出两者的交点。

假设平面上的点也在射线上,将射线p的方程代入平面:

\\ n\cdot p(t) + d =0 \\ n\cdot (p_0+tu)+d=0\\ n\cdot p_0+tn\cdot u+d=0\\ tn\cdot u = -n\cdot p_0 - d \\ t=\frac{-n\cdot p_0 - d}{n\cdot u}

如果n\cdot u = 0,那么射线与平面平行,方程不是无解就是无穷个解(射线在平面内)。如果t不在区间[0,∞)内,那么射线不与平面相交,但该射线所在直线与平面相交。如果t在[0,∞)内,那么射线与平面相交,就可以通过t为t_0=\frac{-n\cdot p_0 -d}{n\cdot u}的射线方程求出两者的交点。

射线与平面的相交检测可以方便地该做线段与平面的相交检测。若给出定义一条线段的两个端点p与q,那么就可以用它们来构建射线r(t)=p+t(q-p)。我们就将这条射线用于相交检测。如果t∈[0,1],那么线段与平面相交,否则就不相交。

// Intersect:相交
// 该函数判断平面与线段是否相交
XMVECTOR XMPlaneIntersectLine(
    XMVECTOR P,
    XMVECTOR LinePoint1,
    XMVECTOR LinePoint2
);
// 返回值:交点

⑧反射向量:

指定一个向量I,欲求出它关于某平面法线n的反射向量。

❌:\overrightarrow{I}+ \overrightarrow{r}=2\overrightarrow{n} 因为n只是方向,n的大小是无关的

✔:这里我们假设n是单位向量:

\\ -\overrightarrow{I}+ \overrightarrow{r}=2\frac{\overrightarrow{I}\cdot \overrightarrow{n}}{||\overrightarrow{I}||\cdot ||\overrightarrow{n}||}\cdot ||\overrightarrow{I}||\cdot \overrightarrow{n} \\ \overrightarrow{I}-\overrightarrow{r}=2(\overrightarrow{I}\cdot \overrightarrow{n})\overrightarrow{n}

I的方向是入射方向,指向反射点,如图:

⑨反射点(对称点):

⑩反射矩阵:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值