babylon.mesh.js 102 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163
  1. var __extends = (this && this.__extends) || function (d, b) {
  2. for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
  3. function __() { this.constructor = d; }
  4. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  5. };
  6. var BABYLON;
  7. (function (BABYLON) {
  8. var _InstancesBatch = (function () {
  9. function _InstancesBatch() {
  10. this.mustReturn = false;
  11. this.visibleInstances = new Array();
  12. this.renderSelf = new Array();
  13. }
  14. return _InstancesBatch;
  15. })();
  16. BABYLON._InstancesBatch = _InstancesBatch;
  17. var Mesh = (function (_super) {
  18. __extends(Mesh, _super);
  19. /**
  20. * @constructor
  21. * @param {string} name - The value used by scene.getMeshByName() to do a lookup.
  22. * @param {Scene} scene - The scene to add this mesh to.
  23. * @param {Node} parent - The parent of this mesh, if it has one
  24. * @param {Mesh} source - An optional Mesh from which geometry is shared, cloned.
  25. * @param {boolean} doNotCloneChildren - When cloning, skip cloning child meshes of source, default False.
  26. * When false, achieved by calling a clone(), also passing False.
  27. * This will make creation of children, recursive.
  28. */
  29. function Mesh(name, scene, parent, source, doNotCloneChildren) {
  30. if (parent === void 0) { parent = null; }
  31. _super.call(this, name, scene);
  32. // Members
  33. this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
  34. this.instances = new Array();
  35. this._LODLevels = new Array();
  36. this._onBeforeRenderCallbacks = new Array();
  37. this._onAfterRenderCallbacks = new Array();
  38. this._visibleInstances = {};
  39. this._renderIdForInstances = new Array();
  40. this._batchCache = new _InstancesBatch();
  41. this._instancesBufferSize = 32 * 16 * 4; // let's start with a maximum of 32 instances
  42. this._sideOrientation = Mesh._DEFAULTSIDE;
  43. this._areNormalsFrozen = false; // Will be used by ribbons mainly
  44. if (source) {
  45. // Geometry
  46. if (source._geometry) {
  47. source._geometry.applyToMesh(this);
  48. }
  49. // Deep copy
  50. BABYLON.Tools.DeepCopy(source, this, ["name", "material", "skeleton", "instances"], []);
  51. this.id = name + "." + source.id;
  52. // Material
  53. this.material = source.material;
  54. var index;
  55. if (!doNotCloneChildren) {
  56. // Children
  57. for (index = 0; index < scene.meshes.length; index++) {
  58. var mesh = scene.meshes[index];
  59. if (mesh.parent === source) {
  60. // doNotCloneChildren is always going to be False
  61. var newChild = mesh.clone(name + "." + mesh.name, this, doNotCloneChildren);
  62. }
  63. }
  64. }
  65. // Particles
  66. for (index = 0; index < scene.particleSystems.length; index++) {
  67. var system = scene.particleSystems[index];
  68. if (system.emitter === source) {
  69. system.clone(system.name, this);
  70. }
  71. }
  72. this.computeWorldMatrix(true);
  73. }
  74. // Parent
  75. if (parent !== null) {
  76. this.parent = parent;
  77. }
  78. }
  79. Object.defineProperty(Mesh, "FRONTSIDE", {
  80. get: function () {
  81. return Mesh._FRONTSIDE;
  82. },
  83. enumerable: true,
  84. configurable: true
  85. });
  86. Object.defineProperty(Mesh, "BACKSIDE", {
  87. get: function () {
  88. return Mesh._BACKSIDE;
  89. },
  90. enumerable: true,
  91. configurable: true
  92. });
  93. Object.defineProperty(Mesh, "DOUBLESIDE", {
  94. get: function () {
  95. return Mesh._DOUBLESIDE;
  96. },
  97. enumerable: true,
  98. configurable: true
  99. });
  100. Object.defineProperty(Mesh, "DEFAULTSIDE", {
  101. get: function () {
  102. return Mesh._DEFAULTSIDE;
  103. },
  104. enumerable: true,
  105. configurable: true
  106. });
  107. Object.defineProperty(Mesh, "NO_CAP", {
  108. get: function () {
  109. return Mesh._NO_CAP;
  110. },
  111. enumerable: true,
  112. configurable: true
  113. });
  114. Object.defineProperty(Mesh, "CAP_START", {
  115. get: function () {
  116. return Mesh._CAP_START;
  117. },
  118. enumerable: true,
  119. configurable: true
  120. });
  121. Object.defineProperty(Mesh, "CAP_END", {
  122. get: function () {
  123. return Mesh._CAP_END;
  124. },
  125. enumerable: true,
  126. configurable: true
  127. });
  128. Object.defineProperty(Mesh, "CAP_ALL", {
  129. get: function () {
  130. return Mesh._CAP_ALL;
  131. },
  132. enumerable: true,
  133. configurable: true
  134. });
  135. Object.defineProperty(Mesh.prototype, "hasLODLevels", {
  136. // Methods
  137. get: function () {
  138. return this._LODLevels.length > 0;
  139. },
  140. enumerable: true,
  141. configurable: true
  142. });
  143. Mesh.prototype._sortLODLevels = function () {
  144. this._LODLevels.sort(function (a, b) {
  145. if (a.distance < b.distance) {
  146. return 1;
  147. }
  148. if (a.distance > b.distance) {
  149. return -1;
  150. }
  151. return 0;
  152. });
  153. };
  154. /**
  155. * Add a mesh as LOD level triggered at the given distance.
  156. * @param {number} distance - the distance from the center of the object to show this level
  157. * @param {BABYLON.Mesh} mesh - the mesh to be added as LOD level
  158. * @return {BABYLON.Mesh} this mesh (for chaining)
  159. */
  160. Mesh.prototype.addLODLevel = function (distance, mesh) {
  161. if (mesh && mesh._masterMesh) {
  162. BABYLON.Tools.Warn("You cannot use a mesh as LOD level twice");
  163. return this;
  164. }
  165. var level = new BABYLON.Internals.MeshLODLevel(distance, mesh);
  166. this._LODLevels.push(level);
  167. if (mesh) {
  168. mesh._masterMesh = this;
  169. }
  170. this._sortLODLevels();
  171. return this;
  172. };
  173. Mesh.prototype.getLODLevelAtDistance = function (distance) {
  174. for (var index = 0; index < this._LODLevels.length; index++) {
  175. var level = this._LODLevels[index];
  176. if (level.distance === distance) {
  177. return level.mesh;
  178. }
  179. }
  180. return null;
  181. };
  182. /**
  183. * Remove a mesh from the LOD array
  184. * @param {BABYLON.Mesh} mesh - the mesh to be removed.
  185. * @return {BABYLON.Mesh} this mesh (for chaining)
  186. */
  187. Mesh.prototype.removeLODLevel = function (mesh) {
  188. for (var index = 0; index < this._LODLevels.length; index++) {
  189. if (this._LODLevels[index].mesh === mesh) {
  190. this._LODLevels.splice(index, 1);
  191. if (mesh) {
  192. mesh._masterMesh = null;
  193. }
  194. }
  195. }
  196. this._sortLODLevels();
  197. return this;
  198. };
  199. Mesh.prototype.getLOD = function (camera, boundingSphere) {
  200. if (!this._LODLevels || this._LODLevels.length === 0) {
  201. return this;
  202. }
  203. var distanceToCamera = (boundingSphere ? boundingSphere : this.getBoundingInfo().boundingSphere).centerWorld.subtract(camera.position).length();
  204. if (this._LODLevels[this._LODLevels.length - 1].distance > distanceToCamera) {
  205. if (this.onLODLevelSelection) {
  206. this.onLODLevelSelection(distanceToCamera, this, this._LODLevels[this._LODLevels.length - 1].mesh);
  207. }
  208. return this;
  209. }
  210. for (var index = 0; index < this._LODLevels.length; index++) {
  211. var level = this._LODLevels[index];
  212. if (level.distance < distanceToCamera) {
  213. if (level.mesh) {
  214. level.mesh._preActivate();
  215. level.mesh._updateSubMeshesBoundingInfo(this.worldMatrixFromCache);
  216. }
  217. if (this.onLODLevelSelection) {
  218. this.onLODLevelSelection(distanceToCamera, this, level.mesh);
  219. }
  220. return level.mesh;
  221. }
  222. }
  223. if (this.onLODLevelSelection) {
  224. this.onLODLevelSelection(distanceToCamera, this, this);
  225. }
  226. return this;
  227. };
  228. Object.defineProperty(Mesh.prototype, "geometry", {
  229. get: function () {
  230. return this._geometry;
  231. },
  232. enumerable: true,
  233. configurable: true
  234. });
  235. Mesh.prototype.getTotalVertices = function () {
  236. if (!this._geometry) {
  237. return 0;
  238. }
  239. return this._geometry.getTotalVertices();
  240. };
  241. Mesh.prototype.getVerticesData = function (kind, copyWhenShared) {
  242. if (!this._geometry) {
  243. return null;
  244. }
  245. return this._geometry.getVerticesData(kind, copyWhenShared);
  246. };
  247. Mesh.prototype.getVertexBuffer = function (kind) {
  248. if (!this._geometry) {
  249. return undefined;
  250. }
  251. return this._geometry.getVertexBuffer(kind);
  252. };
  253. Mesh.prototype.isVerticesDataPresent = function (kind) {
  254. if (!this._geometry) {
  255. if (this._delayInfo) {
  256. return this._delayInfo.indexOf(kind) !== -1;
  257. }
  258. return false;
  259. }
  260. return this._geometry.isVerticesDataPresent(kind);
  261. };
  262. Mesh.prototype.getVerticesDataKinds = function () {
  263. if (!this._geometry) {
  264. var result = [];
  265. if (this._delayInfo) {
  266. for (var kind in this._delayInfo) {
  267. result.push(kind);
  268. }
  269. }
  270. return result;
  271. }
  272. return this._geometry.getVerticesDataKinds();
  273. };
  274. Mesh.prototype.getTotalIndices = function () {
  275. if (!this._geometry) {
  276. return 0;
  277. }
  278. return this._geometry.getTotalIndices();
  279. };
  280. Mesh.prototype.getIndices = function (copyWhenShared) {
  281. if (!this._geometry) {
  282. return [];
  283. }
  284. return this._geometry.getIndices(copyWhenShared);
  285. };
  286. Object.defineProperty(Mesh.prototype, "isBlocked", {
  287. get: function () {
  288. return this._masterMesh !== null && this._masterMesh !== undefined;
  289. },
  290. enumerable: true,
  291. configurable: true
  292. });
  293. Mesh.prototype.isReady = function () {
  294. if (this.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_LOADING) {
  295. return false;
  296. }
  297. return _super.prototype.isReady.call(this);
  298. };
  299. Mesh.prototype.isDisposed = function () {
  300. return this._isDisposed;
  301. };
  302. Object.defineProperty(Mesh.prototype, "sideOrientation", {
  303. get: function () {
  304. return this._sideOrientation;
  305. },
  306. set: function (sideO) {
  307. this._sideOrientation = sideO;
  308. },
  309. enumerable: true,
  310. configurable: true
  311. });
  312. Object.defineProperty(Mesh.prototype, "areNormalsFrozen", {
  313. get: function () {
  314. return this._areNormalsFrozen;
  315. },
  316. enumerable: true,
  317. configurable: true
  318. });
  319. /** This function affects parametric shapes on update only : ribbons, tubes, etc. It has no effect at all on other shapes */
  320. Mesh.prototype.freezeNormals = function () {
  321. this._areNormalsFrozen = true;
  322. };
  323. /** This function affects parametric shapes on update only : ribbons, tubes, etc. It has no effect at all on other shapes */
  324. Mesh.prototype.unfreezeNormals = function () {
  325. this._areNormalsFrozen = false;
  326. };
  327. // Methods
  328. Mesh.prototype._preActivate = function () {
  329. var sceneRenderId = this.getScene().getRenderId();
  330. if (this._preActivateId === sceneRenderId) {
  331. return;
  332. }
  333. this._preActivateId = sceneRenderId;
  334. this._visibleInstances = null;
  335. };
  336. Mesh.prototype._registerInstanceForRenderId = function (instance, renderId) {
  337. if (!this._visibleInstances) {
  338. this._visibleInstances = {};
  339. this._visibleInstances.defaultRenderId = renderId;
  340. this._visibleInstances.selfDefaultRenderId = this._renderId;
  341. }
  342. if (!this._visibleInstances[renderId]) {
  343. this._visibleInstances[renderId] = new Array();
  344. }
  345. this._visibleInstances[renderId].push(instance);
  346. };
  347. Mesh.prototype.refreshBoundingInfo = function () {
  348. var data = this.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  349. if (data) {
  350. var extend = BABYLON.Tools.ExtractMinAndMax(data, 0, this.getTotalVertices());
  351. this._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
  352. }
  353. if (this.subMeshes) {
  354. for (var index = 0; index < this.subMeshes.length; index++) {
  355. this.subMeshes[index].refreshBoundingInfo();
  356. }
  357. }
  358. this._updateBoundingInfo();
  359. };
  360. Mesh.prototype._createGlobalSubMesh = function () {
  361. var totalVertices = this.getTotalVertices();
  362. if (!totalVertices || !this.getIndices()) {
  363. return null;
  364. }
  365. this.releaseSubMeshes();
  366. return new BABYLON.SubMesh(0, 0, totalVertices, 0, this.getTotalIndices(), this);
  367. };
  368. Mesh.prototype.subdivide = function (count) {
  369. if (count < 1) {
  370. return;
  371. }
  372. var totalIndices = this.getTotalIndices();
  373. var subdivisionSize = (totalIndices / count) | 0;
  374. var offset = 0;
  375. // Ensure that subdivisionSize is a multiple of 3
  376. while (subdivisionSize % 3 !== 0) {
  377. subdivisionSize++;
  378. }
  379. this.releaseSubMeshes();
  380. for (var index = 0; index < count; index++) {
  381. if (offset >= totalIndices) {
  382. break;
  383. }
  384. BABYLON.SubMesh.CreateFromIndices(0, offset, Math.min(subdivisionSize, totalIndices - offset), this);
  385. offset += subdivisionSize;
  386. }
  387. this.synchronizeInstances();
  388. };
  389. Mesh.prototype.setVerticesData = function (kind, data, updatable, stride) {
  390. if (!this._geometry) {
  391. var vertexData = new BABYLON.VertexData();
  392. vertexData.set(data, kind);
  393. var scene = this.getScene();
  394. new BABYLON.Geometry(BABYLON.Geometry.RandomId(), scene, vertexData, updatable, this);
  395. }
  396. else {
  397. this._geometry.setVerticesData(kind, data, updatable, stride);
  398. }
  399. };
  400. Mesh.prototype.updateVerticesData = function (kind, data, updateExtends, makeItUnique) {
  401. if (!this._geometry) {
  402. return;
  403. }
  404. if (!makeItUnique) {
  405. this._geometry.updateVerticesData(kind, data, updateExtends);
  406. }
  407. else {
  408. this.makeGeometryUnique();
  409. this.updateVerticesData(kind, data, updateExtends, false);
  410. }
  411. };
  412. Mesh.prototype.updateVerticesDataDirectly = function (kind, data, offset, makeItUnique) {
  413. BABYLON.Tools.Warn("Mesh.updateVerticesDataDirectly deprecated since 2.3.");
  414. if (!this._geometry) {
  415. return;
  416. }
  417. if (!makeItUnique) {
  418. this._geometry.updateVerticesDataDirectly(kind, data, offset);
  419. }
  420. else {
  421. this.makeGeometryUnique();
  422. this.updateVerticesDataDirectly(kind, data, offset, false);
  423. }
  424. };
  425. // Mesh positions update function :
  426. // updates the mesh positions according to the positionFunction returned values.
  427. // The positionFunction argument must be a javascript function accepting the mesh "positions" array as parameter.
  428. // This dedicated positionFunction computes new mesh positions according to the given mesh type.
  429. Mesh.prototype.updateMeshPositions = function (positionFunction, computeNormals) {
  430. if (computeNormals === void 0) { computeNormals = true; }
  431. var positions = this.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  432. positionFunction(positions);
  433. this.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positions, false, false);
  434. if (computeNormals) {
  435. var indices = this.getIndices();
  436. var normals = this.getVerticesData(BABYLON.VertexBuffer.NormalKind);
  437. BABYLON.VertexData.ComputeNormals(positions, indices, normals);
  438. this.updateVerticesData(BABYLON.VertexBuffer.NormalKind, normals, false, false);
  439. }
  440. };
  441. Mesh.prototype.makeGeometryUnique = function () {
  442. if (!this._geometry) {
  443. return;
  444. }
  445. var geometry = this._geometry.copy(BABYLON.Geometry.RandomId());
  446. geometry.applyToMesh(this);
  447. };
  448. Mesh.prototype.setIndices = function (indices, totalVertices) {
  449. if (!this._geometry) {
  450. var vertexData = new BABYLON.VertexData();
  451. vertexData.indices = indices;
  452. var scene = this.getScene();
  453. new BABYLON.Geometry(BABYLON.Geometry.RandomId(), scene, vertexData, false, this);
  454. }
  455. else {
  456. this._geometry.setIndices(indices, totalVertices);
  457. }
  458. };
  459. Mesh.prototype._bind = function (subMesh, effect, fillMode) {
  460. var engine = this.getScene().getEngine();
  461. // Wireframe
  462. var indexToBind;
  463. switch (fillMode) {
  464. case BABYLON.Material.PointFillMode:
  465. indexToBind = null;
  466. break;
  467. case BABYLON.Material.WireFrameFillMode:
  468. indexToBind = subMesh.getLinesIndexBuffer(this.getIndices(), engine);
  469. break;
  470. default:
  471. case BABYLON.Material.TriangleFillMode:
  472. indexToBind = this._geometry.getIndexBuffer();
  473. break;
  474. }
  475. // VBOs
  476. engine.bindMultiBuffers(this._geometry.getVertexBuffers(), indexToBind, effect);
  477. };
  478. Mesh.prototype._draw = function (subMesh, fillMode, instancesCount) {
  479. if (!this._geometry || !this._geometry.getVertexBuffers() || !this._geometry.getIndexBuffer()) {
  480. return;
  481. }
  482. var engine = this.getScene().getEngine();
  483. // Draw order
  484. switch (fillMode) {
  485. case BABYLON.Material.PointFillMode:
  486. engine.drawPointClouds(subMesh.verticesStart, subMesh.verticesCount, instancesCount);
  487. break;
  488. case BABYLON.Material.WireFrameFillMode:
  489. engine.draw(false, 0, subMesh.linesIndexCount, instancesCount);
  490. break;
  491. default:
  492. engine.draw(true, subMesh.indexStart, subMesh.indexCount, instancesCount);
  493. }
  494. };
  495. Mesh.prototype.registerBeforeRender = function (func) {
  496. this._onBeforeRenderCallbacks.push(func);
  497. };
  498. Mesh.prototype.unregisterBeforeRender = function (func) {
  499. var index = this._onBeforeRenderCallbacks.indexOf(func);
  500. if (index > -1) {
  501. this._onBeforeRenderCallbacks.splice(index, 1);
  502. }
  503. };
  504. Mesh.prototype.registerAfterRender = function (func) {
  505. this._onAfterRenderCallbacks.push(func);
  506. };
  507. Mesh.prototype.unregisterAfterRender = function (func) {
  508. var index = this._onAfterRenderCallbacks.indexOf(func);
  509. if (index > -1) {
  510. this._onAfterRenderCallbacks.splice(index, 1);
  511. }
  512. };
  513. Mesh.prototype._getInstancesRenderList = function (subMeshId) {
  514. var scene = this.getScene();
  515. this._batchCache.mustReturn = false;
  516. this._batchCache.renderSelf[subMeshId] = this.isEnabled() && this.isVisible;
  517. this._batchCache.visibleInstances[subMeshId] = null;
  518. if (this._visibleInstances) {
  519. var currentRenderId = scene.getRenderId();
  520. this._batchCache.visibleInstances[subMeshId] = this._visibleInstances[currentRenderId];
  521. var selfRenderId = this._renderId;
  522. if (!this._batchCache.visibleInstances[subMeshId] && this._visibleInstances.defaultRenderId) {
  523. this._batchCache.visibleInstances[subMeshId] = this._visibleInstances[this._visibleInstances.defaultRenderId];
  524. currentRenderId = Math.max(this._visibleInstances.defaultRenderId, currentRenderId);
  525. selfRenderId = Math.max(this._visibleInstances.selfDefaultRenderId, currentRenderId);
  526. }
  527. if (this._batchCache.visibleInstances[subMeshId] && this._batchCache.visibleInstances[subMeshId].length) {
  528. if (this._renderIdForInstances[subMeshId] === currentRenderId) {
  529. this._batchCache.mustReturn = true;
  530. return this._batchCache;
  531. }
  532. if (currentRenderId !== selfRenderId) {
  533. this._batchCache.renderSelf[subMeshId] = false;
  534. }
  535. }
  536. this._renderIdForInstances[subMeshId] = currentRenderId;
  537. }
  538. return this._batchCache;
  539. };
  540. Mesh.prototype._renderWithInstances = function (subMesh, fillMode, batch, effect, engine) {
  541. var visibleInstances = batch.visibleInstances[subMesh._id];
  542. var matricesCount = visibleInstances.length + 1;
  543. var bufferSize = matricesCount * 16 * 4;
  544. while (this._instancesBufferSize < bufferSize) {
  545. this._instancesBufferSize *= 2;
  546. }
  547. if (!this._worldMatricesInstancesBuffer || this._worldMatricesInstancesBuffer.capacity < this._instancesBufferSize) {
  548. if (this._worldMatricesInstancesBuffer) {
  549. engine.deleteInstancesBuffer(this._worldMatricesInstancesBuffer);
  550. }
  551. this._worldMatricesInstancesBuffer = engine.createInstancesBuffer(this._instancesBufferSize);
  552. this._worldMatricesInstancesArray = new Float32Array(this._instancesBufferSize / 4);
  553. }
  554. var offset = 0;
  555. var instancesCount = 0;
  556. var world = this.getWorldMatrix();
  557. if (batch.renderSelf[subMesh._id]) {
  558. world.copyToArray(this._worldMatricesInstancesArray, offset);
  559. offset += 16;
  560. instancesCount++;
  561. }
  562. if (visibleInstances) {
  563. for (var instanceIndex = 0; instanceIndex < visibleInstances.length; instanceIndex++) {
  564. var instance = visibleInstances[instanceIndex];
  565. instance.getWorldMatrix().copyToArray(this._worldMatricesInstancesArray, offset);
  566. offset += 16;
  567. instancesCount++;
  568. }
  569. }
  570. var offsetLocation0 = effect.getAttributeLocationByName("world0");
  571. var offsetLocation1 = effect.getAttributeLocationByName("world1");
  572. var offsetLocation2 = effect.getAttributeLocationByName("world2");
  573. var offsetLocation3 = effect.getAttributeLocationByName("world3");
  574. var offsetLocations = [offsetLocation0, offsetLocation1, offsetLocation2, offsetLocation3];
  575. engine.updateAndBindInstancesBuffer(this._worldMatricesInstancesBuffer, this._worldMatricesInstancesArray, offsetLocations);
  576. this._draw(subMesh, fillMode, instancesCount);
  577. engine.unBindInstancesBuffer(this._worldMatricesInstancesBuffer, offsetLocations);
  578. };
  579. Mesh.prototype._processRendering = function (subMesh, effect, fillMode, batch, hardwareInstancedRendering, onBeforeDraw) {
  580. var scene = this.getScene();
  581. var engine = scene.getEngine();
  582. if (hardwareInstancedRendering) {
  583. this._renderWithInstances(subMesh, fillMode, batch, effect, engine);
  584. }
  585. else {
  586. if (batch.renderSelf[subMesh._id]) {
  587. // Draw
  588. if (onBeforeDraw) {
  589. onBeforeDraw(false, this.getWorldMatrix());
  590. }
  591. this._draw(subMesh, fillMode);
  592. }
  593. if (batch.visibleInstances[subMesh._id]) {
  594. for (var instanceIndex = 0; instanceIndex < batch.visibleInstances[subMesh._id].length; instanceIndex++) {
  595. var instance = batch.visibleInstances[subMesh._id][instanceIndex];
  596. // World
  597. var world = instance.getWorldMatrix();
  598. if (onBeforeDraw) {
  599. onBeforeDraw(true, world);
  600. }
  601. // Draw
  602. this._draw(subMesh, fillMode);
  603. }
  604. }
  605. }
  606. };
  607. Mesh.prototype.render = function (subMesh, enableAlphaMode) {
  608. var scene = this.getScene();
  609. // Managing instances
  610. var batch = this._getInstancesRenderList(subMesh._id);
  611. if (batch.mustReturn) {
  612. return;
  613. }
  614. // Checking geometry state
  615. if (!this._geometry || !this._geometry.getVertexBuffers() || !this._geometry.getIndexBuffer()) {
  616. return;
  617. }
  618. var callbackIndex;
  619. for (callbackIndex = 0; callbackIndex < this._onBeforeRenderCallbacks.length; callbackIndex++) {
  620. this._onBeforeRenderCallbacks[callbackIndex](this);
  621. }
  622. var engine = scene.getEngine();
  623. var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
  624. // Material
  625. var effectiveMaterial = subMesh.getMaterial();
  626. if (!effectiveMaterial || !effectiveMaterial.isReady(this, hardwareInstancedRendering)) {
  627. return;
  628. }
  629. // Outline - step 1
  630. var savedDepthWrite = engine.getDepthWrite();
  631. if (this.renderOutline) {
  632. engine.setDepthWrite(false);
  633. scene.getOutlineRenderer().render(subMesh, batch);
  634. engine.setDepthWrite(savedDepthWrite);
  635. }
  636. effectiveMaterial._preBind();
  637. var effect = effectiveMaterial.getEffect();
  638. // Bind
  639. var fillMode = scene.forcePointsCloud ? BABYLON.Material.PointFillMode : (scene.forceWireframe ? BABYLON.Material.WireFrameFillMode : effectiveMaterial.fillMode);
  640. this._bind(subMesh, effect, fillMode);
  641. var world = this.getWorldMatrix();
  642. effectiveMaterial.bind(world, this);
  643. // Alpha mode
  644. if (enableAlphaMode) {
  645. engine.setAlphaMode(effectiveMaterial.alphaMode);
  646. }
  647. // Draw
  648. this._processRendering(subMesh, effect, fillMode, batch, hardwareInstancedRendering, function (isInstance, world) {
  649. if (isInstance) {
  650. effectiveMaterial.bindOnlyWorldMatrix(world);
  651. }
  652. });
  653. // Unbind
  654. effectiveMaterial.unbind();
  655. // Outline - step 2
  656. if (this.renderOutline && savedDepthWrite) {
  657. engine.setDepthWrite(true);
  658. engine.setColorWrite(false);
  659. scene.getOutlineRenderer().render(subMesh, batch);
  660. engine.setColorWrite(true);
  661. }
  662. // Overlay
  663. if (this.renderOverlay) {
  664. var currentMode = engine.getAlphaMode();
  665. engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
  666. scene.getOutlineRenderer().render(subMesh, batch, true);
  667. engine.setAlphaMode(currentMode);
  668. }
  669. for (callbackIndex = 0; callbackIndex < this._onAfterRenderCallbacks.length; callbackIndex++) {
  670. this._onAfterRenderCallbacks[callbackIndex](this);
  671. }
  672. };
  673. Mesh.prototype.getEmittedParticleSystems = function () {
  674. var results = new Array();
  675. for (var index = 0; index < this.getScene().particleSystems.length; index++) {
  676. var particleSystem = this.getScene().particleSystems[index];
  677. if (particleSystem.emitter === this) {
  678. results.push(particleSystem);
  679. }
  680. }
  681. return results;
  682. };
  683. Mesh.prototype.getHierarchyEmittedParticleSystems = function () {
  684. var results = new Array();
  685. var descendants = this.getDescendants();
  686. descendants.push(this);
  687. for (var index = 0; index < this.getScene().particleSystems.length; index++) {
  688. var particleSystem = this.getScene().particleSystems[index];
  689. if (descendants.indexOf(particleSystem.emitter) !== -1) {
  690. results.push(particleSystem);
  691. }
  692. }
  693. return results;
  694. };
  695. Mesh.prototype.getChildren = function () {
  696. var results = [];
  697. for (var index = 0; index < this.getScene().meshes.length; index++) {
  698. var mesh = this.getScene().meshes[index];
  699. if (mesh.parent === this) {
  700. results.push(mesh);
  701. }
  702. }
  703. return results;
  704. };
  705. Mesh.prototype._checkDelayState = function () {
  706. var _this = this;
  707. var that = this;
  708. var scene = this.getScene();
  709. if (this._geometry) {
  710. this._geometry.load(scene);
  711. }
  712. else if (that.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_NOTLOADED) {
  713. that.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADING;
  714. scene._addPendingData(that);
  715. var getBinaryData = (this.delayLoadingFile.indexOf(".babylonbinarymeshdata") !== -1);
  716. BABYLON.Tools.LoadFile(this.delayLoadingFile, function (data) {
  717. if (data instanceof ArrayBuffer) {
  718. _this._delayLoadingFunction(data, _this);
  719. }
  720. else {
  721. _this._delayLoadingFunction(JSON.parse(data), _this);
  722. }
  723. _this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADED;
  724. scene._removePendingData(_this);
  725. }, function () { }, scene.database, getBinaryData);
  726. }
  727. };
  728. Mesh.prototype.isInFrustum = function (frustumPlanes) {
  729. if (this.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_LOADING) {
  730. return false;
  731. }
  732. if (!_super.prototype.isInFrustum.call(this, frustumPlanes)) {
  733. return false;
  734. }
  735. this._checkDelayState();
  736. return true;
  737. };
  738. Mesh.prototype.setMaterialByID = function (id) {
  739. var materials = this.getScene().materials;
  740. var index;
  741. for (index = 0; index < materials.length; index++) {
  742. if (materials[index].id === id) {
  743. this.material = materials[index];
  744. return;
  745. }
  746. }
  747. // Multi
  748. var multiMaterials = this.getScene().multiMaterials;
  749. for (index = 0; index < multiMaterials.length; index++) {
  750. if (multiMaterials[index].id === id) {
  751. this.material = multiMaterials[index];
  752. return;
  753. }
  754. }
  755. };
  756. Mesh.prototype.getAnimatables = function () {
  757. var results = [];
  758. if (this.material) {
  759. results.push(this.material);
  760. }
  761. if (this.skeleton) {
  762. results.push(this.skeleton);
  763. }
  764. return results;
  765. };
  766. // Geometry
  767. Mesh.prototype.bakeTransformIntoVertices = function (transform) {
  768. // Position
  769. if (!this.isVerticesDataPresent(BABYLON.VertexBuffer.PositionKind)) {
  770. return;
  771. }
  772. this._resetPointsArrayCache();
  773. var data = this.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  774. var temp = [];
  775. var index;
  776. for (index = 0; index < data.length; index += 3) {
  777. BABYLON.Vector3.TransformCoordinates(BABYLON.Vector3.FromArray(data, index), transform).toArray(temp, index);
  778. }
  779. this.setVerticesData(BABYLON.VertexBuffer.PositionKind, temp, this.getVertexBuffer(BABYLON.VertexBuffer.PositionKind).isUpdatable());
  780. // Normals
  781. if (!this.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
  782. return;
  783. }
  784. data = this.getVerticesData(BABYLON.VertexBuffer.NormalKind);
  785. temp = [];
  786. for (index = 0; index < data.length; index += 3) {
  787. BABYLON.Vector3.TransformNormal(BABYLON.Vector3.FromArray(data, index), transform).normalize().toArray(temp, index);
  788. }
  789. this.setVerticesData(BABYLON.VertexBuffer.NormalKind, temp, this.getVertexBuffer(BABYLON.VertexBuffer.NormalKind).isUpdatable());
  790. // flip faces?
  791. if (transform.m[0] * transform.m[5] * transform.m[10] < 0) {
  792. this.flipFaces();
  793. }
  794. };
  795. // Will apply current transform to mesh and reset world matrix
  796. Mesh.prototype.bakeCurrentTransformIntoVertices = function () {
  797. this.bakeTransformIntoVertices(this.computeWorldMatrix(true));
  798. this.scaling.copyFromFloats(1, 1, 1);
  799. this.position.copyFromFloats(0, 0, 0);
  800. this.rotation.copyFromFloats(0, 0, 0);
  801. //only if quaternion is already set
  802. if (this.rotationQuaternion) {
  803. this.rotationQuaternion = BABYLON.Quaternion.Identity();
  804. }
  805. this._worldMatrix = BABYLON.Matrix.Identity();
  806. };
  807. // Cache
  808. Mesh.prototype._resetPointsArrayCache = function () {
  809. this._positions = null;
  810. };
  811. Mesh.prototype._generatePointsArray = function () {
  812. if (this._positions)
  813. return true;
  814. this._positions = [];
  815. var data = this.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  816. if (!data) {
  817. return false;
  818. }
  819. for (var index = 0; index < data.length; index += 3) {
  820. this._positions.push(BABYLON.Vector3.FromArray(data, index));
  821. }
  822. return true;
  823. };
  824. // Clone
  825. Mesh.prototype.clone = function (name, newParent, doNotCloneChildren) {
  826. return new Mesh(name, this.getScene(), newParent, this, doNotCloneChildren);
  827. };
  828. // Dispose
  829. Mesh.prototype.dispose = function (doNotRecurse) {
  830. if (this._geometry) {
  831. this._geometry.releaseForMesh(this, true);
  832. }
  833. // Instances
  834. if (this._worldMatricesInstancesBuffer) {
  835. this.getEngine().deleteInstancesBuffer(this._worldMatricesInstancesBuffer);
  836. this._worldMatricesInstancesBuffer = null;
  837. }
  838. while (this.instances.length) {
  839. this.instances[0].dispose();
  840. }
  841. _super.prototype.dispose.call(this, doNotRecurse);
  842. };
  843. // Geometric tools
  844. Mesh.prototype.applyDisplacementMap = function (url, minHeight, maxHeight, onSuccess) {
  845. var _this = this;
  846. var scene = this.getScene();
  847. var onload = function (img) {
  848. // Getting height map data
  849. var canvas = document.createElement("canvas");
  850. var context = canvas.getContext("2d");
  851. var heightMapWidth = img.width;
  852. var heightMapHeight = img.height;
  853. canvas.width = heightMapWidth;
  854. canvas.height = heightMapHeight;
  855. context.drawImage(img, 0, 0);
  856. // Create VertexData from map data
  857. //Cast is due to wrong definition in lib.d.ts from ts 1.3 - https://github.com/Microsoft/TypeScript/issues/949
  858. var buffer = context.getImageData(0, 0, heightMapWidth, heightMapHeight).data;
  859. _this.applyDisplacementMapFromBuffer(buffer, heightMapWidth, heightMapHeight, minHeight, maxHeight);
  860. //execute success callback, if set
  861. if (onSuccess) {
  862. onSuccess(_this);
  863. }
  864. };
  865. BABYLON.Tools.LoadImage(url, onload, function () { }, scene.database);
  866. };
  867. Mesh.prototype.applyDisplacementMapFromBuffer = function (buffer, heightMapWidth, heightMapHeight, minHeight, maxHeight) {
  868. if (!this.isVerticesDataPresent(BABYLON.VertexBuffer.PositionKind)
  869. || !this.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)
  870. || !this.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
  871. BABYLON.Tools.Warn("Cannot call applyDisplacementMap: Given mesh is not complete. Position, Normal or UV are missing");
  872. return;
  873. }
  874. var positions = this.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  875. var normals = this.getVerticesData(BABYLON.VertexBuffer.NormalKind);
  876. var uvs = this.getVerticesData(BABYLON.VertexBuffer.UVKind);
  877. var position = BABYLON.Vector3.Zero();
  878. var normal = BABYLON.Vector3.Zero();
  879. var uv = BABYLON.Vector2.Zero();
  880. for (var index = 0; index < positions.length; index += 3) {
  881. BABYLON.Vector3.FromArrayToRef(positions, index, position);
  882. BABYLON.Vector3.FromArrayToRef(normals, index, normal);
  883. BABYLON.Vector2.FromArrayToRef(uvs, (index / 3) * 2, uv);
  884. // Compute height
  885. var u = ((Math.abs(uv.x) * heightMapWidth) % heightMapWidth) | 0;
  886. var v = ((Math.abs(uv.y) * heightMapHeight) % heightMapHeight) | 0;
  887. var pos = (u + v * heightMapWidth) * 4;
  888. var r = buffer[pos] / 255.0;
  889. var g = buffer[pos + 1] / 255.0;
  890. var b = buffer[pos + 2] / 255.0;
  891. var gradient = r * 0.3 + g * 0.59 + b * 0.11;
  892. normal.normalize();
  893. normal.scaleInPlace(minHeight + (maxHeight - minHeight) * gradient);
  894. position = position.add(normal);
  895. position.toArray(positions, index);
  896. }
  897. BABYLON.VertexData.ComputeNormals(positions, this.getIndices(), normals);
  898. this.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positions);
  899. this.updateVerticesData(BABYLON.VertexBuffer.NormalKind, normals);
  900. };
  901. Mesh.prototype.convertToFlatShadedMesh = function () {
  902. /// <summary>Update normals and vertices to get a flat shading rendering.</summary>
  903. /// <summary>Warning: This may imply adding vertices to the mesh in order to get exactly 3 vertices per face</summary>
  904. var kinds = this.getVerticesDataKinds();
  905. var vbs = [];
  906. var data = [];
  907. var newdata = [];
  908. var updatableNormals = false;
  909. var kindIndex;
  910. var kind;
  911. for (kindIndex = 0; kindIndex < kinds.length; kindIndex++) {
  912. kind = kinds[kindIndex];
  913. var vertexBuffer = this.getVertexBuffer(kind);
  914. if (kind === BABYLON.VertexBuffer.NormalKind) {
  915. updatableNormals = vertexBuffer.isUpdatable();
  916. kinds.splice(kindIndex, 1);
  917. kindIndex--;
  918. continue;
  919. }
  920. vbs[kind] = vertexBuffer;
  921. data[kind] = vbs[kind].getData();
  922. newdata[kind] = [];
  923. }
  924. // Save previous submeshes
  925. var previousSubmeshes = this.subMeshes.slice(0);
  926. var indices = this.getIndices();
  927. var totalIndices = this.getTotalIndices();
  928. // Generating unique vertices per face
  929. var index;
  930. for (index = 0; index < totalIndices; index++) {
  931. var vertexIndex = indices[index];
  932. for (kindIndex = 0; kindIndex < kinds.length; kindIndex++) {
  933. kind = kinds[kindIndex];
  934. var stride = vbs[kind].getStrideSize();
  935. for (var offset = 0; offset < stride; offset++) {
  936. newdata[kind].push(data[kind][vertexIndex * stride + offset]);
  937. }
  938. }
  939. }
  940. // Updating faces & normal
  941. var normals = [];
  942. var positions = newdata[BABYLON.VertexBuffer.PositionKind];
  943. for (index = 0; index < totalIndices; index += 3) {
  944. indices[index] = index;
  945. indices[index + 1] = index + 1;
  946. indices[index + 2] = index + 2;
  947. var p1 = BABYLON.Vector3.FromArray(positions, index * 3);
  948. var p2 = BABYLON.Vector3.FromArray(positions, (index + 1) * 3);
  949. var p3 = BABYLON.Vector3.FromArray(positions, (index + 2) * 3);
  950. var p1p2 = p1.subtract(p2);
  951. var p3p2 = p3.subtract(p2);
  952. var normal = BABYLON.Vector3.Normalize(BABYLON.Vector3.Cross(p1p2, p3p2));
  953. // Store same normals for every vertex
  954. for (var localIndex = 0; localIndex < 3; localIndex++) {
  955. normals.push(normal.x);
  956. normals.push(normal.y);
  957. normals.push(normal.z);
  958. }
  959. }
  960. this.setIndices(indices);
  961. this.setVerticesData(BABYLON.VertexBuffer.NormalKind, normals, updatableNormals);
  962. // Updating vertex buffers
  963. for (kindIndex = 0; kindIndex < kinds.length; kindIndex++) {
  964. kind = kinds[kindIndex];
  965. this.setVerticesData(kind, newdata[kind], vbs[kind].isUpdatable());
  966. }
  967. // Updating submeshes
  968. this.releaseSubMeshes();
  969. for (var submeshIndex = 0; submeshIndex < previousSubmeshes.length; submeshIndex++) {
  970. var previousOne = previousSubmeshes[submeshIndex];
  971. var subMesh = new BABYLON.SubMesh(previousOne.materialIndex, previousOne.indexStart, previousOne.indexCount, previousOne.indexStart, previousOne.indexCount, this);
  972. }
  973. this.synchronizeInstances();
  974. };
  975. // will inverse faces orientations, and invert normals too if specified
  976. Mesh.prototype.flipFaces = function (flipNormals) {
  977. if (flipNormals === void 0) { flipNormals = false; }
  978. var vertex_data = BABYLON.VertexData.ExtractFromMesh(this);
  979. var i;
  980. if (flipNormals && this.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
  981. for (i = 0; i < vertex_data.normals.length; i++) {
  982. vertex_data.normals[i] *= -1;
  983. }
  984. }
  985. var temp;
  986. for (i = 0; i < vertex_data.indices.length; i += 3) {
  987. // reassign indices
  988. temp = vertex_data.indices[i + 1];
  989. vertex_data.indices[i + 1] = vertex_data.indices[i + 2];
  990. vertex_data.indices[i + 2] = temp;
  991. }
  992. vertex_data.applyToMesh(this);
  993. };
  994. // Instances
  995. Mesh.prototype.createInstance = function (name) {
  996. return new BABYLON.InstancedMesh(name, this);
  997. };
  998. Mesh.prototype.synchronizeInstances = function () {
  999. for (var instanceIndex = 0; instanceIndex < this.instances.length; instanceIndex++) {
  1000. var instance = this.instances[instanceIndex];
  1001. instance._syncSubMeshes();
  1002. }
  1003. };
  1004. /**
  1005. * Simplify the mesh according to the given array of settings.
  1006. * Function will return immediately and will simplify async.
  1007. * @param settings a collection of simplification settings.
  1008. * @param parallelProcessing should all levels calculate parallel or one after the other.
  1009. * @param type the type of simplification to run.
  1010. * @param successCallback optional success callback to be called after the simplification finished processing all settings.
  1011. */
  1012. Mesh.prototype.simplify = function (settings, parallelProcessing, simplificationType, successCallback) {
  1013. if (parallelProcessing === void 0) { parallelProcessing = true; }
  1014. if (simplificationType === void 0) { simplificationType = BABYLON.SimplificationType.QUADRATIC; }
  1015. this.getScene().simplificationQueue.addTask({
  1016. settings: settings,
  1017. parallelProcessing: parallelProcessing,
  1018. mesh: this,
  1019. simplificationType: simplificationType,
  1020. successCallback: successCallback
  1021. });
  1022. };
  1023. /**
  1024. * Optimization of the mesh's indices, in case a mesh has duplicated vertices.
  1025. * The function will only reorder the indices and will not remove unused vertices to avoid problems with submeshes.
  1026. * This should be used together with the simplification to avoid disappearing triangles.
  1027. * @param successCallback an optional success callback to be called after the optimization finished.
  1028. */
  1029. Mesh.prototype.optimizeIndices = function (successCallback) {
  1030. var _this = this;
  1031. var indices = this.getIndices();
  1032. var positions = this.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  1033. var vectorPositions = [];
  1034. for (var pos = 0; pos < positions.length; pos = pos + 3) {
  1035. vectorPositions.push(BABYLON.Vector3.FromArray(positions, pos));
  1036. }
  1037. var dupes = [];
  1038. BABYLON.AsyncLoop.SyncAsyncForLoop(vectorPositions.length, 40, function (iteration) {
  1039. var realPos = vectorPositions.length - 1 - iteration;
  1040. var testedPosition = vectorPositions[realPos];
  1041. for (var j = 0; j < realPos; ++j) {
  1042. var againstPosition = vectorPositions[j];
  1043. if (testedPosition.equals(againstPosition)) {
  1044. dupes[realPos] = j;
  1045. break;
  1046. }
  1047. }
  1048. }, function () {
  1049. for (var i = 0; i < indices.length; ++i) {
  1050. indices[i] = dupes[indices[i]] || indices[i];
  1051. }
  1052. //indices are now reordered
  1053. var originalSubMeshes = _this.subMeshes.slice(0);
  1054. _this.setIndices(indices);
  1055. _this.subMeshes = originalSubMeshes;
  1056. if (successCallback) {
  1057. successCallback(_this);
  1058. }
  1059. });
  1060. };
  1061. Mesh.CreateRibbon = function (name, options, closeArrayOrScene, closePath, offset, scene, updatable, sideOrientation, instance) {
  1062. if (sideOrientation === void 0) { sideOrientation = Mesh.DEFAULTSIDE; }
  1063. if (instance === void 0) { instance = null; }
  1064. var pathArray;
  1065. var closeArray;
  1066. if (Array.isArray(options)) {
  1067. pathArray = options;
  1068. closeArray = closeArrayOrScene;
  1069. if (!instance) {
  1070. options = {
  1071. pathArray: pathArray,
  1072. closeArray: closeArray,
  1073. closePath: closePath,
  1074. offset: offset,
  1075. updatable: updatable,
  1076. sideOrientation: sideOrientation
  1077. };
  1078. }
  1079. }
  1080. else {
  1081. scene = closeArrayOrScene;
  1082. pathArray = options.pathArray;
  1083. closeArray = options.closeArray;
  1084. closePath = options.closePath;
  1085. offset = options.offset;
  1086. sideOrientation = options.sideOrientation;
  1087. instance = options.instance;
  1088. updatable = options.updatable;
  1089. }
  1090. if (instance) {
  1091. // positionFunction : ribbon case
  1092. // only pathArray and sideOrientation parameters are taken into account for positions update
  1093. var positionFunction = function (positions) {
  1094. var minlg = pathArray[0].length;
  1095. var i = 0;
  1096. var ns = (instance.sideOrientation === Mesh.DOUBLESIDE) ? 2 : 1;
  1097. for (var si = 1; si <= ns; si++) {
  1098. for (var p = 0; p < pathArray.length; p++) {
  1099. var path = pathArray[p];
  1100. var l = path.length;
  1101. minlg = (minlg < l) ? minlg : l;
  1102. var j = 0;
  1103. while (j < minlg) {
  1104. positions[i] = path[j].x;
  1105. positions[i + 1] = path[j].y;
  1106. positions[i + 2] = path[j].z;
  1107. j++;
  1108. i += 3;
  1109. }
  1110. if (instance._closePath) {
  1111. positions[i] = path[0].x;
  1112. positions[i + 1] = path[0].y;
  1113. positions[i + 2] = path[0].z;
  1114. i += 3;
  1115. }
  1116. }
  1117. }
  1118. };
  1119. var positions = instance.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  1120. positionFunction(positions);
  1121. instance.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positions, false, false);
  1122. if (!(instance.areNormalsFrozen)) {
  1123. var indices = instance.getIndices();
  1124. var normals = instance.getVerticesData(BABYLON.VertexBuffer.NormalKind);
  1125. BABYLON.VertexData.ComputeNormals(positions, indices, normals);
  1126. if (instance._closePath) {
  1127. var indexFirst = 0;
  1128. var indexLast = 0;
  1129. for (var p = 0; p < pathArray.length; p++) {
  1130. indexFirst = instance._idx[p] * 3;
  1131. if (p + 1 < pathArray.length) {
  1132. indexLast = (instance._idx[p + 1] - 1) * 3;
  1133. }
  1134. else {
  1135. indexLast = normals.length - 3;
  1136. }
  1137. normals[indexFirst] = (normals[indexFirst] + normals[indexLast]) * 0.5;
  1138. normals[indexFirst + 1] = (normals[indexFirst + 1] + normals[indexLast + 1]) * 0.5;
  1139. normals[indexFirst + 2] = (normals[indexFirst + 2] + normals[indexLast + 2]) * 0.5;
  1140. normals[indexLast] = normals[indexFirst];
  1141. normals[indexLast + 1] = normals[indexFirst + 1];
  1142. normals[indexLast + 2] = normals[indexFirst + 2];
  1143. }
  1144. }
  1145. instance.updateVerticesData(BABYLON.VertexBuffer.NormalKind, normals, false, false);
  1146. }
  1147. return instance;
  1148. }
  1149. else {
  1150. var ribbon = new Mesh(name, scene);
  1151. ribbon.sideOrientation = sideOrientation;
  1152. var vertexData = BABYLON.VertexData.CreateRibbon(options);
  1153. if (closePath) {
  1154. ribbon._idx = vertexData._idx;
  1155. }
  1156. ribbon._closePath = closePath;
  1157. ribbon._closeArray = closeArray;
  1158. vertexData.applyToMesh(ribbon, updatable);
  1159. return ribbon;
  1160. }
  1161. };
  1162. Mesh.CreateDisc = function (name, options, tessellationOrScene, scene, updatable, sideOrientation) {
  1163. if (sideOrientation === void 0) { sideOrientation = Mesh.DEFAULTSIDE; }
  1164. if (tessellationOrScene instanceof BABYLON.Scene) {
  1165. scene = tessellationOrScene;
  1166. }
  1167. else {
  1168. var radius = options;
  1169. options = {
  1170. radius: radius,
  1171. tessellation: tessellationOrScene,
  1172. sideOrientation: sideOrientation
  1173. };
  1174. }
  1175. var disc = new Mesh(name, scene);
  1176. var vertexData = BABYLON.VertexData.CreateDisc(options);
  1177. vertexData.applyToMesh(disc, updatable || options.updatable);
  1178. return disc;
  1179. };
  1180. Mesh.CreateBox = function (name, size, scene, updatable, sideOrientation) {
  1181. var options = {
  1182. size: size,
  1183. sideOrientation: sideOrientation
  1184. };
  1185. var box = new Mesh(name, scene);
  1186. var vertexData = BABYLON.VertexData.CreateBox(options);
  1187. vertexData.applyToMesh(box, updatable);
  1188. return box;
  1189. };
  1190. Mesh.CreateSphere = function (name, options, diameterOrScene, scene, updatable, sideOrientation) {
  1191. if (sideOrientation === void 0) { sideOrientation = Mesh.DEFAULTSIDE; }
  1192. if (diameterOrScene instanceof BABYLON.Scene) {
  1193. scene = diameterOrScene;
  1194. updatable = options.updatable;
  1195. }
  1196. else {
  1197. var segments = options;
  1198. options = {
  1199. segments: segments,
  1200. diameterX: diameterOrScene,
  1201. diameterY: diameterOrScene,
  1202. diameterZ: diameterOrScene,
  1203. sideOrientation: sideOrientation
  1204. };
  1205. }
  1206. var sphere = new Mesh(name, scene);
  1207. var vertexData = BABYLON.VertexData.CreateSphere(options);
  1208. vertexData.applyToMesh(sphere, updatable);
  1209. return sphere;
  1210. };
  1211. Mesh.CreateCylinder = function (name, options, diameterTopOrScene, diameterBottom, tessellation, subdivisions, scene, updatable, sideOrientation) {
  1212. if (sideOrientation === void 0) { sideOrientation = Mesh.DEFAULTSIDE; }
  1213. if (diameterTopOrScene instanceof BABYLON.Scene) {
  1214. scene = diameterTopOrScene;
  1215. updatable = options.updatable;
  1216. }
  1217. else {
  1218. if (scene === undefined || !(scene instanceof BABYLON.Scene)) {
  1219. if (scene !== undefined) {
  1220. sideOrientation = updatable || Mesh.DEFAULTSIDE;
  1221. updatable = scene;
  1222. }
  1223. scene = subdivisions;
  1224. subdivisions = 1;
  1225. }
  1226. var height = options;
  1227. options = {
  1228. height: height,
  1229. diameterTop: diameterTopOrScene,
  1230. diameterBottom: diameterBottom,
  1231. tessellation: tessellation,
  1232. subdivisions: subdivisions,
  1233. sideOrientation: sideOrientation
  1234. };
  1235. }
  1236. var cylinder = new Mesh(name, scene);
  1237. var vertexData = BABYLON.VertexData.CreateCylinder(options);
  1238. vertexData.applyToMesh(cylinder, updatable);
  1239. return cylinder;
  1240. };
  1241. Mesh.CreateTorus = function (name, options, thicknessOrScene, tessellation, scene, updatable, sideOrientation) {
  1242. if (thicknessOrScene instanceof BABYLON.Scene) {
  1243. scene = thicknessOrScene;
  1244. updatable = options.updatable;
  1245. }
  1246. else {
  1247. var diameter = options;
  1248. options = {
  1249. diameter: diameter,
  1250. thickness: thicknessOrScene,
  1251. tessellation: tessellation,
  1252. sideOrientation: sideOrientation
  1253. };
  1254. }
  1255. var torus = new Mesh(name, scene);
  1256. var vertexData = BABYLON.VertexData.CreateTorus(options);
  1257. vertexData.applyToMesh(torus, updatable);
  1258. return torus;
  1259. };
  1260. Mesh.CreateTorusKnot = function (name, options, tubeOrScene, radialSegments, tubularSegments, p, q, scene, updatable, sideOrientation) {
  1261. if (tubeOrScene instanceof BABYLON.Scene) {
  1262. scene = tubeOrScene;
  1263. updatable = options.updatable;
  1264. }
  1265. else {
  1266. var radius = options;
  1267. options = {
  1268. radius: radius,
  1269. tube: tubeOrScene,
  1270. radialSegments: radialSegments,
  1271. tubularSegments: tubularSegments,
  1272. p: p,
  1273. q: q,
  1274. sideOrientation: sideOrientation
  1275. };
  1276. }
  1277. var torusKnot = new Mesh(name, scene);
  1278. var vertexData = BABYLON.VertexData.CreateTorusKnot(options);
  1279. vertexData.applyToMesh(torusKnot, updatable);
  1280. return torusKnot;
  1281. };
  1282. Mesh.CreateLines = function (name, options, scene, updatable, instance) {
  1283. var points;
  1284. if (Array.isArray(options)) {
  1285. points = options;
  1286. if (!instance) {
  1287. options = {
  1288. points: points
  1289. };
  1290. }
  1291. }
  1292. else {
  1293. instance = options.instance;
  1294. points = options.points;
  1295. }
  1296. if (instance) {
  1297. var positionFunction = function (positions) {
  1298. var i = 0;
  1299. for (var p = 0; p < points.length; p++) {
  1300. positions[i] = points[p].x;
  1301. positions[i + 1] = points[p].y;
  1302. positions[i + 2] = points[p].z;
  1303. i += 3;
  1304. }
  1305. };
  1306. instance.updateMeshPositions(positionFunction, false);
  1307. return instance;
  1308. }
  1309. // lines creation
  1310. var lines = new BABYLON.LinesMesh(name, scene);
  1311. var vertexData = BABYLON.VertexData.CreateLines(options);
  1312. vertexData.applyToMesh(lines, updatable || options.updatable);
  1313. return lines;
  1314. };
  1315. Mesh.CreateDashedLines = function (name, options, dashSizeOrScene, gapSize, dashNb, scene, updatable, instance) {
  1316. var points;
  1317. var dashSize;
  1318. if (Array.isArray(options)) {
  1319. points = options;
  1320. dashSize = dashSizeOrScene;
  1321. if (!instance) {
  1322. options = {
  1323. points: points,
  1324. dashSize: dashSize,
  1325. gapSize: gapSize,
  1326. dashNb: dashNb
  1327. };
  1328. }
  1329. }
  1330. else {
  1331. scene = dashSizeOrScene,
  1332. points = options.points;
  1333. instance = options.instance;
  1334. gapSize = options.gapSize;
  1335. dashNb = options.dashNb;
  1336. dashSize = options.dashSize;
  1337. }
  1338. if (instance) {
  1339. var positionFunction = function (positions) {
  1340. var curvect = BABYLON.Vector3.Zero();
  1341. var nbSeg = positions.length / 6;
  1342. var lg = 0;
  1343. var nb = 0;
  1344. var shft = 0;
  1345. var dashshft = 0;
  1346. var curshft = 0;
  1347. var p = 0;
  1348. var i = 0;
  1349. var j = 0;
  1350. for (i = 0; i < points.length - 1; i++) {
  1351. points[i + 1].subtractToRef(points[i], curvect);
  1352. lg += curvect.length();
  1353. }
  1354. shft = lg / nbSeg;
  1355. dashshft = instance.dashSize * shft / (instance.dashSize + instance.gapSize);
  1356. for (i = 0; i < points.length - 1; i++) {
  1357. points[i + 1].subtractToRef(points[i], curvect);
  1358. nb = Math.floor(curvect.length() / shft);
  1359. curvect.normalize();
  1360. j = 0;
  1361. while (j < nb && p < positions.length) {
  1362. curshft = shft * j;
  1363. positions[p] = points[i].x + curshft * curvect.x;
  1364. positions[p + 1] = points[i].y + curshft * curvect.y;
  1365. positions[p + 2] = points[i].z + curshft * curvect.z;
  1366. positions[p + 3] = points[i].x + (curshft + dashshft) * curvect.x;
  1367. positions[p + 4] = points[i].y + (curshft + dashshft) * curvect.y;
  1368. positions[p + 5] = points[i].z + (curshft + dashshft) * curvect.z;
  1369. p += 6;
  1370. j++;
  1371. }
  1372. }
  1373. while (p < positions.length) {
  1374. positions[p] = points[i].x;
  1375. positions[p + 1] = points[i].y;
  1376. positions[p + 2] = points[i].z;
  1377. p += 3;
  1378. }
  1379. };
  1380. instance.updateMeshPositions(positionFunction, false);
  1381. return instance;
  1382. }
  1383. // dashed lines creation
  1384. var dashedLines = new BABYLON.LinesMesh(name, scene);
  1385. var vertexData = BABYLON.VertexData.CreateDashedLines(options);
  1386. vertexData.applyToMesh(dashedLines, updatable || options.updatable);
  1387. dashedLines.dashSize = dashSize;
  1388. dashedLines.gapSize = gapSize;
  1389. return dashedLines;
  1390. };
  1391. Mesh.ExtrudeShape = function (name, options, pathOrScene, scale, rotation, cap, scene, updatable, sideOrientation, instance) {
  1392. if (sideOrientation === void 0) { sideOrientation = Mesh.DEFAULTSIDE; }
  1393. if (instance === void 0) { instance = null; }
  1394. var path;
  1395. var shape;
  1396. if (Array.isArray(options)) {
  1397. shape = options;
  1398. path = pathOrScene;
  1399. scale = scale || 1;
  1400. rotation = rotation || 0;
  1401. cap = (cap === 0) ? 0 : cap || Mesh.NO_CAP;
  1402. }
  1403. else {
  1404. scene = pathOrScene;
  1405. path = options.path;
  1406. shape = options.shape;
  1407. scale = options.scale || 1;
  1408. rotation = options.rotation || 0;
  1409. cap = (options.cap === 0) ? 0 : options.cap || Mesh.NO_CAP;
  1410. updatable = options.updatable;
  1411. sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || Mesh.DEFAULTSIDE;
  1412. instance = options.instance;
  1413. }
  1414. var extruded = Mesh._ExtrudeShapeGeneric(name, shape, path, scale, rotation, null, null, false, false, cap, false, scene, updatable, sideOrientation, instance);
  1415. return extruded;
  1416. };
  1417. Mesh.ExtrudeShapeCustom = function (name, options, pathOrScene, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, cap, scene, updatable, sideOrientation, instance) {
  1418. if (sideOrientation === void 0) { sideOrientation = Mesh.DEFAULTSIDE; }
  1419. if (instance === void 0) { instance = null; }
  1420. var path;
  1421. var shape;
  1422. if (Array.isArray(options)) {
  1423. shape = options;
  1424. path = pathOrScene;
  1425. ribbonCloseArray = ribbonCloseArray || false;
  1426. ribbonClosePath = ribbonClosePath || false;
  1427. cap = (cap === 0) ? 0 : cap || Mesh.NO_CAP;
  1428. }
  1429. else {
  1430. scene = pathOrScene;
  1431. path = options.path;
  1432. shape = options.shape;
  1433. scaleFunction = options.scaleFunction || (function (i, distance) { return 1; });
  1434. rotationFunction = options.rotationFunction || (function (i, distance) { return 0; });
  1435. ribbonCloseArray = options.ribbonCloseArray || false;
  1436. ribbonClosePath = options.ribbonClosePath || false;
  1437. cap = (options.cap === 0) ? 0 : options.cap || Mesh.NO_CAP;
  1438. updatable = options.updatable;
  1439. sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || Mesh.DEFAULTSIDE;
  1440. instance = options.instance;
  1441. }
  1442. var extrudedCustom = Mesh._ExtrudeShapeGeneric(name, shape, path, null, null, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, cap, true, scene, updatable, sideOrientation, instance);
  1443. return extrudedCustom;
  1444. };
  1445. Mesh._ExtrudeShapeGeneric = function (name, shape, curve, scale, rotation, scaleFunction, rotateFunction, rbCA, rbCP, cap, custom, scene, updtbl, side, instance) {
  1446. // extrusion geometry
  1447. var extrusionPathArray = function (shape, curve, path3D, shapePaths, scale, rotation, scaleFunction, rotateFunction, cap, custom) {
  1448. var tangents = path3D.getTangents();
  1449. var normals = path3D.getNormals();
  1450. var binormals = path3D.getBinormals();
  1451. var distances = path3D.getDistances();
  1452. var angle = 0;
  1453. var returnScale = function (i, distance) { return scale; };
  1454. var returnRotation = function (i, distance) { return rotation; };
  1455. var rotate = custom ? rotateFunction : returnRotation;
  1456. var scl = custom ? scaleFunction : returnScale;
  1457. var index = (cap === Mesh.NO_CAP || cap === Mesh.CAP_END) ? 0 : 2;
  1458. var rotationMatrix = BABYLON.Matrix.Zero();
  1459. for (var i = 0; i < curve.length; i++) {
  1460. var shapePath = new Array();
  1461. var angleStep = rotate(i, distances[i]);
  1462. var scaleRatio = scl(i, distances[i]);
  1463. for (var p = 0; p < shape.length; p++) {
  1464. BABYLON.Matrix.RotationAxisToRef(tangents[i], angle, rotationMatrix);
  1465. var planed = ((tangents[i].scale(shape[p].z)).add(normals[i].scale(shape[p].x)).add(binormals[i].scale(shape[p].y)));
  1466. var rotated = BABYLON.Vector3.TransformCoordinates(planed, rotationMatrix).scaleInPlace(scaleRatio).add(curve[i]);
  1467. shapePath.push(rotated);
  1468. }
  1469. shapePaths[index] = shapePath;
  1470. angle += angleStep;
  1471. index++;
  1472. }
  1473. // cap
  1474. var capPath = function (shapePath) {
  1475. var pointCap = Array();
  1476. var barycenter = BABYLON.Vector3.Zero();
  1477. var i;
  1478. for (i = 0; i < shapePath.length; i++) {
  1479. barycenter.addInPlace(shapePath[i]);
  1480. }
  1481. barycenter.scaleInPlace(1 / shapePath.length);
  1482. for (i = 0; i < shapePath.length; i++) {
  1483. pointCap.push(barycenter);
  1484. }
  1485. return pointCap;
  1486. };
  1487. switch (cap) {
  1488. case Mesh.NO_CAP:
  1489. break;
  1490. case Mesh.CAP_START:
  1491. shapePaths[0] = capPath(shapePaths[2]);
  1492. shapePaths[1] = shapePaths[2].slice(0);
  1493. break;
  1494. case Mesh.CAP_END:
  1495. shapePaths[index] = shapePaths[index - 1];
  1496. shapePaths[index + 1] = capPath(shapePaths[index - 1]);
  1497. break;
  1498. case Mesh.CAP_ALL:
  1499. shapePaths[0] = capPath(shapePaths[2]);
  1500. shapePaths[1] = shapePaths[2].slice(0);
  1501. shapePaths[index] = shapePaths[index - 1];
  1502. shapePaths[index + 1] = capPath(shapePaths[index - 1]);
  1503. break;
  1504. default:
  1505. break;
  1506. }
  1507. return shapePaths;
  1508. };
  1509. var path3D;
  1510. var pathArray;
  1511. if (instance) {
  1512. path3D = (instance.path3D).update(curve);
  1513. pathArray = extrusionPathArray(shape, curve, instance.path3D, instance.pathArray, scale, rotation, scaleFunction, rotateFunction, instance.cap, custom);
  1514. instance = Mesh.CreateRibbon(null, pathArray, null, null, null, null, null, null, instance);
  1515. return instance;
  1516. }
  1517. // extruded shape creation
  1518. path3D = new BABYLON.Path3D(curve);
  1519. var newShapePaths = new Array();
  1520. cap = (cap < 0 || cap > 3) ? 0 : cap;
  1521. pathArray = extrusionPathArray(shape, curve, path3D, newShapePaths, scale, rotation, scaleFunction, rotateFunction, cap, custom);
  1522. var extrudedGeneric = Mesh.CreateRibbon(name, pathArray, rbCA, rbCP, 0, scene, updtbl, side);
  1523. extrudedGeneric.pathArray = pathArray;
  1524. extrudedGeneric.path3D = path3D;
  1525. extrudedGeneric.cap = cap;
  1526. return extrudedGeneric;
  1527. };
  1528. Mesh.CreateLathe = function (name, options, radiusOrScene, tessellation, scene, updatable, sideOrientation) {
  1529. if (sideOrientation === void 0) { sideOrientation = Mesh.DEFAULTSIDE; }
  1530. var shape;
  1531. var radius;
  1532. var arc = (options.arc <= 0) ? 1.0 : options.arc || 1.0;
  1533. var closed = (options.closed === undefined) ? true : options.closed;
  1534. if (Array.isArray(options)) {
  1535. shape = options;
  1536. radius = radiusOrScene || 1;
  1537. tessellation = tessellation || 64;
  1538. }
  1539. else {
  1540. scene = radiusOrScene;
  1541. shape = options.shape;
  1542. radius = options.radius || 1;
  1543. tessellation = options.tessellation || 64;
  1544. updatable = options.updatable;
  1545. sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || Mesh.DEFAULTSIDE;
  1546. }
  1547. var pi2 = Math.PI * 2;
  1548. var shapeLathe = new Array();
  1549. // first rotatable point
  1550. var i = 0;
  1551. while (shape[i].x === 0) {
  1552. i++;
  1553. }
  1554. var pt = shape[i];
  1555. for (i = 0; i < shape.length; i++) {
  1556. shapeLathe.push(shape[i].subtract(pt));
  1557. }
  1558. // circle path
  1559. var step = pi2 / tessellation * arc;
  1560. var rotated;
  1561. var path = new Array();
  1562. ;
  1563. for (i = 0; i <= tessellation; i++) {
  1564. rotated = new BABYLON.Vector3(Math.cos(i * step) * radius, 0, Math.sin(i * step) * radius);
  1565. path.push(rotated);
  1566. }
  1567. if (closed) {
  1568. path.push(path[0]);
  1569. }
  1570. // extrusion
  1571. var scaleFunction = function () { return 1; };
  1572. var rotateFunction = function () { return 0; };
  1573. var lathe = Mesh.ExtrudeShapeCustom(name, shapeLathe, path, scaleFunction, rotateFunction, closed, false, Mesh.NO_CAP, scene, updatable, sideOrientation);
  1574. return lathe;
  1575. };
  1576. Mesh.CreatePlane = function (name, options, scene, updatable, sideOrientation) {
  1577. if (sideOrientation === void 0) { sideOrientation = Mesh.DEFAULTSIDE; }
  1578. if (typeof options === 'number') {
  1579. var size = options;
  1580. options = {
  1581. size: size,
  1582. width: size,
  1583. height: size,
  1584. sideOrientation: sideOrientation
  1585. };
  1586. }
  1587. var plane = new Mesh(name, scene);
  1588. var vertexData = BABYLON.VertexData.CreatePlane(options);
  1589. vertexData.applyToMesh(plane, updatable || options.updatable);
  1590. return plane;
  1591. };
  1592. Mesh.CreateGround = function (name, options, heightOrScene, subdivisions, scene, updatable) {
  1593. if (heightOrScene instanceof BABYLON.Scene) {
  1594. scene = heightOrScene;
  1595. updatable = options.updatable;
  1596. }
  1597. else {
  1598. var width = options;
  1599. options = {
  1600. width: width,
  1601. height: heightOrScene,
  1602. subdivisions: subdivisions
  1603. };
  1604. }
  1605. var ground = new BABYLON.GroundMesh(name, scene);
  1606. ground._setReady(false);
  1607. ground._subdivisions = options.subdivisions || 1;
  1608. var vertexData = BABYLON.VertexData.CreateGround(options);
  1609. vertexData.applyToMesh(ground, updatable || options.updatable);
  1610. ground._setReady(true);
  1611. return ground;
  1612. };
  1613. Mesh.CreateTiledGround = function (name, options, zminOrScene, xmax, zmax, subdivisions, precision, scene, updatable) {
  1614. var xmin;
  1615. var zmin;
  1616. if (typeof options === 'number') {
  1617. xmin = options || -1;
  1618. zmin = zminOrScene || -1;
  1619. xmax = xmax || 1;
  1620. zmax = zmax || 1;
  1621. subdivisions = subdivisions || { w: 6, h: 6 };
  1622. precision = precision || { w: 2, h: 2 };
  1623. }
  1624. else {
  1625. scene = zminOrScene;
  1626. xmin = options.xmin || -1;
  1627. zmin = options.zmin || -1;
  1628. xmax = options.xmax || 1;
  1629. zmax = options.zmax || 1;
  1630. subdivisions = options.subdivisions || { w: 6, h: 6 };
  1631. precision = options.precision || { w: 2, h: 2 };
  1632. }
  1633. var tiledGround = new Mesh(name, scene);
  1634. var vertexData = BABYLON.VertexData.CreateTiledGround({ xmin: xmin, zmin: zmin, xmax: xmax, zmax: zmax, subdivisions: subdivisions, precision: precision });
  1635. vertexData.applyToMesh(tiledGround, updatable);
  1636. return tiledGround;
  1637. };
  1638. Mesh.CreateGroundFromHeightMap = function (name, url, widthOrOptions, heightorScene, subdivisions, minHeight, maxHeight, scene, updatable, onReady) {
  1639. var width;
  1640. var height;
  1641. if (typeof widthOrOptions === "number") {
  1642. width = widthOrOptions;
  1643. height = heightorScene;
  1644. }
  1645. else {
  1646. width = widthOrOptions.width || 10;
  1647. height = widthOrOptions.height || 10;
  1648. subdivisions = widthOrOptions.subdivisions || 1;
  1649. minHeight = widthOrOptions.minHeight;
  1650. maxHeight = widthOrOptions.maxHeight || 10;
  1651. updatable = widthOrOptions.updatable;
  1652. onReady = widthOrOptions.onReady;
  1653. scene = heightorScene;
  1654. }
  1655. var ground = new BABYLON.GroundMesh(name, scene);
  1656. ground._subdivisions = subdivisions;
  1657. ground._setReady(false);
  1658. var onload = function (img) {
  1659. // Getting height map data
  1660. var canvas = document.createElement("canvas");
  1661. var context = canvas.getContext("2d");
  1662. var bufferWidth = img.width;
  1663. var bufferHeight = img.height;
  1664. canvas.width = bufferWidth;
  1665. canvas.height = bufferHeight;
  1666. context.drawImage(img, 0, 0);
  1667. // Create VertexData from map data
  1668. // Cast is due to wrong definition in lib.d.ts from ts 1.3 - https://github.com/Microsoft/TypeScript/issues/949
  1669. var buffer = context.getImageData(0, 0, bufferWidth, bufferHeight).data;
  1670. var vertexData = BABYLON.VertexData.CreateGroundFromHeightMap({
  1671. width: width, height: height,
  1672. subdivisions: subdivisions,
  1673. minHeight: minHeight, maxHeight: maxHeight,
  1674. buffer: buffer, bufferWidth: bufferWidth, bufferHeight: bufferHeight
  1675. });
  1676. vertexData.applyToMesh(ground, updatable);
  1677. ground._setReady(true);
  1678. //execute ready callback, if set
  1679. if (onReady) {
  1680. onReady(ground);
  1681. }
  1682. };
  1683. BABYLON.Tools.LoadImage(url, onload, function () { }, scene.database);
  1684. return ground;
  1685. };
  1686. Mesh.CreateTube = function (name, options, radiusOrScene, tessellation, radiusFunction, cap, scene, updatable, sideOrientation, instance) {
  1687. if (sideOrientation === void 0) { sideOrientation = Mesh.DEFAULTSIDE; }
  1688. if (instance === void 0) { instance = null; }
  1689. var path;
  1690. var radius;
  1691. var arc = (options.arc <= 0) ? 1.0 : options.arc || 1.0;
  1692. ;
  1693. if (Array.isArray(options)) {
  1694. path = options;
  1695. radius = radiusOrScene;
  1696. }
  1697. else {
  1698. scene = radiusOrScene;
  1699. path = options.path;
  1700. radius = options.radius || 1;
  1701. tessellation = options.tessellation || 64;
  1702. radiusFunction = options.radiusFunction;
  1703. cap = options.cap || Mesh.NO_CAP,
  1704. updatable = options.updatable;
  1705. sideOrientation = options.sideOrientation || Mesh.DEFAULTSIDE,
  1706. instance = options.instance;
  1707. }
  1708. // tube geometry
  1709. var tubePathArray = function (path, path3D, circlePaths, radius, tessellation, radiusFunction, cap, arc) {
  1710. var tangents = path3D.getTangents();
  1711. var normals = path3D.getNormals();
  1712. var distances = path3D.getDistances();
  1713. var pi2 = Math.PI * 2;
  1714. var step = pi2 / tessellation * arc;
  1715. var returnRadius = function (i, distance) { return radius; };
  1716. var radiusFunctionFinal = radiusFunction || returnRadius;
  1717. var circlePath;
  1718. var rad;
  1719. var normal;
  1720. var rotated;
  1721. var rotationMatrix = BABYLON.Matrix.Zero();
  1722. var index = (cap === Mesh._NO_CAP || cap === Mesh.CAP_END) ? 0 : 2;
  1723. for (var i = 0; i < path.length; i++) {
  1724. rad = radiusFunctionFinal(i, distances[i]); // current radius
  1725. circlePath = Array(); // current circle array
  1726. normal = normals[i]; // current normal
  1727. for (var t = 0; t < tessellation; t++) {
  1728. BABYLON.Matrix.RotationAxisToRef(tangents[i], step * t, rotationMatrix);
  1729. rotated = BABYLON.Vector3.TransformCoordinates(normal, rotationMatrix).scaleInPlace(rad).add(path[i]);
  1730. circlePath.push(rotated);
  1731. }
  1732. circlePaths[index] = circlePath;
  1733. index++;
  1734. }
  1735. // cap
  1736. var capPath = function (nbPoints, pathIndex) {
  1737. var pointCap = Array();
  1738. for (var i = 0; i < nbPoints; i++) {
  1739. pointCap.push(path[pathIndex]);
  1740. }
  1741. return pointCap;
  1742. };
  1743. switch (cap) {
  1744. case Mesh.NO_CAP:
  1745. break;
  1746. case Mesh.CAP_START:
  1747. circlePaths[0] = capPath(tessellation, 0);
  1748. circlePaths[1] = circlePaths[2].slice(0);
  1749. break;
  1750. case Mesh.CAP_END:
  1751. circlePaths[index] = circlePaths[index - 1].slice(0);
  1752. circlePaths[index + 1] = capPath(tessellation, path.length - 1);
  1753. break;
  1754. case Mesh.CAP_ALL:
  1755. circlePaths[0] = capPath(tessellation, 0);
  1756. circlePaths[1] = circlePaths[2].slice(0);
  1757. circlePaths[index] = circlePaths[index - 1].slice(0);
  1758. circlePaths[index + 1] = capPath(tessellation, path.length - 1);
  1759. break;
  1760. default:
  1761. break;
  1762. }
  1763. return circlePaths;
  1764. };
  1765. var path3D;
  1766. var pathArray;
  1767. if (instance) {
  1768. arc = arc || instance.arc;
  1769. path3D = (instance.path3D).update(path);
  1770. pathArray = tubePathArray(path, path3D, instance.pathArray, radius, instance.tessellation, radiusFunction, instance.cap, arc);
  1771. instance = Mesh.CreateRibbon(null, { pathArray: pathArray, instance: instance });
  1772. instance.path3D = path3D;
  1773. instance.pathArray = pathArray;
  1774. instance.arc = arc;
  1775. return instance;
  1776. }
  1777. // tube creation
  1778. path3D = new BABYLON.Path3D(path);
  1779. var newPathArray = new Array();
  1780. cap = (cap < 0 || cap > 3) ? 0 : cap;
  1781. pathArray = tubePathArray(path, path3D, newPathArray, radius, tessellation, radiusFunction, cap, arc);
  1782. var tube = Mesh.CreateRibbon(name, { pathArray: pathArray, closePath: true, closeArray: false, updatable: updatable, sideOrientation: sideOrientation }, scene);
  1783. tube.pathArray = pathArray;
  1784. tube.path3D = path3D;
  1785. tube.tessellation = tessellation;
  1786. tube.cap = cap;
  1787. tube.arc = arc;
  1788. return tube;
  1789. };
  1790. Mesh.CreatePolyhedron = function (name, options, scene) {
  1791. var polyhedron = new Mesh(name, scene);
  1792. var vertexData = BABYLON.VertexData.CreatePolyhedron(options);
  1793. vertexData.applyToMesh(polyhedron, options.updatable);
  1794. return polyhedron;
  1795. };
  1796. Mesh.CreateDecal = function (name, sourceMesh, positionOrOptions, normal, size, angle) {
  1797. if (angle === void 0) { angle = 0; }
  1798. var indices = sourceMesh.getIndices();
  1799. var positions = sourceMesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  1800. var normals = sourceMesh.getVerticesData(BABYLON.VertexBuffer.NormalKind);
  1801. var position;
  1802. if (positionOrOptions instanceof BABYLON.Vector3) {
  1803. position = positionOrOptions;
  1804. }
  1805. else {
  1806. position = positionOrOptions.position || BABYLON.Vector3.Zero();
  1807. normal = positionOrOptions.normal || BABYLON.Vector3.Up();
  1808. size = positionOrOptions.size || new BABYLON.Vector3(1, 1, 1);
  1809. angle = positionOrOptions.angle;
  1810. }
  1811. // Getting correct rotation
  1812. if (!normal) {
  1813. var target = new BABYLON.Vector3(0, 0, 1);
  1814. var camera = sourceMesh.getScene().activeCamera;
  1815. var cameraWorldTarget = BABYLON.Vector3.TransformCoordinates(target, camera.getWorldMatrix());
  1816. normal = camera.globalPosition.subtract(cameraWorldTarget);
  1817. }
  1818. var yaw = -Math.atan2(normal.z, normal.x) - Math.PI / 2;
  1819. var len = Math.sqrt(normal.x * normal.x + normal.z * normal.z);
  1820. var pitch = Math.atan2(normal.y, len);
  1821. // Matrix
  1822. var decalWorldMatrix = BABYLON.Matrix.RotationYawPitchRoll(yaw, pitch, angle).multiply(BABYLON.Matrix.Translation(position.x, position.y, position.z));
  1823. var inverseDecalWorldMatrix = BABYLON.Matrix.Invert(decalWorldMatrix);
  1824. var meshWorldMatrix = sourceMesh.getWorldMatrix();
  1825. var transformMatrix = meshWorldMatrix.multiply(inverseDecalWorldMatrix);
  1826. var vertexData = new BABYLON.VertexData();
  1827. vertexData.indices = [];
  1828. vertexData.positions = [];
  1829. vertexData.normals = [];
  1830. vertexData.uvs = [];
  1831. var currentVertexDataIndex = 0;
  1832. var extractDecalVector3 = function (indexId) {
  1833. var vertexId = indices[indexId];
  1834. var result = new BABYLON.PositionNormalVertex();
  1835. result.position = new BABYLON.Vector3(positions[vertexId * 3], positions[vertexId * 3 + 1], positions[vertexId * 3 + 2]);
  1836. // Send vector to decal local world
  1837. result.position = BABYLON.Vector3.TransformCoordinates(result.position, transformMatrix);
  1838. // Get normal
  1839. result.normal = new BABYLON.Vector3(normals[vertexId * 3], normals[vertexId * 3 + 1], normals[vertexId * 3 + 2]);
  1840. return result;
  1841. }; // Inspired by https://github.com/mrdoob/three.js/blob/eee231960882f6f3b6113405f524956145148146/examples/js/geometries/DecalGeometry.js
  1842. var clip = function (vertices, axis) {
  1843. if (vertices.length === 0) {
  1844. return vertices;
  1845. }
  1846. var clipSize = 0.5 * Math.abs(BABYLON.Vector3.Dot(size, axis));
  1847. var clipVertices = function (v0, v1) {
  1848. var clipFactor = BABYLON.Vector3.GetClipFactor(v0.position, v1.position, axis, clipSize);
  1849. return new BABYLON.PositionNormalVertex(BABYLON.Vector3.Lerp(v0.position, v1.position, clipFactor), BABYLON.Vector3.Lerp(v0.normal, v1.normal, clipFactor));
  1850. };
  1851. var result = new Array();
  1852. for (var index = 0; index < vertices.length; index += 3) {
  1853. var v1Out;
  1854. var v2Out;
  1855. var v3Out;
  1856. var total = 0;
  1857. var nV1, nV2, nV3, nV4;
  1858. var d1 = BABYLON.Vector3.Dot(vertices[index].position, axis) - clipSize;
  1859. var d2 = BABYLON.Vector3.Dot(vertices[index + 1].position, axis) - clipSize;
  1860. var d3 = BABYLON.Vector3.Dot(vertices[index + 2].position, axis) - clipSize;
  1861. v1Out = d1 > 0;
  1862. v2Out = d2 > 0;
  1863. v3Out = d3 > 0;
  1864. total = (v1Out ? 1 : 0) + (v2Out ? 1 : 0) + (v3Out ? 1 : 0);
  1865. switch (total) {
  1866. case 0:
  1867. result.push(vertices[index]);
  1868. result.push(vertices[index + 1]);
  1869. result.push(vertices[index + 2]);
  1870. break;
  1871. case 1:
  1872. if (v1Out) {
  1873. nV1 = vertices[index + 1];
  1874. nV2 = vertices[index + 2];
  1875. nV3 = clipVertices(vertices[index], nV1);
  1876. nV4 = clipVertices(vertices[index], nV2);
  1877. }
  1878. if (v2Out) {
  1879. nV1 = vertices[index];
  1880. nV2 = vertices[index + 2];
  1881. nV3 = clipVertices(vertices[index + 1], nV1);
  1882. nV4 = clipVertices(vertices[index + 1], nV2);
  1883. result.push(nV3);
  1884. result.push(nV2.clone());
  1885. result.push(nV1.clone());
  1886. result.push(nV2.clone());
  1887. result.push(nV3.clone());
  1888. result.push(nV4);
  1889. break;
  1890. }
  1891. if (v3Out) {
  1892. nV1 = vertices[index];
  1893. nV2 = vertices[index + 1];
  1894. nV3 = clipVertices(vertices[index + 2], nV1);
  1895. nV4 = clipVertices(vertices[index + 2], nV2);
  1896. }
  1897. result.push(nV1.clone());
  1898. result.push(nV2.clone());
  1899. result.push(nV3);
  1900. result.push(nV4);
  1901. result.push(nV3.clone());
  1902. result.push(nV2.clone());
  1903. break;
  1904. case 2:
  1905. if (!v1Out) {
  1906. nV1 = vertices[index].clone();
  1907. nV2 = clipVertices(nV1, vertices[index + 1]);
  1908. nV3 = clipVertices(nV1, vertices[index + 2]);
  1909. result.push(nV1);
  1910. result.push(nV2);
  1911. result.push(nV3);
  1912. }
  1913. if (!v2Out) {
  1914. nV1 = vertices[index + 1].clone();
  1915. nV2 = clipVertices(nV1, vertices[index + 2]);
  1916. nV3 = clipVertices(nV1, vertices[index]);
  1917. result.push(nV1);
  1918. result.push(nV2);
  1919. result.push(nV3);
  1920. }
  1921. if (!v3Out) {
  1922. nV1 = vertices[index + 2].clone();
  1923. nV2 = clipVertices(nV1, vertices[index]);
  1924. nV3 = clipVertices(nV1, vertices[index + 1]);
  1925. result.push(nV1);
  1926. result.push(nV2);
  1927. result.push(nV3);
  1928. }
  1929. break;
  1930. case 3:
  1931. break;
  1932. }
  1933. }
  1934. return result;
  1935. };
  1936. for (var index = 0; index < indices.length; index += 3) {
  1937. var faceVertices = new Array();
  1938. faceVertices.push(extractDecalVector3(index));
  1939. faceVertices.push(extractDecalVector3(index + 1));
  1940. faceVertices.push(extractDecalVector3(index + 2));
  1941. // Clip
  1942. faceVertices = clip(faceVertices, new BABYLON.Vector3(1, 0, 0));
  1943. faceVertices = clip(faceVertices, new BABYLON.Vector3(-1, 0, 0));
  1944. faceVertices = clip(faceVertices, new BABYLON.Vector3(0, 1, 0));
  1945. faceVertices = clip(faceVertices, new BABYLON.Vector3(0, -1, 0));
  1946. faceVertices = clip(faceVertices, new BABYLON.Vector3(0, 0, 1));
  1947. faceVertices = clip(faceVertices, new BABYLON.Vector3(0, 0, -1));
  1948. if (faceVertices.length === 0) {
  1949. continue;
  1950. }
  1951. // Add UVs and get back to world
  1952. for (var vIndex = 0; vIndex < faceVertices.length; vIndex++) {
  1953. var vertex = faceVertices[vIndex];
  1954. vertexData.indices.push(currentVertexDataIndex);
  1955. vertex.position.toArray(vertexData.positions, currentVertexDataIndex * 3);
  1956. vertex.normal.toArray(vertexData.normals, currentVertexDataIndex * 3);
  1957. vertexData.uvs.push(0.5 + vertex.position.x / size.x);
  1958. vertexData.uvs.push(0.5 + vertex.position.y / size.y);
  1959. currentVertexDataIndex++;
  1960. }
  1961. }
  1962. // Return mesh
  1963. var decal = new Mesh(name, sourceMesh.getScene());
  1964. vertexData.applyToMesh(decal);
  1965. decal.position = position.clone();
  1966. decal.rotation = new BABYLON.Vector3(pitch, yaw, angle);
  1967. return decal;
  1968. };
  1969. // Skeletons
  1970. /**
  1971. * @returns original positions used for CPU skinning. Useful for integrating Morphing with skeletons in same mesh.
  1972. */
  1973. Mesh.prototype.setPositionsForCPUSkinning = function () {
  1974. var source;
  1975. if (!this._sourcePositions) {
  1976. source = this.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  1977. this._sourcePositions = new Float32Array(source);
  1978. if (!this.getVertexBuffer(BABYLON.VertexBuffer.PositionKind).isUpdatable()) {
  1979. this.setVerticesData(BABYLON.VertexBuffer.PositionKind, source, true);
  1980. }
  1981. }
  1982. return this._sourcePositions;
  1983. };
  1984. /**
  1985. * @returns original normals used for CPU skinning. Useful for integrating Morphing with skeletons in same mesh.
  1986. */
  1987. Mesh.prototype.setNormalsForCPUSkinning = function () {
  1988. var source;
  1989. if (!this._sourceNormals) {
  1990. source = this.getVerticesData(BABYLON.VertexBuffer.NormalKind);
  1991. this._sourceNormals = new Float32Array(source);
  1992. if (!this.getVertexBuffer(BABYLON.VertexBuffer.NormalKind).isUpdatable()) {
  1993. this.setVerticesData(BABYLON.VertexBuffer.NormalKind, source, true);
  1994. }
  1995. }
  1996. return this._sourceNormals;
  1997. };
  1998. /**
  1999. * Update the vertex buffers by applying transformation from the bones
  2000. * @param {skeleton} skeleton to apply
  2001. */
  2002. Mesh.prototype.applySkeleton = function (skeleton) {
  2003. if (!this.isVerticesDataPresent(BABYLON.VertexBuffer.PositionKind)) {
  2004. return this;
  2005. }
  2006. if (!this.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
  2007. return this;
  2008. }
  2009. if (!this.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)) {
  2010. return this;
  2011. }
  2012. if (!this.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
  2013. return this;
  2014. }
  2015. if (!this._sourcePositions) {
  2016. this.setPositionsForCPUSkinning();
  2017. }
  2018. if (!this._sourceNormals) {
  2019. this.setNormalsForCPUSkinning();
  2020. }
  2021. // positionsData checks for not being Float32Array will only pass at most once
  2022. var positionsData = this.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  2023. if (!(positionsData instanceof Float32Array)) {
  2024. positionsData = new Float32Array(positionsData);
  2025. }
  2026. // normalsData checks for not being Float32Array will only pass at most once
  2027. var normalsData = this.getVerticesData(BABYLON.VertexBuffer.NormalKind);
  2028. if (!(normalsData instanceof Float32Array)) {
  2029. normalsData = new Float32Array(normalsData);
  2030. }
  2031. var matricesIndicesData = this.getVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind);
  2032. var matricesWeightsData = this.getVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind);
  2033. var skeletonMatrices = skeleton.getTransformMatrices();
  2034. var tempVector3 = BABYLON.Vector3.Zero();
  2035. var finalMatrix = new BABYLON.Matrix();
  2036. var tempMatrix = new BABYLON.Matrix();
  2037. for (var index = 0; index < positionsData.length; index += 3) {
  2038. var index4 = (index / 3) * 4;
  2039. var matricesWeight0 = matricesWeightsData[index4];
  2040. var matricesWeight1 = matricesWeightsData[index4 + 1];
  2041. var matricesWeight2 = matricesWeightsData[index4 + 2];
  2042. var matricesWeight3 = matricesWeightsData[index4 + 3];
  2043. if (matricesWeight0 > 0) {
  2044. BABYLON.Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesData[index4] * 16, matricesWeight0, tempMatrix);
  2045. finalMatrix.addToSelf(tempMatrix);
  2046. }
  2047. if (matricesWeight1 > 0) {
  2048. BABYLON.Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesData[index4 + 1] * 16, matricesWeight1, tempMatrix);
  2049. finalMatrix.addToSelf(tempMatrix);
  2050. }
  2051. if (matricesWeight2 > 0) {
  2052. BABYLON.Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesData[index4 + 2] * 16, matricesWeight2, tempMatrix);
  2053. finalMatrix.addToSelf(tempMatrix);
  2054. }
  2055. if (matricesWeight3 > 0) {
  2056. BABYLON.Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesData[index4 + 3] * 16, matricesWeight3, tempMatrix);
  2057. finalMatrix.addToSelf(tempMatrix);
  2058. }
  2059. BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(this._sourcePositions[index], this._sourcePositions[index + 1], this._sourcePositions[index + 2], finalMatrix, tempVector3);
  2060. tempVector3.toArray(positionsData, index);
  2061. BABYLON.Vector3.TransformNormalFromFloatsToRef(this._sourceNormals[index], this._sourceNormals[index + 1], this._sourceNormals[index + 2], finalMatrix, tempVector3);
  2062. tempVector3.toArray(normalsData, index);
  2063. finalMatrix.reset();
  2064. }
  2065. this.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positionsData);
  2066. this.updateVerticesData(BABYLON.VertexBuffer.NormalKind, normalsData);
  2067. return this;
  2068. };
  2069. // Tools
  2070. Mesh.MinMax = function (meshes) {
  2071. var minVector = null;
  2072. var maxVector = null;
  2073. for (var i in meshes) {
  2074. var mesh = meshes[i];
  2075. var boundingBox = mesh.getBoundingInfo().boundingBox;
  2076. if (!minVector) {
  2077. minVector = boundingBox.minimumWorld;
  2078. maxVector = boundingBox.maximumWorld;
  2079. continue;
  2080. }
  2081. minVector.MinimizeInPlace(boundingBox.minimumWorld);
  2082. maxVector.MaximizeInPlace(boundingBox.maximumWorld);
  2083. }
  2084. return {
  2085. min: minVector,
  2086. max: maxVector
  2087. };
  2088. };
  2089. Mesh.Center = function (meshesOrMinMaxVector) {
  2090. var minMaxVector = meshesOrMinMaxVector.min !== undefined ? meshesOrMinMaxVector : Mesh.MinMax(meshesOrMinMaxVector);
  2091. return BABYLON.Vector3.Center(minMaxVector.min, minMaxVector.max);
  2092. };
  2093. /**
  2094. * Merge the array of meshes into a single mesh for performance reasons.
  2095. * @param {Array<Mesh>} meshes - The vertices source. They should all be of the same material. Entries can empty
  2096. * @param {boolean} disposeSource - When true (default), dispose of the vertices from the source meshes
  2097. * @param {boolean} allow32BitsIndices - When the sum of the vertices > 64k, this must be set to true.
  2098. * @param {Mesh} meshSubclass - When set, vertices inserted into this Mesh. Meshes can then be merged into a Mesh sub-class.
  2099. */
  2100. Mesh.MergeMeshes = function (meshes, disposeSource, allow32BitsIndices, meshSubclass) {
  2101. if (disposeSource === void 0) { disposeSource = true; }
  2102. var index;
  2103. if (!allow32BitsIndices) {
  2104. var totalVertices = 0;
  2105. // Counting vertices
  2106. for (index = 0; index < meshes.length; index++) {
  2107. if (meshes[index]) {
  2108. totalVertices += meshes[index].getTotalVertices();
  2109. if (totalVertices > 65536) {
  2110. BABYLON.Tools.Warn("Cannot merge meshes because resulting mesh will have more than 65536 vertices. Please use allow32BitsIndices = true to use 32 bits indices");
  2111. return null;
  2112. }
  2113. }
  2114. }
  2115. }
  2116. // Merge
  2117. var vertexData;
  2118. var otherVertexData;
  2119. var source;
  2120. for (index = 0; index < meshes.length; index++) {
  2121. if (meshes[index]) {
  2122. meshes[index].computeWorldMatrix(true);
  2123. otherVertexData = BABYLON.VertexData.ExtractFromMesh(meshes[index], true);
  2124. otherVertexData.transform(meshes[index].getWorldMatrix());
  2125. if (vertexData) {
  2126. vertexData.merge(otherVertexData);
  2127. }
  2128. else {
  2129. vertexData = otherVertexData;
  2130. source = meshes[index];
  2131. }
  2132. }
  2133. }
  2134. if (!meshSubclass) {
  2135. meshSubclass = new Mesh(source.name + "_merged", source.getScene());
  2136. }
  2137. vertexData.applyToMesh(meshSubclass);
  2138. // Setting properties
  2139. meshSubclass.material = source.material;
  2140. meshSubclass.checkCollisions = source.checkCollisions;
  2141. // Cleaning
  2142. if (disposeSource) {
  2143. for (index = 0; index < meshes.length; index++) {
  2144. if (meshes[index]) {
  2145. meshes[index].dispose();
  2146. }
  2147. }
  2148. }
  2149. return meshSubclass;
  2150. };
  2151. // Consts
  2152. Mesh._FRONTSIDE = 0;
  2153. Mesh._BACKSIDE = 1;
  2154. Mesh._DOUBLESIDE = 2;
  2155. Mesh._DEFAULTSIDE = 0;
  2156. Mesh._NO_CAP = 0;
  2157. Mesh._CAP_START = 1;
  2158. Mesh._CAP_END = 2;
  2159. Mesh._CAP_ALL = 3;
  2160. return Mesh;
  2161. })(BABYLON.AbstractMesh);
  2162. BABYLON.Mesh = Mesh;
  2163. })(BABYLON || (BABYLON = {}));