⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 quad.cs

📁 Game Engine Desing Direct X and C#.rar
💻 CS
字号:
using System;
using System.Collections;
using System.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace GameEngine
{
	/// <summary>
	/// The basic structure for building a Quadtree 
	/// </summary>
	public class Quad : IDisposable
	{
		private Rectangle  m_Bounds;
		private Quad       m_NorthEast = null;
		private Quad       m_NorthWest = null;
		private Quad       m_SouthWest = null;
		private Quad       m_SouthEast = null;
		private Quad       m_Parent    = null;
		private int        m_nLevel;
		private SortedList m_Objects;
		private float      m_fRadius;
		private Vector3    m_vPosition;
		private string     m_sName;
		private static Quad m_BaseQuad = null;

		public String Name { get { return m_sName; } }

		public Rectangle Bounds { get { return m_Bounds; } }

		public Quad(Rectangle bounds, int level, int maxlevel, Quad parent )
		{
			if ( m_BaseQuad == null )
			{
				m_BaseQuad = this;
			}

			m_Bounds = bounds;
			m_nLevel = level;
			m_Parent = parent;
			m_Objects = new SortedList();

			m_sName = "L" + level + ":X" + bounds.Left + "Y" + bounds.Top;

			m_vPosition.X = (bounds.Left + bounds.Right) / 2.0f;
			m_vPosition.Y = 0.0f;
			m_vPosition.Z = (bounds.Top + bounds.Bottom) / 2.0f;

			double dx = bounds.Width;
			double dz = bounds.Height;
			m_fRadius = (float)Math.Sqrt( dx * dx + dz * dz ) / 2.0f;

			if ( level < maxlevel )
			{
				int nHalfHeight = (int)dz / 2;
				int nHalfWidth = (int)dx / 2;
				m_NorthEast = new Quad ( 
					new Rectangle(bounds.Left + nHalfWidth, bounds.Top, nHalfWidth, nHalfHeight), 
					level+1, maxlevel, this );
				m_NorthWest = new Quad ( 
					new Rectangle(bounds.Left, bounds.Top, nHalfWidth, nHalfHeight), 
					level+1, maxlevel, this);
				m_SouthWest = new Quad ( 
					new Rectangle(bounds.Left, bounds.Top + nHalfHeight, nHalfWidth, nHalfHeight), 
					level+1, maxlevel, this);
				m_SouthEast = new Quad ( 
					new Rectangle(bounds.Left + nHalfWidth, bounds.Top + nHalfHeight, nHalfWidth, nHalfHeight), 
					level+1, maxlevel, this);
			}
		}

		public void AddObject( Object3D obj )
		{
			try
			{
				if ( obj != null )
				{
					if ( obj.InRect( m_Bounds ) )
					{
						int nIndex = m_Objects.IndexOfKey( obj.Name );
						try
						{
							if ( nIndex < 0 )  // add object if we don't have it yet
							{
								m_Objects.Add(obj.Name, obj );
								obj.m_Quads.Add(this);
//								if ( !obj.Name.StartsWith("Quad") && !obj.Name.StartsWith("tree") && !obj.Name.StartsWith("red")&& !obj.Name.StartsWith("blue"))
//								{
//									Console.AddLine(obj.Name + " added to " + Name );
//								}
								if ( m_NorthEast != null && obj.InRect( m_NorthEast.Bounds ) )
								{
									m_NorthEast.AddObject( obj );
								}
								if ( m_NorthWest != null && obj.InRect( m_NorthWest.Bounds ) )
								{
									m_NorthWest.AddObject( obj );
								}
								if ( m_SouthWest != null && obj.InRect( m_SouthWest.Bounds ) )
								{
									m_SouthWest.AddObject( obj );
								}
								if ( m_SouthEast != null && obj.InRect( m_SouthEast.Bounds ) )
								{
									m_SouthEast.AddObject( obj );
								}
							}
							else
							{
								//							Console.AddLine("Attempt to add another " + obj.Name );
							}
						}
						catch (DirectXException d3de)
						{
							Console.AddLine("Unable to add object" );
							Console.AddLine(d3de.ErrorString);
						}
						catch ( Exception e )
						{
							Console.AddLine("Unable to add object" );
							Console.AddLine(e.Message);
						}
					}
					else
					{
						int nIndex = m_Objects.IndexOfKey( obj.Name );
						if ( nIndex >= 0 )  // remove the  object if we have it 
						{
							RemoveObject( obj );
							if ( m_Parent != null )
							{
								m_Parent.AddObject( obj );
							}
						}
					}
				}
			}
			catch
			{
				Console.AddLine("fails in Quad AddObject");
			}
		}

		public void RemoveObject( Object3D obj )
		{
			try
			{
				if ( obj != null ) 
				{
					int nIndex = m_Objects.IndexOfKey( obj.Name );
					if ( nIndex >= 0 )
					{
						try
						{
							m_Objects.Remove( obj.Name );
						}
						catch
						{
							Console.AddLine("failing while removing object from quad object list" );
						}
						try
						{
							if ( obj.m_Quads.Count > 0 )
							{
								obj.m_Quads.Clear();
							}
						}
						catch
						{
							Console.AddLine("failing while clearing objects quad list");
						}
						if ( m_NorthEast != null )
						{
							m_NorthEast.RemoveObject( obj );
						}
						if ( m_NorthWest != null )
						{
							m_NorthWest.RemoveObject( obj );
						}
						if ( m_SouthWest != null )
						{
							m_SouthWest.RemoveObject( obj );
						}
						if ( m_SouthEast != null )
						{
							m_SouthEast.RemoveObject( obj );
						}
					}
				}
			}
			catch (DirectXException d3de)
			{
				Console.AddLine("Unable to remove object" );
				Console.AddLine(d3de.ErrorString);
			}
			catch ( Exception e )
			{
				Console.AddLine("Unable to remove object" );
				Console.AddLine(e.Message);
			}
		}

		public void Cull( Camera cam ) 
		{ 
			Object3D obj;
			int i;

			cam.Reset();

			if ( m_Objects.Count > 0 )
			{

				try
				{
					switch ( cam.CheckFrustum( m_vPosition, m_fRadius ) )
					{
						case Camera.CullState.AllInside:
							for ( i = 0; i < m_Objects.Count; i++ )  
							{
								obj = (Object3D)m_Objects.GetByIndex(i);
								obj.Range = cam.GetDistance( obj );
								obj.Culled = false;
								m_Objects.SetByIndex(i, obj);
								cam.AddVisibleObject( obj );
							}
							break;
						case Camera.CullState.AllOutside:
							if ( m_Parent == null ) // i.e. if this is the root quad
							{
								goto case Camera.CullState.PartiallyIn;
							}
							// do nothing since the default state is true (reset after each render)
							break;
						case Camera.CullState.PartiallyIn:
							if ( m_NorthEast != null ) 
							{
								m_NorthEast.Cull( cam );
								m_NorthWest.Cull( cam );
								m_SouthWest.Cull( cam );
								m_SouthEast.Cull( cam );
							}
							else  // if partially in at the bottom level treat as in
							{
								for ( i = 0; i < m_Objects.Count; i++ )  
								{
									obj = (Object3D)m_Objects.GetByIndex(i);
									obj.Culled = false;
									m_Objects.SetByIndex(i, obj);
									cam.AddVisibleObject( obj );
								}
							}
							break;
					}
				}
				catch (DirectXException d3de)
				{
					Console.AddLine("Unable to cull object" );
					Console.AddLine(d3de.ErrorString);
				}
				catch ( Exception e )
				{
					Console.AddLine("Unable to cull object" );
					Console.AddLine(e.Message);
				}
			}
		}


		public void Update ( Object3D obj )
		{
			bool bResetNeeded = false;

			try
			{

				// only need to reset the quad for the object if it is no longer in one of the quads
				try
				{
					foreach ( Quad q in obj.m_Quads )
					{
						try
						{
							if ( !obj.InRect( q.m_Bounds ) )
							{
								bResetNeeded = true;
							}
						}
						catch
						{
							Console.AddLine("invalid quad in object quad list");
						}
					}
				}
				catch
				{
					Console.AddLine("fails in foreach");
				}
				try
				{
					if ( bResetNeeded )
					{
						m_BaseQuad.RemoveObject( obj );
						m_BaseQuad.AddObject( obj );
					}
				}
				catch
				{
					Console.AddLine("fails in reset needed");
				}
			}
			catch (DirectXException d3de)
			{
				Console.AddLine("Unable to update a Quad " + Name);
				Console.AddLine(d3de.ErrorString);
			}
			catch ( Exception e )
			{
				Console.AddLine("Unable to update a Quad " + Name);
				Console.AddLine(e.Message);
			}

		}

		public void Dispose()
		{
			if ( m_NorthEast != null ) m_NorthEast.Dispose();
			if ( m_NorthWest != null ) m_NorthWest.Dispose();
			if ( m_SouthWest != null ) m_SouthWest.Dispose();
			if ( m_SouthEast != null ) m_SouthEast.Dispose();
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -