Explorar o código

Fixed culling, calculating bounding box, and entities visibility

Ronen Ness %!s(int64=8) %!d(string=hai) anos
pai
achega
13f4700faf

+ 1 - 1
MonoGameSceneGraph/Game1.cs

@@ -113,7 +113,7 @@ namespace MonoGameSceneGraph
 
 
             // rotate inner node on X axis
             // rotate inner node on X axis
             node.RotationZ = node.RotationZ + 0.01f;
             node.RotationZ = node.RotationZ + 0.01f;
-
+            
             // scale node container
             // scale node container
             nodeContainer.ScaleZ = (1.0f + (float)System.Math.Cos(gameTime.TotalGameTime.TotalSeconds * 2f) / 4f);
             nodeContainer.ScaleZ = (1.0f + (float)System.Math.Cos(gameTime.TotalGameTime.TotalSeconds * 2f) / 4f);
 
 

+ 8 - 2
MonoGameSceneGraph/Source/Entities/IEntity.cs

@@ -27,12 +27,18 @@ namespace MonoGameSceneGraph
         void Draw(Node parent, Matrix localTransformations, Matrix worldTransformations);
         void Draw(Node parent, Matrix localTransformations, Matrix worldTransformations);
 
 
         /// <summary>
         /// <summary>
-        /// Get the bounding box of this entity.
+        /// Get the bounding box of this entity (in world space).
         /// </summary>
         /// </summary>
         /// <param name="parent">Parent node that's currently drawing this entity.</param>
         /// <param name="parent">Parent node that's currently drawing this entity.</param>
         /// <param name="localTransformations">Local transformations from the direct parent node.</param>
         /// <param name="localTransformations">Local transformations from the direct parent node.</param>
         /// <param name="worldTransformations">World transformations to apply on this entity (this is what you should use to draw this entity).</param>
         /// <param name="worldTransformations">World transformations to apply on this entity (this is what you should use to draw this entity).</param>
-        /// <returns>Bounding box of the entity.</returns>
+        /// <returns>Bounding box of the entity, in world space.</returns>
         BoundingBox GetBoundingBox(Node parent, Matrix localTransformations, Matrix worldTransformations);
         BoundingBox GetBoundingBox(Node parent, Matrix localTransformations, Matrix worldTransformations);
+
+        /// <summary>
+        /// Return if the entity is currently visible.
+        /// </summary>
+        /// <returns>If the entity is visible or not.</returns>
+        bool Visible { get; set; }
     }
     }
 }
 }

+ 18 - 16
MonoGameSceneGraph/Source/Entities/ModelEntity.cs

@@ -46,6 +46,9 @@ namespace MonoGameSceneGraph
         /// <param name="model">Model to draw.</param>
         /// <param name="model">Model to draw.</param>
         public ModelEntity(Model model)
         public ModelEntity(Model model)
         {
         {
+            // visible by default
+            Visible = true;
+
             // store model
             // store model
             Model = model;
             Model = model;
 
 
@@ -72,16 +75,10 @@ namespace MonoGameSceneGraph
         /// <param name="worldTransformations">World transformations to apply on this entity (this is what you should use to draw this entity).</param>
         /// <param name="worldTransformations">World transformations to apply on this entity (this is what you should use to draw this entity).</param>
         public void Draw(Node parent, Matrix localTransformations, Matrix worldTransformations)
         public void Draw(Node parent, Matrix localTransformations, Matrix worldTransformations)
         {
         {
-            // A model is composed of "Meshes" which are
-            // parts of the model which can be positioned
-            // independently, which can use different textures,
-            // and which can have different rendering states
-            // such as lighting applied.
+            // iterate model meshes
             foreach (var mesh in Model.Meshes)
             foreach (var mesh in Model.Meshes)
             {
             {
-                // "Effect" refers to a shader. Each mesh may
-                // have multiple shaders applied to it for more
-                // advanced visuals. 
+                // iterate effect in mesh
                 foreach (BasicEffect effect in mesh.Effects)
                 foreach (BasicEffect effect in mesh.Effects)
                 {
                 {
                     // enable lights
                     // enable lights
@@ -105,12 +102,20 @@ namespace MonoGameSceneGraph
                     effect.Projection = Projection;
                     effect.Projection = Projection;
                 }
                 }
 
 
-                // Now that we've assigned our properties on the effects we can
-                // draw the entire mesh
+                // draw current mesh
                 mesh.Draw();
                 mesh.Draw();
             }
             }
         }
         }
 
 
+        /// <summary>
+        /// Return if the entity is currently visible.
+        /// </summary>
+        /// <returns>If the entity is visible or not.</returns>
+        public bool Visible
+        {
+            get; set;
+        }
+
         /// <summary>
         /// <summary>
         /// Get the bounding box of this entity.
         /// Get the bounding box of this entity.
         /// </summary>
         /// </summary>
@@ -142,18 +147,15 @@ namespace MonoGameSceneGraph
                     {
                     {
                         // get curr position and update min / max
                         // get curr position and update min / max
                         Vector3 currPosition = new Vector3(vertexData[i], vertexData[i + 1], vertexData[i + 2]);
                         Vector3 currPosition = new Vector3(vertexData[i], vertexData[i + 1], vertexData[i + 2]);
+                        currPosition = Vector3.Transform(currPosition, worldTransformations);
                         min = Vector3.Min(min, currPosition);
                         min = Vector3.Min(min, currPosition);
                         max = Vector3.Max(max, currPosition);
                         max = Vector3.Max(max, currPosition);
                     }
                     }
                 }
                 }
             }
             }
 
 
