From f917210f8cd77f48b99ddf8d4a871f1589531e0a Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sat, 24 Dec 2022 18:04:53 +0530 Subject: [PATCH] fix minor bugs and improve moving platform broadphase --- src/Marble.hx | 2 +- src/MarbleWorld.hx | 37 ++++++++++++++++++----------- src/collision/BVHTree.hx | 37 ++++++++++++++++------------- src/collision/BoxCollisionEntity.hx | 3 ++- src/collision/CollisionEntity.hx | 5 ++-- src/collision/CollisionSurface.hx | 10 ++------ src/collision/CollisionWorld.hx | 16 ++++++------- src/gui/PlayGui.hx | 3 +++ src/octree/Octree.hx | 2 +- 9 files changed, 63 insertions(+), 52 deletions(-) diff --git a/src/Marble.hx b/src/Marble.hx index b11c8496..782f0d2b 100644 --- a/src/Marble.hx +++ b/src/Marble.hx @@ -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) diff --git a/src/MarbleWorld.hx b/src/MarbleWorld.hx index 18e0a338..6d6cb97b 100644 --- a/src/MarbleWorld.hx +++ b/src/MarbleWorld.hx @@ -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(); diff --git a/src/collision/BVHTree.hx b/src/collision/BVHTree.hx index 688cbff0..145fd756 100644 --- a/src/collision/BVHTree.hx +++ b/src/collision/BVHTree.hx @@ -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; +} + @:publicFields -class BVHNode { +class BVHNode { var id:Int; - var parent:BVHNode; - var child1:BVHNode; - var child2:BVHNode; + var parent:BVHNode; + var child1:BVHNode; + var child2:BVHNode; var isLeaf:Bool; var bounds:Bounds; - var surface:CollisionSurface; + var object:T; public function new() {} } -class BVHTree { +class BVHTree { var nodeId:Int = 0; - var root:BVHNode; + var root:BVHNode; 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) -> 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) { var parent = node.parent; if (parent != null) { @@ -203,7 +208,7 @@ class BVHTree { } } - function rotate(node:BVHNode) { + function rotate(node:BVHNode) { 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); diff --git a/src/collision/BoxCollisionEntity.hx b/src/collision/BoxCollisionEntity.hx index 9f1edd55..c8b37950 100644 --- a/src/collision/BoxCollisionEntity.hx +++ b/src/collision/BoxCollisionEntity.hx @@ -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; diff --git a/src/collision/CollisionEntity.hx b/src/collision/CollisionEntity.hx index f2739cff..b12c9167 100644 --- a/src/collision/CollisionEntity.hx +++ b/src/collision/CollisionEntity.hx @@ -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; public var surfaces:Array; diff --git a/src/collision/CollisionSurface.hx b/src/collision/CollisionSurface.hx index 608beaf1..c4a6915c 100644 --- a/src/collision/CollisionSurface.hx +++ b/src/collision/CollisionSurface.hx @@ -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; public var normals:Array; public var indices:Array; - public var friction:Float = 1; public var restitution:Float = 1; public var force:Float = 0; - public var edgeData:Array; - public var edgeConcavities:Array; public var originalIndices:Array; - public var originalSurfaceIndex:Int; - public var key:Bool = false; public function new() {} diff --git a/src/collision/CollisionWorld.hx b/src/collision/CollisionWorld.hx index ad976c97..c2d88b60 100644 --- a/src/collision/CollisionWorld.hx +++ b/src/collision/CollisionWorld.hx @@ -11,9 +11,11 @@ class CollisionWorld { public var octree:Octree; public var entities:Array = []; public var dynamicEntities:Array = []; + public var dynamicBVH:BVHTree; 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) { diff --git a/src/gui/PlayGui.hx b/src/gui/PlayGui.hx index 2f98cd8a..72d66e0f 100644 --- a/src/gui/PlayGui.hx +++ b/src/gui/PlayGui.hx @@ -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; diff --git a/src/octree/Octree.hx b/src/octree/Octree.hx index 447ff45b..6dbd258a 100644 --- a/src/octree/Octree.hx +++ b/src/octree/Octree.hx @@ -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) {