都说 “一流企业定标准,二流企业卖品牌,三流企业卖产品,四流企业做项目”,在面向类 WebGL 技术的三维浏览器端渲染的大规模流式数据加载技术中,等到了 MapGIS 主导的 m3d 标准。
这一份浓浓的武汉味似乎是想在继 Cesium 3d-Tiles
、Esri i3s
、超图 S3M
后再在三维市场分一杯羹。
在前言中,吴老爷子带路,洋洋洒洒的一队人。
Model of 3D
,在原文第 4 节有指出,但是翻译过来不太对的样子。glTF
数据规范中,对于 glb 格式的一种变种文件。原文指的是 “gltf数据的扩展格式”,我不清楚 m3d 标准对 gltf 扩展了什么顶层属性,或者是没有好好研究 glTF
规范,因为 glTF
规范本身在几乎所有的属性中都有 extensions
和 extras
的预留属性,用于扩展各种不同逻辑的业务功能或渲染特征。结构的设计与 Esri i3s
略相类似,使用 Node
充当空间剖分的术语。
M3DDataInfo.mcj
:一种 JSON 文本文件,后缀名是 mcj,且此文件的文件名可任意设置,用于描述整份 m3d 数据RootNodeInfo.json
、NodeInfo<i>.json
:对 node 的描述文件,文件名可以自定义*.m3d
:m3d 文件,一种压缩文件,可选压缩格式有:,后缀名是m3d
,文件名可以自定义每份 m3d 数据,其根目录下有
mcj
文件描述整份数据Shared
目录存放 Shared.m3d
文件Data
目录用于存放子一级的节点目录
Geometry
、Texture
、Attribute
,分别存放 *.glb/glbx
、*.jpg/png/webp
、*.json/bin
文件用于存储几何、纹理、属性数据规范中的术语是 “数据树形结构”,个人认为使用 空间剖分方式 更好,直观。
使用了三种常规三维数据结构,即空间八叉树、四叉树、KD树。
BoundingBox
BoundingSphere
以上两种常见空间范围体二选一。
其中,BoundingBox
使用的定义是 6 元素的 AABB 包围盒,即经纬高三轴的最值。
M3DDataInfo.mcj
类定义描述整个 m3d 文件的 json 文件,它拥有如下顶层属性:
string
,在文下是 float
,我认为 string
更合适。"zip"
、"7z"
、"rar"
"WGS84"
、"CGCS2000"
"QuadTree"
、"OCTree"
、"K-DTree"
、"RTree"
,这点我也有点无语,在前文中并未提及 R树,虽然 R树在空间搜索中还是很常见的。"ADD"
、"REPLACE"
其中,BoundingVolume
在上文已提及,连同 Point
、Field
,在此简单使用 Rust
结构体定义:
struct BoundingVolume {
boundingBox: BoundingBox,
boundingSphere: BoundingSphere,
}
struct BoundingBox {
left: f64,
top: f64,
right: f64,
bottom: f64,
minHeight: f64,
maxHeight: f64,
}
struct BoundingSphere {
center: Point,
radius: f64,
}
struct Point {
x: f64,
y: f64,
z: f64,
}
struct Field {
name: String,
type: String,
alias: String,
size: i32,
}
其中,Field
的 type 字段可选值为 "bool"
、"int16"
、"uint16"
、"int32"
、"uint32"
、"int64"
、"uint64"
、"float"
、"double"
、"wchar"
、"text"
、"date"
、"time"
、"timestamp"
。
NodeInfo.json
类定义每个节点(node)的描述文件是一个 json 文件,它的顶层属性有:
"distance"
、"pixel"
"ADD"
、"REPLACE"
lodMode
决定其中,TileDataInfo
的类定义用 rust 表示可为:
struct TileDataInfo {
tileData: Uri,
geometry: Geometry,
attribute: Attribute,
texture: Uri,
dataType: string, // 可选值 "Vector"、"TiltPhotography"、"Model"、"BIM"、"PointCloud"、"PipeLine"、"GeoModel"、"GeoGrid"、"GeoDrill"、"GeoSection",分别表示:矢量、倾斜、模型、BIM、点云、管线、地质体、地质体网格、地址钻孔、地质剖面
}
struct Geometry {
blobType: string, // 可选值 "glb"、"glbx"
url: string,
geoCompressType: string, // 只能是 "draco"
geometryType: string, // 可选值 "Point"、"Line"、"Polygon"、"Surface"、"Entity"
}
struct Attribute {
attType: string, // 可选值 "json"、"bin"
uri: string,
}
*.m3d
文件文中对 m3d 的介绍在 7.4 节,就不复述了,主要提一点:
我觉得这个格式的提出是多余的,槽点最后再谈。
由于本部分(原文位于7.4.3节)在原文中较为详细,只捡几个点提一提。
略。
剖面使用的是一个点列表表示的简单封闭三维线,这是有缺点的,因为不能表达多剖面的情况。
地质体在此处使用了多个索引三角面来定义,其实可以完全使用 glTF 来定义,只不过这里简化成了索引+顶点的形式。
这部分的设计略显冗杂,有重复设计的嫌疑,没有优化。
属性文件的类型在 M3DDataInfo 对象中定义,见本文第 4 部分。
它使用 “属性记录(Record)” 来描述一个属性,又分了下列两个类定义:
struct Record {
oid: long,
rcdValues: Vec<RcdValue>,
}
struct RcdValue<T> {
fldName: String,
rcdValue: T
}
关于此部分的吐槽留到最后。
m3d 标准使用一个叫 oidTable
的表,记录每个 “物件” 的单体信息。
具体做法是,对每个顶点进行设定值,例如房屋A设定每个顶点的值是1,那么就记录在 oidTable 中即可。
并由此扩展 glb 文件,构成 glbx 文件。
在 Cesium 提出的 glTF 扩展中,有一个更为接近此设计的扩充:glTF 中 Primitive 的定义增加一个 _BATCHID
,使得顶点属性新增一个,与 POSITION
、COLOR
等同级别,使用此 _BATCHID
来区分顶点归属于哪个 batch。
利用 glTF 强大的扩展能力完全没必要 “扩展 glb 文件成 glbx”。
另外,单体化也是一个伪命题。因为倾斜摄影模型仅仅是有外观的三角网模型,不具备精细模型和 GIS 要素的独立性,所以才提出 “单体化” 这种词。
在 GIS 数据、BIM 数据中就很少听说过这词,因为这两种数据本身就有着完备的物件独立信息。
如果模型建模时,有完整的地理要素的定义,其实就具备了单体化的信息,使用 GIS 中的 “要素” 完全可以区分开不同的物体。
Shared
文件夹关于此文件夹没有过多的描述,只有不到 1/4 页纸。
它似乎是设计来存放公共数据的,用来提供 instance
能力。
url模板:<base-url>/services/<service-name>/M3dServer
例:
http://igserver.mapgis.com/igs/rest/services/wuhan-3d/M3dServer
调取方法是 HTTP GET
,返回类型是 application/json
url模板:<m3d-data-url>/shared-resources
例:
http://igserver.mapgis.com/igs/rest/services/wuhan-3d/M3dServer/shared-resource
调取方法是 HTTP GET
,返回类型是 application/octet-stream
略
为什么写两个就不写了?
因为原文定义已经很详细了,无需复述。
glTF
定义webp
作为纹理贴图如无必要,勿增实体。glbx 是一种多余的设计。
对于路径的定义,在原文见过 Uri
、url
、string
三种写法。
对于空间剖分的定义,在文件组织上,使用 Node
文件夹来组织,但是其下的各部分数据又使用 Tile
来定义,在原文第 3.2 节还专门说明了瓦片数据,却不见 Node
的详细定义;
在图1和图2中,对 Node 和 m3d 文件的组织十分困惑,Node<i>
目录应该是一个 Node
,下面能挂载 N 个 m3d 文件;但是在原文 3.3 节中,每个瓦片下面挂 0 或 1 个 m3d 文件,却不见瓦片的定义,只见 tile data(瓦片数据)
的定义。
asset
属性按理说可以囊括 name
、version
、guid
、dataName
等属性的,却将他们分开,不知道设计上是否经过足够的考虑。
在 M3DDataInfo 的类定义中,对于 version
字段的类型,表格里是 float
,表格上面的 UML 类图又是 string
,这种低级错误应该在校对的时候修正。
属性的默认值、属性的可选性未指出。
例如 geoCompressType
,此属性是 Geometry
类下的,按理说就不需要 geo
前缀,只需保留 compressType
即可。
还有 attType
,该简写的地方简写,此处就不该简写,它是 Attribute
对象的一个属性,所以它应该是 type
。
RcdValue
对象应该完整的命名为 RecordValue
,且其 rcdValue
应简单命名为 value
,它的类型还出现了模糊不清的定义,因为没有人知道 value
是什么值类型。
驼峰命名法、下划线命名法混用就不说了。
lodType
:对 "ADD"
、"REPLACE"
未完全解释lodError
:未解释其详细的值含义在原文的第 8 部分体现的十分明显,RESTful
风格其实完全没有必要设计如此冗杂的 URL 模板。
数据的结构层级是与行业无关的,例如 “矢量” 是一种概念,矢量数据可以囊括二维图形、三维图形数据,完全可以描述几何部分。
行业层级必须基于结构层级去定义,才有物质基础,这一点马克思老爷子早就总结好了。如果一个行业的数据对其底层的结构不清楚,例如单提 “BIM数据”,不提是什么格式,不提它的结构,那也只能是谈判桌上的词,落实不下来,谈不了什么自主创新。
若为开放标准,而使用半封闭的 rar 格式,则必须在服务端多准备一个 rar 解压的程序。
zip、7z 作为存储时能有效减少体积,但是文章中并未提及这两种压缩方式的压缩等级、压缩与解压缩的性能开销,如果因为这些延长了文件 IO 的时间,那是得不偿失的。
这一点是 i3s 的资源 gzip 法则占优,因为浏览器天生支持 gzip,并且开销不算很大。
若将来要新增气象数据或时态数据,没有留有冗余的设计。
定义这种类型的数据规范,不仅要有足够充足的行业一线实践经历,还要在 Web 可视化领域有足够的底层技术积累。
从技术和数据的视角做定义,才具备完整的可实施性和一般适配性。
M3D 的提出丰富了我国对三维数据规范的标准库,但是现在缺实现,生态不足,推广几乎没有,如何让各行各业买账,还需要走相当长的路,务必脚踏实地,方可行百里路。
原文:https://www.cnblogs.com/onsummer/p/14652462.html