diff --git a/src/oimo/dynamics/Contact.hx b/src/oimo/dynamics/Contact.hx index deaec04..6a03e93 100644 --- a/src/oimo/dynamics/Contact.hx +++ b/src/oimo/dynamics/Contact.hx @@ -41,6 +41,7 @@ class Contact { public var _updater:ManifoldUpdater; public var _contactConstraint:ContactConstraint; public var _touching:Bool; + public var _triggering:Bool; @:dox(hide) public function new() { @@ -112,6 +113,26 @@ class Contact { if (cc2 != null) cc2.endContact(this); } + extern inline function sendBeginTriggerContact():Void { + var cc1:ContactCallback = _s1._contactCallback; + var cc2:ContactCallback = _s2._contactCallback; + if (cc1 == cc2) { + cc2 = null; // avoid calling twice + } + if (cc1 != null) cc1.beginTriggerContact(this); + if (cc2 != null) cc2.beginTriggerContact(this); + } + + extern inline function sendEndTriggerContact():Void { + var cc1:ContactCallback = _s1._contactCallback; + var cc2:ContactCallback = _s2._contactCallback; + if (cc1 == cc2) { + cc2 = null; // avoid calling twice + } + if (cc1 != null) cc1.endTriggerContact(this); + if (cc2 != null) cc2.endTriggerContact(this); + } + extern inline function sendPreSolve():Void { var cc1:ContactCallback = _s1._contactCallback; var cc2:ContactCallback = _s2._contactCallback; @@ -153,6 +174,11 @@ class Contact { sendEndContact(); } + if (_triggering) { + // triggering in the last frame + sendEndTriggerContact(); + } + detachLinks(); _s1 = null; _s2 = null; @@ -172,12 +198,14 @@ class Contact { if (_detector == null) return; var ptouching:Bool = _touching; + var pTriggering:Bool = _triggering; var result:DetectorResult = _detectorResult; _detector.detect(result, _s1._geom, _s2._geom, _s1._transform, _s2._transform, _cachedDetectorData); var num:Int = result.numPoints; _touching = num > 0; + if (!_touching && _triggering) _triggering = false; if (_touching) { // update manifold basis @@ -200,6 +228,8 @@ class Contact { // one-shot manifold _updater.totalUpdate(result, _b1._transform, _b2._transform); } + + if (_s1._rigidBody._isTrigger || _s2._rigidBody._isTrigger) _triggering = true; } else { _manifold._clear(); } @@ -210,6 +240,12 @@ class Contact { if (!_touching && ptouching) { sendEndContact(); } + if (_triggering && !pTriggering) { + sendBeginTriggerContact(); + } + if (!_triggering && pTriggering) { + sendEndTriggerContact(); + } if (_touching) { sendPreSolve(); } @@ -243,6 +279,13 @@ class Contact { return _touching; } + /** + * Returns whether the shapes are triggering. + */ + public inline function isTriggering():Bool { + return _triggering; + } + /** * Returns the contact manifold. */ diff --git a/src/oimo/dynamics/ContactManager.hx b/src/oimo/dynamics/ContactManager.hx index 6262f27..9c7b29a 100644 --- a/src/oimo/dynamics/ContactManager.hx +++ b/src/oimo/dynamics/ContactManager.hx @@ -142,7 +142,7 @@ class ContactManager { return false; } - if (r1._type != RigidBodyType._DYNAMIC && r2._type != RigidBodyType._DYNAMIC) { + if (r1._type != RigidBodyType._DYNAMIC && r2._type != RigidBodyType._DYNAMIC && (!s1._rigidBody._isTrigger && !s2._rigidBody._isTrigger)) { // none of the two bodies are dynamic return false; } diff --git a/src/oimo/dynamics/World.hx b/src/oimo/dynamics/World.hx index 99c882e..2e176ab 100644 --- a/src/oimo/dynamics/World.hx +++ b/src/oimo/dynamics/World.hx @@ -204,7 +204,7 @@ class World { // ignore if not touching var cc:ContactConstraint = cl._contact._contactConstraint; var ccs:ConstraintSolver = cl._contact._contactConstraint._solver; - if (cc.isTouching() && !ccs._addedToIsland) { + if (!cl._contact._triggering && cc.isTouching() && !ccs._addedToIsland) { // add to constraint array (to clear island flag later) if (_solversInIslands.length == _numSolversInIslands) { @@ -795,6 +795,7 @@ class World { Performance.totalTime = M.profile({ _updateContacts(); + // FEHM - here the manifolds of triggers must be cleared? Detached etc. _solveIslands(); }); } diff --git a/src/oimo/dynamics/callback/ContactCallback.hx b/src/oimo/dynamics/callback/ContactCallback.hx index 037a6d8..523ed93 100644 --- a/src/oimo/dynamics/callback/ContactCallback.hx +++ b/src/oimo/dynamics/callback/ContactCallback.hx @@ -1,4 +1,7 @@ package oimo.dynamics.callback; + +import oimo.dynamics.constraint.contact.Manifold; +import oimo.collision.narrowphase.DetectorResult; import oimo.dynamics.Contact; /** @@ -47,4 +50,16 @@ class ContactCallback { */ public function endContact(c:Contact):Void { } + + /** + * Trigger event started. + */ + public function beginTriggerContact(c:Contact):Void { + } + + /** + * Trigger event ended. + */ + public function endTriggerContact(c:Contact):Void { + } } diff --git a/src/oimo/dynamics/rigidbody/RigidBody.hx b/src/oimo/dynamics/rigidbody/RigidBody.hx index 2e540a4..494f5fb 100644 --- a/src/oimo/dynamics/rigidbody/RigidBody.hx +++ b/src/oimo/dynamics/rigidbody/RigidBody.hx @@ -74,6 +74,8 @@ class RigidBody { public var _addedToIsland:Bool; public var _gravityScale:Float; + public var _isTrigger:Bool; + /** * Extra field that users can use for their own purposes. */ @@ -842,6 +844,13 @@ class RigidBody { wakeUp(); } + /** + * Sets if the body is a trigger or not. + */ + public inline function setIsTrigger(isTrigger:Bool) { + _isTrigger = isTrigger; + } + /** * Returns the local coordinates of the point `worldPoint` in world coodinates. */