babylon.renderablePrim2d.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  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 __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  7. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  8. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  9. else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  10. return c > 3 && r && Object.defineProperty(target, key, r), r;
  11. };
  12. var BABYLON;
  13. (function (BABYLON) {
  14. var InstanceClassInfo = (function () {
  15. function InstanceClassInfo(base) {
  16. this._baseInfo = base;
  17. this._nextOffset = new BABYLON.StringDictionary();
  18. this._attributes = new Array();
  19. }
  20. InstanceClassInfo.prototype.mapProperty = function (propInfo, push) {
  21. var curOff = this._nextOffset.getOrAdd(InstanceClassInfo._CurCategories, 0);
  22. propInfo.instanceOffset.add(InstanceClassInfo._CurCategories, this._getBaseOffset(InstanceClassInfo._CurCategories) + curOff);
  23. //console.log(`[${InstanceClassInfo._CurCategories}] New PropInfo. Category: ${propInfo.category}, Name: ${propInfo.attributeName}, Offset: ${propInfo.instanceOffset.get(InstanceClassInfo._CurCategories)}, Size: ${propInfo.size / 4}`);
  24. this._nextOffset.set(InstanceClassInfo._CurCategories, curOff + (propInfo.size / 4));
  25. if (push) {
  26. this._attributes.push(propInfo);
  27. }
  28. };
  29. InstanceClassInfo.prototype.getInstancingAttributeInfos = function (effect, categories) {
  30. var catInline = categories.join(";");
  31. var res = new Array();
  32. var curInfo = this;
  33. while (curInfo) {
  34. for (var _i = 0, _a = curInfo._attributes; _i < _a.length; _i++) {
  35. var attrib = _a[_i];
  36. // Only map if there's no category assigned to the instance data or if there's a category and it's in the given list
  37. if (!attrib.category || categories.indexOf(attrib.category) !== -1) {
  38. var index = effect.getAttributeLocationByName(attrib.attributeName);
  39. var iai = new BABYLON.InstancingAttributeInfo();
  40. iai.index = index;
  41. iai.attributeSize = attrib.size / 4; // attrib.size is in byte and we need to store in "component" (i.e float is 1, vec3 is 3)
  42. iai.offset = attrib.instanceOffset.get(catInline) * 4; // attrib.instanceOffset is in float, iai.offset must be in bytes
  43. iai.attributeName = attrib.attributeName;
  44. res.push(iai);
  45. }
  46. }
  47. curInfo = curInfo._baseInfo;
  48. }
  49. return res;
  50. };
  51. InstanceClassInfo.prototype.getShaderAttributes = function (categories) {
  52. var res = new Array();
  53. var curInfo = this;
  54. while (curInfo) {
  55. for (var _i = 0, _a = curInfo._attributes; _i < _a.length; _i++) {
  56. var attrib = _a[_i];
  57. // Only map if there's no category assigned to the instance data or if there's a category and it's in the given list
  58. if (!attrib.category || categories.indexOf(attrib.category) !== -1) {
  59. res.push(attrib.attributeName);
  60. }
  61. }
  62. curInfo = curInfo._baseInfo;
  63. }
  64. return res;
  65. };
  66. InstanceClassInfo.prototype._getBaseOffset = function (categories) {
  67. var curOffset = 0;
  68. var curBase = this._baseInfo;
  69. while (curBase) {
  70. curOffset += curBase._nextOffset.getOrAdd(categories, 0);
  71. curBase = curBase._baseInfo;
  72. }
  73. return curOffset;
  74. };
  75. return InstanceClassInfo;
  76. })();
  77. BABYLON.InstanceClassInfo = InstanceClassInfo;
  78. var InstancePropInfo = (function () {
  79. //uniformLocation: WebGLUniformLocation;
  80. function InstancePropInfo() {
  81. this.instanceOffset = new BABYLON.StringDictionary();
  82. }
  83. InstancePropInfo.prototype.setSize = function (val) {
  84. if (val instanceof BABYLON.Vector2) {
  85. this.size = 8;
  86. this.dataType = 0 /* Vector2 */;
  87. return;
  88. }
  89. if (val instanceof BABYLON.Vector3) {
  90. this.size = 12;
  91. this.dataType = 1 /* Vector3 */;
  92. return;
  93. }
  94. if (val instanceof BABYLON.Vector4) {
  95. this.size = 16;
  96. this.dataType = 2 /* Vector4 */;
  97. return;
  98. }
  99. if (val instanceof BABYLON.Matrix) {
  100. throw new Error("Matrix type is not supported by WebGL Instance Buffer, you have to use four Vector4 properties instead");
  101. }
  102. if (typeof (val) === "number") {
  103. this.size = 4;
  104. this.dataType = 4 /* float */;
  105. return;
  106. }
  107. if (val instanceof BABYLON.Color3) {
  108. this.size = 12;
  109. this.dataType = 5 /* Color3 */;
  110. return;
  111. }
  112. if (val instanceof BABYLON.Color4) {
  113. this.size = 16;
  114. this.dataType = 6 /* Color4 */;
  115. return;
  116. }
  117. return;
  118. };
  119. InstancePropInfo.prototype.writeData = function (array, offset, val) {
  120. switch (this.dataType) {
  121. case 0 /* Vector2 */:
  122. {
  123. var v = val;
  124. array[offset + 0] = v.x;
  125. array[offset + 1] = v.y;
  126. break;
  127. }
  128. case 1 /* Vector3 */:
  129. {
  130. var v = val;
  131. array[offset + 0] = v.x;
  132. array[offset + 1] = v.y;
  133. array[offset + 2] = v.z;
  134. break;
  135. }
  136. case 2 /* Vector4 */:
  137. {
  138. var v = val;
  139. array[offset + 0] = v.x;
  140. array[offset + 1] = v.y;
  141. array[offset + 2] = v.z;
  142. array[offset + 3] = v.w;
  143. break;
  144. }
  145. case 5 /* Color3 */:
  146. {
  147. var v = val;
  148. array[offset + 0] = v.r;
  149. array[offset + 1] = v.g;
  150. array[offset + 2] = v.b;
  151. break;
  152. }
  153. case 6 /* Color4 */:
  154. {
  155. var v = val;
  156. array[offset + 0] = v.r;
  157. array[offset + 1] = v.g;
  158. array[offset + 2] = v.b;
  159. array[offset + 3] = v.a;
  160. break;
  161. }
  162. case 4 /* float */:
  163. {
  164. var v = val;
  165. array[offset] = v;
  166. break;
  167. }
  168. case 3 /* Matrix */:
  169. {
  170. var v = val;
  171. for (var i = 0; i < 16; i++) {
  172. array[offset + i] = v.m[i];
  173. }
  174. break;
  175. }
  176. }
  177. };
  178. return InstancePropInfo;
  179. })();
  180. BABYLON.InstancePropInfo = InstancePropInfo;
  181. function instanceData(category, shaderAttributeName) {
  182. return function (target, propName, descriptor) {
  183. var dic = BABYLON.ClassTreeInfo.getOrRegister(target, function (base) { return new InstanceClassInfo(base); });
  184. var node = dic.getLevelOf(target);
  185. var instanceDataName = propName;
  186. shaderAttributeName = shaderAttributeName || instanceDataName;
  187. var info = node.levelContent.get(instanceDataName);
  188. if (info) {
  189. throw new Error("The ID " + instanceDataName + " is already taken by another instance data");
  190. }
  191. info = new InstancePropInfo();
  192. info.attributeName = shaderAttributeName;
  193. info.category = category || null;
  194. node.levelContent.add(instanceDataName, info);
  195. descriptor.get = function () {
  196. return null;
  197. };
  198. descriptor.set = function (val) {
  199. if (!info.size) {
  200. info.setSize(val);
  201. node.classContent.mapProperty(info, true);
  202. }
  203. else if (!info.instanceOffset.contains(InstanceClassInfo._CurCategories)) {
  204. node.classContent.mapProperty(info, false);
  205. }
  206. var obj = this;
  207. if (obj.dataBuffer && obj.dataElements) {
  208. var offset = obj.dataElements[obj.curElement].offset + info.instanceOffset.get(InstanceClassInfo._CurCategories);
  209. info.writeData(obj.dataBuffer.buffer, offset, val);
  210. }
  211. };
  212. };
  213. }
  214. BABYLON.instanceData = instanceData;
  215. var InstanceDataBase = (function () {
  216. function InstanceDataBase(partId, dataElementCount) {
  217. this.id = partId;
  218. this.curElement = 0;
  219. this.dataElementCount = dataElementCount;
  220. }
  221. Object.defineProperty(InstanceDataBase.prototype, "zBias", {
  222. get: function () {
  223. return null;
  224. },
  225. enumerable: true,
  226. configurable: true
  227. });
  228. Object.defineProperty(InstanceDataBase.prototype, "transformX", {
  229. get: function () {
  230. return null;
  231. },
  232. enumerable: true,
  233. configurable: true
  234. });
  235. Object.defineProperty(InstanceDataBase.prototype, "transformY", {
  236. get: function () {
  237. return null;
  238. },
  239. enumerable: true,
  240. configurable: true
  241. });
  242. Object.defineProperty(InstanceDataBase.prototype, "origin", {
  243. get: function () {
  244. return null;
  245. },
  246. enumerable: true,
  247. configurable: true
  248. });
  249. InstanceDataBase.prototype.getClassTreeInfo = function () {
  250. if (!this.typeInfo) {
  251. this.typeInfo = BABYLON.ClassTreeInfo.get(Object.getPrototypeOf(this));
  252. }
  253. return this.typeInfo;
  254. };
  255. InstanceDataBase.prototype.allocElements = function () {
  256. if (!this.dataBuffer) {
  257. return;
  258. }
  259. var res = new Array(this.dataElementCount);
  260. for (var i = 0; i < this.dataElementCount; i++) {
  261. res[i] = this.dataBuffer.allocElement();
  262. }
  263. this.dataElements = res;
  264. };
  265. InstanceDataBase.prototype.freeElements = function () {
  266. if (!this.dataElements) {
  267. return;
  268. }
  269. for (var _i = 0, _a = this.dataElements; _i < _a.length; _i++) {
  270. var ei = _a[_i];
  271. this.dataBuffer.freeElement(ei);
  272. }
  273. this.dataElements = null;
  274. };
  275. Object.defineProperty(InstanceDataBase.prototype, "dataElementCount", {
  276. get: function () {
  277. return this._dataElementCount;
  278. },
  279. set: function (value) {
  280. if (value === this._dataElementCount) {
  281. return;
  282. }
  283. this.freeElements();
  284. this._dataElementCount = value;
  285. this.allocElements();
  286. },
  287. enumerable: true,
  288. configurable: true
  289. });
  290. __decorate([
  291. instanceData()
  292. ], InstanceDataBase.prototype, "zBias", null);
  293. __decorate([
  294. instanceData()
  295. ], InstanceDataBase.prototype, "transformX", null);
  296. __decorate([
  297. instanceData()
  298. ], InstanceDataBase.prototype, "transformY", null);
  299. __decorate([
  300. instanceData()
  301. ], InstanceDataBase.prototype, "origin", null);
  302. return InstanceDataBase;
  303. })();
  304. BABYLON.InstanceDataBase = InstanceDataBase;
  305. var RenderablePrim2D = (function (_super) {
  306. __extends(RenderablePrim2D, _super);
  307. function RenderablePrim2D() {
  308. _super.apply(this, arguments);
  309. }
  310. Object.defineProperty(RenderablePrim2D.prototype, "isTransparent", {
  311. get: function () {
  312. return this._isTransparent;
  313. },
  314. set: function (value) {
  315. this._isTransparent = value;
  316. },
  317. enumerable: true,
  318. configurable: true
  319. });
  320. RenderablePrim2D.prototype.setupRenderablePrim2D = function (owner, parent, id, position, isVisible) {
  321. this.setupPrim2DBase(owner, parent, id, position);
  322. this._isTransparent = false;
  323. };
  324. RenderablePrim2D.prototype.dispose = function () {
  325. if (!_super.prototype.dispose.call(this)) {
  326. return false;
  327. }
  328. if (this._modelRenderInstanceID) {
  329. this._modelRenderCache.removeInstanceData(this._modelRenderInstanceID);
  330. this._modelRenderInstanceID = null;
  331. }
  332. if (this._modelRenderCache) {
  333. this._modelRenderCache.dispose();
  334. this._modelRenderCache = null;
  335. }
  336. if (this._instanceDataParts) {
  337. this._instanceDataParts.forEach(function (p) {
  338. p.freeElements();
  339. });
  340. this._instanceDataParts = null;
  341. }
  342. return true;
  343. };
  344. RenderablePrim2D.prototype._prepareRenderPre = function (context) {
  345. var _this = this;
  346. _super.prototype._prepareRenderPre.call(this, context);
  347. // If the model changed and we have already an instance, we must remove this instance from the obsolete model
  348. if (this._modelDirty && this._modelRenderInstanceID) {
  349. this._modelRenderCache.removeInstanceData(this._modelRenderInstanceID);
  350. this._modelRenderInstanceID = null;
  351. }
  352. // Need to create the model?
  353. var setupModelRenderCache = false;
  354. if (!this._modelRenderCache || this._modelDirty) {
  355. if (this._modelRenderCache) {
  356. this._modelRenderCache.dispose();
  357. }
  358. this._modelRenderCache = this.owner._engineData.GetOrAddModelCache(this.modelKey, function (key) {
  359. var mrc = _this.createModelRenderCache(key, _this.isTransparent);
  360. setupModelRenderCache = true;
  361. return mrc;
  362. });
  363. this._modelDirty = false;
  364. // if this is still false it means the MRC already exists, so we add a reference to it
  365. if (!setupModelRenderCache) {
  366. this._modelRenderCache.addRef();
  367. }
  368. }
  369. var gii;
  370. var newInstance = false;
  371. // Need to create the instance data parts?
  372. if (!this._modelRenderInstanceID) {
  373. // Yes, flag it for later, more processing will have to be done
  374. newInstance = true;
  375. // Create the instance data parts of the primitive and store them
  376. var parts = this.createInstanceDataParts();
  377. this._instanceDataParts = parts;
  378. // Check if the ModelRenderCache for this particular instance is also brand new, initialize it if it's the case
  379. if (!this._modelRenderCache._partsDataStride) {
  380. var ctiArray = new Array();
  381. var dataStrides = new Array();
  382. var usedCatList = new Array();
  383. var partIdList = new Array();
  384. var joinedUsedCatList = new Array();
  385. for (var _i = 0; _i < parts.length; _i++) {
  386. var dataPart = parts[_i];
  387. var cat = this.getUsedShaderCategories(dataPart);
  388. var cti = dataPart.getClassTreeInfo();
  389. // Make sure the instance is visible other the properties won't be set and their size/offset wont be computed
  390. var curVisible = this.isVisible;
  391. this.isVisible = true;
  392. // We manually trigger refreshInstanceData for the only sake of evaluating each instance property size and offset in the instance data, this can only be made at runtime. Once it's done we have all the information to create the instance data buffer.
  393. //console.log("Build Prop Layout for " + Tools.getClassName(this._instanceDataParts[0]));
  394. var joinCat = cat.join(";");
  395. joinedUsedCatList.push(joinCat);
  396. InstanceClassInfo._CurCategories = joinCat;
  397. var obj = this.beforeRefreshForLayoutConstruction(dataPart);
  398. this.refreshInstanceDataPart(dataPart);
  399. this.afterRefreshForLayoutConstruction(dataPart, obj);
  400. this.isVisible = curVisible;
  401. var size = 0;
  402. cti.fullContent.forEach(function (k, v) {
  403. if (!v.category || cat.indexOf(v.category) !== -1) {
  404. if (!v.size) {
  405. console.log("ERROR: Couldn't detect the size of the Property " + v.attributeName + " from type " + BABYLON.Tools.getClassName(cti.type) + ". Property is ignored.");
  406. }
  407. else {
  408. size += v.size;
  409. }
  410. }
  411. });
  412. dataStrides.push(size);
  413. usedCatList.push(cat);
  414. ctiArray.push(cti);
  415. partIdList.push(dataPart.id);
  416. }
  417. this._modelRenderCache._partsDataStride = dataStrides;
  418. this._modelRenderCache._partsUsedCategories = usedCatList;
  419. this._modelRenderCache._partsJoinedUsedCategories = joinedUsedCatList;
  420. this._modelRenderCache._partsClassInfo = ctiArray;
  421. this._modelRenderCache._partIdList = partIdList;
  422. }
  423. // The Rendering resources (Effect, VB, IB, Textures) are stored in the ModelRenderCache
  424. // But it's the RenderGroup that will store all the Instanced related data to render all the primitive it owns.
  425. // So for a given ModelKey we getOrAdd a GroupInstanceInfo that will store all these data
  426. gii = this.renderGroup._renderGroupInstancesInfo.getOrAddWithFactory(this.modelKey, function (k) { return new BABYLON.GroupInstanceInfo(_this.renderGroup, _this._modelRenderCache); });
  427. // First time init of the GroupInstanceInfo
  428. if (gii._instancesPartsData.length === 0) {
  429. for (var j = 0; j < this._modelRenderCache._partsDataStride.length; j++) {
  430. var stride = this._modelRenderCache._partsDataStride[j];
  431. gii._instancesPartsData.push(new BABYLON.DynamicFloatArray(stride / 4, 50));
  432. gii._partIndexFromId.add(this._modelRenderCache._partIdList[j].toString(), j);
  433. for (var _a = 0, _b = this._instanceDataParts; _a < _b.length; _a++) {
  434. var part = _b[_a];
  435. gii._instancesPartsUsedShaderCategories[gii._partIndexFromId.get(part.id.toString())] = this.getUsedShaderCategories(part).join(";");
  436. }
  437. }
  438. }
  439. // For each instance data part of the primitive, allocate the instanced element it needs for render
  440. for (var i = 0; i < parts.length; i++) {
  441. var part = parts[i];
  442. part.dataBuffer = gii._instancesPartsData[i];
  443. part.allocElements();
  444. }
  445. // Add the instance data parts in the ModelRenderCache they belong, track them by storing their ID in the primitive in case we need to change the model later on, so we'll have to release the allocated instance data parts because they won't fit anymore
  446. this._modelRenderInstanceID = this._modelRenderCache.addInstanceDataParts(this._instanceDataParts);
  447. }
  448. // If the ModelRenderCache is brand new, now is the time to call the implementation's specific setup method to create the rendering resources
  449. if (setupModelRenderCache) {
  450. this.setupModelRenderCache(this._modelRenderCache);
  451. }
  452. // At this stage we have everything correctly initialized, ModelRenderCache is setup, Model Instance data are good too, they have allocated elements in the Instanced DynamicFloatArray.
  453. // The last thing to do is check if the instanced related data must be updated because a InstanceLevel property had changed or the primitive visibility changed.
  454. if (this._visibilityChanged || context.forceRefreshPrimitive || newInstance || (this._instanceDirtyFlags !== 0) || (this._globalTransformProcessStep !== this._globalTransformStep)) {
  455. // Fetch the GroupInstanceInfo if we don't already have it
  456. if (!gii) {
  457. gii = this.renderGroup._renderGroupInstancesInfo.get(this.modelKey);
  458. }
  459. // For each Instance Data part, refresh it to update the data in the DynamicFloatArray
  460. for (var _c = 0, _d = this._instanceDataParts; _c < _d.length; _c++) {
  461. var part = _d[_c];
  462. // Check if we need to allocate data elements (hidden prim which becomes visible again)
  463. if (this._visibilityChanged && !part.dataElements) {
  464. part.allocElements();
  465. }
  466. InstanceClassInfo._CurCategories = gii._instancesPartsUsedShaderCategories[gii._partIndexFromId.get(part.id.toString())];
  467. // Will return false if the instance should not be rendered (not visible or other any reasons)
  468. if (!this.refreshInstanceDataPart(part)) {
  469. // Free the data element
  470. if (part.dataElements) {
  471. part.freeElements();
  472. }
  473. }
  474. }
  475. this._instanceDirtyFlags = 0;
  476. gii._dirtyInstancesData = true;
  477. this._visibilityChanged = false; // Reset the flag as we've handled the case
  478. }
  479. };
  480. RenderablePrim2D.prototype.getDataPartEffectInfo = function (dataPartId, vertexBufferAttributes) {
  481. var dataPart = BABYLON.Tools.first(this._instanceDataParts, function (i) { return i.id === dataPartId; });
  482. if (!dataPart) {
  483. return null;
  484. }
  485. var instancedArray = this.owner.supportInstancedArray;
  486. var cti = dataPart.getClassTreeInfo();
  487. var categories = this.getUsedShaderCategories(dataPart);
  488. var att = cti.classContent.getShaderAttributes(categories);
  489. var defines = "";
  490. categories.forEach(function (c) { defines += "#define " + c + "\n"; });
  491. if (instancedArray) {
  492. defines += "#define Instanced\n";
  493. }
  494. return { attributes: instancedArray ? vertexBufferAttributes.concat(att) : vertexBufferAttributes, uniforms: instancedArray ? [] : att, defines: defines };
  495. };
  496. Object.defineProperty(RenderablePrim2D.prototype, "modelRenderCache", {
  497. get: function () {
  498. return this._modelRenderCache;
  499. },
  500. enumerable: true,
  501. configurable: true
  502. });
  503. RenderablePrim2D.prototype.createModelRenderCache = function (modelKey, isTransparent) {
  504. return null;
  505. };
  506. RenderablePrim2D.prototype.setupModelRenderCache = function (modelRenderCache) {
  507. };
  508. RenderablePrim2D.prototype.createInstanceDataParts = function () {
  509. return null;
  510. };
  511. RenderablePrim2D.prototype.getUsedShaderCategories = function (dataPart) {
  512. return [];
  513. };
  514. RenderablePrim2D.prototype.beforeRefreshForLayoutConstruction = function (part) {
  515. };
  516. RenderablePrim2D.prototype.afterRefreshForLayoutConstruction = function (part, obj) {
  517. };
  518. RenderablePrim2D.prototype.refreshInstanceDataPart = function (part) {
  519. if (!this.isVisible) {
  520. return false;
  521. }
  522. part.isVisible = this.isVisible;
  523. // Which means, if there's only one data element, we're update it from this method, otherwise it is the responsibility of the derived class to call updateInstanceDataPart as many times as needed, properly (look at Text2D's implementation for more information)
  524. if (part.dataElementCount === 1) {
  525. part.curElement = 0;
  526. this.updateInstanceDataPart(part);
  527. }
  528. return true;
  529. };
  530. /**
  531. * Update the instanceDataBase level properties of a part
  532. * @param part the part to update
  533. * @param positionOffset to use in multi part per primitive (e.g. the Text2D has N parts for N letter to display), this give the offset to apply (e.g. the position of the letter from the bottom/left corner of the text). You MUST also set customSize.
  534. * @param customSize to use in multi part per primitive, this is the size of the overall primitive to display (the bounding rect's size of the Text, for instance). This is mandatory to compute correct transformation based on the Primitive's origin property.
  535. */
  536. RenderablePrim2D.prototype.updateInstanceDataPart = function (part, positionOffset, customSize) {
  537. if (positionOffset === void 0) { positionOffset = null; }
  538. if (customSize === void 0) { customSize = null; }
  539. var t = this._globalTransform.multiply(this.renderGroup.invGlobalTransform);
  540. var size = this.renderGroup.viewportSize;
  541. var zBias = this.getActualZOffset();
  542. var offX = 0;
  543. var offY = 0;
  544. // If there's an offset, apply the global transformation matrix on it to get a global offset
  545. if (positionOffset && customSize) {
  546. offX = (positionOffset.x - (customSize.width * this.origin.x)) * t.m[0] + (positionOffset.y - (customSize.height * this.origin.y)) * t.m[4];
  547. offY = (positionOffset.x - (customSize.width * this.origin.x)) * t.m[1] + (positionOffset.y - (customSize.height * this.origin.y)) * t.m[5];
  548. }
  549. // Have to convert the coordinates to clip space which is ranged between [-1;1] on X and Y axis, with 0,0 being the left/bottom corner
  550. // Current coordinates are expressed in renderGroup coordinates ([0, renderGroup.actualSize.width|height]) with 0,0 being at the left/top corner
  551. // RenderGroup Width and Height are multiplied by zBias because the VertexShader will multiply X and Y by W, which is 1/zBias. As we divide our coordinate by these Width/Height, we will also divide by the zBias to compensate the operation made by the VertexShader.
  552. // So for X:
  553. // - tx.x = value * 2 / width: is to switch from [0, renderGroup.width] to [0, 2]
  554. // - tx.w = (value * 2 / width) - 1: w stores the translation in renderGroup coordinates so (value * 2 / width) to switch to a clip space translation value. - 1 is to offset the overall [0;2] to [-1;1]. Don't forget it's -(1/zBias) and not -1 because everything need to be scaled by 1/zBias.
  555. var w = size.width * zBias;
  556. var h = size.height * zBias;
  557. var invZBias = 1 / zBias;
  558. var tx = new BABYLON.Vector4(t.m[0] * 2 / w, t.m[4] * 2 / w, 0 /*t.m[8]*/, ((t.m[12] + offX) * 2 / w) - (invZBias));
  559. var ty = new BABYLON.Vector4(t.m[1] * 2 / h, t.m[5] * 2 / h, 0 /*t.m[9]*/, ((t.m[13] + offY) * 2 / h) - (invZBias));
  560. part.transformX = tx;
  561. part.transformY = ty;
  562. part.origin = this.origin;
  563. // Stores zBias and it's inverse value because that's needed to compute the clip space W coordinate (which is 1/Z, so 1/zBias)
  564. part.zBias = new BABYLON.Vector2(zBias, invZBias);
  565. };
  566. RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT = BABYLON.Prim2DBase.PRIM2DBASE_PROPCOUNT + 5;
  567. __decorate([
  568. BABYLON.modelLevelProperty(BABYLON.Prim2DBase.PRIM2DBASE_PROPCOUNT + 1, function (pi) { return RenderablePrim2D.isTransparentProperty = pi; })
  569. ], RenderablePrim2D.prototype, "isTransparent", null);
  570. RenderablePrim2D = __decorate([
  571. BABYLON.className("RenderablePrim2D")
  572. ], RenderablePrim2D);
  573. return RenderablePrim2D;
  574. })(BABYLON.Prim2DBase);
  575. BABYLON.RenderablePrim2D = RenderablePrim2D;
  576. })(BABYLON || (BABYLON = {}));