3D Tiles 是爲流式處理和渲染海量3D地理空間數據而設計的,例如傾斜攝影、BIM、CAD。定義了一種數據分層結構和一組切片格式,用於渲染數據內容,對於數據可視化沒有明確的規則,可以自定義規則。
tileset是被一組切片組織成的空間數據結構(樹),一個tileset至少有一個tileset Json文件描述,tileset JSON包含tileset元數據和tile對象樹。
切片內容是一個二進制的blob與特定格式的部分,包括一個要素表和批處理表。每個要素的位置和外觀屬性都存儲在切片要素表中,以及存儲在批處理表中的用於特定程序的屬性,客戶端在運行時選擇要素,並檢索其屬性以進行可視化顯示或者分析。
批量3D模型和實例3D模型是基於glTF構建的,glTF是一種專爲高效傳輸3D內容而設計的開放性規範。這種格式的切片內容在二進制體中嵌入了glTF數據,其中包含集合模型和紋理信息。
每個tile都具有邊界範圍框,邊界範圍框定義完全包圍其內容的空間範圍。樹具有空間一致性,子切片的內容完全在父圖像的邊界內。如下圖:
由於切片集的內容通常是不均勻的或者可能不容易僅在兩個維度中被組織起來,因此樹可以是具有空間相干性的任何空間數據結構,包括k-d樹,四叉樹,八叉樹和網格。
3D Tiles使用的文件擴展名和MIME類型:
tileset文件使用.json擴展名和application/json MIME類型;切片內容文件使用特定的文件類型和MIME格式來作爲切片格式規範;tileset樣式文件使用.json擴展名和application/json MIME類型。
3D Tiles使用URL來引用tile內容。當URL是相對時,其基數始終相對於引用的tileset JSON文件。
所有線性距離的單位都是米;所有角度都是弧度。
3D Tiles使用右手笛卡爾座標系;也就是說,x和y的矢量乘積產生z。3D Tiles將z軸定義爲局部笛卡爾座標系的向上。tileset的全局座標系通常是位於WGS84地球中心或者地球固定參考系中。可以應用附加的切片變換來將切片的局部座標系變換到父切片的座標系。區域邊界框使用地理座標系(經緯高度)來指定邊界。
邊界範圍框區域boundingVolume.region屬性是一個由6位數字組成的數組,用於定義具有緯度、經度和高度座標的邊界地理區域,其順序爲[西、南、東、北、最小高度、最大高度]
boundingVolume.box屬性是一個12個數字組成的數組,他們定義了右手3軸(x,y,z)笛卡爾座標系中的定向邊界框,其中z軸是向上的。前三個元素定義了邊界框中心的x,y,z值。接下來的三個元素定義x軸方向和半長度,接下來的三個元素定義了y軸方向和半長度,最後三個元素定義了z軸方向和半長度。
boundingVolume.sphere(球)屬性是一個由四個數字組成的數組,用於定義邊界球體。前三個定義右手3軸x,y,z笛卡爾座標系中球體中心的x/y/z,其中z軸是向上,最後一個元素定義以米爲單位的半徑。
Transforms(變換)是一個4*4仿射變換矩陣,以列優先順序進行存儲,從切片的局部座標系轉換到父切片的座標系,或者轉換到根切片的tileset座標系:
使用Cesium的Matrix4和Matrix3類型來計算它:
function computeTransforms(tileset){
var t=tileset.root;
var transformToRoot=defined(t.transform)?Matrix4.fromArray(t.transform):Matrix4.IDENTITY;
computeTransform(t,transformToRoot);
}
function computeTransform(title,transformToRoot){
var inverseTransform=Matrix4.inverse(transformToRoot,new Matrix4());
var normalTransform=Matrix4.getRotation(inverseTransform,new Matrix3());
normalTransform=Matrix3.transpose(normalTransform,normalTransform);
var children=tile.children;
var length=children.length;
for(var i=0;i<length;i++){
var child=children[i];
var childToRoot=defined(child.transform)?Matrix4.fromArray(child.transform):Matrix4.clone(Matrix4.IDENTITY);
childToRoot=Matrix4.multiplyTransformation(transformToRoot,childToRoot,childToRoot);
computeTransform(child,childToRoot)
}
}
Tile Json(切片json對象有以下屬性組成:
tileset由一個樹組成,其由root定義,子tile是遞歸的,可以由不同類型的空間數據結構組織。運行時引擎是通用的,它將呈現tileset定義的任何樹,可以使用切片格式和細化方法任意組合,從而實現支持異構數據集的靈活性。
3D Tiles如何表示各種空間數據結構:
四叉樹:當每個切片具有四個均勻細分的子切片(例如使用中心經度緯度),通過創建四叉樹來表示,類似於典型的2D地理空間切片方案,可以省略空子切片。3dtiles使用四叉樹的變體,例如非均勻細分和緊密邊界體積,比如父對象的25%,對於疏散數據集而言是浪費的。所以還可以使用鬆散四叉樹,其中子切片重疊但仍然保留空間連貫性,即父切片完全包圍其所有子切片,這種方法有助於避免將要素跨塊分隔。
K-d樹:當每個切片具有由平行於xyz的分隔平面分隔的兩個子切片時,創建k-d樹。當水平沿樹向下增加時,分隔軸通常是循環旋轉的,並且可以使用中值分隔。k-d樹不像典型的2D空間切片方案那樣具有統一的細分,因此可以爲稀疏和非均勻分佈的數據集來創建更均衡的樹。使用k-d樹時是多樣的,可以多路k-d樹,其在樹的每個葉子處,沿着軸有多個分裂。每個切片不是兩個子節點,而是有n個節點。
八叉樹:通過使用三個正交分隔平面來擴展四叉樹以將切片細分爲八個子元素。和四叉樹一樣,可以進行非均勻細分,緊密邊界範圍框和子切片重疊。
網格:通過支持任意數量的子切片來實現均勻、不均勻、重疊的網格。利用空的tile(具有邊界範圍框但是沒有內容的tile),由於不需要定義tile的content屬性,因此可以使用空的非葉子tile來加速具有分層剔除的非均勻網格。實際上是創建了一個沒有層次結構細節的四叉樹和八叉樹。
一個3D Tiles切片數據集json格式:
asset元數據,整個tileset的元數據:
邊界範圍框,boundingVolume,只需要一個box/region/sphere:
Tile切片屬性:
要素表(Feature Table)是切片的二進制文件的一部分,它描述了渲染切片中每個要素的位置和外觀屬性。
訪問position屬性:
var byteOffset=featureTableJSON.POSITION.byteOffset;
var positionArray=new Float32Array(featureTableBinary.buffer,byteOffset,featuresLength*3);
var position=positionArray.subarray(featureId*3,featureId*3+3);
批處理表是切片二進制體的一個組件,它包含切片中的每個要素應用與特定程序的屬性,在運行時查詢這些屬性,以用於聲明樣式和應用與任何特定程序的用例,例如填充UI或者發出REST API 請求。在js中可以使用TextDecoder JavaScript API從ArrayBuffer中提取批處理表JSON,並使用JSON.parse將其轉換爲js對象。
Binary body(二進制體),通過byteOffset來索引數據。
頂點來分配batchIds.
3D Tiles採用的是z-up座標系。
實例化3D模型:是一種切片格式,用於高效流式傳輸和渲染大量模型,稱爲實例。例如相同的樹模型可以在幾個地方定位或者實例化,每個實例引用相同的模型並具有每個實例的屬性,例如位置,每個實例都是一個要素。實例化3D模型可以很好的映射到ANGLE_instanced-arrays擴展,以便高效的進行webGL渲染。實例3D模型設計,主題部分有三個字段組成:要素表、批處理表和glTF。實例的方向由向上和向右矢量創建的標準正交基礎定義,方向通過切片變換進行轉換。標準基礎中的x向量映射到變換基礎中的右向量,y向量映射到向上的向量,z映射到正向向量。標準基準中的盒子:
實例的方向:如果不存在NORMAL_UP和normal_right或者NORMAL_UP_OCT32P和NORMAL_RIGHT-OCT32P,則實例沒有自定義方向。如果EAST_NORTH_UP爲真,則假定實例位於wgs84橢圓體上,並且其方向將默認爲其製圖爲真處的東/北/上參考系。
實例位置:可以相對於中心定義位置已進行高精度渲染。如果已經定義,則RTC_CENTER指定中心位置,並將所有實例位置視爲相對於此值。
量化位置:如果沒有爲實例定義POSITION,則其位置可以存儲在POSITION_QUANTIZED中,其定義相對於量化體積的實例位置。如果都沒有定義,則認爲實例不存在,不會創建實例。量化體積有偏移和比例定義,以將量化位置映射到局部空間。
可以使用以下公式將量化位置映射到局部空間:
position=position_quantized* quantized_volume_scale/ 65535.0+quantized_volume_offset;
實例縮放:SCALE和SCALE_NON_UNIFORM;scale沿所有軸應用均勻刻度,scale_non_unifrom獨立應用縮放到xyz軸。