babylon.groundMesh.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. var __extends = (this && this.__extends) || function (d, b) {
  2. for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
  3. function __() { this.constructor = d; }
  4. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  5. };
  6. var BABYLON;
  7. (function (BABYLON) {
  8. var GroundMesh = (function (_super) {
  9. __extends(GroundMesh, _super);
  10. function GroundMesh(name, scene) {
  11. _super.call(this, name, scene);
  12. this.generateOctree = false;
  13. this._worldInverse = new BABYLON.Matrix();
  14. }
  15. Object.defineProperty(GroundMesh.prototype, "subdivisions", {
  16. get: function () {
  17. return this._subdivisions;
  18. },
  19. enumerable: true,
  20. configurable: true
  21. });
  22. GroundMesh.prototype.optimize = function (chunksCount, octreeBlocksSize) {
  23. if (octreeBlocksSize === void 0) { octreeBlocksSize = 32; }
  24. this._subdivisions = chunksCount;
  25. this.subdivide(this._subdivisions);
  26. this.createOrUpdateSubmeshesOctree(octreeBlocksSize);
  27. };
  28. /**
  29. * Returns a height (y) value in the Worl system :
  30. * the ground altitude at the coordinates (x, z) expressed in the World system.
  31. * Returns the ground y position if (x, z) are outside the ground surface.
  32. * Not pertinent if the ground is rotated.
  33. */
  34. GroundMesh.prototype.getHeightAtCoordinates = function (x, z) {
  35. // express x and y in the ground local system
  36. x -= this.position.x;
  37. z -= this.position.z;
  38. x /= this.scaling.x;
  39. z /= this.scaling.z;
  40. if (x < this._minX || x > this._maxX || z < this._minZ || z > this._maxZ) {
  41. return this.position.y;
  42. }
  43. if (!this._heightQuads || this._heightQuads.length == 0) {
  44. this._initHeightQuads();
  45. this._computeHeightQuads();
  46. }
  47. var facet = this._getFacetAt(x, z);
  48. var y = -(facet.x * x + facet.z * z + facet.w) / facet.y;
  49. // return y in the World system
  50. return y * this.scaling.y + this.position.y;
  51. };
  52. /**
  53. * Returns a normalized vector (Vector3) orthogonal to the ground
  54. * at the ground coordinates (x, z) expressed in the World system.
  55. * Returns Vector3(0, 1, 0) if (x, z) are outside the ground surface.
  56. * Not pertinent if the ground is rotated.
  57. */
  58. GroundMesh.prototype.getNormalAtCoordinates = function (x, z) {
  59. var normal = new BABYLON.Vector3(0, 1, 0);
  60. this.getNormalAtCoordinatesToRef(x, z, normal);
  61. return normal;
  62. };
  63. /**
  64. * Updates the Vector3 passed a reference with a normalized vector orthogonal to the ground
  65. * at the ground coordinates (x, z) expressed in the World system.
  66. * Doesn't uptade the reference Vector3 if (x, z) are outside the ground surface.
  67. * Not pertinent if the ground is rotated.
  68. */
  69. GroundMesh.prototype.getNormalAtCoordinatesToRef = function (x, z, ref) {
  70. // express x and y in the ground local system
  71. x -= this.position.x;
  72. z -= this.position.z;
  73. x /= this.scaling.x;
  74. z /= this.scaling.z;
  75. if (x < this._minX || x > this._maxX || z < this._minZ || z > this._maxZ) {
  76. return;
  77. }
  78. if (!this._heightQuads || this._heightQuads.length == 0) {
  79. this._initHeightQuads();
  80. this._computeHeightQuads();
  81. }
  82. var facet = this._getFacetAt(x, z);
  83. ref.x = facet.x;
  84. ref.y = facet.y;
  85. ref.z = facet.z;
  86. };
  87. /**
  88. * Force the heights to be recomputed for getHeightAtCoordinates() or getNormalAtCoordinates()
  89. * if the ground has been updated.
  90. * This can be used in the render loop
  91. */
  92. GroundMesh.prototype.updateCoordinateHeights = function () {
  93. if (!this._heightQuads || this._heightQuads.length == 0) {
  94. this._initHeightQuads();
  95. }
  96. this._computeHeightQuads();
  97. };
  98. // Returns the element "facet" from the heightQuads array relative to (x, z) local coordinates
  99. GroundMesh.prototype._getFacetAt = function (x, z) {
  100. // retrieve col and row from x, z coordinates in the ground local system
  101. var col = Math.floor((x + this._maxX) * this._subdivisions / this._width);
  102. var row = Math.floor(-(z + this._maxZ) * this._subdivisions / this._height + this._subdivisions);
  103. var quad = this._heightQuads[row * this._subdivisions + col];
  104. var facet;
  105. if (z < quad.slope.x * x + quad.slope.y) {
  106. facet = quad.facet1;
  107. }
  108. else {
  109. facet = quad.facet2;
  110. }
  111. return facet;
  112. };
  113. // Creates and populates the heightMap array with "facet" elements :
  114. // a quad is two triangular facets separated by a slope, so a "facet" element is 1 slope + 2 facets
  115. // slope : Vector2(c, h) = 2D diagonal line equation setting appart two triangular facets in a quad : z = cx + h
  116. // facet1 : Vector4(a, b, c, d) = first facet 3D plane equation : ax + by + cz + d = 0
  117. // facet2 : Vector4(a, b, c, d) = second facet 3D plane equation : ax + by + cz + d = 0
  118. GroundMesh.prototype._initHeightQuads = function () {
  119. this._heightQuads = new Array();
  120. for (var row = 0; row < this._subdivisions; row++) {
  121. for (var col = 0; col < this._subdivisions; col++) {
  122. var quad = { slope: BABYLON.Vector2.Zero(), facet1: new BABYLON.Vector4(0, 0, 0, 0), facet2: new BABYLON.Vector4(0, 0, 0, 0) };
  123. this._heightQuads[row * this._subdivisions + col] = quad;
  124. }
  125. }
  126. };
  127. // Compute each quad element values and update the the heightMap array :
  128. // slope : Vector2(c, h) = 2D diagonal line equation setting appart two triangular facets in a quad : z = cx + h
  129. // facet1 : Vector4(a, b, c, d) = first facet 3D plane equation : ax + by + cz + d = 0
  130. // facet2 : Vector4(a, b, c, d) = second facet 3D plane equation : ax + by + cz + d = 0
  131. GroundMesh.prototype._computeHeightQuads = function () {
  132. var positions = this.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  133. var v1 = BABYLON.Tmp.Vector3[0];
  134. var v2 = BABYLON.Tmp.Vector3[1];
  135. var v3 = BABYLON.Tmp.Vector3[2];
  136. var v4 = BABYLON.Tmp.Vector3[3];
  137. var v1v2 = BABYLON.Tmp.Vector3[4];
  138. var v1v3 = BABYLON.Tmp.Vector3[5];
  139. var v1v4 = BABYLON.Tmp.Vector3[6];
  140. var norm1 = BABYLON.Tmp.Vector3[7];
  141. var norm2 = BABYLON.Tmp.Vector3[8];
  142. var i = 0;
  143. var j = 0;
  144. var k = 0;
  145. var cd = 0; // 2D slope coefficient : z = cd * x + h
  146. var h = 0;
  147. var d1 = 0; // facet plane equation : ax + by + cz + d = 0
  148. var d2 = 0;
  149. for (var row = 0; row < this._subdivisions; row++) {
  150. for (var col = 0; col < this._subdivisions; col++) {
  151. i = col * 3;
  152. j = row * (this._subdivisions + 1) * 3;
  153. k = (row + 1) * (this._subdivisions + 1) * 3;
  154. v1.x = positions[j + i];
  155. v1.y = positions[j + i + 1];
  156. v1.z = positions[j + i + 2];
  157. v2.x = positions[j + i + 3];
  158. v2.y = positions[j + i + 4];
  159. v2.z = positions[j + i + 5];
  160. v3.x = positions[k + i];
  161. v3.y = positions[k + i + 1];
  162. v3.z = positions[k + i + 2];
  163. v4.x = positions[k + i + 3];
  164. v4.y = positions[k + i + 4];
  165. v4.z = positions[k + i + 5];
  166. // 2D slope V1V4
  167. cd = (v4.z - v1.z) / (v4.x - v1.x);
  168. h = v1.z - cd * v1.x; // v1 belongs to the slope
  169. // facet equations :
  170. // we compute each facet normal vector
  171. // the equation of the facet plane is : norm.x * x + norm.y * y + norm.z * z + d = 0
  172. // we compute the value d by applying the equation to v1 which belongs to the plane
  173. // then we store the facet equation in a Vector4
  174. v2.subtractToRef(v1, v1v2);
  175. v3.subtractToRef(v1, v1v3);
  176. v4.subtractToRef(v1, v1v4);
  177. BABYLON.Vector3.CrossToRef(v1v4, v1v3, norm1);
  178. BABYLON.Vector3.CrossToRef(v1v2, v1v4, norm2);
  179. norm1.normalize();
  180. norm2.normalize();
  181. d1 = -(norm1.x * v1.x + norm1.y * v1.y + norm1.z * v1.z);
  182. d2 = -(norm2.x * v2.x + norm2.y * v2.y + norm2.z * v2.z);
  183. var quad = this._heightQuads[row * this._subdivisions + col];
  184. quad.slope.copyFromFloats(cd, h);
  185. quad.facet1.copyFromFloats(norm1.x, norm1.y, norm1.z, d1);
  186. quad.facet2.copyFromFloats(norm2.x, norm2.y, norm2.z, d2);
  187. }
  188. }
  189. };
  190. return GroundMesh;
  191. })(BABYLON.Mesh);
  192. BABYLON.GroundMesh = GroundMesh;
  193. })(BABYLON || (BABYLON = {}));
  194. //# sourceMappingURL=babylon.groundMesh.js.map