babylon.physicsEngineComponent.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. module BABYLON {
  2. export interface Scene {
  3. /** @hidden (Backing field) */
  4. _physicsEngine: Nullable<IPhysicsEngine>;
  5. /**
  6. * Gets the current physics engine
  7. * @returns a IPhysicsEngine or null if none attached
  8. */
  9. getPhysicsEngine(): Nullable<IPhysicsEngine>;
  10. /**
  11. * Enables physics to the current scene
  12. * @param gravity defines the scene's gravity for the physics engine
  13. * @param plugin defines the physics engine to be used. defaults to OimoJS.
  14. * @return a boolean indicating if the physics engine was initialized
  15. */
  16. enablePhysics(gravity: Nullable<Vector3>, plugin?: IPhysicsEnginePlugin): boolean;
  17. /**
  18. * Disables and disposes the physics engine associated with the scene
  19. */
  20. disablePhysicsEngine(): void;
  21. /**
  22. * Gets a boolean indicating if there is an active physics engine
  23. * @returns a boolean indicating if there is an active physics engine
  24. */
  25. isPhysicsEnabled(): boolean;
  26. /**
  27. * Deletes a physics compound impostor
  28. * @param compound defines the compound to delete
  29. */
  30. deleteCompoundImpostor(compound: any): void;
  31. /**
  32. * An event triggered when physic simulation is about to be run
  33. */
  34. onBeforePhysicsObservable: Observable<Scene>;
  35. /**
  36. * An event triggered when physic simulation has been done
  37. */
  38. onAfterPhysicsObservable: Observable<Scene>;
  39. }
  40. /**
  41. * Gets the current physics engine
  42. * @returns a IPhysicsEngine or null if none attached
  43. */
  44. Scene.prototype.getPhysicsEngine = function(): Nullable<IPhysicsEngine> {
  45. return this._physicsEngine;
  46. };
  47. /**
  48. * Enables physics to the current scene
  49. * @param gravity defines the scene's gravity for the physics engine
  50. * @param plugin defines the physics engine to be used. defaults to OimoJS.
  51. * @return a boolean indicating if the physics engine was initialized
  52. */
  53. Scene.prototype.enablePhysics = function(gravity: Nullable<Vector3> = null, plugin?: IPhysicsEnginePlugin): boolean {
  54. if (this._physicsEngine) {
  55. return true;
  56. }
  57. // Register the component to the scene
  58. let component = this._getComponent(SceneComponentConstants.NAME_PHYSICSENGINE) as PhysicsEngineSceneComponent;
  59. if (!component) {
  60. component = new PhysicsEngineSceneComponent(this);
  61. this._addComponent(component);
  62. }
  63. try {
  64. this._physicsEngine = new PhysicsEngine(gravity, plugin);
  65. return true;
  66. } catch (e) {
  67. Tools.Error(e.message);
  68. return false;
  69. }
  70. };
  71. /**
  72. * Disables and disposes the physics engine associated with the scene
  73. */
  74. Scene.prototype.disablePhysicsEngine = function(): void {
  75. if (!this._physicsEngine) {
  76. return;
  77. }
  78. this._physicsEngine.dispose();
  79. this._physicsEngine = null;
  80. };
  81. /**
  82. * Gets a boolean indicating if there is an active physics engine
  83. * @returns a boolean indicating if there is an active physics engine
  84. */
  85. Scene.prototype.isPhysicsEnabled = function(): boolean {
  86. return this._physicsEngine !== undefined;
  87. };
  88. /**
  89. * Deletes a physics compound impostor
  90. * @param compound defines the compound to delete
  91. */
  92. Scene.prototype.deleteCompoundImpostor = function(compound: any): void {
  93. var mesh: AbstractMesh = compound.parts[0].mesh;
  94. if (mesh.physicsImpostor) {
  95. mesh.physicsImpostor.dispose(/*true*/);
  96. mesh.physicsImpostor = null;
  97. }
  98. };
  99. /** @hidden */
  100. Scene.prototype._advancePhysicsEngineStep = function(step: number) {
  101. if (this._physicsEngine) {
  102. this.onBeforePhysicsObservable.notifyObservers(this);
  103. this._physicsEngine._step(step / 1000);
  104. this.onAfterPhysicsObservable.notifyObservers(this);
  105. }
  106. };
  107. export interface AbstractMesh {
  108. /** @hidden */
  109. _physicsImpostor: Nullable<PhysicsImpostor>;
  110. /**
  111. * Gets or sets impostor used for physic simulation
  112. * @see http://doc.babylonjs.com/features/physics_engine
  113. */
  114. physicsImpostor: Nullable<PhysicsImpostor>;
  115. /**
  116. * Gets the current physics impostor
  117. * @see http://doc.babylonjs.com/features/physics_engine
  118. * @returns a physics impostor or null
  119. */
  120. getPhysicsImpostor(): Nullable<PhysicsImpostor>;
  121. /** Apply a physic impulse to the mesh
  122. * @param force defines the force to apply
  123. * @param contactPoint defines where to apply the force
  124. * @returns the current mesh
  125. * @see http://doc.babylonjs.com/how_to/using_the_physics_engine
  126. */
  127. applyImpulse(force: Vector3, contactPoint: Vector3): AbstractMesh;
  128. /**
  129. * Creates a physic joint between two meshes
  130. * @param otherMesh defines the other mesh to use
  131. * @param pivot1 defines the pivot to use on this mesh
  132. * @param pivot2 defines the pivot to use on the other mesh
  133. * @param options defines additional options (can be plugin dependent)
  134. * @returns the current mesh
  135. * @see https://www.babylonjs-playground.com/#0BS5U0#0
  136. */
  137. setPhysicsLinkWith(otherMesh: Mesh, pivot1: Vector3, pivot2: Vector3, options?: any): AbstractMesh;
  138. /** @hidden */
  139. _disposePhysicsObserver: Nullable<Observer<Node>>;
  140. }
  141. Object.defineProperty(AbstractMesh.prototype, "physicsImpostor", {
  142. get: function(this: AbstractMesh) {
  143. return this._physicsImpostor;
  144. },
  145. set: function(this: AbstractMesh, value: Nullable<PhysicsImpostor>) {
  146. if (this._physicsImpostor === value) {
  147. return;
  148. }
  149. if (this._disposePhysicsObserver) {
  150. this.onDisposeObservable.remove(this._disposePhysicsObserver);
  151. }
  152. this._physicsImpostor = value;
  153. if (value) {
  154. this._disposePhysicsObserver = this.onDisposeObservable.add(() => {
  155. // Physics
  156. if (this.physicsImpostor) {
  157. this.physicsImpostor.dispose(/*!doNotRecurse*/);
  158. this.physicsImpostor = null;
  159. }
  160. });
  161. }
  162. },
  163. enumerable: true,
  164. configurable: true
  165. });
  166. /**
  167. * Gets the current physics impostor
  168. * @see http://doc.babylonjs.com/features/physics_engine
  169. * @returns a physics impostor or null
  170. */
  171. AbstractMesh.prototype.getPhysicsImpostor = function(): Nullable<PhysicsImpostor> {
  172. return this.physicsImpostor;
  173. };
  174. /**
  175. * Apply a physic impulse to the mesh
  176. * @param force defines the force to apply
  177. * @param contactPoint defines where to apply the force
  178. * @returns the current mesh
  179. * @see http://doc.babylonjs.com/how_to/using_the_physics_engine
  180. */
  181. AbstractMesh.prototype.applyImpulse = function(force: Vector3, contactPoint: Vector3): AbstractMesh {
  182. if (!this.physicsImpostor) {
  183. return this;
  184. }
  185. this.physicsImpostor.applyImpulse(force, contactPoint);
  186. return this;
  187. };
  188. /**
  189. * Creates a physic joint between two meshes
  190. * @param otherMesh defines the other mesh to use
  191. * @param pivot1 defines the pivot to use on this mesh
  192. * @param pivot2 defines the pivot to use on the other mesh
  193. * @param options defines additional options (can be plugin dependent)
  194. * @returns the current mesh
  195. * @see https://www.babylonjs-playground.com/#0BS5U0#0
  196. */
  197. AbstractMesh.prototype.setPhysicsLinkWith = function(otherMesh: Mesh, pivot1: Vector3, pivot2: Vector3, options?: any): AbstractMesh {
  198. if (!this.physicsImpostor || !otherMesh.physicsImpostor) {
  199. return this;
  200. }
  201. this.physicsImpostor.createJoint(otherMesh.physicsImpostor, PhysicsJoint.HingeJoint, {
  202. mainPivot: pivot1,
  203. connectedPivot: pivot2,
  204. nativeParams: options
  205. });
  206. return this;
  207. };
  208. /**
  209. * Defines the physics engine scene component responsible to manage a physics engine
  210. */
  211. export class PhysicsEngineSceneComponent implements ISceneComponent {
  212. /**
  213. * The component name helpful to identify the component in the list of scene components.
  214. */
  215. public readonly name = SceneComponentConstants.NAME_PHYSICSENGINE;
  216. /**
  217. * The scene the component belongs to.
  218. */
  219. public scene: Scene;
  220. /**
  221. * Creates a new instance of the component for the given scene
  222. * @param scene Defines the scene to register the component in
  223. */
  224. constructor(scene: Scene) {
  225. this.scene = scene;
  226. this.scene.onBeforePhysicsObservable = new Observable<Scene>();
  227. this.scene.onAfterPhysicsObservable = new Observable<Scene>();
  228. // Replace the function used to get the deterministic frame time
  229. this.scene.getDeterministicFrameTime = () => {
  230. if (this.scene._physicsEngine) {
  231. return this.scene._physicsEngine.getTimeStep() * 1000;
  232. }
  233. return 1000.0 / 60.0;
  234. };
  235. }
  236. /**
  237. * Registers the component in a given scene
  238. */
  239. public register(): void {
  240. }
  241. /**
  242. * Rebuilds the elements related to this component in case of
  243. * context lost for instance.
  244. */
  245. public rebuild(): void {
  246. // Nothing to do for this component
  247. }
  248. /**
  249. * Disposes the component and the associated ressources
  250. */
  251. public dispose(): void {
  252. this.scene.onBeforePhysicsObservable.clear();
  253. this.scene.onAfterPhysicsObservable.clear();
  254. if (this.scene._physicsEngine) {
  255. this.scene.disablePhysicsEngine();
  256. }
  257. }
  258. }
  259. }