Cesium開(kāi)發(fā)基礎(chǔ)篇 | 063D Tiles介紹及加載

上一節(jié)我們介紹了glTF的主要數(shù)據(jù)結(jié)構(gòu)以及Cesium是如何對(duì)其進(jìn)行加載的陨亡,這一節(jié)我們來(lái)介紹一下glTF的升級(jí)版3D Tiles 曲伊,也是目前 Cesium 在加載海量三維模型數(shù)據(jù)方面必須采用的一種數(shù)據(jù)格式贪磺。

3D Tiles介紹

3D Tiles 是在glTF的基礎(chǔ)上坯苹,加入了分層LOD的概念(可以把3D Tiles簡(jiǎn)單地理解為帶有 LOD 的 glTF )参咙,專(zhuān)門(mén)為流式傳輸和渲染海量 3D 地理空間數(shù)據(jù)而設(shè)計(jì)的犀农,例如傾斜攝影惰赋、3D 建筑、BIM/CAD呵哨、實(shí)例化要素集和點(diǎn)云赁濒。它定義了一種數(shù)據(jù)分層結(jié)構(gòu)和一組切片格式,用于渲染數(shù)據(jù)內(nèi)容孟害。3D Tiles 沒(méi)有為數(shù)據(jù)的可視化定義明確的規(guī)則流部,客戶(hù)可以按照自己合適的方式來(lái)可視化 3D 空間數(shù)據(jù)。同時(shí)纹坐,3D Tiles 也是 OGC 標(biāo)準(zhǔn)規(guī)范成員之一枝冀,可用于在臺(tái)式機(jī)、Web端和移動(dòng)應(yīng)用程序中實(shí)現(xiàn)與海量異構(gòu)3D地理空間數(shù)據(jù)的共享耘子、可視化果漾、融合以及交互功能。下圖的動(dòng)畫(huà)則是加入了LOD的效果:


帶有 LOD 的3D Tiles

在 3D Tiles 中谷誓,一個(gè)瓦片集(Tileset)是由一組瓦片(Tile)按照空間數(shù)據(jù)結(jié)構(gòu)(樹(shù)狀結(jié)構(gòu))組織而成的绒障,它至少包含一個(gè)用于描述瓦片集的 JSON 文件(包含瓦片集的元數(shù)據(jù)和瓦片對(duì)象),其中每一個(gè)瓦片對(duì)象可以引用下面的其中一種格式捍歪,用于渲染瓦片內(nèi)容:


瓦片的內(nèi)容(瓦片格式的一個(gè)單獨(dú)實(shí)例)是一個(gè)二進(jìn)制blob户辱,具有特定于格式的組件鸵钝,包括要素表(Feature Table)和批處理表(Batch Table)。瓦片內(nèi)容參考多種要素集特征庐镐,例如表示建筑物或樹(shù)木的 3D 模型或點(diǎn)云中的點(diǎn)恩商。每個(gè)要素的位置和外觀(guān)屬性都存儲(chǔ)在瓦片要素表中,其他應(yīng)用于特定程序的屬性則存儲(chǔ)在批處理表中必逆〉】埃客戶(hù)端可選擇在運(yùn)行時(shí)選擇要素,并檢索其屬性以進(jìn)行可視化或分析名眉。

上面表格中的b3dm 和 i3dm 格式是基于 glTF(一種專(zhuān)為高效傳輸 3D 內(nèi)容而設(shè)計(jì)的開(kāi)放性規(guī)范)構(gòu)建的粟矿,它們的瓦片內(nèi)容在二進(jìn)制體中嵌入了 glTF 資源,包含模型的幾何和紋理信息损拢,而 pnts 格式卻沒(méi)有嵌入 glTF 資源陌粹。

瓦片中的樹(shù)狀組織結(jié)合了層次細(xì)節(jié)模型(Hierarchical Level of Detail,簡(jiǎn)稱(chēng)HLOD)的概念福压,以便最佳地渲染空間數(shù)據(jù)掏秩。在樹(shù)狀結(jié)構(gòu)中,每個(gè)瓦片都有一個(gè)邊界范圍框?qū)傩运砀啵撨吔绶秶蛟诳臻g中能夠完全包圍該瓦片和孩子節(jié)點(diǎn)的數(shù)據(jù)哗讥。下圖為一種 3D Tiles 邊界范圍框所形成的層次體系示例:


tree.png

瓦片集可以使用類(lèi)似于 2D 空間的柵格和矢量瓦片方案(例如Web地圖切片服務(wù) WMTS 或 XYZ 方案)嚷那,其在若干細(xì)節(jié)級(jí)別(或縮放級(jí)別)處提供預(yù)定義的瓦片胞枕。但是,由于瓦片集的內(nèi)容通常是不一致的魏宽,或者可能很難僅在二維上組織腐泻,因此樹(shù)可以是具有空間一致性的任何空間數(shù)據(jù)結(jié)構(gòu),包括k-d樹(shù)队询,四叉樹(shù)派桩,八叉樹(shù)和網(wǎng)格。

3D Tiles 的樣式是可選的蚌斩,可以將其應(yīng)用于 Tileset 铆惑。樣式是由可計(jì)算的表達(dá)式所定義,用于修改每個(gè)要素的顯示方式送膳。

獲取更多關(guān)于3D Tiles 的信息可查其GitHub地址:https://github.com/CesiumGS/3d-tiles和 OGC 相關(guān)規(guī)范地址:http://docs.opengeospatial.org/cs/18-053r2/18-053r2.html员魏。下面主要簡(jiǎn)單介紹一下最核心的兩個(gè)概念:Tiles、Tileset叠聋。

首先撕阎,我從一個(gè)簡(jiǎn)單的3D Tiles數(shù)據(jù)示例說(shuō)起。下面代碼為一個(gè)3D Tiles的主瓦片集JSON 文件(tileset.json)的一部分碌补,也是調(diào)用3D Tiles數(shù)據(jù)的入口文件虏束。為了盡可能少占篇幅棉饶,children部分已省略,獲取完整tileset.json可查看該地址:https://github.com/CesiumGS/3d-tiles/blob/master/examples/tileset.json镇匀。

{
  "asset" : {
    "version": "1.0",
    "tilesetVersion": "e575c6f1-a45b-420a-b172-6449fa6e0a59",
  },
  "properties": {
    "Height": {
      "minimum": 1,
      "maximum": 241.6
    }
  },
  "geometricError": 494.50961650991815,
  "root": {
    "boundingVolume": {
      "region": [
        -0.0005682966577418737,
        0.8987233516605286,
        0.00011646582098558159,
        0.8990603398325034,
        0,
        241.6
      ]
    },
    "geometricError": 268.37878244706053,
    "refine": "ADD",
    "content": {
      "uri": "0/0/0.b3dm",
      "boundingVolume": {
        "region": [
          -0.0004001690908972599,
          0.8988700116775743,
          0.00010096729722787196,
          0.8989625664878067,
          0,
          241.6
        ]
      }
    },
    "children": [..]
  }
}

上面代碼中 root 下面的內(nèi)容照藻,就是一個(gè)Tile,即一個(gè)瓦片坑律。

Tiles—瓦片

瓦片包含用于確定是否渲染瓦片的元數(shù)據(jù)岩梳、對(duì)渲染內(nèi)容的引用以及任何子瓦片的數(shù)組。切片實(shí)際上也是一個(gè)JSON對(duì)象晃择,它由以下屬性組成冀值。如下所示:


tile.png

1)boundingVolumes(邊界范圍框)
定義了瓦片的最小邊界范圍,用于確定在運(yùn)行時(shí)渲染哪個(gè)瓦片宫屠,有region列疗、box、sphere三種形式浪蹂。

2)geometricError(幾何誤差)
是一個(gè)非負(fù)數(shù)抵栈,以米為單位定義了不同瓦片層級(jí)的幾何誤差,通過(guò)幾何誤差來(lái)計(jì)算以像素為單位的屏幕誤差(SSE)坤次,從而確定不同縮放級(jí)別下應(yīng)該調(diào)用哪個(gè)層級(jí)的瓦片古劲。簡(jiǎn)單來(lái)說(shuō),Tile的幾何誤差是用來(lái)確定瓦片切換層級(jí)的缰猴,即控制LOD的产艾。

3)refine(細(xì)化方式)
確定瓦片從低級(jí)別(LOD)切換為高級(jí)別(LOD)的呈現(xiàn)過(guò)程,簡(jiǎn)單來(lái)說(shuō)就是瓦片是如何切換的滑绒,其中包括替換(REPLACE)和添加(ADD)兩種方式闷堡。替換就是直接把父級(jí)的瓦片替換掉,添加則是在父級(jí)瓦片的基礎(chǔ)增加細(xì)節(jié)部分疑故。如下圖所示杠览,說(shuō)明了具體的切換方式:

