public void UpdateTest() { var tree = new AABBTree(true); var node = new AABBExternalNode() { Data = 1 }; tree.add(node, new AABBBox(new Point3(1, 1, 1), new Point3(10, 10, 10))); tree.add(new AABBExternalNode() { Data = 2 }, new AABBBox(new Point3(5, 5, 5), new Point3(15, 15, 15))); tree.finalize(); Assert.Equal(3, tree.getNodes().Count); tree.update(node, new AABBBox(new Point3(20, 20, 20), new Point3(33, 33, 33))); tree.finalize(); Assert.Equal(3, tree.getNodes().Count); var treeNode = tree.getNodes().FirstOrDefault(n => n.externalNode?.spatialIndex == node.spatialIndex); Assert.NotNull(treeNode); Assert.Equal(20, treeNode.extents[0]); Assert.Equal(20, treeNode.extents[1]); Assert.Equal(20, treeNode.extents[2]); Assert.Equal(33, treeNode.extents[3]); Assert.Equal(33, treeNode.extents[4]); Assert.Equal(33, treeNode.extents[5]); tree.clear(); Assert.Equal(0, tree.getNodes().Count); }
private AABBTreeRayTestResult DefaultCallback(AABBTree tree, AABBExternalNode node, AABBTreeRay ray, double distance, double upperBound) { return(new AABBTreeRayTestResult() { factor = Math.Min(distance, upperBound) }); }
public void clear() { this.escapeNodeOffset = 1; this.externalNode = null; var oldExtents = this.extents; var maxNumber = double.MaxValue; oldExtents[0] = maxNumber; oldExtents[1] = maxNumber; oldExtents[2] = maxNumber; oldExtents[3] = -maxNumber; oldExtents[4] = -maxNumber; oldExtents[5] = -maxNumber; }
public void reset(double minX, double minY, double minZ, double maxX, double maxY, double maxZ, int escapeNodeOffset, AABBExternalNode externalNode = null) { this.escapeNodeOffset = escapeNodeOffset; this.externalNode = externalNode; var oldExtents = this.extents; oldExtents[0] = minX; oldExtents[1] = minY; oldExtents[2] = minZ; oldExtents[3] = maxX; oldExtents[4] = maxY; oldExtents[5] = maxZ; }
public void remove(AABBExternalNode externalNode) { var index = externalNode.spatialIndex; if (index >= 0) { if (this.numExternalNodes > 1) { var nodes = this.nodes; Debug.Assert(nodes[index].externalNode == externalNode); nodes[index].clear(); var endNode = this.getNodeCount(); if ((index + 1) >= endNode) { while (nodes[endNode - 1].externalNode == null) // No leaf { endNode -= 1; } if (this.nodes.Count > endNode) { this.nodes.RemoveRange(endNode, this.nodes.Count - endNode); } } else { this.needsRebuild = true; } this.numExternalNodes -= 1; } else { this.clear(); } externalNode.spatialIndex = -1; } }
public void RemoveTest() { var tree = new AABBTree(true); var node = new AABBExternalNode() { Data = 1 }; tree.add(node, new AABBBox(new Point3(1, 1, 1), new Point3(10, 10, 10))); tree.add(new AABBExternalNode() { Data = 2 }, new AABBBox(new Point3(5, 5, 5), new Point3(15, 15, 15))); tree.finalize(); Assert.Equal(3, tree.getNodes().Count); tree.remove(node); tree.finalize(); Assert.Equal(1, tree.getNodes().Count); tree.clear(); Assert.Equal(0, tree.getNodes().Count); }
public void add(AABBExternalNode externalNode, AABBBox extents) { var endNode = this.getNodeCount(); externalNode.spatialIndex = endNode - 1; var node = new AABBTreeNode(new AABBBox(), 1, null); node.escapeNodeOffset = 1; node.externalNode = externalNode; var copyExtents = node.extents; copyExtents[0] = extents[0]; copyExtents[1] = extents[1]; copyExtents[2] = extents[2]; copyExtents[3] = extents[3]; copyExtents[4] = extents[4]; copyExtents[5] = extents[5]; this.nodes.Add(node); this.needsRebuild = true; this.numAdds += 1; this.numExternalNodes += 1; }
public void update(AABBExternalNode externalNode, AABBBox extents) { var index = externalNode.spatialIndex; if (index >= 0) { var min0 = extents[0]; var min1 = extents[1]; var min2 = extents[2]; var max0 = extents[3]; var max1 = extents[4]; var max2 = extents[5]; var needsRebuild = this.needsRebuild; var needsRebound = this.needsRebound; var nodes = this.nodes; var node = nodes[index]; Debug.Assert(node.externalNode == externalNode); var nodeExtents = node.extents; var doUpdate = (needsRebuild || needsRebound || nodeExtents[0] > min0 || nodeExtents[1] > min1 || nodeExtents[2] > min2 || nodeExtents[3] < max0 || nodeExtents[4] < max1 || nodeExtents[5] < max2); nodeExtents[0] = min0; nodeExtents[1] = min1; nodeExtents[2] = min2; nodeExtents[3] = max0; nodeExtents[4] = max1; nodeExtents[5] = max2; if (doUpdate) { if (!needsRebuild && 1 < nodes.Count) { this.numUpdates += 1; if (this.startUpdate > index) { this.startUpdate = index; if (this.endUpdate < index) { this.endUpdate = index; if (!needsRebound) { // force a rebound when things change too much if ((2 * this.numUpdates) > this.numExternalNodes) { this.needsRebound = true; } else { var parent = this.findParent(index); var parentExtents = parent.extents; if (parentExtents[0] > min0 || parentExtents[1] > min1 || parentExtents[2] > min2 || parentExtents[3] < max0 || parentExtents[4] < max1 || parentExtents[5] < max2) { this.needsRebound = true; } } } else { // force a rebuild when things change too much if (this.numUpdates > (3 * this.numExternalNodes)) { this.needsRebuild = true; this.numAdds = this.numUpdates; } } } } } else { this.add(externalNode, extents); } } } }
static void Main(string[] args) { // build tree var tree = new AABBTree(true); tree.add(new AABBExternalNode() { Data = 1 }, new AABBBox(new Point3(0, 0, 0), new Point3(10, 10, 10))); tree.add(new AABBExternalNode() { Data = 2 }, new AABBBox(new Point3(5, 5, 5), new Point3(15, 15, 15))); tree.add(new AABBExternalNode() { Data = 3 }, new AABBBox(new Point3(20, 20, 20), new Point3(30, 30, 30))); tree.add(new AABBExternalNode() { Data = 4 }, new AABBBox(new Point3(40, 40, 40), new Point3(50, 50, 50))); var node = new AABBExternalNode() { Data = 6 }; tree.add(node, new AABBBox(new Point3(50, 50, 50), new Point3(60, 60, 60))); var lastNode = new AABBExternalNode() { Data = 5 }; tree.add(lastNode, new AABBBox(new Point3(51, 51, 51), new Point3(60, 60, 60))); tree.finalize(); // remove tree.remove(node); tree.update(lastNode, new AABBBox(new Point3(51, 51, 51), new Point3(61, 61, 61))); tree.finalize(); // get parent var parent = tree.findParent(lastNode.spatialIndex); var children = tree.findChildren(1); // get all the overlapping pairs List <AABBExternalNode> overlappingNodes = new List <AABBExternalNode>(); var count = tree.getOverlappingPairs(overlappingNodes); Console.WriteLine($"Node Count:{count}"); overlappingNodes.ForEach(node => node.Print()); overlappingNodes.Clear(); // find overlapping nodes by bounding box var queryExtents = new AABBBox(new Point3(-40, -40, -40), new Point3(40, 40, 40)); count = tree.getOverlappingNodes(queryExtents, overlappingNodes); Console.WriteLine($"Node Count:{count}"); overlappingNodes.ForEach(node => node.Print()); overlappingNodes.Clear(); // find overlapping nodes by sphere count = tree.getSphereOverlappingNodes(new Point3(20, 20, 20), 21, overlappingNodes); Console.WriteLine($"Node Count:{count}"); overlappingNodes.ForEach(node => node.Print()); overlappingNodes.Clear(); // find nodes by planes var normal = new Vector3(0, 0, 1); var plane = new Plane3(normal.X, normal.Y, normal.Z, -20); count = tree.getVisibleNodes(new Plane3[] { plane }, overlappingNodes); Console.WriteLine($"Node Count:{count}"); overlappingNodes.ForEach(node => node.Print()); overlappingNodes.Clear(); // TODO: ray test var ray = new AABBTreeRay() { direction = new Vector3(1, 1, 1), origin = new Point3(), maxFactor = 30 }; var testRes = new AABBTreeRayTest().rayTest(new AABBTree[] { tree }, ray); tree.clear(); }
public AABBBox extents; // bounding box public AABBTreeNode(AABBBox extents, int escapeNodeOffset, AABBExternalNode externalNode) { this.escapeNodeOffset = escapeNodeOffset; this.externalNode = externalNode; this.extents = extents; }