babylon.geometry.ts 89 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220
  1. module BABYLON {
  2. /**
  3. * Class used to store geometry data (vertex buffers + index buffer)
  4. */
  5. export class Geometry implements IGetSetVerticesData {
  6. // Members
  7. /**
  8. * Gets or sets the unique ID of the geometry
  9. */
  10. public id: string;
  11. /**
  12. * Gets the delay loading state of the geometry (none by default which means not delayed)
  13. */
  14. public delayLoadState = Engine.DELAYLOADSTATE_NONE;
  15. /**
  16. * Gets the file containing the data to load when running in delay load state
  17. */
  18. public delayLoadingFile: Nullable<string>;
  19. /**
  20. * Callback called when the geometry is updated
  21. */
  22. public onGeometryUpdated: (geometry: Geometry, kind?: string) => void;
  23. // Private
  24. private _scene: Scene;
  25. private _engine: Engine;
  26. private _meshes: Mesh[];
  27. private _totalVertices = 0;
  28. /** @hidden */
  29. public _indices: IndicesArray;
  30. /** @hidden */
  31. public _vertexBuffers: { [key: string]: VertexBuffer; };
  32. private _isDisposed = false;
  33. private _extend: { minimum: Vector3, maximum: Vector3 };
  34. private _boundingBias: Vector2;
  35. /** @hidden */
  36. public _delayInfo: Array<string>;
  37. private _indexBuffer: Nullable<WebGLBuffer>;
  38. private _indexBufferIsUpdatable = false;
  39. /** @hidden */
  40. public _boundingInfo: Nullable<BoundingInfo>;
  41. /** @hidden */
  42. public _delayLoadingFunction: Nullable<(any: any, geometry: Geometry) => void>;
  43. /** @hidden */
  44. public _softwareSkinningFrameId: number;
  45. private _vertexArrayObjects: { [key: string]: WebGLVertexArrayObject; };
  46. private _updatable: boolean;
  47. // Cache
  48. /** @hidden */
  49. public _positions: Nullable<Vector3[]>;
  50. /**
  51. * Gets or sets the Bias Vector to apply on the bounding elements (box/sphere), the max extend is computed as v += v * bias.x + bias.y, the min is computed as v -= v * bias.x + bias.y
  52. */
  53. public get boundingBias(): Vector2 {
  54. return this._boundingBias;
  55. }
  56. /**
  57. * Gets or sets the Bias Vector to apply on the bounding elements (box/sphere), the max extend is computed as v += v * bias.x + bias.y, the min is computed as v -= v * bias.x + bias.y
  58. */
  59. public set boundingBias(value: Vector2) {
  60. if (this._boundingBias) {
  61. if (this._boundingBias.equals(value)) {
  62. return;
  63. }
  64. this._boundingBias.copyFrom(value);
  65. }
  66. else {
  67. this._boundingBias = value.clone();
  68. }
  69. this._updateBoundingInfo(true, null);
  70. }
  71. /**
  72. * Static function used to attach a new empty geometry to a mesh
  73. * @param mesh defines the mesh to attach the geometry to
  74. * @returns the new {BABYLON.Geometry}
  75. */
  76. public static CreateGeometryForMesh(mesh: Mesh): Geometry {
  77. let geometry = new Geometry(Geometry.RandomId(), mesh.getScene());
  78. geometry.applyToMesh(mesh);
  79. return geometry;
  80. }
  81. /**
  82. * Creates a new geometry
  83. * @param id defines the unique ID
  84. * @param scene defines the hosting scene
  85. * @param vertexData defines the {BABYLON.VertexData} used to get geometry data
  86. * @param updatable defines if geometry must be updatable (false by default)
  87. * @param mesh defines the mesh that will be associated with the geometry
  88. */
  89. constructor(id: string, scene: Scene, vertexData?: VertexData, updatable: boolean = false, mesh: Nullable<Mesh> = null) {
  90. this.id = id;
  91. this._engine = scene.getEngine();
  92. this._meshes = [];
  93. this._scene = scene;
  94. //Init vertex buffer cache
  95. this._vertexBuffers = {};
  96. this._indices = [];
  97. this._updatable = updatable;
  98. // vertexData
  99. if (vertexData) {
  100. this.setAllVerticesData(vertexData, updatable);
  101. }
  102. else {
  103. this._totalVertices = 0;
  104. this._indices = [];
  105. }
  106. if (this._engine.getCaps().vertexArrayObject) {
  107. this._vertexArrayObjects = {};
  108. }
  109. // applyToMesh
  110. if (mesh) {
  111. if (mesh.getClassName() === "LinesMesh") {
  112. this.boundingBias = new Vector2(0, (<LinesMesh>mesh).intersectionThreshold);
  113. this._updateExtend();
  114. }
  115. this.applyToMesh(mesh);
  116. mesh.computeWorldMatrix(true);
  117. }
  118. }
  119. /**
  120. * Gets the current extend of the geometry
  121. */
  122. public get extend(): { minimum: Vector3, maximum: Vector3 } {
  123. return this._extend;
  124. }
  125. /**
  126. * Gets the hosting scene
  127. * @returns the hosting {BABYLON.Scene}
  128. */
  129. public getScene(): Scene {
  130. return this._scene;
  131. }
  132. /**
  133. * Gets the hosting engine
  134. * @returns the hosting {BABYLON.Engine}
  135. */
  136. public getEngine(): Engine {
  137. return this._engine;
  138. }
  139. /**
  140. * Defines if the geometry is ready to use
  141. * @returns true if the geometry is ready to be used
  142. */
  143. public isReady(): boolean {
  144. return this.delayLoadState === Engine.DELAYLOADSTATE_LOADED || this.delayLoadState === Engine.DELAYLOADSTATE_NONE;
  145. }
  146. /**
  147. * Gets a value indicating that the geometry should not be serialized
  148. */
  149. public get doNotSerialize(): boolean {
  150. for (var index = 0; index < this._meshes.length; index++) {
  151. if (!this._meshes[index].doNotSerialize) {
  152. return false;
  153. }
  154. }
  155. return true;
  156. }
  157. /** @hidden */
  158. public _rebuild(): void {
  159. if (this._vertexArrayObjects) {
  160. this._vertexArrayObjects = {};
  161. }
  162. // Index buffer
  163. if (this._meshes.length !== 0 && this._indices) {
  164. this._indexBuffer = this._engine.createIndexBuffer(this._indices);
  165. }
  166. // Vertex buffers
  167. for (var key in this._vertexBuffers) {
  168. let vertexBuffer = <VertexBuffer>this._vertexBuffers[key];
  169. vertexBuffer._rebuild();
  170. }
  171. }
  172. /**
  173. * Affects all geometry data in one call
  174. * @param vertexData defines the geometry data
  175. * @param updatable defines if the geometry must be flagged as updatable (false as default)
  176. */
  177. public setAllVerticesData(vertexData: VertexData, updatable?: boolean): void {
  178. vertexData.applyToGeometry(this, updatable);
  179. this.notifyUpdate();
  180. }
  181. /**
  182. * Set specific vertex data
  183. * @param kind defines the data kind (Position, normal, etc...)
  184. * @param data defines the vertex data to use
  185. * @param updatable defines if the vertex must be flagged as updatable (false as default)
  186. * @param stride defines the stride to use (0 by default). This value is deduced from the kind value if not specified
  187. */
  188. public setVerticesData(kind: string, data: FloatArray, updatable: boolean = false, stride?: number): void {
  189. var buffer = new VertexBuffer(this._engine, data, kind, updatable, this._meshes.length === 0, stride);
  190. this.setVerticesBuffer(buffer);
  191. }
  192. /**
  193. * Removes a specific vertex data
  194. * @param kind defines the data kind (Position, normal, etc...)
  195. */
  196. public removeVerticesData(kind: string) {
  197. if (this._vertexBuffers[kind]) {
  198. this._vertexBuffers[kind].dispose();
  199. delete this._vertexBuffers[kind];
  200. }
  201. }
  202. /**
  203. * Affect a vertex buffer to the geometry. the vertexBuffer.getKind() function is used to determine where to store the data
  204. * @param buffer defines the vertex buffer to use
  205. * @param totalVertices defines the total number of vertices for position kind (could be null)
  206. */
  207. public setVerticesBuffer(buffer: VertexBuffer, totalVertices: Nullable<number> = null): void {
  208. var kind = buffer.getKind();
  209. if (this._vertexBuffers[kind]) {
  210. this._vertexBuffers[kind].dispose();
  211. }
  212. this._vertexBuffers[kind] = buffer;
  213. if (kind === VertexBuffer.PositionKind) {
  214. var data = <FloatArray>buffer.getData();
  215. if (totalVertices != null) {
  216. this._totalVertices = totalVertices;
  217. } else {
  218. if (data != null) {
  219. this._totalVertices = data.length / (buffer.byteStride / 4);
  220. }
  221. }
  222. this._updateExtend(data);
  223. this._resetPointsArrayCache();
  224. var meshes = this._meshes;
  225. var numOfMeshes = meshes.length;
  226. for (var index = 0; index < numOfMeshes; index++) {
  227. var mesh = meshes[index];
  228. mesh._boundingInfo = new BoundingInfo(this._extend.minimum, this._extend.maximum);
  229. mesh._createGlobalSubMesh(false);
  230. mesh.computeWorldMatrix(true);
  231. }
  232. }
  233. this.notifyUpdate(kind);
  234. if (this._vertexArrayObjects) {
  235. this._disposeVertexArrayObjects();
  236. this._vertexArrayObjects = {}; // Will trigger a rebuild of the VAO if supported
  237. }
  238. }
  239. /**
  240. * Update a specific vertex buffer
  241. * This function will directly update the underlying WebGLBuffer according to the passed numeric array or Float32Array
  242. * It will do nothing if the buffer is not updatable
  243. * @param kind defines the data kind (Position, normal, etc...)
  244. * @param data defines the data to use
  245. * @param offset defines the offset in the target buffer where to store the data
  246. * @param useBytes set to true if the offset is in bytes
  247. */
  248. public updateVerticesDataDirectly(kind: string, data: DataArray, offset: number, useBytes: boolean = false): void {
  249. var vertexBuffer = this.getVertexBuffer(kind);
  250. if (!vertexBuffer) {
  251. return;
  252. }
  253. vertexBuffer.updateDirectly(data, offset, useBytes);
  254. this.notifyUpdate(kind);
  255. }
  256. /**
  257. * Update a specific vertex buffer
  258. * This function will create a new buffer if the current one is not updatable
  259. * @param kind defines the data kind (Position, normal, etc...)
  260. * @param data defines the data to use
  261. * @param updateExtends defines if the geometry extends must be recomputed (false by default)
  262. */
  263. public updateVerticesData(kind: string, data: FloatArray, updateExtends: boolean = false): void {
  264. var vertexBuffer = this.getVertexBuffer(kind);
  265. if (!vertexBuffer) {
  266. return;
  267. }
  268. vertexBuffer.update(data);
  269. if (kind === VertexBuffer.PositionKind) {
  270. this._updateBoundingInfo(updateExtends, data);
  271. }
  272. this.notifyUpdate(kind);
  273. }
  274. private _updateBoundingInfo(updateExtends: boolean, data: Nullable<FloatArray>) {
  275. if (updateExtends) {
  276. this._updateExtend(data);
  277. }
  278. var meshes = this._meshes;
  279. var numOfMeshes = meshes.length;
  280. this._resetPointsArrayCache();
  281. for (var index = 0; index < numOfMeshes; index++) {
  282. var mesh = meshes[index];
  283. if (updateExtends) {
  284. mesh._boundingInfo = new BoundingInfo(this._extend.minimum, this._extend.maximum);
  285. for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
  286. var subMesh = mesh.subMeshes[subIndex];
  287. subMesh.refreshBoundingInfo();
  288. }
  289. }
  290. }
  291. }
  292. /** @hidden */
  293. public _bind(effect: Nullable<Effect>, indexToBind?: Nullable<WebGLBuffer>): void {
  294. if (!effect) {
  295. return;
  296. }
  297. if (indexToBind === undefined) {
  298. indexToBind = this._indexBuffer;
  299. }
  300. let vbs = this.getVertexBuffers();
  301. if (!vbs) {
  302. return;
  303. }
  304. if (indexToBind != this._indexBuffer || !this._vertexArrayObjects) {
  305. this._engine.bindBuffers(vbs, indexToBind, effect);
  306. return;
  307. }
  308. // Using VAO
  309. if (!this._vertexArrayObjects[effect.key]) {
  310. this._vertexArrayObjects[effect.key] = this._engine.recordVertexArrayObject(vbs, indexToBind, effect);
  311. }
  312. this._engine.bindVertexArrayObject(this._vertexArrayObjects[effect.key], indexToBind);
  313. }
  314. /**
  315. * Gets total number of vertices
  316. * @returns the total number of vertices
  317. */
  318. public getTotalVertices(): number {
  319. if (!this.isReady()) {
  320. return 0;
  321. }
  322. return this._totalVertices;
  323. }
  324. /**
  325. * Gets a specific vertex data attached to this geometry. Float data is constructed if the vertex buffer data cannot be returned directly.
  326. * @param kind defines the data kind (Position, normal, etc...)
  327. * @param copyWhenShared defines if the returned array must be cloned upon returning it if the current geometry is shared between multiple meshes
  328. * @param forceCopy defines a boolean indicating that the returned array must be cloned upon returning it
  329. * @returns a float array containing vertex data
  330. */
  331. public getVerticesData(kind: string, copyWhenShared?: boolean, forceCopy?: boolean): Nullable<FloatArray> {
  332. const vertexBuffer = this.getVertexBuffer(kind);
  333. if (!vertexBuffer) {
  334. return null;
  335. }
  336. let data = vertexBuffer.getData();
  337. if (!data) {
  338. return null;
  339. }
  340. const tightlyPackedByteStride = vertexBuffer.getSize() * VertexBuffer.GetTypeByteLength(vertexBuffer.type);
  341. const count = this._totalVertices * vertexBuffer.getSize();
  342. if (vertexBuffer.type !== VertexBuffer.FLOAT || vertexBuffer.byteStride !== tightlyPackedByteStride) {
  343. const copy = new Array<number>(count);
  344. vertexBuffer.forEach(count, (value, index) => {
  345. copy[index] = value;
  346. });
  347. return copy;
  348. }
  349. if (!((data instanceof Array) || (data instanceof Float32Array)) || vertexBuffer.byteOffset !== 0 || data.length !== count) {
  350. if (data instanceof Array) {
  351. const offset = vertexBuffer.byteOffset / 4;
  352. return Tools.Slice(data, offset, offset + count);
  353. }
  354. else if (data instanceof ArrayBuffer) {
  355. return new Float32Array(data, vertexBuffer.byteOffset, count);
  356. }
  357. else {
  358. const offset = data.byteOffset + vertexBuffer.byteOffset;
  359. if (forceCopy || (copyWhenShared && this._meshes.length !== 1)) {
  360. let result = new Float32Array(count);
  361. let source = new Float32Array(data.buffer, offset, count);
  362. result.set(source);
  363. return result;
  364. }
  365. return new Float32Array(data.buffer, offset, count);
  366. }
  367. }
  368. if (forceCopy || (copyWhenShared && this._meshes.length !== 1)) {
  369. return Tools.Slice(data);
  370. }
  371. return data;
  372. }
  373. /**
  374. * Returns a boolean defining if the vertex data for the requested `kind` is updatable
  375. * @param kind defines the data kind (Position, normal, etc...)
  376. * @returns true if the vertex buffer with the specified kind is updatable
  377. */
  378. public isVertexBufferUpdatable(kind: string): boolean {
  379. let vb = this._vertexBuffers[kind];
  380. if (!vb) {
  381. return false;
  382. }
  383. return vb.isUpdatable();
  384. }
  385. /**
  386. * Gets a specific vertex buffer
  387. * @param kind defines the data kind (Position, normal, etc...)
  388. * @returns a {BABYLON.VertexBuffer}
  389. */
  390. public getVertexBuffer(kind: string): Nullable<VertexBuffer> {
  391. if (!this.isReady()) {
  392. return null;
  393. }
  394. return this._vertexBuffers[kind];
  395. }
  396. /**
  397. * Returns all vertex buffers
  398. * @return an object holding all vertex buffers indexed by kind
  399. */
  400. public getVertexBuffers(): Nullable<{ [key: string]: VertexBuffer; }> {
  401. if (!this.isReady()) {
  402. return null;
  403. }
  404. return this._vertexBuffers;
  405. }
  406. /**
  407. * Gets a boolean indicating if specific vertex buffer is present
  408. * @param kind defines the data kind (Position, normal, etc...)
  409. * @returns true if data is present
  410. */
  411. public isVerticesDataPresent(kind: string): boolean {
  412. if (!this._vertexBuffers) {
  413. if (this._delayInfo) {
  414. return this._delayInfo.indexOf(kind) !== -1;
  415. }
  416. return false;
  417. }
  418. return this._vertexBuffers[kind] !== undefined;
  419. }
  420. /**
  421. * Gets a list of all attached data kinds (Position, normal, etc...)
  422. * @returns a list of string containing all kinds
  423. */
  424. public getVerticesDataKinds(): string[] {
  425. var result = [];
  426. var kind;
  427. if (!this._vertexBuffers && this._delayInfo) {
  428. for (kind in this._delayInfo) {
  429. result.push(kind);
  430. }
  431. } else {
  432. for (kind in this._vertexBuffers) {
  433. result.push(kind);
  434. }
  435. }
  436. return result;
  437. }
  438. /**
  439. * Update index buffer
  440. * @param indices defines the indices to store in the index buffer
  441. * @param offset defines the offset in the target buffer where to store the data
  442. */
  443. public updateIndices(indices: IndicesArray, offset?: number): void {
  444. if (!this._indexBuffer) {
  445. return;
  446. }
  447. if (!this._indexBufferIsUpdatable) {
  448. this.setIndices(indices, null, true);
  449. } else {
  450. this._engine.updateDynamicIndexBuffer(this._indexBuffer, indices, offset);
  451. }
  452. }
  453. /**
  454. * Creates a new index buffer
  455. * @param indices defines the indices to store in the index buffer
  456. * @param totalVertices defines the total number of vertices (could be null)
  457. * @param updatable defines if the index buffer must be flagged as updatable (false by default)
  458. */
  459. public setIndices(indices: IndicesArray, totalVertices: Nullable<number> = null, updatable: boolean = false): void {
  460. if (this._indexBuffer) {
  461. this._engine._releaseBuffer(this._indexBuffer);
  462. }
  463. this._disposeVertexArrayObjects();
  464. this._indices = indices;
  465. this._indexBufferIsUpdatable = updatable;
  466. if (this._meshes.length !== 0 && this._indices) {
  467. this._indexBuffer = this._engine.createIndexBuffer(this._indices, updatable);
  468. }
  469. if (totalVertices != undefined) { // including null and undefined
  470. this._totalVertices = totalVertices;
  471. }
  472. var meshes = this._meshes;
  473. var numOfMeshes = meshes.length;
  474. for (var index = 0; index < numOfMeshes; index++) {
  475. meshes[index]._createGlobalSubMesh(true);
  476. }
  477. this.notifyUpdate();
  478. }
  479. /**
  480. * Return the total number of indices
  481. * @returns the total number of indices
  482. */
  483. public getTotalIndices(): number {
  484. if (!this.isReady()) {
  485. return 0;
  486. }
  487. return this._indices.length;
  488. }
  489. /**
  490. * Gets the index buffer array
  491. * @param copyWhenShared defines if the returned array must be cloned upon returning it if the current geometry is shared between multiple meshes
  492. * @param forceCopy defines a boolean indicating that the returned array must be cloned upon returning it
  493. * @returns the index buffer array
  494. */
  495. public getIndices(copyWhenShared?: boolean, forceCopy?: boolean): Nullable<IndicesArray> {
  496. if (!this.isReady()) {
  497. return null;
  498. }
  499. var orig = this._indices;
  500. if (!forceCopy && (!copyWhenShared || this._meshes.length === 1)) {
  501. return orig;
  502. } else {
  503. var len = orig.length;
  504. var copy = [];
  505. for (var i = 0; i < len; i++) {
  506. copy.push(orig[i]);
  507. }
  508. return copy;
  509. }
  510. }
  511. /**
  512. * Gets the index buffer
  513. * @return the index buffer
  514. */
  515. public getIndexBuffer(): Nullable<WebGLBuffer> {
  516. if (!this.isReady()) {
  517. return null;
  518. }
  519. return this._indexBuffer;
  520. }
  521. /** @hidden */
  522. public _releaseVertexArrayObject(effect: Nullable<Effect> = null) {
  523. if (!effect || !this._vertexArrayObjects) {
  524. return;
  525. }
  526. if (this._vertexArrayObjects[effect.key]) {
  527. this._engine.releaseVertexArrayObject(this._vertexArrayObjects[effect.key]);
  528. delete this._vertexArrayObjects[effect.key];
  529. }
  530. }
  531. /**
  532. * Release the associated resources for a specific mesh
  533. * @param mesh defines the source mesh
  534. * @param shouldDispose defines if the geometry must be disposed if there is no more mesh pointing to it
  535. */
  536. public releaseForMesh(mesh: Mesh, shouldDispose?: boolean): void {
  537. var meshes = this._meshes;
  538. var index = meshes.indexOf(mesh);
  539. if (index === -1) {
  540. return;
  541. }
  542. meshes.splice(index, 1);
  543. mesh._geometry = null;
  544. if (meshes.length === 0 && shouldDispose) {
  545. this.dispose();
  546. }
  547. }
  548. /**
  549. * Apply current geometry to a given mesh
  550. * @param mesh defines the mesh to apply geometry to
  551. */
  552. public applyToMesh(mesh: Mesh): void {
  553. if (mesh._geometry === this) {
  554. return;
  555. }
  556. var previousGeometry = mesh._geometry;
  557. if (previousGeometry) {
  558. previousGeometry.releaseForMesh(mesh);
  559. }
  560. var meshes = this._meshes;
  561. // must be done before setting vertexBuffers because of mesh._createGlobalSubMesh()
  562. mesh._geometry = this;
  563. this._scene.pushGeometry(this);
  564. meshes.push(mesh);
  565. if (this.isReady()) {
  566. this._applyToMesh(mesh);
  567. }
  568. else {
  569. mesh._boundingInfo = this._boundingInfo;
  570. }
  571. }
  572. private _updateExtend(data: Nullable<FloatArray> = null) {
  573. if (!data) {
  574. data = this.getVerticesData(VertexBuffer.PositionKind)!;
  575. }
  576. this._extend = Tools.ExtractMinAndMax(data, 0, this._totalVertices, this.boundingBias, 3);
  577. }
  578. private _applyToMesh(mesh: Mesh): void {
  579. var numOfMeshes = this._meshes.length;
  580. // vertexBuffers
  581. for (var kind in this._vertexBuffers) {
  582. if (numOfMeshes === 1) {
  583. this._vertexBuffers[kind].create();
  584. }
  585. var buffer = this._vertexBuffers[kind].getBuffer();
  586. if (buffer)
  587. buffer.references = numOfMeshes;
  588. if (kind === VertexBuffer.PositionKind) {
  589. if (!this._extend) {
  590. this._updateExtend();
  591. }
  592. mesh._boundingInfo = new BoundingInfo(this._extend.minimum, this._extend.maximum);
  593. mesh._createGlobalSubMesh(false);
  594. //bounding info was just created again, world matrix should be applied again.
  595. mesh._updateBoundingInfo();
  596. }
  597. }
  598. // indexBuffer
  599. if (numOfMeshes === 1 && this._indices && this._indices.length > 0) {
  600. this._indexBuffer = this._engine.createIndexBuffer(this._indices);
  601. }
  602. if (this._indexBuffer) {
  603. this._indexBuffer.references = numOfMeshes;
  604. }
  605. }
  606. private notifyUpdate(kind?: string) {
  607. if (this.onGeometryUpdated) {
  608. this.onGeometryUpdated(this, kind);
  609. }
  610. for (var mesh of this._meshes) {
  611. mesh._markSubMeshesAsAttributesDirty();
  612. }
  613. }
  614. /**
  615. * Load the geometry if it was flagged as delay loaded
  616. * @param scene defines the hosting scene
  617. * @param onLoaded defines a callback called when the geometry is loaded
  618. */
  619. public load(scene: Scene, onLoaded?: () => void): void {
  620. if (this.delayLoadState === Engine.DELAYLOADSTATE_LOADING) {
  621. return;
  622. }
  623. if (this.isReady()) {
  624. if (onLoaded) {
  625. onLoaded();
  626. }
  627. return;
  628. }
  629. this.delayLoadState = Engine.DELAYLOADSTATE_LOADING;
  630. this._queueLoad(scene, onLoaded);
  631. }
  632. private _queueLoad(scene: Scene, onLoaded?: () => void): void {
  633. if (!this.delayLoadingFile) {
  634. return;
  635. }
  636. scene._addPendingData(this);
  637. scene._loadFile(this.delayLoadingFile, data => {
  638. if (!this._delayLoadingFunction) {
  639. return;
  640. }
  641. this._delayLoadingFunction(JSON.parse(data as string), this);
  642. this.delayLoadState = Engine.DELAYLOADSTATE_LOADED;
  643. this._delayInfo = [];
  644. scene._removePendingData(this);
  645. var meshes = this._meshes;
  646. var numOfMeshes = meshes.length;
  647. for (var index = 0; index < numOfMeshes; index++) {
  648. this._applyToMesh(meshes[index]);
  649. }
  650. if (onLoaded) {
  651. onLoaded();
  652. }
  653. }, undefined, true);
  654. }
  655. /**
  656. * Invert the geometry to move from a right handed system to a left handed one.
  657. */
  658. public toLeftHanded(): void {
  659. // Flip faces
  660. let tIndices = this.getIndices(false);
  661. if (tIndices != null && tIndices.length > 0) {
  662. for (let i = 0; i < tIndices.length; i += 3) {
  663. let tTemp = tIndices[i + 0];
  664. tIndices[i + 0] = tIndices[i + 2];
  665. tIndices[i + 2] = tTemp;
  666. }
  667. this.setIndices(tIndices);
  668. }
  669. // Negate position.z
  670. let tPositions = this.getVerticesData(VertexBuffer.PositionKind, false);
  671. if (tPositions != null && tPositions.length > 0) {
  672. for (let i = 0; i < tPositions.length; i += 3) {
  673. tPositions[i + 2] = -tPositions[i + 2];
  674. }
  675. this.setVerticesData(VertexBuffer.PositionKind, tPositions, false);
  676. }
  677. // Negate normal.z
  678. let tNormals = this.getVerticesData(VertexBuffer.NormalKind, false);
  679. if (tNormals != null && tNormals.length > 0) {
  680. for (let i = 0; i < tNormals.length; i += 3) {
  681. tNormals[i + 2] = -tNormals[i + 2];
  682. }
  683. this.setVerticesData(VertexBuffer.NormalKind, tNormals, false);
  684. }
  685. }
  686. // Cache
  687. /** @hidden */
  688. public _resetPointsArrayCache(): void {
  689. this._positions = null;
  690. }
  691. /** @hidden */
  692. public _generatePointsArray(): boolean {
  693. if (this._positions)
  694. return true;
  695. var data = this.getVerticesData(VertexBuffer.PositionKind);
  696. if (!data || data.length === 0) {
  697. return false;
  698. }
  699. this._positions = [];
  700. for (var index = 0; index < data.length; index += 3) {
  701. this._positions.push(Vector3.FromArray(data, index));
  702. }
  703. return true;
  704. }
  705. /**
  706. * Gets a value indicating if the geometry is disposed
  707. * @returns true if the geometry was disposed
  708. */
  709. public isDisposed(): boolean {
  710. return this._isDisposed;
  711. }
  712. private _disposeVertexArrayObjects(): void {
  713. if (this._vertexArrayObjects) {
  714. for (var kind in this._vertexArrayObjects) {
  715. this._engine.releaseVertexArrayObject(this._vertexArrayObjects[kind]);
  716. }
  717. this._vertexArrayObjects = {};
  718. }
  719. }
  720. /**
  721. * Free all associated resources
  722. */
  723. public dispose(): void {
  724. var meshes = this._meshes;
  725. var numOfMeshes = meshes.length;
  726. var index: number;
  727. for (index = 0; index < numOfMeshes; index++) {
  728. this.releaseForMesh(meshes[index]);
  729. }
  730. this._meshes = [];
  731. this._disposeVertexArrayObjects();
  732. for (var kind in this._vertexBuffers) {
  733. this._vertexBuffers[kind].dispose();
  734. }
  735. this._vertexBuffers = {};
  736. this._totalVertices = 0;
  737. if (this._indexBuffer) {
  738. this._engine._releaseBuffer(this._indexBuffer);
  739. }
  740. this._indexBuffer = null;
  741. this._indices = [];
  742. this.delayLoadState = Engine.DELAYLOADSTATE_NONE;
  743. this.delayLoadingFile = null;
  744. this._delayLoadingFunction = null;
  745. this._delayInfo = [];
  746. this._boundingInfo = null;
  747. this._scene.removeGeometry(this);
  748. this._isDisposed = true;
  749. }
  750. /**
  751. * Clone the current geometry into a new geometry
  752. * @param id defines the unique ID of the new geometry
  753. * @returns a new geometry object
  754. */
  755. public copy(id: string): Geometry {
  756. var vertexData = new VertexData();
  757. vertexData.indices = [];
  758. var indices = this.getIndices();
  759. if (indices) {
  760. for (var index = 0; index < indices.length; index++) {
  761. (<number[]>vertexData.indices).push(indices[index]);
  762. }
  763. }
  764. var updatable = false;
  765. var stopChecking = false;
  766. var kind;
  767. for (kind in this._vertexBuffers) {
  768. // using slice() to make a copy of the array and not just reference it
  769. var data = this.getVerticesData(kind);
  770. if (data instanceof Float32Array) {
  771. vertexData.set(new Float32Array(<Float32Array>data), kind);
  772. } else {
  773. vertexData.set((<number[]>data).slice(0), kind);
  774. }
  775. if (!stopChecking) {
  776. let vb = this.getVertexBuffer(kind);
  777. if (vb) {
  778. updatable = vb.isUpdatable();
  779. stopChecking = !updatable;
  780. }
  781. }
  782. }
  783. var geometry = new Geometry(id, this._scene, vertexData, updatable);
  784. geometry.delayLoadState = this.delayLoadState;
  785. geometry.delayLoadingFile = this.delayLoadingFile;
  786. geometry._delayLoadingFunction = this._delayLoadingFunction;
  787. for (kind in this._delayInfo) {
  788. geometry._delayInfo = geometry._delayInfo || [];
  789. geometry._delayInfo.push(kind);
  790. }
  791. // Bounding info
  792. geometry._boundingInfo = new BoundingInfo(this._extend.minimum, this._extend.maximum);
  793. return geometry;
  794. }
  795. /**
  796. * Serialize the current geometry info (and not the vertices data) into a JSON object
  797. * @return a JSON representation of the current geometry data (without the vertices data)
  798. */
  799. public serialize(): any {
  800. var serializationObject: any = {};
  801. serializationObject.id = this.id;
  802. serializationObject.updatable = this._updatable;
  803. if (Tags && Tags.HasTags(this)) {
  804. serializationObject.tags = Tags.GetTags(this);
  805. }
  806. return serializationObject;
  807. }
  808. private toNumberArray(origin: Nullable<Float32Array | IndicesArray>): number[] {
  809. if (Array.isArray(origin)) {
  810. return origin;
  811. } else {
  812. return Array.prototype.slice.call(origin);
  813. }
  814. }
  815. /**
  816. * Serialize all vertices data into a JSON oject
  817. * @returns a JSON representation of the current geometry data
  818. */
  819. public serializeVerticeData(): any {
  820. var serializationObject = this.serialize();
  821. if (this.isVerticesDataPresent(VertexBuffer.PositionKind)) {
  822. serializationObject.positions = this.toNumberArray(this.getVerticesData(VertexBuffer.PositionKind));
  823. if (this.isVertexBufferUpdatable(VertexBuffer.PositionKind)) {
  824. serializationObject.positions._updatable = true;
  825. }
  826. }
  827. if (this.isVerticesDataPresent(VertexBuffer.NormalKind)) {
  828. serializationObject.normals = this.toNumberArray(this.getVerticesData(VertexBuffer.NormalKind));
  829. if (this.isVertexBufferUpdatable(VertexBuffer.NormalKind)) {
  830. serializationObject.normals._updatable = true;
  831. }
  832. }
  833. if (this.isVerticesDataPresent(VertexBuffer.TangentKind)) {
  834. serializationObject.tangets = this.toNumberArray(this.getVerticesData(VertexBuffer.TangentKind));
  835. if (this.isVertexBufferUpdatable(VertexBuffer.TangentKind)) {
  836. serializationObject.tangets._updatable = true;
  837. }
  838. }
  839. if (this.isVerticesDataPresent(VertexBuffer.UVKind)) {
  840. serializationObject.uvs = this.toNumberArray(this.getVerticesData(VertexBuffer.UVKind));
  841. if (this.isVertexBufferUpdatable(VertexBuffer.UVKind)) {
  842. serializationObject.uvs._updatable = true;
  843. }
  844. }
  845. if (this.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
  846. serializationObject.uv2s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV2Kind));
  847. if (this.isVertexBufferUpdatable(VertexBuffer.UV2Kind)) {
  848. serializationObject.uv2s._updatable = true;
  849. }
  850. }
  851. if (this.isVerticesDataPresent(VertexBuffer.UV3Kind)) {
  852. serializationObject.uv3s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV3Kind));
  853. if (this.isVertexBufferUpdatable(VertexBuffer.UV3Kind)) {
  854. serializationObject.uv3s._updatable = true;
  855. }
  856. }
  857. if (this.isVerticesDataPresent(VertexBuffer.UV4Kind)) {
  858. serializationObject.uv4s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV4Kind));
  859. if (this.isVertexBufferUpdatable(VertexBuffer.UV4Kind)) {
  860. serializationObject.uv4s._updatable = true;
  861. }
  862. }
  863. if (this.isVerticesDataPresent(VertexBuffer.UV5Kind)) {
  864. serializationObject.uv5s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV5Kind));
  865. if (this.isVertexBufferUpdatable(VertexBuffer.UV5Kind)) {
  866. serializationObject.uv5s._updatable = true;
  867. }
  868. }
  869. if (this.isVerticesDataPresent(VertexBuffer.UV6Kind)) {
  870. serializationObject.uv6s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV6Kind));
  871. if (this.isVertexBufferUpdatable(VertexBuffer.UV6Kind)) {
  872. serializationObject.uv6s._updatable = true;
  873. }
  874. }
  875. if (this.isVerticesDataPresent(VertexBuffer.ColorKind)) {
  876. serializationObject.colors = this.toNumberArray(this.getVerticesData(VertexBuffer.ColorKind));
  877. if (this.isVertexBufferUpdatable(VertexBuffer.ColorKind)) {
  878. serializationObject.colors._updatable = true;
  879. }
  880. }
  881. if (this.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind)) {
  882. serializationObject.matricesIndices = this.toNumberArray(this.getVerticesData(VertexBuffer.MatricesIndicesKind));
  883. serializationObject.matricesIndices._isExpanded = true;
  884. if (this.isVertexBufferUpdatable(VertexBuffer.MatricesIndicesKind)) {
  885. serializationObject.matricesIndices._updatable = true;
  886. }
  887. }
  888. if (this.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind)) {
  889. serializationObject.matricesWeights = this.toNumberArray(this.getVerticesData(VertexBuffer.MatricesWeightsKind));
  890. if (this.isVertexBufferUpdatable(VertexBuffer.MatricesWeightsKind)) {
  891. serializationObject.matricesWeights._updatable = true;
  892. }
  893. }
  894. serializationObject.indices = this.toNumberArray(this.getIndices());
  895. return serializationObject;
  896. }
  897. // Statics
  898. /**
  899. * Extracts a clone of a mesh geometry
  900. * @param mesh defines the source mesh
  901. * @param id defines the unique ID of the new geometry object
  902. * @returns the new geometry object
  903. */
  904. public static ExtractFromMesh(mesh: Mesh, id: string): Nullable<Geometry> {
  905. var geometry = mesh._geometry;
  906. if (!geometry) {
  907. return null;
  908. }
  909. return geometry.copy(id);
  910. }
  911. /**
  912. * You should now use Tools.RandomId(), this method is still here for legacy reasons.
  913. * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
  914. * Be aware Math.random() could cause collisions, but:
  915. * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
  916. * @returns a string containing a new GUID
  917. */
  918. public static RandomId(): string {
  919. return Tools.RandomId();
  920. }
  921. /** @hidden */
  922. public static _ImportGeometry(parsedGeometry: any, mesh: Mesh): void {
  923. var scene = mesh.getScene();
  924. // Geometry
  925. var geometryId = parsedGeometry.geometryId;
  926. if (geometryId) {
  927. var geometry = scene.getGeometryByID(geometryId);
  928. if (geometry) {
  929. geometry.applyToMesh(mesh);
  930. }
  931. } else if (parsedGeometry instanceof ArrayBuffer) {
  932. var binaryInfo = mesh._binaryInfo;
  933. if (binaryInfo.positionsAttrDesc && binaryInfo.positionsAttrDesc.count > 0) {
  934. var positionsData = new Float32Array(parsedGeometry, binaryInfo.positionsAttrDesc.offset, binaryInfo.positionsAttrDesc.count);
  935. mesh.setVerticesData(VertexBuffer.PositionKind, positionsData, false);
  936. }
  937. if (binaryInfo.normalsAttrDesc && binaryInfo.normalsAttrDesc.count > 0) {
  938. var normalsData = new Float32Array(parsedGeometry, binaryInfo.normalsAttrDesc.offset, binaryInfo.normalsAttrDesc.count);
  939. mesh.setVerticesData(VertexBuffer.NormalKind, normalsData, false);
  940. }
  941. if (binaryInfo.tangetsAttrDesc && binaryInfo.tangetsAttrDesc.count > 0) {
  942. var tangentsData = new Float32Array(parsedGeometry, binaryInfo.tangetsAttrDesc.offset, binaryInfo.tangetsAttrDesc.count);
  943. mesh.setVerticesData(VertexBuffer.TangentKind, tangentsData, false);
  944. }
  945. if (binaryInfo.uvsAttrDesc && binaryInfo.uvsAttrDesc.count > 0) {
  946. var uvsData = new Float32Array(parsedGeometry, binaryInfo.uvsAttrDesc.offset, binaryInfo.uvsAttrDesc.count);
  947. mesh.setVerticesData(VertexBuffer.UVKind, uvsData, false);
  948. }
  949. if (binaryInfo.uvs2AttrDesc && binaryInfo.uvs2AttrDesc.count > 0) {
  950. var uvs2Data = new Float32Array(parsedGeometry, binaryInfo.uvs2AttrDesc.offset, binaryInfo.uvs2AttrDesc.count);
  951. mesh.setVerticesData(VertexBuffer.UV2Kind, uvs2Data, false);
  952. }
  953. if (binaryInfo.uvs3AttrDesc && binaryInfo.uvs3AttrDesc.count > 0) {
  954. var uvs3Data = new Float32Array(parsedGeometry, binaryInfo.uvs3AttrDesc.offset, binaryInfo.uvs3AttrDesc.count);
  955. mesh.setVerticesData(VertexBuffer.UV3Kind, uvs3Data, false);
  956. }
  957. if (binaryInfo.uvs4AttrDesc && binaryInfo.uvs4AttrDesc.count > 0) {
  958. var uvs4Data = new Float32Array(parsedGeometry, binaryInfo.uvs4AttrDesc.offset, binaryInfo.uvs4AttrDesc.count);
  959. mesh.setVerticesData(VertexBuffer.UV4Kind, uvs4Data, false);
  960. }
  961. if (binaryInfo.uvs5AttrDesc && binaryInfo.uvs5AttrDesc.count > 0) {
  962. var uvs5Data = new Float32Array(parsedGeometry, binaryInfo.uvs5AttrDesc.offset, binaryInfo.uvs5AttrDesc.count);
  963. mesh.setVerticesData(VertexBuffer.UV5Kind, uvs5Data, false);
  964. }
  965. if (binaryInfo.uvs6AttrDesc && binaryInfo.uvs6AttrDesc.count > 0) {
  966. var uvs6Data = new Float32Array(parsedGeometry, binaryInfo.uvs6AttrDesc.offset, binaryInfo.uvs6AttrDesc.count);
  967. mesh.setVerticesData(VertexBuffer.UV6Kind, uvs6Data, false);
  968. }
  969. if (binaryInfo.colorsAttrDesc && binaryInfo.colorsAttrDesc.count > 0) {
  970. var colorsData = new Float32Array(parsedGeometry, binaryInfo.colorsAttrDesc.offset, binaryInfo.colorsAttrDesc.count);
  971. mesh.setVerticesData(VertexBuffer.ColorKind, colorsData, false, binaryInfo.colorsAttrDesc.stride);
  972. }
  973. if (binaryInfo.matricesIndicesAttrDesc && binaryInfo.matricesIndicesAttrDesc.count > 0) {
  974. var matricesIndicesData = new Int32Array(parsedGeometry, binaryInfo.matricesIndicesAttrDesc.offset, binaryInfo.matricesIndicesAttrDesc.count);
  975. var floatIndices = [];
  976. for (var i = 0; i < matricesIndicesData.length; i++) {
  977. var index = matricesIndicesData[i];
  978. floatIndices.push(index & 0x000000FF);
  979. floatIndices.push((index & 0x0000FF00) >> 8);
  980. floatIndices.push((index & 0x00FF0000) >> 16);
  981. floatIndices.push(index >> 24);
  982. }
  983. mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, floatIndices, false);
  984. }
  985. if (binaryInfo.matricesWeightsAttrDesc && binaryInfo.matricesWeightsAttrDesc.count > 0) {
  986. var matricesWeightsData = new Float32Array(parsedGeometry, binaryInfo.matricesWeightsAttrDesc.offset, binaryInfo.matricesWeightsAttrDesc.count);
  987. mesh.setVerticesData(VertexBuffer.MatricesWeightsKind, matricesWeightsData, false);
  988. }
  989. if (binaryInfo.indicesAttrDesc && binaryInfo.indicesAttrDesc.count > 0) {
  990. var indicesData = new Int32Array(parsedGeometry, binaryInfo.indicesAttrDesc.offset, binaryInfo.indicesAttrDesc.count);
  991. mesh.setIndices(indicesData, null);
  992. }
  993. if (binaryInfo.subMeshesAttrDesc && binaryInfo.subMeshesAttrDesc.count > 0) {
  994. var subMeshesData = new Int32Array(parsedGeometry, binaryInfo.subMeshesAttrDesc.offset, binaryInfo.subMeshesAttrDesc.count * 5);
  995. mesh.subMeshes = [];
  996. for (var i = 0; i < binaryInfo.subMeshesAttrDesc.count; i++) {
  997. var materialIndex = subMeshesData[(i * 5) + 0];
  998. var verticesStart = subMeshesData[(i * 5) + 1];
  999. var verticesCount = subMeshesData[(i * 5) + 2];
  1000. var indexStart = subMeshesData[(i * 5) + 3];
  1001. var indexCount = subMeshesData[(i * 5) + 4];
  1002. SubMesh.AddToMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, <AbstractMesh>mesh);
  1003. }
  1004. }
  1005. } else if (parsedGeometry.positions && parsedGeometry.normals && parsedGeometry.indices) {
  1006. mesh.setVerticesData(VertexBuffer.PositionKind, parsedGeometry.positions, parsedGeometry.positions._updatable);
  1007. mesh.setVerticesData(VertexBuffer.NormalKind, parsedGeometry.normals, parsedGeometry.normals._updatable);
  1008. if (parsedGeometry.tangents) {
  1009. mesh.setVerticesData(VertexBuffer.TangentKind, parsedGeometry.tangents, parsedGeometry.tangents._updatable);
  1010. }
  1011. if (parsedGeometry.uvs) {
  1012. mesh.setVerticesData(VertexBuffer.UVKind, parsedGeometry.uvs, parsedGeometry.uvs._updatable);
  1013. }
  1014. if (parsedGeometry.uvs2) {
  1015. mesh.setVerticesData(VertexBuffer.UV2Kind, parsedGeometry.uvs2, parsedGeometry.uvs2._updatable);
  1016. }
  1017. if (parsedGeometry.uvs3) {
  1018. mesh.setVerticesData(VertexBuffer.UV3Kind, parsedGeometry.uvs3, parsedGeometry.uvs3._updatable);
  1019. }
  1020. if (parsedGeometry.uvs4) {
  1021. mesh.setVerticesData(VertexBuffer.UV4Kind, parsedGeometry.uvs4, parsedGeometry.uvs4._updatable);
  1022. }
  1023. if (parsedGeometry.uvs5) {
  1024. mesh.setVerticesData(VertexBuffer.UV5Kind, parsedGeometry.uvs5, parsedGeometry.uvs5._updatable);
  1025. }
  1026. if (parsedGeometry.uvs6) {
  1027. mesh.setVerticesData(VertexBuffer.UV6Kind, parsedGeometry.uvs6, parsedGeometry.uvs6._updatable);
  1028. }
  1029. if (parsedGeometry.colors) {
  1030. mesh.setVerticesData(VertexBuffer.ColorKind, Color4.CheckColors4(parsedGeometry.colors, parsedGeometry.positions.length / 3), parsedGeometry.colors._updatable);
  1031. }
  1032. if (parsedGeometry.matricesIndices) {
  1033. if (!parsedGeometry.matricesIndices._isExpanded) {
  1034. var floatIndices = [];
  1035. for (var i = 0; i < parsedGeometry.matricesIndices.length; i++) {
  1036. var matricesIndex = parsedGeometry.matricesIndices[i];
  1037. floatIndices.push(matricesIndex & 0x000000FF);
  1038. floatIndices.push((matricesIndex & 0x0000FF00) >> 8);
  1039. floatIndices.push((matricesIndex & 0x00FF0000) >> 16);
  1040. floatIndices.push(matricesIndex >> 24);
  1041. }
  1042. mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, floatIndices, parsedGeometry.matricesIndices._updatable);
  1043. } else {
  1044. delete parsedGeometry.matricesIndices._isExpanded;
  1045. mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, parsedGeometry.matricesIndices, parsedGeometry.matricesIndices._updatable);
  1046. }
  1047. }
  1048. if (parsedGeometry.matricesIndicesExtra) {
  1049. if (!parsedGeometry.matricesIndicesExtra._isExpanded) {
  1050. var floatIndices = [];
  1051. for (var i = 0; i < parsedGeometry.matricesIndicesExtra.length; i++) {
  1052. var matricesIndex = parsedGeometry.matricesIndicesExtra[i];
  1053. floatIndices.push(matricesIndex & 0x000000FF);
  1054. floatIndices.push((matricesIndex & 0x0000FF00) >> 8);
  1055. floatIndices.push((matricesIndex & 0x00FF0000) >> 16);
  1056. floatIndices.push(matricesIndex >> 24);
  1057. }
  1058. mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, floatIndices, parsedGeometry.matricesIndicesExtra._updatable);
  1059. } else {
  1060. delete parsedGeometry.matricesIndices._isExpanded;
  1061. mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, parsedGeometry.matricesIndicesExtra, parsedGeometry.matricesIndicesExtra._updatable);
  1062. }
  1063. }
  1064. if (parsedGeometry.matricesWeights) {
  1065. Geometry._CleanMatricesWeights(parsedGeometry, mesh);
  1066. mesh.setVerticesData(VertexBuffer.MatricesWeightsKind, parsedGeometry.matricesWeights, parsedGeometry.matricesWeights._updatable);
  1067. }
  1068. if (parsedGeometry.matricesWeightsExtra) {
  1069. mesh.setVerticesData(VertexBuffer.MatricesWeightsExtraKind, parsedGeometry.matricesWeightsExtra, parsedGeometry.matricesWeights._updatable);
  1070. }
  1071. mesh.setIndices(parsedGeometry.indices, null);
  1072. }
  1073. // SubMeshes
  1074. if (parsedGeometry.subMeshes) {
  1075. mesh.subMeshes = [];
  1076. for (var subIndex = 0; subIndex < parsedGeometry.subMeshes.length; subIndex++) {
  1077. var parsedSubMesh = parsedGeometry.subMeshes[subIndex];
  1078. SubMesh.AddToMesh(parsedSubMesh.materialIndex, parsedSubMesh.verticesStart, parsedSubMesh.verticesCount, parsedSubMesh.indexStart, parsedSubMesh.indexCount, <AbstractMesh>mesh);
  1079. }
  1080. }
  1081. // Flat shading
  1082. if (mesh._shouldGenerateFlatShading) {
  1083. mesh.convertToFlatShadedMesh();
  1084. delete mesh._shouldGenerateFlatShading;
  1085. }
  1086. // Update
  1087. mesh.computeWorldMatrix(true);
  1088. scene.onMeshImportedObservable.notifyObservers(<AbstractMesh>mesh);
  1089. }
  1090. private static _CleanMatricesWeights(parsedGeometry: any, mesh: Mesh): void {
  1091. const epsilon: number = 1e-3;
  1092. if (!SceneLoader.CleanBoneMatrixWeights) {
  1093. return;
  1094. }
  1095. let noInfluenceBoneIndex = 0.0;
  1096. if (parsedGeometry.skeletonId > -1) {
  1097. let skeleton = mesh.getScene().getLastSkeletonByID(parsedGeometry.skeletonId);
  1098. if (!skeleton) {
  1099. return;
  1100. }
  1101. noInfluenceBoneIndex = skeleton.bones.length;
  1102. } else {
  1103. return;
  1104. }
  1105. let matricesIndices = (<FloatArray>mesh.getVerticesData(VertexBuffer.MatricesIndicesKind));
  1106. let matricesIndicesExtra = (<FloatArray>mesh.getVerticesData(VertexBuffer.MatricesIndicesExtraKind));
  1107. let matricesWeights = parsedGeometry.matricesWeights;
  1108. let matricesWeightsExtra = parsedGeometry.matricesWeightsExtra;
  1109. let influencers = parsedGeometry.numBoneInfluencer;
  1110. let size = matricesWeights.length;
  1111. for (var i = 0; i < size; i += 4) {
  1112. let weight = 0.0;
  1113. let firstZeroWeight = -1;
  1114. for (var j = 0; j < 4; j++) {
  1115. let w = matricesWeights[i + j];
  1116. weight += w;
  1117. if (w < epsilon && firstZeroWeight < 0) {
  1118. firstZeroWeight = j;
  1119. }
  1120. }
  1121. if (matricesWeightsExtra) {
  1122. for (var j = 0; j < 4; j++) {
  1123. let w = matricesWeightsExtra[i + j];
  1124. weight += w;
  1125. if (w < epsilon && firstZeroWeight < 0) {
  1126. firstZeroWeight = j + 4;
  1127. }
  1128. }
  1129. }
  1130. if (firstZeroWeight < 0 || firstZeroWeight > (influencers - 1)) {
  1131. firstZeroWeight = influencers - 1;
  1132. }
  1133. if (weight > epsilon) {
  1134. let mweight = 1.0 / weight;
  1135. for (var j = 0; j < 4; j++) {
  1136. matricesWeights[i + j] *= mweight;
  1137. }
  1138. if (matricesWeightsExtra) {
  1139. for (var j = 0; j < 4; j++) {
  1140. matricesWeightsExtra[i + j] *= mweight;
  1141. }
  1142. }
  1143. } else {
  1144. if (firstZeroWeight >= 4) {
  1145. matricesWeightsExtra[i + firstZeroWeight - 4] = 1.0 - weight;
  1146. matricesIndicesExtra[i + firstZeroWeight - 4] = noInfluenceBoneIndex;
  1147. } else {
  1148. matricesWeights[i + firstZeroWeight] = 1.0 - weight;
  1149. matricesIndices[i + firstZeroWeight] = noInfluenceBoneIndex;
  1150. }
  1151. }
  1152. }
  1153. mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, matricesIndices);
  1154. if (parsedGeometry.matricesWeightsExtra) {
  1155. mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, matricesIndicesExtra);
  1156. }
  1157. }
  1158. /**
  1159. * Create a new geometry from persisted data (Using .babylon file format)
  1160. * @param parsedVertexData defines the persisted data
  1161. * @param scene defines the hosting scene
  1162. * @param rootUrl defines the root url to use to load assets (like delayed data)
  1163. * @returns the new geometry object
  1164. */
  1165. public static Parse(parsedVertexData: any, scene: Scene, rootUrl: string): Nullable<Geometry> {
  1166. if (scene.getGeometryByID(parsedVertexData.id)) {
  1167. return null; // null since geometry could be something else than a box...
  1168. }
  1169. var geometry = new Geometry(parsedVertexData.id, scene, undefined, parsedVertexData.updatable);
  1170. if (Tags) {
  1171. Tags.AddTagsTo(geometry, parsedVertexData.tags);
  1172. }
  1173. if (parsedVertexData.delayLoadingFile) {
  1174. geometry.delayLoadState = Engine.DELAYLOADSTATE_NOTLOADED;
  1175. geometry.delayLoadingFile = rootUrl + parsedVertexData.delayLoadingFile;
  1176. geometry._boundingInfo = new BoundingInfo(Vector3.FromArray(parsedVertexData.boundingBoxMinimum), Vector3.FromArray(parsedVertexData.boundingBoxMaximum));
  1177. geometry._delayInfo = [];
  1178. if (parsedVertexData.hasUVs) {
  1179. geometry._delayInfo.push(VertexBuffer.UVKind);
  1180. }
  1181. if (parsedVertexData.hasUVs2) {
  1182. geometry._delayInfo.push(VertexBuffer.UV2Kind);
  1183. }
  1184. if (parsedVertexData.hasUVs3) {
  1185. geometry._delayInfo.push(VertexBuffer.UV3Kind);
  1186. }
  1187. if (parsedVertexData.hasUVs4) {
  1188. geometry._delayInfo.push(VertexBuffer.UV4Kind);
  1189. }
  1190. if (parsedVertexData.hasUVs5) {
  1191. geometry._delayInfo.push(VertexBuffer.UV5Kind);
  1192. }
  1193. if (parsedVertexData.hasUVs6) {
  1194. geometry._delayInfo.push(VertexBuffer.UV6Kind);
  1195. }
  1196. if (parsedVertexData.hasColors) {
  1197. geometry._delayInfo.push(VertexBuffer.ColorKind);
  1198. }
  1199. if (parsedVertexData.hasMatricesIndices) {
  1200. geometry._delayInfo.push(VertexBuffer.MatricesIndicesKind);
  1201. }
  1202. if (parsedVertexData.hasMatricesWeights) {
  1203. geometry._delayInfo.push(VertexBuffer.MatricesWeightsKind);
  1204. }
  1205. geometry._delayLoadingFunction = VertexData.ImportVertexData;
  1206. } else {
  1207. VertexData.ImportVertexData(parsedVertexData, geometry);
  1208. }
  1209. scene.pushGeometry(geometry, true);
  1210. return geometry;
  1211. }
  1212. }
  1213. // Primitives
  1214. /// Abstract class
  1215. /**
  1216. * Abstract class used to provide common services for all typed geometries
  1217. * @hidden
  1218. */
  1219. export class _PrimitiveGeometry extends Geometry {
  1220. private _beingRegenerated: boolean;
  1221. /**
  1222. * Creates a new typed geometry
  1223. * @param id defines the unique ID of the geometry
  1224. * @param scene defines the hosting scene
  1225. * @param _canBeRegenerated defines if the geometry supports being regenerated with new parameters (false by default)
  1226. * @param mesh defines the hosting mesh (can be null)
  1227. */
  1228. constructor(id: string, scene: Scene, private _canBeRegenerated: boolean = false, mesh: Nullable<Mesh> = null) {
  1229. super(id, scene, undefined, false, mesh); // updatable = false to be sure not to update vertices
  1230. this._beingRegenerated = true;
  1231. this.regenerate();
  1232. this._beingRegenerated = false;
  1233. }
  1234. /**
  1235. * Gets a value indicating if the geometry supports being regenerated with new parameters (false by default)
  1236. * @returns true if the geometry can be regenerated
  1237. */
  1238. public canBeRegenerated(): boolean {
  1239. return this._canBeRegenerated;
  1240. }
  1241. /**
  1242. * If the geometry supports regeneration, the function will recreates the geometry with updated parameter values
  1243. */
  1244. public regenerate(): void {
  1245. if (!this._canBeRegenerated) {
  1246. return;
  1247. }
  1248. this._beingRegenerated = true;
  1249. this.setAllVerticesData(this._regenerateVertexData(), false);
  1250. this._beingRegenerated = false;
  1251. }
  1252. /**
  1253. * Clone the geometry
  1254. * @param id defines the unique ID of the new geometry
  1255. * @returns the new geometry
  1256. */
  1257. public asNewGeometry(id: string): Geometry {
  1258. return super.copy(id);
  1259. }
  1260. // overrides
  1261. public setAllVerticesData(vertexData: VertexData, updatable?: boolean): void {
  1262. if (!this._beingRegenerated) {
  1263. return;
  1264. }
  1265. super.setAllVerticesData(vertexData, false);
  1266. }
  1267. public setVerticesData(kind: string, data: FloatArray, updatable?: boolean): void {
  1268. if (!this._beingRegenerated) {
  1269. return;
  1270. }
  1271. super.setVerticesData(kind, data, false);
  1272. }
  1273. // to override
  1274. /** @hidden */
  1275. public _regenerateVertexData(): VertexData {
  1276. throw new Error("Abstract method");
  1277. }
  1278. public copy(id: string): Geometry {
  1279. throw new Error("Must be overriden in sub-classes.");
  1280. }
  1281. public serialize(): any {
  1282. var serializationObject = super.serialize();
  1283. serializationObject.canBeRegenerated = this.canBeRegenerated();
  1284. return serializationObject;
  1285. }
  1286. }
  1287. /**
  1288. * Creates a ribbon geometry
  1289. * @description See http://doc.babylonjs.com/how_to/ribbon_tutorial, http://doc.babylonjs.com/resources/maths_make_ribbons
  1290. */
  1291. export class RibbonGeometry extends _PrimitiveGeometry {
  1292. /**
  1293. * Creates a ribbon geometry
  1294. * @param id defines the unique ID of the geometry
  1295. * @param scene defines the hosting scene
  1296. * @param pathArray defines the array of paths to use
  1297. * @param closeArray defines if the last path and the first path must be joined
  1298. * @param closePath defines if the last and first points of each path in your pathArray must be joined
  1299. * @param offset defines the offset between points
  1300. * @param canBeRegenerated defines if the geometry supports being regenerated with new parameters (false by default)
  1301. * @param mesh defines the hosting mesh (can be null)
  1302. * @param side defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1303. */
  1304. constructor(
  1305. id: string, scene: Scene,
  1306. /**
  1307. * Defines the array of paths to use
  1308. */
  1309. public pathArray: Vector3[][],
  1310. /**
  1311. * Defines if the last and first points of each path in your pathArray must be joined
  1312. */
  1313. public closeArray: boolean,
  1314. /**
  1315. * Defines if the last and first points of each path in your pathArray must be joined
  1316. */
  1317. public closePath: boolean,
  1318. /**
  1319. * Defines the offset between points
  1320. */
  1321. public offset: number,
  1322. canBeRegenerated?: boolean,
  1323. mesh?: Mesh,
  1324. /**
  1325. * Defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1326. */
  1327. public side: number = Mesh.DEFAULTSIDE) {
  1328. super(id, scene, canBeRegenerated, mesh);
  1329. }
  1330. /** @hidden */
  1331. public _regenerateVertexData(): VertexData {
  1332. return VertexData.CreateRibbon({ pathArray: this.pathArray, closeArray: this.closeArray, closePath: this.closePath, offset: this.offset, sideOrientation: this.side });
  1333. }
  1334. public copy(id: string): Geometry {
  1335. return new RibbonGeometry(id, this.getScene(), this.pathArray, this.closeArray, this.closePath, this.offset, this.canBeRegenerated(), undefined, this.side);
  1336. }
  1337. }
  1338. /**
  1339. * Creates a box geometry
  1340. * @description see http://doc.babylonjs.com/how_to/set_shapes#box
  1341. */
  1342. export class BoxGeometry extends _PrimitiveGeometry {
  1343. /**
  1344. * Creates a box geometry
  1345. * @param id defines the unique ID of the geometry
  1346. * @param scene defines the hosting scene
  1347. * @param size defines the zise of the box (width, height and depth are the same)
  1348. * @param canBeRegenerated defines if the geometry supports being regenerated with new parameters (false by default)
  1349. * @param mesh defines the hosting mesh (can be null)
  1350. * @param side defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1351. */
  1352. constructor(
  1353. id: string, scene: Scene,
  1354. /**
  1355. * Defines the zise of the box (width, height and depth are the same)
  1356. */
  1357. public size: number,
  1358. canBeRegenerated?: boolean,
  1359. mesh: Nullable<Mesh> = null,
  1360. /**
  1361. * Defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1362. */
  1363. public side: number = Mesh.DEFAULTSIDE) {
  1364. super(id, scene, canBeRegenerated, mesh);
  1365. }
  1366. /** @hidden */
  1367. public _regenerateVertexData(): VertexData {
  1368. return VertexData.CreateBox({ size: this.size, sideOrientation: this.side });
  1369. }
  1370. public copy(id: string): Geometry {
  1371. return new BoxGeometry(id, this.getScene(), this.size, this.canBeRegenerated(), undefined, this.side);
  1372. }
  1373. public serialize(): any {
  1374. var serializationObject = super.serialize();
  1375. serializationObject.size = this.size;
  1376. return serializationObject;
  1377. }
  1378. public static Parse(parsedBox: any, scene: Scene): Nullable<BoxGeometry> {
  1379. if (scene.getGeometryByID(parsedBox.id)) {
  1380. return null; // null since geometry could be something else than a box...
  1381. }
  1382. var box = new BoxGeometry(parsedBox.id, scene, parsedBox.size, parsedBox.canBeRegenerated, null);
  1383. if (Tags) {
  1384. Tags.AddTagsTo(box, parsedBox.tags);
  1385. }
  1386. scene.pushGeometry(box, true);
  1387. return box;
  1388. }
  1389. }
  1390. /**
  1391. * Creates a sphere geometry
  1392. * @description see http://doc.babylonjs.com/how_to/set_shapes#sphere
  1393. */
  1394. export class SphereGeometry extends _PrimitiveGeometry {
  1395. /**
  1396. * Create a new sphere geometry
  1397. * @param id defines the unique ID of the geometry
  1398. * @param scene defines the hosting scene
  1399. * @param segments defines the number of segments to use to create the sphere
  1400. * @param diameter defines the diameter of the sphere
  1401. * @param canBeRegenerated defines if the geometry supports being regenerated with new parameters (false by default)
  1402. * @param mesh defines the hosting mesh (can be null)
  1403. * @param side defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1404. */
  1405. constructor(
  1406. id: string, scene: Scene,
  1407. /**
  1408. * Defines the number of segments to use to create the sphere
  1409. */
  1410. public segments: number,
  1411. /**
  1412. * Defines the diameter of the sphere
  1413. */
  1414. public diameter: number,
  1415. canBeRegenerated?: boolean,
  1416. mesh: Nullable<Mesh> = null,
  1417. /**
  1418. * Defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1419. */
  1420. public side: number = Mesh.DEFAULTSIDE) {
  1421. super(id, scene, canBeRegenerated, mesh);
  1422. }
  1423. /** @hidden */
  1424. public _regenerateVertexData(): VertexData {
  1425. return VertexData.CreateSphere({ segments: this.segments, diameter: this.diameter, sideOrientation: this.side });
  1426. }
  1427. public copy(id: string): Geometry {
  1428. return new SphereGeometry(id, this.getScene(), this.segments, this.diameter, this.canBeRegenerated(), null, this.side);
  1429. }
  1430. public serialize(): any {
  1431. var serializationObject = super.serialize();
  1432. serializationObject.segments = this.segments;
  1433. serializationObject.diameter = this.diameter;
  1434. return serializationObject;
  1435. }
  1436. public static Parse(parsedSphere: any, scene: Scene): Nullable<SphereGeometry> {
  1437. if (scene.getGeometryByID(parsedSphere.id)) {
  1438. return null; // null since geometry could be something else than a sphere...
  1439. }
  1440. var sphere = new SphereGeometry(parsedSphere.id, scene, parsedSphere.segments, parsedSphere.diameter, parsedSphere.canBeRegenerated, null);
  1441. if (Tags) {
  1442. Tags.AddTagsTo(sphere, parsedSphere.tags);
  1443. }
  1444. scene.pushGeometry(sphere, true);
  1445. return sphere;
  1446. }
  1447. }
  1448. /**
  1449. * Creates a disc geometry
  1450. * @description see http://doc.babylonjs.com/how_to/set_shapes#disc-or-regular-polygon
  1451. */
  1452. export class DiscGeometry extends _PrimitiveGeometry {
  1453. /**
  1454. * Creates a new disc geometry
  1455. * @param id defines the unique ID of the geometry
  1456. * @param scene defines the hosting scene
  1457. * @param radius defines the radius of the disc
  1458. * @param tessellation defines the tesselation factor to apply to the disc
  1459. * @param canBeRegenerated defines if the geometry supports being regenerated with new parameters (false by default)
  1460. * @param mesh defines the hosting mesh (can be null)
  1461. * @param side defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1462. */
  1463. constructor(
  1464. id: string, scene: Scene,
  1465. /**
  1466. * Defines the radius of the disc
  1467. */
  1468. public radius: number,
  1469. /**
  1470. * Defines the tesselation factor to apply to the disc
  1471. */
  1472. public tessellation: number,
  1473. canBeRegenerated?: boolean,
  1474. mesh: Nullable<Mesh> = null,
  1475. /**
  1476. * Defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1477. */
  1478. public side: number = Mesh.DEFAULTSIDE) {
  1479. super(id, scene, canBeRegenerated, mesh);
  1480. }
  1481. /** @hidden */
  1482. public _regenerateVertexData(): VertexData {
  1483. return VertexData.CreateDisc({ radius: this.radius, tessellation: this.tessellation, sideOrientation: this.side });
  1484. }
  1485. public copy(id: string): Geometry {
  1486. return new DiscGeometry(id, this.getScene(), this.radius, this.tessellation, this.canBeRegenerated(), null, this.side);
  1487. }
  1488. }
  1489. /**
  1490. * Creates a new cylinder geometry
  1491. * @description see http://doc.babylonjs.com/how_to/set_shapes#cylinder-or-cone
  1492. */
  1493. export class CylinderGeometry extends _PrimitiveGeometry {
  1494. /**
  1495. * Creates a new cylinder geometry
  1496. * @param id defines the unique ID of the geometry
  1497. * @param scene defines the hosting scene
  1498. * @param height defines the height of the cylinder
  1499. * @param diameterTop defines the diameter of the cylinder's top cap
  1500. * @param diameterBottom defines the diameter of the cylinder's bottom cap
  1501. * @param tessellation defines the tessellation factor to apply to the cylinder (number of radial sides)
  1502. * @param subdivisions defines the number of subdivisions to apply to the cylinder (number of rings) (1 by default)
  1503. * @param canBeRegenerated defines if the geometry supports being regenerated with new parameters (false by default)
  1504. * @param mesh defines the hosting mesh (can be null)
  1505. * @param side defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1506. */
  1507. constructor(
  1508. id: string, scene: Scene,
  1509. /**
  1510. * Defines the height of the cylinder
  1511. */
  1512. public height: number,
  1513. /**
  1514. * Defines the diameter of the cylinder's top cap
  1515. */
  1516. public diameterTop: number,
  1517. /**
  1518. * Defines the diameter of the cylinder's bottom cap
  1519. */
  1520. public diameterBottom: number,
  1521. /**
  1522. * Defines the tessellation factor to apply to the cylinder
  1523. */
  1524. public tessellation: number,
  1525. /**
  1526. * Defines the number of subdivisions to apply to the cylinder (1 by default)
  1527. */
  1528. public subdivisions: number = 1,
  1529. canBeRegenerated?: boolean, mesh:
  1530. Nullable<Mesh> = null,
  1531. /**
  1532. * Defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1533. */
  1534. public side: number = Mesh.DEFAULTSIDE) {
  1535. super(id, scene, canBeRegenerated, mesh);
  1536. }
  1537. /** @hidden */
  1538. public _regenerateVertexData(): VertexData {
  1539. return VertexData.CreateCylinder({ height: this.height, diameterTop: this.diameterTop, diameterBottom: this.diameterBottom, tessellation: this.tessellation, subdivisions: this.subdivisions, sideOrientation: this.side });
  1540. }
  1541. public copy(id: string): Geometry {
  1542. return new CylinderGeometry(id, this.getScene(), this.height, this.diameterTop, this.diameterBottom, this.tessellation, this.subdivisions, this.canBeRegenerated(), null, this.side);
  1543. }
  1544. public serialize(): any {
  1545. var serializationObject = super.serialize();
  1546. serializationObject.height = this.height;
  1547. serializationObject.diameterTop = this.diameterTop;
  1548. serializationObject.diameterBottom = this.diameterBottom;
  1549. serializationObject.tessellation = this.tessellation;
  1550. return serializationObject;
  1551. }
  1552. public static Parse(parsedCylinder: any, scene: Scene): Nullable<CylinderGeometry> {
  1553. if (scene.getGeometryByID(parsedCylinder.id)) {
  1554. return null; // null since geometry could be something else than a cylinder...
  1555. }
  1556. var cylinder = new CylinderGeometry(parsedCylinder.id, scene, parsedCylinder.height, parsedCylinder.diameterTop, parsedCylinder.diameterBottom, parsedCylinder.tessellation, parsedCylinder.subdivisions, parsedCylinder.canBeRegenerated, null);
  1557. if (Tags) {
  1558. Tags.AddTagsTo(cylinder, parsedCylinder.tags);
  1559. }
  1560. scene.pushGeometry(cylinder, true);
  1561. return cylinder;
  1562. }
  1563. }
  1564. /**
  1565. * Creates a new torus geometry
  1566. * @description see http://doc.babylonjs.com/how_to/set_shapes#torus
  1567. */
  1568. export class TorusGeometry extends _PrimitiveGeometry {
  1569. /**
  1570. * Creates a new torus geometry
  1571. * @param id defines the unique ID of the geometry
  1572. * @param scene defines the hosting scene
  1573. * @param diameter defines the diameter of the torus
  1574. * @param thickness defines the thickness of the torus (ie. internal diameter)
  1575. * @param tessellation defines the tesselation factor to apply to the torus (number of segments along the circle)
  1576. * @param canBeRegenerated defines if the geometry supports being regenerated with new parameters (false by default)
  1577. * @param mesh defines the hosting mesh (can be null)
  1578. * @param side defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1579. */
  1580. constructor(
  1581. id: string, scene: Scene,
  1582. /**
  1583. * Defines the diameter of the torus
  1584. */
  1585. public diameter: number,
  1586. /**
  1587. * Defines the thickness of the torus (ie. internal diameter)
  1588. */
  1589. public thickness: number,
  1590. /**
  1591. * Defines the tesselation factor to apply to the torus
  1592. */
  1593. public tessellation: number,
  1594. canBeRegenerated?: boolean,
  1595. mesh: Nullable<Mesh> = null,
  1596. /**
  1597. * Defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1598. */
  1599. public side: number = Mesh.DEFAULTSIDE) {
  1600. super(id, scene, canBeRegenerated, mesh);
  1601. }
  1602. /** @hidden */
  1603. public _regenerateVertexData(): VertexData {
  1604. return VertexData.CreateTorus({ diameter: this.diameter, thickness: this.thickness, tessellation: this.tessellation, sideOrientation: this.side });
  1605. }
  1606. public copy(id: string): Geometry {
  1607. return new TorusGeometry(id, this.getScene(), this.diameter, this.thickness, this.tessellation, this.canBeRegenerated(), null, this.side);
  1608. }
  1609. public serialize(): any {
  1610. var serializationObject = super.serialize();
  1611. serializationObject.diameter = this.diameter;
  1612. serializationObject.thickness = this.thickness;
  1613. serializationObject.tessellation = this.tessellation;
  1614. return serializationObject;
  1615. }
  1616. public static Parse(parsedTorus: any, scene: Scene): Nullable<TorusGeometry> {
  1617. if (scene.getGeometryByID(parsedTorus.id)) {
  1618. return null; // null since geometry could be something else than a torus...
  1619. }
  1620. var torus = new TorusGeometry(parsedTorus.id, scene, parsedTorus.diameter, parsedTorus.thickness, parsedTorus.tessellation, parsedTorus.canBeRegenerated, null);
  1621. if (Tags) {
  1622. Tags.AddTagsTo(torus, parsedTorus.tags);
  1623. }
  1624. scene.pushGeometry(torus, true);
  1625. return torus;
  1626. }
  1627. }
  1628. /**
  1629. * Creates a new ground geometry
  1630. * @description see http://doc.babylonjs.com/how_to/set_shapes#ground
  1631. */
  1632. export class GroundGeometry extends _PrimitiveGeometry {
  1633. /**
  1634. * Creates a new ground geometry
  1635. * @param id defines the unique ID of the geometry
  1636. * @param scene defines the hosting scene
  1637. * @param width defines the width of the ground
  1638. * @param height defines the height of the ground
  1639. * @param subdivisions defines the subdivisions to apply to the ground
  1640. * @param canBeRegenerated defines if the geometry supports being regenerated with new parameters (false by default)
  1641. * @param mesh defines the hosting mesh (can be null)
  1642. */
  1643. constructor(
  1644. id: string, scene: Scene,
  1645. /**
  1646. * Defines the width of the ground
  1647. */
  1648. public width: number,
  1649. /**
  1650. * Defines the height of the ground
  1651. */
  1652. public height: number,
  1653. /**
  1654. * Defines the subdivisions to apply to the ground
  1655. */
  1656. public subdivisions: number,
  1657. canBeRegenerated?: boolean,
  1658. mesh: Nullable<Mesh> = null) {
  1659. super(id, scene, canBeRegenerated, mesh);
  1660. }
  1661. /** @hidden */
  1662. public _regenerateVertexData(): VertexData {
  1663. return VertexData.CreateGround({ width: this.width, height: this.height, subdivisions: this.subdivisions });
  1664. }
  1665. public copy(id: string): Geometry {
  1666. return new GroundGeometry(id, this.getScene(), this.width, this.height, this.subdivisions, this.canBeRegenerated(), null);
  1667. }
  1668. public serialize(): any {
  1669. var serializationObject = super.serialize();
  1670. serializationObject.width = this.width;
  1671. serializationObject.height = this.height;
  1672. serializationObject.subdivisions = this.subdivisions;
  1673. return serializationObject;
  1674. }
  1675. public static Parse(parsedGround: any, scene: Scene): Nullable<GroundGeometry> {
  1676. if (scene.getGeometryByID(parsedGround.id)) {
  1677. return null; // null since geometry could be something else than a ground...
  1678. }
  1679. var ground = new GroundGeometry(parsedGround.id, scene, parsedGround.width, parsedGround.height, parsedGround.subdivisions, parsedGround.canBeRegenerated, null);
  1680. if (Tags) {
  1681. Tags.AddTagsTo(ground, parsedGround.tags);
  1682. }
  1683. scene.pushGeometry(ground, true);
  1684. return ground;
  1685. }
  1686. }
  1687. /**
  1688. * Creates a tiled ground geometry
  1689. * @description see http://doc.babylonjs.com/how_to/set_shapes#tiled-ground
  1690. */
  1691. export class TiledGroundGeometry extends _PrimitiveGeometry {
  1692. /**
  1693. * Creates a tiled ground geometry
  1694. * @param id defines the unique ID of the geometry
  1695. * @param scene defines the hosting scene
  1696. * @param xmin defines the minimum value on X axis
  1697. * @param zmin defines the minimum value on Z axis
  1698. * @param xmax defines the maximum value on X axis
  1699. * @param zmax defines the maximum value on Z axis
  1700. * @param subdivisions defines the subdivisions to apply to the ground (number of subdivisions (tiles) on the height and the width of the map)
  1701. * @param precision defines the precision to use when computing the tiles
  1702. * @param canBeRegenerated defines if the geometry supports being regenerated with new parameters (false by default)
  1703. * @param mesh defines the hosting mesh (can be null)
  1704. */
  1705. constructor(
  1706. id: string, scene: Scene,
  1707. /**
  1708. * Defines the minimum value on X axis
  1709. */
  1710. public xmin: number,
  1711. /**
  1712. * Defines the minimum value on Z axis
  1713. */
  1714. public zmin: number,
  1715. /**
  1716. * Defines the maximum value on X axis
  1717. */
  1718. public xmax: number,
  1719. /**
  1720. * Defines the maximum value on Z axis
  1721. */
  1722. public zmax: number,
  1723. /**
  1724. * Defines the subdivisions to apply to the ground
  1725. */
  1726. public subdivisions: { w: number; h: number; },
  1727. /**
  1728. * Defines the precision to use when computing the tiles
  1729. */
  1730. public precision: { w: number; h: number; },
  1731. canBeRegenerated?: boolean,
  1732. mesh: Nullable<Mesh> = null) {
  1733. super(id, scene, canBeRegenerated, mesh);
  1734. }
  1735. /** @hidden */
  1736. public _regenerateVertexData(): VertexData {
  1737. return VertexData.CreateTiledGround({ xmin: this.xmin, zmin: this.zmin, xmax: this.xmax, zmax: this.zmax, subdivisions: this.subdivisions, precision: this.precision });
  1738. }
  1739. public copy(id: string): Geometry {
  1740. return new TiledGroundGeometry(id, this.getScene(), this.xmin, this.zmin, this.xmax, this.zmax, this.subdivisions, this.precision, this.canBeRegenerated(), null);
  1741. }
  1742. }
  1743. /**
  1744. * Creates a plane geometry
  1745. * @description see http://doc.babylonjs.com/how_to/set_shapes#plane
  1746. */
  1747. export class PlaneGeometry extends _PrimitiveGeometry {
  1748. /**
  1749. * Creates a plane geometry
  1750. * @param id defines the unique ID of the geometry
  1751. * @param scene defines the hosting scene
  1752. * @param size defines the size of the plane (width === height)
  1753. * @param canBeRegenerated defines if the geometry supports being regenerated with new parameters (false by default)
  1754. * @param mesh defines the hosting mesh (can be null)
  1755. * @param side defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1756. */
  1757. constructor(
  1758. id: string, scene: Scene,
  1759. /**
  1760. * Defines the size of the plane (width === height)
  1761. */
  1762. public size: number,
  1763. canBeRegenerated?: boolean,
  1764. mesh: Nullable<Mesh> = null,
  1765. /**
  1766. * Defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1767. */
  1768. public side: number = Mesh.DEFAULTSIDE) {
  1769. super(id, scene, canBeRegenerated, mesh);
  1770. }
  1771. /** @hidden */
  1772. public _regenerateVertexData(): VertexData {
  1773. return VertexData.CreatePlane({ size: this.size, sideOrientation: this.side });
  1774. }
  1775. public copy(id: string): Geometry {
  1776. return new PlaneGeometry(id, this.getScene(), this.size, this.canBeRegenerated(), null, this.side);
  1777. }
  1778. public serialize(): any {
  1779. var serializationObject = super.serialize();
  1780. serializationObject.size = this.size;
  1781. return serializationObject;
  1782. }
  1783. public static Parse(parsedPlane: any, scene: Scene): Nullable<PlaneGeometry> {
  1784. if (scene.getGeometryByID(parsedPlane.id)) {
  1785. return null; // null since geometry could be something else than a ground...
  1786. }
  1787. var plane = new PlaneGeometry(parsedPlane.id, scene, parsedPlane.size, parsedPlane.canBeRegenerated, null);
  1788. if (Tags) {
  1789. Tags.AddTagsTo(plane, parsedPlane.tags);
  1790. }
  1791. scene.pushGeometry(plane, true);
  1792. return plane;
  1793. }
  1794. }
  1795. /**
  1796. * Creates a torus knot geometry
  1797. * @description see http://doc.babylonjs.com/how_to/set_shapes#torus-knot
  1798. */
  1799. export class TorusKnotGeometry extends _PrimitiveGeometry {
  1800. /**
  1801. * Creates a torus knot geometry
  1802. * @param id defines the unique ID of the geometry
  1803. * @param scene defines the hosting scene
  1804. * @param radius defines the radius of the torus knot
  1805. * @param tube defines the thickness of the torus knot tube
  1806. * @param radialSegments defines the number of radial segments
  1807. * @param tubularSegments defines the number of tubular segments
  1808. * @param p defines the first number of windings
  1809. * @param q defines the second number of windings
  1810. * @param canBeRegenerated defines if the geometry supports being regenerated with new parameters (false by default)
  1811. * @param mesh defines the hosting mesh (can be null)
  1812. * @param side defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1813. */
  1814. constructor(
  1815. id: string, scene: Scene,
  1816. /**
  1817. * Defines the radius of the torus knot
  1818. */
  1819. public radius: number,
  1820. /**
  1821. * Defines the thickness of the torus knot tube
  1822. */
  1823. public tube: number,
  1824. /**
  1825. * Defines the number of radial segments
  1826. */
  1827. public radialSegments: number,
  1828. /**
  1829. * Defines the number of tubular segments
  1830. */
  1831. public tubularSegments: number,
  1832. /**
  1833. * Defines the first number of windings
  1834. */
  1835. public p: number,
  1836. /**
  1837. * Defines the second number of windings
  1838. */
  1839. public q: number,
  1840. canBeRegenerated?: boolean,
  1841. mesh: Nullable<Mesh> = null,
  1842. /**
  1843. * Defines if the created geometry is double sided or not (default is BABYLON.Mesh.DEFAULTSIDE)
  1844. */
  1845. public side: number = Mesh.DEFAULTSIDE) {
  1846. super(id, scene, canBeRegenerated, mesh);
  1847. }
  1848. /** @hidden */
  1849. public _regenerateVertexData(): VertexData {
  1850. return VertexData.CreateTorusKnot({ radius: this.radius, tube: this.tube, radialSegments: this.radialSegments, tubularSegments: this.tubularSegments, p: this.p, q: this.q, sideOrientation: this.side });
  1851. }
  1852. public copy(id: string): Geometry {
  1853. return new TorusKnotGeometry(id, this.getScene(), this.radius, this.tube, this.radialSegments, this.tubularSegments, this.p, this.q, this.canBeRegenerated(), null, this.side);
  1854. }
  1855. public serialize(): any {
  1856. var serializationObject = super.serialize();
  1857. serializationObject.radius = this.radius;
  1858. serializationObject.tube = this.tube;
  1859. serializationObject.radialSegments = this.radialSegments;
  1860. serializationObject.tubularSegments = this.tubularSegments;
  1861. serializationObject.p = this.p;
  1862. serializationObject.q = this.q;
  1863. return serializationObject;
  1864. };
  1865. public static Parse(parsedTorusKnot: any, scene: Scene): Nullable<TorusKnotGeometry> {
  1866. if (scene.getGeometryByID(parsedTorusKnot.id)) {
  1867. return null; // null since geometry could be something else than a ground...
  1868. }
  1869. var torusKnot = new TorusKnotGeometry(parsedTorusKnot.id, scene, parsedTorusKnot.radius, parsedTorusKnot.tube, parsedTorusKnot.radialSegments, parsedTorusKnot.tubularSegments, parsedTorusKnot.p, parsedTorusKnot.q, parsedTorusKnot.canBeRegenerated, null);
  1870. if (Tags) {
  1871. Tags.AddTagsTo(torusKnot, parsedTorusKnot.tags);
  1872. }
  1873. scene.pushGeometry(torusKnot, true);
  1874. return torusKnot;
  1875. }
  1876. }
  1877. //}
  1878. }