当前的胶合扣效应导致Opentk闪烁的对象

  • 本文关键字:Opentk 闪烁 对象 c# opengl opentk
  • 更新时间 :
  • 英文 :


我对我的flustum culling的方式有一些问题。当前的方法确实可以在淘汰中解决,但确实有一个奇怪的效果。当我离我的主要父对象太近时,我正在使用场景图来渲染所有内容,这些对象开始非常快速地闪烁。当我离开时,这消失了。我尝试了很多事情,但没有想法了。你们有任何想法吗?任何帮助都非常感谢。

我首先创建一个由模型周围的八个点组成的边界箱。据我所知,这些测试是正确的。

这是我计算冰果平面点的方式。相机位置是世界空间中的位置,方向是它正在寻找的方向。每次旋转相机时,都会计算相机和照相机。

    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);

我将我的frustum点存储在阵列中。首先,近平面点,然后是偏面,桌面,底部平面,左平台,最后是右平台。然后,如果该点位于平面的右侧,则循环遍历所有六个平面和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 
}

如果对于立方体上的这些点之一,计数为六个,则这些点位于所有平面内,因此frustum和我绘制对象。如果这些点都不等于6,则对象未得到绘制。

问题我不知道我在哪里犯错,所以你们有任何想法吗?

预先感谢

Jeromer

如果对于立方体上的这些点之一,计数为六个,则这些点位于所有平面内,因此frustum和我绘制对象。如果这些点都不等于6,则对象未得到绘制。

您的逻辑似乎是

  • "如果没有位于frustum内部的立方体顶点,则立方体不可见。"

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

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

因此,您挖出了可能可见的东西。

flustum culling的通常逻辑是仅在同一平面拒绝其所有顶点拒绝其所有顶点时才能剔除框。(这将导致一些奇怪的情况,盒子完全在外面而不被淘汰,但是这些情况很可能很可能,通常不必担心。(

最新更新