예제 #1
0
            /// <summary>
            /// Test for visibility, return true if VISIBLE and cache result.
            /// </summary>
            /// <param name="camera"></param>
            /// <returns></returns>
            public bool CullTest(Camera camera)
            {
                Culled = true;
                if (renderables.Count > 0)
                {
                    Frustum.CullResult cull = camera.Frustum.CullTest(Bounds);
                    if (cull != Frustum.CullResult.TotallyOutside)
                    {
                        Culled = false;

                        Debug.Assert(_disposes.Count == 0);
                        Dictionary <byte, Renderable> .ValueCollection values = renderables.Values;
                        foreach (Renderable renderable in values)
                        {
                            if (!renderable.CullTest(camera))
                            {
                                _disposes.Add(renderable.Label);
                            }
                        }

                        foreach (byte label in _disposes)
                        {
                            Dispose(label);
                        }
                        _disposes.Clear();
                    }
                }
                return(!Culled);
            }
예제 #2
0
 public void CullCheck(Camera camera)
 {
     if (Bounds == null)
     {
         Culled = true;
     }
     else
     {
         Frustum.CullResult cull = camera.Frustum.CullTest(Bounds);
         Culled = cull == Frustum.CullResult.TotallyOutside;
         if (!Culled)
         {
             Dictionary <ushort, Renderable> .ValueCollection values = renderableDict.Values;
             if (cull == Frustum.CullResult.TotallyInside)
             {
                 foreach (Renderable r in values)
                 {
                     r.Culled = false;
                 }
             }
             else
             {
                 foreach (Renderable r in values)
                 {
                     cull     = camera.Frustum.CullTest(r.Bounds);
                     r.Culled = cull == Frustum.CullResult.TotallyOutside;
                 }
             }
         }
     }
     //Culled = false; // Debug hack to disable all culling, to separate fill from drawprim overhead
 }
예제 #3
0
            /// <summary>
            /// Hierarchical cull check, with result cached. This is just
            /// so we don't have to recheck for each face pass.
            /// </summary>
            /// <param name="camera"></param>
            /// <param name="nodes"></param>
            /// <returns></returns>
            public Frustum.CullResult PreCull(Camera camera, List <Node> nodes)
            {
#if MF_HOLDFRUSTUM
                GamePadInput pad = GamePadInput.GetGamePad0();
                if (pad.ButtonY.IsPressed)
                {
                    _holdFrustum = camera.Frustum.Clone();
                }
                else if (pad.ButtonX.IsPressed)
                {
                    _holdFrustum = null;
                }
                Frustum frustum = _holdFrustum == null ? camera.Frustum : _holdFrustum;
#else // MF_HOLDFRUSTUM
                Frustum frustum = camera.Frustum;
#endif // MF_HOLDFRUSTUM

                Cull = frustum.CullTest(Min, Max);

                if (Cull == Frustum.CullResult.PartiallyInside)
                {
                    if (Left >= 0)
                    {
                        Debug.Assert(Right >= 0);
                        nodes[Left].PreCull(camera, nodes);
                        nodes[Right].PreCull(camera, nodes);
                    }
                }
                return(Cull);
            }
예제 #4
0
            /// <summary>
            /// Render this batch of geometry. No renderstate setup, just throw triangles at the card.
            /// </summary>
            /// <param name="camera"></param>
            public void Render(Camera camera)
            {
#if MF_RENDERSOLO
                Frustum.CullResult cull = camera.Frustum.CullTest(Bounds);
                if (cull != Frustum.CullResult.TotallyOutside)
#endif // !MF_RENDERSOLO
                {
                    GraphicsDevice device = BokuGame.bokuGame.GraphicsDevice;

                    device.SetVertexBuffer(data.Buffer);

#if MF_KEYHACK
                    if (!KeyboardInput.IsPressed(Keys.M) ||
                        !keyState.IsKeyDown(Keys.N))
                    {
#endif // MF_KEYHACK

                    device.DrawIndexedPrimitives(PrimitiveType.TriangleList,
                                                 0, 0, NumVerts,
                                                 0, NumTris);

#if MF_KEYHACK
                }
#endif // MF_KEYHACK
                }
            }
예제 #5
0
 /// <summary>
 /// Set up a leaf node.
 /// </summary>
 /// <param name="batch"></param>
 /// <param name="bounds"></param>
 public Node(Int16 batch, AABB bounds)
 {
     this.Left  = -1;
     this.Right = -1;
     this.Batch = batch;
     this.Min   = bounds.Min;
     this.Max   = bounds.Max;
     this.Cull  = Frustum.CullResult.TotallyInside;
 }
예제 #6
0
 /// <summary>
 /// Set up an interior node.
 /// </summary>
 /// <param name="left"></param>
 /// <param name="right"></param>
 /// <param name="bounds"></param>
 public Node(Int16 left, Int16 right, AABB bounds)
 {
     this.Left  = left;
     this.Right = right;
     this.Batch = -1;
     this.Min   = bounds.Min;
     this.Max   = bounds.Max;
     this.Cull  = Frustum.CullResult.TotallyInside;
 }
예제 #7
0
 /// <summary>
 /// Render this section of road/wall
 /// </summary>
 /// <param name="camera"></param>
 public void Render(Camera camera)
 {
     if (RenderObj != null)
     {
         Frustum.CullResult cull = camera.Frustum.CullTest(Sphere);
         if (cull != Frustum.CullResult.TotallyOutside)
         {
             RenderObj.Render(camera, Road);
         }
     }
 }
예제 #8
0
 /// <summary>
 /// Render this intersection of road/wall
 /// </summary>
 /// <param name="camera"></param>
 public void Render(Camera camera)
 {
     Frustum.CullResult cull = camera.Frustum.CullTest(Sphere);
     if (cull != Frustum.CullResult.TotallyOutside)
     {
         foreach (RenderObj fan in Fans)
         {
             fan.Render(camera, Road);
         }
     }
 }
예제 #9
0
                /// <summary>
                /// Test for visibility, return true if VISIBLE and cache result.
                /// </summary>
                /// <param name="camera"></param>
                /// <returns></returns>
                public bool CullTest(Camera camera)
                {
                    Water water = Water.FromLabel(Label);

                    if (water != null)
                    {
                        Bounds.MaxZ = water.BaseHeight;
                        Frustum.CullResult cull = camera.Frustum.CullTest(Bounds);
                        Culled = (cull == Frustum.CullResult.TotallyOutside);

                        return(true);
                    }

                    return(false);
                }
예제 #10
0
        }   // end of RenderObj c'tor

        public override void Render(Camera camera)
        {
            if (!parent.Visible)
            {
                return;
            }

            Frustum.CullResult cull = camera.Frustum.CullTest(parent.BoundingSphere.Center + parent.Movement.Position, parent.BoundingSphere.Radius);
            if (cull != Frustum.CullResult.TotallyOutside)
            {
                sro.PreRender   = parent.PreRender;
                sro.Animators   = parent.Animators;
                sro.RenderColor = parent.Classification.ColorRGBA;
                GameActor parentActor = parent as GameActor;
                if (parentActor != null)
                {
                    sro.GlowEmissiveColor = parentActor.GlowEmissivity * parentActor.GlowColor;
                }

                Matrix local = Matrix.CreateScale(parent.ReScale) * parent.Movement.LocalMatrix;

                // Add in squashed transform if appropriate.
                if (parentActor.SquashScale != Vector3.One)
                {
                    if (parent.CurrentState == GameThing.State.Squashed && false)
                    {
                        // Translate down to the ground.
                        // TODO (****) should probably make this happen smoothly.
                        float terrainHeight = Boku.SimWorld.Terra.Terrain.GetHeight(parent.Movement.Position);
                        if (terrainHeight > 0)
                        {
                            Vector3 translation = local.Translation;
                            translation.Z            = terrainHeight;
                            local.Translation        = translation;
                            parent.Movement.Altitude = translation.Z;
                        }
                    }
                    local = Matrix.CreateScale(parentActor.SquashScale) * local;
                }

                sro.Render(camera, ref local, null);

                sro.PreRender = null;

                parent.DebugDisplay(camera);
            }
        }
 public void Render(Camera camera, Road road)
 {
     if (Model != null)
     {
         BoundingSphere bound = Model.BoundingSphere;
         bound.Center = Vector3.Transform(bound.Center, localToWorld);
         Frustum.CullResult cull = camera.Frustum.CullTest(bound);
         if (cull != Frustum.CullResult.TotallyOutside)
         {
             if (Animator != null)
             {
                 Animator.SetupActive(Model);
             }
             Model.DiffuseColor = road.Path.RGBColor;
             Model.Render(camera, ref localToWorld, null);
         }
     }
 }
