コード例 #1
0
ファイル: TerrainQuad.cs プロジェクト: Climberfx/Scatterer
        /**
         * Subdivides or unsubdivides this quad based on the current
         * viewer distance to this quad, relatively to its size. This
         * method uses the current viewer position provided by the
         * TerrainNode to which this quadtree belongs.
         */
        public void Update()
        {
            Frustum.VISIBILTY v = (m_parent == null) ? Frustum.VISIBILTY.PARTIALLY : m_parent.GetVisible();

            if (v == Frustum.VISIBILTY.PARTIALLY) {
                m_visible = m_owner.GetVisibility(m_localBox);
            }
            else {
                m_visible = v;
            }

            // here we reuse the occlusion test from the previous frame:
            // if the quad was found unoccluded in the previous frame, we suppose it is
            // still unoccluded at this frame. If it was found occluded, we perform
            // an occlusion test to check if it is still occluded.
            if (m_visible != Frustum.VISIBILTY.INVISIBLE && m_occluded)
            {
                m_occluded = m_owner.IsOccluded(m_localBox);

                if(m_occluded) {
                    m_visible = Frustum.VISIBILTY.INVISIBLE;
                }
            }

            double ground = m_owner.GetView().GetGroundHeight();
            double dist = m_owner.GetCameraDist(new Box3d(m_ox, m_ox + m_length, m_oy, m_oy + m_length, Math.Min(0.0, ground), Math.Max(0.0, ground)));

            if ((m_owner.GetSplitInvisibleQuads() || m_visible != Frustum.VISIBILTY.INVISIBLE) && dist < m_length * m_owner.GetSplitDist() && m_level < m_owner.GetMaxLevel())
            {
                if (IsLeaf()) {
                    Subdivide();
                }

                int[] order = new int[4];
                double ox = m_owner.GetLocalCameraPos().x;
                double oy = m_owner.GetLocalCameraPos().y;
                double cx = m_ox + m_length / 2.0;
                double cy = m_oy + m_length / 2.0;

                if (oy < cy) {
                    if (ox < cx) {
                        order[0] = 0;
                        order[1] = 1;
                        order[2] = 2;
                        order[3] = 3;
                    } else {
                        order[0] = 1;
                        order[1] = 0;
                        order[2] = 3;
                        order[3] = 2;
                    }
                } else {
                    if (ox < cx) {
                        order[0] = 2;
                        order[1] = 0;
                        order[2] = 3;
                        order[3] = 1;
                    } else {
                        order[0] = 3;
                        order[1] = 1;
                        order[2] = 2;
                        order[3] = 0;
                    }
                }

                m_children[order[0]].Update();
                m_children[order[1]].Update();
                m_children[order[2]].Update();
                m_children[order[3]].Update();

                // we compute a more precise occlusion for the next frame (see above),
                // by combining the occlusion status of the child nodes
                m_occluded = (m_children[0].GetOccluded() && m_children[1].GetOccluded() && m_children[2].GetOccluded() && m_children[3].GetOccluded());
            }
            else
            {
                if (m_visible != Frustum.VISIBILTY.INVISIBLE) {
                    // we add the bounding box of this quad to the occluders list
                    m_occluded = m_owner.AddOccluder(m_localBox);
                    if (m_occluded) {
                        m_visible = Frustum.VISIBILTY.INVISIBLE;
                    }
                }

                if (!IsLeaf()) {
                    Release();
                }
            }
        }
コード例 #2
0
        public override Frustum.VISIBILTY GetVisibility(TerrainNode t, Box3d localBox)
        {
            Vector3d2[] deformedBox = new Vector3d2[4];
            deformedBox[0] = LocalToDeformed(new Vector3d2(localBox.xmin, localBox.ymin, localBox.zmin));
            deformedBox[1] = LocalToDeformed(new Vector3d2(localBox.xmax, localBox.ymin, localBox.zmin));
            deformedBox[2] = LocalToDeformed(new Vector3d2(localBox.xmax, localBox.ymax, localBox.zmin));
            deformedBox[3] = LocalToDeformed(new Vector3d2(localBox.xmin, localBox.ymax, localBox.zmin));

            double a  = (localBox.zmax + R) / (localBox.zmin + R);
            double dx = (localBox.xmax - localBox.xmin) / 2 * a;
            double dy = (localBox.ymax - localBox.ymin) / 2 * a;
            double dz = localBox.zmax + R;
            double f  = Math.Sqrt(dx * dx + dy * dy + dz * dz) / (localBox.zmin + R);

            Vector4d[] deformedFrustumPlanes = t.GetDeformedFrustumPlanes();

            Frustum.VISIBILTY v0 = GetVisibility(deformedFrustumPlanes[0], deformedBox, f);
            if (v0 == Frustum.VISIBILTY.INVISIBLE)
            {
                return(Frustum.VISIBILTY.INVISIBLE);
            }

            Frustum.VISIBILTY v1 = GetVisibility(deformedFrustumPlanes[1], deformedBox, f);
            if (v1 == Frustum.VISIBILTY.INVISIBLE)
            {
                return(Frustum.VISIBILTY.INVISIBLE);
            }

            Frustum.VISIBILTY v2 = GetVisibility(deformedFrustumPlanes[2], deformedBox, f);
            if (v2 == Frustum.VISIBILTY.INVISIBLE)
            {
                return(Frustum.VISIBILTY.INVISIBLE);
            }

            Frustum.VISIBILTY v3 = GetVisibility(deformedFrustumPlanes[3], deformedBox, f);
            if (v3 == Frustum.VISIBILTY.INVISIBLE)
            {
                return(Frustum.VISIBILTY.INVISIBLE);
            }

            Frustum.VISIBILTY v4 = GetVisibility(deformedFrustumPlanes[4], deformedBox, f);
            if (v4 == Frustum.VISIBILTY.INVISIBLE)
            {
                return(Frustum.VISIBILTY.INVISIBLE);
            }

            Vector3d2 c        = t.GetDeformedCameraPos();
            double    lSq      = c.SqrMagnitude();
            double    rm       = R + Math.Min(0.0, localBox.zmin);
            double    rM       = R + localBox.zmax;
            double    rmSq     = rm * rm;
            double    rMSq     = rM * rM;
            Vector4d  farPlane = new Vector4d(c.x, c.y, c.z, Math.Sqrt((lSq - rmSq) * (rMSq - rmSq)) - rmSq);

            Frustum.VISIBILTY v5 = GetVisibility(farPlane, deformedBox, f);
            if (v5 == Frustum.VISIBILTY.INVISIBLE)
            {
                return(Frustum.VISIBILTY.INVISIBLE);
            }

            if (v0 == Frustum.VISIBILTY.FULLY && v1 == Frustum.VISIBILTY.FULLY &&
                v2 == Frustum.VISIBILTY.FULLY && v3 == Frustum.VISIBILTY.FULLY &&
                v4 == Frustum.VISIBILTY.FULLY && v5 == Frustum.VISIBILTY.FULLY)
            {
                return(Frustum.VISIBILTY.FULLY);
            }
            return(Frustum.VISIBILTY.PARTIALLY);
        }
