Cesium 通过primitive 添加垂直图片资源

实际Cesium 项目中添加了部分贴地的资源。资源类型有图片,gltf或者glb的模型。这里简单比较一下primitive 和entity。

primitive 基于比较底层的webgl技术,进行渲染资源,所以对于很多自定义的效果支持比较好,灵活度比较高,带来的开销就是API复杂,参数多,单独相对大。

entity, 是对primitive的封装,操作简单,一般的效果都能满足。

本次项目中是为了通过坐标系,变换实体模型对象。目前知道的就是通过primitive加进去的模型,支持坐标变换。其他的应该也有,但是没接触到。

先看一下效果

其实有两种思路处理这个问题,一种是做一个glb的模型,另一外一种是通过图片作为材质创建primitive对象。实际验证的效果是通过glb模型创建添加的资源,可以实现坐标系的编辑,通过图片作为材质创建的primitive对象,无法完成坐标变换。调试发现是因为图片添加的primitive modelMatrix 为空。可能也和我操作有关,我亲自测试失败了。

作为glb模型添加

var targetPosition = Cesium.Cartesian3.fromDegrees(pos[0], pos[1], pos[2] + 0.5);
    var headingPitchRoll = new Cesium.HeadingPitchRoll(0, 0, 0);
    var modelMatrix = new Cesium.Matrix4();
    var modelEntity;
    Cesium.Transforms.headingPitchRollToFixedFrame(targetPosition, headingPitchRoll, Cesium.Ellipsoid.WGS84, Cesium.Transforms.eastNorthUpToFixedFrame, modelMatrix);
    window.setTimeout(function() {
        modelEntity = viewer.scene.primitives.add(Cesium.Model.fromGltf({
            id: src_manager._GenGuid("3d_geo_"),
            name: name,
            url: url,
            modelMatrix: modelMatrix,
            scale: 2,
            colorBlendMode: Cesium.ColorBlendMode.HIGHLIGHT
        }));
        modelEntity.readyPromise.then(function(modeltemp) {
        });
    }, 500);

作为图片添加的primitive对象,参考链接https://zhuanlan.zhihu.com/p/41862338

function addDevImg(pos, size, url) {
    var dimensions = new Cesium.Cartesian3(size, size, 1.0);
    var positionOnEllipsoid = Cesium.Cartesian3.fromDegrees(parseFloat(pos[0]), parseFloat(pos[1]));
    var translateMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(positionOnEllipsoid);
    var rotationYMatrix = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(120.0)));
    var scaleMatrix = Cesium.Matrix4.fromScale(dimensions);

    var planeYModelMatrix = new Cesium.Matrix4();
    Cesium.Matrix4.multiply(translateMatrix, rotationYMatrix, planeYModelMatrix);
    Cesium.Matrix4.multiply(planeYModelMatrix, scaleMatrix, planeYModelMatrix);

    createPlane(planeYModelMatrix, new Cesium.Color(0.0, 1.0, 0.0, 1.0));

    function createPlane(planeModelMatrix, color) {
        // 创建平面
        /*var planeGeometry = new Cesium.PlaneGeometry({
            vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
        });*/
        var planeGeometry = new Cesium.PlaneGeometry();

        var planeGeometryInstance = new Cesium.GeometryInstance({
            geometry: planeGeometry,
            modelMatrix: planeModelMatrix,
        });

        var material = new Cesium.Material({
            fabric: {
                type: "DiffuseMap",
                uniforms: {
                    image: url,
                },
            },
        });
        var model = viewer.scene.primitives.add(new Cesium.Primitive({
            geometryInstances: planeGeometryInstance,
            appearance: new Cesium.MaterialAppearance({
                closed: false,
                //translucent: false,
                material: material
            })
        }));
    }
}

 

通过坐标系拾取模型对象进行坐标变换。

