轉載請規範聲明。@秋意正寒 http://www.javashuo.com/article/p-vydtlexa-mv.html
個人git地址:github.com/onsummerhtml
pnts,即 Points
,點雲的意思。git
las、xyz數據等都可。github
pnts不存在gltf模型,故結構以下:json
與b3dm是同樣的。數組
屬性的官方名稱 | 字節長 | 類型 | 含義 |
---|---|---|---|
magic |
4 | string(或char[4]) | 該瓦片文件的類型,在pnts中是 "pnts" |
version |
4 | uint32 | 該瓦片的版本,目前限定是 1. |
byteLength |
4 | uint32 | 該瓦片文件的文件大小,單位:byte |
featureTableJSONByteLength |
4 | uint32 | 要素表的JSON文本(二進制形式)長度 |
featureTableBinaryByteLength |
4 | uint32 | 要素表的二進制數據長度 |
batchTableJSONByteLength |
4 | uint32 | 批量表的JSON文本(二進制形式)長度 |
batchTableBinaryByteLength |
4 | uint32 | 批量表的二進制數據長度 |
在 b3dm 篇,有介紹到要素表存在 全局屬性 和 要素屬性。在 pnts 和上篇 i3dm 中,這對概念會解釋得很透徹。佈局
屬性名 | 數據類型 | 描述 | 是否必須 |
---|---|---|---|
POINTS_LENGTH | uint32 | 瓦片中點的數量。全部的點屬性的長度必須與這個同樣。 | 必須存在 |
RTC_CENTER | float32 * 3 | 若是全部點是相對於某個點定位的,那麼這個屬性就是這個相對的點的座標。 | 沒必要須 |
QUANTIZED_VOLUME_OFFSET | float32 * 3 | 量化偏移值 | 與QUANTIZED_VOLUME_SCALE屬性必須同時存在或同時不存在 |
QUANTIZED_VOLUME_SCALE | float32 * 3 | 量化縮放比例 | 與QUANTIZED_VOLUME_OFFSET屬性必須同時存在或同時不存在 |
CONSTANT_RGBA | uint8 * 4 | 爲全部點定義同一個顏色 | 沒必要須 |
BATCH_LENGTH | uint32 | BATCH_ID的個數 | 與點屬性中的BATCH_ID必須同時存在或者同時不存在 |
第一第二個能與 b3dm 中的 BATCH_LENGTH
和 RTC_CENTER
類比來理解,就不解釋了。ui
第三、4個與 i3dm 是一致的。編碼
第5個即每一個點的默認顏色,默認是灰色。spa
最後一個頗有意思,和 b3dm 裏的「重合」了,它的意義是:點雲瓦片中這麼多點是能夠劃分的,每一類叫作 BATCH。3d
例如對一棟建築進行點雲掃射,那麼牆體的全部的點能夠歸屬爲 牆體BATCH,窗戶的全部點能夠歸屬爲 窗戶BATCH。
BATCH_LENGTH
指示了當前pnts瓦片的點被劃分紅了多少個類別。
RGBA
>RGB
>RGB565
>CONSTANT_RGBA
。其中,CONSTANT_RGBA
是全局的,前三個是點要素屬性裏的。
固然,還可使用 3dTiles 的 style 來改變樣式。
這個詞兒是我本身意譯的。
一般點雲數據只留其「形」,而具體每一個點的座標能夠不那麼精確。由於存儲高精度的點座標,是十分消耗空間的。默認每一個點使用逐要素屬性 POSITION
來記錄每一個點的座標,座標值類型是 FLOAT
,即 4字節,假如使用量化座標,每一個座標值使用 UInt16
類型,即 2字節,那麼座標信息就能壓縮一倍!
具體什麼是 量化空間範圍體,我認爲在上一篇 i3dm 中已經解釋得很清楚了:
只不過,在點雲瓦片中,POSITION
表明的再也不是 instance 的座標,而是點座標。
看到這,是否能理解「要素表的全局屬性是對於整個瓦片文件而言」這句話了呢?
其實,我以爲在點雲中叫 點屬性 更好。
屬性名 | 數據類型 | 描述 | 是否必須 |
---|---|---|---|
POSITION | float32 * 3 | 直角座標的點 | 是,除非POSITION_QUANTIZED屬性存在 |
POSITION_QUANTIZED | uint16 * 3 | 量化空間範圍體內的直角座標點 | 是,除非POSITION屬性存在 |
RGBA | uint8 * 4 | 四通道顏色 | 沒必要須 |
RGB | uint8 * 3 | RGB顏色 | 沒必要須 |
RGB565 | uint16 | 有損壓縮顏色,紅5綠6藍5,即65536種顏色 | 沒必要須 |
NORMAL | float32 *3 | 法線 | 沒必要須 |
NORMAL_OCT16P | uint8 * 2 | 點的法線,10進制單位向量,有16bit精度 | 沒必要須 |
BATCH_ID | uint8/uint16(默認)/uint32 | 從BatchTable種檢索元數據的id | 沒必要須,取決於全局屬性BATCH_LENGTH |
其中,第一和第二個與 i3dm 中的定義一致。
第三~第五個是顏色信息,在第①小節中的a部分講了。
第6、七與 i3dm 中的相似。
第八個與 i3dm 中的定義徹底一致。
上述全部屬性所有會記錄在要素表的 JSON 中,對於 全局屬性,其值記錄在 JSON 中。
對於其要素屬性,由於點雲中的點數量會很是巨大,寫在JSON中體積會變大,因此使用 JSON引用要素表二進制數據體 的形式。
下列是一個要素表的JSON:
{ POINTS_LENGTH : 4, // 意味着有4個點 POSITION : { byteOffset : 0 // 意味着從ftBinary的第0個byte開始讀取 } }
這個要素表的釋義與 i3dm 中的示例同樣,只不過從 INSTANCES_LENGTH
變成了 POINTS_LENGTH
。
要素表JSON中引用的二進制數據均順次記錄在此,通常爲要素屬性(點屬性)。
批量表與b3dm的差很少,若是在 pnts 的要素表和批量表中存儲了 BATCH_LENGTH
信息,那每一個 BATCH 的屬性就存於此。
可是與 b3dm、i3dm 略有不一樣的是,若是要素表JSON中沒有 BATCH_ID
的定義,可是批量表中卻存在與點的數量 POINTS_LENGTH
同樣長的屬性數組,那麼說明該點雲瓦片的每個點都有屬性。
結構參考 b3dm 篇章。
此部分參考官方文檔。
const featureTableJSON = { POINTS_LENGTH : 4, // 意味着有4個點 POSITION : { byteOffset : 0 // 意味着從ftBinary的第0個byte開始讀取 } } const featureTableBinary = new Buffer(new Float32Array([ 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0 ]).buffer)
這個例子只記錄了4個點。
const featureTableJSON = { POINTS_LENGTH : 4, // 意味着有4個點 RTC_CENTER : [1215013.8, -4736316.7, 4081608.4], // 意味着相對於這個點 POSITION : { byteOffset : 0 // 意味着從ftBinary的第0個byte開始讀取 }, RGB : { byteOffset : 48 // 顏色值意味着從ftBinary的第48個byte讀取,緊接在POSITION後 } } const positionBinary = new Buffer(new Float32Array([ 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0 ]).buffer) // 一共12*4byte = 48byte const colorBinary = new Buffer(new Uint8Array([ 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 0, ]).buffer) // 一共12*1byte = 12byte // ftBinary一共48+12=60byte const featureTableBinary = Buffer.concat([positionBinary, colorBinary])
這個例子有4個點,是相對於中心定位的點。顏色依次爲:紅綠藍黃。
const featureTableJSON = { POINTS_LENGTH : 4, // 意味着有4個點 QUANTIZED_VOLUME_OFFSET : [-250.0, 0.0, -250.0], // 意味着偏移基座標是 (-250, 0, -250) QUANTIZED_VOLUME_SCALE : [500.0, 0.0, 500.0], // 意味着x和z方向的縮放比是500 POSITION_QUANTIZED : { byteOffset : 0 // 意味着量化座標的數據存在ftBinary的第0個字節日後 }, NORMAL_OCT16P : { byteOffset : 24 // 意味着量化座標頂點法線的數據存在ftBinary的第24個字節日後 } } const positionQuantizedBinary = new Buffer(new Uint16Array([ 0, 0, 0, 65535, 0, 0, 0, 0, 65535, 65535, 0, 65535 ]).buffer) // 一共12*2byte=24byte,Uint16=16bit=2byte const normalOct16PBinary = new Buffer(new Uint8Array([ 128, 255, 128, 255, 128, 255, 128, 255 ]).buffer) // 一共8*1=8byte,Uint8=8bit=1byte const featureTableBinary = Buffer.concat([positionQuantizedBinary, normalOct16PBinary])
這個例子中,有4個點,每一個點的法向量都是八進制編碼的\([0.0, 1.0, 0.0]\),它們將被放置在x和z方向上.
const featureTableJSON = { POINTS_LENGTH : 4, // 意味着有4個點 BATCH_LENGTH : 2, // 意味着4個點分紅了2類(批、batch) POSITION : { byteOffset : 0 // 意味着POSITION將存儲在ftBinary的第 0 byte以後 }, BATCH_ID : { byteOffset : 48, // 意味着BATCH_ID的值將從ftBinary的第 48 byte以後 componentType : "UNSIGNED_BYTE" // 意味着BATCH_ID的值類型是無符號字節數 } } const positionBinary = new Buffer(new Float32Array([ 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0 ]).buffer) // 4個點,一共12個值,每一個值4byte(Float每一個數字佔4byte,即32bit),一共48byte const batchIdBinary = new Buffer(new Uint8Array([ 0, 0, 1, 1 ]).buffer) // 前2個的類型是0(batchId),後2個點的類型是1 const featureTableBinary = Buffer.concat([positionBinary, batchIdBinary]); // 合併 const batchTableJSON = { names : ['object1', 'object2'] } // 批量表JSON記錄了屬性值,有兩個,恰好對上 BATCH_LENGTH
這個例子中,前2個點的 batchId
是0,後2個點的 batchId
是1。
const featureTableJSON = { POINTS_LENGTH : 4, // 意味着有4個點 POSITION : { byteOffset : 0 // 意味着從ftBinary的第0byte開始 } } const featureTableBinary = new Buffer(new Float32Array([ 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0 ]).buffer) const batchTableJSON = { names : ['point1', 'point2', 'point3', 'point4'] // 意味着這4個點都有names屬性,其值寫在這裏 }
若是在 要素表中沒有 BATCH_ID
屬性的定義,而且批量表中存有屬性數據,那麼這些屬性的個數一定與點的個數相同,即每一個點都有屬性。
與b3dm裏寫的一致,能夠回看:http://www.javashuo.com/article/p-hcrvzhto-nh.html
一樣,這部份內容與b3dm篇章內介紹的一致,會在後續文章內介紹。