mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2026-04-26 12:41:40 +00:00
undo mbp port
This commit is contained in:
parent
295901f951
commit
0523bb946b
5 changed files with 342 additions and 247 deletions
|
|
@ -1294,6 +1294,11 @@ class Marble extends GameObject {
|
||||||
var a = retf[1];
|
var a = retf[1];
|
||||||
this.velocity = this.velocity.add(A.multiply(timeStep));
|
this.velocity = this.velocity.add(A.multiply(timeStep));
|
||||||
this.omega = this.omega.add(a.multiply(timeStep));
|
this.omega = this.omega.add(a.multiply(timeStep));
|
||||||
|
if (this.mode == Start) {
|
||||||
|
// Bruh...
|
||||||
|
this.velocity.y = 0;
|
||||||
|
this.velocity.x = 0;
|
||||||
|
}
|
||||||
stoppedPaths = this.velocityCancel(timeState.currentAttemptTime, timeStep, isCentered, true, stoppedPaths, pathedInteriors);
|
stoppedPaths = this.velocityCancel(timeState.currentAttemptTime, timeStep, isCentered, true, stoppedPaths, pathedInteriors);
|
||||||
this._totalTime += timeStep;
|
this._totalTime += timeStep;
|
||||||
if (contacts.length != 0) {
|
if (contacts.length != 0) {
|
||||||
|
|
@ -1367,30 +1372,6 @@ class Marble extends GameObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var pos = this.getAbsPos().getPosition();
|
|
||||||
this.prevPos = pos.clone();
|
|
||||||
|
|
||||||
if (mode == Start) {
|
|
||||||
var upVec = this.level.currentUp;
|
|
||||||
var startpadNormal = startPad.getAbsPos().up();
|
|
||||||
this.velocity = upVec.multiply(this.velocity.dot(upVec));
|
|
||||||
// Apply contact forces in startPad up direction if upVec is not startpad up, fixes the weird startpad shit in pinball wizard
|
|
||||||
if (upVec.dot(startpadNormal) < 0.95) {
|
|
||||||
for (contact in contacts) {
|
|
||||||
var normF = contact.normal.multiply(contact.normalForce);
|
|
||||||
var startpadF = startpadNormal.multiply(normF.dot(startpadNormal));
|
|
||||||
var upF = upVec.multiply(normF.dot(upVec));
|
|
||||||
this.velocity = this.velocity.add(startpadF.multiply(timeStep / 4));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (mode == Finish) {
|
|
||||||
// this.velocity = this.velocity.multiply(0.925);
|
|
||||||
// }
|
|
||||||
|
|
||||||
var newPos = pos.add(this.velocity.multiply(timeStep));
|
|
||||||
newPos = nudgeToContacts(newPos, _radius);
|
|
||||||
var rot = this.getRotationQuat();
|
var rot = this.getRotationQuat();
|
||||||
var quat = new Quat();
|
var quat = new Quat();
|
||||||
quat.initRotation(omega.x * timeStep, omega.y * timeStep, omega.z * timeStep);
|
quat.initRotation(omega.x * timeStep, omega.y * timeStep, omega.z * timeStep);
|
||||||
|
|
|
||||||
|
|
@ -971,16 +971,11 @@ class MarbleWorld extends Scheduler {
|
||||||
if (timeTravelSound == null) {
|
if (timeTravelSound == null) {
|
||||||
var ttsnd = ResourceLoader.getResource("data/sound/timetravelactive.wav", ResourceLoader.getAudio, this.soundResources);
|
var ttsnd = ResourceLoader.getResource("data/sound/timetravelactive.wav", ResourceLoader.getAudio, this.soundResources);
|
||||||
timeTravelSound = AudioManager.playSound(ttsnd, null, true);
|
timeTravelSound = AudioManager.playSound(ttsnd, null, true);
|
||||||
|
|
||||||
if (alarmSound != null)
|
|
||||||
alarmSound.pause = true;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (timeTravelSound != null) {
|
if (timeTravelSound != null) {
|
||||||
timeTravelSound.stop();
|
timeTravelSound.stop();
|
||||||
timeTravelSound = null;
|
timeTravelSound = null;
|
||||||
if (alarmSound != null)
|
|
||||||
alarmSound.pause = false;
|
|
||||||
}
|
}
|
||||||
if (this.timeState.currentAttemptTime >= 3.5)
|
if (this.timeState.currentAttemptTime >= 3.5)
|
||||||
this.timeState.gameplayClock += dt;
|
this.timeState.gameplayClock += dt;
|
||||||
|
|
@ -1063,8 +1058,6 @@ class MarbleWorld extends Scheduler {
|
||||||
val = Util.getKeyForButton(Settings.controlsSettings.powerup);
|
val = Util.getKeyForButton(Settings.controlsSettings.powerup);
|
||||||
if (funcdata[1] == "freelook")
|
if (funcdata[1] == "freelook")
|
||||||
val = Util.getKeyForButton(Settings.controlsSettings.freelook);
|
val = Util.getKeyForButton(Settings.controlsSettings.freelook);
|
||||||
if (funcdata[1] == "useblast")
|
|
||||||
val = Util.getKeyForButton(Settings.controlsSettings.blast);
|
|
||||||
}
|
}
|
||||||
start = val.length + pos;
|
start = val.length + pos;
|
||||||
text = pre + val + post;
|
text = pre + val + post;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package collision;
|
package collision;
|
||||||
|
|
||||||
|
import h3d.Vector;
|
||||||
import h3d.col.Bounds;
|
import h3d.col.Bounds;
|
||||||
|
|
||||||
interface IBVHObject {
|
interface IBVHObject {
|
||||||
|
|
@ -17,217 +18,348 @@ class BVHNode<T:IBVHObject> {
|
||||||
var bounds:Bounds;
|
var bounds:Bounds;
|
||||||
var object:T;
|
var object:T;
|
||||||
|
|
||||||
public function new(bounds:Bounds) {
|
public function new() {}
|
||||||
this.bounds = bounds.clone();
|
}
|
||||||
surfaceArea = this.bounds.xSize * this.bounds.ySize + this.bounds.xSize * this.bounds.zSize + this.bounds.ySize * this.bounds.zSize;
|
|
||||||
|
class BVHTree<T:IBVHObject> {
|
||||||
|
var nodeId:Int = 0;
|
||||||
|
var root:BVHNode<T>;
|
||||||
|
|
||||||
|
public function new() {}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
var invalidNodes = [];
|
||||||
|
this.traverse(node -> {
|
||||||
|
if (node.isLeaf) {
|
||||||
|
var entity = node.object;
|
||||||
|
var tightAABB = entity.boundingBox;
|
||||||
|
|
||||||
|
if (node.bounds.containsBounds(tightAABB)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidNodes.push(node);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
for (node in invalidNodes) {
|
||||||
|
this.remove(node);
|
||||||
|
this.add(node.object);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BVHTree<T:IBVHObject> {
|
public function add(entity:T) {
|
||||||
var nodeId:Int = 0;
|
// Enlarged AABB
|
||||||
var root:BVHNode<T>;
|
var aabb = entity.boundingBox;
|
||||||
|
|
||||||
public function new() {}
|
var newNode = new BVHNode();
|
||||||
|
newNode.id = this.nodeId++;
|
||||||
|
newNode.bounds = aabb;
|
||||||
|
newNode.object = entity;
|
||||||
|
newNode.isLeaf = true;
|
||||||
|
|
||||||
function update() {
|
if (this.root == null) {
|
||||||
var invalidNodes = [];
|
this.root = newNode;
|
||||||
this.traverse(node -> {
|
return newNode;
|
||||||
if (node.isLeaf) {
|
}
|
||||||
var entity = node.object;
|
|
||||||
var tightAABB = entity.boundingBox;
|
|
||||||
|
|
||||||
if (node.bounds.containsBounds(tightAABB)) {
|
// Find the best sibling for the new leaf
|
||||||
return;
|
var bestSibling = this.root;
|
||||||
|
var bestCostBox = this.root.bounds.clone();
|
||||||
|
bestCostBox.add(aabb);
|
||||||
|
var bestCost = bestCostBox.xSize * bestCostBox.ySize + bestCostBox.xSize * bestCostBox.zSize + bestCostBox.ySize * bestCostBox.zSize;
|
||||||
|
var q = [{p1: this.root, p2: 0.0}];
|
||||||
|
|
||||||
|
while (q.length != 0) {
|
||||||
|
var front = q.shift();
|
||||||
|
var current = front.p1;
|
||||||
|
var inheritedCost = front.p2;
|
||||||
|
|
||||||
|
var combined = current.bounds.clone();
|
||||||
|
combined.add(aabb);
|
||||||
|
var directCost = combined.xSize * combined.ySize + combined.xSize * combined.zSize + combined.ySize * combined.zSize;
|
||||||
|
|
||||||
|
var costForCurrent = directCost + inheritedCost;
|
||||||
|
if (costForCurrent < bestCost) {
|
||||||
|
bestCost = costForCurrent;
|
||||||
|
bestSibling = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
inheritedCost += directCost
|
||||||
|
- (current.bounds.xSize * current.bounds.ySize + current.bounds.xSize * current.bounds.zSize + current.bounds.ySize * current.bounds.zSize);
|
||||||
|
|
||||||
|
var aabbCost = aabb.xSize * aabb.ySize + aabb.xSize * aabb.zSize + aabb.ySize * aabb.zSize;
|
||||||
|
var lowerBoundCost = aabbCost + inheritedCost;
|
||||||
|
if (lowerBoundCost < bestCost) {
|
||||||
|
if (!current.isLeaf) {
|
||||||
|
if (current.child1 != null)
|
||||||
|
q.push({p1: current.child1, p2: inheritedCost});
|
||||||
|
if (current.child2 != null)
|
||||||
|
q.push({p1: current.child2, p2: inheritedCost});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new parent
|
||||||
|
var oldParent = bestSibling.parent;
|
||||||
|
var newParent = new BVHNode();
|
||||||
|
newParent.id = this.nodeId++;
|
||||||
|
newParent.parent = oldParent;
|
||||||
|
newParent.bounds = bestSibling.bounds.clone();
|
||||||
|
newParent.bounds.add(aabb);
|
||||||
|
newParent.isLeaf = false;
|
||||||
|
|
||||||
|
if (oldParent != null) {
|
||||||
|
if (oldParent.child1 == bestSibling) {
|
||||||
|
oldParent.child1 = newParent;
|
||||||
|
} else {
|
||||||
|
oldParent.child2 = newParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
newParent.child1 = bestSibling;
|
||||||
|
newParent.child2 = newNode;
|
||||||
|
bestSibling.parent = newParent;
|
||||||
|
newNode.parent = newParent;
|
||||||
|
} else {
|
||||||
|
newParent.child1 = bestSibling;
|
||||||
|
newParent.child2 = newNode;
|
||||||
|
bestSibling.parent = newParent;
|
||||||
|
newNode.parent = newParent;
|
||||||
|
this.root = newParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk back up the tree refitting ancestors' AABB and applying rotations
|
||||||
|
var ancestor = newNode.parent;
|
||||||
|
|
||||||
|
while (ancestor != null) {
|
||||||
|
var child1 = ancestor.child1;
|
||||||
|
var child2 = ancestor.child2;
|
||||||
|
|
||||||
|
ancestor.bounds = new Bounds();
|
||||||
|
if (child1 != null)
|
||||||
|
ancestor.bounds.add(child1.bounds);
|
||||||
|
if (child2 != null)
|
||||||
|
ancestor.bounds.add(child2.bounds);
|
||||||
|
|
||||||
|
this.rotate(ancestor);
|
||||||
|
|
||||||
|
ancestor = ancestor.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
this.nodeId = 0;
|
||||||
|
this.root = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BFS tree traversal
|
||||||
|
function traverse(callback:(node:BVHNode<T>) -> Void) {
|
||||||
|
var q = [this.root];
|
||||||
|
|
||||||
|
while (q.length != 0) {
|
||||||
|
var current = q.shift();
|
||||||
|
if (current == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(current);
|
||||||
|
|
||||||
|
if (!current.isLeaf) {
|
||||||
|
if (current.child1 != null)
|
||||||
|
q.push(current.child1);
|
||||||
|
if (current.child2 != null)
|
||||||
|
q.push(current.child2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function remove(node:BVHNode<T>) {
|
||||||
|
var parent = node.parent;
|
||||||
|
|
||||||
|
if (parent != null) {
|
||||||
|
var sibling = parent.child1 == node ? parent.child2 : parent.child1;
|
||||||
|
|
||||||
|
if (parent.parent != null) {
|
||||||
|
sibling.parent = parent.parent;
|
||||||
|
if (parent.parent.child1 == parent) {
|
||||||
|
parent.parent.child1 = sibling;
|
||||||
|
} else {
|
||||||
|
parent.parent.child2 = sibling;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.root = sibling;
|
||||||
|
sibling.parent = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ancestor = sibling.parent;
|
||||||
|
while (ancestor != null) {
|
||||||
|
var child1 = ancestor.child1;
|
||||||
|
var child2 = ancestor.child2;
|
||||||
|
|
||||||
|
ancestor.bounds = child1.bounds.clone();
|
||||||
|
ancestor.bounds.add(child2.bounds);
|
||||||
|
ancestor = ancestor.parent;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.root == node) {
|
||||||
|
this.root = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function rotate(node:BVHNode<T>) {
|
||||||
|
if (node.parent == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var parent = node.parent;
|
||||||
|
var sibling = parent.child1 == node ? parent.child2 : parent.child1;
|
||||||
|
var costDiffs = [];
|
||||||
|
var nodeArea = node.bounds.xSize * node.bounds.ySize + node.bounds.zSize * node.bounds.ySize + node.bounds.xSize * node.bounds.zSize;
|
||||||
|
|
||||||
|
var ch1 = sibling.bounds.clone();
|
||||||
|
ch1.add(node.child1.bounds);
|
||||||
|
costDiffs.push(ch1.xSize * ch1.ySize + ch1.zSize * ch1.ySize + ch1.xSize * ch1.zSize - nodeArea);
|
||||||
|
var ch2 = sibling.bounds.clone();
|
||||||
|
ch2.add(node.child2.bounds);
|
||||||
|
costDiffs.push(ch2.xSize * ch2.ySize + ch2.zSize * ch2.ySize + ch2.xSize * ch2.zSize - nodeArea);
|
||||||
|
|
||||||
|
if (!sibling.isLeaf) {
|
||||||
|
var siblingArea = sibling.bounds.xSize * sibling.bounds.ySize + sibling.bounds.zSize * sibling.bounds.ySize
|
||||||
|
+ sibling.bounds.xSize * sibling.bounds.zSize;
|
||||||
|
if (sibling.child1 != null) {
|
||||||
|
var ch3 = node.bounds.clone();
|
||||||
|
ch3.add(sibling.child1.bounds);
|
||||||
|
costDiffs.push(ch3.xSize * ch3.ySize + ch3.zSize * ch3.ySize + ch3.xSize * ch3.zSize - siblingArea);
|
||||||
|
}
|
||||||
|
if (sibling.child2 != null) {
|
||||||
|
var ch4 = node.bounds.clone();
|
||||||
|
ch4.add(sibling.child2.bounds);
|
||||||
|
costDiffs.push(ch4.xSize * ch4.ySize + ch4.zSize * ch4.ySize + ch4.xSize * ch4.zSize - siblingArea);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var bestDiffIndex = 0;
|
||||||
|
for (i in 1...costDiffs.length) {
|
||||||
|
if (costDiffs[i] < costDiffs[bestDiffIndex]) {
|
||||||
|
bestDiffIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (costDiffs[bestDiffIndex] < 0.0) {
|
||||||
|
switch (bestDiffIndex) {
|
||||||
|
case 0:
|
||||||
|
if (parent.child1 == sibling) {
|
||||||
|
parent.child1 = node.child2;
|
||||||
|
} else {
|
||||||
|
parent.child2 = node.child2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function split() {
|
if (node.child2 != null) {
|
||||||
// Splitting first time
|
node.child2.parent = parent;
|
||||||
// Calculate the centroids of all objects
|
}
|
||||||
var objs = objects.map(x -> {
|
|
||||||
x.generateBoundingBox();
|
|
||||||
return {obj: x, centroid: x.boundingBox.getCenter()};
|
|
||||||
});
|
|
||||||
for (node in invalidNodes) {
|
|
||||||
this.remove(node);
|
|
||||||
this.add(node.object);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function add(entity:T) {
|
node.child2 = sibling;
|
||||||
// Enlarged AABB
|
sibling.parent = node;
|
||||||
var aabb = entity.boundingBox;
|
node.bounds = sibling.bounds.clone();
|
||||||
|
if (node.child1 != null) {
|
||||||
|
node.bounds.add(node.child1.bounds);
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if (parent.child1 == sibling) {
|
||||||
|
parent.child1 = node.child1;
|
||||||
|
} else {
|
||||||
|
parent.child2 = node.child1;
|
||||||
|
}
|
||||||
|
if (node.child1 != null) {
|
||||||
|
node.child1.parent = parent;
|
||||||
|
}
|
||||||
|
node.child1 = sibling;
|
||||||
|
sibling.parent = node;
|
||||||
|
node.bounds = sibling.bounds.clone();
|
||||||
|
if (node.child2 != null) {
|
||||||
|
node.bounds.add(node.child2.bounds);
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if (parent.child1 == node) {
|
||||||
|
parent.child1 = sibling.child2;
|
||||||
|
} else {
|
||||||
|
parent.child2 = sibling.child2;
|
||||||
|
}
|
||||||
|
if (sibling.child2 != null) {
|
||||||
|
sibling.child2.parent = parent;
|
||||||
|
}
|
||||||
|
sibling.child2 = node;
|
||||||
|
node.parent = sibling;
|
||||||
|
sibling.bounds = node.bounds.clone();
|
||||||
|
if (sibling.child2 != null) {
|
||||||
|
sibling.bounds.add(sibling.child2.bounds);
|
||||||
|
}
|
||||||
|
|
||||||
var newNode = new BVHNode();
|
case 3:
|
||||||
newNode.id = this.nodeId++;
|
if (parent.child1 == node) {
|
||||||
newNode.bounds = aabb;
|
parent.child1 = sibling.child1;
|
||||||
newNode.object = entity;
|
} else {
|
||||||
newNode.isLeaf = true;
|
parent.child2 = sibling.child1;
|
||||||
|
}
|
||||||
|
if (sibling.child1 != null) {
|
||||||
|
sibling.child1.parent = parent;
|
||||||
|
}
|
||||||
|
sibling.child1 = node;
|
||||||
|
node.parent = sibling;
|
||||||
|
sibling.bounds = node.bounds.clone();
|
||||||
|
if (sibling.child1 != null) {
|
||||||
|
sibling.bounds.add(sibling.child1.bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.root == null) {
|
public function boundingSearch(searchbox:Bounds) {
|
||||||
this.root = newNode;
|
var res = [];
|
||||||
return newNode;
|
if (this.root == null)
|
||||||
}
|
return res;
|
||||||
|
|
||||||
// Make the child nodes
|
var q = [this.root];
|
||||||
var leftBounds = new Bounds();
|
|
||||||
var rightBounds = new Bounds();
|
|
||||||
for (o in leftObjs)
|
|
||||||
leftBounds.add(o.boundingBox);
|
|
||||||
for (o in rightObjs)
|
|
||||||
rightBounds.add(o.boundingBox);
|
|
||||||
left = new BVHNode(leftBounds);
|
|
||||||
right = new BVHNode(rightBounds);
|
|
||||||
left.objects = leftObjs;
|
|
||||||
right.objects = rightObjs;
|
|
||||||
this.objects = intersectObjs;
|
|
||||||
this.objectBounds = new Bounds();
|
|
||||||
for (o in intersectObjs)
|
|
||||||
this.objectBounds.add(o.boundingBox);
|
|
||||||
|
|
||||||
left.split();
|
while (q.length != 0) {
|
||||||
right.split();
|
var current = q.shift();
|
||||||
}
|
|
||||||
|
|
||||||
public function boundingSearch(searchbox:Bounds) {
|
if (current.bounds.containsBounds(searchbox) || current.bounds.collide(searchbox)) {
|
||||||
if (this.bounds.containsBounds(searchbox) || this.bounds.collide(searchbox)) {
|
if (current.isLeaf) {
|
||||||
var intersects = [];
|
res.push(current.object);
|
||||||
if (this.left != null && this.right != null) {
|
} else {
|
||||||
intersects = intersects.concat(this.left.boundingSearch(searchbox));
|
if (current.child1 != null)
|
||||||
intersects = intersects.concat(this.right.boundingSearch(searchbox));
|
q.push(current.child1);
|
||||||
}
|
if (current.child2 != null)
|
||||||
if (this.objectBounds.collide(searchbox) || this.objectBounds.containsBounds(searchbox)) {
|
q.push(current.child2);
|
||||||
for (o in this.objects) {
|
}
|
||||||
if (o.boundingBox.containsBounds(searchbox) || o.boundingBox.collide(searchbox))
|
}
|
||||||
intersects.push(o);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return intersects;
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function reset() {
|
return res;
|
||||||
this.nodeId = 0;
|
}
|
||||||
this.root = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// BFS tree traversal
|
public function rayCast(origin:Vector, direction:Vector) {
|
||||||
function traverse(callback:(node:BVHNode<T>) -> Void) {
|
var res = [];
|
||||||
var q = [this.root];
|
if (this.root == null)
|
||||||
|
return res;
|
||||||
|
|
||||||
while (q.length != 0) {
|
var ray = h3d.col.Ray.fromValues(origin.x, origin.y, origin.z, direction.x, direction.y, direction.z);
|
||||||
var current = q.shift();
|
var q = [this.root];
|
||||||
if (current == null) {
|
while (q.length != 0) {
|
||||||
break;
|
var current = q.shift();
|
||||||
}
|
if (ray.collide(current.bounds)) {
|
||||||
|
if (current.isLeaf) {
|
||||||
callback(current);
|
res = res.concat(current.object.rayCast(origin, direction));
|
||||||
|
} else {
|
||||||
if (!current.isLeaf) {
|
if (current.child1 != null)
|
||||||
if (current.child1 != null)
|
q.push(current.child1);
|
||||||
q.push(current.child1);
|
if (current.child2 != null)
|
||||||
if (current.child2 != null)
|
q.push(current.child2);
|
||||||
q.push(current.child2);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return res;
|
||||||
|
}
|
||||||
public function remove(node:BVHNode<T>) {
|
}
|
||||||
var parent = node.parent;
|
|
||||||
|
|
||||||
if (parent != null) {
|
|
||||||
var sibling = parent.child1 == node ? parent.child2 : parent.child1;
|
|
||||||
|
|
||||||
if (parent.parent != null) {
|
|
||||||
sibling.parent = parent.parent;
|
|
||||||
if (parent.parent.child1 == parent) {
|
|
||||||
parent.parent.child1 = sibling;
|
|
||||||
} else {
|
|
||||||
parent.parent.child2 = sibling;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return intersects;
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function rotate(node:BVHNode<T>) {
|
|
||||||
if (node.parent == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var parent = node.parent;
|
|
||||||
var sibling = parent.child1 == node ? parent.child2 : parent.child1;
|
|
||||||
var costDiffs = [];
|
|
||||||
var nodeArea = node.bounds.xSize * node.bounds.ySize + node.bounds.zSize * node.bounds.ySize
|
|
||||||
+ node.bounds.xSize * node.bounds.zSize;
|
|
||||||
|
|
||||||
class BVHTree {
|
|
||||||
public var bounds:Bounds;
|
|
||||||
|
|
||||||
var surfaces:Array<CollisionSurface> = [];
|
|
||||||
|
|
||||||
var root:BVHNode;
|
|
||||||
|
|
||||||
public function new(bounds:Bounds) {
|
|
||||||
this.bounds = bounds.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function insert(surf:CollisionSurface) {
|
|
||||||
surfaces.push(surf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function build() {
|
|
||||||
root = new BVHNode(bounds);
|
|
||||||
// Add all children
|
|
||||||
root.objects = this.surfaces;
|
|
||||||
root.split();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function boundingSearch(searchbox:Bounds) {
|
|
||||||
var res = [];
|
|
||||||
if (this.root == null)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
var q = [this.root];
|
|
||||||
|
|
||||||
while (q.length != 0) {
|
|
||||||
var current = q.shift();
|
|
||||||
|
|
||||||
if (current.bounds.containsBounds(searchbox) || current.bounds.collide(searchbox)) {
|
|
||||||
if (current.isLeaf) {
|
|
||||||
res.push(current.object);
|
|
||||||
} else {
|
|
||||||
if (current.child1 != null)
|
|
||||||
q.push(current.child1);
|
|
||||||
if (current.child2 != null)
|
|
||||||
q.push(current.child2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function rayCast(origin:Vector, direction:Vector) {
|
|
||||||
var res = [];
|
|
||||||
if (this.root == null)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
var ray = h3d.col.Ray.fromValues(origin.x, origin.y, origin.z, direction.x, direction.y, direction.z);
|
|
||||||
var q = [this.root];
|
|
||||||
while (q.length != 0) {
|
|
||||||
var current = q.shift();
|
|
||||||
if (ray.collide(current.bounds)) {
|
|
||||||
if (current.isLeaf) {
|
|
||||||
res = res.concat(current.object.rayCast(origin, direction));
|
|
||||||
} else {
|
|
||||||
if (current.child1 != null)
|
|
||||||
q.push(current.child1);
|
|
||||||
if (current.child2 != null)
|
|
||||||
q.push(current.child2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -58,11 +58,11 @@ class CollisionEntity implements IOctreeObject implements IBVHObject {
|
||||||
// Generates the bvh
|
// Generates the bvh
|
||||||
public function finalize() {
|
public function finalize() {
|
||||||
this.generateBoundingBox();
|
this.generateBoundingBox();
|
||||||
this.bvh = new BVHTree(this.boundingBox);
|
this.bvh = new BVHTree();
|
||||||
for (surface in this.surfaces) {
|
for (surface in this.surfaces) {
|
||||||
this.bvh.insert(surface);
|
this.bvh.add(surface);
|
||||||
}
|
}
|
||||||
this.bvh.build();
|
// this.bvh.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setTransform(transform:Matrix) {
|
public function setTransform(transform:Matrix) {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import src.MarbleGame;
|
||||||
@:publicFields
|
@:publicFields
|
||||||
class GuiImage extends GuiControl {
|
class GuiImage extends GuiControl {
|
||||||
var bmp:Bitmap;
|
var bmp:Bitmap;
|
||||||
var bmpFlow:Flow;
|
|
||||||
|
|
||||||
public var pressedAction:GuiControl->Void = null;
|
public var pressedAction:GuiControl->Void = null;
|
||||||
|
|
||||||
|
|
@ -25,23 +24,16 @@ class GuiImage extends GuiControl {
|
||||||
// bmp.scaleY = renderRect.extent.y / bmp.tile.height;
|
// bmp.scaleY = renderRect.extent.y / bmp.tile.height;
|
||||||
bmp.width = renderRect.extent.x;
|
bmp.width = renderRect.extent.x;
|
||||||
bmp.height = renderRect.extent.y;
|
bmp.height = renderRect.extent.y;
|
||||||
if (doClipping) {
|
if (scene2d.contains(bmp)) {
|
||||||
bmpFlow.maxWidth = Std.int(hittestRect.extent.x);
|
scene2d.removeChild(bmp); // Refresh "layer"
|
||||||
bmpFlow.maxHeight = Std.int(hittestRect.extent.y);
|
|
||||||
}
|
}
|
||||||
if (scene2d.contains(obj)) {
|
scene2d.addChild(bmp);
|
||||||
scene2d.removeChild(obj); // Refresh "layer"
|
|
||||||
}
|
|
||||||
scene2d.addChild(obj);
|
|
||||||
super.render(scene2d);
|
super.render(scene2d);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override function dispose() {
|
public override function dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
if (this.doClipping) {
|
this.bmp.remove();
|
||||||
bmpFlow.remove();
|
|
||||||
} else
|
|
||||||
this.bmp.remove();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override function onMouseRelease(mouseState:MouseState) {
|
public override function onMouseRelease(mouseState:MouseState) {
|
||||||
|
|
@ -53,9 +45,6 @@ class GuiImage extends GuiControl {
|
||||||
|
|
||||||
public override function onRemove() {
|
public override function onRemove() {
|
||||||
super.onRemove();
|
super.onRemove();
|
||||||
if (MarbleGame.canvas.scene2d.contains(bmpFlow)) {
|
|
||||||
MarbleGame.canvas.scene2d.removeChild(bmpFlow); // Refresh "layer"
|
|
||||||
}
|
|
||||||
if (MarbleGame.canvas.scene2d.contains(bmp)) {
|
if (MarbleGame.canvas.scene2d.contains(bmp)) {
|
||||||
MarbleGame.canvas.scene2d.removeChild(bmp); // Refresh "layer"
|
MarbleGame.canvas.scene2d.removeChild(bmp); // Refresh "layer"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue