createVerticesFromGoogleEarthEnterpriseBuffer.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. /* This file is automatically rebuilt by the Cesium build process. */
  2. define(['./defined-26bd4a03', './Check-da037458', './freezeObject-2d83f591', './defaultValue-f2e68450', './Math-fa6e45cb', './Cartesian2-2a723276', './defineProperties-6f7a50f2', './Transforms-65aba0a4', './RuntimeError-ad75c885', './WebGLConstants-497deb20', './ComponentDatatype-69643096', './when-ee12a2cb', './AttributeCompression-87682214', './IntersectionTests-c2360ffa', './Plane-a1a3fd52', './WebMercatorProjection-f2dc467d', './createTaskProcessorWorker', './EllipsoidTangentPlane-10c6053a', './OrientedBoundingBox-a786ab5d', './EllipsoidalOccluder-5541419b', './TerrainEncoding-4dcd0461'], function (defined, Check, freezeObject, defaultValue, _Math, Cartesian2, defineProperties, Transforms, RuntimeError, WebGLConstants, ComponentDatatype, when, AttributeCompression, IntersectionTests, Plane, WebMercatorProjection, createTaskProcessorWorker, EllipsoidTangentPlane, OrientedBoundingBox, EllipsoidalOccluder, TerrainEncoding) { 'use strict';
  3. var sizeOfUint16 = Uint16Array.BYTES_PER_ELEMENT;
  4. var sizeOfInt32 = Int32Array.BYTES_PER_ELEMENT;
  5. var sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT;
  6. var sizeOfFloat = Float32Array.BYTES_PER_ELEMENT;
  7. var sizeOfDouble = Float64Array.BYTES_PER_ELEMENT;
  8. function indexOfEpsilon(arr, elem, elemType) {
  9. elemType = defaultValue.defaultValue(elemType, _Math.CesiumMath);
  10. var count = arr.length;
  11. for (var i = 0; i < count; ++i) {
  12. if (elemType.equalsEpsilon(arr[i], elem, _Math.CesiumMath.EPSILON12)) {
  13. return i;
  14. }
  15. }
  16. return -1;
  17. }
  18. function createVerticesFromGoogleEarthEnterpriseBuffer(parameters, transferableObjects) {
  19. parameters.ellipsoid = Cartesian2.Ellipsoid.clone(parameters.ellipsoid);
  20. parameters.rectangle = Cartesian2.Rectangle.clone(parameters.rectangle);
  21. var statistics = processBuffer(parameters.buffer, parameters.relativeToCenter, parameters.ellipsoid,
  22. parameters.rectangle, parameters.nativeRectangle, parameters.exaggeration, parameters.skirtHeight,
  23. parameters.includeWebMercatorT, parameters.negativeAltitudeExponentBias, parameters.negativeElevationThreshold);
  24. var vertices = statistics.vertices;
  25. transferableObjects.push(vertices.buffer);
  26. var indices = statistics.indices;
  27. transferableObjects.push(indices.buffer);
  28. return {
  29. vertices : vertices.buffer,
  30. indices : indices.buffer,
  31. numberOfAttributes : statistics.encoding.getStride(),
  32. minimumHeight : statistics.minimumHeight,
  33. maximumHeight : statistics.maximumHeight,
  34. boundingSphere3D : statistics.boundingSphere3D,
  35. orientedBoundingBox : statistics.orientedBoundingBox,
  36. occludeePointInScaledSpace : statistics.occludeePointInScaledSpace,
  37. encoding : statistics.encoding,
  38. vertexCountWithoutSkirts : statistics.vertexCountWithoutSkirts,
  39. skirtIndex : statistics.skirtIndex,
  40. westIndicesSouthToNorth : statistics.westIndicesSouthToNorth,
  41. southIndicesEastToWest : statistics.southIndicesEastToWest,
  42. eastIndicesNorthToSouth : statistics.eastIndicesNorthToSouth,
  43. northIndicesWestToEast : statistics.northIndicesWestToEast
  44. };
  45. }
  46. var scratchCartographic = new Cartesian2.Cartographic();
  47. var scratchCartesian = new Cartesian2.Cartesian3();
  48. var minimumScratch = new Cartesian2.Cartesian3();
  49. var maximumScratch = new Cartesian2.Cartesian3();
  50. var matrix4Scratch = new Transforms.Matrix4();
  51. function processBuffer(buffer, relativeToCenter, ellipsoid, rectangle, nativeRectangle, exaggeration, skirtHeight, includeWebMercatorT, negativeAltitudeExponentBias, negativeElevationThreshold) {
  52. var geographicWest;
  53. var geographicSouth;
  54. var geographicEast;
  55. var geographicNorth;
  56. var rectangleWidth, rectangleHeight;
  57. if (!defined.defined(rectangle)) {
  58. geographicWest = _Math.CesiumMath.toRadians(nativeRectangle.west);
  59. geographicSouth = _Math.CesiumMath.toRadians(nativeRectangle.south);
  60. geographicEast = _Math.CesiumMath.toRadians(nativeRectangle.east);
  61. geographicNorth = _Math.CesiumMath.toRadians(nativeRectangle.north);
  62. rectangleWidth = _Math.CesiumMath.toRadians(rectangle.width);
  63. rectangleHeight = _Math.CesiumMath.toRadians(rectangle.height);
  64. } else {
  65. geographicWest = rectangle.west;
  66. geographicSouth = rectangle.south;
  67. geographicEast = rectangle.east;
  68. geographicNorth = rectangle.north;
  69. rectangleWidth = rectangle.width;
  70. rectangleHeight = rectangle.height;
  71. }
  72. // Keep track of quad borders so we can remove duplicates around the borders
  73. var quadBorderLatitudes = [geographicSouth, geographicNorth];
  74. var quadBorderLongitudes = [geographicWest, geographicEast];
  75. var fromENU = Transforms.Transforms.eastNorthUpToFixedFrame(relativeToCenter, ellipsoid);
  76. var toENU = Transforms.Matrix4.inverseTransformation(fromENU, matrix4Scratch);
  77. var southMercatorY;
  78. var oneOverMercatorHeight;
  79. if (includeWebMercatorT) {
  80. southMercatorY = WebMercatorProjection.WebMercatorProjection.geodeticLatitudeToMercatorAngle(geographicSouth);
  81. oneOverMercatorHeight = 1.0 / (WebMercatorProjection.WebMercatorProjection.geodeticLatitudeToMercatorAngle(geographicNorth) - southMercatorY);
  82. }
  83. var dv = new DataView(buffer);
  84. var minHeight = Number.POSITIVE_INFINITY;
  85. var maxHeight = Number.NEGATIVE_INFINITY;
  86. var minimum = minimumScratch;
  87. minimum.x = Number.POSITIVE_INFINITY;
  88. minimum.y = Number.POSITIVE_INFINITY;
  89. minimum.z = Number.POSITIVE_INFINITY;
  90. var maximum = maximumScratch;
  91. maximum.x = Number.NEGATIVE_INFINITY;
  92. maximum.y = Number.NEGATIVE_INFINITY;
  93. maximum.z = Number.NEGATIVE_INFINITY;
  94. // Compute sizes
  95. var offset = 0;
  96. var size = 0;
  97. var indicesSize = 0;
  98. var quadSize;
  99. var quad;
  100. for (quad = 0; quad < 4; ++quad) {
  101. var o = offset;
  102. quadSize = dv.getUint32(o, true);
  103. o += sizeOfUint32;
  104. var x = _Math.CesiumMath.toRadians(dv.getFloat64(o, true) * 180.0);
  105. o += sizeOfDouble;
  106. if (indexOfEpsilon(quadBorderLongitudes, x) === -1) {
  107. quadBorderLongitudes.push(x);
  108. }
  109. var y = _Math.CesiumMath.toRadians(dv.getFloat64(o, true) * 180.0);
  110. o += sizeOfDouble;
  111. if (indexOfEpsilon(quadBorderLatitudes, y) === -1) {
  112. quadBorderLatitudes.push(y);
  113. }
  114. o += 2 * sizeOfDouble; // stepX + stepY
  115. var c = dv.getInt32(o, true); // Read point count
  116. o += sizeOfInt32;
  117. size += c;
  118. c = dv.getInt32(o, true); // Read index count
  119. indicesSize += c * 3;
  120. offset += quadSize + sizeOfUint32; // Jump to next quad
  121. }
  122. // Quad Border points to remove duplicates
  123. var quadBorderPoints = [];
  124. var quadBorderIndices = [];
  125. // Create arrays
  126. var positions = new Array(size);
  127. var uvs = new Array(size);
  128. var heights = new Array(size);
  129. var webMercatorTs = includeWebMercatorT ? new Array(size) : [];
  130. var indices = new Array(indicesSize);
  131. // Points are laid out in rows starting at SW, so storing border points as we
  132. // come across them all points will be adjacent.
  133. var westBorder = [];
  134. var southBorder = [];
  135. var eastBorder = [];
  136. var northBorder = [];
  137. // Each tile is split into 4 parts
  138. var pointOffset = 0;
  139. var indicesOffset = 0;
  140. offset = 0;
  141. for (quad = 0; quad < 4; ++quad) {
  142. quadSize = dv.getUint32(offset, true);
  143. offset += sizeOfUint32;
  144. var startQuad = offset;
  145. var originX = _Math.CesiumMath.toRadians(dv.getFloat64(offset, true) * 180.0);
  146. offset += sizeOfDouble;
  147. var originY = _Math.CesiumMath.toRadians(dv.getFloat64(offset, true) * 180.0);
  148. offset += sizeOfDouble;
  149. var stepX = _Math.CesiumMath.toRadians(dv.getFloat64(offset, true) * 180.0);
  150. var halfStepX = stepX * 0.5;
  151. offset += sizeOfDouble;
  152. var stepY = _Math.CesiumMath.toRadians(dv.getFloat64(offset, true) * 180.0);
  153. var halfStepY = stepY * 0.5;
  154. offset += sizeOfDouble;
  155. var numPoints = dv.getInt32(offset, true);
  156. offset += sizeOfInt32;
  157. var numFaces = dv.getInt32(offset, true);
  158. offset += sizeOfInt32;
  159. //var level = dv.getInt32(offset, true);
  160. offset += sizeOfInt32;
  161. // Keep track of quad indices to overall tile indices
  162. var indicesMapping = new Array(numPoints);
  163. for (var i = 0; i < numPoints; ++i) {
  164. var longitude = originX + dv.getUint8(offset++) * stepX;
  165. scratchCartographic.longitude = longitude;
  166. var latitude = originY + dv.getUint8(offset++) * stepY;
  167. scratchCartographic.latitude = latitude;
  168. var height = dv.getFloat32(offset, true);
  169. offset += sizeOfFloat;
  170. // In order to support old clients, negative altitude values are stored as
  171. // height/-2^32. Old clients see the value as really close to 0 but new clients multiply
  172. // by -2^32 to get the real negative altitude value.
  173. if (height !== 0 && height < negativeElevationThreshold) {
  174. height *= -Math.pow(2, negativeAltitudeExponentBias);
  175. }
  176. // Height is stored in units of (1/EarthRadius) or (1/6371010.0)
  177. height *= 6371010.0 * exaggeration;
  178. scratchCartographic.height = height;
  179. // Is it along a quad border - if so check if already exists and use that index
  180. if (indexOfEpsilon(quadBorderLongitudes, longitude) !== -1 ||
  181. indexOfEpsilon(quadBorderLatitudes, latitude) !== -1) {
  182. var index = indexOfEpsilon(quadBorderPoints, scratchCartographic, Cartesian2.Cartographic);
  183. if (index === -1) {
  184. quadBorderPoints.push(Cartesian2.Cartographic.clone(scratchCartographic));
  185. quadBorderIndices.push(pointOffset);
  186. } else {
  187. indicesMapping[i] = quadBorderIndices[index];
  188. continue;
  189. }
  190. }
  191. indicesMapping[i] = pointOffset;
  192. if (Math.abs(longitude - geographicWest) < halfStepX) {
  193. westBorder.push({
  194. index : pointOffset,
  195. cartographic : Cartesian2.Cartographic.clone(scratchCartographic)
  196. });
  197. } else if (Math.abs(longitude - geographicEast) < halfStepX) {
  198. eastBorder.push({
  199. index : pointOffset,
  200. cartographic : Cartesian2.Cartographic.clone(scratchCartographic)
  201. });
  202. } else if (Math.abs(latitude - geographicSouth) < halfStepY) {
  203. southBorder.push({
  204. index : pointOffset,
  205. cartographic : Cartesian2.Cartographic.clone(scratchCartographic)
  206. });
  207. } else if (Math.abs(latitude - geographicNorth) < halfStepY) {
  208. northBorder.push({
  209. index : pointOffset,
  210. cartographic : Cartesian2.Cartographic.clone(scratchCartographic)
  211. });
  212. }
  213. minHeight = Math.min(height, minHeight);
  214. maxHeight = Math.max(height, maxHeight);
  215. heights[pointOffset] = height;
  216. var pos = ellipsoid.cartographicToCartesian(scratchCartographic);
  217. positions[pointOffset] = pos;
  218. if (includeWebMercatorT) {
  219. webMercatorTs[pointOffset] = (WebMercatorProjection.WebMercatorProjection.geodeticLatitudeToMercatorAngle(latitude) - southMercatorY) * oneOverMercatorHeight;
  220. }
  221. Transforms.Matrix4.multiplyByPoint(toENU, pos, scratchCartesian);
  222. Cartesian2.Cartesian3.minimumByComponent(scratchCartesian, minimum, minimum);
  223. Cartesian2.Cartesian3.maximumByComponent(scratchCartesian, maximum, maximum);
  224. var u = (longitude - geographicWest) / (geographicEast - geographicWest);
  225. u = _Math.CesiumMath.clamp(u, 0.0, 1.0);
  226. var v = (latitude - geographicSouth) / (geographicNorth - geographicSouth);
  227. v = _Math.CesiumMath.clamp(v, 0.0, 1.0);
  228. uvs[pointOffset] = new Cartesian2.Cartesian2(u, v);
  229. ++pointOffset;
  230. }
  231. var facesElementCount = numFaces * 3;
  232. for (var j = 0; j < facesElementCount; ++j, ++indicesOffset) {
  233. indices[indicesOffset] = indicesMapping[dv.getUint16(offset, true)];
  234. offset += sizeOfUint16;
  235. }
  236. if (quadSize !== (offset - startQuad)) {
  237. throw new RuntimeError.RuntimeError('Invalid terrain tile.');
  238. }
  239. }
  240. positions.length = pointOffset;
  241. uvs.length = pointOffset;
  242. heights.length = pointOffset;
  243. if (includeWebMercatorT) {
  244. webMercatorTs.length = pointOffset;
  245. }
  246. var vertexCountWithoutSkirts = pointOffset;
  247. var skirtIndex = indicesOffset;
  248. // Add skirt points
  249. var skirtOptions = {
  250. hMin : minHeight,
  251. lastBorderPoint : undefined,
  252. skirtHeight : skirtHeight,
  253. toENU : toENU,
  254. ellipsoid : ellipsoid,
  255. minimum : minimum,
  256. maximum : maximum
  257. };
  258. // Sort counter clockwise from NW corner
  259. // Corner points are in the east/west arrays
  260. westBorder.sort(function(a, b) {
  261. return b.cartographic.latitude - a.cartographic.latitude;
  262. });
  263. southBorder.sort(function(a, b) {
  264. return a.cartographic.longitude - b.cartographic.longitude;
  265. });
  266. eastBorder.sort(function(a, b) {
  267. return a.cartographic.latitude - b.cartographic.latitude;
  268. });
  269. northBorder.sort(function(a, b) {
  270. return b.cartographic.longitude - a.cartographic.longitude;
  271. });
  272. var percentage = 0.00001;
  273. addSkirt(positions, heights, uvs, webMercatorTs, indices, skirtOptions,
  274. westBorder, -percentage * rectangleWidth, true, -percentage * rectangleHeight);
  275. addSkirt(positions, heights, uvs, webMercatorTs, indices, skirtOptions,
  276. southBorder, -percentage * rectangleHeight, false);
  277. addSkirt(positions, heights, uvs, webMercatorTs, indices, skirtOptions,
  278. eastBorder, percentage * rectangleWidth, true, percentage * rectangleHeight);
  279. addSkirt(positions, heights, uvs, webMercatorTs, indices, skirtOptions,
  280. northBorder, percentage * rectangleHeight, false);
  281. // Since the corner between the north and west sides is in the west array, generate the last
  282. // two triangles between the last north vertex and the first west vertex
  283. if (westBorder.length > 0 && northBorder.length > 0) {
  284. var firstBorderIndex = westBorder[0].index;
  285. var firstSkirtIndex = vertexCountWithoutSkirts;
  286. var lastBorderIndex = northBorder[northBorder.length - 1].index;
  287. var lastSkirtIndex = positions.length - 1;
  288. indices.push(lastBorderIndex, lastSkirtIndex, firstSkirtIndex, firstSkirtIndex, firstBorderIndex, lastBorderIndex);
  289. }
  290. size = positions.length; // Get new size with skirt vertices
  291. var boundingSphere3D = Transforms.BoundingSphere.fromPoints(positions);
  292. var orientedBoundingBox;
  293. if (defined.defined(rectangle) && rectangle.width < _Math.CesiumMath.PI_OVER_TWO + _Math.CesiumMath.EPSILON5) {
  294. // Here, rectangle.width < pi/2, and rectangle.height < pi
  295. // (though it would still work with rectangle.width up to pi)
  296. orientedBoundingBox = OrientedBoundingBox.OrientedBoundingBox.fromRectangle(rectangle, minHeight, maxHeight, ellipsoid);
  297. }
  298. var occluder = new EllipsoidalOccluder.EllipsoidalOccluder(ellipsoid);
  299. var occludeePointInScaledSpace = occluder.computeHorizonCullingPoint(relativeToCenter, positions);
  300. var aaBox = new EllipsoidTangentPlane.AxisAlignedBoundingBox(minimum, maximum, relativeToCenter);
  301. var encoding = new TerrainEncoding.TerrainEncoding(aaBox, skirtOptions.hMin, maxHeight, fromENU, false, includeWebMercatorT);
  302. var vertices = new Float32Array(size * encoding.getStride());
  303. var bufferIndex = 0;
  304. for (var k = 0; k < size; ++k) {
  305. bufferIndex = encoding.encode(vertices, bufferIndex, positions[k], uvs[k], heights[k], undefined, webMercatorTs[k]);
  306. }
  307. var westIndicesSouthToNorth = westBorder.map(function(vertex) { return vertex.index; }).reverse();
  308. var southIndicesEastToWest = southBorder.map(function(vertex) { return vertex.index; }).reverse();
  309. var eastIndicesNorthToSouth = eastBorder.map(function(vertex) { return vertex.index; }).reverse();
  310. var northIndicesWestToEast = northBorder.map(function(vertex) { return vertex.index; }).reverse();
  311. southIndicesEastToWest.unshift(eastIndicesNorthToSouth[eastIndicesNorthToSouth.length - 1]);
  312. southIndicesEastToWest.push(westIndicesSouthToNorth[0]);
  313. northIndicesWestToEast.unshift(westIndicesSouthToNorth[westIndicesSouthToNorth.length - 1]);
  314. northIndicesWestToEast.push(eastIndicesNorthToSouth[0]);
  315. return {
  316. vertices : vertices,
  317. indices : new Uint16Array(indices),
  318. maximumHeight : maxHeight,
  319. minimumHeight : minHeight,
  320. encoding : encoding,
  321. boundingSphere3D : boundingSphere3D,
  322. orientedBoundingBox : orientedBoundingBox,
  323. occludeePointInScaledSpace : occludeePointInScaledSpace,
  324. vertexCountWithoutSkirts : vertexCountWithoutSkirts,
  325. skirtIndex : skirtIndex,
  326. westIndicesSouthToNorth : westIndicesSouthToNorth,
  327. southIndicesEastToWest : southIndicesEastToWest,
  328. eastIndicesNorthToSouth : eastIndicesNorthToSouth,
  329. northIndicesWestToEast : northIndicesWestToEast
  330. };
  331. }
  332. function addSkirt(positions, heights, uvs, webMercatorTs, indices, skirtOptions,
  333. borderPoints, fudgeFactor, eastOrWest, cornerFudge) {
  334. var count = borderPoints.length;
  335. for (var j = 0; j < count; ++j) {
  336. var borderPoint = borderPoints[j];
  337. var borderCartographic = borderPoint.cartographic;
  338. var borderIndex = borderPoint.index;
  339. var currentIndex = positions.length;
  340. var longitude = borderCartographic.longitude;
  341. var latitude = borderCartographic.latitude;
  342. latitude = _Math.CesiumMath.clamp(latitude, -_Math.CesiumMath.PI_OVER_TWO, _Math.CesiumMath.PI_OVER_TWO); // Don't go over the poles
  343. var height = borderCartographic.height - skirtOptions.skirtHeight;
  344. skirtOptions.hMin = Math.min(skirtOptions.hMin, height);
  345. Cartesian2.Cartographic.fromRadians(longitude, latitude, height, scratchCartographic);
  346. // Adjust sides to angle out
  347. if (eastOrWest) {
  348. scratchCartographic.longitude += fudgeFactor;
  349. }
  350. // Adjust top or bottom to angle out
  351. // Since corners are in the east/west arrays angle the first and last points as well
  352. if (!eastOrWest) {
  353. scratchCartographic.latitude += fudgeFactor;
  354. } else if (j === (count - 1)) {
  355. scratchCartographic.latitude += cornerFudge;
  356. } else if (j === 0) {
  357. scratchCartographic.latitude -= cornerFudge;
  358. }
  359. var pos = skirtOptions.ellipsoid.cartographicToCartesian(scratchCartographic);
  360. positions.push(pos);
  361. heights.push(height);
  362. uvs.push(Cartesian2.Cartesian2.clone(uvs[borderIndex])); // Copy UVs from border point
  363. if (webMercatorTs.length > 0) {
  364. webMercatorTs.push(webMercatorTs[borderIndex]);
  365. }
  366. Transforms.Matrix4.multiplyByPoint(skirtOptions.toENU, pos, scratchCartesian);
  367. var minimum = skirtOptions.minimum;
  368. var maximum = skirtOptions.maximum;
  369. Cartesian2.Cartesian3.minimumByComponent(scratchCartesian, minimum, minimum);
  370. Cartesian2.Cartesian3.maximumByComponent(scratchCartesian, maximum, maximum);
  371. var lastBorderPoint = skirtOptions.lastBorderPoint;
  372. if (defined.defined(lastBorderPoint)) {
  373. var lastBorderIndex = lastBorderPoint.index;
  374. indices.push(lastBorderIndex, currentIndex - 1, currentIndex, currentIndex, borderIndex, lastBorderIndex);
  375. }
  376. skirtOptions.lastBorderPoint = borderPoint;
  377. }
  378. }
  379. var createVerticesFromGoogleEarthEnterpriseBuffer$1 = createTaskProcessorWorker(createVerticesFromGoogleEarthEnterpriseBuffer);
  380. return createVerticesFromGoogleEarthEnterpriseBuffer$1;
  381. });