package com.igorcrevar.goingunder.collision; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; /** * Oriented boundary box or AA boundary box * @author crewce */ public class BoundingBox { private float centerX; private float centerY; private float width; private float height; private float originalAngle; private float ownerAngle; private Vector2[] tVertices; private Vector2 tCenter; private Vector2[] axes; private Vector2 tmp = new Vector2(); public BoundingBox() { this(0.0f, 0.0f, 0.0f, 0.0f, 0.0f); } public BoundingBox(float centerX, float centerY, float width, float height, float originalAngle) { this.centerX = centerX; this.centerY = centerY; this.width = width; this.height = height; this.originalAngle = originalAngle; this.ownerAngle = 0.0f; initVertices(); } public void populateFromRectangle(Rectangle rect) { width = rect.getWidth(); height = rect.getHeight(); originalAngle = 0.0f; centerX = width / 2.0f; centerY = height / 2.0f; this.update(rect.x, rect.y, 0.0f); } private void initVertices() { tCenter = new Vector2(); tVertices = new Vector2[4]; for (int i = 0; i < tVertices.length; ++i) { tVertices[i] = new Vector2(); } axes = new Vector2[4]; for (int i = 0; i < axes.length; ++i) { axes[i] = new Vector2(); } } public Vector2[] getVertices() { return tVertices; } public Vector2 getCenter() { return tCenter; } public float getOriginalAngle() { return originalAngle; } public float getOwnerAngle() { return ownerAngle; } public void setOriginalAngle(float v) { originalAngle = v; } public void setOwnerAngle(float v) { ownerAngle = v; } public float getWidth() { return width; } public float getHeight() { return height; } public void update(float x, float y, float ownerAngle) { this.ownerAngle = ownerAngle; // first calculate new current center tCenter.set(centerX, centerY); if (ownerAngle != 0.0f) { tCenter.rotate(ownerAngle); } tCenter.x += x; tCenter.y += y; // than caclulate vertices float h2 = height / 2.0f; float w2 = width / 2.0f; tVertices[0].set(-w2, -h2); tVertices[1].set( w2, -h2); tVertices[2].set( w2, h2); tVertices[3].set(-w2, h2); // rotate vertices (original angle + new angle) // add center to each for (int i = 0; i < tVertices.length; ++i) { tVertices[i].rotate(originalAngle + ownerAngle); tVertices[i].x += tCenter.x; tVertices[i].y += tCenter.y; } } public Vector2[] getAxes() { // loop over the vertices for (int i = 0; i < tVertices.length; i++) { // get the current vertex tmp.set(tVertices[i]); // get the next vertex Vector2 p2 = tVertices[i + 1 == tVertices.length ? 0 : i + 1]; // subtract the two to get the edge vector Vector2 edge = tmp.sub(p2); // get either perpendicular vector // the perp method is just (x, y) => (-y, x) or (y, -x) axes[i].set(-edge.y, edge.x).nor(); } return axes; } public Vector2 project(Vector2 axis) { float min = axis.dot(tVertices[0]); float max = min; for (int i = 1; i < tVertices.length; i++) { // NOTE: the axis must be normalized to get accurate projections float p = axis.dot(tVertices[i]); if (p < min) { min = p; } else if (p > max) { max = p; } } tmp.set(min, max); return tmp; } }