我遇到了一些与我进行截头剔除的问题有关的问题。目前的方法确实在剔除时解决,但有一个非常奇怪的效果。当我太靠近我的主要父对象时,我使用场景图来渲染所有东西,对象开始快速闪烁。当我离开时,这已经消失了。我已经尝试了很多东西,但已经没有想法了。你们有什么想法吗?非常感谢任何帮助。
我首先创建一个由我的模型周围的八个点组成的边界框。据我所知,经过大量测试后,这些都是正确的。
这是我计算平截头体平面点的方法。 相机位置是世界空间中的位置,方向是它所看到的方向。此外,每次旋转相机时都会计算cameraUp和cameraRight。
Vector3 pos = Camera.staticPosition;
Vector3 view = Camera.staticOrientation;
Vector3 upVector3 = Camera.cameraUp;
Vector3 rightVector3 = Camera.cameraRight;
float toRadians = (float)Math.PI / 180.0f;
float nearDis = .1f;
float farDistance = 1000f;
float fov = Game.FOV;
float aspectRatio = 1.3f;
//Get with and height of near and far plane
float tanDiv = 2 * (float) Math.Tan(fov*toRadians / 2);
float heightNear = tanDiv * nearDis;
float widthNear = heightNear * aspectRatio;
float heightFar = tanDiv * farDistance;
float widthFar = heightFar * aspectRatio;
// get the centre points of the planes so they can be used to calculate the edge points
Vector3 centreNear = pos + view * nearDis;
Vector3 centreFar = pos + view * farDistance;
// get the halfht values of the width and hegiht to make sure you can get the points
float hNearHalf = heightNear / 2;
float wNearHalf = widthNear / 2;
float hFarHalf = heightFar / 2;
float wFarHalf = widthFar / 2;
Vector3 nearTopLeft = centreNear + (upVector3 * hNearHalf) - (rightVector3 * wNearHalf);
Vector3 nearTopRight = centreNear + (upVector3 * hNearHalf) + (rightVector3 * wNearHalf);
Vector3 nearBottomLeft = centreNear - (upVector3 * hNearHalf) - (rightVector3 * wNearHalf);
Vector3 nearBottomRight = centreNear - (upVector3 * hNearHalf) + (rightVector3 * wNearHalf);
Vector3 farTopLeft = centreFar + (upVector3 * hFarHalf) - (rightVector3 * wFarHalf);
Vector3 farTopRight = centreFar + (upVector3 * hFarHalf) + (rightVector3 * wFarHalf);
Vector3 farBotomLeft = centreFar - (upVector3 * hFarHalf) - (rightVector3 * wFarHalf);
Vector3 farBottomRight = centreFar - (upVector3 * hFarHalf) + (rightVector3 * wFarHalf);
我将平截头体积存在一个数组中。首先是近平面点,然后是飞机,topplane,bottomplane,左翼,最后是右翼。然后我遍历所有六个平面和边界框的8个点,如果该点位于平面的右侧,则增加字典中该键的值。
Vector3[] frustumPoints = new Vector3[18]
{
nearTopLeft, nearTopRight, nearBottomLeft, farTopLeft, farTopRight, farBotomLeft, nearTopLeft, farTopLeft,
nearTopRight, nearBottomLeft, farBotomLeft, nearBottomRight, nearTopLeft, nearBottomLeft, farTopLeft,
nearTopRight, nearBottomRight, farTopRight
};
Dictionary<Vector3, int> count = new Dictionary<Vector3, int>(8);
for (int value = 0; value < 8; value++)
{
count.Add(cubePositions[value], 0);
}
for (int x = 0; x < 18; x += 3)
{
Vector3 normal = NormalPlane(frustumPoints[x], frustumPoints[x + 1], frustumPoints[x + 2]);
for (int y = 0; y < 8; y++)
{
Vector3 pointPlane = frustumPoints[x] - cubePositions[y];
float dot = Vector3.Dot(pointPlane, normal);
if (dot <= 0 && x % 6 == 0)
{
count[cubePositions[y]]++;
}
else if (dot >= 0 && x % 3 == 0)
{
count[cubePositions[y]]++;
}
}
}
这是我获取飞机法线的方法
Vector3 NormalPlane(Vector3 pointOne, Vector3 pointTwo, Vector3 pointThree)
{
Vector3 normal;
Vector3 edgeOne = pointTwo - pointOne; // calculate vector from point one to point two
Vector3 edgeTwo = pointThree - pointOne; // calculate vector from point one to point three
normal = Vector3.Normalize(Vector3.Cross(edgeOne, edgeTwo)); // calculate the cross product of the two given vectors. Then normalize it so you have normal of plane
return normal; // return the normal
}
如果对于立方体上的这些点之一,计数为6,则点在所有平面内,因此截锥体和我绘制对象。如果这些点都不等于6,则不会绘制对象。
问题是我不知道我在哪里犯了错误所以你们有什么想法吗?
提前致谢,
Jeromer
答案 0 :(得分:2)
如果对于立方体上的这些点之一,计数为6,则点在所有平面内,因此截锥体和我绘制对象。如果这些点都不等于6,则不会绘制对象。
这里的逻辑似乎是
然而。这只是错误。即使立方体的所有8个顶点都位于平截头体之外,立方体仍然可以与平截头体相交,如2D草图中所示:
*----------*
| |
+-----------------+--+ |
\ | / |
\ |/ |
\ / |
\ /| |
\ / *----------*
\ /
\ /
+----+
因此,你剔除可能可见的东西。
截头剔除的通常逻辑是,只有当所有顶点被同一平面拒绝时才剔除该框。 (这会导致一些奇怪的情况,即盒子完全在外面而不是剔除,但这些情况不太可能,通常也不用担心。)