Cesium 模型压平

这篇具有很好参考价值的文章主要介绍了Cesium 模型压平。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近整理了下手上的代码,以下是对模型压平的说明。

原理是使用了customShader来重新设置了模型的着色器,通过修改模型顶点的坐标来实现了压平。
Cesium 模型压平,前端,Cesium,压平

废话不多说,下面上代码:

/**
 * @class
 * @description 3dtiles模型压平
 */
class Flat {
    /**
     * 
     * @param {Cesium.Cesium3DTileset} tileset 三维模型
     * @param {Object} opt 
     * @param {Number} opt.flatHeight 压平高度 
     */
    constructor(tileset, opt) {
        if (!tileset) return;
        this.tileset = tileset;
        this.opt = opt || {};
        this.flatHeight = this.opt.flatHeight || 0;

        this.center = tileset.boundingSphere.center.clone();


        this.matrix = Cesium.Transforms.eastNorthUpToFixedFrame(this.center.clone());
        this.localMatrix = Cesium.Matrix4.inverse(this.matrix, new Cesium.Matrix4());

        // 多面的坐标数组
        this.regionList = [];
        // 多个面坐标转为局部模型坐标
        this.localPositionsArr = [];
    }

    /**
     * 添加压平面
     * @param {Object} attr 参数
     * @param {Cesium.Cartesian3[]} attr.positions 压平面坐标
     * @param {Number} attr.height 压平深度,当前不支持单独设置
     * @param {Number} attr.id 唯一标识
     */
    addRegion(attr) {
        let { positions, height, id } = attr || {};
        // this.flatHeight = height;
        if (!id) id = (new Date()).getTime() + "" + Number(Math.random() * 1000).toFixed(0);
        this.regionList.push(attr);
        for (let i = 0; i < this.regionList.length; i++) {
            let item = this.regionList[i];
            const positions = item.positions;
            let localCoor = this.cartesiansToLocal(positions);
            this.localPositionsArr.push(localCoor);
        }

        const funstr = this.getIsinPolygonFun(this.localPositionsArr);
        let str = ``;
        for (let i = 0; i < this.localPositionsArr.length; i++) {
            const coors = this.localPositionsArr[i];
            const n = coors.length;
            let instr = ``;
            coors.forEach((coordinate, index) => {
                instr += `points_${n}[${index}] = vec2(${coordinate[0]}, ${coordinate[1]});\n`;
            })
            str += `
                ${instr}
                if(isPointInPolygon_${n}(position2D)){
                    vec4 tileset_local_position_transformed = vec4(tileset_local_position.x, tileset_local_position.y, ground_z, 1.0);
                    vec4 model_local_position_transformed = czm_inverseModel * u_tileset_localToWorldMatrix * tileset_local_position_transformed;
                    vsOutput.positionMC.xy = model_local_position_transformed.xy;
                    vsOutput.positionMC.z = model_local_position_transformed.z+ modelMC.z*0.002;
                    return;
                }`;

        }

        this.updateShader(funstr, str);
    }

    /**
     * 根据id删除压平的面
     * @param {String} id 唯一标识
     */
    removeRegionById(id) {
        if (!id) return;

        this.regionList = this.regionList.filter((attr) => {
            return attr.id != id;
        })

        this.localPositionsArr = [];
        for (let i = 0; i < this.regionList.length; i++) {
            let item = this.regionList[i];
            const positions = item.positions;
            let localCoor = this.cartesiansToLocal(positions);
            this.localPositionsArr.push(localCoor);
        }

        const funstr = this.getIsinPolygonFun(this.localPositionsArr);
        let str = ``;
        for (let i = 0; i < this.localPositionsArr.length; i++) {
            const coors = this.localPositionsArr[i];
            const n = coors.length;
            let instr = ``;
            coors.forEach((coordinate, index) => {
                instr += `points_${n}[${index}] = vec2(${coordinate[0]}, ${coordinate[1]});\n`;
            })
            str += `
                ${instr}
                if(isPointInPolygon_${n}(position2D)){
                    vec4 tileset_local_position_transformed = vec4(tileset_local_position.x, tileset_local_position.y, ground_z, 1.0);
                    vec4 model_local_position_transformed = czm_inverseModel * u_tileset_localToWorldMatrix * tileset_local_position_transformed;
                    vsOutput.positionMC.xy = model_local_position_transformed.xy;
                    vsOutput.positionMC.z = model_local_position_transformed.z+ modelMC.z*0.002;
                    return;
                }`;

        }
        this.updateShader(funstr, str);
    }

