说在前面:加载和旋转缩放没什么好说的,但是平移还是用些细节要注意的。我也是跳了几天才偶然发现问题。

1、primitives方式加载:

handler.setInputAction(function (evt) {
    let cartesian = viewer.scene.pickPosition(evt.position);
    if (Cesium.defined(cartesian)) {
        let headingPitchRoll = new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(0), Cesium.Math.toRadians(0), Cesium.Math.toRadians(0));
        let modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(cartesian, headingPitchRoll, Cesium.Ellipsoid.WGS84, Cesium.Transforms.eastNorthUpToFixedFrame, new Cesium.Matrix4());
        let model = viewer.scene.primitives.add(Cesium.Model.fromGltf({
            url :  '../src/data/GLTF/oneBuilding.gltf',
            modelMatrix : modelMatrix,
            minimumPixelSize : 128,
            scale : 1,
            cull:false,
        }));
    }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

2、旋转和缩放(说明一点,我设定的鼠标在3Dtiles上移动点击才可以。向直接在地表点击的话可能需要修改 判断是否是渠道模型 的那句代码)

// 旋转的关键代码
handler.setInputAction(function (evt) {
    let pickedObject = viewer.scene.pick(evt.position); //判断是否拾取到模型
    if ( pickedObject ){
        let m = pickedObject.primitive.modelMatrix;// 带旋转模型的矩阵
        let rotationM = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(rtaleX)); // rtaleX表示水平方向旋转的度数
        let newMatrix4 = Cesium.Matrix4.multiplyByMatrix3(m, rotationM, new Cesium.Matrix4());// 计算矩阵4的变换矩阵(在原变换中,累加变换)
        pickedObject.primitive.modelMatrix = newMatrix4
    }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);


// 调整高度的关键代码
handler.setInputAction(function (evt) {
    let pickedObject = viewer.scene.pick(evt.position); //判断是否拾取到模型
    if ( pickedObject ){
        let oldMatrix = pickedObject.primitive.modelMatrix;// 模型的矩阵
        let oldCenter = new Cesium.Cartesian3(oldMatrix[12],oldMatrix[13],oldMatrix[14]);// 模型高度调整前中心点笛卡尔坐标
        let oldCartographic = Cesium.Cartographic.fromCartesian(oldCenter);// 高度调整前的弧度坐标
        let newHeight = oldCartographic.height+height;
        let newCartographic = new Cesium.Cartographic( oldCartographic.longitude, oldCartographic.latitude, newHeight ); // 高度调整后的弧度坐标
        let newCartesian = viewer.scene.globe.ellipsoid.cartographicToCartesian(newCartographic);
        let headingPitchRoll = new Cesium.HeadingPitchRoll(0,0,0);
        let m = Cesium.Transforms.headingPitchRollToFixedFrame(newCartesian, headingPitchRoll, Cesium.Ellipsoid.WGS84, Cesium.Transforms.eastNorthUpToFixedFrame, new Cesium.Matrix4());
        pickedObject.primitive.modelMatrix = m;// 平移变换
    }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

3、平移:这是我写这篇博客的关键。管网demo里升降平移是对3Dtiles,对gltf不一定有效的,我也是愣了几天偶然改正确的,主要就是获取鼠标移动时坐标。

// 移动模型
function moveGltfModel ( ) {
    let _this = this;
    let viewer = _this.viewer;
    let handler = new Cesium.ScreenSpaceEventHandler( viewer.canvas);
    let pickedObject = null;
    let leftDownFlag = false;
    let rtaleX = parseFloat( $("#rangeRtaleX").val() );

    handler.setInputAction(function (movement) {
        pickedObject = viewer.scene.pick(movement.position);
        if(Cesium.defined(pickedObject)){
            if (pickedObject.primitive.isCesium3DTileset == undefined ){
                leftDownFlag = true;
                document.body.style.cursor = 'pointer';
                viewer.scene.screenSpaceCameraController.enableRotate = false;//锁定相机
                pickedObject.primitive.color = new Cesium.Color(0, 1, 0, 1); //选中模型后高亮
                pickedObject.primitive.silhouetteSize = 3.0;//选中模型后高亮
            }
        }
    }, Cesium.ScreenSpaceEventType.LEFT_DOWN);

    handler.setInputAction(function () {
        pickedObject.primitive.color = new Cesium.Color(1, 1, 1, 1);
        pickedObject.primitive.silhouetteSize = 0;
        leftDownFlag = false;
        pickedObject = null;
        viewer.scene.screenSpaceCameraController.enableRotate = true;//解除锁定相机
        handler.destroy();//销毁左键监听事件
        document.body.style.cursor = 'default';
    }, Cesium.ScreenSpaceEventType.LEFT_UP);

    handler.setInputAction((movement) => {
        if ( leftDownFlag && pickedObject.primitive.modelMatrix ) {

            // ************g关键代码:cartesian的值************
            let ray = viewer.camera.getPickRay(movement.endPosition);
            let cartesian = viewer.scene.globe.pick(ray, viewer.scene);
            let headingPitchRoll = new Cesium.HeadingPitchRoll( Cesium.Math.toRadians(0),0,0);
            let m = Cesium.Transforms.headingPitchRollToFixedFrame(cartesian, headingPitchRoll, Cesium.Ellipsoid.WGS84, Cesium.Transforms.eastNorthUpToFixedFrame, new Cesium.Matrix4());
            pickedObject.primitive.modelMatrix = m;

        }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}

说明一下:我之前用了好几种获取鼠标坐标导致的结果是移动时会到处跑。但下面这样获取就不会。

// 这样获取就不会到处跑
let ray = viewer.camera.getPickRay(movement.endPosition);
let cartesian = viewer.scene.globe.pick(ray, viewer.scene);


//列几种我之前的获取方式会出问题的额 
// let headingPitchRoll = new Cesium.HeadingPitchRoll(0,0,0);
// let cartesian = viewer.scene.pickPosition(movement.endPosition);

// let headingPitchRoll = new Cesium.HeadingPitchRoll(0,0,0);
// let position = viewer.scene.globe.pick(viewer.camera.getPickRay(movement.endPosition), viewer.scene);// 获取鼠标移动后的点
// let cartesian = new Cesium.Cartesian3( position.x, position.y, position.z )

扩展一下:entity加载的话,直接修改entity的position就可以了

handler.setInputAction(function (movement) {
    if (leftDownFlag === true && pointDraged != null) {
        let ray = viewer.camera.getPickRay(movement.endPosition);
        let cartesian = viewer.scene.globe.pick(ray, viewer.scene);
        console.log(cartesian);
        pointDraged.id.position = new Cesium.CallbackProperty(function () {
            return cartesian;
        }, false);//防止闪烁,在移动的过程
    }
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);