コード例 #3
0
        /*
         * Subdivides or unsubdivides this quad based on the current
         * viewer distance to this quad, relatively to its size. This
         * method uses the current viewer position provided by the
         * TerrainNode to which this quadtree belongs.
         */
        public void Update()
        {
            Frustum.VISIBILTY v = (m_parent == null) ? Frustum.VISIBILTY.PARTIALLY : m_parent.GetVisible();

            if (v == Frustum.VISIBILTY.PARTIALLY)
            {
                m_visible = m_owner.GetVisibility(m_localBox);
            }
            else
            {
                m_visible = v;
            }

            // here we reuse the occlusion test from the previous frame:
            // if the quad was found unoccluded in the previous frame, we suppose it is
            // still unoccluded at this frame. If it was found occluded, we perform
            // an occlusion test to check if it is still occluded.
            if (m_visible != Frustum.VISIBILTY.INVISIBLE && m_occluded)
            {
                m_occluded = m_owner.IsOccluded(m_localBox);

                if (m_occluded)
                {
                    m_visible = Frustum.VISIBILTY.INVISIBLE;
                }
            }

            double ground = m_owner.GetView().GetGroundHeight();
            double dist   = m_owner.GetCameraDist(new Box3d(m_ox, m_ox + m_length, m_oy, m_oy + m_length, Math.Min(0.0, ground), Math.Max(0.0, ground)));

            if ((m_owner.GetSplitInvisibleQuads() || m_visible != Frustum.VISIBILTY.INVISIBLE) && dist < m_length * m_owner.GetSplitDist() && m_level < m_owner.GetMaxLevel())
            {
                if (IsLeaf())
                {
                    Subdivide();
                }

                int[]  order = new int[4];
                double ox    = m_owner.GetLocalCameraPos().x;
                double oy    = m_owner.GetLocalCameraPos().y;
                double cx    = m_ox + m_length / 2.0;
                double cy    = m_oy + m_length / 2.0;

                if (oy < cy)
                {
                    if (ox < cx)
                    {
                        order[0] = 0;
                        order[1] = 1;
                        order[2] = 2;
                        order[3] = 3;
                    }
                    else
                    {
                        order[0] = 1;
                        order[1] = 0;
                        order[2] = 3;
                        order[3] = 2;
                    }
                }
                else
                {
                    if (ox < cx)
                    {
                        order[0] = 2;
                        order[1] = 0;
                        order[2] = 3;
                        order[3] = 1;
                    }
                    else
                    {
                        order[0] = 3;
                        order[1] = 1;
                        order[2] = 2;
                        order[3] = 0;
                    }
                }

                m_children[order[0]].Update();
                m_children[order[1]].Update();
                m_children[order[2]].Update();
                m_children[order[3]].Update();

                // we compute a more precise occlusion for the next frame (see above),
                // by combining the occlusion status of the child nodes
                m_occluded = (m_children[0].GetOccluded() && m_children[1].GetOccluded() && m_children[2].GetOccluded() && m_children[3].GetOccluded());
            }
            else
            {
                if (m_visible != Frustum.VISIBILTY.INVISIBLE)
                {
                    // we add the bounding box of this quad to the occluders list
                    m_occluded = m_owner.AddOccluder(m_localBox);
                    if (m_occluded)
                    {
                        m_visible = Frustum.VISIBILTY.INVISIBLE;
                    }
                }

                if (!IsLeaf())
                {
                    Release();
                }
            }
        }