【three.js】世界坐标系和设备坐标系

2023-10-29

简述

物体的坐标转换过程大致为:局部坐标 -> 世界坐标 -> 观察空间坐标 -> 裁剪空间坐标 -> 屏幕空间坐标

我们将 观察空间坐标系 和 裁剪空间坐标系 之间的转换统一处理,最终得到 标准设备坐标系

因此坐标转换过程就变成了:局部坐标 -> 世界坐标 -> 标准设备坐标 -> 屏幕空间坐标

屏幕坐标转世界坐标

ThreeJS 是使用了 canvas 画布绘制图形的,因此屏幕坐标系就是 canvas 中的坐标系,也就是左上角是坐标原点:

在 ThreeJS 中,一个物体可看作一个 Mesh,Mesh 的坐标是用一个 Vector3 来表示的,Vector3 中包含了 x、y、z 坐标。

空间坐标系是三维的,其原点默认在屏幕中心,且 x y z 的范围是 [-1,1],因此其 x、y 轴在屏幕坐标系中的表示就是
  
在这里插入图片描述
通过Vector3对象的方法project,方法的参数是相机对象,语句worldVector.project(camera);返回的结果是世界坐标worldVector在camera相机对象矩阵变化下对应的标准设备坐标, 标准设备坐标xyz的范围是[-1,1]。

ThreeJS 中,画布一般是全屏的,因此画布的宽高 w,h 就是:window.innerWidth 和 window.innerHeight,所以 Three 的空间坐标系中点 (cx, cy)在屏幕坐标系中就是:(w / 2,h / 2)。

假设 canvas 中有一点 (x,y),这个点在空间坐标系中为 (x1,y1),那么这个转换公式是:

x1=(x/w)∗2−1

y1=−(y/h)∗2+1

公式推导过程如下:

在这里插入图片描述

世界坐标转屏幕坐标

屏幕坐标转空间坐标需要经过两个步骤:屏幕坐标 -> 标准设备坐标 -> 世界坐标。
 通过 Vector3对象的方法 project(camera),返回的结果是世界坐标 worldVector在 camera相机对象矩阵变化下对应的标准设备坐标, 标准设备坐标 xyz 的范围是[-1,1]。

同样的,假设画布宽为 w ,高为 h,屏幕坐标系中的一点为 (x, y),标准设备坐标系中对应的点为 (x1, y1)

从标准设备坐标系转换到屏幕坐标系与我们前面计算出的公式相反:
在这里插入图片描述

首先计算出屏幕坐标系中心:

const centerX = window.innerWidth / 2;
const centerY = window.innerHeight / 2;

计算出的 centerX 和 centerY 同时也表示了坐标轴的一半大小。

然后,将设备坐标系使用 project 方法转换到标准设备坐标系,再转换到屏幕坐标系中:

const standardVec = worldVector.project(camera);

const screenX = Math.round(centerX * standardVec.x + centerX);
const screenY = Math.round(-centerY * standardVec.y + centerY);

在这里插入图片描述

第三方 CSS2DRenderer

 /**
    * 创建div元素(作为立方体标签)
    */
    var div = document.createElement('div');
    div.innerHTML = '立方体';
    div.style.padding = '5px 10px';
    div.style.color = '#fff';
    div.style.fontSize = '16px';
    div.style.position = 'absolute';
    div.style.backgroundColor = 'rgba(25,25,25,0.5)';
    div.style.borderRadius = '5px'
    // document.body.appendChild(div);

    // 获得HTML元素创建的UI界面
    var tag = document.getElementById('tag');

    //div元素包装为CSS2模型对象CSS2DObject,并插入场景中
    var label = new CSS2DObject(div);
    label.position.copy(boxMesh.position);
    // label.position.y += 30
    scene.add(label); //CSS2模型标签插入到场景中

    // 创建一个CSS2渲染器CSS2DRenderer
    var labelRenderer = new CSS2DRenderer();
    labelRenderer.setSize(window.innerWidth, window.innerHeight);
    labelRenderer.domElement.style.position = 'absolute';
    // 避免renderer.domElement影响HTMl标签定位,设置top为0px
    labelRenderer.domElement.style.top = '0px';
    labelRenderer.domElement.style.left = '0px';
    //设置.pointerEvents=none,以免模型标签HTML元素遮挡鼠标选择场景模型
    labelRenderer.domElement.style.pointerEvents = 'none';
    document.body.appendChild(labelRenderer.domElement);