REPLACE 方式

ADD 方式

理論上來(lái)說(shuō),ADD方式是一種非常好的方式纵势,是一種增量的LOD策略踱阿,能夠減少數(shù)據(jù)的傳輸。這里強(qiáng)調(diào)一下钦铁,refine屬性在根節(jié)點(diǎn)的Tile中是必須定義的软舌,子節(jié)點(diǎn)中是可選的。如果子節(jié)點(diǎn)沒(méi)有定義育瓜,則繼承父節(jié)點(diǎn)的該屬性葫隙。

4)content(內(nèi)容)
content屬性指定了瓦片實(shí)際渲染的內(nèi)容。content.uri屬性可以是一個(gè)指定二進(jìn)制塊(b3dm躏仇、i3dm恋脚、pnts腺办、cmpt)的位置,也可以是指向另一個(gè)外部的tileset.json糟描。
content.boundingVolume屬性定義了類(lèi)似 Tile屬性boundingVolume的邊界范圍框怀喉,但是content.boundingVolume是一個(gè)緊密貼合的邊界范圍框,僅包含切片的內(nèi)容船响。該屬性可以用來(lái)做視錐體裁剪躬拢,只渲染視圖范圍內(nèi)的內(nèi)容,如果該屬性沒(méi)定義见间,系統(tǒng)也會(huì)自動(dòng)計(jì)算聊闯。下圖是關(guān)于Tile.boundingVolumes和content.boundingVolumes 的比較,紅色是Tile的boundingVolumes米诉,包圍了Tileset的整個(gè)區(qū)域菱蔬;藍(lán)色是content的boundingVolumes,僅包圍切片中的渲染模型史侣。

5)children(孩子節(jié)點(diǎn))
這個(gè)很容易理解拴泌,因?yàn)?D Tiles是分級(jí)別的,所以每個(gè)Tile還會(huì)有子Tile惊橱、子子Tile蚪腐、子子子Tile ......,分的越多税朴,層級(jí)劃分的越精細(xì)回季,和下面講到的Tileset瓦片集root.children是同一個(gè)概念。

6)viewerRequestVolume(可選掉房,觀(guān)察者請(qǐng)求體)
定義了一個(gè)邊界范圍茧跋,使用與boundingVolumes相同的模式慰丛,只有當(dāng)觀(guān)察者處于其定義的范圍內(nèi)時(shí)卓囚,Tile才顯示,從而精細(xì)控制了個(gè)別瓦片的顯示與否诅病。如下圖所示哪亿,只有相機(jī)拉近到某一個(gè)距離時(shí),才顯示屋內(nèi)的球贤笆。

7)transform(可選蝇棉,位置變換矩陣)
定義了一個(gè)4x4的變換矩陣 ,通過(guò)此屬性芥永,Tile的坐標(biāo)就可以是自己的局部坐標(biāo)系內(nèi)的坐標(biāo)篡殷,最后通過(guò)自己的transform矩陣變換到父節(jié)點(diǎn)的坐標(biāo)系中。它會(huì)對(duì)Tile的content埋涧、boudingVolume板辽、viewerRequestVolume進(jìn)行轉(zhuǎn)換奇瘦。詳情可查看3D Tiles的規(guī)范文檔。

Tileset—瓦片集

通常劲弦,一個(gè)3D Tiles 數(shù)據(jù)會(huì)使用一個(gè)主 tileset JSON 文件作為定義 tileset 的入口點(diǎn)耳标,一般是以 tileset.json 文件命名(當(dāng)然該文件名稱(chēng)可以修改)。從上面示例代碼可以看出邑跪,tileset JSON 有四個(gè)頂級(jí)屬性:asset次坡、properties、geometricError画畅、root砸琅。

1)asset
asset包含整個(gè)tileSet的元數(shù)據(jù)對(duì)象。asset.Version屬性轴踱,用于定義3D Tiles版本明棍,該版本指定tileset的JSON模式和基本的tileset格式。tileVersion屬性可選寇僧,用于定義特定的應(yīng)用程序的tileset摊腋。

