赞
踩
Cesium中的3DTiles数据加载的过程中会进行缓存,使用的是Cesium3DTilesetCache这个类,这个类中维护了一个双向链表DoublyLinkedList,链表的每个节点DoublyLinkedListNode包含了3部分内容,item(即tile)、previous、next,而DoublyLinkedList维护了链表的head和tail游标,并包含三个方法remove(移除节点)、add(添加节点)、slice(移动节点)。
对于Cesium3DTilesetCache,这个类中使用了一个空节点sentinel(哨兵),这个节点的在链表中起到隔离作用,每一帧中这个哨兵节点都可能会移动,哨兵的左边是当前帧之前缓存的瓦片(数据已经下载完成)节点,右边是当前帧需要的瓦片节点,其中左边的节点受到瓦片集的最大内存选项maximumMemoryUsage和是否剔除的标记trimTiles以及sentinel的三方挟持,只要有一方不满足条件就会删除已经缓存的节点,在当前帧中会检索是否之前缓存的节点在当前帧中可以重复利用,如果是则会将该节点从哨兵的左边移动到哨兵的右边,当前帧处理完成后,哨兵节点会reset到链表的尾部,并进行新一轮的哨兵移动。
- /**
- * Stores tiles with content loaded.
- * 用来存储已经加载完成的带有数据的瓦片
- *
- * @private
- */
- function Cesium3DTilesetCache() {
- // [head, sentinel) -> tiles that weren't selected this frame and may be removed from the cache
- // (sentinel, tail] -> tiles that were selected this frame
- // 双向链表
- this._list = new DoublyLinkedList();
- // 哨兵(空节点)
- this._sentinel = this._list.add();
- this._trimTiles = false;
- }
-
- // 重置时把哨兵节点移动到末尾
- Cesium3DTilesetCache.prototype.reset = function () {
- // Move sentinel node to the tail so, at the start of the frame, all tiles
- // may be potentially replaced. Tiles are moved to the right of the sentinel
- // when they are selected so they will not be replaced.
- // 把哨兵节点移动到链表的末尾,在一帧的开始,所有的瓦片可能被替换,可见的瓦片将被移动到链表的右边,它们不能被替换
- this._list.splice(this._list.tail, this._sentinel);
- };
-
- // 节点移动到哨兵的后边(从原来缓存的数据中拿到可以使用的节点然后移动到哨兵的右边)
- Cesium3DTilesetCache.prototype.touch = function (tile) {
- var node = tile.cacheNode;
- if (defined(node)) {
- // 节点移动到哨兵节点的后面
- this._list.splice(this._sentinel, node);
- }
- };
-
- // 在末尾添加节点,这个节点一定在哨兵的后面
- Cesium3DTilesetCache.prototype.add = function (tile) {
- // 如果瓦片的缓存结点不存在就创建
- if (!defined(tile.cacheNode)) {
- tile.cacheNode = this._list.add(tile);
- }
- };
-
- // 卸载瓦片的缓存节点
- Cesium3DTilesetCache.prototype.unloadTile = function (
- tileset,
- tile,
- unloadCallback
- ) {
- var node = tile.cacheNode;
- // 未定义就返回
- if (!defined(node)) {
- return;
- }
-
- // 链表中移除节点
- this._list.remove(node);
- // 清空
- tile.cacheNode = undefined;
- // 回调
- unloadCallback(tileset, tile);
- };
-
- // 卸载瓦片集
- Cesium3DTilesetCache.prototype.unloadTiles = function (
- tileset,
- unloadCallback
- ) {
- var trimTiles = this._trimTiles;
- this._trimTiles = false;
-
- // 链表
- var list = this._list;
-
- // 最大缓存(MB转换为字节)
- var maximumMemoryUsageInBytes = tileset.maximumMemoryUsage * 1024 * 1024;
-
- // Traverse the list only to the sentinel since tiles/nodes to the
- // right of the sentinel were used this frame.
- // 遍历列表列表,只遍历哨兵左边的节点,因为哨兵右边的节点是正在使用的
- //
- // The sub-list to the left of the sentinel is ordered from LRU to MRU.
-
- // 哨兵
- var sentinel = this._sentinel;
- // 头节点
- var node = list.head;
-
- while (
- node !== sentinel && // 不是哨兵节点
- (tileset.totalMemoryUsageInBytes > maximumMemoryUsageInBytes || trimTiles) // 缓存没有超过界限就不删除
- ) {
- // 获取节点的数据
- var tile = node.item;
- // 遍历下一个节点
- node = node.next;
- // 卸载节点
- this.unloadTile(tileset, tile, unloadCallback);
- }
- };
-
- // 减少瓦片的缓存(cpu中)
- Cesium3DTilesetCache.prototype.trim = function () {
- this._trimTiles = true;
- };
- export default Cesium3DTilesetCache;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。