/// <summary> /// Constructs a Quadtree object /// </summary> public QuadTree(Game game) : base(game) { _valid = false; _root = null; _gameComponents = new Collection<QuadTreeGameComponent>(); }
internal QuadTreeModelInfo(Model model, Vector3 position, float scale, Vector3 rotation) { _model = model; _position = position; _rotation = rotation; _scale = scale; _node = null; }
public QuadTreeNode(QuadTreeNode parent) { m_parent = parent; children = new QuadTreeNode[4]; // TryCull instance variables m_corners = new Vector3[8]; m_projCorners = new Vector4[8]; // Models and Components collections _models = new Collection<QuadTreeModelInfo>(); _gameComponents = new Collection<QuadTreeGameComponent>(); }
//------------------------------------------- // Build the quadTree using the height data //------------------------------------------- public bool Buildout(GraphicsDevice gd, float cellSize, int sectorsize, int minX, int minY, int width, int height, float[,] heightData, Vector3[,] normals) { m_width = width; m_height = height; if (minX + m_width >= heightData.GetLength(1)) m_width = heightData.GetLength(1) - minX - 1; // handle end of row case ( sectorsize - 1) if (minY + m_height >= heightData.GetLength(0)) m_height = heightData.GetLength(0) - minY - 1; // handle end of column case (sectorsize - 1) m_cellSize = cellSize; // set instance variables that define world coords of this sector m_startX = cellSize * (float)minX; m_startY = cellSize * (float)minY; m_endX = cellSize * (float)(minX + m_width); m_endY = cellSize * (float)(minY + m_height); // now we don't need to do any more if we will delegate to children if (m_width > sectorsize || m_height > sectorsize) { int halfWidth = m_width / 2; if ((m_width & 0x01) == 0x01) { halfWidth++; } int halfHeight = m_height / 2; if ((halfHeight & 0x01) == 0x01) { halfHeight++; } m_minHeight = 999.0f; m_maxHeight = -999.0f; if (children[NW] == null) { children[NW] = new QuadTreeNode(this); } children[NW].Buildout(gd, cellSize, sectorsize, minX, minY, halfWidth, halfHeight, heightData, normals); m_minHeight = children[NW].m_minHeight < m_minHeight ? children[NW].m_minHeight : m_minHeight; m_maxHeight = children[NW].m_maxHeight > m_maxHeight ? children[NW].m_maxHeight : m_maxHeight; if (width > sectorsize) { if (children[NE] == null) children[NE] = new QuadTreeNode(this); children[NE].Buildout(gd, cellSize, sectorsize, minX + halfWidth, minY, halfWidth, halfHeight, heightData, normals); m_minHeight = children[NE].m_minHeight < m_minHeight ? children[NE].m_minHeight : m_minHeight; m_maxHeight = children[NE].m_maxHeight > m_maxHeight ? children[NE].m_maxHeight : m_maxHeight; } if (height > sectorsize) { if (children[SW] == null) children[SW] = new QuadTreeNode(this); children[SW].Buildout(gd, cellSize, sectorsize, minX, minY + halfHeight, halfWidth, halfHeight, heightData, normals); m_minHeight = children[SW].m_minHeight < m_minHeight ? children[SW].m_minHeight : m_minHeight; m_maxHeight = children[SW].m_maxHeight > m_maxHeight ? children[SW].m_maxHeight : m_maxHeight; } if (height > sectorsize && width > sectorsize) { if (children[SE] == null) children[SE] = new QuadTreeNode(this); children[SE].Buildout(gd, cellSize, sectorsize, minX + halfWidth, minY + halfHeight, halfWidth, halfHeight, heightData, normals); m_minHeight = children[SE].m_minHeight < m_minHeight ? children[SE].m_minHeight : m_minHeight; m_maxHeight = children[SE].m_maxHeight > m_maxHeight ? children[SE].m_maxHeight : m_maxHeight; } // find the 4 corners of this node (flat) // these are used in TryCull ComputeCorners(); //---------------------------------------- // we're done here! // We will only keep track of children nodes, // no data needed for rendering in this node //---------------------------------------- return true; } //-------------------------------------- // we are a lowest level child and have // arrived at width and height <= sectorsize // save the height data for this sector // and create the data for rendering //-------------------------------------- // we actually duplicate verts and heightdata on borders of sectors // that is, m_width and m_height are the number of cells // so the number of vertices is (m_width+1) * (m_height+1). // We save the heightdata in an instance variable so that we // can compute GetHeightAt(x,y) later. m_heightData = new float[m_height + 1, m_width + 1]; if (m_heightData == null) throw new Exception("QuadtreeNode.BuildOut : Out of memory for local heightData"); m_minHeight = 9999.0f; m_maxHeight = -9999.0f; for (int y = 0; y <= m_height; y++) { for (int x = 0; x <= m_width; x++) { m_heightData[y, x] = heightData[minY + y, minX + x]; float data = m_heightData[y, x]; if (data > m_maxHeight) m_maxHeight = data; if (data < m_minHeight) m_minHeight = data; } } // find the 4 corners of this node (flat) // these are used in TryCull ComputeCorners(); float totalHeight = (float)heightData.GetLength(0); float totalWidth = (float)heightData.GetLength(1); float ustep = 1.0f / totalWidth;// / (float )m_width; float ustart = (float)minX * ustep; float vstep = 1.0f / totalHeight;// / (float )m_height; float vstart = (float)minY * vstep; return CreateMeshFromHeightData(gd, minX, minY, ustart, ustep, vstart, vstep, normals); }
public QuadTreeGameComponent(Game game) : base(game) { quadTree = null; qNode = null; }
/// <summary> /// Creates the QuadTree nodes and initializes them for rendering. /// This method must be called after content is loaded but before Draw(). /// </summary> /// <param name="cellSize">Width/Height of a cell in the terrain</param> /// <param name="sectorsize">Number of cells in x and z that will be rendered or culled as a unit</param> /// <param name="heightData">The HeightData to use.</param> public bool Create(float cellSize, int sectorSize, float[,] heightData) { int width = heightData.GetLength(1); int height = heightData.GetLength(0); _totalWidth = cellSize * width; _totalHeight = cellSize * height; //m_sectorsize = sectorSize; if (height > heightData.GetLength(0)) _valid = false; if (width > heightData.GetLength(1)) _valid = false; Vector3[,] normals = CreateNormals(cellSize, heightData); _root = new QuadTreeNode(null); _valid = _root.Buildout(GraphicsDevice, cellSize, sectorSize, 0, 0, width, height, heightData, normals); if (!_valid) _root = null; normals = null; // don't need them anymore here // if we have QuadTreeGameComponents added to the quadTree already // then distribute them to the new nodes if (_valid && _root != null) { foreach (QuadTreeGameComponent component in _gameComponents) { _root.AddComponent(component); } } return _valid; }