Пример #1
0
    private void Build()
    {
        var triangles = _bvhData.scene.triangles;
        var vetices   = _bvhData.scene.vertices;

        var rootSpec = NodeSpec.New();

        rootSpec.numRef = triangles.Count;

        // 遍历所有图元(引用),计算根节点的包围盒
        for (int i = 0; i < rootSpec.numRef; i++)
        {
            var pRef = PrimitiveRef.New();
            pRef.triangleIdx = i;

            // 计算单个图元的包围盒
            for (int j = 0; j < 3; j++)
            {
                pRef.bounds.Union(vetices[triangles[i][j]]);
            }

            rootSpec.bounds.Union(pRef.bounds);

            _refStack.Add(pRef);
        }

        // 最小重叠面积,只有重叠面积大于这个值时才考虑进行spatial split
        _minOverlap = rootSpec.bounds.Area * SPLIT_ALPHA;

        // 递归创建BVH
        _bvhData.root = BuildNodeRecursively(rootSpec, 0);
        Debug.Log("Build Completely.");
    }
Пример #2
0
    private void SplitReference(out PrimitiveRef leftRef, out PrimitiveRef rightRef, PrimitiveRef curRef, int dim, float pos)
    {
        leftRef             = rightRef = PrimitiveRef.New();
        leftRef.triangleIdx = rightRef.triangleIdx = curRef.triangleIdx;

        var triangle = _bvhData.scene.triangles[curRef.triangleIdx];
        var vertices = _bvhData.scene.vertices;

        // 遍历三角形的三条边01,12,20,然后将顶点与分割平面组成包围盒
        for (byte i = 0; i < 3; i++)
        {
            var   v0  = vertices[triangle[i]];
            var   v1  = vertices[triangle[i + 1 == 3 ? 0 : i + 1]];
            float v0p = v0[dim];
            float v1p = v1[dim];

            if (v0p <= pos)
            {
                leftRef.bounds.Union(v0);
            }
            if (v0p >= pos)
            {
                rightRef.bounds.Union(v0);
            }

            // 求得分割平面与三角形的交点,且算进左右两边的包围盒
            if ((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos))
            {
                Vector3 t = Vector3.Lerp(v0, v1, Mathf.Clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
                leftRef.bounds.Union(t);
                rightRef.bounds.Union(t);
            }
        }

        leftRef.bounds.max[dim]  = pos;
        rightRef.bounds.min[dim] = pos;
        // 上面得到的是图元(三角形)被分割后左右两边的包围盒,但我们希望得到的包围盒除此之外,还应该限制在分割平面左右两个bin中
        leftRef.bounds.Intersect(curRef.bounds);
        rightRef.bounds.Intersect(curRef.bounds);
    }