Refactor physics

This commit is contained in:
schmelczerandras 2020-10-05 20:30:42 +02:00
parent 46a48e7c15
commit c5d97eeea6
40 changed files with 484 additions and 791 deletions

View file

@ -1,60 +1,60 @@
import { BoundingBoxBase } from '../bounding-boxes/bounding-box-base';
import { StaticPhysical } from './static-physical-object';
// source: https://github.com/ubilabs/kd-tree-javascript/blob/master/kdTree.js
import { ImmutableBoundingBox } from '../bounds/immutable-bounding-box';
class Node {
public left?: Node = null;
public right?: Node = null;
constructor(public rectangle: ImmutableBoundingBox, public parent: Node) {}
constructor(public object: StaticPhysical, public parent: Node) {}
}
export class BoundingBoxTree {
root?: Node;
constructor(boxes: Array<ImmutableBoundingBox> = []) {
this.build(boxes);
constructor(objects: Array<StaticPhysical> = []) {
this.build(objects);
}
public build(boxes: Array<ImmutableBoundingBox>) {
this.root = this.buildRecursive(boxes, 0, null);
public build(objects: Array<StaticPhysical>) {
this.root = this.buildRecursive(objects, 0, null);
}
private buildRecursive(
boxes: Array<ImmutableBoundingBox>,
objects: Array<StaticPhysical>,
depth: number,
parent: Node
): Node {
if (boxes.length === 0) {
if (objects.length === 0) {
return null;
}
if (boxes.length === 1) {
return new Node(boxes[0], parent);
if (objects.length === 1) {
return new Node(objects[0], parent);
}
const dimension = depth % 4;
boxes.sort((a, b) => a[dimension] - b[dimension]);
objects.sort((a, b) => a.boundingBox[dimension] - b.boundingBox[dimension]);
const median = Math.floor(boxes.length / 2);
const median = Math.floor(objects.length / 2);
const node = new Node(boxes[median], parent);
node.left = this.buildRecursive(boxes.slice(0, median), depth + 1, node);
node.right = this.buildRecursive(boxes.slice(median + 1), depth + 1, node);
const node = new Node(objects[median], parent);
node.left = this.buildRecursive(objects.slice(0, median), depth + 1, node);
node.right = this.buildRecursive(objects.slice(median + 1), depth + 1, node);
return node;
}
public insert(box: ImmutableBoundingBox) {
const [insertPosition, depth] = this.findParent(box, this.root, 0, null);
public insert(object: StaticPhysical) {
const [insertPosition, depth] = this.findParent(object, this.root, 0, null);
if (insertPosition === null) {
this.root = new Node(box, null);
this.root = new Node(object, null);
} else {
const node = new Node(box, insertPosition);
const node = new Node(object, insertPosition);
const dimension = depth % 4;
if (box[dimension] < insertPosition.rectangle[dimension]) {
if (object.boundingBox[dimension] < insertPosition.object.boundingBox[dimension]) {
insertPosition.left = node;
} else {
insertPosition.right = node;
@ -62,46 +62,46 @@ export class BoundingBoxTree {
}
}
public findIntersecting(box: ImmutableBoundingBox): Array<ImmutableBoundingBox> {
const maybeResults = this.findMaybeIntersecting(box, this.root, 0);
const results = maybeResults.filter((b) => b.intersects(box));
public findIntersecting(boundingBox: BoundingBoxBase): Array<StaticPhysical> {
const maybeResults = this.findMaybeIntersecting(boundingBox, this.root, 0);
const results = maybeResults.filter((b) => b.boundingBox.intersects(boundingBox));
return results;
}
private findMaybeIntersecting(
box: ImmutableBoundingBox,
boundingBox: BoundingBoxBase,
node: Node,
depth: number
): Array<ImmutableBoundingBox> {
): Array<StaticPhysical> {
if (node === null) {
return [];
}
if (depth % 4 == 0 && box.xMax < node.rectangle.xMin) {
return this.findMaybeIntersecting(box, node.left, depth + 1);
if (depth % 4 == 0 && boundingBox.xMax < node.object.boundingBox.xMin) {
return this.findMaybeIntersecting(boundingBox, node.left, depth + 1);
}
if (depth % 4 == 1 && box.xMin > node.rectangle.xMax) {
return this.findMaybeIntersecting(box, node.right, depth + 1);
if (depth % 4 == 1 && boundingBox.xMin > node.object.boundingBox.xMax) {
return this.findMaybeIntersecting(boundingBox, node.right, depth + 1);
}
if (depth % 4 == 2 && box.yMax < node.rectangle.yMin) {
return this.findMaybeIntersecting(box, node.left, depth + 1);
if (depth % 4 == 2 && boundingBox.yMax < node.object.boundingBox.yMin) {
return this.findMaybeIntersecting(boundingBox, node.left, depth + 1);
}
if (depth % 4 == 3 && box.yMin > node.rectangle.yMax) {
return this.findMaybeIntersecting(box, node.right, depth + 1);
if (depth % 4 == 3 && boundingBox.yMin > node.object.boundingBox.yMax) {
return this.findMaybeIntersecting(boundingBox, node.right, depth + 1);
}
return [
node.rectangle,
...this.findMaybeIntersecting(box, node.left, depth + 1),
...this.findMaybeIntersecting(box, node.right, depth + 1),
node.object,
...this.findMaybeIntersecting(boundingBox, node.left, depth + 1),
...this.findMaybeIntersecting(boundingBox, node.right, depth + 1),
];
}
private findParent(
box: ImmutableBoundingBox,
object: StaticPhysical,
node: Node,
depth: number,
parent: Node
@ -112,10 +112,10 @@ export class BoundingBoxTree {
const dimension = depth % 4;
if (box[dimension] < node.rectangle[dimension]) {
return this.findParent(box, node.left, depth + 1, node);
if (object.boundingBox[dimension] < node.object.boundingBox[dimension]) {
return this.findParent(object, node.left, depth + 1, node);
}
return this.findParent(box, node.right, depth + 1, node);
return this.findParent(object, node.right, depth + 1, node);
}
}