Three.js如何计算3DObject的2D包围框?

推荐:用 NSDT编辑器 快速搭建可编程3D场景
在Three.js应用开发中,有时你可能需要为3D场景中的网格绘制2D的包围框,应该怎么做?
朴素的想法是把网格的3D包围框投影到屏幕空间,例如,下图中的绿色框 3D包围框, 当将其投影为 2D 时,得到的红色2D包围框,显然比想要的蓝色框大很多:

正确的做法是先将3D网格投影到屏幕空间,再计算2D包围框。
1、计算单个网格的2D包围框
只需将所有顶点转换为屏幕空间并从中创建一个 2d 边界框:
function computescreenspaceboundingbox(mesh, camera) {var vertices = mesh.geometry.vertices;var vertex = new three.vector3();var min = new three.vector3(1, 1, 1);var max = new three.vector3(-1, -1, -1);for (var i = 0; i < vertices.length; i++) {var vertexworldcoord = vertex.copy(vertices[i]).applymatrix4(mesh.matrixworld);var vertexscreenspace = vertexworldcoord.project(camera);min.min(vertexscreenspace);max.max(vertexscreenspace);}return new three.box2(min, max);
}
生成的 box2 位于标准化屏幕坐标 [-1, 1] 中, 可以通过乘以渲染器高度和宽度的一半来获得像素:
function normalizedtopixels(coord, renderwidthpixels, renderheightpixels) {var halfscreen = new three.vector2(renderwidthpixels/2, renderheightpixels/2)return coord.clone().multiply(halfscreen);
}
2、计算3DObject的2D包围框
更完善的实现需要考虑组、子节点等各种3DObject,其中可能包含多个网格,这需要一个递归实现,代码如下:
function computescreenspaceboundingbox(obj, camera) {var min;var max;// is this an array of objects?if(array.isarray(obj)) {for(var i = 0; i < obj.length; ++i) {let box2 = computescreenspaceboundingbox(obj[i], camera);if(min === undefined) {min = box2.min.clone();max = box2.max.clone();} else {min.min(box2.min);max.max(box2.max);}}}// does this object have geometry?if(obj.geometry !== undefined) {var vertices = obj.geometry.vertices;if(vertices === undefined&& obj.geometry.attributes !== undefined&& 'position' in obj.geometry.attributes) {// buffered geometryvar vertex = new three.vector3(); var pos = obj.geometry.attributes.position;for(var i = 0; i < pos.count * pos.itemsize; i += pos.itemsize){vertex.set(pos.array[i], pos.array[i + 1], pos.array[1 + 2]);var vertexworldcoord = vertex.applymatrix4(obj.matrixworld);var vertexscreenspace = vertexworldcoord.project(camera);if(min === undefined) {min = vertexscreenspace.clone();max = vertexscreenspace.clone();}min.min(vertexscreenspace);max.max(vertexscreenspace);}} else {// regular geometryvar vertex = new three.vector3(); for(var i = 0; i < vertices.length; ++i) {var vertexworldcoord = vertex.copy(vertices[i]).applymatrix4(obj.matrixworld);var vertexscreenspace = vertexworldcoord.project(camera);if(min === undefined) {min = vertexscreenspace.clone();max = vertexscreenspace.clone();}min.min(vertexscreenspace);max.max(vertexscreenspace);}}}// does this object have children?if(obj.children !== undefined) {for(var i = 0; i < obj.children.length; ++i) {let box2 = computescreenspaceboundingbox(obj.children[i], camera);if(min === undefined) {min = box2.min.clone();max = box2.max.clone();} else {min.min(box2.min);max.max(box2.max);}}}return new three.box2(min, max);
}
原文链接:计算3D对象的2D包围框 — BimAnt
相关文章:
Three.js如何计算3DObject的2D包围框?
推荐:用 NSDT编辑器 快速搭建可编程3D场景 在Three.js应用开发中,有时你可能需要为3D场景中的网格绘制2D的包围框,应该怎么做? 朴素的想法是把网格的3D包围框投影到屏幕空间,例如,下图中的绿色框 3D包围框…...
【LeetCode热题100】--347.前K个高频元素
347.前K个高频元素 方法:堆 首先遍历整个数组,并使用哈希表记录每个数字出现的次数,并形成一个「出现次数数组」。找出原数组的前 k 个高频元素,就相当于找出「出现次数数组」的前 k 大的值 利用堆的思想:建立一个小…...
解决服务器80端口无法连接的办法
云服务器是现代企业建立应用程序和存储数据的理想选择。但是在使用云服务器的过程中,会遇到80端口无法连接的问题。这个问题可能会导致网站无法正常运行,从而给企业带来负面影响。因此,在这篇文章中,我们将探讨如何解决云服务器80…...
040:mapboxGL鼠标hover更换选中feature颜色
第040个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中通过鼠标hover的方式来更换选中feature颜色。这里面利用了mousemove和mouseleave的方法,通过选中图层的feature,来设置hover的true或者false,从而通过opacity的case状态来判断透明度用哪一个值。 直接复…...
【C++心愿便利店】No.8---C++之重识类和对象
文章目录 前言一、再谈构造函数二、static成员三、友元四、内部类五、匿名对象六、再次理解类和对象 前言 👧个人主页:小沈YO. 😚小编介绍:欢迎来到我的乱七八糟小星球🌝 📋专栏:C 心愿便利店 &…...
【AI视野·今日NLP 自然语言处理论文速览 第五十二期】Wed, 11 Oct 2023
AI视野今日CS.NLP 自然语言处理论文速览 Wed, 11 Oct 2023 Totally 81 papers 👉上期速览✈更多精彩请移步主页 Daily Computation and Language Papers LongLLMLingua: Accelerating and Enhancing LLMs in Long Context Scenarios via Prompt Compression Author…...
优雅而高效的JavaScript——模板字面量
🤨博主:小猫娃来啦 🤨文章核心:优雅而高效的JavaScript——模板字面量 文章目录 什么是模板字面量使用模板字面量插入变量处理多文本模板字面量的高级应用标签模板字量自定义模板字面量函数 常见应用场景拼接字符串HTML模板SQL查询…...
Python一步到位实现图像转PDF自动化处理详解
什么是 img2pdf 库? img2pdf 是一个 Python 库,它可以让你轻松地把多张图像转换为 PDF 文件。它支持多种图像格式,如 JPG, PNG, GIF, BMP 等,并且可以自动调整图像的大小和方向,以适应 PDF 的页面大小和方向。它还可以…...
基于IDEA集成环境---Nacos安装
Nacos服务器是独立安装部署的,因此我们需要下载最新的Nacos服务端程序,下载地址:https://github.com/alibaba/nacos。 将文件进行解压,得到以下内容: 直接将其拖入到项目文件夹下,便于我们一会在IDEA内部…...
使用 puppeteer 加载 html 文件来运行 js 文件
遇到一个需求, 在浏览器环境下来运行 js sdk 文件, 这个 js 文件是不能运行在 nodejs 环境下的; 所以通过 puppeteer 无头浏览器来运行代码获取对应的结果。 首先是安装插件 puppeteer,然后创建一个项目, 我这里是express; 这里是主要的代码。 const p…...
Java 操作 Excel:生成数据、设置单元格样式、设置数据有效性(hutool)
必读信息 该篇文章,主要通过 Java 代码对 Excel 文件的常用操作,包括:生成表格、修改单元格样式、设置数据有效性。 该篇文章,在官网文献下增加个人的看法和理解,如文中有出现不符、错误或需要补充的地方,…...
YOLOv5算法改进(11)— 主干网络介绍(MobileNetV3、ShuffleNetV2和GhostNet)
前言:Hello大家好,我是小哥谈。主干网络通常指的是深度学习中的主干模型,通常由多个卷积层和池化层组成,用于提取输入数据的特征。在训练过程中,主干网络的参数会被不断优化以提高模型的准确性。YOLOv5算法中的主干网络可以有多种替换方案,为了后面讲解的方便,本篇文章就…...
ideal远程Debug部署在服务器上的服务详解
ideal远程Debug部署在服务器上的服务详解 一 简介二 ideal配置步骤第一步:点击Edit Configurations选项添加远程连接第二步:配置Remote JVM debug参数第三步:服务的启动参数中添加第二步生成的命令并重新启动服务第四步:ideal启动…...
基于SSM的校园音乐平台系统
基于SSM的校园音乐平台系统~ 开发语言:Java数据库:MySQL技术:SpringSpringMVCMyBatisVue工具:IDEA/Ecilpse、Navicat、Maven 系统展示 主页 登录界面 管理员界面 歌手管理 歌曲管理 摘要 校园音乐平台系统(Campus Mu…...
07_03文件系统怎么玩的
文件系统 Linux将文件系统分为了两层:VFS(虚拟文件系统)、具体文件系统,如下图所示: VFS(Virtual Filesystem Switch)称为虚拟文件系统或虚拟文件系统转换,是一个内核软件层&#…...
php实战案例记录(24)不要键名只保留值的算法
php中对数组 $originalArray array( “name” > “John”, “age” > 25, “city” > “New York” )仅去除键名保留值的算法是什么 array_values() 函数 在 PHP 中,你可以使用 array_values() 函数来去掉数组的键名。该函数会返回一个新数组,…...
【交付高质量,用户高增长】-用户增长质量保证方法论 | 京东云技术团队
前言 俗话说,“测试是质量的守护者”,但单凭测试本身却远远不够。大多数情况下,测试像“一面镜子”,照出系统的面貌,给开发者提供修改代码的依据,这个“照镜子”的过程,就是质量评估的过程&…...
LMI FocalSpec 3D线共焦传感器 使用笔记1
一.硬件介绍 以上特别注意: 屏蔽线必须接地,因为在现场实际调试中,使用软件调试发现经常 弹窗 传感器丢失警告!! 以上 Position LED 的灯被钣金挡住,无法查看异常现象,能否将指示灯设置在软件界面上? 需要确认是软触发还是硬触发,理论上 硬触发比软触发速度要快.(我们目前使用…...
四、RocketMQ发送普通消息、批量消息和延迟消息
Producer发送普通消息的方式 1.同步发送消息 同步消息代表发送端发送消息到broker之后,等待消息发送结果后,再次发送消息 实现步骤 创建生产端,声明在哪个生产组注册NameServer地址构建Message实体,指定topic、tag、body启动…...
idea自定义 postfix completion提高编码效率
postfix completion的使用 详情见: https://www.cnblogs.com/expiator/p/17380495.html 自定义 postfix completion List、 String 初始化list: key: list表达式: List<$EXPR$> $END$List new ArrayList<>();字符串判空&…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
