public void Build(SceneQuadTreeNode rParentNode, int nIndex, ref SceneQuadTreeNode rQuadNode, int nDepth, Vector3 rCenter, float fLength) { rQuadNode = new SceneQuadTreeNode(); rQuadNode.ID = nIndex; rQuadNode.Parent = rParentNode; rQuadNode.Children = new SceneQuadTreeNode[4]; rQuadNode.NodeList = new List <SceneObject>(); rQuadNode.Center = rCenter; rQuadNode.Length = fLength; rQuadNode.LooseFactor = this.LooseFactor; rQuadNode.Depth = nDepth; rQuadNode.SubtreeObjCount = 0; var fLooseLength = fLength; rQuadNode.AABB = new Rect(rCenter.x - fLooseLength / 2.0f, rCenter.z - fLooseLength / 2.0f, fLooseLength, fLooseLength); if (nDepth == this.MaxDepth - 1) { return; } for (int i = 0; i < 4; i++) { var rChildCenter = rCenter + this.QuadDirs[i] * fLength * 0.25f; this.Build(rQuadNode, i, ref rQuadNode.Children[i], nDepth + 1, rChildCenter, fLength * 0.5f); } }
public SceneQuadTreeNode AddNode(SceneObject rGo) { // 计算四叉树的深度层次 var rBoxCollider = rGo.GameObject.GetComponentInChildren <BoxCollider>(); var rBounds = rBoxCollider.bounds; var fObjRadius = Mathf.Max(rBounds.size.x, rBounds.size.z); var nCurDepth = Mathf.FloorToInt(Mathf.Log(this.LooseFactor * this.Length / fObjRadius, 2.0f) - 1); nCurDepth = Mathf.Clamp(0, this.MaxDepth - 1, nCurDepth); var nTempDepth = 0; SceneQuadTreeNode rCurNode = this.TreeRoot; while (nTempDepth < nCurDepth) { var nIndex = ((rGo.GameObject.transform.position.x > rCurNode.Center.x) ? 1 : 0) | ((rGo.GameObject.transform.position.z > rCurNode.Center.z) ? 2 : 0); rCurNode = rCurNode.Children[nIndex]; nTempDepth++; } rCurNode.NodeList.Add(rGo); rCurNode.SubtreeObjCount++; // 增加子节点的个数 var rParentNode = rCurNode.Parent; while (rParentNode != null) { rParentNode.SubtreeObjCount++; rParentNode = rParentNode.Parent; } return(rCurNode); }
private void ClearAllNodes(SceneQuadTreeNode rTreeNode) { if (rTreeNode == null) { return; } rTreeNode.SubtreeObjCount = 0; rTreeNode.NodeList.Clear(); for (int i = 0; i < rTreeNode.Children.Length; i++) { this.ClearAllNodes(rTreeNode.Children[i]); } }
public void DebugDraw(SceneQuadTreeNode rQuadNode) { if (rQuadNode == null || rQuadNode.SubtreeObjCount == 0) { return; } var rColor = new Color(this.DepthColors[rQuadNode.Depth].r, this.DepthColors[rQuadNode.Depth].g, this.DepthColors[rQuadNode.Depth].b, 1f); Gizmos.color = this.DepthColors[rQuadNode.Depth]; Gizmos.DrawWireCube(rQuadNode.Center, new Vector3(rQuadNode.Length, 1, rQuadNode.Length)); for (int i = 0; i < rQuadNode.Children.Length; i++) { this.DebugDraw(rQuadNode.Children[i]); } }
public void UpdateNode(SceneObject rSceneGo) { var rBoxCollider = rSceneGo.GameObject.GetComponentInChildren <BoxCollider>(); var rBounds = rBoxCollider.bounds; var fObjRadius = Mathf.Max(rBounds.size.x, rBounds.size.z); var nCurDepth = Mathf.FloorToInt(Mathf.Log(this.LooseFactor * this.Length / fObjRadius, 2.0f) - 1); nCurDepth = Mathf.Clamp(0, this.MaxDepth - 1, nCurDepth); var nTempDepth = 0; SceneQuadTreeNode rCurNode = this.TreeRoot; while (nTempDepth < nCurDepth) { var nIndex = ((rBounds.center.x > rCurNode.Center.x) ? 1 : 0) | ((rBounds.center.z > rCurNode.Center.z) ? 2 : 0); rCurNode = rCurNode.Children[nIndex]; nTempDepth++; } if (rSceneGo.QuadNode == rCurNode) { return; } // 替换 rSceneGo.QuadNode.NodeList.Remove(rSceneGo); rSceneGo.QuadNode.SubtreeObjCount--; var rParentNode = rSceneGo.QuadNode.Parent; while (rParentNode != null) { rParentNode.SubtreeObjCount--; rParentNode = rParentNode.Parent; } rSceneGo.QuadNode = rCurNode; rSceneGo.QuadNode.NodeList.Add(rSceneGo); rSceneGo.QuadNode.SubtreeObjCount++; rParentNode = rSceneGo.QuadNode.Parent; while (rParentNode != null) { rParentNode.SubtreeObjCount++; rParentNode = rParentNode.Parent; } }
private void GetAllIntersectSceneGos(SceneObject rSceneGo, List <SceneQuadTreeNode> rQaudTreeNodes, SceneQuadTreeNode rQuadNode) { if (rQuadNode == null) { return; } if (!rSceneGo.BoxCollider) { return; } var rRect = new Rect( rSceneGo.BoxCollider.bounds.center.x - rSceneGo.BoxCollider.bounds.size.x / 2.0f, rSceneGo.BoxCollider.bounds.center.z - rSceneGo.BoxCollider.bounds.size.z / 2.0f, rSceneGo.BoxCollider.bounds.size.x, rSceneGo.BoxCollider.bounds.size.z); if (!rQuadNode.AABB.Overlaps(rRect)) { return; } if (rQuadNode.NodeList.Count > 0) { rQaudTreeNodes.Add(rQuadNode); } for (int i = 0; i < rQuadNode.Children.Length; i++) { this.GetAllIntersectSceneGos(rSceneGo, rQaudTreeNodes, rQuadNode.Children[i]); } }