예제 #12
0
        }   // end of HandleTouchInput()

        public override void Render(Camera camera)
        {
            // Don't bother if offscreen.
            Vector3 position = worldMatrix.Translation;
            float   radius   = 2.0f;

            Frustum.CullResult cullResult = camera.Frustum.CullTest(position, radius);
            if (cullResult == Frustum.CullResult.TotallyOutside)
            {
                return;
            }

            GraphicsDevice device  = BokuGame.bokuGame.GraphicsDevice;
            Terrain        terrain = BokuGame.bokuGame.inGame.Terrain;

            int materialIndex = Terrain.UISlotToMatIndex(uiSlot);

            Effect          effect    = terrain.EffectColor;
            EffectTechnique technique = TerrainMaterial.Get(materialIndex).TechniqueColor(TerrainMaterial.EffectTechs.TerrainColorPass);

            effect.CurrentTechnique = technique;

            // We need to push the near plane out more than is normal for UI
            // so that the material cubes don't render behind the terrain.
            Camera cam = camera;

            cam.NearClip = 6.0f;

            Matrix twistMatrix = Matrix.CreateRotationZ(worldMatrix.Translation.X + 0.5f);
            float  scale       = MathHelper.Clamp(2.0f / ((float)Math.Abs(worldMatrix.Translation.X) + 1.0f), 0.1f, 1.0f);
            Matrix scaleMatrix = Matrix.CreateScale(scale);

            Matrix world = twistMatrix * scaleMatrix * worldMatrix;

            Vector3 trans = world.Translation;

            trans.X          *= scale + 0.5f;
            world.Translation = trans;

            hitWorld = world;

            // Compensate for verts being [0..1] instead of [-0.5..0.5] as we'd prefer.
            // They must be in [0..1] because UV mapping is implicit in local position.
            Matrix preTrans = Matrix.Identity;

            preTrans.Translation = new Vector3(-0.5f, -0.5f, -0.5f);
            world = preTrans * world;

            Matrix worldViewProjMatrix = world * cam.ViewProjectionMatrix;

            terrain.ParameterColor(Terrain.EffectParams.WorldMatrix).SetValue(worldMatrix);
            terrain.ParameterColor(Terrain.EffectParams.WorldViewProjMatrix).SetValue(worldViewProjMatrix);
            terrain.ParameterColor(Terrain.EffectParams.WarpCenter).SetValue(Vector4.Zero);
            terrain.ParameterEdit(Terrain.EffectParams.WorldMatrix).SetValue(worldMatrix);
            terrain.ParameterEdit(Terrain.EffectParams.WorldViewProjMatrix).SetValue(worldViewProjMatrix);
            terrain.ParameterEdit(Terrain.EffectParams.WarpCenter).SetValue(Vector4.Zero);

#if NETFX_CORE
            // Note: Indexing into shaders doesn't work with MG.  Apparently it
            // was some hack done in XNA related to the Effect code they used.
            // Anyway, instead of using this indexing we need to pick and set
            // the right technique which we do further down from here.
#else
            if (BokuSettings.Settings.PreferReach)
            {
                //Select the VS based on the number of point-lights
                var lightNum = Boku.Fx.Luz.Count;
                if (lightNum > 6)
                {
                    terrain.ParameterColor(Terrain.EffectParams.VSIndex).SetValue(4);
                    terrain.ParameterEdit(Terrain.EffectParams.VSIndex).SetValue(4);
                }
                else if (lightNum > 4)
                {
                    terrain.ParameterColor(Terrain.EffectParams.VSIndex).SetValue(3);
                    terrain.ParameterEdit(Terrain.EffectParams.VSIndex).SetValue(3);
                }
                else if (lightNum > 2)
                {
                    terrain.ParameterColor(Terrain.EffectParams.VSIndex).SetValue(2);
                    terrain.ParameterEdit(Terrain.EffectParams.VSIndex).SetValue(2);
                }
                else if (lightNum > 0)
                {
                    terrain.ParameterColor(Terrain.EffectParams.VSIndex).SetValue(1);
                    terrain.ParameterEdit(Terrain.EffectParams.VSIndex).SetValue(1);
                }
                else
                {
                    terrain.ParameterColor(Terrain.EffectParams.VSIndex).SetValue(0);
                    terrain.ParameterEdit(Terrain.EffectParams.VSIndex).SetValue(0);
                }

                //Select the PS
                terrain.ParameterColor(Terrain.EffectParams.PSIndex).SetValue(0);
                terrain.ParameterEdit(Terrain.EffectParams.PSIndex).SetValue(0);
            }
            else // Shader Model v3
            {
                //SM3 only uses one VS
                terrain.ParameterColor(Terrain.EffectParams.VSIndex).SetValue(5);
                terrain.ParameterEdit(Terrain.EffectParams.VSIndex).SetValue(5);

                //Select the PS
                terrain.ParameterColor(Terrain.EffectParams.PSIndex).SetValue(2);
                terrain.ParameterEdit(Terrain.EffectParams.PSIndex).SetValue(2);
            }
#endif

            if (MaterialPicker.FabricMode)
            {
                var cubeSize = 1f;
                terrain.ParameterColor(Terrain.EffectParams.InvCubeSize).SetValue(new Vector3(cubeSize, 1.0f / cubeSize, cubeSize * 0.5f));
                terrain.ParameterEdit(Terrain.EffectParams.InvCubeSize).SetValue(new Vector3(cubeSize, 1.0f / cubeSize, cubeSize * 0.5f));

                #region Fabric
                device.SetVertexBuffer(vBuff_FA);
                device.Indices = iBuff_FA;

                terrain.SetGlobalParams_FA();
                terrain.SetMaterialParams_FA((ushort)materialIndex, true);

                TerrainMaterial mat = TerrainMaterial.Get(materialIndex);

#if NETFX_CORE
                int lightNum = Boku.Fx.Luz.Count;
                if (lightNum > 6)
                {
                    effect.CurrentTechnique = effect.Techniques["TerrainColorPass_L10_FA_SM2"];
                }
                else if (lightNum > 4)
                {
                    effect.CurrentTechnique = effect.Techniques["TerrainColorPass_L6_FA_SM2"];
                }
                else if (lightNum > 2)
                {
                    effect.CurrentTechnique = effect.Techniques["TerrainColorPass_L4_FA_SM2"];
                }
                else if (lightNum > 0)
                {
                    effect.CurrentTechnique = effect.Techniques["TerrainColorPass_L2_FA_SM2"];
                }
                else
                {
                    effect.CurrentTechnique = effect.Techniques["TerrainColorPass_L0_FA_SM2"];
                }
#else
                effect.CurrentTechnique = mat.TechniqueColor(TerrainMaterial.EffectTechs_FA.TerrainColorPass_FA);
#endif
                foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                {
                    pass.Apply();

                    device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, 37, 0, 56);
                }

                #endregion
            }
            else
            {
                #region Cube
                var cubeSize = 1.0f;
                terrain.ParameterColor(Terrain.EffectParams.InvCubeSize).SetValue(new Vector3(cubeSize, 1.0f / cubeSize, cubeSize * 0.5f));
                terrain.ParameterEdit(Terrain.EffectParams.InvCubeSize).SetValue(new Vector3(cubeSize, 1.0f / cubeSize, cubeSize * 0.5f));

                Tile.CheckIndices(new Point(32, 32));

                if (Terrain.RenderMethod == Terrain.RenderMethods.FewerDraws)
                {
                    device.SetVertexBuffer(vBuff);

                    device.Indices = Tile.IndexBuffer_FD();

                    terrain.SetGlobalParams_FD();
                    terrain.SetMaterialParams_FD((ushort)materialIndex, true);
                }

                TerrainMaterial mat = TerrainMaterial.Get(materialIndex);

#if NETFX_CORE
                int lightNum = Boku.Fx.Luz.Count;
                if (lightNum > 6)
                {
                    effect.CurrentTechnique = effect.Techniques["TerrainColorPass_L10_FD_SM2"];
                }
                else if (lightNum > 4)
                {
                    effect.CurrentTechnique = effect.Techniques["TerrainColorPass_L6_FD_SM2"];
                }
                else if (lightNum > 2)
                {
                    effect.CurrentTechnique = effect.Techniques["TerrainColorPass_L4_FD_SM2"];
                }
                else if (lightNum > 0)
                {
                    effect.CurrentTechnique = effect.Techniques["TerrainColorPass_L2_FD_SM2"];
                }
                else
                {
                    effect.CurrentTechnique = effect.Techniques["TerrainColorPass_L0_FD_SM2"];
                }
#else
                effect.CurrentTechnique = mat.TechniqueColor(TerrainMaterial.EffectTechs.TerrainColorPass);
#endif

                foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                {
                    if (Terrain.RenderMethod == Terrain.RenderMethods.FewerDraws)
                    {
                        terrain.SetTopParams_FD((ushort)materialIndex, true);
                        pass.Apply();

                        device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, 4, 0, 2); //20 verts, 10 triangles

                        terrain.SetSideParams_FD((ushort)materialIndex, true);
                        pass.Apply();

                        device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 4, 0, 16, 0, 8); //20 verts, 10 triangles
                    }
                }
                #endregion
            }

            RenderLabel(camera, world);
        }   // end of UIGridMaterialElement Render()