2)properties
properties是一個(gè)對(duì)象,包含tileset中每個(gè)feature屬性的對(duì)象嘁傀。上面的例子是一個(gè)建筑物的3DTiles兴蒸,因此每個(gè)瓦片都含有三維建筑物模型,每個(gè)三維建筑物模型都有高度屬性细办,所以上面的例子中就定義了Height屬性橙凳。屬性中每個(gè)對(duì)象的名稱(chēng)與每個(gè)要素屬性的名稱(chēng)相對(duì)應(yīng)(如例子中的Height對(duì)應(yīng)高度),并且包含該屬性的最大值和最小值笑撞,這些值用于創(chuàng)建樣式的顏色漸變非常有用岛啸。

3)geometricError
geometricError是一個(gè)非負(fù)數(shù),是通過(guò)這個(gè)幾何誤差的值來(lái)計(jì)算屏幕誤差茴肥,確定Tileset是否渲染坚踩。如果在渲染的過(guò)程中,當(dāng)前屏幕誤差大于這里定義的屏幕誤差瓤狐,這個(gè)Tileset就不渲染瞬铸。即根據(jù)屏幕誤差來(lái)控制Tileset中的root是否渲染。

4)root
root 是一個(gè) JSON 對(duì)象础锐,定義了最根級(jí)的 Tile 嗓节,它存儲(chǔ)的是真正的Tile 。也就是說(shuō)皆警,root 的數(shù)據(jù)組織方式與 Tile 的數(shù)據(jù)組織方式是一樣的拦宣。

需要注意的是,root.geometricError 與 tileset 的頂級(jí) geometricError 不同,tileSet的geometricError是根據(jù)屏幕誤差來(lái)控制tileSet中的root是否渲染鸵隧,而root(tile)中的geometricError則是用來(lái)控制tile中的children是否渲染桐愉。

root.children 是一個(gè)定義子 Tile 的對(duì)象數(shù)組,每個(gè)Tile還會(huì)有其children掰派,這樣就形成了一種遞歸定義的樹(shù)狀結(jié)構(gòu)从诲。每個(gè)子 Tile 的內(nèi)容完全由其父 Tile 的boundingVolume 包圍,并且通常是其 geometricError 小于其父 Tile 的 geometricError靡羡,因?yàn)樵浇咏~子節(jié)點(diǎn)系洛,模型越精細(xì),與原模型的幾何誤差就越小略步。對(duì)于葉子節(jié)點(diǎn)的 Tile 描扯,其數(shù)組的長(zhǎng)度為零,或者是未定義 children 趟薄。

當(dāng)然绽诚,為了創(chuàng)建樹(shù)狀結(jié)構(gòu),tile 的 content.uri 也可以指向外部的 tileset(另一個(gè) tileset 的 JSON 文件)杭煎。這樣做的一個(gè)好處就是恩够,不同的tileset可以分開(kāi)存儲(chǔ),例如我國(guó)的每個(gè)城市可單獨(dú)存儲(chǔ)成一個(gè)tileset羡铲,然后再定義一個(gè)包含所有 tileset 的全局 tileset蜂桶。


tilesets.png

Cesium加載3D Tiles

Cesium雖然也支持兩種方式(Entity和Primitive)加載3D Tiles數(shù)據(jù),但因?yàn)槎鄶?shù)情況下3D Tiles數(shù)據(jù)都是成片區(qū)的數(shù)據(jù)也切,數(shù)據(jù)量比較大扑媚,所以為了保證性能,建議使用Primitive方式雷恃。

1)Cesium中3D Tiles相關(guān)類(lèi)
我們?cè)贑esium API幫助文檔中搜索3dtile關(guān)鍵詞疆股,搜出如下結(jié)果:

我把幾個(gè)非常重要的也非常常用的類(lèi)用紅框標(biāo)了出來(lái),便于大家記憶倒槐。

  • Cesium3Dtileset:用于流式傳輸大量的異構(gòu)3D地理空間數(shù)據(jù)集旬痹;
  • Cesium3DTileStyle:瓦片集樣式;
  • Cesium3DTile:數(shù)據(jù)集中的一個(gè)瓦片;
  • Cesium3DTileContent:瓦片內(nèi)容导犹;
  • Cesium3DTileFeature:瓦片集要素唱凯,用于訪(fǎng)問(wèn)Tile中批量表中的屬性數(shù)據(jù)羡忘,可通過(guò)scene.pick方法來(lái)獲取一個(gè) BATCH谎痢,即三維要素。Cesium3DTileFeature.getPropertyNames() 方法獲取批量表中所有屬性名卷雕,Cesium3DTileFeature.getProperty(string Name) 來(lái)獲取對(duì)應(yīng)屬性名的屬性值节猿。