第三方 CSS3DRenderer

 /**
    * 创建div元素(作为立方体标签)
    */
    var div = document.createElement('div');
    div.innerHTML = '立方体';
    div.style.padding = '5px 10px';
    div.style.color = '#fff';
    div.style.fontSize = '16px';
    div.style.position = 'absolute';
    div.style.backgroundColor = 'rgba(25,25,25,0.5)';
    div.style.borderRadius = '5px'
    // document.body.appendChild(div);

    // 获得HTML元素创建的UI界面
    // var tag = document.getElementById('tag');

    //div元素包装为CSS3模型对象CSS3DObject,并插入场景中
    var label = new CSS3DObject(div);
    div.style.pointerEvents = 'none';//避免HTML标签遮挡三维场景的鼠标事件
    label.position.copy(boxMesh.position);
    //缩放CSS3DObject模型对象
    label.scale.set(0.5,0.5,0.5)
    label.position.y += 20
    scene.add(label); //CSS3模型标签插入到场景中

    // 创建一个CSS3渲染器CSS3DRenderer
    var labelRenderer = new CSS3DRenderer();
    labelRenderer.setSize(window.innerWidth, window.innerHeight);
    labelRenderer.domElement.style.position = 'absolute';
    // 避免renderer.domElement影响HTMl标签定位,设置top为0px
    labelRenderer.domElement.style.top = '0px';
    labelRenderer.domElement.style.left = '0px';
    //设置.pointerEvents=none,以免模型标签HTML元素遮挡鼠标选择场景模型
    labelRenderer.domElement.style.pointerEvents = 'none';
    document.body.appendChild(labelRenderer.domElement);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【three.js】世界坐标系和设备坐标系 的相关文章

  • 如何在同一页面上使用AJAX处理多个表单

    我有一个表单 当我单击 提交 时 它就被提交了 然后该表单隐藏 操作页面的结果显示在 div 中 classname dig 它工作正常 但是当我添加另一个表单时 它停止正常工作并且所有表单同时提交 我如何更改我的代码 done click
  • 主干视图 DOM 元素已删除

    我一直在阅读有关 Backbone js 僵尸 或内存泄漏 问题的信息 基本上 当您不再需要该元素时 您必须从 DOM 中解除绑定并删除该元素 以确保所有事件也被删除 现在 我有一个包含几个容器的单页应用程序 div div div div
  • 如何测试 javascript 闭包内的函数

    这似乎是不可能的 也可能是 但我正在尝试更多的 TDD 但我总是在闭包方面碰壁 假设我有以下内容 function createSomething init function privateMethod param return init
  • Android 设备上的 PhoneGap 蓝牙插件

    我一直在尝试让 PhoneGap 工作的蓝牙插件 但我似乎不知道哪里出了问题 首先 我的测试设备是 Galaxy S3 GT 19305T 应用程序是使用PhoneGap CLI http docs phonegap com en 3 0
  • 解析“流”JSON

    我在浏览器中有一个网格 我想通过 JSON 将数据行发送到网格 但浏览器应该在接收到 JSON 时不断解析它 并在解析时将行添加到网格中 换句话说 在接收到整个 JSON 对象后 不应将行全部添加到网格中 应该在接收到行时将其添加到网格中
  • 使用模数按字母顺序对列表进行排序

    我在获取元素列表并按字母顺序对它们进行排序方面没有任何问题 但我很难理解如何使用模数来做到这一点 更新 这是按我的方式工作的代码 但是 我更喜欢下面提供的答案的可重用性 因此接受了该答案
  • 使用 JavaScript 使链接保持活动状态并在单击时显示悬停效果

    I am struggling to make this work I d like to make it where if O F is clicked the hover state stays active if another li
  • 检查 JavaScript 字符串是否为 URL

    JavaScript 有没有办法检查字符串是否是 URL 正则表达式被排除在外 因为 URL 很可能是这样写的stackoverflow 也就是说它可能没有 com www or http 如果你想检查一个字符串是否是有效的 HTTP UR
  • 使用 Angular 下载具有动态 src 的脚本

    Angular 提供了通过动态名称动态加载模板的方法ng include 该部分中的内联 JS 和 CSS 可以正常加载 但没有一个好的方法来下载带有动态 url 的脚本 我们需要下载脚本 相对于调用它们的 html 部分的路径 即我们有一
  • 在 Wordpress 站点中进行 AJAX 调用时出现问题

    我在使用 Wordpress 站点功能的 AJAX 部分时遇到了一些问题 该功能接受在表单上输入的邮政编码 使用 PHP 函数来查找邮政编码是否引用特定位置并返回到该位置的永久链接 我的第一个问题是关于我构建的表单 现在我的表单操作是空白的
  • Node.js:如何在检索数据(块)时关闭响应/请求

    我正在用 node js 构建一个应用程序 它加载多个页面并分析内容 因为 node js 发送块 所以我可以分析这些块 如果一个块包含例如索引 nofollow 我想关闭该连接并继续其余部分 var host example com to
  • Jquery/Javascript 上传和下载文件,无需后端

    是否可以在没有后端服务器的情况下在 JavaScript 函数中下载和上传文件 我需要导出和导入由 JavaScript 函数生成的 XML 我想创建按钮 保存 xml 来保存文件 但我不知道是否可行 另一方面 我希望将 XML 文件直接上
  • MVC 在布局代码之前执行视图代码并破坏我的脚本顺序

    我正在尝试将所有 javascript 包含内容移至页面底部 我正在将 MVC 与 Razor 一起使用 我编写了一个辅助方法来注册脚本 它按注册顺序保留脚本 并排除重复的内容 Html RegisterScript scripts som
  • Babel 7 Jest Core JS“TypeError:wks不是函数”

    将我的项目升级到 Babel 7 后 通过 Jest 运行测试会抛出以下错误 测试在 Babel 6 中运行没有任何问题 但在 Babel 7 中失败并出现以下错误 TypeError wks is not a function at Ob
  • 如何使输入字段和提交按钮变灰

    我想变灰这两件事 http doorsplit heroku com 歌曲输入字段和提交按钮 直到用户输入艺术家 有没有一种简单的方法可以通过 JQuery 来做到这一点 艺术家输入字段的id是 request artist 你可以这样做
  • 提交表单并重定向页面

    我在 SO 上看到了很多与此相关的其他问题 但没有一个对我有用 我正在尝试提交POST表单 然后将用户重定向到另一个页面 但我无法同时实现这两种情况 我可以获取重定向或帖子 但不能同时获取两者 这是我现在所拥有的
  • Laravel 中只向登录用户显示按钮

    如果我以 John 身份登录 如何才能只显示 John 的红色按钮而不显示 Susan 的红色按钮 测试系统环境 Win10 Laravel5 4 Mysql5 7 19 table class table table responsive
  • 条件在反应本机生产中失败,但在开发中有效

    我创建了一个反应本机应用程序 我需要通过它进行比较 如果属实 就会执行死刑 问题是 该条件适用于 React Native 开发模式 而不适用于 React Native 生产版本 我使用 firebase 作为数据库 也使用 redux
  • Safari 支持 JavaScript window.onerror 吗?

    我有一个附加到 window onerror 的函数 window onerror function errorMsg url line window alert asdf 这在 firefox chrome 和 IE 中工作正常 但在 s
  • 使用 Ajax 请求作为源数据的 Jquery 自动完成搜索

    我想做的事 我想使用 jquery 自动完成函数创建一个输入文本字段 该函数从跨域curl 请求获取源数据 结果应该与此示例完全相同 CSS 在这里并不重要 http abload de img jquerydblf5 png http a

