平面與網(wǎng)格相交
計算截面與三角形網(wǎng)格的相交可以分解為三角形面與平面的相交瀑粥。而三角形面與平面的相交又可以分解為線段與平面的相交竭宰,那么現(xiàn)在問題就變?yōu)榱?strong>線段與平面相交的計算。
直線–平面相交
在3D中留量,直線 L或者平行于平面π或者與平面π相交于一點吼具。
描述L的函數(shù)是 $L = P(s) = P_0 + s(P_1-P_0) = P_0 + su$
描述平面π可以用平面上一點$V_0$和法線n表示
是否平行
如果直線與平面平行,則直線與平面不交
u表示直線的法線从橘,如果$n·u=0$念赶,那就意味著直線法向量 u垂直于平面法向量n。如果成立恰力,直線 L和平面π平行叉谜,即或者不相交,或者完全在平面p內(nèi)踩萎。通過驗證L上是否存在點P在平面π內(nèi)停局,可以判斷L和平面π是否相交,也就是說是否滿足隱式直線方程:$n·(P-V_0) = 0$香府。
直線與平面相較于平面內(nèi)一點
如果直線和平面不平行董栽,即直線L和平面π相交于點$P(s_I)$,利用類似于2D中兩條直線相交的方法企孩,我們可以計算出點P(sI)的值锭碳。如圖所示:

在相交點,當$w=P_0-V_0$勿璃,向量$P(s)-V_0 = w+su$垂直于n擒抛。這等同于點乘:$n · (w+su) = 0$推汽。求解得出:
$$s_I=\frac{-n \cdot w}{n\cdot u} = \frac{n \cdot (V_0-P0)}{n \cdot(P_1 - P_0)} $$
線段-直線相交
如果L 是從$P_0$到$P_1$的有限線段,我們必須檢查sI是否滿足 $0<= s_I <=1$歧沪,從而證明線段和平面是否相交歹撒。對于正方向的射線,當$s_I >=0$時诊胞,和平面相交暖夭。
而交點的坐標就等于$P(s_I ) = P_0 + s_I (P_1-P_0) = P_0 + s_I u$
需要處理的特殊情況是$n·(P_1-P_0) = 0$時,即線段與平面平行厢钧,這時由于除數(shù)為0不能計算鳞尔,只需要判斷P1在平面內(nèi)即可(計算平面方程$n·(V_0 - P_0) = 0$)
float lineCrossFace(glm::vec3& point0,glm::vec3& point1,glm::vec3& v0,glm::vec3& normals)
{
glm::vec3 ver = point1 - point0;
float norDotVer = glm::dot(normals,ver);
if (norDotVer == 0)
{
if (glm::dot(normals,(v0 - point1)) == 0)
{
return 1;
}
return -1;
}
float scale = (glm::dot(normals,(v0 - point0)))/norDotVer;
return scale;
}
平面與網(wǎng)格相交實現(xiàn)
有了lineCrossFace,函數(shù)計算線段與平面相交,現(xiàn)在只需要將網(wǎng)格的每一條邊作為一個線段遍歷和平面求交就完成了早直。
std::vector<glm::vec3> sectionLine(std::vector<glm::vec4>& vertex,
std::vector<glm::ivec3>& indexArray,
glm::vec3& normal, glm::vec3& surfacePoint)
{
std::vector<glm::vec3> sectionLine;
normal = glm::normalize(normal);
int crossPointIndex = 0;
glm::vec3 curCrossVec[2];
for (auto index : indexArray)
{
if (crossPointIndex == 2)
{
glm::vec3 point0 = curCrossVec[0];
glm::vec3 point1 = curCrossVec[1];
sectionLine.push_back(point0);
sectionLine.push_back(point1);
}
crossPointIndex = 0;
for (int lineIndex = 0;lineIndex < 3;lineIndex++)
{
float scale = lineCrossFace(vertex[index[lineIndex]],
vertex[index[(lineIndex+1)%3]],
surfacePoint,normal);
if (scale <= 1 && scale > 0)
{
curCrossVec[crossPointIndex] = scale * (vertex[index[(lineIndex+1)%3]] -
vertex[index[lineIndex]]) + vertex[index[lineIndex]];
++crossPointIndex;
}
else if (scale == 0)
{
curCrossVec[crossPointIndex] = vertex[index[lineIndex]];
++crossPointIndex;
}
if ( crossPointIndex > 1)
break;
}
}
return sectionLine;
}