-            // transform min and max position so it will be in world space
-            min = Vector3.Transform(min, worldTransformations);
-            max = Vector3.Transform(max, worldTransformations);
-
-            // return the bounding box (in world space)
-            return new BoundingBox(Vector3.Min(min, max), Vector3.Max(min, max));
+            // return bounding box
+            return new BoundingBox(min, max);
         }
         }
     }
     }
 }
 }

+ 3 - 3
MonoGameSceneGraph/Source/Nodes/CullingNode.cs

@@ -48,7 +48,7 @@ namespace MonoGameSceneGraph
         /// <summary>
         /// <summary>
         /// Do we need to update the bounding box?
         /// Do we need to update the bounding box?
         /// </summary>
         /// </summary>
-        private bool _isBoundingBoxDirty = true;
+        protected bool _isBoundingBoxDirty = true;
 
 
         /// <summary>
         /// <summary>
         /// Draw the node and its children.
         /// Draw the node and its children.
@@ -56,7 +56,7 @@ namespace MonoGameSceneGraph
         public override void Draw()
         public override void Draw()
         {
         {
             // if not visible skip
             // if not visible skip
-            if (!IsVisible)
+            if (!Visible)
             {
             {
                 return;
                 return;
             }
             }
@@ -140,7 +140,7 @@ namespace MonoGameSceneGraph
         /// <summary>
         /// <summary>
         /// Update the bounding box of this Culling Node.
         /// Update the bounding box of this Culling Node.
         /// </summary>
         /// </summary>
-        protected void UpdateBoundingBox()
+        protected virtual void UpdateBoundingBox()
         {
         {
             // if bounding box is not dirty, skip
             // if bounding box is not dirty, skip
             if (!_isBoundingBoxDirty)
             if (!_isBoundingBoxDirty)

+ 45 - 12
MonoGameSceneGraph/Source/Nodes/Node.cs

@@ -32,7 +32,7 @@ namespace MonoGameSceneGraph
         /// <summary>
         /// <summary>
         /// Is this node currently visible?
         /// Is this node currently visible?
         /// </summary>
         /// </summary>
-        public bool IsVisible = true;
+        public virtual bool Visible { get; set; }
 
 
         /// <summary>
         /// <summary>
         /// Optional identifier we can give to nodes.
         /// Optional identifier we can give to nodes.
@@ -103,13 +103,21 @@ namespace MonoGameSceneGraph
         /// </summary>
         /// </summary>
         public uint TransformVersion { get { return _transformVersion; } }
         public uint TransformVersion { get { return _transformVersion; } }
 
 
+        /// <summary>
+        /// Create the new node.
+        /// </summary>
+        public Node()
+        {
+            Visible = true;
+        }
+
         /// <summary>
         /// <summary>
         /// Draw the node and its children.
         /// Draw the node and its children.
         /// </summary>
         /// </summary>
         public virtual void Draw()
         public virtual void Draw()
         {
         {
             // not visible? skip
             // not visible? skip
-            if (!IsVisible)
+            if (!Visible)
             {
             {
                 return;
                 return;
             }
             }
@@ -487,31 +495,56 @@ namespace MonoGameSceneGraph
             // make sure transformations are up-to-date
             // make sure transformations are up-to-date
             UpdateTransformations();
             UpdateTransformations();
 
 
-            // initialize minimum and maximum corners of the bounding box to max and min values
-            Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
-            Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue);
+            // list of points to build bounding box from
+            List<Vector3> corners = new List<Vector3>();
 
 
             // apply all child nodes bounding boxes
             // apply all child nodes bounding boxes
             if (includeChildNodes)
             if (includeChildNodes)
             {
             {
                 foreach (Node child in _childNodes)
                 foreach (Node child in _childNodes)
                 {
                 {
-                    BoundingBox curr = child.GetBoundingBox();
-                    min = Vector3.Min(min, curr.Min);
-                    max = Vector3.Max(max, curr.Max);
+                    // skip invisible nodes
+                    if (!child.Visible)
+                    {
+                        continue;
+                    }
+
+                    // get bounding box
+                    BoundingBox currBox = child.GetBoundingBox();
+                    if (currBox.Min != currBox.Max)
+                    {
+                        corners.Add(currBox.Min);
+                        corners.Add(currBox.Max);
+                    }
                 }
                 }
             }
             }
 
 
             // apply all entities directly under this node
             // apply all entities directly under this node
             foreach (IEntity entity in _childEntities)
             foreach (IEntity entity in _childEntities)
             {
             {
-                BoundingBox curr = entity.GetBoundingBox(this, _localTransform, _worldTransform);
-                min = Vector3.Min(min, curr.Min);
-                max = Vector3.Max(max, curr.Max);
+                // skip invisible entities
+                if (!entity.Visible)
+                {
+                    continue;
+                }
+
+                // get entity bounding box
+                BoundingBox currBox = entity.GetBoundingBox(this, _localTransform, _worldTransform);
+                if (currBox.Min != currBox.Max)
+                {
+                    corners.Add(currBox.Min);
+                    corners.Add(currBox.Max);
+                }
+            }
+
+            // nothing in this node?
+            if (corners.Count == 0)
+            {
+                return new BoundingBox();
             }
             }
 
 
             // return final bounding box
             // return final bounding box
-            return new BoundingBox(min, max);
+            return BoundingBox.CreateFromPoints(corners);
         }
         }
     }
     }
 }
 }