fix minor bugs and improve moving platform broadphase

This commit is contained in:
RandomityGuy 2022-12-24 18:04:53 +05:30
parent c64d6bef13
commit f917210f8c
9 changed files with 63 additions and 52 deletions

View file

@ -1557,7 +1557,7 @@ class Marble extends GameObject {
var tempTimeState = timeState.clone();
tempState.currentAttemptTime = piTime;
tempState.dt = timeStep;
this.level.callCollisionHandlers(cast this, tempTimeState);
this.level.callCollisionHandlers(cast this, tempTimeState, pos, newPos, rot, quat);
}
if (contacts.length != 0)

View file

@ -1429,6 +1429,8 @@ class MarbleWorld extends Scheduler {
val = Util.getKeyForButton(Settings.controlsSettings.powerup);
if (funcdata[1] == "freelook")
val = Util.getKeyForButton(Settings.controlsSettings.freelook);
if (funcdata[1] == "useblast")
val = Util.getKeyForButton(Settings.controlsSettings.blast);
}
start = val.length + pos;
text = pre + val + post;
@ -1472,13 +1474,18 @@ class MarbleWorld extends Scheduler {
this.playGui.formatGemCounter(this.gemCount, this.totalGems);
}
public function callCollisionHandlers(marble:Marble, timeState:TimeState) {
var gjkSphere = new collision.gjk.Sphere();
gjkSphere.position = marble.getAbsPos().getPosition();
gjkSphere.radius = marble._radius;
public function callCollisionHandlers(marble:Marble, timeState:TimeState, start:Vector, end:Vector, startQuat:Quat, endQuat:Quat) {
var expansion = marble._radius + 0.2;
var minP = new Vector(Math.min(start.x, end.x) - expansion, Math.min(start.y, end.y) - expansion, Math.min(start.z, end.z) - expansion);
var maxP = new Vector(Math.max(start.x, end.x) + expansion, Math.max(start.y, end.y) + expansion, Math.max(start.z, end.z) + expansion);
var box = Bounds.fromPoints(minP.toPoint(), maxP.toPoint());
var marbleHitbox = new Bounds();
marbleHitbox.addSpherePos(0, 0, 0, marble._radius);
marbleHitbox.transform(startQuat.toMatrix());
marbleHitbox.transform(endQuat.toMatrix());
marbleHitbox.offset(end.x, end.y, end.z);
var spherebounds = new Bounds();
spherebounds.addSpherePos(gjkSphere.position.x, gjkSphere.position.y, gjkSphere.position.z, gjkSphere.radius);
// spherebounds.addSpherePos(gjkCapsule.p2.x, gjkCapsule.p2.y, gjkCapsule.p2.z, gjkCapsule.radius);
// var contacts = this.collisionWorld.radiusSearch(marble.getAbsPos().getPosition(), marble._radius);
var contacts = marble.contactEntities;
@ -1489,18 +1496,20 @@ class MarbleWorld extends Scheduler {
if (contact.go is DtsObject) {
var shape:DtsObject = cast contact.go;
shape.onMarbleInside(timeState);
if (!this.shapeOrTriggerInside.contains(contact.go)) {
this.shapeOrTriggerInside.push(contact.go);
shape.onMarbleEnter(timeState);
if (contact.boundingBox.collide(marbleHitbox)) {
shape.onMarbleInside(timeState);
if (!this.shapeOrTriggerInside.contains(contact.go)) {
this.shapeOrTriggerInside.push(contact.go);
shape.onMarbleEnter(timeState);
}
inside.push(contact.go);
}
inside.push(contact.go);
}
if (contact.go is Trigger) {
var trigger:Trigger = cast contact.go;
var triggeraabb = trigger.collider.boundingBox;
if (triggeraabb.collide(spherebounds)) {
if (triggeraabb.collide(marbleHitbox)) {
trigger.onMarbleInside(timeState);
if (!this.shapeOrTriggerInside.contains(contact.go)) {
this.shapeOrTriggerInside.push(contact.go);
@ -1520,11 +1529,11 @@ class MarbleWorld extends Scheduler {
}
if (this.finishTime == null) {
if (spherebounds.collide(this.endPad.finishBounds)) {
if (marbleHitbox.collide(this.endPad.finishBounds)) {
var padUp = this.endPad.getAbsPos().up();
padUp = padUp.multiply(10);
var checkBounds = spherebounds.clone();
var checkBounds = box.clone();
checkBounds.zMin -= 10;
checkBounds.zMax += 10;
var checkBoundsCenter = checkBounds.getCenter();

View file

@ -3,22 +3,27 @@ package collision;
import h3d.Vector;
import h3d.col.Bounds;
interface IBVHObject {
var boundingBox:Bounds;
function rayCast(rayOrigin:Vector, rayDirection:Vector):Array<octree.IOctreeObject.RayIntersectionData>;
}
@:publicFields
class BVHNode {
class BVHNode<T:IBVHObject> {
var id:Int;
var parent:BVHNode;
var child1:BVHNode;
var child2:BVHNode;
var parent:BVHNode<T>;
var child1:BVHNode<T>;
var child2:BVHNode<T>;
var isLeaf:Bool;
var bounds:Bounds;
var surface:CollisionSurface;
var object:T;
public function new() {}
}
class BVHTree {
class BVHTree<T:IBVHObject> {
var nodeId:Int = 0;
var root:BVHNode;
var root:BVHNode<T>;
public function new() {}
@ -26,7 +31,7 @@ class BVHTree {
var invalidNodes = [];
this.traverse(node -> {
if (node.isLeaf) {
var entity = node.surface;
var entity = node.object;
var tightAABB = entity.boundingBox;
if (node.bounds.containsBounds(tightAABB)) {
@ -38,18 +43,18 @@ class BVHTree {
});
for (node in invalidNodes) {
this.remove(node);
this.add(node.surface);
this.add(node.object);
}
}
public function add(entity:CollisionSurface) {
public function add(entity:T) {
// Enlarged AABB
var aabb = entity.boundingBox;
var newNode = new BVHNode();
newNode.id = this.nodeId++;
newNode.bounds = aabb;
newNode.surface = entity;
newNode.object = entity;
newNode.isLeaf = true;
if (this.root == null) {
@ -149,7 +154,7 @@ class BVHTree {
}
// BFS tree traversal
function traverse(callback:(node:BVHNode) -> Void) {
function traverse(callback:(node:BVHNode<T>) -> Void) {
var q = [this.root];
while (q.length != 0) {
@ -169,7 +174,7 @@ class BVHTree {
}
}
public function remove(node:BVHNode) {
public function remove(node:BVHNode<T>) {
var parent = node.parent;
if (parent != null) {
@ -203,7 +208,7 @@ class BVHTree {
}
}
function rotate(node:BVHNode) {
function rotate(node:BVHNode<T>) {
if (node.parent == null) {
return;
}
@ -322,7 +327,7 @@ class BVHTree {
if (current.bounds.containsBounds(searchbox) || current.bounds.collide(searchbox)) {
if (current.isLeaf) {
res.push(current.surface);
res.push(current.object);
} else {
if (current.child1 != null)
q.push(current.child1);
@ -346,7 +351,7 @@ class BVHTree {
var current = q.shift();
if (ray.collide(current.bounds)) {
if (current.isLeaf) {
res = res.concat(current.surface.rayCast(origin, direction));
res = res.concat(current.object.rayCast(origin, direction));
} else {
if (current.child1 != null)
q.push(current.child1);

View file

@ -1,5 +1,6 @@
package collision;
import collision.BVHTree.IBVHObject;
import src.MarbleGame;
import src.TimeState;
import h3d.Matrix;
@ -10,7 +11,7 @@ import h3d.Vector;
import h3d.col.Sphere;
import h3d.col.Bounds;
class BoxCollisionEntity extends CollisionEntity {
class BoxCollisionEntity extends CollisionEntity implements IBVHObject {
var bounds:Bounds;
var _dbgEntity:h3d.scene.Object;

View file

@ -1,5 +1,6 @@
package collision;
import collision.BVHTree.IBVHObject;
import src.TimeState;
import src.GameObject;
import dif.math.Point3F;
@ -14,12 +15,12 @@ import h3d.col.Bounds;
import src.PathedInterior;
import src.Util;
class CollisionEntity implements IOctreeObject {
class CollisionEntity implements IOctreeObject implements IBVHObject {
public var boundingBox:Bounds;
public var octree:Octree;
public var bvh:BVHTree;
public var bvh:BVHTree<CollisionSurface>;
public var surfaces:Array<CollisionSurface>;

View file

@ -4,28 +4,22 @@ import h3d.Matrix;
import h3d.col.Bounds;
import octree.IOctreeObject;
import h3d.Vector;
import collision.BVHTree.IBVHObject;
class CollisionSurface implements IOctreeObject {
class CollisionSurface implements IOctreeObject implements IBVHObject {
public var priority:Int;
public var position:Int;
public var boundingBox:Bounds;
public var points:Array<Vector>;
public var normals:Array<Vector>;
public var indices:Array<Int>;
public var friction:Float = 1;
public var restitution:Float = 1;
public var force:Float = 0;
public var edgeData:Array<Int>;
public var edgeConcavities:Array<Bool>;
public var originalIndices:Array<Int>;
public var originalSurfaceIndex:Int;
public var key:Bool = false;
public function new() {}

View file

@ -11,9 +11,11 @@ class CollisionWorld {
public var octree:Octree;
public var entities:Array<CollisionEntity> = [];
public var dynamicEntities:Array<CollisionEntity> = [];
public var dynamicBVH:BVHTree<CollisionEntity>;
public function new() {
this.octree = new Octree();
this.dynamicBVH = new BVHTree();
}
public function sphereIntersection(spherecollision:SphereCollisionEntity, timeState:TimeState) {
@ -44,7 +46,8 @@ class CollisionWorld {
}
}
for (obj in dynamicEntities) {
var dynSearch = dynamicBVH.boundingSearch(box);
for (obj in dynSearch) {
if (obj != spherecollision) {
if (obj.boundingBox.collide(box) && obj.go.isCollideable)
contacts = contacts.concat(obj.sphereIntersection(spherecollision, timeState));
@ -72,20 +75,14 @@ class CollisionWorld {
contacts.push(entity);
}
for (obj in dynamicEntities) {
if (obj.boundingBox.collide(box))
contacts.push(obj);
}
contacts = contacts.concat(dynamicBVH.boundingSearch(box));
return contacts;
}
public function boundingSearch(bounds:Bounds, useCache:Bool = true) {
var contacts = this.octree.boundingSearch(bounds, useCache).map(x -> cast(x, CollisionEntity));
for (obj in dynamicEntities) {
if (obj.boundingBox.collide(bounds))
contacts.push(obj);
}
contacts = contacts.concat(dynamicBVH.boundingSearch(bounds));
return contacts;
}
@ -117,6 +114,7 @@ class CollisionWorld {
public function addMovingEntity(entity:CollisionEntity) {
this.dynamicEntities.push(entity);
this.dynamicBVH.add(entity);
}
public function updateTransform(entity:CollisionEntity) {

View file

@ -534,6 +534,9 @@ class PlayGui {
} else if (powerupIdentifier == "Helicopter") {
powerupImageObject = new DtsObject();
powerupImageObject.dtsPath = "data/shapes/images/helicopter.dts";
} else if (powerupIdentifier == "MegaMarble") {
powerupImageObject = new DtsObject();
powerupImageObject.dtsPath = "data/shapes/items/megamarble.dts";
} else {
powerupIdentifier = "";
this.powerupImageObject = null;

View file

@ -139,7 +139,7 @@ class Octree {
return intersections;
}
public function boundingSearch(bounds:Bounds, useCache:Bool = true) {
public function boundingSearch(bounds:Bounds, useCache:Bool = false) {
var intersections = [];
if (useCache) {
if (this.prevBoundSearch != null) {