关于加载3dtile模型数据及修改坐标
3d tile模型是倾斜摄影模型,导出的坐标可能不对,或者坐标需要调整
Cesium下如何加载、修改3d tile模型的海拔及经纬度
⽅案⼀、加载的同时,指定变换矩阵进⾏修改
const url ='/local/3dtile.json'
const x =[
identity matrix是什么意思1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1]// 这⾥的实际上不是这个1矩阵
const modelMatrix =new Cesium.Matrix4(...x)
const tileset =new Cesium.Cesium3DTileset({
url,
maximumScreenSpaceError:1,
maximumNumberOfLoadedTiles:1000,
modelMatrix
})
viewer.scene.primitives.add(tileset)
代码分析:
modelMatrix 需要提前获取,如何获取见下⽂如何获取需要的变换矩阵
this._viewer.scene.primitives.add(tileset) 执⾏完成后,返回titleset本⾝
注意: modelMatrix 的变化貌没法让3d tile 绕⾃⾝中⼼的坐标进⾏旋转,什么原因没到,实际测试
过多次没实现。猜测有可能是模型的相对坐标就正好是世界坐标,所以,发现⽆论怎么调整这个modelMatrix发现都有问题(通
过Cesium.Matrix3.fromRotationX(Radians(heading) 获得的旋转矩阵,貌似旋转中⼼,在世界坐标系的x y z轴上,所以看起来,旋转的⾓度特别⼤)。
也可以直接 delMatrix=modelMatrix 与上⾯的效果是样的,这也提供了⼀种加载后,动态修改3d tile的坐标的⽅法
⽤这种⽅法去实现修改位置时,主要是通过使⽤旋转(矩阵中主要是旋转变换)来实现模型的位置修改的,因为旋转中⼼是世界坐标,所以旋转矩阵的效果就是在地表进⾏⼤圆移动。⽽如果矩阵中有平移变换的话,那么,貌似⼜好像是相对模型中⼼进⾏平移的。
⽅案⼆、加载完成后,在加载完成的回调中、或后续作动态修改(常⽤)
下⾯实现,指定经纬度、海拔来修改3d tile模型
const url ='/local/3dtile.json'
const pos ={lng:110.0, lat:22.1, alt:100}
const tileset =new Cesium.Cesium3DTileset({
url,
maximumScreenSpaceError:1,
maximumNumberOfLoadedTiles:1000,
})
viewer.scene.primitives.add(tileset)
const modifyPos=()=>{
const{lng, lat, alt }= pos
const position = Cesium.Cartesian3.fromDegrees(lng, lat, alt)
const mat = Cesium.Transforms.eastNorthUpToFixedFrame(position)
/
*
const heading = 45 // 绕X轴⾓度
const A = Cesium.Matrix3.fromRotationX(Radians(heading))
const rotationX = Cesium.Matrix4.fromRotationTranslation(A);
Cesium.Matrix4.multiply(mat, rotationX, mat)
*/
}
代码分析
Cesium.Transforms.eastNorthUpToFixedFrame(position) 是世界坐标到某点的局部坐标的变换获取
关键是ansform = mat ,使⽤模型平移变换,上⾯已经获取了世界坐标到局部指定点的变换了,将该变换给到tileset,即可实现模型移动到指定点
注意:上⾯代码中,有⼀段注释,该段的内容为获取绕X轴的旋转矩阵,这也是⽹上很多所谓可实现平移+旋转的⽅法,但是,实际只有平移有效,即使该变换矩阵包含旋转的内容,也只有平移⽣效。ansform 显然,只能改变平移
如何上⾯回调中获取的矩阵该直接给delMatrix = mat,你会发现,你的模型飞去很远很远的外太空,直接对modelMatrix 进⾏修改,可以理解为相对平移,⽽Cesium.Transforms.eastNorthUpToFixedFrame(position) 是世界坐标中⼼到指定点的平移,显然这个移动是很⼤的。
两种⽅式的总结
上⾯两种⽅式都有点怪异:
⽅法⼀、可实现绕地球旋转(不可绕⾃⾝旋转),但是旋转中⼼在世界坐标系中⼼,也就是相当于绕地表进⾏旋转,最后的效果等效于实现位置修改;⽽平移的平移中⼼⼜好像在模型中⼼
⽅法⼆、不可实现旋转变换,可实现正确平移,任意指定经纬度海拔,实现定位
如何获取需要的变换矩阵
前⾯第⼀种⽅法实现经纬度的定位关键是要获取modelMatrix,那怎么获取呢?
⼿动调整,⼀点点测试
默认情况下delMatrix = Cesium.Matrix4.IDENTITY (就是对⾓1) ,下⾯提供⼀种⽅法实现模型的位置调整,然后,打印modelMatrix 的值,再把该值写在代码中
offset=(type, value=0.0001)=>{
const m = delMatrix
let m1
if(type==='x') m1 = Cesium.Matrix3.fromRotationX(value)
if(type==='y') m1 = Cesium.Matrix3.fromRotationY(value)
if(type==='z') m1 = Cesium.Matrix3.fromRotationZ(value)
Cesium.Matrix4.multiplyByMatrix3(m, m1, m)
console.delMatrix)
}
注意: Cesium.Matrix4.multiplyByMatrix3(mat4, mat3, mat4) 第⼀个参数是4阶矩阵
上⾯的第⼆种⽅法,则可直接初步设置⼀个⼤该位置的坐标,然后,通过修改position坐标,并通
过Cesium.Transforms.eastNorthUpToFixedFrame(position)重新计算新的矩阵,当然修改的position你需要⾃⼰记录好
确定好正确的位置后,再把pos写到代码中
modifyPos = (newPos)=>{
const {lng, lat, alt } = newPos
const position = Cesium.Cartesian3.fromDegrees(lng, lat, alt)
const mat = Cesium.Transforms.eastNorthUpToFixedFrame(position)
console.log(newPos)
}
⽆论如何,还没到使⽤模型绕⾃⾝旋转的⽅法。或者说使坐标系移动到模型内部。这样对delMatrix的修改,理论上就可以实现任意的变换了。(获取该倾斜摄影模型导出时坐标系没设置好,所以导致这样的问题)
遇到的坑
1、 关于矩阵的坑
通过delMatrix输出的是⼀个16个元素的数组[],在回写到代码中重构属性性需要注意,创建的4阶矩阵的元素排布问题
console.delMatrix)// [x1,x2,x3,x4, y1,y2,y3,y4, z1,z2,z3,z4, o1,o2,o3,o4]
m =new Cesium.Matrix4(
x1, y1, z1, o1,
x2, y2, z2, o2,
x3, y3, z3, o3,
x4, y4, z4, o4)
2、关于异步加载未完成时前,⽆法使⽤root属性的坑
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论