예제 #13
0
        }   // end of Render()

        //
        //
        // TODO (****)  Need to verify that these all work!
        //
        //

        /// <summary>
        /// Test rectangle to see if it is visible in the camera.
        /// Note this is camera units (zoomed) not raw pixels.
        /// </summary>
        /// <param name="rect"></param>
        /// <returns></returns>
        public Frustum.CullResult CullTest(RectangleF rect)
        {
            // Get rect vertices.
            Vector2[] p = new Vector2[4];
            p[0] = rect.Position;
            p[1] = p[0] + new Vector2(rect.Size.X, 0);
            p[2] = p[0] + new Vector2(0, rect.Size.Y);
            p[3] = p[0] + new Vector2(rect.Size.X, rect.Size.Y);

            // Transform into homogeneous coords.
            for (int i = 0; i < 4; i++)
            {
                p[i] = Vector2.Transform(p[i], ViewProjMatrix);
            }

            // Most common case is that all points are inside so look at that one first.
            Frustum.CullResult result = Frustum.CullResult.TotallyInside;
            for (int i = 0; i < 4; i++)
            {
                // Check if point is outside.
                if (p[i].X < -1 || p[i].X > 1 || p[i].Y < -1 || p[i].Y > 1)
                {
                    // Found one that's outside, break;
                    result = Frustum.CullResult.PartiallyInside;
                    break;
                }
            }

            // All points are inside so we're done.
            if (result == Frustum.CullResult.TotallyInside)
            {
                return(result);
            }

            // See if all points are fully outside the same side of the screen.
            if (p[0].X < -1 && p[1].X < -1 && p[2].X < -1 && p[3].X < -1)
            {
                return(Frustum.CullResult.TotallyOutside);
            }
            if (p[0].X > 1 && p[1].X > 1 && p[2].X > 1 && p[3].X > 1)
            {
                return(Frustum.CullResult.TotallyOutside);
            }
            if (p[0].Y < -1 && p[1].Y < -1 && p[2].Y < -1 && p[3].Y < -1)
            {
                return(Frustum.CullResult.TotallyOutside);
            }
            if (p[0].Y > 1 && p[1].Y > 1 && p[2].Y > 1 && p[3].Y > 1)
            {
                return(Frustum.CullResult.TotallyOutside);
            }

            // TODO (****) Note this is not full correct.  You can still have a
            // rect which is oriented diagonally with all its vertices off screen
            // but overlapping a corner of the screen.  A proper, general solution
            // would probably be to do the fully inside test and then test each
            // line segment of the rect vs each edge of the screen.  Bit too much
            // overkill for now.

            return(result);
        }