Cesium 模型压平

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

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

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

/*** @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模型压平
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/628531.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

推荐给前端程序员的5款浏览器插件

所谓“工欲善其事&#xff0c;必先利其器”。Chrome&#xff08;谷歌浏览器&#xff09; 应该是程序员或者互联网行业人员使用最多的浏览器了。而在日常开发中&#xff0c;下面几款 浏览器 扩展也许能让你的开发工作事半功倍 。 1、Vimium vimium 是一个旨在将你的双手从鼠标…

C++核心编程(包含:内存、函数、引用、类与对象、文件操作等)【持续更新】

&#x1f308;个人主页&#xff1a;godspeed_lucip &#x1f525; 系列专栏&#xff1a;C从基础到进阶 C核心编程&#x1f30f;1 内存分区模型&#x1f384;1.1 程序运行前&#x1f384;1.2 程序运行后&#x1f384;1.3 new操作符 &#x1f30f;2 引用&#x1f384;2.1 引用的基…

【Golang开源项目】Golang高性能内存缓存库BigCache设计与分析

项目地址 BigCache 是一个快速&#xff0c;支持并发访问&#xff0c;自淘汰的内存型缓存&#xff0c;可以在存储大量元素时依然保持高性能。BigCache将元素保存在堆上却避免了GC的开销。 背景介绍 BigCache的作者在项目里遇到了如下的需求&#xff1a; 支持http协议支持 10…

Linux shell编程学习笔记39:df命令

0 前言1 df命令的功能、格式和选项说明 1.1 df命令的功能1.2 df命令的格式1.3 df命令选项说明 2 df命令使用实例 2.1 df&#xff1a;显示主要文件系统信息2.2 df -a&#xff1a;显示所有文件系统信息2.3 df -t[]TYPE或--type[]TYPE&#xff1a;显示TYPE指定类型的文件系统信…

解决英特尔无线网卡WiFi或者蓝牙突然消失问题

winR&#xff0c;输入“devmgmt.msc”&#xff0c;检查设备管理器中的无线网卡驱动是否安装好。 访问https://www.intel.cn/content/www/cn/zh/download/19351/windows-10-and-windows-11-wi-fi-drivers-for-intel-wireless-adapters.html下载对应系统版本的英特尔无线网卡WiFi…

遇到问题不要慌,轻松搞定内存泄露

当一个系统在发生 OOM 的时候&#xff0c;行为可能会让你感到非常困惑。因为 JVM 是运行在操作系统之上的&#xff0c;操作系统的一些限制&#xff0c;会严重影响 JVM 的行为。故障排查是一个综合性的技术问题&#xff0c;在日常工作中要增加自己的知识广度。多总结、多思考、多…

基于PyQT的图片批处理系统

项目背景&#xff1a; 随着数字摄影技术的普及&#xff0c;人们拍摄和处理大量图片的需求也越来越高。为了提高效率&#xff0c;开发一个基于 PyQt 的图片批处理系统是很有意义的。该系统可以提供一系列图像增强、滤波、水印、翻转、放大缩小、旋转等功能&#xff0c;使用户能够…

SpringBoot:详解依赖注入和使用配置文件

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java项目分享》 《RabbitMQ》《Spring》《SpringMVC》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 前言一、&#x1f3…

力扣精选算法100题——等于目标值的两个数or三数之和(双指针专题)

目录 &#x1f6a9;等于目标值的俩个数 第一步&#xff1a;了解题意 第二步&#xff1a;算法原理 第三步&#xff1a;代码实现 &#x1f6a9;三数之和 第一步&#xff1a;了解题意 第二步&#xff1a;算法原理 思路&#xff1a; ❗不漏&#xff1a; ❗去重: &#xf…

Simulink旧版本如何打开新版的模型文件

Simulink旧版本如何打开新版的模型文件 当用旧版本Simulink软件打开模型时会报错&#xff0c;是因为版本不兼容造成的 解决办法 在simulink的选项中去掉 do not load models created with newer version of Simulink

计算机视觉的应用

计算机视觉&#xff08;Computer Vision&#xff09;是一门研究如何让计算机能够理解和分析数字图像或视频的学科。简单来说&#xff0c;计算机视觉的目标是让计算机能够像人类一样对视觉信息进行处理和理解。为实现这个目标&#xff0c;计算机视觉结合了图像处理、机器学习、模…

分享用 vector的vector实现一个二维数组并初始化的逆置矩阵问题

题目名称 867.转置矩阵 目录 题目名称 867.转置矩阵 1.题目 2.题目分析 3.题目知识点 3.1vector的构造函数 3.2vector构造二维数组 最后&#x1f490; 推荐阅读顺序: 1.题目->2.题目分析->3.题目知识点 1.题目 如果矩阵 matrix为 m 行 n列&#xff0c;则转置后的矩…

【Python学习】Python学习15-模块

目录 【Python学习】Python学习15-模块 前言创建语法引入模块from…import 语句from…import* 语句搜索路径PYTHONPATH 变量-*- coding: UTF-8 -*-导入模块现在可以调用模块里包含的函数了PYTHONPATH 变量命名空间和作用域dir()函数globals() 和 locals() 函数reload() 函数Py…

Python中如何简化if...else...语句

一、引言 我们通常在Python中采用if...else..语句对结果进行判断&#xff0c;根据条件来返回不同的结果&#xff0c;如下面的例子。这段代码是一个简单的Python代码片段&#xff0c;让用户输入姓名并将其赋值给变量user_input。我们能不能把这几行代码进行简化&#xff0c;优化…

RocketMQ源码阅读-Message拉取与消费-Consumer篇

RocketMQ源码阅读-Message拉取与消费-Consumer篇 1. Consumer2. PushConsumer3. PushConsumer 订阅3.1 subscribe订阅3.2 registerMessageListener注册监听器 4. PushConsumer 消息队列Rebalance4.1 Rebalance流程4.2 Rebalance策略AllocateMessageQueueAveragelyAllocateMessa…

CSS 动态邮件查收效果

<template><view class="content"><view class="tooltip-container"><text class="tooltip">查看</text><text class="text">@</text></view></view> </template><sc…

Visual Studio调试模式下无法使用右键菜单将ppt转换到pdf

Visual Studio调试模式下无法使用右键菜单将ppt转换到pdf 症状 Visual Studio调试模式下&#xff0c;程序停在断点时&#xff0c;我临时需要将ppt转为pdf&#xff0c;遂右键单击文件&#xff0c;想直接转pdf&#xff0c;奈何光标转了几秒钟&#xff0c;毫无反应。 解决方法 …

未来科技五年人工智能行业产业发展趋势最新竞争力

人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;是近年来快速发展的热门领域&#xff0c;被广泛应用于各个行业。随着技术的不断创新和突破&#xff0c;人工智能行业的竞争力也在不断提升。本文将分析未来科技五年人工智能行业产业发展趋势&#xff0c…

力扣精选算法100题——水果成篮(滑动窗口专题)

本题链接&#x1f449;水果成篮 第一步&#xff1a;了解题意 我就按照实例1来进行对这题的理解。 1代表种类类型&#xff0c;这个数组里面有2个种类类型 ps:种类1和种类2 &#xff0c;只不过种类1是有2个水果&#xff0c;种类2有一个水果&#xff0c;共计3个水果。 本题需要解…

如何区分GPT-3.5模型与GPT-4模型?

GPT 3.5 和 GPT-4 有什么区别&#xff1f; GPT-3.5 在经过大量数据训练后&#xff0c;成功地发展到可以考虑 1750 亿个参数以响应提示。这使其具备令人印象深刻的语言技能&#xff0c;以非常人性化的方式回应各种查询。然而&#xff0c;GPT-4 在更为庞大的训练数据基础上进行了…