当前位置: 首页 > news >正文

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

http://www.lryc.cn/news/192146.html

相关文章:

  • 【LeetCode热题100】--347.前K个高频元素
  • 解决服务器80端口无法连接的办法
  • 040:mapboxGL鼠标hover更换选中feature颜色
  • 【C++心愿便利店】No.8---C++之重识类和对象
  • 【AI视野·今日NLP 自然语言处理论文速览 第五十二期】Wed, 11 Oct 2023
  • 优雅而高效的JavaScript——模板字面量
  • Python一步到位实现图像转PDF自动化处理详解
  • 基于IDEA集成环境---Nacos安装
  • 使用 puppeteer 加载 html 文件来运行 js 文件
  • Java 操作 Excel:生成数据、设置单元格样式、设置数据有效性(hutool)
  • YOLOv5算法改进(11)— 主干网络介绍(MobileNetV3、ShuffleNetV2和GhostNet)
  • ideal远程Debug部署在服务器上的服务详解
  • 基于SSM的校园音乐平台系统
  • 07_03文件系统怎么玩的
  • php实战案例记录(24)不要键名只保留值的算法
  • 【交付高质量,用户高增长】-用户增长质量保证方法论 | 京东云技术团队
  • LMI FocalSpec 3D线共焦传感器 使用笔记1
  • 四、RocketMQ发送普通消息、批量消息和延迟消息
  • idea自定义 postfix completion提高编码效率
  • 解锁学习电路设计的正确姿势!
  • 【Linux】 ps命令使用
  • 打造高效的分布式爬虫系统:利用Scrapy框架实现
  • SpringCloud组件Ribbon的IRule的问题排查
  • 比较完整一些chatGPT项目代码(权威)
  • Python - 生成二维码、条形码
  • 8+纯生信,多组机器学习+分型探讨黑色素瘤发文思路。
  • GPU高性能面试-写一个ReduceKernel
  • 深入探索STARK的安全性和可靠性——STARKs全面安全分析
  • WPF 控件分辨率自适应问题
  • CANoe创建仿真工程