use of org.jbox2d.collision.AABB in project libgdx by libgdx.
the class DynamicTree method insertLeaf.
private final void insertLeaf(int leaf_index) {
DynamicTreeNode leaf = m_nodes[leaf_index];
if (m_root == null) {
m_root = leaf;
m_root.parent = null;
return;
}
// find the best sibling
AABB leafAABB = leaf.aabb;
DynamicTreeNode index = m_root;
while (index.child1 != null) {
final DynamicTreeNode node = index;
DynamicTreeNode child1 = node.child1;
DynamicTreeNode child2 = node.child2;
float area = node.aabb.getPerimeter();
combinedAABB.combine(node.aabb, leafAABB);
float combinedArea = combinedAABB.getPerimeter();
// 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 (child1.child1 == null) {
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;
}
// Cost of descending into child2
float cost2;
if (child2.child1 == null) {
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;
}
// Descend according to the minimum cost.
if (cost < cost1 && cost < cost2) {
break;
}
// Descend
if (cost1 < cost2) {
index = child1;
} else {
index = child2;
}
}
DynamicTreeNode sibling = index;
DynamicTreeNode oldParent = m_nodes[sibling.id].parent;
final DynamicTreeNode newParent = allocateNode();
newParent.parent = oldParent;
newParent.userData = null;
newParent.aabb.combine(leafAABB, sibling.aabb);
newParent.height = sibling.height + 1;
if (oldParent != null) {
// The sibling was not the root.
if (oldParent.child1 == sibling) {
oldParent.child1 = newParent;
} else {
oldParent.child2 = newParent;
}
newParent.child1 = sibling;
newParent.child2 = leaf;
sibling.parent = newParent;
leaf.parent = newParent;
} else {
// The sibling was the root.
newParent.child1 = sibling;
newParent.child2 = leaf;
sibling.parent = newParent;
leaf.parent = newParent;
m_root = newParent;
}
// Walk back up the tree fixing heights and AABBs
index = leaf.parent;
while (index != null) {
index = balance(index);
DynamicTreeNode child1 = index.child1;
DynamicTreeNode child2 = index.child2;
assert (child1 != null);
assert (child2 != null);
index.height = 1 + MathUtils.max(child1.height, child2.height);
index.aabb.combine(child1.aabb, child2.aabb);
index = index.parent;
}
// validate();
}
use of org.jbox2d.collision.AABB in project libgdx by libgdx.
the class DynamicTree method createProxy.
@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;
}
use of org.jbox2d.collision.AABB in project libgdx by libgdx.
the class DynamicTreeFlatNodes method moveProxy.
@Override
public final boolean moveProxy(int proxyId, final AABB aabb, Vec2 displacement) {
assert (0 <= proxyId && proxyId < m_nodeCapacity);
final int node = proxyId;
assert (m_child1[node] == NULL_NODE);
final AABB nodeAABB = m_aabb[node];
// if (nodeAABB.contains(aabb)) {
if (nodeAABB.lowerBound.x <= aabb.lowerBound.x && nodeAABB.lowerBound.y <= aabb.lowerBound.y && aabb.upperBound.x <= nodeAABB.upperBound.x && aabb.upperBound.y <= nodeAABB.upperBound.y) {
return false;
}
removeLeaf(node);
// Extend AABB
final Vec2 lowerBound = nodeAABB.lowerBound;
final Vec2 upperBound = nodeAABB.upperBound;
lowerBound.x = aabb.lowerBound.x - Settings.aabbExtension;
lowerBound.y = aabb.lowerBound.y - Settings.aabbExtension;
upperBound.x = aabb.upperBound.x + Settings.aabbExtension;
upperBound.y = aabb.upperBound.y + Settings.aabbExtension;
// Predict AABB displacement.
final float dx = displacement.x * Settings.aabbMultiplier;
final float dy = displacement.y * Settings.aabbMultiplier;
if (dx < 0.0f) {
lowerBound.x += dx;
} else {
upperBound.x += dx;
}
if (dy < 0.0f) {
lowerBound.y += dy;
} else {
upperBound.y += dy;
}
insertLeaf(proxyId);
return true;
}
use of org.jbox2d.collision.AABB in project libgdx by libgdx.
the class DynamicTreeFlatNodes method validateMetrics.
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);
}
use of org.jbox2d.collision.AABB in project libgdx by libgdx.
the class ParticleSystem method updateBodyContacts.
public void updateBodyContacts() {
final AABB aabb = temp;
aabb.lowerBound.x = Float.MAX_VALUE;
aabb.lowerBound.y = Float.MAX_VALUE;
aabb.upperBound.x = -Float.MAX_VALUE;
aabb.upperBound.y = -Float.MAX_VALUE;
for (int i = 0; i < m_count; i++) {
Vec2 p = m_positionBuffer.data[i];
Vec2.minToOut(aabb.lowerBound, p, aabb.lowerBound);
Vec2.maxToOut(aabb.upperBound, p, aabb.upperBound);
}
aabb.lowerBound.x -= m_particleDiameter;
aabb.lowerBound.y -= m_particleDiameter;
aabb.upperBound.x += m_particleDiameter;
aabb.upperBound.y += m_particleDiameter;
m_bodyContactCount = 0;
ubccallback.system = this;
m_world.queryAABB(ubccallback, aabb);
}
Aggregations