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

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

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

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

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

先看一下效果

Cesium 通过primitive 添加垂直图片资源_第1张图片

其实有两种思路处理这个问题,一种是做一个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 = '

单击选择单体模型

'; 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模型的方式统一加载,效果可以。贴一张效果图。

Cesium 通过primitive 添加垂直图片资源_第2张图片

你可能感兴趣的:(Cesium)