babylon.debugModules.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. module BABYLON {
  2. export class Debug {
  3. public static AxesViewer = class AxesViewer {
  4. _xline = [Vector3.Zero(), Vector3.Zero()];
  5. _yline = [Vector3.Zero(), Vector3.Zero()];
  6. _zline = [Vector3.Zero(), Vector3.Zero()];
  7. _xmesh: Nullable<LinesMesh>;
  8. _ymesh: Nullable<LinesMesh>;
  9. _zmesh: Nullable<LinesMesh>;
  10. public scene: Nullable<Scene>;
  11. public scaleLines = 1;
  12. constructor(scene: Scene, scaleLines = 1) {
  13. this.scaleLines = scaleLines;
  14. this._xmesh = Mesh.CreateLines("xline", this._xline, scene, true);
  15. this._ymesh = Mesh.CreateLines("yline", this._yline, scene, true);
  16. this._zmesh = Mesh.CreateLines("zline", this._zline, scene, true);
  17. this._xmesh.renderingGroupId = 2;
  18. this._ymesh.renderingGroupId = 2;
  19. this._zmesh.renderingGroupId = 2;
  20. this._xmesh.material.checkReadyOnlyOnce = true;
  21. this._xmesh.color = new Color3(1, 0, 0);
  22. this._ymesh.material.checkReadyOnlyOnce = true;
  23. this._ymesh.color = new Color3(0, 1, 0);
  24. this._zmesh.material.checkReadyOnlyOnce = true;
  25. this._zmesh.color = new Color3(0, 0, 1);
  26. this.scene = scene;
  27. }
  28. public update(position: Vector3, xaxis: Vector3, yaxis: Vector3, zaxis: Vector3): void {
  29. var scaleLines = this.scaleLines;
  30. if (this._xmesh) {
  31. this._xmesh.position.copyFrom(position);
  32. }
  33. if (this._ymesh) {
  34. this._ymesh.position.copyFrom(position);
  35. }
  36. if (this._zmesh) {
  37. this._zmesh.position.copyFrom(position);
  38. }
  39. var point2 = this._xline[1];
  40. point2.x = xaxis.x * scaleLines;
  41. point2.y = xaxis.y * scaleLines;
  42. point2.z = xaxis.z * scaleLines;
  43. Mesh.CreateLines("", this._xline, null, false, this._xmesh);
  44. point2 = this._yline[1];
  45. point2.x = yaxis.x * scaleLines;
  46. point2.y = yaxis.y * scaleLines;
  47. point2.z = yaxis.z * scaleLines;
  48. Mesh.CreateLines("", this._yline, null, false, this._ymesh);
  49. point2 = this._zline[1];
  50. point2.x = zaxis.x * scaleLines;
  51. point2.y = zaxis.y * scaleLines;
  52. point2.z = zaxis.z * scaleLines;
  53. Mesh.CreateLines("", this._zline, null, false, this._zmesh);
  54. }
  55. public dispose() {
  56. if (this._xmesh) {
  57. this._xmesh.dispose();
  58. }
  59. if (this._ymesh) {
  60. this._ymesh.dispose();
  61. }
  62. if (this._zmesh) {
  63. this._zmesh.dispose();
  64. }
  65. this._xmesh = null;
  66. this._ymesh = null;
  67. this._zmesh = null;
  68. this.scene = null;
  69. }
  70. }
  71. public static BoneAxesViewer = class BoneAxesViewer extends Debug.AxesViewer {
  72. public mesh: Nullable<Mesh>;
  73. public bone: Nullable<Bone>;
  74. public pos = Vector3.Zero();
  75. public xaxis = Vector3.Zero();
  76. public yaxis = Vector3.Zero();
  77. public zaxis = Vector3.Zero();
  78. constructor(scene: Scene, bone: Bone, mesh: Mesh, scaleLines = 1) {
  79. super(scene, scaleLines);
  80. this.mesh = mesh;
  81. this.bone = bone;
  82. }
  83. public update(): void {
  84. if (!this.mesh || !this.bone) {
  85. return;
  86. }
  87. var bone = this.bone;
  88. bone.getAbsolutePositionToRef(this.mesh, this.pos);
  89. bone.getDirectionToRef(Axis.X, this.mesh, this.xaxis);
  90. bone.getDirectionToRef(Axis.Y, this.mesh, this.yaxis);
  91. bone.getDirectionToRef(Axis.Z, this.mesh, this.zaxis);
  92. super.update(this.pos, this.xaxis, this.yaxis, this.zaxis);
  93. }
  94. public dispose() {
  95. if (this.mesh) {
  96. this.mesh = null;
  97. this.bone = null;
  98. super.dispose();
  99. }
  100. }
  101. }
  102. public static PhysicsViewer = class PhysicsViewer {
  103. _impostors: Array<Nullable<PhysicsImpostor>> = [];
  104. _meshes: Array<Nullable<AbstractMesh>> = [];
  105. _scene: Nullable<Scene>;
  106. _numMeshes = 0;
  107. _physicsEnginePlugin: Nullable<IPhysicsEnginePlugin>;
  108. _renderFunction: () => void;
  109. _debugBoxMesh: Mesh;
  110. _debugSphereMesh: Mesh;
  111. _debugMaterial: StandardMaterial;
  112. constructor(scene: Scene) {
  113. this._scene = scene || Engine.LastCreatedScene;
  114. let physicEngine = this._scene.getPhysicsEngine();
  115. if (physicEngine) {
  116. this._physicsEnginePlugin = physicEngine.getPhysicsPlugin();
  117. }
  118. }
  119. _updateDebugMeshes(): void {
  120. var plugin = this._physicsEnginePlugin;
  121. for (var i = 0; i < this._numMeshes; i++) {
  122. let impostor = this._impostors[i];
  123. if (!impostor) {
  124. continue;
  125. }
  126. if (impostor.isDisposed) {
  127. this.hideImpostor(this._impostors[i--]);
  128. } else {
  129. let mesh = this._meshes[i];
  130. if (mesh && plugin) {
  131. plugin.syncMeshWithImpostor(mesh, impostor);
  132. }
  133. }
  134. }
  135. }
  136. public showImpostor(impostor: PhysicsImpostor): void {
  137. if (!this._scene) {
  138. return;
  139. }
  140. for (var i = 0; i < this._numMeshes; i++) {
  141. if (this._impostors[i] == impostor) {
  142. return;
  143. }
  144. }
  145. var debugMesh = this._getDebugMesh(impostor, this._scene);
  146. if (debugMesh) {
  147. this._impostors[this._numMeshes] = impostor;
  148. this._meshes[this._numMeshes] = debugMesh;
  149. if (this._numMeshes === 0) {
  150. this._renderFunction = this._updateDebugMeshes.bind(this);
  151. this._scene.registerBeforeRender(this._renderFunction);
  152. }
  153. this._numMeshes++;
  154. }
  155. }
  156. public hideImpostor(impostor: Nullable<PhysicsImpostor>) {
  157. if (!impostor || !this._scene) {
  158. return;
  159. }
  160. var removed = false;
  161. for (var i = 0; i < this._numMeshes; i++) {
  162. if (this._impostors[i] == impostor) {
  163. let mesh = this._meshes[i];
  164. if (!mesh) {
  165. continue;
  166. }
  167. this._scene.removeMesh(mesh);
  168. mesh.dispose();
  169. this._numMeshes--;
  170. if (this._numMeshes > 0) {
  171. this._meshes[i] = this._meshes[this._numMeshes];
  172. this._impostors[i] = this._impostors[this._numMeshes];
  173. this._meshes[this._numMeshes] = null;
  174. this._impostors[this._numMeshes] = null;
  175. } else {
  176. this._meshes[0] = null;
  177. this._impostors[0] = null;
  178. }
  179. removed = true;
  180. break;
  181. }
  182. }
  183. if (removed && this._numMeshes === 0) {
  184. this._scene.unregisterBeforeRender(this._renderFunction);
  185. }
  186. }
  187. _getDebugMaterial(scene: Scene): Material {
  188. if (!this._debugMaterial) {
  189. this._debugMaterial = new StandardMaterial('', scene);
  190. this._debugMaterial.wireframe = true;
  191. }
  192. return this._debugMaterial;
  193. }
  194. _getDebugBoxMesh(scene: Scene): AbstractMesh {
  195. if (!this._debugBoxMesh) {
  196. this._debugBoxMesh = MeshBuilder.CreateBox('physicsBodyBoxViewMesh', { size: 1 }, scene);
  197. this._debugBoxMesh.renderingGroupId = 1;
  198. this._debugBoxMesh.rotationQuaternion = Quaternion.Identity();
  199. this._debugBoxMesh.material = this._getDebugMaterial(scene);
  200. scene.removeMesh(this._debugBoxMesh);
  201. }
  202. return this._debugBoxMesh.createInstance('physicsBodyBoxViewInstance');
  203. }
  204. _getDebugSphereMesh(scene: Scene): AbstractMesh {
  205. if (!this._debugSphereMesh) {
  206. this._debugSphereMesh = MeshBuilder.CreateSphere('physicsBodySphereViewMesh', { diameter: 1 }, scene);
  207. this._debugSphereMesh.renderingGroupId = 1;
  208. this._debugSphereMesh.rotationQuaternion = Quaternion.Identity();
  209. this._debugSphereMesh.material = this._getDebugMaterial(scene);
  210. scene.removeMesh(this._debugSphereMesh);
  211. }
  212. return this._debugSphereMesh.createInstance('physicsBodyBoxViewInstance');
  213. }
  214. _getDebugMesh(impostor: PhysicsImpostor, scene: Scene): Nullable<AbstractMesh> {
  215. var mesh: Nullable<AbstractMesh> = null;
  216. if (impostor.type == PhysicsImpostor.BoxImpostor) {
  217. mesh = this._getDebugBoxMesh(scene);
  218. impostor.getBoxSizeToRef(mesh.scaling);
  219. } else if (impostor.type == PhysicsImpostor.SphereImpostor) {
  220. mesh = this._getDebugSphereMesh(scene);
  221. var radius = impostor.getRadius();
  222. mesh.scaling.x = radius * 2;
  223. mesh.scaling.y = radius * 2;
  224. mesh.scaling.z = radius * 2;
  225. }
  226. return mesh;
  227. }
  228. public dispose() {
  229. for (var i = 0; i < this._numMeshes; i++) {
  230. this.hideImpostor(this._impostors[i]);
  231. }
  232. if (this._debugBoxMesh) {
  233. this._debugBoxMesh.dispose();
  234. }
  235. if (this._debugSphereMesh) {
  236. this._debugSphereMesh.dispose();
  237. }
  238. if (this._debugMaterial) {
  239. this._debugMaterial.dispose();
  240. }
  241. this._impostors.length = 0;
  242. this._scene = null;
  243. this._physicsEnginePlugin = null;
  244. }
  245. }
  246. public static SkeletonViewer = class SkeletonViewer {
  247. public color: Color3 = Color3.White();
  248. _scene: Scene;
  249. _debugLines = new Array<Array<Vector3>>();
  250. _debugMesh: Nullable<LinesMesh>;
  251. _isEnabled = false;
  252. _renderFunction: () => void;
  253. constructor(public skeleton: Skeleton, public mesh: AbstractMesh, scene: Scene, public autoUpdateBonesMatrices = true, public renderingGroupId = 1) {
  254. this._scene = scene;
  255. this.update();
  256. this._renderFunction = this.update.bind(this);
  257. }
  258. public set isEnabled(value: boolean) {
  259. if (this._isEnabled === value) {
  260. return;
  261. }
  262. this._isEnabled = value;
  263. if (value) {
  264. this._scene.registerBeforeRender(this._renderFunction);
  265. } else {
  266. this._scene.unregisterBeforeRender(this._renderFunction);
  267. }
  268. }
  269. public get isEnabled(): boolean {
  270. return this._isEnabled;
  271. }
  272. _getBonePosition(position: Vector3, bone: Bone, meshMat: Matrix, x = 0, y = 0, z = 0): void {
  273. var tmat = Tmp.Matrix[0];
  274. var parentBone = bone.getParent();
  275. tmat.copyFrom(bone.getLocalMatrix());
  276. if (x !== 0 || y !== 0 || z !== 0) {
  277. var tmat2 = Tmp.Matrix[1];
  278. BABYLON.Matrix.IdentityToRef(tmat2);
  279. tmat2.m[12] = x;
  280. tmat2.m[13] = y;
  281. tmat2.m[14] = z;
  282. tmat2.multiplyToRef(tmat, tmat);
  283. }
  284. if (parentBone) {
  285. tmat.multiplyToRef(parentBone.getAbsoluteTransform(), tmat);
  286. }
  287. tmat.multiplyToRef(meshMat, tmat);
  288. position.x = tmat.m[12];
  289. position.y = tmat.m[13];
  290. position.z = tmat.m[14];
  291. }
  292. _getLinesForBonesWithLength(bones: Bone[], meshMat: Matrix): void {
  293. var len = bones.length;
  294. var meshPos = this.mesh.position;
  295. for (var i = 0; i < len; i++) {
  296. var bone = bones[i];
  297. var points = this._debugLines[i];
  298. if (!points) {
  299. points = [Vector3.Zero(), Vector3.Zero()];
  300. this._debugLines[i] = points;
  301. }
  302. this._getBonePosition(points[0], bone, meshMat);
  303. this._getBonePosition(points[1], bone, meshMat, 0, bone.length, 0);
  304. points[0].subtractInPlace(meshPos);
  305. points[1].subtractInPlace(meshPos);
  306. }
  307. }
  308. _getLinesForBonesNoLength(bones: Bone[], meshMat: Matrix): void {
  309. var len = bones.length;
  310. var boneNum = 0;
  311. var meshPos = this.mesh.position;
  312. for (var i = len - 1; i >= 0; i--) {
  313. var childBone = bones[i];
  314. var parentBone = childBone.getParent();
  315. if (!parentBone) {
  316. continue;
  317. }
  318. var points = this._debugLines[boneNum];
  319. if (!points) {
  320. points = [Vector3.Zero(), Vector3.Zero()];
  321. this._debugLines[boneNum] = points;
  322. }
  323. childBone.getAbsolutePositionToRef(this.mesh, points[0]);
  324. parentBone.getAbsolutePositionToRef(this.mesh, points[1]);
  325. points[0].subtractInPlace(meshPos);
  326. points[1].subtractInPlace(meshPos);
  327. boneNum++;
  328. }
  329. }
  330. public update() {
  331. if (this.autoUpdateBonesMatrices) {
  332. this.skeleton.computeAbsoluteTransforms();
  333. }
  334. if (this.skeleton.bones[0].length === undefined) {
  335. this._getLinesForBonesNoLength(this.skeleton.bones, this.mesh.getWorldMatrix());
  336. } else {
  337. this._getLinesForBonesWithLength(this.skeleton.bones, this.mesh.getWorldMatrix());
  338. }
  339. if (!this._debugMesh) {
  340. this._debugMesh = BABYLON.MeshBuilder.CreateLineSystem("", { lines: this._debugLines, updatable: true, instance: null }, this._scene);
  341. this._debugMesh.renderingGroupId = this.renderingGroupId;
  342. } else {
  343. BABYLON.MeshBuilder.CreateLineSystem("", { lines: this._debugLines, updatable: true, instance: this._debugMesh }, this._scene);
  344. }
  345. this._debugMesh.position.copyFrom(this.mesh.position);
  346. this._debugMesh.color = this.color;
  347. }
  348. public dispose() {
  349. if (this._debugMesh) {
  350. this.isEnabled = false;
  351. this._debugMesh.dispose();
  352. this._debugMesh = null;
  353. }
  354. }
  355. }
  356. }
  357. }