TileEntity.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // 物体状态
  2. var EntityState = {
  3. FAILED: 0,
  4. UNLOADED: 1,
  5. RECEIVING: 2,
  6. RECEIVED: 3,
  7. TRANSFORMING: 4,
  8. TRANSFORMED: 5,
  9. READY: 6
  10. };
  11. /**
  12. * 物体瓦片,负责管理瓦片内物体的加载过程。
  13. * @param provider
  14. * @constructor
  15. */
  16. function TileEntity(provider) {
  17. if (!Cesium.defined(provider)) {
  18. throw new DeveloperError('provider is required.');
  19. }
  20. this.provider = provider;
  21. this.state = EntityState.UNLOADED;
  22. this.buffers = [];
  23. this.dataList = [];
  24. }
  25. /**
  26. * Processes the load state machine for this instance.
  27. *
  28. */
  29. TileEntity.prototype.processStateMachine = function (frameState, entityProvider, x, y, level, priorityFunction) {
  30. if (this.state === EntityState.UNLOADED) {
  31. requestEntityData(this, entityProvider, x, y, level, priorityFunction);
  32. }
  33. if (this.state === EntityState.RECEIVED) {
  34. transform(this, frameState, entityProvider, x, y, level);
  35. }
  36. if (this.state === EntityState.TRANSFORMED) {
  37. createResources(this, frameState.context, entityProvider, x, y, level);
  38. }
  39. if (this.state === EntityState.READY) {
  40. return true; // done loading
  41. }
  42. // 没有加载完成也应该使用父节点的,不能四个子节点都使用父节点显示那样就重复了;可以给节点增加计数,确保每个节点只显示一次。
  43. // 目前所有父节点都是可见,后期再完善。
  44. // Find some ancestor imagery we can use while this imagery is still loading.
  45. // var ancestor = this.parent;
  46. // var closestAncestorThatNeedsLoading;
  47. // while (defined(ancestor) && (ancestor.state !== ImageryState.READY || (!this.useWebMercatorT && !defined(ancestor.texture)))) {
  48. // if (ancestor.state !== ImageryState.FAILED && ancestor.state !== ImageryState.INVALID) {
  49. // // ancestor is still loading
  50. // closestAncestorThatNeedsLoading = closestAncestorThatNeedsLoading || ancestor;
  51. // }
  52. // ancestor = ancestor.parent;
  53. // }
  54. //
  55. // if (this.readyImagery !== ancestor) {
  56. // if (defined(this.readyImagery)) {
  57. // this.readyImagery.releaseReference();
  58. // }
  59. //
  60. // this.readyImagery = ancestor;
  61. //
  62. // if (defined(ancestor)) {
  63. // ancestor.addReference();
  64. // this.textureTranslationAndScale = imageryLayer._calculateTextureTranslationAndScale(tile, this);
  65. // }
  66. // }
  67. if (this.state === EntityState.FAILED) {
  68. // The imagery tile is failed or invalid, so we'd like to use an ancestor instead.
  69. // if (defined(closestAncestorThatNeedsLoading)) {
  70. // // Push the ancestor's load process along a bit. This is necessary because some ancestor imagery
  71. // // tiles may not be attached directly to a terrain tile. Such tiles will never load if
  72. // // we don't do it here.
  73. // closestAncestorThatNeedsLoading.processStateMachine(frameState, !this.useWebMercatorT, tile._priorityFunction);
  74. // return false; // not done loading
  75. // }
  76. // This imagery tile is failed or invalid, and we have the "best available" substitute.
  77. return true; // done loading
  78. }
  79. return false; // not done loading
  80. }
  81. function requestEntityData(tileEntity, entityProvider, x, y, level, priorityFunction) {
  82. function success(buffers) {
  83. if (!Cesium.defined(buffers)) {
  84. tileEntity.state = EntityState.UNLOADED;
  85. tileEntity.request = undefined;
  86. return;
  87. }
  88. tileEntity.buffers = buffers;
  89. tileEntity.state = EntityState.RECEIVED;
  90. tileEntity.request = undefined;
  91. }
  92. function failure() {
  93. if (tileEntity.request.state === RequestState.CANCELLED) {
  94. // Cancelled due to low priority - try again later.
  95. tileEntity.state = EntityState.UNLOADED;
  96. tileEntity.request = undefined;
  97. return;
  98. }
  99. // Initially assume failure. handleError may retry, in which case the state will
  100. // change to RECEIVING or UNLOADED.
  101. tileEntity.state = EntityState.FAILED;
  102. tileEntity.request = undefined;
  103. var message = 'Failed to obtain entity tile X: ' + x + ' Y: ' + y + ' Level: ' + level + '.';
  104. entityProvider._requestError = Cesium.TileProviderError.handleError(
  105. entityProvider._requestError,
  106. entityProvider,
  107. entityProvider.errorEvent,
  108. message,
  109. x, y, level,
  110. doRequest);
  111. }
  112. function doRequest() {
  113. // Request the entity data from the entity provider.
  114. var request = new Cesium.Request({
  115. throttle: true,
  116. throttleByServer: true,
  117. type: Cesium.RequestType.TILES3D,
  118. priorityFunction: priorityFunction
  119. });
  120. tileEntity.request = request;
  121. var data = entityProvider.requestEntityData(x, y, level, request);
  122. // If the request method returns undefined (instead of a promise), the request
  123. // has been deferred.
  124. if (Cesium.defined(data)) {
  125. tileEntity.state = tileEntity.RECEIVING;
  126. Cesium.when(data, success, failure);
  127. } else {
  128. // Deferred - try again later.
  129. //tileEntity.state = EntityState.UNLOADED;
  130. tileEntity.request = undefined;
  131. tileEntity.state = EntityState.FAILED;
  132. }
  133. }
  134. doRequest();
  135. }
  136. function transform(tileEntity, frameState, provider, x, y, level) {
  137. if (!Cesium.defined(tileEntity.buffers)) {
  138. return null;
  139. }
  140. // 解析数据(也可以放在分支线程)
  141. for (var i = 0, len = tileEntity.buffers.length; i < len; ++i) {
  142. var stream = new MemStream(tileEntity.buffers[i]);
  143. var version = stream.readInt32();
  144. var count = stream.readInt32();
  145. for (var j = 0; j < count; ++j) {
  146. var lon = stream.readFloat();
  147. var lat = stream.readFloat();
  148. var h = stream.readFloat();
  149. var text = '';
  150. var textLen = stream.readUChar8();
  151. if (textLen > 0) {
  152. var strData = stream.readUChar8Array2(textLen);
  153. text = new TextDecoder("utf-8").decode(strData);
  154. text = text.replace(/\|/g, ''); // 替换掉所有的|字符
  155. }
  156. var useFont = provider.fontSize * 2 + "px " + provider.fontFamily;
  157. var entity = provider.viewer.entities.add({
  158. parent: provider.fatherGroup,
  159. position: Cesium.Cartesian3.fromDegrees(lon, lat, h),
  160. label: {
  161. text: text,
  162. font: useFont,
  163. fillColor: Cesium.Color.WHITE,
  164. outlineColor: Cesium.Color.BLACK,
  165. outlineWidth: 6,
  166. style: Cesium.LabelStyle.FILL_AND_OUTLINE,
  167. scale: 0.5
  168. }
  169. });
  170. tileEntity.dataList.push(entity.id); // 保留id供移除时使用
  171. }
  172. }
  173. tileEntity.buffers.length = 0;
  174. tileEntity.state = EntityState.TRANSFORMING;
  175. // 如果是在其他线程做,完成后再改变状态
  176. // when(meshPromise, function(mesh) {
  177. // tileTerrain.mesh = mesh;
  178. // tileTerrain.state = TerrainState.TRANSFORMED;
  179. // }, function() {
  180. // tileTerrain.state = TerrainState.FAILED;
  181. // });
  182. tileEntity.state = EntityState.TRANSFORMED;
  183. }
  184. function createResources(tileEntity, context) {
  185. // 使用现有的结构就不手动构建渲染单元了
  186. // tileTerrain.vertexArray = new VertexArray({
  187. // context : context,
  188. // attributes : attributes,
  189. // indexBuffer : indexBuffer
  190. // });
  191. tileEntity.state = EntityState.READY;
  192. }
  193. TileEntity.prototype.freeResources = function () {
  194. for (var i = 0, len = this.dataList.length; i < len; ++i) {
  195. this.provider.viewer.entities.removeById(this.dataList[i]);
  196. }
  197. this.dataList.length = 0;
  198. this.buffers.length = 0;
  199. };