Cesium 模型开挖

和模型压平类似,此处开挖也是采用修改了模型的顶点,通过判断定的位置来判断改顶点是否加载。
缺点:会有毛边。
后续我会再上个修改源码无毛边的版本。

// 三维模型裁剪
class TilesetCut {constructor(tileset, opt) {if (!tileset) {console.log("缺少模型");return;}this.tileset = tileset;this.opt = opt || {};/*** @property {Boolean} iscutOutter 是否为外部裁剪,默认为内部裁剪*/this._iscutOutter = this.opt.iscutOutter; // 是否为外部裁剪  默认为内部裁剪this.cutRegions = []; // 当前裁剪面数组对象/* this.modelMatrix = new Cesium.Matrix4(); // 世界坐标系--》模型坐标系Cesium.Matrix4.inverseTransformation(this.tileset.root.computedTransform, this.modelMatrix) */// 建立模型中心点坐标系const center = this.tileset.boundingSphere.center;const enuMtx4 = Cesium.Transforms.eastNorthUpToFixedFrame(center);this.modelMatrix = Cesium.Matrix4.inverse(enuMtx4, new Cesium.Matrix4());this.canvas = undefined;}get iscutOutter() {return this._iscutOutter}set iscutOutter(val) {this._iscutOutter = val;this.updateShader();}/*** 添加裁剪面* @param {Object} attr 参数* @param {Cesium.Cartesian3[]} attr.positions 压平面坐标* @param {Number} attr.id 唯一标识*/addRegion(attr) {let { positions, id } = attr || {};if (!id) id = (new Date()).getTime() + "" + Number(Math.random() * 1000).toFixed(0);if (!positions || positions.length < 3) {console.log("缺少裁剪面坐标");return;}const index = this.cutRegions.findIndex(item => item.id === id)if (index == -1) {this.cutRegions.push({id: id,positions: positions})} else {this.cutRegions[index].positions = positions;}this.updateShader()}/*** 移除裁剪面* @param {String} id */removeRegionById(id) {if (id) { // 表示移除所有的裁剪面const index = this.cutRegions.findIndex(item => item.id === id)if (index != -1) this.cutRegions.splice(index, 1)} else { // 表示移除单个的裁剪面this.cutRegions = [];}this.updateShader();}/*** 销毁*/destroy() {this.tileset.customShader = undefined;}/*** 修改模型着色器*/updateShader() {debugger// 定义着色器中裁剪函数const fs_textureMapRect = `vec4 textureMapRect(vec4 rect, sampler2D map, vec2 xy) {// 判断当前图元坐标和多边形关系 如果在多边形内 进行纹素拾取if (xy.x >= rect.x && xy.x <= rect.z && xy.y >= rect.y && xy.y <= rect.w) {float w = rect.z - rect.x;float h = rect.w - rect.y;float s = (xy.x - rect.x) / w;float t = (xy.y - rect.y) / h;vec4 color = texture(map, vec2(s, 1.0 - t));return color;}return vec4(1.0);}`;let allUniforms = {u_inverseModel: {type: Cesium.UniformType.MAT4,value: this.modelMatrix.clone()},u_unionCutRegions: {type: Cesium.UniformType.BOOL,value: this._iscutOutter}}// 构建多区域着色器let fs = ``;this.cutRegions.forEach(element => {const uniforms = this.createUniforms(element.positions, element.id)allUniforms = Cesium.combine(allUniforms, uniforms)fs += `vec4 color_${element.id} = textureMapRect(u_rect_${element.id}, u_map_${element.id}, xy);cutColor *= color_${element.id};`})fs += `if (u_unionCutRegions) {material.diffuse *= (vec3(1.0) - cutColor.rgb);} else {material.diffuse *= cutColor.rgb;}if (material.diffuse.r <= 0.0001 && material.diffuse.g <= 0.0001 && material.diffuse.b <= 0.0001) {discard;}`;this.tileset.customShader = new Cesium.CustomShader({uniforms: allUniforms,fragmentShaderText: ` ${fs_textureMapRect}void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {vec4 positionMC = u_inverseModel * vec4(fsInput.attributes.positionWC, 1.0);vec2 xy = positionMC.xy;vec4 cutColor = vec4(1.0);${fs}}`})}/*** 根据坐标创建片元着色器* @param {Cartesian3[]} positions * @param {String} id */createUniforms(positions, id) {if (!positions || positions.length < 3) {console.log("缺少裁剪面坐标");return;}id = id || Math.ceil(Math.random() * 100000) + '_' + Math.ceil(Math.random() * 100000)// 根据世界坐标范围计算相对模型坐标范围const xs = [], ys = [], zs = []// 计算模型坐标系下坐标const modelPoints = positions.map(p => {const point = Cesium.Matrix4.multiplyByPoint(this.modelMatrix, p, new Cesium.Cartesian3());xs.push(point.x)ys.push(point.y)zs.push(point.z)return point})// 计算当前裁剪面边界范围(模型坐标系下)const rect = new Cesium.Cartesian4(Math.min.apply(null, xs), Math.min.apply(null, ys), Math.max.apply(null, xs), Math.max.apply(null, ys))const canvas = document.createElement('canvas')canvas.width = 1024canvas.height = 1024const width = rect.z - rect.xconst height = rect.w - rect.yconst ctx = canvas.getContext('2d')ctx.fillStyle = '#fff' // 设置整体背景为白色ctx.fillRect(0, 0, canvas.width, canvas.height)ctx.beginPath()ctx.moveTo(canvas.width * (modelPoints[0].x - rect.x) / width, canvas.height * (modelPoints[0].y - rect.y) / height)for (let i = 1; i < modelPoints.length; i++) {ctx.lineTo(canvas.width * (modelPoints[i].x - rect.x) / width, canvas.height * (modelPoints[i].y - rect.y) / height)}ctx.closePath()ctx.fillStyle = '#000' // 根据填充的黑色来裁剪模型ctx.fill()this.canvas = canvas;const uniforms = {}uniforms[`u_rect_${id}`] = {type: Cesium.UniformType.VEC4,value: rect}uniforms[`u_map_${id}`] = {type: Cesium.UniformType.SAMPLER_2D,value: new Cesium.TextureUniform({url: canvas.toDataURL()}),minificationFilter: Cesium.TextureMinificationFilter.LINEAR,magnificationFilter: Cesium.TextureMagnificationFilter.LINEAR}return uniforms}}export default TilesetCut

调用方式:
 

let cutTool = new Cut(tileset);cutTool.addRegion({positions : positions,id : new Date().getTime()});

仓库地址:https://gitee.com/caozl1132/CesiumExp-tilesetFlat

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

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

相关文章

人工智能推动供应链革命的成功

人工智能推动供应链革命的成功 目录 人工智能推动供应链革命的成功一、供应链管理不断变化的面貌二、拥挤的解决方案景观三、踏上人工智能驱动的转型1. 价值创造识别、战略和路线图2. 目标解决方案设计和供应商选择3. 实施与系统集成4. 变革管理、能力建设和全面价值获取 新技术…

缺陷检测设备可以用于检测各种类型的缺陷,包括裂纹、气泡、疏松、异物、变形等

缺陷检测设备是用于检测产品或材料缺陷的工具。这些设备可以用于检测各种类型的缺陷&#xff0c;包括裂纹、气泡、疏松、异物、变形等。常见的缺陷检测设备包括X射线检测设备、超声波检测设备、磁粉检测设备、红外检测设备等。这些设备可以帮助生产厂家在生产过程中及时发现并修…

NPN PNP SS8050 SS8550 S8050

SS8050的使用及引脚判断方法 今天讲的是NPN型三极管SS8050&#xff0c;主要分为以下几个方面&#xff1a; 一、前言 二、SS8050简介 三、NPN三极管与PNP三极管 四、三极管管脚识别方法 五、不拆卸三极管判断其好坏 六、S8050和SS8050的区别 七、三极管与MOS管的区别 八…

力扣题解24. 两两交换链表中的节点(图解递归和双指针)

24. 两两交换链表中的节点 题目描述&#xff1a; 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&…

解决python画图无法显示中文的问题

python画图遇到的问题&#xff1a; 中文不显示&#xff1a; 解决方法&#xff1a;把字体设置为支持中文的字体&#xff0c;比如黑体 黑体下载链接&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1BD7zQEBUfcIs6mC2CPYy6A?pwdv120 提取码&#xff1a;v120 pyhon…

CSS 选择器全攻略:从入门到精通(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

Python的运算符与表达式

目录 运算符与表达式运算符算数运算符赋值运算符关系运算符逻辑运算符位运算符 运算符与表达式 运算符 算数运算符 赋值运算符 关系运算符 逻辑运算符 位运算符

力扣热题 100

文章目录 哈希双指针滑动窗口子串普通数组矩阵链表二叉树图论回溯二分查找栈堆贪心算法动态规划多维动态规划技巧 哈希 双指针 移动零 class Solution {public void moveZeroes(int[] nums) {int k 0;for(int i 0;i < nums.length; i){if(nums[i] ! 0) {nums[k] nums[…

揭秘关键指标稳定币供应比率(SSR):它如何影响你的投资?

作者&#xff1a;lesleyfootprint.network 数据源&#xff1a;The Stablecoin Dashboard 在加密世界里&#xff0c;稳定币扮演着重要的角色&#xff0c;为投资者提供了一个相对稳定的避风港。 稳定币旨在保持相对稳定的价值&#xff0c;这通常通过将它们与商品、法定货币挂钩…

(leetcode)替换所有的问号 -- 模拟算法

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 本题链接 力扣&#xff08;LeetCode&#xff09; 输入描述 string modifyString(string s) 输入一个字符串&#xff0c;字符串中仅包含小写字母和 ‘?’ 字符。 输出描述 将问号替换为小写字母&#xff0c;且这个替…

全链路压力测试有哪些主要作用

全链路压力测试是在软件开发和维护过程中不可或缺的一环&#xff0c;尤其在复杂系统和高并发场景下显得尤为重要。下面将详细介绍全链路压力测试的主要作用。 一、全链路压力测试概述 全链路压力测试是指对软件系统的全部组件(包括前端、后端、数据库、网络、中间件等)在高负载…

机器学习激活函数

激活函数 激活函数是人工神经网络中的一个重要组成部分。它们用于向神经网络中添加非线性因素&#xff0c;使得网络能够解决复杂问题&#xff0c;如图像识别、语言处理等。激活函数的作用是决定一个神经元是否应该被激活&#xff0c;也就是说&#xff0c;它帮助决定神经元的输…