完整代码下载:https://download.csdn.net/download/caozl1132/13755277
有时我们在项目里加载一个3dtiles模型但是总是调整不到对应的位置上去,如果我们靠修改代码里的参数一点点儿的挪,效率就太低了,针对这种情况我单独开发了一个页面来进行模型的调整。
以下是界面:此处借用了火星的地形及案例里的模型(表示感谢,如有侵权,请告知修改)。
先说下这个界面为什么要这样设置:本页面主要设置了两个模块 地形模块及模型模块
为什么此处要对地形还做这么多的选项呢?
在开发的过程中,一般在不同的地形上,模型的设置高度是不一样的。此处我设置了三种地形,第一种火星地形是火星服务器上的地形,他和我们常用的30m地形以及cesium ion的地形是不一样。 第二种就是ion地形,cesium官方在线地形,此处不做解释。第三种是自定义在线地形,大部分时候我们为了具体的项目业务开发,会将dem数据单独发布成地形(如何发布,出门左转参考我的另一篇文章),此处第三种自定义地形就是为了方便在自定义地形上进行高度调节的。
下面模块是模型模块,针对我们加载的模型进行调节。其中经度、纬度、高度为一个模型的基本属性,加载后自动计算模型的包围盒的center然后在此处赋值。
下面的是设置模型的旋转轴。有时我们的模型的朝向可能不是我们理想的方向,可以通过此处的设置进行模型方向的设置。
以下晒出核心代码:其中有部分方法我封装起来了,都是简单的方法,可以自己写下。
// 加载3dtiles
var tileset;
function load3dtiles(url, success) {
if (!url) {
alert("缺少模型地址");
return;
}
var tp = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
maximumScreenSpaceError: 1,
url: url
})
);
tp.readyPromise.then(function (tileset) {
if (success) success(tileset);
}).otherwise(function (error) { })
}
// 修改3dtiles位置
/* var opt = {
position: "",
rx: 30,
ry: 30,
rz: 30,
scale: 2
} */
function update3dtiles(tileset, opt) {
if (!tileset) {
alert("缺少模型!")
return;
}
var position = opt.position;
if (!position) {
alert("缺少坐标信息!")
return;
}
opt.scale = opt.scale || 1; // 缩放系数 默认为1
// 建立从局部到世界的坐标矩阵
var mtx = Cesium.Transforms.eastNorthUpToFixedFrame(position);
Cesium.Matrix4.multiplyByUniformScale(mtx, opt.scale,
mtx);
// 表示绕x轴旋转
if (opt.rx) {
var mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(opt.rx)); //绕x轴旋转
var rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
Cesium.Matrix4.multiply(mtx, rotationX, mtx);
}
// 表示绕x轴旋转
if (opt.ry) {
var my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(opt.ry)); //绕x轴旋转
var rotationY = Cesium.Matrix4.fromRotationTranslation(my);
Cesium.Matrix4.multiply(mtx, rotationY, mtx);
}
// 表示绕x轴旋转
if (opt.rz) {
var mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(opt.rz)); //绕x轴旋转
var rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
Cesium.Matrix4.multiply(mtx, rotationZ, mtx);
}
tileset._root.transform = mtx;
}
以下重点解释下update3dtiles()方法:
看了加载代码的朋友都知道,在cesium里对一个模型进行位置设定和修改都是通过matrix即模型矩阵,所以如果我们想修改模型的姿态也是通过设置模型的矩阵。
所以:
1、var mtx = Cesium.Transforms.eastNorthUpToFixedFrame(position);
在指定位置建立局部坐标系,建立模型和世界坐标之间的转换矩阵。(此处涉及到webgl中的几个矩阵,比如模型矩阵、视图矩阵、投影矩阵等,可看下webgl编程指南第七章,内部有详细讲解)。由于此处并未用到世界坐标转换到局部坐标,故没有用到逆转矩阵inverse。
2、Cesium.Matrix4.multiplyByUniformScale(mtx, opt.scale,
mtx);
此处是缩放,这个是cesium内置的矩阵缩放方法。
3、
var mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(opt.rx)); //绕x轴旋转
var rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
Cesium.Matrix4.multiply(mtx, rotationX, mtx);
此处是旋转,中间用了Cesium.Matrix4.fromRotationTranslation(mx)这个方法,主要是将三维矩阵转化为四维矩阵,因为我们知道你如果想同时完成平移和旋转必须得四维矩阵(单独旋转,三维矩阵即可,单独平移也要四维矩阵),并且模型的矩阵类型也是四维的。
注:这里只能修改一次,不能连续修改(比如先绕x轴旋转60度,再绕z轴旋转60度,这里是做不到的,这里会直接绕z轴旋转60度)。想要连续修改得改下代码。这里平时也够用了。