gpt4 book ai didi

c# - 当前的截锥体剔除效果导致 openTk 中的对象闪烁

转载 作者:行者123 更新时间:2023-11-30 21:40:17 25 4
gpt4 key购买 nike

我在进行视锥体剔除的方式上遇到了一些问题。当前的方法确实解决了剔除问题,但效果确实很奇怪。当我离我的主要父对象太近时,我正在使用场景图来渲染所有内容,对象开始非常快速地闪烁。当我离开时,它就消失了。我尝试了很多东西,但再也没有想法了。你们有什么想法吗?非常感谢任何帮助。

我首先在我的模型周围创建一个由八个点组成的边界框。据我所知,经过大量测试,这些都是正确的。

这是我计算截锥平面点的方法。相机位置是世界空间中的位置,方向是它正在看的方向。此外,每次旋转相机时都会计算 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);

我将平截头体点存储在一个数组中。首先是近平面点,然后是远平面、顶平面、底平面、左平面,最后是右平面。然后我遍历所有六个平面和 boundinbox 的 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,则不会绘制对象。

问题是我不知道我在哪里犯了错误所以你们有什么想法吗?

提前致谢

杰罗默

最佳答案

If for one of these points on the cube the count is six, the points is within all planes and thus the frustum and I draw the object. If none of the points is equal to 6 the objects don't get drawn.

你这里的逻辑好像是

  • “如果立方体的顶点不在截锥体内,则立方体不可见。”

但是。这是错误的。即使立方体的所有 8 个顶点都位于平截头体之外,立方体仍然可以与平截头体相交,如这个 2D 草图所示:

                  *----------*
| |
+-----------------+--+ |
\ | / |
\ |/ |
\ / |
\ /| |
\ / *----------*
\ /
\ /
+----+

因此,您剔除了可能可见的内容。

截头体剔除的通常逻辑是只有当所有顶点都被同一平面拒绝时才剔除该框。 (这会导致一些奇怪的情况,即盒子完全在外面并且没有被剔除,但这些情况不太可能发生,通常也没什么大不了的。)

关于c# - 当前的截锥体剔除效果导致 openTk 中的对象闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44735084/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com