physicsHelper.ts 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. import { Nullable } from "../types";
  2. import { Logger } from "../Misc/logger";
  3. import { Vector3 } from "../Maths/math";
  4. import { AbstractMesh } from "../Meshes/abstractMesh";
  5. import { Mesh } from "../Meshes/mesh";
  6. import { SphereBuilder } from "../Meshes/Builders/sphereBuilder";
  7. import { CylinderBuilder } from "../Meshes/Builders/cylinderBuilder";
  8. import { Ray } from "../Culling/ray";
  9. import { Scene } from "../scene";
  10. import { IPhysicsEngine } from "./IPhysicsEngine";
  11. import { PhysicsEngine } from "./physicsEngine";
  12. import { PhysicsImpostor } from "./physicsImpostor";
  13. /**
  14. * A helper for physics simulations
  15. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  16. */
  17. export class PhysicsHelper {
  18. private _scene: Scene;
  19. private _physicsEngine: Nullable<IPhysicsEngine>;
  20. /**
  21. * Initializes the Physics helper
  22. * @param scene Babylon.js scene
  23. */
  24. constructor(scene: Scene) {
  25. this._scene = scene;
  26. this._physicsEngine = this._scene.getPhysicsEngine();
  27. if (!this._physicsEngine) {
  28. Logger.Warn('Physics engine not enabled. Please enable the physics before you can use the methods.');
  29. }
  30. }
  31. /**
  32. * Applies a radial explosion impulse
  33. * @param origin the origin of the explosion
  34. * @param eventOptions the options of radial explosion
  35. * @returns A physics radial explosion event, or null
  36. */
  37. public applyRadialExplosionImpulse(origin: Vector3, eventOptions: PhysicsRadialExplosionEventOptions): Nullable<PhysicsRadialExplosionEvent> {
  38. if (!this._physicsEngine) {
  39. Logger.Warn('Physics engine not enabled. Please enable the physics before you call this method.');
  40. return null;
  41. }
  42. var impostors = this._physicsEngine.getImpostors();
  43. if (impostors.length === 0) {
  44. return null;
  45. }
  46. var event = new PhysicsRadialExplosionEvent(this._scene, eventOptions);
  47. impostors.forEach((impostor) => {
  48. var impostorForceAndContactPoint = event.getImpostorForceAndContactPoint(impostor, origin);
  49. if (!impostorForceAndContactPoint) {
  50. return;
  51. }
  52. impostor.applyImpulse(impostorForceAndContactPoint.force, impostorForceAndContactPoint.contactPoint);
  53. });
  54. event.dispose(false);
  55. return event;
  56. }
  57. /**
  58. * Applies a radial explosion force
  59. * @param origin the origin of the explosion
  60. * @param eventOptions the options of radial explosion
  61. * @returns A physics radial explosion event, or null
  62. */
  63. public applyRadialExplosionForce(origin: Vector3, eventOptions: PhysicsRadialExplosionEventOptions): Nullable<PhysicsRadialExplosionEvent> {
  64. if (!this._physicsEngine) {
  65. Logger.Warn('Physics engine not enabled. Please enable the physics before you call the PhysicsHelper.');
  66. return null;
  67. }
  68. var impostors = this._physicsEngine.getImpostors();
  69. if (impostors.length === 0) {
  70. return null;
  71. }
  72. var event = new PhysicsRadialExplosionEvent(this._scene, eventOptions);
  73. impostors.forEach((impostor) => {
  74. var impostorForceAndContactPoint = event.getImpostorForceAndContactPoint(impostor, origin);
  75. if (!impostorForceAndContactPoint) {
  76. return;
  77. }
  78. impostor.applyForce(impostorForceAndContactPoint.force, impostorForceAndContactPoint.contactPoint);
  79. });
  80. event.dispose(false);
  81. return event;
  82. }
  83. /**
  84. * Creates a gravitational field
  85. * @param origin the origin of the explosion
  86. * @param eventOptions the options of gravitational field
  87. * @returns A physics gravitational field event, or null
  88. */
  89. public gravitationalField(origin: Vector3, eventOptions: PhysicsRadialExplosionEventOptions): Nullable<PhysicsGravitationalFieldEvent> {
  90. if (!this._physicsEngine) {
  91. Logger.Warn('Physics engine not enabled. Please enable the physics before you call the PhysicsHelper.');
  92. return null;
  93. }
  94. var impostors = this._physicsEngine.getImpostors();
  95. if (impostors.length === 0) {
  96. return null;
  97. }
  98. var event = new PhysicsGravitationalFieldEvent(this, this._scene, origin, eventOptions);
  99. event.dispose(false);
  100. return event;
  101. }
  102. /**
  103. * Creates a physics updraft event
  104. * @param origin the origin of the updraft
  105. * @param eventOptions the options of updraft
  106. * @returns A physics updraft event, or null
  107. */
  108. public updraft(origin: Vector3, eventOptions: PhysicsUpdraftEventOptions): Nullable<PhysicsUpdraftEvent> {
  109. if (!this._physicsEngine) {
  110. Logger.Warn('Physics engine not enabled. Please enable the physics before you call the PhysicsHelper.');
  111. return null;
  112. }
  113. if (this._physicsEngine.getImpostors().length === 0) {
  114. return null;
  115. }
  116. var event = new PhysicsUpdraftEvent(this._scene, origin, eventOptions);
  117. event.dispose(false);
  118. return event;
  119. }
  120. /**
  121. * Creates a physics vortex event
  122. * @param origin the of the vortex
  123. * @param eventOptions the options of vortex
  124. * @returns a Physics vortex event, or null
  125. * A physics vortex event or null
  126. */
  127. public vortex(origin: Vector3, eventOptions: PhysicsVortexEventOptions): Nullable<PhysicsVortexEvent> {
  128. if (!this._physicsEngine) {
  129. Logger.Warn('Physics engine not enabled. Please enable the physics before you call the PhysicsHelper.');
  130. return null;
  131. }
  132. if (this._physicsEngine.getImpostors().length === 0) {
  133. return null;
  134. }
  135. var event = new PhysicsVortexEvent(this._scene, origin, eventOptions);
  136. event.dispose(false);
  137. return event;
  138. }
  139. }
  140. /**
  141. * Represents a physics radial explosion event
  142. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  143. */
  144. export class PhysicsRadialExplosionEvent {
  145. private _sphere: Mesh; // create a sphere, so we can get the intersecting meshes inside
  146. private _sphereOptions: { segments: number, diameter: number } = { segments: 32, diameter: 1 }; // TODO: make configurable
  147. private _dataFetched: boolean = false; // check if the data has been fetched. If not, do cleanup
  148. /**
  149. * Initializes a radial explosioin event
  150. * @param _scene BabylonJS scene
  151. * @param _options The options for the vortex event
  152. */
  153. constructor(private _scene: Scene, private _options: PhysicsRadialExplosionEventOptions) {
  154. this._options = {...(new PhysicsRadialExplosionEventOptions), ...this._options};
  155. }
  156. /**
  157. * Returns the data related to the radial explosion event (sphere).
  158. * @returns The radial explosion event data
  159. */
  160. public getData(): PhysicsRadialExplosionEventData {
  161. this._dataFetched = true;
  162. return {
  163. sphere: this._sphere,
  164. };
  165. }
  166. /**
  167. * Returns the force and contact point of the impostor or false, if the impostor is not affected by the force/impulse.
  168. * @param impostor A physics imposter
  169. * @param origin the origin of the explosion
  170. * @returns {Nullable<PhysicsForceAndContactPoint>} A physics force and contact point, or null
  171. */
  172. public getImpostorForceAndContactPoint(impostor: PhysicsImpostor, origin: Vector3): Nullable<PhysicsForceAndContactPoint> {
  173. if (impostor.mass === 0) {
  174. return null;
  175. }
  176. if (!this._intersectsWithSphere(impostor, origin, this._options.radius)) {
  177. return null;
  178. }
  179. if (impostor.object.getClassName() !== 'Mesh' && impostor.object.getClassName() !== 'InstancedMesh') {
  180. return null;
  181. }
  182. var impostorObjectCenter = impostor.getObjectCenter();
  183. var direction = impostorObjectCenter.subtract(origin);
  184. var ray = new Ray(origin, direction, this._options.radius);
  185. var hit = ray.intersectsMesh(<AbstractMesh>impostor.object);
  186. var contactPoint = hit.pickedPoint;
  187. if (!contactPoint) {
  188. return null;
  189. }
  190. var distanceFromOrigin = Vector3.Distance(origin, contactPoint);
  191. if (distanceFromOrigin > this._options.radius) {
  192. return null;
  193. }
  194. var multiplier = this._options.falloff === PhysicsRadialImpulseFalloff.Constant
  195. ? this._options.strength
  196. : this._options.strength * (1 - (distanceFromOrigin / this._options.radius));
  197. var force = direction.multiplyByFloats(multiplier, multiplier, multiplier);
  198. return { force: force, contactPoint: contactPoint };
  199. }
  200. /**
  201. * Disposes the sphere.
  202. * @param force Specifies if the sphere should be disposed by force
  203. */
  204. public dispose(force: boolean = true) {
  205. if (force) {
  206. this._sphere.dispose();
  207. } else {
  208. setTimeout(() => {
  209. if (!this._dataFetched) {
  210. this._sphere.dispose();
  211. }
  212. }, 0);
  213. }
  214. }
  215. /*** Helpers ***/
  216. private _prepareSphere(): void {
  217. if (!this._sphere) {
  218. this._sphere = SphereBuilder.CreateSphere("radialExplosionEventSphere", this._sphereOptions, this._scene);
  219. this._sphere.isVisible = false;
  220. }
  221. }
  222. private _intersectsWithSphere(impostor: PhysicsImpostor, origin: Vector3, radius: number): boolean {
  223. var impostorObject = <AbstractMesh>impostor.object;
  224. this._prepareSphere();
  225. this._sphere.position = origin;
  226. this._sphere.scaling = new Vector3(radius * 2, radius * 2, radius * 2);
  227. this._sphere._updateBoundingInfo();
  228. this._sphere.computeWorldMatrix(true);
  229. return this._sphere.intersectsMesh(impostorObject, true);
  230. }
  231. }
  232. /**
  233. * Represents a gravitational field event
  234. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  235. */
  236. export class PhysicsGravitationalFieldEvent {
  237. private _tickCallback: any;
  238. private _sphere: Mesh;
  239. private _dataFetched: boolean = false; // check if the has been fetched the data. If not, do cleanup
  240. /**
  241. * Initializes the physics gravitational field event
  242. * @param _physicsHelper A physics helper
  243. * @param _scene BabylonJS scene
  244. * @param _origin The origin position of the gravitational field event
  245. * @param _options The options for the vortex event
  246. */
  247. constructor(private _physicsHelper: PhysicsHelper, private _scene: Scene, private _origin: Vector3, private _options: PhysicsRadialExplosionEventOptions) {
  248. this._options = {...(new PhysicsRadialExplosionEventOptions), ...this._options};
  249. this._tickCallback = this._tick.bind(this);
  250. this._options.strength = this._options.strength * -1;
  251. }
  252. /**
  253. * Returns the data related to the gravitational field event (sphere).
  254. * @returns A gravitational field event
  255. */
  256. public getData(): PhysicsGravitationalFieldEventData {
  257. this._dataFetched = true;
  258. return {
  259. sphere: this._sphere,
  260. };
  261. }
  262. /**
  263. * Enables the gravitational field.
  264. */
  265. public enable() {
  266. this._tickCallback.call(this);
  267. this._scene.registerBeforeRender(this._tickCallback);
  268. }
  269. /**
  270. * Disables the gravitational field.
  271. */
  272. public disable() {
  273. this._scene.unregisterBeforeRender(this._tickCallback);
  274. }
  275. /**
  276. * Disposes the sphere.
  277. * @param force The force to dispose from the gravitational field event
  278. */
  279. public dispose(force: boolean = true) {
  280. if (force) {
  281. this._sphere.dispose();
  282. } else {
  283. setTimeout(() => {
  284. if (!this._dataFetched) {
  285. this._sphere.dispose();
  286. }
  287. }, 0);
  288. }
  289. }
  290. private _tick() {
  291. // Since the params won't change, we fetch the event only once
  292. if (this._sphere) {
  293. this._physicsHelper.applyRadialExplosionForce(this._origin, this._options);
  294. } else {
  295. var radialExplosionEvent = this._physicsHelper.applyRadialExplosionForce(this._origin, this._options);
  296. if (radialExplosionEvent) {
  297. this._sphere = <Mesh>radialExplosionEvent.getData().sphere.clone('radialExplosionEventSphereClone');
  298. }
  299. }
  300. }
  301. }
  302. /**
  303. * Represents a physics updraft event
  304. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  305. */
  306. export class PhysicsUpdraftEvent {
  307. private _physicsEngine: PhysicsEngine;
  308. private _originTop: Vector3 = Vector3.Zero(); // the most upper part of the cylinder
  309. private _originDirection: Vector3 = Vector3.Zero(); // used if the updraftMode is perpendicular
  310. private _tickCallback: any;
  311. private _cylinder: Mesh;
  312. private _cylinderPosition: Vector3 = Vector3.Zero(); // to keep the cylinders position, because normally the origin is in the center and not on the bottom
  313. private _dataFetched: boolean = false; // check if the has been fetched the data. If not, do cleanup
  314. /**
  315. * Initializes the physics updraft event
  316. * @param _scene BabylonJS scene
  317. * @param _origin The origin position of the updraft
  318. * @param _options The options for the updraft event
  319. */
  320. constructor(private _scene: Scene, private _origin: Vector3, private _options: PhysicsUpdraftEventOptions) {
  321. this._physicsEngine = <PhysicsEngine>this._scene.getPhysicsEngine();
  322. this._options = {...(new PhysicsUpdraftEventOptions), ...this._options};
  323. this._origin.addToRef(new Vector3(0, this._options.height / 2, 0), this._cylinderPosition);
  324. this._origin.addToRef(new Vector3(0, this._options.height, 0), this._originTop);
  325. if (this._options.updraftMode === PhysicsUpdraftMode.Perpendicular) {
  326. this._originDirection = this._origin.subtract(this._originTop).normalize();
  327. }
  328. this._tickCallback = this._tick.bind(this);
  329. this._prepareCylinder();
  330. }
  331. /**
  332. * Returns the data related to the updraft event (cylinder).
  333. * @returns A physics updraft event
  334. */
  335. public getData(): PhysicsUpdraftEventData {
  336. this._dataFetched = true;
  337. return {
  338. cylinder: this._cylinder,
  339. };
  340. }
  341. /**
  342. * Enables the updraft.
  343. */
  344. public enable() {
  345. this._tickCallback.call(this);
  346. this._scene.registerBeforeRender(this._tickCallback);
  347. }
  348. /**
  349. * Disables the cortex.
  350. */
  351. public disable() {
  352. this._scene.unregisterBeforeRender(this._tickCallback);
  353. }
  354. /**
  355. * Disposes the sphere.
  356. * @param force Specifies if the updraft should be disposed by force
  357. */
  358. public dispose(force: boolean = true) {
  359. if (!this._cylinder) {
  360. return;
  361. }
  362. if (force) {
  363. this._cylinder.dispose();
  364. } else {
  365. setTimeout(() => {
  366. if (!this._dataFetched) {
  367. this._cylinder.dispose();
  368. }
  369. }, 0);
  370. }
  371. }
  372. private getImpostorForceAndContactPoint(impostor: PhysicsImpostor): Nullable<PhysicsForceAndContactPoint> {
  373. if (impostor.mass === 0) {
  374. return null;
  375. }
  376. if (!this._intersectsWithCylinder(impostor)) {
  377. return null;
  378. }
  379. var impostorObjectCenter = impostor.getObjectCenter();
  380. if (this._options.updraftMode === PhysicsUpdraftMode.Perpendicular) {
  381. var direction = this._originDirection;
  382. } else {
  383. var direction = impostorObjectCenter.subtract(this._originTop);
  384. }
  385. var multiplier = this._options.strength * -1;
  386. var force = direction.multiplyByFloats(multiplier, multiplier, multiplier);
  387. return { force: force, contactPoint: impostorObjectCenter };
  388. }
  389. private _tick() {
  390. this._physicsEngine.getImpostors().forEach((impostor) => {
  391. var impostorForceAndContactPoint = this.getImpostorForceAndContactPoint(impostor);
  392. if (!impostorForceAndContactPoint) {
  393. return;
  394. }
  395. impostor.applyForce(impostorForceAndContactPoint.force, impostorForceAndContactPoint.contactPoint);
  396. });
  397. }
  398. /*** Helpers ***/
  399. private _prepareCylinder(): void {
  400. if (!this._cylinder) {
  401. this._cylinder = CylinderBuilder.CreateCylinder("updraftEventCylinder", {
  402. height: this._options.height,
  403. diameter: this._options.radius * 2,
  404. }, this._scene);
  405. this._cylinder.isVisible = false;
  406. }
  407. }
  408. private _intersectsWithCylinder(impostor: PhysicsImpostor): boolean {
  409. var impostorObject = <AbstractMesh>impostor.object;
  410. this._cylinder.position = this._cylinderPosition;
  411. return this._cylinder.intersectsMesh(impostorObject, true);
  412. }
  413. }
  414. /**
  415. * Represents a physics vortex event
  416. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  417. */
  418. export class PhysicsVortexEvent {
  419. private _physicsEngine: PhysicsEngine;
  420. private _originTop: Vector3 = Vector3.Zero(); // the most upper part of the cylinder
  421. private _tickCallback: any;
  422. private _cylinder: Mesh;
  423. private _cylinderPosition: Vector3 = Vector3.Zero(); // to keep the cylinders position, because normally the origin is in the center and not on the bottom
  424. private _dataFetched: boolean = false; // check if the has been fetched the data. If not, do cleanup
  425. /**
  426. * Initializes the physics vortex event
  427. * @param _scene The BabylonJS scene
  428. * @param _origin The origin position of the vortex
  429. * @param _options The options for the vortex event
  430. */
  431. constructor(private _scene: Scene, private _origin: Vector3, private _options: PhysicsVortexEventOptions) {
  432. this._physicsEngine = <PhysicsEngine>this._scene.getPhysicsEngine();
  433. this._options = {...(new PhysicsVortexEventOptions), ...this._options};
  434. this._origin.addToRef(new Vector3(0, this._options.height / 2, 0), this._cylinderPosition);
  435. this._origin.addToRef(new Vector3(0, this._options.height, 0), this._originTop);
  436. this._tickCallback = this._tick.bind(this);
  437. this._prepareCylinder();
  438. }
  439. /**
  440. * Returns the data related to the vortex event (cylinder).
  441. * @returns The physics vortex event data
  442. */
  443. public getData(): PhysicsVortexEventData {
  444. this._dataFetched = true;
  445. return {
  446. cylinder: this._cylinder,
  447. };
  448. }
  449. /**
  450. * Enables the vortex.
  451. */
  452. public enable() {
  453. this._tickCallback.call(this);
  454. this._scene.registerBeforeRender(this._tickCallback);
  455. }
  456. /**
  457. * Disables the cortex.
  458. */
  459. public disable() {
  460. this._scene.unregisterBeforeRender(this._tickCallback);
  461. }
  462. /**
  463. * Disposes the sphere.
  464. * @param force
  465. */
  466. public dispose(force: boolean = true) {
  467. if (force) {
  468. this._cylinder.dispose();
  469. } else {
  470. setTimeout(() => {
  471. if (!this._dataFetched) {
  472. this._cylinder.dispose();
  473. }
  474. }, 0);
  475. }
  476. }
  477. private getImpostorForceAndContactPoint(impostor: PhysicsImpostor): Nullable<PhysicsForceAndContactPoint> {
  478. if (impostor.mass === 0) {
  479. return null;
  480. }
  481. if (!this._intersectsWithCylinder(impostor)) {
  482. return null;
  483. }
  484. if (impostor.object.getClassName() !== 'Mesh' && impostor.object.getClassName() !== 'InstancedMesh') {
  485. return null;
  486. }
  487. var impostorObjectCenter = impostor.getObjectCenter();
  488. var originOnPlane = new Vector3(this._origin.x, impostorObjectCenter.y, this._origin.z); // the distance to the origin as if both objects were on a plane (Y-axis)
  489. var originToImpostorDirection = impostorObjectCenter.subtract(originOnPlane);
  490. var ray = new Ray(originOnPlane, originToImpostorDirection, this._options.radius);
  491. var hit = ray.intersectsMesh(<AbstractMesh>impostor.object);
  492. var contactPoint = hit.pickedPoint;
  493. if (!contactPoint) {
  494. return null;
  495. }
  496. var absoluteDistanceFromOrigin = hit.distance / this._options.radius;
  497. var directionToOrigin = contactPoint.normalize();
  498. if (absoluteDistanceFromOrigin > this._options.centripetalForceThreshold) {
  499. directionToOrigin = directionToOrigin.negate();
  500. }
  501. // TODO: find a more physics based solution
  502. if (absoluteDistanceFromOrigin > this._options.centripetalForceThreshold) {
  503. var forceX = directionToOrigin.x * this._options.strength / 8;
  504. var forceY = directionToOrigin.y * this._options.updraftMultiplier;
  505. var forceZ = directionToOrigin.z * this._options.strength / 8;
  506. } else {
  507. var perpendicularDirection = Vector3.Cross(originOnPlane, impostorObjectCenter).normalize();
  508. var forceX = (perpendicularDirection.x + directionToOrigin.x) / 2;
  509. var forceY = this._originTop.y * this._options.updraftMultiplier;
  510. var forceZ = (perpendicularDirection.z + directionToOrigin.z) / 2;
  511. }
  512. var force = new Vector3(forceX, forceY, forceZ);
  513. force = force.multiplyByFloats(this._options.strength, this._options.strength, this._options.strength);
  514. return { force: force, contactPoint: impostorObjectCenter };
  515. }
  516. private _tick() {
  517. this._physicsEngine.getImpostors().forEach((impostor) => {
  518. var impostorForceAndContactPoint = this.getImpostorForceAndContactPoint(impostor);
  519. if (!impostorForceAndContactPoint) {
  520. return;
  521. }
  522. impostor.applyForce(impostorForceAndContactPoint.force, impostorForceAndContactPoint.contactPoint);
  523. });
  524. }
  525. /*** Helpers ***/
  526. private _prepareCylinder(): void {
  527. if (!this._cylinder) {
  528. this._cylinder = CylinderBuilder.CreateCylinder("vortexEventCylinder", {
  529. height: this._options.height,
  530. diameter: this._options.radius * 2,
  531. }, this._scene);
  532. this._cylinder.isVisible = false;
  533. }
  534. }
  535. private _intersectsWithCylinder(impostor: PhysicsImpostor): boolean {
  536. var impostorObject = <AbstractMesh>impostor.object;
  537. this._cylinder.position = this._cylinderPosition;
  538. return this._cylinder.intersectsMesh(impostorObject, true);
  539. }
  540. }
  541. /**
  542. * Options fot the radial explosion event
  543. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  544. */
  545. export class PhysicsRadialExplosionEventOptions {
  546. /**
  547. * The radius of the sphere for the radial explosion.
  548. */
  549. radius: number = 5;
  550. /**
  551. * The strenth of the explosion.
  552. */
  553. strength: number = 10;
  554. /**
  555. * The strenght of the force in correspondence to the distance of the affected object
  556. */
  557. falloff: PhysicsRadialImpulseFalloff = PhysicsRadialImpulseFalloff.Constant;
  558. }
  559. /**
  560. * Options fot the updraft event
  561. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  562. */
  563. export class PhysicsUpdraftEventOptions {
  564. /**
  565. * The radius of the cylinder for the vortex
  566. */
  567. radius: number = 5;
  568. /**
  569. * The strenth of the updraft.
  570. */
  571. strength: number = 10;
  572. /**
  573. * The height of the cylinder for the updraft.
  574. */
  575. height: number = 10;
  576. /**
  577. * The mode for the the updraft.
  578. */
  579. updraftMode: PhysicsUpdraftMode = PhysicsUpdraftMode.Center;
  580. }
  581. /**
  582. * Options fot the vortex event
  583. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  584. */
  585. export class PhysicsVortexEventOptions {
  586. /**
  587. * The radius of the cylinder for the vortex
  588. */
  589. radius: number = 5;
  590. /**
  591. * The strenth of the vortex.
  592. */
  593. strength: number = 10;
  594. /**
  595. * The height of the cylinder for the vortex.
  596. */
  597. height: number = 10;
  598. /**
  599. * At which distance, relative to the radius the centripetal forces should kick in?
  600. */
  601. centripetalForceThreshold: number = 0.7;
  602. /**
  603. * The updraft multiplier.
  604. */
  605. updraftMultiplier: number = 0.02;
  606. }
  607. /**
  608. * The strenght of the force in correspondence to the distance of the affected object
  609. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  610. */
  611. export enum PhysicsRadialImpulseFalloff {
  612. /** Defines that impulse is constant in strength across it's whole radius */
  613. Constant,
  614. /** Defines that impulse gets weaker if it's further from the origin */
  615. Linear
  616. }
  617. /**
  618. * The strength of the force in correspondence to the distance of the affected object
  619. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  620. */
  621. export enum PhysicsUpdraftMode {
  622. /** Defines that the upstream forces will pull towards the top center of the cylinder */
  623. Center,
  624. /** Defines that once a impostor is inside the cylinder, it will shoot out perpendicular from the ground of the cylinder */
  625. Perpendicular
  626. }
  627. /**
  628. * Interface for a physics force and contact point
  629. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  630. */
  631. export interface PhysicsForceAndContactPoint {
  632. /**
  633. * The force applied at the contact point
  634. */
  635. force: Vector3;
  636. /**
  637. * The contact point
  638. */
  639. contactPoint: Vector3;
  640. }
  641. /**
  642. * Interface for radial explosion event data
  643. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  644. */
  645. export interface PhysicsRadialExplosionEventData {
  646. /**
  647. * A sphere used for the radial explosion event
  648. */
  649. sphere: Mesh;
  650. }
  651. /**
  652. * Interface for gravitational field event data
  653. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  654. */
  655. export interface PhysicsGravitationalFieldEventData {
  656. /**
  657. * A sphere mesh used for the gravitational field event
  658. */
  659. sphere: Mesh;
  660. }
  661. /**
  662. * Interface for updraft event data
  663. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  664. */
  665. export interface PhysicsUpdraftEventData {
  666. /**
  667. * A cylinder used for the updraft event
  668. */
  669. cylinder: Mesh;
  670. }
  671. /**
  672. * Interface for vortex event data
  673. * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
  674. */
  675. export interface PhysicsVortexEventData {
  676. /**
  677. * A cylinder used for the vortex event
  678. */
  679. cylinder: Mesh;
  680. }