API Docs for: GoblinPhysics
Show:

File: src\classes\NearPhase.js

  1. /**
  2. * Takes possible contacts found by a broad phase and determines if they are legitimate contacts
  3. *
  4. * @class NearPhase
  5. * @constructor
  6. */
  7. Goblin.NearPhase = function() {
  8. /**
  9. * holds all contacts which currently exist in the scene
  10. *
  11. * @property contact_manifolds
  12. * @type Goblin.ContactManifoldList
  13. */
  14. this.contact_manifolds = new Goblin.ContactManifoldList();
  15. };
  16.  
  17. /**
  18. * Iterates over all contact manifolds, updating penetration depth & contact locations
  19. *
  20. * @method updateContactManifolds
  21. */
  22. Goblin.NearPhase.prototype.updateContactManifolds = function() {
  23. var current = this.contact_manifolds.first,
  24. prev = null;
  25.  
  26. while ( current !== null ) {
  27. current.update();
  28.  
  29. if ( current.points.length === 0 ) {
  30. Goblin.ObjectPool.freeObject( 'ContactManifold', current );
  31. if ( prev == null ) {
  32. this.contact_manifolds.first = current.next_manifold;
  33. } else {
  34. prev.next_manifold = current.next_manifold;
  35. }
  36. current = current.next_manifold;
  37. } else {
  38. prev = current;
  39. current = current.next_manifold;
  40. }
  41. }
  42. };
  43.  
  44. Goblin.NearPhase.prototype.midPhase = function( object_a, object_b ) {
  45. var compound,
  46. other;
  47.  
  48. if ( object_a.shape instanceof Goblin.CompoundShape ) {
  49. compound = object_a;
  50. other = object_b;
  51. } else {
  52. compound = object_b;
  53. other = object_a;
  54. }
  55.  
  56. var proxy = Goblin.ObjectPool.getObject( 'RigidBodyProxy' ),
  57. child_shape, contact;
  58. for ( var i = 0; i < compound.shape.child_shapes.length; i++ ) {
  59. child_shape = compound.shape.child_shapes[i];
  60. proxy.setFrom( compound, child_shape );
  61.  
  62. if ( proxy.shape instanceof Goblin.CompoundShape || other.shape instanceof Goblin.CompoundShape ) {
  63. this.midPhase( proxy, other );
  64. } else {
  65. contact = this.getContact( proxy, other );
  66. if ( contact != null ) {
  67.  
  68. var parent_a, parent_b;
  69. if ( contact.object_a === proxy ) {
  70. contact.object_a = compound;
  71. parent_a = proxy;
  72. parent_b = other;
  73. } else {
  74. contact.object_b = compound;
  75. parent_a = other;
  76. parent_b = proxy;
  77. }
  78.  
  79. if ( parent_a instanceof Goblin.RigidBodyProxy ) {
  80. while ( parent_a.parent ) {
  81. if ( parent_a instanceof Goblin.RigidBodyProxy ) {
  82. parent_a.shape_data.transform.transformVector3( contact.contact_point_in_a );
  83. }
  84. parent_a = parent_a.parent;
  85. }
  86. }
  87.  
  88. if ( parent_b instanceof Goblin.RigidBodyProxy ) {
  89. while ( parent_b.parent ) {
  90. if ( parent_b instanceof Goblin.RigidBodyProxy ) {
  91. parent_b.shape_data.transform.transformVector3( contact.contact_point_in_b );
  92. }
  93. parent_b = parent_b.parent;
  94. }
  95. }
  96.  
  97. contact.object_a = parent_a;
  98. contact.object_b = parent_b;
  99. this.addContact( parent_a, parent_b, contact );
  100. }
  101. }
  102. }
  103. Goblin.ObjectPool.freeObject( 'RigidBodyProxy', proxy );
  104. };
  105.  
  106. /**
  107. * Tests two objects for contact
  108. *
  109. * @method getContact
  110. * @param {RigidBody} object_a
  111. * @param {RigidBody} object_b
  112. */
  113. Goblin.NearPhase.prototype.getContact = function( object_a, object_b ) {
  114. if ( object_a.shape instanceof Goblin.CompoundShape || object_b.shape instanceof Goblin.CompoundShape ) {
  115. this.midPhase( object_a, object_b );
  116. return;
  117. }
  118.  
  119. var contact;
  120.  
  121. if ( object_a.shape instanceof Goblin.SphereShape && object_b.shape instanceof Goblin.SphereShape ) {
  122. // Sphere - Sphere contact check
  123. contact = Goblin.SphereSphere( object_a, object_b );
  124. } else if (
  125. object_a.shape instanceof Goblin.SphereShape && object_b.shape instanceof Goblin.BoxShape ||
  126. object_a.shape instanceof Goblin.BoxShape && object_b.shape instanceof Goblin.SphereShape
  127. ) {
  128. // Sphere - Box contact check
  129. contact = Goblin.BoxSphere( object_a, object_b );
  130. } else {
  131. // contact check based on GJK
  132. if ( (contact = Goblin.GjkEpa2.GJK( object_a, object_b )) != null ) {
  133. contact = Goblin.GjkEpa2.EPA( contact );
  134. }
  135. }
  136.  
  137. return contact;
  138. };
  139.  
  140. Goblin.NearPhase.prototype.addContact = function( object_a, object_b, contact ) {
  141. this.contact_manifolds.getManifoldForObjects( object_a, object_b ).addContact( contact );
  142. };
  143.  
  144. /**
  145. * Loops over the passed array of object pairs which may be in contact
  146. * valid contacts are put in this object's `contacts` property
  147. *
  148. * @param possible_contacts {Array}
  149. */
  150. Goblin.NearPhase.prototype.generateContacts = function( possible_contacts ) {
  151. var i,
  152. contact,
  153. possible_contacts_length = possible_contacts.length;
  154.  
  155. // Make sure all of the manifolds are up to date
  156. this.updateContactManifolds();
  157.  
  158. for ( i = 0; i < possible_contacts_length; i++ ) {
  159. contact = this.getContact( possible_contacts[i][0], possible_contacts[i][1] );
  160. if ( contact != null ) {
  161. this.addContact( possible_contacts[i][0], possible_contacts[i][1], contact );
  162. }
  163. }
  164. };