private void InsertLeaf(int leaf) { if (_root == NullNode) { _root = leaf; _nodes[_root].ParentOrNext = NullNode; return; } // Find the best sibling for this node AABB leafAABB = _nodes[leaf].AABB; int index = _root; while (_nodes[index].IsLeaf() == false) { int child1 = _nodes[index].Child1; int child2 = _nodes[index].Child2; float area = _nodes[index].AABB.Perimeter; AABB combinedAABB = new AABB(); combinedAABB.Combine(ref _nodes[index].AABB, ref leafAABB); float combinedArea = combinedAABB.Perimeter; // Cost of creating a new parent for this node and the new leaf float cost = 2.0f * combinedArea; // Minimum cost of pushing the leaf further down the tree float inheritanceCost = 2.0f * (combinedArea - area); // Cost of descending into child1 float cost1; if (_nodes[child1].IsLeaf()) { AABB aabb = new AABB(); aabb.Combine(ref leafAABB, ref _nodes[child1].AABB); cost1 = aabb.Perimeter + inheritanceCost; } else { AABB aabb = new AABB(); aabb.Combine(ref leafAABB, ref _nodes[child1].AABB); float oldArea = _nodes[child1].AABB.Perimeter; float newArea = aabb.Perimeter; cost1 = (newArea - oldArea) + inheritanceCost; } // Cost of descending into child2 float cost2; if (_nodes[child2].IsLeaf()) { AABB aabb = new AABB(); aabb.Combine(ref leafAABB, ref _nodes[child2].AABB); cost2 = aabb.Perimeter + inheritanceCost; } else { AABB aabb = new AABB(); aabb.Combine(ref leafAABB, ref _nodes[child2].AABB); float oldArea = _nodes[child2].AABB.Perimeter; float newArea = aabb.Perimeter; cost2 = newArea - oldArea + inheritanceCost; } // Descend according to the minimum cost. if (cost < cost1 && cost1 < cost2) { break; } // Descend if (cost1 < cost2) { index = child1; } else { index = child2; } } int sibling = index; // Create a new parent. int oldParent = _nodes[sibling].ParentOrNext; int newParent = AllocateNode(); _nodes[newParent].ParentOrNext = oldParent; _nodes[newParent].UserData = default(T); _nodes[newParent].AABB.Combine(ref leafAABB, ref _nodes[sibling].AABB); _nodes[newParent].Height = _nodes[sibling].Height + 1; if (oldParent != NullNode) { // The sibling was not the root. if (_nodes[oldParent].Child1 == sibling) { _nodes[oldParent].Child1 = newParent; } else { _nodes[oldParent].Child2 = newParent; } _nodes[newParent].Child1 = sibling; _nodes[newParent].Child2 = leaf; _nodes[sibling].ParentOrNext = newParent; _nodes[leaf].ParentOrNext = newParent; } else { // The sibling was the root. _nodes[newParent].Child1 = sibling; _nodes[newParent].Child2 = leaf; _nodes[sibling].ParentOrNext = newParent; _nodes[leaf].ParentOrNext = newParent; _root = newParent; } // Walk back up the tree fixing heights and AABBs index = _nodes[leaf].ParentOrNext; while (index != NullNode) { index = Balance(index); int child1 = _nodes[index].Child1; int child2 = _nodes[index].Child2; Debug.Assert(child1 != NullNode); Debug.Assert(child2 != NullNode); _nodes[index].Height = 1 + Math.Max(_nodes[child1].Height, _nodes[child2].Height); _nodes[index].AABB.Combine(ref _nodes[child1].AABB, ref _nodes[child2].AABB); index = _nodes[index].ParentOrNext; } //Validate(); }
/// <summary> /// Build an optimal tree. Very expensive. For testing. /// </summary> public void RebuildBottomUp() { int[] nodes = new int[_nodeCount]; int count = 0; // Build array of leaves. Free the rest. for (int i = 0; i < _nodeCapacity; ++i) { if (_nodes[i].Height < 0) { // free node in pool continue; } if (_nodes[i].IsLeaf()) { _nodes[i].ParentOrNext = NullNode; nodes[count] = i; ++count; } else { FreeNode(i); } } while (count > 1) { float minCost = Settings.MaxFloat; int iMin = -1, jMin = -1; for (int i = 0; i < count; ++i) { AABB AABBi = _nodes[nodes[i]].AABB; for (int j = i + 1; j < count; ++j) { AABB AABBj = _nodes[nodes[j]].AABB; AABB b = new AABB(); b.Combine(ref AABBi, ref AABBj); float cost = b.Perimeter; if (cost < minCost) { iMin = i; jMin = j; minCost = cost; } } } int index1 = nodes[iMin]; int index2 = nodes[jMin]; TreeNode <T> child1 = _nodes[index1]; TreeNode <T> child2 = _nodes[index2]; int parentIndex = AllocateNode(); TreeNode <T> parent = _nodes[parentIndex]; parent.Child1 = index1; parent.Child2 = index2; parent.Height = 1 + Math.Max(child1.Height, child2.Height); parent.AABB.Combine(ref child1.AABB, ref child2.AABB); parent.ParentOrNext = NullNode; child1.ParentOrNext = parentIndex; child2.ParentOrNext = parentIndex; nodes[jMin] = nodes[count - 1]; nodes[iMin] = parentIndex; --count; } _root = nodes[0]; Validate(); }
public void InsertLeaf(IDistanceFieldPrimitive _Primitive) { AABB PrimAABB = new AABB() { m_Min = _Primitive.Min, m_Max = _Primitive.Max }; Node Leaf = new Node() { m_AABB = PrimAABB, m_Primitive = _Primitive }; m_Primitives.Add(_Primitive); if (m_Root == null) { // This is our new root m_Root = Leaf; return; } // Find the best Sibling for this node AABB LeafAABB = Leaf.m_AABB; Node Current = m_Root; while (!Leaf.IsLeaf) { Node Child0 = Leaf.Child0; Node Child1 = Leaf.Child1; float Area = Current.m_AABB.Perimeter; AABB CombinedAABB = Current.m_AABB; CombinedAABB.Combine(LeafAABB); float CombinedArea = CombinedAABB.Perimeter; // Cost of creating a new parent for this node and the new Leaf float Cost = 2.0f * CombinedArea; // Minimum Cost of pushing the Leaf further down the tree float InheritanceCost = 2.0f * (CombinedArea - Area); // Cost of descending into Child0 AABB aabb = LeafAABB; aabb.Combine(Child0.m_AABB); float Cost0; if (Child0.IsLeaf) { Cost0 = aabb.Perimeter + InheritanceCost; } else { float OldArea = Child0.m_AABB.Perimeter; float NewArea = aabb.Perimeter; Cost0 = (NewArea - OldArea) + InheritanceCost; } // Cost of descending into Child1 aabb = LeafAABB; aabb.Combine(Child1.m_AABB); float Cost1; if (Child1.IsLeaf) { Cost1 = aabb.Perimeter + InheritanceCost; } else { float OldArea = Child1.m_AABB.Perimeter; float NewArea = aabb.Perimeter; Cost1 = NewArea - OldArea + InheritanceCost; } // Descend according to the minimum Cost. if (Cost < Cost0 && Cost < Cost1) { break; } // Descend if (Cost0 < Cost1) { Current = Child0; } else { Current = Child1; } } Node Sibling = Current; // Create a new parent. Node OldParent = Sibling.m_Parent; Node NewParent = new Node() { m_Parent = OldParent, m_Height = Sibling.m_Height + 1 }; NewParent.m_AABB = LeafAABB; NewParent.m_AABB.Combine(Sibling.m_AABB); if (OldParent != null) { // The Sibling was not the root. if (OldParent.Child0 == Sibling) { OldParent.Child0 = NewParent; } else { OldParent.Child1 = NewParent; } NewParent.Child0 = Sibling; NewParent.Child1 = Leaf; Sibling.m_Parent = NewParent; Leaf.m_Parent = NewParent; } else { // The Sibling was the root. NewParent.Child0 = Sibling; NewParent.Child1 = Leaf; Sibling.m_Parent = NewParent; Leaf.m_Parent = NewParent; m_Root = NewParent; } // Walk back up the tree fixing heights and AABBs Current = Leaf.m_Parent; while (Current != null) { Current = Balance(Current); Node Child0 = Current.Child0; if (Child0 == null) { throw new Exception("Unexpected null child!"); } Node Child1 = Current.Child1; if (Child1 == null) { throw new Exception("Unexpected null child!"); } Current.m_Height = 1 + Math.Max(Child0.m_Height, Child1.m_Height); Current.m_AABB = Child0.m_AABB; Current.m_AABB.Combine(Child1.m_AABB); Current = Current.m_Parent; } }
private void InsertLeaf(int leaf) { ++_insertionCount; if (_root == NullNode) { _root = leaf; _nodes[_root].ParentOrNext = NullNode; return; } // Find the best sibling for this node AABB leafAABB = _nodes[leaf].AABB; int sibling = _root; while (_nodes[sibling].IsLeaf() == false) { int child1 = _nodes[sibling].Child1; int child2 = _nodes[sibling].Child2; // Expand the node's AABB. _nodes[sibling].AABB.Combine(ref leafAABB); _nodes[sibling].LeafCount += 1; float siblingArea = _nodes[sibling].AABB.Perimeter; AABB parentAABB = new AABB(); parentAABB.Combine(ref _nodes[sibling].AABB, ref leafAABB); float parentArea = parentAABB.Perimeter; float cost1 = 2.0f * parentArea; float inheritanceCost = 2.0f * (parentArea - siblingArea); float cost2; if (_nodes[child1].IsLeaf()) { AABB aabb = new AABB(); aabb.Combine(ref leafAABB, ref _nodes[child1].AABB); cost2 = aabb.Perimeter + inheritanceCost; } else { AABB aabb = new AABB(); aabb.Combine(ref leafAABB, ref _nodes[child1].AABB); float oldArea = _nodes[child1].AABB.Perimeter; float newArea = aabb.Perimeter; cost2 = (newArea - oldArea) + inheritanceCost; } float cost3; if (_nodes[child2].IsLeaf()) { AABB aabb = new AABB(); aabb.Combine(ref leafAABB, ref _nodes[child2].AABB); cost3 = aabb.Perimeter + inheritanceCost; } else { AABB aabb = new AABB(); aabb.Combine(ref leafAABB, ref _nodes[child2].AABB); float oldArea = _nodes[child2].AABB.Perimeter; float newArea = aabb.Perimeter; cost3 = newArea - oldArea + inheritanceCost; } // Descend according to the minimum cost. if (cost1 < cost2 && cost1 < cost3) { break; } // Expand the node's AABB to account for the new leaf. _nodes[sibling].AABB.Combine(ref leafAABB); // Descend if (cost2 < cost3) { sibling = child1; } else { sibling = child2; } } // Create a new parent for the siblings. int oldParent = _nodes[sibling].ParentOrNext; int newParent = AllocateNode(); _nodes[newParent].ParentOrNext = oldParent; _nodes[newParent].UserData = default(T); _nodes[newParent].AABB.Combine(ref leafAABB, ref _nodes[sibling].AABB); _nodes[newParent].LeafCount = _nodes[sibling].LeafCount + 1; if (oldParent != NullNode) { // The sibling was not the root. if (_nodes[oldParent].Child1 == sibling) { _nodes[oldParent].Child1 = newParent; } else { _nodes[oldParent].Child2 = newParent; } _nodes[newParent].Child1 = sibling; _nodes[newParent].Child2 = leaf; _nodes[sibling].ParentOrNext = newParent; _nodes[leaf].ParentOrNext = newParent; } else { // The sibling was the root. _nodes[newParent].Child1 = sibling; _nodes[newParent].Child2 = leaf; _nodes[sibling].ParentOrNext = newParent; _nodes[leaf].ParentOrNext = newParent; _root = newParent; } }
/// <summary> /// Build an optimal tree. Very expensive. For testing. /// </summary> public void RebuildBottomUp() { var nodes = new int[m_nodeCount]; int count = 0; // Build array of leaves. Free the rest. for (int i = 0; i < m_nodeCapacity; ++i) { if (m_nodes[i].Height < 0) { // free node in pool continue; } if (m_nodes[i].Leaf) { m_nodes[i].Parent = TreeNode.NULL_NODE; nodes[count] = i; ++count; } else { FreeNode(i); } } var b = new AABB(); while (count > 1) { float minCost = Single.MaxValue; int iMin = -1, jMin = -1; for (int i = 0; i < count; ++i) { AABB aabbi = m_nodes[nodes[i]].AABB; for (int j = i + 1; j < count; ++j) { AABB aabbj = m_nodes[nodes[j]].AABB; b.Combine(aabbi, aabbj); float cost = b.Perimeter; if (cost < minCost) { iMin = i; jMin = j; minCost = cost; } } } int index1 = nodes[iMin]; int index2 = nodes[jMin]; TreeNode child1 = m_nodes[index1]; TreeNode child2 = m_nodes[index2]; int parentIndex = AllocateNode(); TreeNode parent = m_nodes[parentIndex]; parent.Child1 = index1; parent.Child2 = index2; parent.Height = 1 + MathUtils.Max(child1.Height, child2.Height); parent.AABB.Combine(child1.AABB, child2.AABB); parent.Parent = TreeNode.NULL_NODE; child1.Parent = parentIndex; child2.Parent = parentIndex; nodes[jMin] = nodes[count - 1]; nodes[iMin] = parentIndex; --count; } m_root = nodes[0]; Validate(); }
private void ValidateMetrics(int index) { if (index == TreeNode.NULL_NODE) { return; } TreeNode node = m_nodes[index]; int child1 = node.Child1; int child2 = node.Child2; if (node.Leaf) { Debug.Assert(child1 == TreeNode.NULL_NODE); Debug.Assert(child2 == TreeNode.NULL_NODE); Debug.Assert(node.Height == 0); return; } Debug.Assert(0 <= child1 && child1 < m_nodeCapacity); Debug.Assert(0 <= child2 && child2 < m_nodeCapacity); int height1 = m_nodes[child1].Height; int height2 = m_nodes[child2].Height; int height = 1 + MathUtils.Max(height1, height2); Debug.Assert(node.Height == height); var aabb = new AABB(); aabb.Combine(m_nodes[child1].AABB, m_nodes[child2].AABB); Debug.Assert(aabb.LowerBound.Equals(node.AABB.LowerBound)); Debug.Assert(aabb.UpperBound.Equals(node.AABB.UpperBound)); ValidateMetrics(child1); ValidateMetrics(child2); }
private void FillAabb() { shape.ComputeAABB(out aabb, transform, 0); shape.ComputeAABB(out _End, _EndTransform, 0); aabb.Combine(_End); }
private void InsertLeaf(int leaf) { ++_insertionCount; if (_root == NullNode) { _root = leaf; _nodes[_root].ParentOrNext = NullNode; return; } // Find the best sibling for this node AABB leafAABB = _nodes[leaf].AABB; int sibling = _root; while (_nodes[sibling].IsLeaf() == false) { // Expand the node's AABB. _nodes[sibling].AABB.Combine(ref leafAABB); _nodes[sibling].LeafCount += 1; int child1 = _nodes[sibling].Child1; int child2 = _nodes[sibling].Child2; #if false // This seems to create imbalanced trees Vector2 delta1 = Math.Abs(_nodes[child1].aabb.GetCenter() - leafCenter); Vector2 delta2 = Math.Abs(_nodes[child2].aabb.GetCenter() - leafCenter); float norm1 = delta1.x + delta1.y; float norm2 = delta2.x + delta2.y; #else // Surface area heuristic AABB aabb1 = new AABB(); AABB aabb2 = new AABB(); aabb1.Combine(ref leafAABB, ref _nodes[child1].AABB); aabb2.Combine(ref leafAABB, ref _nodes[child2].AABB); float norm1 = (_nodes[child1].LeafCount + 1) * aabb1.Perimeter; float norm2 = (_nodes[child2].LeafCount + 1) * aabb2.Perimeter; #endif if (norm1 < norm2) { sibling = child1; } else { sibling = child2; } } // Create a new parent for the siblings. int oldParent = _nodes[sibling].ParentOrNext; int newParent = AllocateNode(); _nodes[newParent].ParentOrNext = oldParent; _nodes[newParent].UserData = null; _nodes[newParent].AABB.Combine(ref leafAABB, ref _nodes[sibling].AABB); _nodes[newParent].LeafCount = _nodes[sibling].LeafCount + 1; if (oldParent != NullNode) { // The sibling was not the root. if (_nodes[oldParent].Child1 == sibling) { _nodes[oldParent].Child1 = newParent; } else { _nodes[oldParent].Child2 = newParent; } _nodes[newParent].Child1 = sibling; _nodes[newParent].Child2 = leaf; _nodes[sibling].ParentOrNext = newParent; _nodes[leaf].ParentOrNext = newParent; } else { // The sibling was the root. _nodes[newParent].Child1 = sibling; _nodes[newParent].Child2 = leaf; _nodes[sibling].ParentOrNext = newParent; _nodes[leaf].ParentOrNext = newParent; _root = newParent; } }
private void InsertLeaf(int leaf) { InsertionCount++; if (m_root == TreeNode.NULL_NODE) { m_root = leaf; m_nodes[m_root].Parent = TreeNode.NULL_NODE; return; } // find the best sibling AABB leafAABB = m_nodes[leaf].AABB; int index = m_root; while (m_nodes[index].Leaf == false) { TreeNode node = m_nodes[index]; int child1 = node.Child1; int child2 = node.Child2; float area = node.AABB.Perimeter; combinedAABB.Combine(node.AABB, leafAABB); float combinedArea = combinedAABB.Perimeter; // Cost of creating a new parent for this node and the new leaf float cost = 2.0f * combinedArea; // Minimum cost of pushing the leaf further down the tree float inheritanceCost = 2.0f * (combinedArea - area); // Cost of descending into child1 float cost1; if (m_nodes[child1].Leaf) { combinedAABB.Combine(leafAABB, m_nodes[child1].AABB); cost1 = combinedAABB.Perimeter + inheritanceCost; } else { combinedAABB.Combine(leafAABB, m_nodes[child1].AABB); float oldArea = m_nodes[child1].AABB.Perimeter; float newArea = combinedAABB.Perimeter; cost1 = (newArea - oldArea) + inheritanceCost; } // Cost of descending into child2 float cost2; if (m_nodes[child2].Leaf) { combinedAABB.Combine(leafAABB, m_nodes[child2].AABB); cost2 = combinedAABB.Perimeter + inheritanceCost; } else { combinedAABB.Combine(leafAABB, m_nodes[child2].AABB); float oldArea = m_nodes[child2].AABB.Perimeter; float newArea = combinedAABB.Perimeter; cost2 = newArea - oldArea + inheritanceCost; } // Descend according to the minimum cost. if (cost < cost1 && cost < cost2) { break; } // Descend index = cost1 < cost2 ? child1 : child2; } int sibling = index; int oldParent = m_nodes[sibling].Parent; int newParentId = AllocateNode(); TreeNode newParent = m_nodes[newParentId]; newParent.Parent = oldParent; newParent.UserData = null; newParent.AABB.Combine(leafAABB, m_nodes[sibling].AABB); newParent.Height = m_nodes[sibling].Height + 1; if (oldParent != TreeNode.NULL_NODE) { // The sibling was not the root. if (m_nodes[oldParent].Child1 == sibling) { m_nodes[oldParent].Child1 = newParentId; } else { m_nodes[oldParent].Child2 = newParentId; } m_nodes[newParentId].Child1 = sibling; m_nodes[newParentId].Child2 = leaf; m_nodes[sibling].Parent = newParentId; m_nodes[leaf].Parent = newParentId; } else { // The sibling was the root. m_nodes[newParentId].Child1 = sibling; m_nodes[newParentId].Child2 = leaf; m_nodes[sibling].Parent = newParentId; m_nodes[leaf].Parent = newParentId; m_root = newParentId; } // Walk back up the tree fixing heights and AABBs index = m_nodes[leaf].Parent; while (index != TreeNode.NULL_NODE) { index = Balance(index); int child1 = m_nodes[index].Child1; int child2 = m_nodes[index].Child2; Debug.Assert(child1 != TreeNode.NULL_NODE); Debug.Assert(child2 != TreeNode.NULL_NODE); m_nodes[index].Height = 1 + MathUtils.Max(m_nodes[child1].Height, m_nodes[child2].Height); m_nodes[index].AABB.Combine(m_nodes[child1].AABB, m_nodes[child2].AABB); index = m_nodes[index].Parent; } // validate(); }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { CurrentFrameIndex++; DebugDrawCommands.Clear(); float deltaSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds; Perf.BeginSample(PerformanceSlots.InputUpdate); Input.Update(deltaSeconds); Perf.EndSample(PerformanceSlots.InputUpdate); if (Input.PlatformInput.WantsExit) { Exit(); } if (Input.PlatformInput.ToggleFullscreen) { graphics.ToggleFullScreen(); } #if DEBUG deltaSeconds *= Input.DebugInput.SpeedMultiplier; { ActiveCamera.Movement.MovementVector = Input.DebugMovement; } if (Input.DebugInput.ToggleMainDrawing) { MainDrawingEnabled = !MainDrawingEnabled; } if (Input.DebugInput.ToggleDebugDrawing) { DebugDrawingEnabled = !DebugDrawingEnabled; } if (Input.DebugInput.TogglePhysicsDebugView) { PhysicsDebugView.Enabled = !PhysicsDebugView.Enabled; } if (Input.DebugInput.ToggleCameraVisibilityBounds) { if (ActiveCamera.CameraComponent.VisibilityBounds == null) { ActiveCamera.CameraComponent.VisibilityBounds = CurrentLevel.LevelBounds; } else { ActiveCamera.CameraComponent.VisibilityBounds = null; } if (ActiveCamera.SpringArm.Target == null) { ActiveCamera.SpringArm.Target = Owliver; } else { ActiveCamera.SpringArm.Target = null; } } if (Input.DebugInput.ResetCameraPosition) { ActiveCamera.Spatial.Position = Owliver.GetWorldSpatialData().Position; } #endif { Owliver.Movement.MovementVector = Input.CharacterMovement; Owliver.Input = Input.CharacterInput; } // TODO(manu): Make use of `Input.CompationInput`! // Add pending game objects. GameObjects.AddRange(GameObjectsPendingAdd); foreach (GameObject go in GameObjectsPendingAdd) { go.Initialize(); go.PostInitialize(); } GameObjectsPendingAdd.Clear(); // Execute pre-physics update. foreach (GameObject go in GameObjects) { go.PrePhysicsUpdate(deltaSeconds); } // Physics simulation float simTime = _excessSimTime + deltaSeconds; Perf.BeginSample(PerformanceSlots.WorldStep); while (simTime > _secondsPerSimStep) { World.Step(_secondsPerSimStep); simTime -= _secondsPerSimStep; } Perf.EndSample(PerformanceSlots.WorldStep); _excessSimTime = simTime; CurrentLevel.Update(deltaSeconds); // Post-physics update. foreach (GameObject go in GameObjects) { go.Update(deltaSeconds); AABB aabb = Global.CreateInvalidAABB(); foreach (SpatialComponent sc in go.GetComponents <SpatialComponent>()) { AABB other = sc.GetWorldSpatialData().AbsoluteAABB; aabb.Combine(ref other); } DebugDrawCommands.Add(view => view.DrawPoint(aabb.Center, Conversion.ToMeters(3), Color.MonoGameOrange)); DebugDrawCommands.Add(view => view.DrawAABB(ref aabb, Color.Lime)); } // Remove pending game objects. GameObjects.RemoveAll(go => GameObjectsPendingRemove.Contains(go)); foreach (GameObject go in GameObjectsPendingRemove) { go.Destroy(); } GameObjectsPendingRemove.Clear(); base.Update(gameTime); Perf.AdvanceFrame(); }