function rotateTranslation(viewer) {
    //handler && handler.destroy();			
    var timeoutID = null;
    if (!window.roate_handler) {
        window.roate_handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    }
    //var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    var tooltip;
    window.roate_handler.setInputAction(function(movement) {
        tooltip = document.getElementById("toolTip");
        tooltip.innerHTML = '<p style="color:red;font-size:16px;">单击选择单体模型</p>';
        tooltip.style.display = "block";
        tooltip.style.left = movement.endPosition.x + 3 + "px";
        tooltip.style.top = movement.endPosition.y - 25 + "px";
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    //鼠标左击
    window.roate_handler.setInputAction(function(movement) {
        if (timeoutID != null) {
            clearTimeout(timeoutID);
        }
        var picked = viewer.scene.pick(movement.position);
        if (Cesium.defined(picked)) {
            if (picked.primitive) {
                var model = picked.primitive;
                var scale = model.boundingSphere.radius;
                timeoutID = window.setTimeout(function() {
                    if (window.axisModel) {
                        viewer.scene.primitives.remove(window.axisModel);
                    }
                    var axisModel = viewer.scene.primitives.add(Cesium.Model.fromGltf({
                        url: '../../Build/DECore/models/TransformGizmo_Tex12.gltf',
                        modelMatrix: model.modelMatrix,
                        scale: 2,
                        colorBlendMode: Cesium.ColorBlendMode.HIGHLIGHT
                    }));
                    if (axisModel) {
                        window.axisModel = axisModel;
                        tooltip.style.display = "none";
                        //旋转平移
                        rotateAndTranslation(viewer, model, axisModel);
                    }
                }, 250);
            }
        }
        clearAxisHandler = function(e) {
            clearTimeout(timeoutID);
            window.roate_handler = window.roate_handler && window.roate_handler.destroy();
            // downHandler = downHandler && downHandler.destroy();
            if (window.axisModel) {
                viewer.scene.primitives.remove(window.axisModel);
            }
            window.axisModel = undefined;
            tooltip.style.display = "none";
        };
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    window.roate_handler.setInputAction(function(movement) {
        clearTimeout(timeoutID);
        window.roate_handler = window.roate_handler && window.roate_handler.destroy();
        // downHandler = downHandler && downHandler.destroy();
        if (window.axisModel) {
            viewer.scene.primitives.remove(window.axisModel);
        }
        window.axisModel = undefined;
        tooltip.style.display = "none";

    }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
}

function rotateAndTranslation(viewer, model, axisModel) {
    // 事件监控
    if (!window.roate_handler) {
        window.roate_handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    }
    // 判断当前是否点击在坐标轴上进行拖动和旋转
    var isAxis = false;

    var zhou = undefined; // 当前拖拽的是哪个轴

    window.roate_handler.setInputAction(function(movement) {

        var cartesian = viewer.scene.pickPosition(movement.position);
        var pickedObject = viewer.scene.pick(movement.position);
        if (!Cesium.defined(pickedObject)) {
            return;
        }
        if (!Cesium.defined(pickedObject.mesh)) {
            return;
        }
        if (Cesium.defined(pickedObject)) {
            zhou = pickedObject.mesh.name;
            isAxis = true;
        }
    }, Cesium.ScreenSpaceEventType.LEFT_DOWN);

    window.roate_handler.setInputAction(function(movement) {
        var pickedObject = viewer.scene.pick(movement.endPosition);
        var startCartesian3 = viewer.scene.pickPosition(movement.startPosition);
        var endCartesian3 = viewer.scene.pickPosition(movement.endPosition);
        var m = model.modelMatrix;
        // 旋转和平移函数得到射线和面交点
        var axisTransForm = function(surface) {

                var matrix = Cesium.Matrix4.inverseTransformation(m, new Cesium.Matrix4());

                // 获取相机坐标
                var camera1 = viewer.camera.position;

                // 转 模型坐标
                var camera = Cesium.Matrix4.multiplyByPoint(matrix, camera1, new Cesium.Cartesian3());
                var startM = Cesium.Matrix4.multiplyByPoint(matrix, startCartesian3, new Cesium.Cartesian3());
                var endM = Cesium.Matrix4.multiplyByPoint(matrix, endCartesian3, new Cesium.Cartesian3());
                // 从相机看模型的方向
                var startDirection = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(startM, camera, new Cesium.Cartesian3()), new Cesium.Cartesian3());
                var endDirection = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(endM, camera, new Cesium.Cartesian3()), new Cesium.Cartesian3())

                // 面
                var plane = Cesium.Plane.fromPointNormal(Cesium.Cartesian3.ZERO, surface);

                // 射线
                var startRay = new Cesium.Ray(camera, startDirection);
                var endRay = new Cesium.Ray(camera, endDirection);

                // 射线和面交点
                var start = Cesium.IntersectionTests.rayPlane(startRay, plane);
                var end = Cesium.IntersectionTests.rayPlane(endRay, plane);
                return { start: start, end: end };
            }
            // 平移函数
        var axisMove = function(surface, zeroAxis1, zeroAxis2) {
            var point = axisTransForm(surface);
            // 两点差值
            var sub = Cesium.Cartesian3.subtract(point.end, point.start, new Cesium.Cartesian3());
            sub[zeroAxis1] = 0;
            sub[zeroAxis2] = 0;
            //  var sub2 = Cesium.Matrix4.multiplyByPoint(m, sub, new Cesium.Cartesian3());
            var mm = Cesium.Matrix4.multiplyByTranslation(m, sub, new Cesium.Matrix4());
            model.modelMatrix = mm;
            // 将坐标轴模型移到和模型相同的位置
            axisModel.modelMatrix = model.modelMatrix;
        }

        // 旋转函数
        var axisRotate = function(surface, tant1, tant2) {
            var point = axisTransForm(surface);
            // 两点角度
            var tant = (point.start[tant1] * point.end[tant2] - point.start[tant2] * point.end[tant1]) / (point.start[tant1] * point.end[tant1] + point.start[tant2] * point.end[tant2]);

            var quat = Cesium.Quaternion.fromAxisAngle(surface, Math.atan(tant)); //quat为围绕这个surface轴旋转d度的四元数
            var rot_mat3 = Cesium.Matrix3.fromQuaternion(quat);

            var m2 = Cesium.Matrix4.multiplyByMatrix3(m, rot_mat3, new Cesium.Matrix4());
            // 移动模型
            model.modelMatrix = m2;
            // 将坐标轴模型移到和模型相同的位置
            axisModel.modelMatrix = model.modelMatrix;
        }
        if (isAxis && startCartesian3 && endCartesian3) {

            cameraControl(false); // 禁止球转动和拖动
            switch (zhou) {
                case 'YArrow_1':
                    axisMove(Cesium.Cartesian3.UNIT_Z, 'y', 'z');
                    break;
                case 'XArrow_1':
                    axisMove(Cesium.Cartesian3.UNIT_X, 'x', 'z');
                    break;
                case 'ZArrow_1':
                    axisMove(Cesium.Cartesian3.UNIT_Y, 'x', 'y');
                    break;
                case 'YAxis_1':
                    axisRotate(Cesium.Cartesian3.UNIT_X, 'y', 'z');
                    break;
                case 'XAxis_1':
                    axisRotate(Cesium.Cartesian3.UNIT_Y, 'z', 'x');
                    break;
                case 'ZAxis_1':
                    axisRotate(Cesium.Cartesian3.UNIT_Z, 'x', 'y');
                    break;

            }

        }

    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    window.roate_handler.setInputAction(function(movement) {
        isAxis = false;
        cameraControl(true);
    }, Cesium.ScreenSpaceEventType.LEFT_UP);


    // 球转动事件
    var cameraControl = function(isCamera) {
        viewer.scene.screenSpaceCameraController.enableRotate = isCamera;
        viewer.scene.screenSpaceCameraController.enableTranslate = isCamera;
        viewer.scene.screenSpaceCameraController.enableZoom = isCamera;
        viewer.scene.screenSpaceCameraController.enableTilt = isCamera;
        viewer.scene.screenSpaceCameraController.enableLook = isCamera;
    }

}

最后结合一下,把图片贴在透明的glb模型上,按glb模型的方式统一加载,效果可以。贴一张效果图。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老朱自强不息

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值