有人说 3d tiles的初始位置由tileset.json中root.transform的变换矩阵指定
然而, 当tileset.json没有定义transform时, 加载的模型还是有位置的.
GPT4回答
在 3D Tiles 数据中,地理位置信息通常存储在以下文件中:
1. **tileset.json**: 这是 3D Tiles 数据集的主要入口文件,包含了关于瓦片集(tileset)的层次结构和元数据。在这个文件中,你可以找到关于每个瓦片(tile)的地理范围(bounding volume)信息,通常以经纬度坐标表示。这有助于确定瓦片在地球上的位置。
2. **瓦片文件(如 .b3dm、.i3dm、.pnts 等)**: 这些文件包含了实际的 3D 模型数据,可能存有地理位置信息。这些文件中可能包含模型的局部坐标系到地理坐标系的转换矩阵,或者包含模型中每个顶点的地理位置。
3. **.glTF 文件(如 .gltf 或 .glb)**: 如果你的 3D Tiles 数据集包含 glTF 格式的模型,那么地理位置信息可能包含在这些文件中。glTF 文件可以包含模型的顶点坐标以及模型的局部坐标系到地理坐标系的转换矩阵。要注意的是,glTF 文件通常在 .b3dm 或 .i3dm 文件中嵌入。
通过查看上述文件,你应该可以找到 3D Tiles 数据中的地理位置信息。
实验数据:
'requestTiles (Cesium.js:107407)分支'
ForEach.topLevel (Cesium.js:65203)
ForEach.material (Cesium.js:65319)
addDefaults (Cesium.js:65581)
(匿名) (Cesium.js:68270)
Promise.then(异步)
processGltfJson (Cesium.js:68269)
processGltfTypedArray (Cesium.js:68284)
GltfJsonLoader.load (Cesium.js:68172)
ResourceCache.load (Cesium.js:69956)
ResourceCache.loadGltfJson (Cesium.js:70067)
GltfLoader.load (Cesium.js:74203)
B3dmLoader.load (Cesium.js:76938)
initialize19 (Cesium.js:88021)
Model (Cesium.js:87953)
Model.fromB3dm (Cesium.js:89114) //这里开始有了model.modelMatrix定义了位置,还是model.referenceMatrix影响位置?
//是 model._boundingSphere
//是 model._sceneGraph.boundingSphere.center
//是 ModelSceneGraph.js 的 ModelSceneGraph.buildDrawCommands的model 的 this._boundingSphere =
//BoundingSphere.fromCornerPoints(primitiveRenderResources.positionMin 和 positionMax)
//是 PrimitiveRenderResources 的 runtimePrimitive.primitive.attributes[0]是:
{
"name": "POSITION",
"semantic": "POSITION",
"componentDatatype": 5126,
"type": "VEC3",
"normalized": false,
"count": 240,
//位置就藏在这里!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
"min": {"x": 1214922.0063094844,"y": -4736399.2068924345,"z": 4081525.4477709476},
"max": {"x": 1215121.59033861,"y": -4736238.163863403,"z": 4081670.8300574976},
"constant": {"x": 0,"y": 0,"z": 0},
"buffer": {
"_id": "a3ded257-2908-4de7-9476-4baa2a022801",
"_gl": {},
"_webgl2": true,
"_bufferTarget": 34962,
"_sizeInBytes": 2880,
"_usage": 35044,
"_buffer": {},
"vertexArrayDestroyable": false
},
"byteOffset": 0,
"byteStride": 12
}
//primitive是ModelSceneGraph.traverseAndCreateSceneGraph把ModelSceneGraph._components.scene.nodes[i].rootNode.primitives[j]传给new ModelRuntimePrimitive再推进runtimePrimitive数组的
//primitive.attributes 本质是GltfLoader.js构造的node,见[[Cesium-GLTF#components]]
Model3DTileContent.fromB3dm (Cesium.js:89456) //modelMatrix: tile.computedTransform, //modelMatrix其实是tile的computedTransform
b3dm (Cesium.js:99387)
makeContent (Cesium.js:104921)
(匿名) (Cesium.js:104859)
Promise.then(异步)
requestSingleContent (Cesium.js:104854)
Cesium3DTile.requestContent (Cesium.js:104758)
Cesium3DTile_default.requestContent (Cesium.js:182512)
requestContent (Cesium.js:107323)
requestTiles (Cesium.js:107407)
追踪源码可知, 其实 b3dm 中的 gltf 中存着模型的 地理位置 !
在 /Source/Scene/GltfLoader.js 的 function parse(loader, gltf, supportedImageFormats, frameState) 打断点可以看到, gltf 其信息如下:
{
"asset": { "credits": [] },
"scene": {
"nodes": [
{
"index": 0,
"children": [],
"primitives": [
{
"attributes": [
{
"name": "POSITION",
"semantic": "POSITION",
"componentDatatype": 5126,
"type": "VEC3",
"normalized": false,
"count": 240,
"min": {"x": 1214922.0063094844,"y": -4736399.2068924345,"z": 4081525.4477709476},//地理位置
"max": {"x": 1215121.59033861,"y": -4736238.163863403,"z": 4081670.8300574976},//地理位置
"constant": {"x": 0,"y": 0,"z": 0},
"byteOffset": 0,
"byteStride": 12
},
{
"name": "NORMAL",
"semantic": "NORMAL",
"componentDatatype": 5126,
"type": "VEC3",
"normalized": false,
"count": 240,
"min": {"x": -0.9686356343768793,"y": -0.7415555652213445,"z": -0.7655670913845589},
"max": {"x": 0.9686356343768793,"y": 0.7415555652213445,"z": 0.7655670913845589},
"constant": {"x": 0,"y": 0,"z": 0},
"byteOffset": 0,
"byteStride": 12
},
{
"name": "_BATCHID",
"semantic": "_FEATURE_ID",
"setIndex": 0,
"componentDatatype": 5126,
"type": "SCALAR",
"normalized": false,
"count": 240,
"min": 0,
"max": 9,
"constant": 0,
"byteOffset": 0,
"byteStride": 4
}
],
"morphTargets": [],
"indices": {
"count": 360
},
"material": {
"metallicRoughness": {
"baseColorFactor": {"x": 1,"y": 1,"z": 1,"w": 1},
"metallicFactor": 0,
"roughnessFactor": 1
},
"emissiveFactor": {
"x": 0,"y": 0,"z": 0},
"alphaMode": "OPAQUE",
"doubleSided": false,
"unlit": false
},
"primitiveType": 4,
"featureIds": [],
"propertyTextureIds": [],
"propertyAttributeIds": []
}
],
"matrix": {"0": 1,"1": 0,"2": 0,"3": 0,"4": 0,"5": 0,"6": -1,"7": 0,"8": 0,"9": 1,"10": 0,"11": 0,"12": 0,"13": 0,"14": 0,"15": 1},
"morphWeights": []
}
]
},
"nodes": [],
"skins": [],
"animations": [],
"articulations": [],
"upAxis": 1,
"forwardAxis": 0,
"transform": {"0": 1,"1": 0,"2": 0,"3": 0,"4": 0,"5": 1,"6": 0,"7": 0,"8": 0,"9": 0,"10": 1,"11": 0,"12": 0,"13": 0,"14": 0,"15": 1}
}
看看坐标的经纬度高度是多少吧
var cartesian3 = Cesium.Cartesian3.fromArray([1214922.0063094844, -4736399.2068924345, 4081525.4477709476]);
var cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
var longitude = Cesium.Math.toDegrees(cartographic.longitude);
var latitude = Cesium.Math.toDegrees(cartographic.latitude);
var height = cartographic.height;
[longitude,latitude,height]
//(3) [-75.6133766160362, 40.04162788081164, 0.2805463552731406]
总结
本质是modelMatrix决定了位置, 而 ModelSceneGraph.buildDrawCommands 用 ModelDrawCommand 决定了 modelMatrix 取决于:
- this.runtimePrimitive.boundingSphere //取决于GLTF中定义的scene.nodes[i].primitives[j].attributes[k].min|max的xyz坐标
- this._modelMatrix //取决与我们代码传入的modelMatrix
- this._boundingVolume //取决于GLTF中定义的scene.nodes[i].primitives[j].attributes[k].min|max的xyz坐标, 但还判断是场景是2D模式还是3D模式