AABB b = new AABB(); while (count > 1) { float minCost = Float.MAX_VALUE; b.combine(aabbi, aabbj); float cost = b.getPerimeter(); if (cost < minCost) { iMin = i; parent.child2 = child2; parent.height = 1 + MathUtils.max(child1.height, child2.height); parent.aabb.combine(child1.aabb, child2.aabb); parent.parent = null;
public void drawTree(DebugDraw argDraw, DynamicTreeNode node, int spot, int height) { node.aabb.getVertices(drawVecs); color.set(1, (height - spot) * 1f / height, (height - spot) * 1f / height); argDraw.drawPolygon(drawVecs, 4, color); argDraw.getViewportTranform().getWorldToScreen(node.aabb.upperBound, textVec); argDraw.drawString(textVec.x, textVec.y, node.id + "-" + (spot + 1) + "/" + height, color); if (node.child1 != null) { drawTree(argDraw, node.child1, spot + 1, height); } if (node.child2 != null) { drawTree(argDraw, node.child2, spot + 1, height); } } }
/** * @deprecated please use {@link #raycast(RayCastOutput, RayCastInput, IWorldPool)} for better * performance * @param output * @param input * @return */ public final boolean raycast(final RayCastOutput output, final RayCastInput input) { return raycast(output, input, new DefaultWorldPool(4, 4)); }
@Override public final void query(TreeCallback callback, AABB aabb) { assert(aabb.isValid()); nodeStackIndex = 0; nodeStack[nodeStackIndex++] = m_root; while (nodeStackIndex > 0) { DynamicTreeNode node = nodeStack[--nodeStackIndex]; if (node == null) { continue; } if (AABB.testOverlap(node.aabb, aabb)) { if (node.child1 == null) { boolean proceed = callback.treeCallback(node.id); if (!proceed) { return; } } else { if (nodeStack.length - nodeStackIndex - 2 <= 0) { DynamicTreeNode[] newBuffer = new DynamicTreeNode[nodeStack.length * 2]; System.arraycopy(nodeStack, 0, newBuffer, 0, nodeStack.length); nodeStack = newBuffer; } nodeStack[nodeStackIndex++] = node.child1; nodeStack[nodeStackIndex++] = node.child2; } } } }
float area = node.aabb.getPerimeter(); combinedAABB.combine(node.aabb, leafAABB); float combinedArea = combinedAABB.getPerimeter(); combinedAABB.combine(leafAABB, child1.aabb); cost1 = combinedAABB.getPerimeter() + inheritanceCost; } else { combinedAABB.combine(leafAABB, child1.aabb); float oldArea = child1.aabb.getPerimeter(); float newArea = combinedAABB.getPerimeter(); cost1 = (newArea - oldArea) + inheritanceCost; combinedAABB.combine(leafAABB, child2.aabb); cost2 = combinedAABB.getPerimeter() + inheritanceCost; } else { combinedAABB.combine(leafAABB, child2.aabb); float oldArea = child2.aabb.getPerimeter(); float newArea = combinedAABB.getPerimeter(); cost2 = newArea - oldArea + inheritanceCost; newParent.parent = oldParent; newParent.userData = null; newParent.aabb.combine(leafAABB, sibling.aabb); newParent.height = sibling.height + 1; index.aabb.combine(child1.aabb, child2.aabb);
protected AABB newInstance() { return new AABB(); } };
private void validateMetrics(int node) { if (node == NULL_NODE) { return; } int child1 = m_child1[node]; int child2 = m_child2[node]; if (child1 == NULL_NODE) { assert (child1 == NULL_NODE); assert (child2 == NULL_NODE); assert (m_height[node] == 0); return; } assert (child1 != NULL_NODE && 0 <= child1 && child1 < m_nodeCapacity); assert (child2 != child1 && 0 <= child2 && child2 < m_nodeCapacity); int height1 = m_height[child1]; int height2 = m_height[child2]; int height; height = 1 + MathUtils.max(height1, height2); assert (m_height[node] == height); AABB aabb = new AABB(); aabb.combine(m_aabb[child1], m_aabb[child2]); assert (aabb.lowerBound.equals(m_aabb[node].lowerBound)); assert (aabb.upperBound.equals(m_aabb[node].upperBound)); validateMetrics(child1); validateMetrics(child2); }
@Override public final void query(TreeCallback callback, AABB aabb) { nodeStackIndex = 0; nodeStack[nodeStackIndex++] = m_root; while (nodeStackIndex > 0) { int node = nodeStack[--nodeStackIndex]; if (node == NULL_NODE) { continue; } if (AABB.testOverlap(m_aabb[node], aabb)) { int child1 = m_child1[node]; if (child1 == NULL_NODE) { boolean proceed = callback.treeCallback(node); if (!proceed) { return; } } else { if (nodeStack.length - nodeStackIndex - 2 <= 0) { nodeStack = BufferUtils.reallocateBuffer(nodeStack, nodeStack.length, nodeStack.length * 2); } nodeStack[nodeStackIndex++] = child1; nodeStack[nodeStackIndex++] = m_child2[node]; } } } }
@Override public float getAreaRatio() { if (m_root == null) { return 0.0f; } final DynamicTreeNode root = m_root; float rootArea = root.aabb.getPerimeter(); float totalArea = 0.0f; for (int i = 0; i < m_nodeCapacity; ++i) { final DynamicTreeNode node = m_nodes[i]; if (node.height < 0) { // Free node in pool continue; } totalArea += node.aabb.getPerimeter(); } return totalArea / rootArea; }
A.child2 = iG; G.parent = iA; A.aabb.combine(B.aabb, G.aabb); C.aabb.combine(A.aabb, F.aabb); A.child2 = iF; F.parent = iA; A.aabb.combine(B.aabb, F.aabb); C.aabb.combine(A.aabb, G.aabb); A.child1 = iE; E.parent = iA; A.aabb.combine(C.aabb, E.aabb); B.aabb.combine(A.aabb, D.aabb); A.child1 = iD; D.parent = iA; A.aabb.combine(C.aabb, D.aabb); B.aabb.combine(A.aabb, E.aabb);
@Override public final int createProxy(final AABB aabb, Object userData) { assert(aabb.isValid()); final DynamicTreeNode node = allocateNode(); int proxyId = node.id; // Fatten the aabb final AABB nodeAABB = node.aabb; nodeAABB.lowerBound.x = aabb.lowerBound.x - Settings.aabbExtension; nodeAABB.lowerBound.y = aabb.lowerBound.y - Settings.aabbExtension; nodeAABB.upperBound.x = aabb.upperBound.x + Settings.aabbExtension; nodeAABB.upperBound.y = aabb.upperBound.y + Settings.aabbExtension; node.userData = userData; insertLeaf(proxyId); return proxyId; }
public void MoveProxy() { for (int i = 0; i < e_actorCount; ++i) { int j = MathUtils.abs(rand.nextInt() % e_actorCount); Actor actor = m_actors[j]; if (actor.proxyId == -1) { continue; } AABB aabb0 = new AABB(actor.aabb); MoveAABB(actor.aabb); Vec2 displacement = actor.aabb.getCenter().sub(aabb0.getCenter()); m_tree.moveProxy(actor.proxyId, new AABB(actor.aabb), displacement); return; } }
Fixture fixtureA = c.getFixtureA(); Fixture fixtureB = c.getFixtureB(); fixtureA.getAABB(c.getChildIndexA()).getCenterToOut(cA); fixtureB.getAABB(c.getChildIndexB()).getCenterToOut(cB); m_debugDraw.drawSegment(cA, cB, color);
private void expandBuffers(int oldSize, int newSize) { m_aabb = BufferUtils.reallocateBuffer(AABB.class, m_aabb, oldSize, newSize); m_userData = BufferUtils.reallocateBuffer(Object.class, m_userData, oldSize, newSize); m_parent = BufferUtils.reallocateBuffer(m_parent, oldSize, newSize); m_child1 = BufferUtils.reallocateBuffer(m_child1, oldSize, newSize); m_child2 = BufferUtils.reallocateBuffer(m_child2, oldSize, newSize); m_height = BufferUtils.reallocateBuffer(m_height, oldSize, newSize); // Build a linked list for the free list. for (int i = oldSize; i < newSize; i++) { m_aabb[i] = new AABB(); m_parent[i] = (i == newSize - 1) ? NULL_NODE : i + 1; m_height[i] = -1; m_child1[i] = -1; m_child2[i] = -1; } m_freeList = oldSize; }
private void validateMetrics(DynamicTreeNode node) { if (node == null) { return; } DynamicTreeNode child1 = node.child1; DynamicTreeNode child2 = node.child2; if (node.child1 == null) { assert (child1 == null); assert (child2 == null); assert (node.height == 0); return; } assert (child1 != null && 0 <= child1.id && child1.id < m_nodeCapacity); assert (child2 != null && 0 <= child2.id && child2.id < m_nodeCapacity); int height1 = child1.height; int height2 = child2.height; int height; height = 1 + MathUtils.max(height1, height2); assert (node.height == height); AABB aabb = new AABB(); aabb.combine(child1.aabb, child2.aabb); assert (aabb.lowerBound.equals(node.aabb.lowerBound)); assert (aabb.upperBound.equals(node.aabb.upperBound)); validateMetrics(child1); validateMetrics(child2); }
if (!AABB.testOverlap(nodeAABB, segAABB)) { continue;
@Override public final void query(TreeCallback callback, AABB aabb) { assert(aabb.isValid()); nodeStackIndex = 0; nodeStack[nodeStackIndex++] = m_root; while (nodeStackIndex > 0) { DynamicTreeNode node = nodeStack[--nodeStackIndex]; if (node == null) { continue; } if (AABB.testOverlap(node.aabb, aabb)) { if (node.child1 == null) { boolean proceed = callback.treeCallback(node.id); if (!proceed) { return; } } else { if (nodeStack.length - nodeStackIndex - 2 <= 0) { DynamicTreeNode[] newBuffer = new DynamicTreeNode[nodeStack.length * 2]; System.arraycopy(nodeStack, 0, newBuffer, 0, nodeStack.length); nodeStack = newBuffer; } nodeStack[nodeStackIndex++] = node.child1; nodeStack[nodeStackIndex++] = node.child2; } } } }
int child2 = m_child2[node]; final AABB nodeAABB = m_aabb[node]; float area = nodeAABB.getPerimeter(); combinedAABB.combine(nodeAABB, leafAABB); float combinedArea = combinedAABB.getPerimeter(); AABB child1AABB = m_aabb[child1]; if (m_child1[child1] == NULL_NODE) { combinedAABB.combine(leafAABB, child1AABB); cost1 = combinedAABB.getPerimeter() + inheritanceCost; } else { combinedAABB.combine(leafAABB, child1AABB); float oldArea = child1AABB.getPerimeter(); float newArea = combinedAABB.getPerimeter(); cost1 = (newArea - oldArea) + inheritanceCost; AABB child2AABB = m_aabb[child2]; if (m_child1[child2] == NULL_NODE) { combinedAABB.combine(leafAABB, child2AABB); cost2 = combinedAABB.getPerimeter() + inheritanceCost; } else { combinedAABB.combine(leafAABB, child2AABB); float oldArea = child2AABB.getPerimeter(); float newArea = combinedAABB.getPerimeter(); cost2 = newArea - oldArea + inheritanceCost; m_parent[newParent] = oldParent; m_userData[newParent] = null;
@Override public float getAreaRatio() { if (m_root == NULL_NODE) { return 0.0f; } final int root = m_root; float rootArea = m_aabb[root].getPerimeter(); float totalArea = 0.0f; for (int i = 0; i < m_nodeCapacity; ++i) { if (m_height[i] < 0) { // Free node in pool continue; } totalArea += m_aabb[i].getPerimeter(); } return totalArea / rootArea; }
m_child2[A] = iG; m_parent[G] = iA; m_aabb[A].combine(m_aabb[B], m_aabb[G]); m_aabb[C].combine(m_aabb[A], m_aabb[F]); m_child2[A] = iF; m_parent[F] = iA; m_aabb[A].combine(m_aabb[B], m_aabb[F]); m_aabb[C].combine(m_aabb[A], m_aabb[G]); m_child1[A] = iE; m_parent[E] = iA; m_aabb[A].combine(m_aabb[C], m_aabb[E]); m_aabb[B].combine(m_aabb[A], m_aabb[D]); m_child1[A] = iD; m_parent[D] = iA; m_aabb[A].combine(m_aabb[C], m_aabb[D]); m_aabb[B].combine(m_aabb[A], m_aabb[E]);