package game;
import game.baseTypes.PhysicalObject;
import game.util.ConstrictedEvent;
import java.util.ArrayList;
import math.AxisAlignedBox;
import math.Vector;
public class Sector extends AxisAlignedBox {
private static final int MAX_SECTOR_SIZE = 31;
private Sector parent;
private Sector[] subSectors = null;
private ArrayList<PhysicalObject> children;
public Sector(Sector parent, Vector position, Vector size) {
super(position, size);
this.parent = parent;
this.children = new ArrayList<PhysicalObject>();
}
public boolean addObject(PhysicalObject object) {
if (!contains(object.getPosition())) {
return false;
}
if (children != null) {
children.add(object);
if (children.size() > MAX_SECTOR_SIZE) {
createSubSectors();
for (PhysicalObject child : children) {
for (Sector subSector : subSectors) {
if (subSector.addObject(child)) {
break;
}
}
}
children = null;
}
} else {
for (Sector subSector : subSectors) {
if (subSector.addObject(object)) {
break;
}
}
}
return true;
}
/**
* Called bottom-up from the leaf containing the event source.
* Searches for the smallest sector containing the whole event
* field, upon which then <code>applyEvent()</code> is called.
*/
public void emittEvent(ConstrictedEvent event) {
if (contains(event)) {
applyEvent(event);
} else if (parent != null) {
parent.emittEvent(event);
}
}
/**
* Finds the set of sub sectors just containing the event field, and applies
* the event on all objects within those sectors. This method can be called
* from the root sector, but better performance in sizeable systems may be
* reached by calling <code>emittEvent()</code> from the source leaf sector.
*/
public void applyEvent(ConstrictedEvent event) {
if (intersects(event)) {
if (children != null) {
for (PhysicalObject child : children) {
event.applyTo(child);
}
} else {
for (Sector subSector : subSectors) {
subSector.applyEvent(event);
}
}
}
}
public void clearDynamics() {
if (children != null) {
for (PhysicalObject child : children) {
child.clearForces();
}
} else {
for (Sector subSector : subSectors) {
subSector.clearDynamics();
}
}
}
private void createSubSectors() {
subSectors = new Sector[8];
Vector subSize = size.clone().scale(0.5f);
double dx = 0.5f * subSize.getX();
double dy = 0.5f * subSize.getY();
double dz = 0.5f * subSize.getZ();
for (int i = 0; i < 8; i++) {
Vector offset = new Vector(((i / 4) * 2 - 1) * dx,
(((i % 4) / 2) * 2 - 1) * dy, ((i % 2) * 2 - 1) * dz);
subSectors[i] = new Sector(this, offset.add(position), subSize);
}
}
}