예제 #1
0
        /*
         * Sets the shader uniforms that are necessary to project on screen the
         * given TerrainQuad. This method can set the uniforms that are specific to
         * the given quad.
         */
        public virtual void SetUniforms(TerrainNode node, TerrainQuad quad, MaterialPropertyBlock matPropertyBlock)
        {
            if (matPropertyBlock == null || node == null || quad == null)
            {
                return;
            }

            double ox         = quad.GetOX();
            double oy         = quad.GetOY();
            double l          = quad.GetLength();
            double distFactor = (double)node.GetDistFactor();
            int    level      = quad.GetLevel();

            matPropertyBlock.AddVector(m_uniforms.offset, new Vector4((float)ox, (float)oy, (float)l, (float)level));

            Vector3d2 camera = node.GetLocalCameraPos();

            matPropertyBlock.AddVector(m_uniforms.camera, new Vector4((float)((camera.x - ox) / l), (float)((camera.y - oy) / l),
                                                                      (float)((camera.z - node.GetView().GetGroundHeight()) / (l * distFactor)),
                                                                      (float)camera.z));

            Vector3d2 c = node.GetLocalCameraPos();

            Matrix3x3d m = m_localToTangent * (new Matrix3x3d(l, 0.0, ox - c.x, 0.0, l, oy - c.y, 0.0, 0.0, 1.0));

            matPropertyBlock.AddMatrix(m_uniforms.tileToTangent, m.ToMatrix4x4());

            SetScreenUniforms(node, quad, matPropertyBlock);
        }
예제 #2
0
        /*
         * Sets the shader uniforms that are necessary to project on screen the
         * TerrainQuad of the given TerrainNode. This method can set the uniforms
         * that are common to all the quads of the given terrain.
         */
        public virtual void SetUniforms(TerrainNode node, Material mat)
        {
            if (mat == null || node == null)
            {
                return;
            }

            float d1 = node.GetSplitDist() + 1.0f;
            float d2 = 2.0f * node.GetSplitDist();

            mat.SetVector(m_uniforms.blending, new Vector2(d1, d2 - d1));

            m_localToCamera = node.GetView().GetWorldToCamera() * node.GetLocalToWorld();
            m_localToScreen = node.GetView().GetCameraToScreen() * m_localToCamera;

            Vector3d2 localCameraPos = node.GetLocalCameraPos();
            Vector3d2 worldCamera    = node.GetView().GetWorldCameraPos();

            Matrix4x4d A = LocalToDeformedDifferential(localCameraPos);
            Matrix4x4d B = DeformedToTangentFrame(worldCamera);

            Matrix4x4d ltot = B * node.GetLocalToWorld() * A;

            m_localToTangent = new Matrix3x3d(ltot.m[0, 0], ltot.m[0, 1], ltot.m[0, 3],
                                              ltot.m[1, 0], ltot.m[1, 1], ltot.m[1, 3],
                                              ltot.m[3, 0], ltot.m[3, 1], ltot.m[3, 3]);

            mat.SetMatrix(m_uniforms.localToScreen, m_localToScreen.ToMatrix4x4());
            mat.SetMatrix(m_uniforms.localToWorld, node.GetLocalToWorld().ToMatrix4x4());
        }
예제 #3
0
        /**
        * Sets the shader uniforms that are necessary to project on screen the
        * given TerrainQuad. This method can set the uniforms that are specific to
        * the given quad.
        */
        public virtual void SetUniforms(TerrainNode node, TerrainQuad quad, MaterialPropertyBlock matPropertyBlock)
        {
            if(matPropertyBlock == null || node == null || quad == null) return;

            double ox = quad.GetOX();
            double oy = quad.GetOY();
            double l = quad.GetLength();
            double distFactor = (double)node.GetDistFactor();
            int level = quad.GetLevel();

            matPropertyBlock.AddVector(m_uniforms.offset, new Vector4((float)ox, (float)oy, (float)l, (float)level));

            Vector3d2 camera = node.GetLocalCameraPos();

            matPropertyBlock.AddVector(m_uniforms.camera, new Vector4(	(float)((camera.x - ox) / l), (float)((camera.y - oy) / l),
                                                                      (float)((camera.z - node.GetView().GetGroundHeight()) / (l * distFactor)),
                                                                      (float)camera.z));

            Vector3d2 c = node.GetLocalCameraPos();

            Matrix3x3d m = m_localToTangent * (new Matrix3x3d(l, 0.0, ox - c.x, 0.0, l, oy - c.y, 0.0, 0.0, 1.0));

            matPropertyBlock.AddMatrix(m_uniforms.tileToTangent, m.ToMatrix4x4());

            SetScreenUniforms(node, quad, matPropertyBlock);
        }
예제 #4
0
        /**
        * Sets the shader uniforms that are necessary to project on screen the
        * TerrainQuad of the given TerrainNode. This method can set the uniforms
        * that are common to all the quads of the given terrain.
        */
        public virtual void SetUniforms(TerrainNode node, Material mat)
        {
            if(mat == null || node == null) return;

            float d1 = node.GetSplitDist() + 1.0f;
            float d2 = 2.0f * node.GetSplitDist();
            mat.SetVector(m_uniforms.blending, new Vector2(d1, d2 - d1));

            m_localToCamera = node.GetView().GetWorldToCamera() * node.GetLocalToWorld();
            m_localToScreen = node.GetView().GetCameraToScreen() * m_localToCamera;

            Vector3d2 localCameraPos = node.GetLocalCameraPos();
            Vector3d2 worldCamera = node.GetView().GetWorldCameraPos();

            Matrix4x4d A = LocalToDeformedDifferential(localCameraPos);
            Matrix4x4d B = DeformedToTangentFrame(worldCamera);

            Matrix4x4d ltot = B * node.GetLocalToWorld() * A;

            m_localToTangent = new Matrix3x3d(	ltot.m[0,0], ltot.m[0,1], ltot.m[0,3],
                                              ltot.m[1,0], ltot.m[1,1], ltot.m[1,3],
                                              ltot.m[3,0], ltot.m[3,1], ltot.m[3,3]);

            mat.SetMatrix(m_uniforms.localToScreen, m_localToScreen.ToMatrix4x4());
            mat.SetMatrix(m_uniforms.localToWorld, node.GetLocalToWorld().ToMatrix4x4());
        }
예제 #5
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();
                }
            }
        }