长沙网站排名公司哪家好,什么是网络营销?,精美ppt模板免费下载百度云,wordpress综合网本文节选自新书《GIS基础原理与技术实践》第8章。当 GIS 迈入三维时代#xff0c;如何高效发布与可视化海量三维模型成为关键挑战。目前#xff0c;Cesium 的 3D Tiles、Esri 的 I3S 和 超图的 S3M 已成为三大主流三维瓦片标准。本文将带你深入其核心机制——从瓦片树、包围体…本文节选自新书《GIS基础原理与技术实践》第8章。当 GIS 迈入三维时代如何高效发布与可视化海量三维模型成为关键挑战。目前Cesium 的 3D Tiles、Esri 的 I3S 和 超图的 S3M 已成为三大主流三维瓦片标准。本文将带你深入其核心机制——从瓦片树、包围体、几何误差到 b3dm/i3dm/pnts 格式细节再到要素化与声明式样式全面解析这“三维瓦片三剑客”的异同与适用场景。8.8 三维模型数据服务与矢量切片服务和地形切片服务一样三维模型数据服务也多数是以静态资源的形式进行发布的毕竟他们还没形成比较标准的规范不用提供额外的空间操作只需要保证能获取资源进行可视化就可以了。因此三维模型数据服务大多直接使用三维模型瓦片数据格式发布的静态资源即可。8.8.1 三维模型瓦片数据格式一般情况下三维模型的数据量比单纯的栅格数据或者矢量数据大得多因此也需要进行类似于切片的处理将三维模型轻量化。其具体的原理也不复杂使用的就是在第7.4节中我们介绍的分页LOD技术通过分层和分块将三维模型划分成不同精细度、不同范围的瓦片根据三维场景的需要使渲染端动态调度出适配场景精细度的三维模型瓦片。第7.4节中我们是通过倾斜摄影模型介绍的具有分页LOD技术的OSGB格式数据但推而广之其实第7.5节中介绍的所有类型的三维模型数据都可以使用OSGB格式来进行表达。不过OSGB格式数据是一个适合桌面端的数据格式并没有针对Web端环境进行优化和适配。目前经常用作三维模型数据服务的三维模型数据是Cesium的3D Tiles格式ArcGIS的I3S格式以及国内超图软件的S3M格式。其中3D Tiles和I3S已经是国际OGC标准而S3M则是CAGIS中国地理信息产业协会空间三维模型数据格式标准。根据3D Tiles官方文档https://github.com/CesiumGS/3d-tiles 提供的定义3D Tiles是专为流式传输和渲染大量3D地理空间内容而设计的三维模型数据格式例如倾斜摄影测量数据、3D建筑数据、BIM/CAD、实例化要素和点云数据等。与OSGB使用的分页LOD技术类似3D Tiles使用分层细节级别 (HLODHierarchical Level of Detail)的空间数据结构保证只有可见的瓦片才会被流式传输和渲染从而提高三维模型数据整体性能。3D Tiles有1.0和1.1两个版本但是目前3D Tiles 1.0是使用最广泛的三维模型瓦片数据格式以下我们会以3D Tiles 1.0为例具体介绍一下三维模型瓦片数据格式的内容。8.8.2 瓦片集和瓦片Tilesets and Tiles3D Tiles合适文件通常是一个散列的包含文件和文件夹的数据集数据集的入口通常是一个名为tileset的JSON文件。如文件名表达的含义一样这个JSON文件就是3D Tiles的根数据集Tilesets一个典型的例子如下例8.6所示:例8.6 3D Tiles的根数据集/* by 01130.hk - online tools website : 01130.hk/zh/worldtime.html */ { asset: {}, properties: {}, geometricError: 100, root: { geometricError: 20, boundingVolume: { region: [] }, refine: ADD, children: [ { geometricError: 10, boundingVolume: {}, content: { uri: house.b3dm }, children: [ { geometricError: 5, boundingVolume: {}, content: { uri: detailsA.b3dm } }, { geometricError: 5, boundingVolume: {}, content: { uri: detailsB.b3dm } } ] }, { geometricError: 10, boundingVolume: {}, content: { uri: tree.pnts } }, { geometricError: 10, boundingVolume: {}, content: { uri: fence.i3dm } }, { geometricError: 10, boundingVolume: {}, content: { uri: external.json } } ] } }在这个JSON文件中最主要的部分就是名为root的元素以及children数组中的元素。其实两者的属性是相同的都应该包含content、children、boundingVolume、geometricError以及refine键值对只不过有的键值对被省略掉了。具体来说3D Tiles中的瓦片Tiles指的就是这个元素。从例8.1可以看出root元素包含了一个children数组元素children数组中的一个元素又可以包含一个children数组元素...如此可以进行多层嵌套就组成了一个瓦片树。我们可以回忆一下第7.4.3节的内容这与OSGB格式的节点树非常相似。在这个瓦片树中越往上模型精细度越低但是分块越少越往下模型精细度越高但是分块越多。父亲节点与所有的子节点表达的数据内容是一样的只是精细度有差别。3D Tiles瓦片和瓦片集的示意图如下图8.53所示一个JSON瓦片集能包含多个瓦片瓦片的content就是具体的模型实体。不过正如例8.6所展示的那样瓦片的content也可以指向另一个JSON瓦片集像这样重复嵌套我们可以组成一个非常复杂的表达三维场景的瓦片树。8.8.3 包围体Bounding Volumes在例8.6中我们就看到的boundingVolume元素就是包围体。可能这里说包围盒这个概念更容易让人理解一点但是3D Tiles中有三种不同的表达切片范围的体要素所以将其称为包围体更好一点。这三种包围体分别是包围盒Bounding Box包围球Bounding sqhere和包围区域Bounding region如下图8.54所示包围盒是我们最熟悉的但是这里反而最不好理解一个包围盒参数的例子如下所示/* by 01130.hk - online tools website : 01130.hk/zh/worldtime.html */ boundingVolume: { box: [ 0, 0, 10, 20, 0, 0, 0, 30, 0, 0, 0, 10 ] }可以看到这里一共12个参数前3个参数表示中心点的位置坐标接下来的三个元素定义x轴方向和半长再接下来的三个元素定义y轴方向和半长最后三个元素定义z轴方向和半长。这个例子的包围盒的描述就是中心点坐标为(0,0,10)X方向长度为40Y方向长度为60Z方向为20。这种包围盒在三维中称为AABBAxis-Aligned Bounding Box轴对称包围盒包围盒一般情况下这么用就可以了。但是如果深入了解一下就会发现12个参数中有很多值是0这些0值其实是用来表达旋转的或者说方向的。AABB包围盒其实对三维物体对象的贴合不够紧密如果调整一下包围盒的方向就有可能让包围盒的范围进一步缩小想象一下从西北到东南的长条状物体的包围盒。这种包围盒就被称为OBB包围盒Oriented Bounding Box有向包围盒。复习前面第3.7.1节的知识就会明白后面9个参数实质是定义了旋转变换缩放变换的几何变换矩阵。因为OBB包围盒的方式复杂一些所以这种表达形式使用的比较少。而包围球就最简单了由中心点坐标和半径定义四个参数定义如下所示boundingVolume: { sphere: [ 10, 5, 15, 140.0 ] }最后的包围区域则是三维图形中没有的概念实际上这个区域其实指的是地理区域由6个参数定义分别是WGS84坐标系中西至经度南至纬度东至经度北至纬度最小椭球高最大椭球高经纬度使用弧度为单位高度以米为单位。如下所示boundingVolume: { region: [ -1.319700, 0.698858, -1.319659, 0.698889, 0.0, 20.0 ] }包围体是三维图形中就非常重要的参数可用于优化渲染和高效空间查询例如在Ceisum中就通过使用包围体实现可见性查询和视锥体剔除显著提升了渲染性能。8.8.4 空间数据结构我们在前面论述过3D Tiles中的瓦片集以树形数据结构进行组织。但是这种树形数据结构不是任意组织的而是具有空间一致性父瓦片的包围体始终包含其所有子瓦片的内容。这对于可见性测试和相交性测试特别重要当在三维场景中我们看不到某个瓦片的时候那么必然看不到它的所有子瓦片。通过这种方式我们可以筛选需要的瓦片进行展示这对性能的提升非常有帮助。另外与基于二维的地图切片不同3D Tiles的瓦片数据结构通常是基于三维的因此要更加复杂例如KD树或者八叉树且每个瓦片可能并不均匀。这样可能就会造成一个现象就是父瓦片的包围盒可能并不能完全包含子瓦片的包围盒。当然父瓦片的包围体包含其子瓦片的内容的特性还是存在的。具体的空间结构示意图如下图8.55所示8.8.5 几何误差Geometric Error几何误差Geometric Error就是例8.6中的geometricError元素。复习一下我们在第7.4.3节中介绍的知识OpenSceneGraph和OSGB格式使用瓦片包围球映射到屏幕端直径来决定渲染的精细度层级而几何误差的作用也非常类似决定了3D Tiles在渲染客户端如Cesium以何种细节级别进行渲染从而在性能和渲染质量之间提供最佳权衡。虽然都是控制LOD级别的因子3D Tiles格式的几何误差表达的含义则与OSGB格式使用的参数完全不同几何误差表达的含义是简化的几何体与真实的几何体之间的误差以米为单位。在可视化端实现的时候会将这个参数转换成屏幕空间误差screen-space errorSSE单位为像素。当SSE超过某个阈值CesiumJS中会设定一个最大屏幕空间误差值的时候运行的时候将会渲染更高级别的细节。具体示意图如下图8.56所示那么几何误差是如何转换成屏幕空间误差呢Cesium官方给出了一个公式对于透视投影他们的转换公式如下式(8-3)\[sse \frac{geometricError ⋅ screenHeight}{tileDistance ⋅ 2 ⋅ tan(fovy / 2)} \tag{8-3} \]其中screenHeight是渲染屏幕的高度以像素为单位tileDistance是瓦片到视点的距离fovy是视锥体的y方向的张角。8.8.6 细化策略Refinement Strategies细化策略Refinement Strategies就是例8.6中的refine参数。这个参数决定了以何种方式在高细节层级瓦片中增加细节。通常的方式是替换REPLACE意思是子瓦片节点会替换其父瓦片这也是OSGB格式采取的策略Cesium中还额外支持新增ADD意思是子瓦片在父瓦片的基础上增加新的内容。具体示意图如下图8.57所示每个瓦片都可以设置细化策略参数如果未指定说明该瓦片的细化策略继承自父瓦片。8.8.7 渲染优化算法假设已经存在一个3D Tiles瓦片集和相机视锥体如下图8.58所示。3D Tiles瓦片集我们比较好理解关键元素我们已经在前面几小节中介绍过了。相机视锥体是三维图形中经常要用到的一个概念好比真实世界中我们需要拍摄到一个物体必须让相机调整到合适的位置Position调整好合适的角度Orientation以及调整合适的焦距Field-of-view angle视场角。接下来我们可以模拟出在可视化客户端渲染实现中3D Tiles格式是如何平衡任何比例的渲染性能和视觉质量了。虽然我们在前面中已经将这个思想分页LOD机制/HLOD论述了很多次了但这里我们可以对照下图8.59所示进行进一步理解最开始加载的是JSON格式的瓦片集文件并测试视锥体与根瓦片边界体积是否相交。在这里视锥体与根瓦片的包围体相交这意味着该瓦片可能需要被加载进行渲染。由于根瓦片是没有内容的那么就测试子瓦片的包围体与视锥体的相交。在这里三个子瓦片中的两个的包围体确实与视锥体相交这意味着这些子瓦片的内容会被考虑进行渲染而剩下的一个瓦片就被直接剔除不用渲染。此时检查瓦片的几何误差根据式(8-3)计算此时的屏幕空间误差。此时由于没有超过阈值18.0说明内容呈现的精细度正好合适。然后当用户进行交互例如放大某个建筑物时根据式(8-3)可知瓦片的屏幕空间误差会增大而超过阈值有可能需要进行下一层级的渲染。并且新的视锥体可能会剔除更多的瓦片不用渲染只有一小部分瓦片集可见。根据所选的细化策略加载和渲染具有较高细节级别的内容。由于较高细节级别瓦片的几何误差较小导致屏幕空间误差低于阈值此时可以呈现更高精细度的视觉质量。8.8.8 瓦片内容数据3D Tiles瓦片内容数据通常以URI的形式引用外部文件如例8.6中的house.b3dm、detailsA.b3dm和detailsB.b3dm。因为这些文件是3D Tiles瓦片的主体所以很多情况下为了方便使用就将其当成瓦片本身。3D Tiles瓦片的格式可以有以下四种表现形式Batched 3D Modelb3dm批处理三维模型最常规的三维模型。Instanced 3D Modeli3dm:实例化三维模型相同三维模型的多个实例。Point Cloudspnts点云大量点组成的数据。Composite Tilescmpt以上三种的复合数据。3D Tiles瓦片其实就是一种普通的三维模型数据我们可以按照第7章三维模型介绍的内容来理解它。不过3D Tiles瓦片与普通三维模型最大的不同就在于它是按照GIS矢量要素特性来进行设计的具体来说就是3D Tiles瓦片中除了三维模型之外还有要素表Feature Table和批处理表Batch Table来作为属性数据。另一方面三维模型自身也被逻辑上拆分成多个要素模型通过ID与属性表相关联。实际上正如第7.5.2节中所述这种设计实现了三维模型的单体化在业务应用中有很大的实用意义。1. 批处理三维模型Batched 3D Models)批处理三维模型Batched 3D Modelsb3dm是3D Tiles常用的瓦片数据格式因为其本质上就是最常规的三维模型数据。具体有多常规呢b3dm内部直接嵌入了一个我们在第7.2节中介绍的glTF三维模型文件具体数据布局如下图8.60所示。根据其数据布局我们可以作一个大概的说明magic是魔法值的意思其实就是文件标识符具体就是“b3dm”四个字符。version和byteLength分别代表版本和整个b3dm文件的字节长度。featureTableJSONByteLength、featureTableBinaryByteLength、batchTableJSONByteLength和batchTableBinaryByteLength的大小分别描述了要素表JSON部分的字节长度、要素表二进制部分的字节长度、批处理表JSON部分的字节长度、批处理表二进制部分的字节长度。文件主体包含三个部分分别是要素表这是必须的批处理表可选的以及内嵌的glTF三维模型文件。b3dm的文件数据组织我们已经初步了解那么是如何将三维模型其拆分成多个要素模型呢方法很简单是通过扩展了一个名为batchId的顶点属性来实现的。对于不同的要素模型我们分别赋予其不同的batchId值这样在将三维模型渲染成二维画面的时候通过二维画面像素关联的batchId值我们就区分哪些画面像素是属于哪个要素的。如下图8.61所示现在已经有了batchId值了那么我们就需要将其关联到要素表和批处理表。对于b3dm瓦片格式来说图8.61对应的要素表的JSON部分通常为{ BATCH_LENGTH: 2 }BATCH_LENGTH是要素表的必须属性表示要素的个数为2。b3dm通常不使用要素表的二进制部分而将要素模型的属性数据放入到批处理表中。例如图8.61对应的批处理表的JSON部分通常为{ height: [ 16.2 23.0, ], address: [ 234 Second Street, 123 Main Street ] }这里表达了批处理表中高度字段属性和地址字段属性每个字段属性值都是一个数组元素而batchId就是这个数组元素的索引。很显然这正是batchId关联属性表的关键第1个模型要素的高度是16.2地址是234 Second Street第2个模型要素的高度是23.0地址是123 Main Street。一般情况下只使用批处理表的JSON部分就可以表达要素模型的属性表了。批处理表的二进制部分则是用来配合JSON部分来表达特定数据类型的属性例如当JSON部分为如下所示时{ location: { byteOffset: 0, componentType: FLOAT, type: VEC2 }, id: { byteOffset: 32, componentType: INT, type: SCALAR } }那么location和id属性字段值就会在二进制部分中进行查找byteOffset表示起始位置字节偏移type表示数据类型componentType则表示数据分量类型。其实这三个参数与glTF中的顶点属性数据的表达非常像type和componentType值的要求也与glTF中值的要求一致复习以下第7.2节中glTF的介绍就会非常容易理解。话说回来我们说b3dm是参照矢量要素的设计思路实现的是从GIS的角度进行出发论述。其实从“批处理”这个命名来说设计者更多的是从图形渲染的角度出发来进行设计的。在图形渲染行业中术语“批处理”是指多个模型的几何数据进行合并组合成单个的缓冲区进入GPU显存中进行渲染这样可以减少复制操作带来的损耗最小化渲染绘制调用次数从而提高渲染性能。不得不说b3dm的设计确实很精妙很多学问到了最深处往往都是相通的。2. 实例化三维模型Instanced 3D Models有了b3dm作为基础实例化三维模型Instanced 3D Modeli3dm就比较容易理解了。不过我们首先需要知道为什么这种瓦片格式叫做实例化三维模型。其实“实例化”这个术语是图形渲染中的一种技术通过实例化技术可以一次性渲染大量相同的模型只不过这些模型有一些特定的变化。例如我们渲染大量的树木我们可以使用同一个树木模型然后让每个树木模型的位置、旋转和缩放不同就可以得到一大片形态各异的树林。实例化的优点就在于既然创建一个树木对象进行渲染是很耗费性能的那么就将这个树木对象改变一下位置、朝向以及大小进行复制粘贴这样就可以很轻易绘制出包含大量三维模型数据的场景并且能保证性能。实例化技术具有非常多的应用场景因为很多现实中的物体是有规范和标准的比如城市中的部件BIM中的基础设施工业设计中的零件等它们往往都有非常相似的外观使用实例化技术可以有非常好的效果。这也是为什么3D Tiles将实例化三维模型作为一种瓦片数据格式。从前面的介绍不难理解i3dm相比较普通三维模型数据最大的区别在于多了表达变化的实例化参数比如前面提到的位置、旋转和缩放。i3dm实例化参数信息是放置在要素表中的因此i3dm瓦片数据布局与b3dm瓦片数据布局基本一致如下图8.62所示除了多了一个表达gltf是外部还是内嵌的参数gltfFormati3dm与b3dm最大的不同就在于要素表和批处理表。要素表中需要存放实例化参数例如一个要素表的JSON部分如下所示{ INSTANCES_LENGTH: 3, POSITION: { byteOffset: 0 }, NORMAL_UP: { byteOffset: 36 }, NORMAL_RIGHT: { byteOffset: 72 }, SCALE: { byteOffset: 108 } }INSTANCES_LENGTH是必须的参数表示实例化个数。POSITION、NORMAL_UP、NORMAL_RIGHT和SCALE是预先定义好的语义分别表示位置、旋转的上方向、旋转的右方向以及缩放它们分别用3个float型、3个float型、3个float型以及1个float型来表示配合起始位置字节偏移byteOffset我们可以很容易找出存储在要素表二进制部分的实例化参数如下图8.63所示另外i3dm也是遵循要素化的设计思路的不过与b3dm不同i3dm是以单个的实例化对象为单个要素并且关联属性。在要素表中可以在JSON部分增加一个名为BATCH_ID的语义在二进制部分存储不同实例化对象的batchId值。而批处理表中则像b3dm一样进行存储其他属性数据这样就实现了单个的实例化模型与属性信息的关联。3. 点云Point Clouds相比较b3dm和i3dm点云Point Cloudspnts形式的瓦片数据格式就更加简单了甚至不用内嵌glTF。点云pnts的数据布局如下图8.64所示点云除了记录点的位置属性之外还可能有法向量、颜色等属性这些属性数据都是记录在要素表中的。如下所示是一个pnts要素表的JSON部分{ POINTS_LENGTH: 219, POSITION: { byteOffset: 0 }, NORMAL: { byteOffset: 2628 }, RGB: { byteOffset: 5256 } }类似i3dm的要素表这里的POINTS_LENGTH表示点的个数而POSITION、NORMAL和RGB这些属性名称也是预定义的语义类型配合起始位置字节偏移量byteOffset可以找到点属性具体的属性值具体示意图如下图8.65所示pnts也是遵循要素化的设计思路从要素表来看似乎点云中一个点就是一个要素但这样理解并不准确。pnts需要表达的是一个要素模型例如一个点云瓦片表示的是一个房屋那么房屋内部中的门、窗或者屋顶才是我们想要知道的要素模型。要实现这样的要素识别非常简单还是使用如同b3dm或i3dm相同的办法在要素表中增加一个名为BATCH_ID的字段记录每个点云的batchId值如下图8.66所示剩下的就还是如同b3dm一样在批处理表中存储其他属性数据实现多个点组成的要素模型与属性信息相关联。4. 复合瓦片Composite Tiles复合瓦片Composite Tilescmpt是以上介绍的瓦片格式的复合数据格式。举例来说一组建筑物可以存储在b3dm中一组树木可以存储在i3dm中如果这些元素出现在同一地理位置时就可以将其组合成cmpt实现单个的请求获取该地理位置所有的可渲染内容如下图 8.67所示。这样的设计可以减少访问的请求个数改善瓦片数据加载时的视觉效果。cmpt的数据组织非常灵活可以包含b3dm、i3dm和pnts中的任意种类任意个数的瓦片数据甚至可以包含另一个cmpt瓦片数据。但它的数据布局就简单了如下图8.68所示。文件头通过tilesLength标识包含的子瓦片的个数文件主体则是具体的子瓦片数据内容。8.8.9 声明式样式Declarative Styling既然3D Tiles的瓦片数据格式是按照要素特性来进行设计的那么免不了要面对的就是模型要素符号化的问题。3D Tiles使用声明性样式在运行时修改功能的外观所谓声明性样式具体来说就是包含一组表达式的JSON。这种样式JSON规定了一些变量表达式以及条件可以看作是一种简单的样式语言。例如我们让一组表达建筑的3D Tiles根据其高度呈现不同的颜色可以使用如下样式JSON{ color: { conditions: [ [${height} 300, rgba(45, 0, 75, 0.5)], [${height} 200, rgb(102, 71, 151)], [${height} 100, rgb(170, 162, 204)], [${height} 50, rgb(224, 226, 238)], [${height} 25, rgb(252, 230, 200)], [${height} 10, rgb(248, 176, 87)], [${height} 5, rgb(198, 106, 11)], [true, rgb(127, 59, 8)] ] } }其中color是要素模型的颜色值属性决定要素模型渲染的颜色。height则表示3D Tiles瓦片中批处理表种的height字段根据这个字段值的不同给模型要素赋予不同的颜色。在CesiumJS中实现效果如下图8.69所示虽然很多写实的三维模型可能用不到这个功能但是这个设计实现在业务系统中很有用处也很容易扩展可以帮助我们实现更酷炫更有价值的可视化效果值得我们进一步研究。8.8.10 其他从以上对3D Tiles格式的介绍可以感受到3D Tiles确实是设计的非常完善的三维模型瓦片数据格式也因此得到了最为广泛的使用。除此之外另一个OGC标准——ArcGIS设计的I3SIndexed 3D Scene Layers三维模型瓦片数据格式也很优秀与3D Tiles相比它的一些特点给笔者留下了比较深刻的印象主要是3D Tiles是离散文件集形式的静态资源I3S则可以打包成.slpk这种zip格式的单文件也支持使用RESTful接口访问。3D Tiles空间坐标参考默认是WGS84椭球的地心地固坐标系少部分参数使用WGS84地理坐标系而I3S则专业很多支持目前绝大多数地理空间坐标参考。不知道是否是处于兼容性的考虑I3S设计的参数非常多但可视化的时候很多参数都没有用上这也是ArcGIS的一贯特色3D Tiles这方面则简练很多只提供了最简单的参数要求其余的需求通过扩展来实现。I3S在设计中实现了几何数据、属性数据、纹理材质的解耦这意味着这些资源可以共享在一些渲染实现中可以通过这种机制来提升性能。I3S确定LOD层级的算法与3D Tiles不同而跟OSGB比较类似通过计算包围球投影到屏幕空间的像素大小来确定。而I3S其余的设计实现基于与3D Tiles大同小异笔者这里就不多作介绍了。值得一提的是I3S虽然没有提供具体的代码实现但是其官方在线文档 https://github.com/Esri/i3s-spec/ 中提供了一个可用于浏览I3S数据的在线浏览器以及各个版本的I3S数据下载这对于我们的研究学习很有帮助。最后国内还有一种使用的比较多的三维模型瓦片数据格式主要由超图软件开发设计的S3Mspatial 3D model格式。尽管S3M是中国地理信息产业协会的空间三维模型数据格式标准但这个格式笔者接触的不多毕竟愿意使用S3M格式的数据多少有点敏感性是不太容易获取进行研究的。不过笔者还是查阅了一下S3M官方在线文档https://github.com/SuperMap/s3m-spec对比3D Tiles和I3S最有诚意的一点是除了提供与其他三维瓦片数据的转换工具还提供了读写S3M瓦片数据的JavaScript和C代码实现并且一直在更新。不过缺点就是文档不够完善至少笔者也没有看到S3M1.0、S3M2.0和S3M3.0不同版本之间的演进。而仅存的一版S3M标准文档的内容相对于3D Tiles文档中完善的技术指导和参数说明也失之简陋。重于实现而轻于文档这一点也只能说是国内开源工作的通病了。本文节选自作者新书《GIS基础原理与技术实践》第8章。书中系统讲解 GIS 核心理论与多语言实战适合开发者与高校师生。配套资源开源GitHub | GitCode支持正版京东当当