随机推荐

  • 【LeetCode刷题】303 区域和检索 -数组不可变 java

    题目 给定一个整数数组 nums 处理以下类型的多个查询 计算索引 left 和 right 包含 left 和 right 之间的 nums 元素的 和 其中 left lt right 实现 NumArray 类 NumArray in
  • python3 [爬虫入门实战] 查看网站有多少个网页(站点)

    前提 进行爬虫的时候需要进行站点的爬取 再选用合适的爬虫框架 所以这里不得不需要知道一下一个网站到底有多少个网页组成 一个域名网站中到底有多少个站点 查看的方法很简单 直接百度就可以了 例如需要知道豆丁网的站点有多少个 直接在百度中输入 s
  • C# 关闭进程

    using System Diagnostics string fileName example txt Process processes Process GetProcessesByName processName foreach Pr
  • (Qt)day4

    widget h ifndef WIDGET H define WIDGET H include
  • ElasticSearch简介

    文章目录 ElasticSearch简介 正向索引和倒排索引 正向索引 倒排索引 ElasticSearch和MySQL的区别 ElasticSearch简介 什么是ElasticSearch ElasticSearch 是一款非常强大的开
  • stlink仿真器报错及处理过程记录

    项目使用stlink连接stm32f101系列的芯片 因为没有仔细阅读相关资料 出一些莫名的错 搞了大半天 前言 使用正版的stlink系列仿真器 身在山寨之国 貌似不用盗版不太合适 这里的盗版指的是别人生产来卖钱的 自己根据电路图做的不算
  • 知识的融入-增强深度学习的学习 Shades of Knowledge- Infused Learning for Enhancing Deep Learning

    知识的融入 增强深度学习的学习 摘要 SHALLOW INFUSION OF KNOWLEDGE 知识的浅层注入 Word embeddings Enriched word embeddings Deep neural language m
  • ctfshow 菜狗杯wp

    果然菜狗杯是教育我们是菜狗的 我是从第二天开始做的 这里只做了一个上午 因为下午网没了 做不了 做出来的有点少 社工也做出来挺多但是感觉社工的wp感觉就没有啥必要写了 目录 misc 签到题 损坏的压缩包 web web签到 web2 c0
  • CUDA入门笔记(三)GPU编程基础——一个典型GPU程序

    参考 优达学城 https classroom udacity com courses cs344 lessons 55120467 concepts 670611900923 一 典型GPU程序构成 一个典型GPU程序有如下几个部分 CP
  • MAC如何将[搜狗输入法]设置为默认输入法

    问题描述 即使我们下载了搜狗输入法 且在mac的 系统偏好设置 里面设置了搜狗输入法 但是当我们切屏幕的时候总是一会 简体拼音 一会 搜狗输入法 解决方式 方式1 只保留搜狗一个输入法 推荐 温馨提示 现在很多第三方输入法都已经具备中英文快
  • ResNet 论文精读 & 残差块的恒等映射 & 网络结构的解析

    论文重要知识 恒等映射 两种残差块 维度匹配和残差学习 层响应标准差 Deep Residual Learning for Image Recognition 用于图像识别的深度残差学习 目录 一 摘要 二 Introduction 介绍R
  • 深入学习java源码之Math.scalb()与 Math.powerOfTwoF()

    深入学习java源码之Math scalb 与 Math powerOfTwoF final关键字 final在Java中是一个保留的关键字 可以声明成员变量 方法 类以及本地变量 一旦你将引用声明作final 你将不能改变这个引用了 编译
  • 百度面试题——天平称重问题

    问题描述 用天平 只能比较 不能称重 从一堆小球中找出其中唯一一个较轻的 使用x 次天平 最多可以从y 个小球中找出较轻的那个 求y 与x 的关系式 解题思想 该题主要考查逻辑思维能力 我在首次遇见该题时 首先想到的对半拆分 找出其中较轻的
  • CUDA矩阵乘法及优化【参加CUDA线上训练营】

    目录 矩阵乘法 CPU方式 GPU方式 GPU中矩阵相乘步骤 GPU矩阵乘法代码示例 利用shared memory优化矩阵乘法 Share Memory矩阵乘法代码示例 矩阵乘法 CPU方式 利用三个for循环进行矩阵乘法 GPU方式 G
  • 网盘系统

    作者主页 编程千纸鹤 作者简介 Java 前端 Pythone开发多年 做过高程 项目经理 架构师 主要内容 Java项目开发 毕业设计开发 面试技术整理 最新技术分享 收藏点赞不迷路 关注作者有好处 文末获得源码 项目编号 BS XX 1
  • CTFhub_SSRF靶场教程

    CTFhub SSRF 题目 1 Bypass 1 1 URL Bypass 请求的URL中必须包含http notfound ctfhub com 来尝试利用URL的一些特殊地方绕过这个限制吧 1 利用 绕过限制url https www
  • http post 方法传递参数的2种方式

    try HttpPost httpPost new HttpPost url StringEntity stringEntity new StringEntity param param参数 可以为 key1 value1 key2 val
  • 什么是人力资源360度评估法?

    1 360度评估法的定义 360度评估法 360 Feedback 又称 360度考核法 或 全方位考核法 属于人力资源中绩效考核方法之一 是指由员工自己 上司 直接部属 同仁同事甚至顾客或家人等从全方位 各个角度来评估人员的方法 而且 为
  • java注解与反射的基本使用(这一篇就够了!)

    一 注解 Annotation 1 什么是注解 相信大家对注解应该并不陌生 在现在信息飞速发展的年代 各种优秀的框架或许都离不开注解的使用 像我们在实现接口一个方法时 也会有 Override注解 注解说白了就是对程序做出解释 与我们在方法
  • 【three.js】世界坐标系和设备坐标系

    three js 坐标系转换 简述 屏幕坐标转世界坐标 世界坐标转屏幕坐标 第三方 CSS2DRenderer 第三方 CSS3DRenderer 简述 物体的坐标转换过程大致为 局部坐标 gt 世界坐标 gt 观察空间坐标 gt 裁剪空间