cesium中每个模型在渲染之前都要进行可见性检测,包括模型是否在地球背面,是否在裁切面中,是否在视锥中。
下面的代码是在视锥中的可见性判断:
AxisAlignedBoundingBox.intersectPlane = function (box, plane) {
//>>includeStart('debug', pragmas.debug);
Check.defined("box", box);
Check.defined("plane", plane);
//>>includeEnd('debug');
// 对角线
intersectScratch = Cartesian3.subtract(
box.maximum,
box.minimum,
intersectScratch
);
// 对角线的一半向量
const h = Cartesian3.multiplyByScalar(
intersectScratch,
0.5,
intersectScratch
); //The positive half diagonal
// 面法线
const normal = plane.normal;
// 点乘
const e =
h.x * Math.abs(normal.x) +
h.y * Math.abs(normal.y) +
h.z * Math.abs(normal.z);
//
const s = Cartesian3.dot(box.center, normal) + plane.distance; //signed distance from center
// 完全在内部
if (s - e > 0) {
return Intersect.INSIDE;
}
// 完全在外部
if (s + e < 0) {
//Not in front because normals point inward
return Intersect.OUTSIDE;
}
// 交叉了
return Intersect.INTERSECTING;
};
大概过程如下:
1、视锥分为6个面,每个面使用到原点距离、法线构成。
2、检测模型包围盒与视锥面的位置关系,在法线的一侧,与视锥面相交,还是与视锥面相交。
其中const s = Cartesian3.dot(box.center, normal) + plane.distance;的计算过程,这个过程分为3中情况:
1、是box的中心点在法线上的投影,如果投影为正,则在box在法线同侧,s - e > 0
2、如果投影为负数,则中心点在法线的另一侧,
3、虽然在另一侧但是box是一个区域,还有交叉的情况存在,所以s + e < 0则box不与视锥面相交,否则就是相交。
这里有一段代码是计算box对角线向量与法线分量都为正的情况,原因是只要中心点在法线的背面,那总会有一个box的顶点与中心点的差向量与裁切面法线方向同向,而这个方向在平面法相法相上的投影值与将他们都挪到原点后的投影值大小相同,故使用绝对值进行计算。