    /**
     * 销毁
     */
    destroy() {
        this.tileset.customShader = undefined;
    }

    /**
     * 根据数组长度,构建 判断点是否在面内 的压平函数
     */
    getIsinPolygonFun(polygons) {
        let pmap = polygons.map((polygon) => polygon.length);
        let uniqueArray = this.getUniqueArray(pmap);
        let str = ``;
        uniqueArray.forEach(length => {
            str += `
                vec2 points_${length}[${length}];
                bool isPointInPolygon_${length}(vec2 point){
                int nCross = 0; // 交点数
                const int n = ${length}; 
                for(int i = 0; i < n; i++){
                    vec2 p1 = points_${length}[i];
                    vec2 p2 = points_${length}[int(mod(float(i+1),float(n)))];
                    if(p1[1] == p2[1]){
                        continue;
                    }
                    if(point[1] < min(p1[1], p2[1])){
                        continue;
                    }
                    if(point[1] >= max(p1[1], p2[1])){
                        continue;
                    }
                    float x = p1[0] + ((point[1] - p1[1]) * (p2[0] - p1[0])) / (p2[1] - p1[1]);
                    if(x > point[0]){
                     nCross++;
                    }
                }

                return int(mod(float(nCross), float(2))) == 1;
                }
            `
        })
        return str
    }

    updateShader(vtx1, vtx2) {
        let flatCustomShader = new Cesium.CustomShader({
            uniforms: {
                u_tileset_localToWorldMatrix: {
                    type: Cesium.UniformType.MAT4,
                    value: this.matrix,
                },
                u_tileset_worldToLocalMatrix: {
                    type: Cesium.UniformType.MAT4,
                    value: this.localMatrix,
                },
                u_flatHeight: {
                    type: Cesium.UniformType.FLOAT,
                    value: this.flatHeight,
                },
            },
            vertexShaderText: `
            // 所有isPointInPolygon函数
            ${vtx1}
            void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput){
                vec3 modelMC = vsInput.attributes.positionMC;
                vec4 model_local_position = vec4(modelMC.x, modelMC.y, modelMC.z, 1.0);
                vec4 tileset_local_position = u_tileset_worldToLocalMatrix * czm_model * model_local_position;
                vec2 position2D = vec2(tileset_local_position.x,tileset_local_position.y);
                float ground_z = 0.0 + u_flatHeight;
                // 多个多边形区域
                ${vtx2}
            }`,
        });
        this.tileset.customShader = flatCustomShader;
    }

    // 数组去重,不能处理嵌套的数组
    getUniqueArray = (arr) => {
        return arr.filter(function (item, index, arr) {
            //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
            return arr.indexOf(item, 0) === index;
        });
    }


    // 世界坐标转数组局部坐标
    cartesiansToLocal(positions) {
        let arr = [];
        for (let i = 0; i < positions.length; i++) {
            let position = positions[i];
            let localp = Cesium.Matrix4.multiplyByPoint(
                this.localMatrix,
                position.clone(),
                new Cesium.Cartesian3()
            )
            arr.push([localp.x, localp.y]);
        }
        return arr;
    }


}

export default Flat;

调用方式:

let flatTool = new Flat(tileset, {
            flatHeight: -30
        });

 flatTool.addRegion({
                positions : positions,
                id : new Date().getTime()
            });

以下是仓库地址:

CesiumExp-tilesetFlat: 3dtiles模型压平
 文章来源地址https://www.toymoban.com/news/detail-788630.html

