InfoCesiumTerrainProvider.js 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  1. /*global define*/
  2. define([
  3. 'scripts/vendor/terrain/throttleRequestByServer',
  4. 'scripts/vendor/terrain/loadArrayBuffer'
  5. ], function (
  6. throttleRequestByServer,
  7. loadArrayBuffer
  8. ) {
  9. 'use strict';
  10. var Uri = Cesium.Uri;
  11. var when = Cesium.when;
  12. var BoundingSphere = Cesium.BoundingSphere;
  13. var Cartesian3 = Cesium.Cartesian3;
  14. var Credit = Cesium.Credit;
  15. var defaultValue = Cesium.defaultValue;
  16. var defined = Cesium.defined;
  17. var defineProperties = Cesium.defineProperties;
  18. var DeveloperError = Cesium.DeveloperError;
  19. var Event = Cesium.Event;
  20. var GeographicTilingScheme = Cesium.GeographicTilingScheme;
  21. var HeightmapTerrainData = Cesium.HeightmapTerrainData;
  22. var IndexDatatype = Cesium.IndexDatatype;
  23. var joinUrls = Cesium.joinUrls;
  24. var loadJson = Cesium.loadJson;
  25. var CesiumMath = Cesium.CesiumMath;
  26. var Matrix3 = Cesium.Matrix3;
  27. var OrientedBoundingBox = Cesium.OrientedBoundingBox;
  28. var QuantizedMeshTerrainData = Cesium.QuantizedMeshTerrainData;
  29. var RuntimeError = Cesium.RuntimeError;
  30. var TerrainProvider = Cesium.TerrainProvider;
  31. //var throttleRequestByServer = Cesium.throttleRequestByServer;
  32. var TileProviderError = Cesium.TileProviderError;
  33. /**
  34. * A {@link TerrainProvider} that access terrain data in a Cesium terrain format.
  35. * The format is described on the
  36. * {@link https://github.com/AnalyticalGraphicsInc/cesium/wiki/Cesium-Terrain-Server|Cesium wiki}.
  37. *
  38. * @alias CesiumTerrainProvider
  39. * @constructor
  40. *
  41. * @param {Object} options Object with the following properties:
  42. * @param {String} options.url The URL of the Cesium terrain server.
  43. * @param {Proxy} [options.proxy] A proxy to use for requests. This object is expected to have a getURL function which returns the proxied URL, if needed.
  44. * @param {Boolean} [options.requestVertexNormals=false] Flag that indicates if the client should request additional lighting information from the server, in the form of per vertex normals if available.
  45. * @param {Boolean} [options.requestWaterMask=false] Flag that indicates if the client should request per tile water masks from the server, if available.
  46. * @param {Ellipsoid} [options.ellipsoid] The ellipsoid. If not specified, the WGS84 ellipsoid is used.
  47. * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas.
  48. *
  49. *
  50. * @example
  51. * // Construct a terrain provider that uses per vertex normals for lighting
  52. * // to add shading detail to an imagery provider.
  53. * var terrainProvider = new Cesium.CesiumTerrainProvider({
  54. * url : 'https://assets.agi.com/stk-terrain/world',
  55. * requestVertexNormals : true
  56. * });
  57. *
  58. * // Terrain geometry near the surface of the globe is difficult to view when using NaturalEarthII imagery,
  59. * // unless the TerrainProvider provides additional lighting information to shade the terrain (as shown above).
  60. * var imageryProvider = Cesium.createTileMapServiceImageryProvider({
  61. * url : 'http://localhost:8080/Source/Assets/Textures/NaturalEarthII',
  62. * fileExtension : 'jpg'
  63. * });
  64. *
  65. * var viewer = new Cesium.Viewer('cesiumContainer', {
  66. * imageryProvider : imageryProvider,
  67. * baseLayerPicker : false,
  68. * terrainProvider : terrainProvider
  69. * });
  70. *
  71. * // The globe must enable lighting to make use of the terrain's vertex normals
  72. * viewer.scene.globe.enableLighting = true;
  73. *
  74. * @see TerrainProvider
  75. */
  76. function InfoCesiumTerrainProvider(options) {
  77. //>>includeStart('debug', pragmas.debug)
  78. if (!defined(options) || !defined(options.url)) {
  79. throw new DeveloperError('options.url is required.');
  80. }
  81. //>>includeEnd('debug');
  82. this.maxLevel = defaultValue(options.maxLevel, 0);
  83. this._url = options.url;
  84. this._proxy = options.proxy;
  85. this._tilingScheme = new GeographicTilingScheme({
  86. numberOfLevelZeroTilesX: 2,
  87. numberOfLevelZeroTilesY: 1,
  88. ellipsoid: options.ellipsoid
  89. });
  90. this._heightmapWidth = 65;
  91. this._levelZeroMaximumGeometricError = TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(this._tilingScheme.ellipsoid, this._heightmapWidth, this._tilingScheme.getNumberOfXTilesAtLevel(0));
  92. this._heightmapStructure = undefined;
  93. this._hasWaterMask = false;
  94. /**
  95. * Boolean flag that indicates if the Terrain Server can provide vertex normals.
  96. * @type {Boolean}
  97. * @default false
  98. * @private
  99. */
  100. this._hasVertexNormals = false;
  101. /**
  102. * Boolean flag that indicates if the client should request vertex normals from the server.
  103. * @type {Boolean}
  104. * @default false
  105. * @private
  106. */
  107. this._requestVertexNormals = defaultValue(options.requestVertexNormals, false);
  108. this._littleEndianExtensionSize = true;
  109. /**
  110. * Boolean flag that indicates if the client should request tile watermasks from the server.
  111. * @type {Boolean}
  112. * @default false
  113. * @private
  114. */
  115. this._requestWaterMask = defaultValue(options.requestWaterMask, false);
  116. this._errorEvent = new Event();
  117. var credit = options.credit;
  118. if (typeof credit === 'string') {
  119. credit = new Credit(credit);
  120. }
  121. this._credit = credit;
  122. this._ready = false;
  123. this._readyPromise = when.defer();
  124. var metadataUrl = this._url;
  125. if (defined(this._proxy)) {
  126. metadataUrl = this._proxy.getURL(metadataUrl);
  127. }
  128. var that = this;
  129. var metadataError;
  130. function metadataSuccess(data) {
  131. var message;
  132. if (!data.format) {
  133. message = 'The tile format is not specified in the layer.json file.';
  134. metadataError = TileProviderError.handleError(metadataError, that, that._errorEvent, message, undefined, undefined, undefined, requestMetadata);
  135. return;
  136. }
  137. if (!data.tiles || data.tiles.length === 0) {
  138. message = 'The layer.json file does not specify any tile URL templates.';
  139. metadataError = TileProviderError.handleError(metadataError, that, that._errorEvent, message, undefined, undefined, undefined, requestMetadata);
  140. return;
  141. }
  142. if (data.format === 'heightmap-1.0') {
  143. that._heightmapStructure = {
  144. heightScale: 1.0,
  145. heightOffset: 5,
  146. elementsPerHeight: 1,
  147. stride: 1,
  148. elementMultiplier: 256.0,
  149. isBigEndian: false,
  150. lowestEncodedHeight: 0,
  151. highestEncodedHeight: 256 * 256 - 1
  152. };
  153. that._hasWaterMask = false;
  154. that._requestWaterMask = false;
  155. } else if (data.format.indexOf('quantized-mesh-1.') !== 0) {
  156. message = 'The tile format "' + data.format + '" is invalid or not supported.';
  157. metadataError = TileProviderError.handleError(metadataError, that, that._errorEvent, message, undefined, undefined, undefined, requestMetadata);
  158. return;
  159. }
  160. that._tileUrlTemplates = that._url; //已更改
  161. that._availableTiles = data.available;
  162. if (!defined(that._credit) && defined(data.attribution) && data.attribution !== null) {
  163. that._credit = new Credit(data.attribution);
  164. }
  165. // The vertex normals defined in the 'octvertexnormals' extension is identical to the original
  166. // contents of the original 'vertexnormals' extension. 'vertexnormals' extension is now
  167. // deprecated, as the extensionLength for this extension was incorrectly using big endian.
  168. // We maintain backwards compatibility with the legacy 'vertexnormal' implementation
  169. // by setting the _littleEndianExtensionSize to false. Always prefer 'octvertexnormals'
  170. // over 'vertexnormals' if both extensions are supported by the server.
  171. if (defined(data.extensions) && data.extensions.indexOf('octvertexnormals') !== -1) {
  172. that._hasVertexNormals = true;
  173. } else if (defined(data.extensions) && data.extensions.indexOf('vertexnormals') !== -1) {
  174. that._hasVertexNormals = true;
  175. that._littleEndianExtensionSize = false;
  176. }
  177. if (defined(data.extensions) && data.extensions.indexOf('watermask') !== -1) {
  178. that._hasWaterMask = true;
  179. }
  180. that._ready = true;
  181. that._readyPromise.resolve(true);
  182. }
  183. /****源码更改,不读配置文件,直接初始数据***/
  184. function metadataIni() {
  185. metadataSuccess({
  186. tilejson: '2.1.0',
  187. format: 'heightmap-1.0',
  188. version: '1.0.0',
  189. scheme: 'wtms',
  190. tiles: [
  191. '?'
  192. ]
  193. });
  194. return;
  195. }
  196. /*
  197. function metadataFailure(data) {
  198. // If the metadata is not found, assume this is a pre-metadata heightmap tileset.
  199. if (defined(data) && data.statusCode === 404) {
  200. metadataSuccess({
  201. tilejson: '2.1.0',
  202. format: 'heightmap-1.0',
  203. version: '1.0.0',
  204. scheme: 'tms',
  205. tiles: [
  206. '{z}/{x}/{y}.terrain?v={version}'
  207. ]
  208. });
  209. return;
  210. }
  211. var message = 'An error occurred while accessing ' + metadataUrl + '.';
  212. metadataError = TileProviderError.handleError(metadataError, that, that._errorEvent, message, undefined, undefined, undefined, requestMetadata);
  213. }
  214. function requestMetadata() {
  215. var metadata = loadJson(metadataUrl);
  216. when(metadata, metadataSuccess, metadataFailure);
  217. }
  218. requestMetadata();*/
  219. metadataIni();
  220. }
  221. /**
  222. * When using the Quantized-Mesh format, a tile may be returned that includes additional extensions, such as PerVertexNormals, watermask, etc.
  223. * This enumeration defines the unique identifiers for each type of extension data that has been appended to the standard mesh data.
  224. *
  225. * @exports QuantizedMeshExtensionIds
  226. * @see CesiumTerrainProvider
  227. * @private
  228. */
  229. var QuantizedMeshExtensionIds = {
  230. /**
  231. * Oct-Encoded Per-Vertex Normals are included as an extension to the tile mesh
  232. *
  233. * @type {Number}
  234. * @constant
  235. * @default 1
  236. */
  237. OCT_VERTEX_NORMALS: 1,
  238. /**
  239. * A watermask is included as an extension to the tile mesh
  240. *
  241. * @type {Number}
  242. * @constant
  243. * @default 2
  244. */
  245. WATER_MASK: 2
  246. };
  247. function getRequestHeader(extensionsList) {
  248. if (!defined(extensionsList) || extensionsList.length === 0) {
  249. return {
  250. Accept: 'application/vnd.quantized-mesh,application/octet-stream;q=0.9,*/*;q=0.01'
  251. };
  252. } else {
  253. var extensions = extensionsList.join('-');
  254. return {
  255. Accept: 'application/vnd.quantized-mesh;extensions=' + extensions + ',application/octet-stream;q=0.9,*/*;q=0.01'
  256. };
  257. }
  258. }
  259. function createHeightmapTerrainData(provider, buffer, level, x, y, tmsY) {
  260. var hasChildOrNot;
  261. if (level < provider.maxLevel) {
  262. hasChildOrNot = new Uint8Array([15])[0];
  263. } else {
  264. hasChildOrNot = new Uint8Array([0])[0];
  265. }
  266. var yTiles1 = provider._tilingScheme.getNumberOfXTilesAtLevel(level);
  267. // var yy1 = (yTiles1 - y - 1);
  268. var yy1 = y;
  269. var bley = yy1 % 2 == 0 ? true : false;
  270. var blex = x % 2 == 0 ? true : false;
  271. if (buffer.byteLength > 0) {
  272. // var intBuffer0 = new Int16Array(buffer, 0, provider._heightmapWidth * provider._heightmapWidth);
  273. var intBuffer0 = new Int16Array(129 * 129);
  274. // var intBuffer0 = new Uint16Array(129* 129);
  275. //数据高地位字节转换
  276. /*
  277. var dataview = new DataView(buffer);
  278. for(var ii=0;ii<(129*129);){
  279. var val1=dataview.getInt8(ii);
  280. var val2=dataview.getInt8(ii+1);
  281. var val3 = ((val1 & 0xFF)|((val2 & 0xFF)<<8));
  282. ii = ii+2;
  283. intBuffer0[ii-1] = val3
  284. intBuffer0[ii] = val3;
  285. }
  286. */
  287. var dataview = new DataView(buffer);
  288. for (var ii = 0; ii < (129 * 129 * 2);) {
  289. var val1 = dataview.getInt8(ii);
  290. var val2 = dataview.getInt8(ii + 1);
  291. var val3 = ((val1 & 0xFF) | ((val2 & 0xFF) << 8));
  292. ii = ii + 2;
  293. //var val4=[];
  294. //val4[0]=val3;
  295. //intBuffer0.set(val4,ii/2-1);
  296. intBuffer0[ii / 2 - 1] = val3;
  297. }
  298. var aabdsk = intBuffer0.subarray(100, 103);
  299. var intBuffer1;
  300. var intBuffer = intBuffer0.subarray(0, 65 * 65);
  301. if (bley) {
  302. intBuffer1 = intBuffer0.subarray(0, 65 * 129);
  303. } else {
  304. intBuffer1 = intBuffer0.subarray(64 * 129, 129 * 129);
  305. }
  306. if (blex) {
  307. for (var i = 0; i < 66; i++) {
  308. intBuffer.set(intBuffer1.subarray(129 * i, 129 * i + 65), 65 * i);
  309. }
  310. } else {
  311. for (var i = 0; i < 66; i++) {
  312. intBuffer.set(intBuffer1.subarray(129 * i + 64, 129 * (i + 1)), 65 * i);
  313. }
  314. }
  315. /*
  316. var temp = 0; //temp用来存储当前高程区块中的最小负值
  317. for (var i = 0; i < intBuffer.length; i++) {
  318. if (temp > intBuffer[i]) {
  319. temp = intBuffer[i];
  320. }
  321. }
  322. var heightBuffer = new Uint16Array(intBuffer.length);
  323. //该循环将所读取的高程数据中的所有值减去所获取到的高程最小值(该最小值为负值)
  324. for (var i = 0; i < intBuffer.length; i++) {
  325. heightBuffer[i] = intBuffer[i] - temp;
  326. }
  327. */
  328. var heightBuffer = intBuffer;
  329. var heightmapStructure = {
  330. heightScale: 1,
  331. heightOffset: 5,
  332. elementsPerHeight: 1,
  333. stride: 1,
  334. elementMultiplier: 256.0,
  335. isBigEndian: false,
  336. lowestEncodedHeight: 0,
  337. highestEncodedHeight: 256 * 256 - 1
  338. };
  339. //console.log(temp);
  340. return new HeightmapTerrainData({
  341. buffer: heightBuffer,
  342. childTileMask: hasChildOrNot,
  343. waterMask: new Uint8Array([0]),
  344. width: provider._heightmapWidth,
  345. height: provider._heightmapWidth,
  346. structure: heightmapStructure
  347. });
  348. } else {
  349. var heightBuffer = new Uint16Array(provider._heightmapWidth * provider._heightmapWidth);
  350. for (var i = 0; i < heightBuffer.byteLength; i++) {
  351. heightBuffer[i] = 0;
  352. }
  353. return new HeightmapTerrainData({
  354. buffer: heightBuffer,
  355. childTileMask: hasChildOrNot,
  356. waterMask: new Uint8Array([0]),
  357. width: provider._heightmapWidth,
  358. height: provider._heightmapWidth,
  359. structure: provider._heightmapStructure
  360. });
  361. }
  362. }
  363. function createQuantizedMeshTerrainData(provider, buffer, level, x, y, tmsY) {
  364. var pos = 0;
  365. var cartesian3Elements = 3;
  366. var boundingSphereElements = cartesian3Elements + 1;
  367. var cartesian3Length = Float64Array.BYTES_PER_ELEMENT * cartesian3Elements;
  368. var boundingSphereLength = Float64Array.BYTES_PER_ELEMENT * boundingSphereElements;
  369. var encodedVertexElements = 3;
  370. var encodedVertexLength = Uint16Array.BYTES_PER_ELEMENT * encodedVertexElements;
  371. var triangleElements = 3;
  372. var bytesPerIndex = Uint16Array.BYTES_PER_ELEMENT;
  373. var triangleLength = bytesPerIndex * triangleElements;
  374. var view = new DataView(buffer);
  375. var center = new Cartesian3(view.getFloat64(pos, true), view.getFloat64(pos + 8, true), view.getFloat64(pos + 16, true));
  376. pos += cartesian3Length;
  377. var minimumHeight = view.getFloat32(pos, true);
  378. pos += Float32Array.BYTES_PER_ELEMENT;
  379. var maximumHeight = view.getFloat32(pos, true);
  380. pos += Float32Array.BYTES_PER_ELEMENT;
  381. var boundingSphere = new BoundingSphere(
  382. new Cartesian3(view.getFloat64(pos, true), view.getFloat64(pos + 8, true), view.getFloat64(pos + 16, true)),
  383. view.getFloat64(pos + cartesian3Length, true));
  384. pos += boundingSphereLength;
  385. var horizonOcclusionPoint = new Cartesian3(view.getFloat64(pos, true), view.getFloat64(pos + 8, true), view.getFloat64(pos + 16, true));
  386. pos += cartesian3Length;
  387. var vertexCount = view.getUint32(pos, true);
  388. pos += Uint32Array.BYTES_PER_ELEMENT;
  389. var encodedVertexBuffer = new Uint16Array(buffer, pos, vertexCount * 3);
  390. pos += vertexCount * encodedVertexLength;
  391. if (vertexCount > 64 * 1024) {
  392. // More than 64k vertices, so indices are 32-bit.
  393. bytesPerIndex = Uint32Array.BYTES_PER_ELEMENT;
  394. triangleLength = bytesPerIndex * triangleElements;
  395. }
  396. // Decode the vertex buffer.
  397. var uBuffer = encodedVertexBuffer.subarray(0, vertexCount);
  398. var vBuffer = encodedVertexBuffer.subarray(vertexCount, 2 * vertexCount);
  399. var heightBuffer = encodedVertexBuffer.subarray(vertexCount * 2, 3 * vertexCount);
  400. var i;
  401. var u = 0;
  402. var v = 0;
  403. var height = 0;
  404. function zigZagDecode(value) {
  405. return (value >> 1) ^ (-(value & 1));
  406. }
  407. for (i = 0; i < vertexCount; ++i) {
  408. u += zigZagDecode(uBuffer[i]);
  409. v += zigZagDecode(vBuffer[i]);
  410. height += zigZagDecode(heightBuffer[i]);
  411. uBuffer[i] = u;
  412. vBuffer[i] = v;
  413. heightBuffer[i] = height;
  414. }
  415. // skip over any additional padding that was added for 2/4 byte alignment
  416. if (pos % bytesPerIndex !== 0) {
  417. pos += (bytesPerIndex - (pos % bytesPerIndex));
  418. }
  419. var triangleCount = view.getUint32(pos, true);
  420. pos += Uint32Array.BYTES_PER_ELEMENT;
  421. var indices = IndexDatatype.createTypedArrayFromArrayBuffer(vertexCount, buffer, pos, triangleCount * triangleElements);
  422. pos += triangleCount * triangleLength;
  423. // High water mark decoding based on decompressIndices_ in webgl-loader's loader.js.
  424. // https://code.google.com/p/webgl-loader/source/browse/trunk/samples/loader.js?r=99#55
  425. // Copyright 2012 Google Inc., Apache 2.0 license.
  426. var highest = 0;
  427. for (i = 0; i < indices.length; ++i) {
  428. var code = indices[i];
  429. indices[i] = highest - code;
  430. if (code === 0) {
  431. ++highest;
  432. }
  433. }
  434. var westVertexCount = view.getUint32(pos, true);
  435. pos += Uint32Array.BYTES_PER_ELEMENT;
  436. var westIndices = IndexDatatype.createTypedArrayFromArrayBuffer(vertexCount, buffer, pos, westVertexCount);
  437. pos += westVertexCount * bytesPerIndex;
  438. var southVertexCount = view.getUint32(pos, true);
  439. pos += Uint32Array.BYTES_PER_ELEMENT;
  440. var southIndices = IndexDatatype.createTypedArrayFromArrayBuffer(vertexCount, buffer, pos, southVertexCount);
  441. pos += southVertexCount * bytesPerIndex;
  442. var eastVertexCount = view.getUint32(pos, true);
  443. pos += Uint32Array.BYTES_PER_ELEMENT;
  444. var eastIndices = IndexDatatype.createTypedArrayFromArrayBuffer(vertexCount, buffer, pos, eastVertexCount);
  445. pos += eastVertexCount * bytesPerIndex;
  446. var northVertexCount = view.getUint32(pos, true);
  447. pos += Uint32Array.BYTES_PER_ELEMENT;
  448. var northIndices = IndexDatatype.createTypedArrayFromArrayBuffer(vertexCount, buffer, pos, northVertexCount);
  449. pos += northVertexCount * bytesPerIndex;
  450. var encodedNormalBuffer;
  451. var waterMaskBuffer;
  452. while (pos < view.byteLength) {
  453. var extensionId = view.getUint8(pos, true);
  454. pos += Uint8Array.BYTES_PER_ELEMENT;
  455. var extensionLength = view.getUint32(pos, provider._littleEndianExtensionSize);
  456. pos += Uint32Array.BYTES_PER_ELEMENT;
  457. if (extensionId === QuantizedMeshExtensionIds.OCT_VERTEX_NORMALS && provider._requestVertexNormals) {
  458. encodedNormalBuffer = new Uint8Array(buffer, pos, vertexCount * 2);
  459. } else if (extensionId === QuantizedMeshExtensionIds.WATER_MASK && provider._requestWaterMask) {
  460. waterMaskBuffer = new Uint8Array(buffer, pos, extensionLength);
  461. }
  462. pos += extensionLength;
  463. }
  464. var skirtHeight = provider.getLevelMaximumGeometricError(level) * 5.0;
  465. var rectangle = provider._tilingScheme.tileXYToRectangle(x, y, level);
  466. var orientedBoundingBox;
  467. if (rectangle.width < CesiumMath.PI_OVER_TWO + CesiumMath.EPSILON5) {
  468. // Here, rectangle.width < pi/2, and rectangle.height < pi
  469. // (though it would still work with rectangle.width up to pi)
  470. // The skirt is not included in the OBB computation. If this ever
  471. // causes any rendering artifacts (cracks), they are expected to be
  472. // minor and in the corners of the screen. It's possible that this
  473. // might need to be changed - just change to `minimumHeight - skirtHeight`
  474. // A similar change might also be needed in `upsampleQuantizedTerrainMesh.js`.
  475. orientedBoundingBox = OrientedBoundingBox.fromRectangle(rectangle, minimumHeight, maximumHeight, provider._tilingScheme.ellipsoid);
  476. }
  477. return new QuantizedMeshTerrainData({
  478. center: center,
  479. minimumHeight: minimumHeight,
  480. maximumHeight: maximumHeight,
  481. boundingSphere: boundingSphere,
  482. orientedBoundingBox: orientedBoundingBox,
  483. horizonOcclusionPoint: horizonOcclusionPoint,
  484. quantizedVertices: encodedVertexBuffer,
  485. encodedNormals: encodedNormalBuffer,
  486. indices: indices,
  487. westIndices: westIndices,
  488. southIndices: southIndices,
  489. eastIndices: eastIndices,
  490. northIndices: northIndices,
  491. westSkirtHeight: skirtHeight,
  492. southSkirtHeight: skirtHeight,
  493. eastSkirtHeight: skirtHeight,
  494. northSkirtHeight: skirtHeight,
  495. childTileMask: getChildMaskForTile(provider, level, x, tmsY),
  496. waterMask: waterMaskBuffer
  497. });
  498. }
  499. /**
  500. * Requests the geometry for a given tile. This function should not be called before
  501. * {@link CesiumTerrainProvider#ready} returns true. The result must include terrain data and
  502. * may optionally include a water mask and an indication of which child tiles are available.
  503. *
  504. * @param {Number} x The X coordinate of the tile for which to request geometry.
  505. * @param {Number} y The Y coordinate of the tile for which to request geometry.
  506. * @param {Number} level The level of the tile for which to request geometry.
  507. * @param {Boolean} [throttleRequests=true] True if the number of simultaneous requests should be limited,
  508. * or false if the request should be initiated regardless of the number of requests
  509. * already in progress.
  510. * @returns {Promise.<TerrainData>|undefined} A promise for the requested geometry. If this method
  511. * returns undefined instead of a promise, it is an indication that too many requests are already
  512. * pending and the request will be retried later.
  513. *
  514. * @exception {DeveloperError} This function must not be called before {@link CesiumTerrainProvider#ready}
  515. * returns true.
  516. */
  517. InfoCesiumTerrainProvider.prototype.requestTileGeometry = function (x, y, level, throttleRequests) {
  518. //>>includeStart('debug', pragmas.debug)
  519. if (!this._ready) {
  520. throw new DeveloperError('requestTileGeometry must not be called before the terrain provider is ready.');
  521. }
  522. //>>includeEnd('debug');
  523. var urlTemplates = this._tileUrlTemplates;
  524. if (urlTemplates.length === 0) {
  525. return undefined;
  526. }
  527. var yTiles = this._tilingScheme.getNumberOfYTilesAtLevel(level);
  528. // var tmsY = (yTiles - y - 1);
  529. var tmsY = y;
  530. // var tmsY = y;
  531. // var url = urlTemplates + '?l=' + level + '&x=' + x + '&y=' + tmsY + '&ticket=999999';
  532. // console.log("--->"+y);
  533. if (level > 1) {
  534. //tmsY = Math.round(tmsY/2) + Math.pow(2,level-2);
  535. tmsY = parseInt(y / 2 + yTiles / (4));
  536. }
  537. var tmsx = parseInt(x / 2);
  538. //var url = urlTemplates[(x + tmsY + level) % urlTemplates.length].replace('{z}', level).replace('{x}', x).replace('{y}', x+"_"+tmsY);
  539. var url = urlTemplates + '?l=' + level + '&x=' + tmsx + '&y=' + tmsY + '&ticket=999999';
  540. //console.log(yTiles);
  541. // console.log(tmsY);
  542. // console.log(level);
  543. // var url = urlTemplates + '?l=' + level + '&x=' + y + '&y=' + x + '&ticket=999999';
  544. //console.log(url);
  545. var proxy = this._proxy;
  546. if (defined(proxy)) {
  547. url = proxy.getURL(url);
  548. }
  549. var promise;
  550. var extensionList = [];
  551. if (this._requestVertexNormals && this._hasVertexNormals) {
  552. extensionList.push(this._littleEndianExtensionSize ? "octvertexnormals" : "vertexnormals");
  553. }
  554. if (this._requestWaterMask && this._hasWaterMask) {
  555. extensionList.push("watermask");
  556. }
  557. function tileLoader(tileUrl) {
  558. return loadArrayBuffer(tileUrl, getRequestHeader(extensionList));
  559. }
  560. throttleRequests = defaultValue(throttleRequests, true);
  561. if (throttleRequests) {
  562. promise = throttleRequestByServer(url, tileLoader);
  563. if (!defined(promise)) {
  564. return undefined;
  565. }
  566. } else {
  567. promise = tileLoader(url);
  568. }
  569. var that = this;
  570. return when(promise, function (buffer) {
  571. // console.log(buffer.byteLength);
  572. if (defined(that._heightmapStructure)) {
  573. return createHeightmapTerrainData(that, buffer, level, x, y, tmsY);
  574. } else {
  575. return createQuantizedMeshTerrainData(that, buffer, level, x, y, tmsY);
  576. }
  577. });
  578. };
  579. defineProperties(InfoCesiumTerrainProvider.prototype, {
  580. /**
  581. * Gets an event that is raised when the terrain provider encounters an asynchronous error. By subscribing
  582. * to the event, you will be notified of the error and can potentially recover from it. Event listeners
  583. * are passed an instance of {@link TileProviderError}.
  584. * @memberof CesiumTerrainProvider.prototype
  585. * @type {Event}
  586. */
  587. errorEvent: {
  588. get: function () {
  589. return this._errorEvent;
  590. }
  591. },
  592. /**
  593. * Gets the credit to display when this terrain provider is active. Typically this is used to credit
  594. * the source of the terrain. This function should not be called before {@link CesiumTerrainProvider#ready} returns true.
  595. * @memberof CesiumTerrainProvider.prototype
  596. * @type {Credit}
  597. */
  598. credit: {
  599. get: function () {
  600. //>>includeStart('debug', pragmas.debug)
  601. if (!this._ready) {
  602. throw new DeveloperError('credit must not be called before the terrain provider is ready.');
  603. }
  604. //>>includeEnd('debug');
  605. return this._credit;
  606. }
  607. },
  608. /**
  609. * Gets the tiling scheme used by this provider. This function should
  610. * not be called before {@link CesiumTerrainProvider#ready} returns true.
  611. * @memberof CesiumTerrainProvider.prototype
  612. * @type {GeographicTilingScheme}
  613. */
  614. tilingScheme: {
  615. get: function () {
  616. //>>includeStart('debug', pragmas.debug)
  617. if (!this._ready) {
  618. throw new DeveloperError('tilingScheme must not be called before the terrain provider is ready.');
  619. }
  620. //>>includeEnd('debug');
  621. return this._tilingScheme;
  622. }
  623. },
  624. /**
  625. * Gets a value indicating whether or not the provider is ready for use.
  626. * @memberof CesiumTerrainProvider.prototype
  627. * @type {Boolean}
  628. */
  629. ready: {
  630. get: function () {
  631. return this._ready;
  632. }
  633. },
  634. /**
  635. * Gets a promise that resolves to true when the provider is ready for use.
  636. * @memberof CesiumTerrainProvider.prototype
  637. * @type {Promise.<Boolean>}
  638. * @readonly
  639. */
  640. readyPromise: {
  641. get: function () {
  642. return this._readyPromise.promise;
  643. }
  644. },
  645. /**
  646. * Gets a value indicating whether or not the provider includes a water mask. The water mask
  647. * indicates which areas of the globe are water rather than land, so they can be rendered
  648. * as a reflective surface with animated waves. This function should not be
  649. * called before {@link CesiumTerrainProvider#ready} returns true.
  650. * @memberof CesiumTerrainProvider.prototype
  651. * @type {Boolean}
  652. * @exception {DeveloperError} This property must not be called before {@link CesiumTerrainProvider#ready}
  653. */
  654. hasWaterMask: {
  655. get: function () {
  656. //>>includeStart('debug', pragmas.debug)
  657. if (!this._ready) {
  658. throw new DeveloperError('hasWaterMask must not be called before the terrain provider is ready.');
  659. }
  660. //>>includeEnd('debug');
  661. return this._hasWaterMask && this._requestWaterMask;
  662. }
  663. },
  664. /**
  665. * Gets a value indicating whether or not the requested tiles include vertex normals.
  666. * This function should not be called before {@link CesiumTerrainProvider#ready} returns true.
  667. * @memberof CesiumTerrainProvider.prototype
  668. * @type {Boolean}
  669. * @exception {DeveloperError} This property must not be called before {@link CesiumTerrainProvider#ready}
  670. */
  671. hasVertexNormals: {
  672. get: function () {
  673. //>>includeStart('debug', pragmas.debug)
  674. if (!this._ready) {
  675. throw new DeveloperError('hasVertexNormals must not be called before the terrain provider is ready.');
  676. }
  677. //>>includeEnd('debug');
  678. // returns true if we can request vertex normals from the server
  679. return this._hasVertexNormals && this._requestVertexNormals;
  680. }
  681. },
  682. /**
  683. * Boolean flag that indicates if the client should request vertex normals from the server.
  684. * Vertex normals data is appended to the standard tile mesh data only if the client requests the vertex normals and
  685. * if the server provides vertex normals.
  686. * @memberof CesiumTerrainProvider.prototype
  687. * @type {Boolean}
  688. */
  689. requestVertexNormals: {
  690. get: function () {
  691. return this._requestVertexNormals;
  692. }
  693. },
  694. /**
  695. * Boolean flag that indicates if the client should request a watermask from the server.
  696. * Watermask data is appended to the standard tile mesh data only if the client requests the watermask and
  697. * if the server provides a watermask.
  698. * @memberof CesiumTerrainProvider.prototype
  699. * @type {Boolean}
  700. */
  701. requestWaterMask: {
  702. get: function () {
  703. return this._requestWaterMask;
  704. }
  705. }
  706. });
  707. /**
  708. * Gets the maximum geometric error allowed in a tile at a given level.
  709. *
  710. * @param {Number} level The tile level for which to get the maximum geometric error.
  711. * @returns {Number} The maximum geometric error.
  712. */
  713. InfoCesiumTerrainProvider.prototype.getLevelMaximumGeometricError = function (level) {
  714. return this._levelZeroMaximumGeometricError / (1 << level);
  715. };
  716. function getChildMaskForTile(terrainProvider, level, x, y) {
  717. var available = terrainProvider._availableTiles;
  718. if (!available || available.length === 0) {
  719. return 15;
  720. }
  721. var childLevel = level + 1;
  722. if (childLevel >= available.length) {
  723. return 0;
  724. }
  725. var levelAvailable = available[childLevel];
  726. var mask = 0;
  727. mask |= isTileInRange(levelAvailable, 2 * x, 2 * y) ? 1 : 0;
  728. mask |= isTileInRange(levelAvailable, 2 * x + 1, 2 * y) ? 2 : 0;
  729. mask |= isTileInRange(levelAvailable, 2 * x, 2 * y + 1) ? 4 : 0;
  730. mask |= isTileInRange(levelAvailable, 2 * x + 1, 2 * y + 1) ? 8 : 0;
  731. return mask;
  732. }
  733. function isTileInRange(levelAvailable, x, y) {
  734. for (var i = 0, len = levelAvailable.length; i < len; ++i) {
  735. var range = levelAvailable[i];
  736. if (x >= range.startX && x <= range.endX && y >= range.startY && y <= range.endY) {
  737. return true;
  738. }
  739. }
  740. return false;
  741. }
  742. /**
  743. * Determines whether data for a tile is available to be loaded.
  744. *
  745. * @param {Number} x The X coordinate of the tile for which to request geometry.
  746. * @param {Number} y The Y coordinate of the tile for which to request geometry.
  747. * @param {Number} level The level of the tile for which to request geometry.
  748. * @returns {Boolean} Undefined if not supported, otherwise true or false.
  749. */
  750. InfoCesiumTerrainProvider.prototype.getTileDataAvailable = function (x, y, level) {
  751. var available = this._availableTiles;
  752. if (!available || available.length === 0) {
  753. return undefined;
  754. } else {
  755. if (level >= available.length) {
  756. return false;
  757. }
  758. var levelAvailable = available[level];
  759. var yTiles = this._tilingScheme.getNumberOfYTilesAtLevel(level);
  760. var tmsY = (yTiles - y - 1);
  761. return isTileInRange(levelAvailable, x, tmsY);
  762. }
  763. };
  764. return InfoCesiumTerrainProvider;
  765. });