babylon.physicsViewer.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. module BABYLON.Debug {
  2. /**
  3. * Used to show the physics impostor around the specific mesh
  4. */
  5. export class PhysicsViewer {
  6. /** @hidden */
  7. protected _impostors: Array<Nullable<PhysicsImpostor>> = [];
  8. /** @hidden */
  9. protected _meshes: Array<Nullable<AbstractMesh>> = [];
  10. /** @hidden */
  11. protected _scene: Nullable<Scene>;
  12. /** @hidden */
  13. protected _numMeshes = 0;
  14. /** @hidden */
  15. protected _physicsEnginePlugin: Nullable<IPhysicsEnginePlugin>;
  16. private _renderFunction: () => void;
  17. private _debugBoxMesh: Mesh;
  18. private _debugSphereMesh: Mesh;
  19. private _debugMaterial: StandardMaterial;
  20. /**
  21. * Creates a new PhysicsViewer
  22. * @param scene defines the hosting scene
  23. */
  24. constructor(scene: Scene) {
  25. this._scene = scene || Engine.LastCreatedScene;
  26. let physicEngine = this._scene.getPhysicsEngine();
  27. if (physicEngine) {
  28. this._physicsEnginePlugin = physicEngine.getPhysicsPlugin();
  29. }
  30. }
  31. /** @hidden */
  32. protected _updateDebugMeshes(): void {
  33. var plugin = this._physicsEnginePlugin;
  34. for (var i = 0; i < this._numMeshes; i++) {
  35. let impostor = this._impostors[i];
  36. if (!impostor) {
  37. continue;
  38. }
  39. if (impostor.isDisposed) {
  40. this.hideImpostor(this._impostors[i--]);
  41. } else {
  42. let mesh = this._meshes[i];
  43. if (mesh && plugin) {
  44. plugin.syncMeshWithImpostor(mesh, impostor);
  45. }
  46. }
  47. }
  48. }
  49. /**
  50. * Renders a specified physic impostor
  51. * @param impostor defines the impostor to render
  52. */
  53. public showImpostor(impostor: PhysicsImpostor): void {
  54. if (!this._scene) {
  55. return;
  56. }
  57. for (var i = 0; i < this._numMeshes; i++) {
  58. if (this._impostors[i] == impostor) {
  59. return;
  60. }
  61. }
  62. var debugMesh = this._getDebugMesh(impostor, this._scene);
  63. if (debugMesh) {
  64. this._impostors[this._numMeshes] = impostor;
  65. this._meshes[this._numMeshes] = debugMesh;
  66. if (this._numMeshes === 0) {
  67. this._renderFunction = this._updateDebugMeshes.bind(this);
  68. this._scene.registerBeforeRender(this._renderFunction);
  69. }
  70. this._numMeshes++;
  71. }
  72. }
  73. /**
  74. * Hides a specified physic impostor
  75. * @param impostor defines the impostor to hide
  76. */
  77. public hideImpostor(impostor: Nullable<PhysicsImpostor>) {
  78. if (!impostor || !this._scene) {
  79. return;
  80. }
  81. var removed = false;
  82. for (var i = 0; i < this._numMeshes; i++) {
  83. if (this._impostors[i] == impostor) {
  84. let mesh = this._meshes[i];
  85. if (!mesh) {
  86. continue;
  87. }
  88. this._scene.removeMesh(mesh);
  89. mesh.dispose();
  90. this._numMeshes--;
  91. if (this._numMeshes > 0) {
  92. this._meshes[i] = this._meshes[this._numMeshes];
  93. this._impostors[i] = this._impostors[this._numMeshes];
  94. this._meshes[this._numMeshes] = null;
  95. this._impostors[this._numMeshes] = null;
  96. } else {
  97. this._meshes[0] = null;
  98. this._impostors[0] = null;
  99. }
  100. removed = true;
  101. break;
  102. }
  103. }
  104. if (removed && this._numMeshes === 0) {
  105. this._scene.unregisterBeforeRender(this._renderFunction);
  106. }
  107. }
  108. private _getDebugMaterial(scene: Scene): Material {
  109. if (!this._debugMaterial) {
  110. this._debugMaterial = new StandardMaterial('', scene);
  111. this._debugMaterial.wireframe = true;
  112. }
  113. return this._debugMaterial;
  114. }
  115. private _getDebugBoxMesh(scene: Scene): AbstractMesh {
  116. if (!this._debugBoxMesh) {
  117. this._debugBoxMesh = MeshBuilder.CreateBox('physicsBodyBoxViewMesh', { size: 1 }, scene);
  118. this._debugBoxMesh.renderingGroupId = 1;
  119. this._debugBoxMesh.rotationQuaternion = Quaternion.Identity();
  120. this._debugBoxMesh.material = this._getDebugMaterial(scene);
  121. scene.removeMesh(this._debugBoxMesh);
  122. }
  123. return this._debugBoxMesh.createInstance('physicsBodyBoxViewInstance');
  124. }
  125. private _getDebugSphereMesh(scene: Scene): AbstractMesh {
  126. if (!this._debugSphereMesh) {
  127. this._debugSphereMesh = MeshBuilder.CreateSphere('physicsBodySphereViewMesh', { diameter: 1 }, scene);
  128. this._debugSphereMesh.renderingGroupId = 1;
  129. this._debugSphereMesh.rotationQuaternion = Quaternion.Identity();
  130. this._debugSphereMesh.material = this._getDebugMaterial(scene);
  131. scene.removeMesh(this._debugSphereMesh);
  132. }
  133. return this._debugSphereMesh.createInstance('physicsBodyBoxViewInstance');
  134. }
  135. private _getDebugMesh(impostor: PhysicsImpostor, scene: Scene): Nullable<AbstractMesh> {
  136. var mesh: Nullable<AbstractMesh> = null;
  137. if (impostor.type == PhysicsImpostor.BoxImpostor) {
  138. mesh = this._getDebugBoxMesh(scene);
  139. impostor.getBoxSizeToRef(mesh.scaling);
  140. } else if (impostor.type == PhysicsImpostor.SphereImpostor) {
  141. mesh = this._getDebugSphereMesh(scene);
  142. var radius = impostor.getRadius();
  143. mesh.scaling.x = radius * 2;
  144. mesh.scaling.y = radius * 2;
  145. mesh.scaling.z = radius * 2;
  146. }
  147. return mesh;
  148. }
  149. /** Releases all resources */
  150. public dispose() {
  151. for (var i = 0; i < this._numMeshes; i++) {
  152. this.hideImpostor(this._impostors[i]);
  153. }
  154. if (this._debugBoxMesh) {
  155. this._debugBoxMesh.dispose();
  156. }
  157. if (this._debugSphereMesh) {
  158. this._debugSphereMesh.dispose();
  159. }
  160. if (this._debugMaterial) {
  161. this._debugMaterial.dispose();
  162. }
  163. this._impostors.length = 0;
  164. this._scene = null;
  165. this._physicsEnginePlugin = null;
  166. }
  167. }
  168. }