2)加載3D Tiles

  var viewer = new Cesium.Viewer("cesiumContainer");
   // 添加3D Tiles
   var tileset = viewer.scene.primitives.add(
     new Cesium.Cesium3DTileset({
       url: "./data/Cesium3DTiles/Tilesets/Tileset/tileset.json",
       // maximumScreenSpaceError: 2, //最大的屏幕空間誤差
       // maximumNumberOfLoadedTiles: 1000, //最大加載瓦片個(gè)數(shù)
     })
   );

3)設(shè)置樣式

      var properties = tileset.properties;
       if (Cesium.defined(properties) && Cesium.defined(properties.Height)) {
         tileset.style = new Cesium.Cesium3DTileStyle({
           color: {
             conditions: [
               ["${Height} >= 83", "color('purple', 0.5)"],
               ["${Height} >= 80", "color('red')"],
               ["${Height} >= 70", "color('orange')"],
               ["${Height} >= 12", "color('yellow')"],
               ["${Height} >= 7", "color('lime')"],
               ["${Height} >= 1", "color('cyan')"],
               ["true", "color('blue')"],
             ],
           },
         });
       }

4)位置調(diào)整

      var cartographic = Cesium.Cartographic.fromCartesian(
         tileset.boundingSphere.center
       );
       var surface = Cesium.Cartesian3.fromRadians(
         cartographic.longitude,
         cartographic.latitude,
         0.0
       );
       var offset = Cesium.Cartesian3.fromRadians(
         cartographic.longitude,
         cartographic.latitude,
         height
       );
       var translation = Cesium.Cartesian3.subtract(
         offset,
         surface,
         new Cesium.Cartesian3()
       );
       tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
     })
     .otherwise(function (error) {
       console.log(error);
     });

5)拾取要素

    var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
    handler.setInputAction(function (movement) {
      var feature = viewer.scene.pick(movement.position);
      if (Cesium.defined(feature) && feature instanceof Cesium.Cesium3DTileFeature) {
        var propertyNames = feature.getPropertyNames();
        var length = propertyNames.length;
        for (var i = 0; i < length; ++i) {
          var propertyName = propertyNames[i];
          console.log(propertyName + ": " + feature.getProperty(propertyName));
        }
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子滨嘱,更是在濱河造成了極大的恐慌峰鄙,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件太雨,死亡現(xiàn)場(chǎng)離奇詭異吟榴,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)囊扳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)吩翻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人锥咸,你說(shuō)我怎么就攤上這事狭瞎。” “怎么了搏予?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵熊锭,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我雪侥,道長(zhǎng)碗殷,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任速缨,我火速辦了婚禮亿扁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鸟廓。我一直安慰自己从祝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布引谜。 她就那樣靜靜地躺著牍陌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪员咽。 梳的紋絲不亂的頭發(fā)上毒涧,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音贝室,去河邊找鬼契讲。 笑死,一個(gè)胖子當(dāng)著我的面吹牛滑频,可吹牛的內(nèi)容都是我干的捡偏。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼峡迷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼银伟!你這毒婦竟也來(lái)了你虹?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤彤避,失蹤者是張志新(化名)和其女友劉穎傅物,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體琉预,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡董饰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了圆米。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尖阔。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖榨咐,靈堂內(nèi)的尸體忽然破棺而出介却,到底是詐尸還是另有隱情,我是刑警寧澤块茁,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布齿坷,位于F島的核電站,受9級(jí)特大地震影響数焊,放射性物質(zhì)發(fā)生泄漏永淌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一佩耳、第九天 我趴在偏房一處隱蔽的房頂上張望遂蛀。 院中可真熱鬧,春花似錦干厚、人聲如沸李滴。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)所坯。三九已至,卻和暖如春挂捅,著一層夾襖步出監(jiān)牢的瞬間芹助,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工闲先, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留状土,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓伺糠,卻偏偏與公主長(zhǎng)得像蒙谓,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子退盯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容