到了这里,关于Cesium 模型压平的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Cesium学习(六)】Cesium加载3D模型(3D tiles和glTF模型)

    前面我们学习到了绘制基本的形状,但是Cesium还可以加载3D模型,因为像高德地图这种的技术来加载大型复杂的建筑模型性能不加,所有只能想Cesium这种专门做3D地图的技术。接下来就学习一下如何加载模型。 Cesium目前支持两种模型方案,一个是使用3D tiles, 另一个是加载g

    2024年02月07日
    浏览(51)
  • Cesium设置模型朝向速度矢量方向

    现有一段飞机起飞、爬升的轨迹数据,需要在Cesium中模拟出飞行过程动画,要求飞机模型的姿态随着速度矢量方向变化,而不是一直保持飞机模型的原始状态。 在 Cesium.Entity 类中有属性 orientation 可以用来控制实体模型 model 的朝向,当不设置该属性时,模型就保持原始状态。

    2024年02月10日
    浏览(38)
  • cesium加载三维模型3dtiles

    目的:为避免跨域 输入cmd命令 python3 -m http.server 5500 http://127.0.0.1:5500/data/mars3d-max-shihua-3dtiles-master/tileset.json http://127.0.0.1:5500/cesium/cesium%E5%8A%A0%E8%BD%BD3dtile2.html

    2024年02月13日
    浏览(90)
  • Cesium地图上加载3DTiles模型

    1,使用Blender创建模型: 官网下载Blender:https://www.blender.org/,在Github上下载Building Tools插件,通过编辑-偏好设置-插件-安装,导入压缩包使用,这个可以自己创建小房子,文件-导出为obj格式 2,将.obj转成3dtiles格式: 1,第一种方法通过加载本地文件展示: 1,github下载ObjTo3

    2024年02月03日
    浏览(46)
  • Cesium:3DTiles三维模型高度调整

            地形遮挡属性          如下两张图所示,输入高度值,根据需要调整模型高度。例如:针对近地面的管线数据,可能有一部分是埋在地下的,那么,如果开启了地形遮挡属性(即:设置为true,默认是false),那么,在进行场景渲染加载模型切片时,就会进行深度测

    2024年02月11日
    浏览(92)
  • 【Cesium】调整3dtiles模型的光照

    最近有个项目需要把掘进车放到巷道里面,加载出来的效果一片漆黑,看不清模型细节。  由于Cesium中材质没有自发光的设置,所以只能设置光源。 在网上查了一些代码,Cesium的光照效果的设置是通过webgl修改白膜的材质来实现的,由于巷道本身有贴图材质,用该方法实现的

    2024年02月11日
    浏览(52)
  • Cesium模型漫游过程中姿态动态调整

    一、功能设计 模型漫游过程中姿态动态调整有两种情况: 1)速度沿默认方向-运动过程中的姿态动态调节 2)沿速度矢量方向-运动过程中姿态的动态调节 二、对数据和服务的要求 gltf数据 三、接口设计 通过修改AnimationTool上的modelHeading,modelPitch,modelRoll来进行姿态动态调节

    2024年02月13日
    浏览(40)
  • vue结合Cesium加载gltf模型

    Cesium支持什么格式?         Cesium支持的格式包括:3D模型格式(如COLLADA、gITF、OBJ)、影像格式(如JPEG、PNG、GeoTIFF)、地形格式(如STL、Heightmap)、矢量数据格式(如GeoJSON、KMZ)、时间动态数据格式(如CZML),以及其他各种数据格式。此外,Cesium还通过插件支持其他特

    2024年02月01日
    浏览(42)
  • cesium加载glb格式的3d模型

    官方示例: Cesium Sandcastle https://sandcastle.cesium.com/?src=3D%20Models.htmllabel=Tutorials glb模型下载:https://sandcastle.cesium.com/SampleData/models/CesiumAir/Cesium_Air.glb   

    2024年02月11日
    浏览(35)
  • 前端VUE框架通过Cesium加载3dtiles,计算3dtiles的面积

    前端VUE框架通过Cesium加载3dtiles,计算3dtiles的面积完整代码 前端开发中,使用Vue框架可以帮助开发者更高效地开发复杂的Web应用程序,并且越来越多的项目开始集成三维地球数据可视化。Cesium是一个开源的JavaScript库,可以轻松地实现地球数据的可视化,同时支持3D场景的绘制

    2024年02月08日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包