File: src\classes\NearPhase.js
- /**
- * Takes possible contacts found by a broad phase and determines if they are legitimate contacts
- *
- * @class NearPhase
- * @constructor
- */
- Goblin.NearPhase = function() {
- /**
- * holds all contacts which currently exist in the scene
- *
- * @property contact_manifolds
- * @type Goblin.ContactManifoldList
- */
- this.contact_manifolds = new Goblin.ContactManifoldList();
- };
-
- /**
- * Iterates over all contact manifolds, updating penetration depth & contact locations
- *
- * @method updateContactManifolds
- */
- Goblin.NearPhase.prototype.updateContactManifolds = function() {
- var current = this.contact_manifolds.first,
- prev = null;
-
- while ( current !== null ) {
- current.update();
-
- if ( current.points.length === 0 ) {
- Goblin.ObjectPool.freeObject( 'ContactManifold', current );
- if ( prev == null ) {
- this.contact_manifolds.first = current.next_manifold;
- } else {
- prev.next_manifold = current.next_manifold;
- }
- current = current.next_manifold;
- } else {
- prev = current;
- current = current.next_manifold;
- }
- }
- };
-
- Goblin.NearPhase.prototype.midPhase = function( object_a, object_b ) {
- var compound,
- other;
-
- if ( object_a.shape instanceof Goblin.CompoundShape ) {
- compound = object_a;
- other = object_b;
- } else {
- compound = object_b;
- other = object_a;
- }
-
- var proxy = Goblin.ObjectPool.getObject( 'RigidBodyProxy' ),
- child_shape, contact;
- for ( var i = 0; i < compound.shape.child_shapes.length; i++ ) {
- child_shape = compound.shape.child_shapes[i];
- proxy.setFrom( compound, child_shape );
-
- if ( proxy.shape instanceof Goblin.CompoundShape || other.shape instanceof Goblin.CompoundShape ) {
- this.midPhase( proxy, other );
- } else {
- contact = this.getContact( proxy, other );
- if ( contact != null ) {
-
- var parent_a, parent_b;
- if ( contact.object_a === proxy ) {
- contact.object_a = compound;
- parent_a = proxy;
- parent_b = other;
- } else {
- contact.object_b = compound;
- parent_a = other;
- parent_b = proxy;
- }
-
- if ( parent_a instanceof Goblin.RigidBodyProxy ) {
- while ( parent_a.parent ) {
- if ( parent_a instanceof Goblin.RigidBodyProxy ) {
- parent_a.shape_data.transform.transformVector3( contact.contact_point_in_a );
- }
- parent_a = parent_a.parent;
- }
- }
-
- if ( parent_b instanceof Goblin.RigidBodyProxy ) {
- while ( parent_b.parent ) {
- if ( parent_b instanceof Goblin.RigidBodyProxy ) {
- parent_b.shape_data.transform.transformVector3( contact.contact_point_in_b );
- }
- parent_b = parent_b.parent;
- }
- }
-
- contact.object_a = parent_a;
- contact.object_b = parent_b;
- this.addContact( parent_a, parent_b, contact );
- }
- }
- }
- Goblin.ObjectPool.freeObject( 'RigidBodyProxy', proxy );
- };
-
- /**
- * Tests two objects for contact
- *
- * @method getContact
- * @param {RigidBody} object_a
- * @param {RigidBody} object_b
- */
- Goblin.NearPhase.prototype.getContact = function( object_a, object_b ) {
- if ( object_a.shape instanceof Goblin.CompoundShape || object_b.shape instanceof Goblin.CompoundShape ) {
- this.midPhase( object_a, object_b );
- return;
- }
-
- var contact;
-
- if ( object_a.shape instanceof Goblin.SphereShape && object_b.shape instanceof Goblin.SphereShape ) {
- // Sphere - Sphere contact check
- contact = Goblin.SphereSphere( object_a, object_b );
- } else if (
- object_a.shape instanceof Goblin.SphereShape && object_b.shape instanceof Goblin.BoxShape ||
- object_a.shape instanceof Goblin.BoxShape && object_b.shape instanceof Goblin.SphereShape
- ) {
- // Sphere - Box contact check
- contact = Goblin.BoxSphere( object_a, object_b );
- } else {
- // contact check based on GJK
- if ( (contact = Goblin.GjkEpa2.GJK( object_a, object_b )) != null ) {
- contact = Goblin.GjkEpa2.EPA( contact );
- }
- }
-
- return contact;
- };
-
- Goblin.NearPhase.prototype.addContact = function( object_a, object_b, contact ) {
- this.contact_manifolds.getManifoldForObjects( object_a, object_b ).addContact( contact );
- };
-
- /**
- * Loops over the passed array of object pairs which may be in contact
- * valid contacts are put in this object's `contacts` property
- *
- * @param possible_contacts {Array}
- */
- Goblin.NearPhase.prototype.generateContacts = function( possible_contacts ) {
- var i,
- contact,
- possible_contacts_length = possible_contacts.length;
-
- // Make sure all of the manifolds are up to date
- this.updateContactManifolds();
-
- for ( i = 0; i < possible_contacts_length; i++ ) {
- contact = this.getContact( possible_contacts[i][0], possible_contacts[i][1] );
- if ( contact != null ) {
- this.addContact( possible_contacts[i][0], possible_contacts[i][1], contact );
- }
- }
- };
-