OpenGL 将屏幕上的二维坐标转换为三维空间中的一个点

news2025/3/19 17:50:16

本文主要介绍将屏幕上的二维坐标转换为三维空间中的一个点,该点位于 近 平面上(即 Z 坐标为 -1)。

一、步骤概述

  1. 屏幕坐标到标准化设备坐标 (NDC): 将屏幕坐标 (x, y) 转换为 NDC 坐标系。
  2. NDC 到相机空间: 使用逆投影矩阵将 NDC 坐标转换到相机空间。
  3. 相机空间到世界空间: 使用逆视图矩阵将相机空间坐标转换到世界空间。

二、详细步骤

1. 屏幕坐标到标准化设备坐标 (NDC)

首先,假设 screenX, screenY 是屏幕空间中的像素坐标,screenW, screenH 是屏幕的宽度和高度。我们可以将屏幕坐标转换为标准化设备坐标:

float ndc_x = (2.0f * screenX) / screenW - 1.0f;  // 将x坐标映射到 [-1, 1]
float ndc_y = 1.0f - (2.0f * screenY) / screenH;  // 将y坐标映射到 [-1, 1],y轴翻转
  • screenXscreenY: 屏幕空间坐标
  • screenWscreenH: 屏幕的宽度和高度
  • ndc_xndc_y: 转换后的 NDC 坐标,范围为 [-1, 1]

2. 从 NDC 到相机空间

假设 z 值为 -1,即该点在近平面上的位置。我们需要通过逆投影矩阵将 NDC 坐标转换到相机空间。

逆投影矩阵是投影矩阵的反向操作。如果我们有一个标准的投影矩阵 P,你可以用它的逆矩阵 P^-1 来将 NDC 坐标恢复到相机空间。假设 z 值为 -1,NDC 坐标为 (ndc_x, ndc_y),那么可以通过以下方式得到相机空间中的坐标:

// 2. Crop spatial coordinates
glm::vec4 clip_coords(ndc_x, ndc_y, -1.0f, 1.0f);// z = -1 => near-plane
// 3. View space coordinates
glm::mat4 P_inv = glm::inverse(projectionMatrix);// to turn clip-space to view-space
glm::vec4 view_coords = P_inv * clip_coords;

得到的 view_coords 是相机空间中的坐标,通常需要进行透视除法,即将 x, y, z 坐标通过 w 分量进行归一化:

view_coords /= view_coords.w;// convert to non-homogeneous coordinates, get real view-space coordinates

3. 从相机空间到世界空间

最后,使用逆视图矩阵将相机空间坐标转换为世界空间坐标。V_inv 是视图矩阵的逆矩阵,转换公式如下:

	glm::mat4 V_inv = glm::inverse(viewMatrix);// to turn view-space to world-space
	glm::vec3 world_coords = glm::vec3(V_inv * view_coords);

最终代码实现如下:

glm::vec3 mapTo3DXZPlane(int screenX, int screenY, int screenW, int screenH, const glm::mat4& viewMatrix, const glm::mat4& projectionMatrix) {
	// 1. Normalized Device Coordinates (NDC:[-1,1], bottom-left=(-1,-1), top-right=(1,1))
	float ndc_x = (2.0f * screenX) / screenW - 1.0f;// Screen[0,screenW] map to NDC[-1,1]
	float ndc_y = 1.0f - (2.0f * screenY) / screenH;// Screen[0,screenH] map to NDC[1,-1] (openGL Y is up, screen Y is down)
	// 2. Crop spatial coordinates
	glm::vec4 clip_coords(ndc_x, ndc_y, -1.0f, 1.0f);// z = -1 => near-plane
	// 3. View space coordinates
	glm::mat4 P_inv = glm::inverse(projectionMatrix);// to turn clip-space to view-space
	glm::vec4 view_coords = P_inv * clip_coords;
	view_coords /= view_coords.w;// convert to non-homogeneous coordinates, get real view-space coordinates
	// 4. World spatial coordinates
	glm::mat4 V_inv = glm::inverse(viewMatrix);// to turn view-space to world-space
	glm::vec3 world_coords = glm::vec3(V_inv * view_coords);
	
	return world_coords;
}

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

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

相关文章

GreenKGC: A Lightweight Knowledge Graph Completion Method(论文笔记)

CCF等级:A 发布时间:2023年7月 代码位置 25年3月17日交 目录 一、简介 二、原理 1.整体 2.表示学习 3.特征修剪 4.决策学习 三、实验性能 1.主要结果 2.消融实验 四、结论和未来工作 一、简介 传统知识图谱补全方法中,嵌入维度…

SSM基础专项复习5——Maven私服搭建(2)

系列文章 1、SSM基础专项复习1——SSM项目整合-CSDN博客 2、SSM基础专项复习2——Spring 框架(1)-CSDN博客 3、SSM基础专项复习3——Spring框架(2)-CSDN博客 4、SSM基础专项复习4——Maven项目管理工具(1&#xff…

ASP4644四通道降压稳压器的工业高效电源管理方案

ASP4644工业级型号(ASP4644I6B)是一款专为工业场景设计的四通道降压稳压器,支持-40C至85C工作温度。其核心特性包括: 宽输入电压范围:4V–14V,适配工业现场多变的电源环境。 高负载能力:单通道…

RabbitMq C++客户端的使用

1.RabbitMq介绍 RabbitMQ 是一款开源的消息队列中间件,基于 AMQP(高级消息队列协议)实现,支持多种编程语言和平台。以下是其核心特点和介绍: 核心特点 多语言支持 提供 Java、Python、C#、Go、JavaScript 等语言的客…

用通义大模型写爬虫程序,汇总各科成绩

需求:根据各科网址,输入学号、姓名查询成绩。 中间反反复复很多次,本文只记下重点的几次和大模型的沟通历史。 输入界面 查询界面 round0(最初的问题) 请在windows下,使用python的selenium库&#xff0…

电商项目Ts版本

文章目录 项目地址一、环境安装1.1 配置作为导入1.2 文件目录 二、路由2.1 publicRoutes 项目地址 教程作者:教程地址: 代码仓库地址: 所用到的框架和插件: dbt airflow一、环境安装 1.1 配置作为导入 vite.config.ts impor…

HarmonyOS Next中的弹出框使用

HarmonyOS Next弹出框概述及分类 弹出框是一种模态窗口,通常用于在保持当前上下文环境的同时,临时展示用户需关注的信息或待处理的操作。用户需在模态弹出框内完成相关交互任务之后,才能退出模态模式。弹出框可以不与任何组件绑定&#xff0…

FPGA中级项目4——DDS实现

FPGA中级项目4——DDS实现 DDS简介 DDS(直接数字频率合成器,Direct Digital Frequency Synthesis)是一种基于数字信号处理技术的频率合成方法,广泛应用于通信、雷达、仪器仪表等领域。在 FPGA中实现 DDS 具有灵活性高、集成度强、…

STM32 DAC详解:从原理到实战输出正弦波

目录 一、DAC基础原理1.1 DAC的作用与特性1.2 DAC功能框图解析 二、DAC配置步骤2.1 硬件配置2.2 初始化结构体详解 三、DAC数据输出与波形生成3.1 数据格式与电压计算3.2 正弦波生成实战3.2.1 生成正弦波数组3.2.2 配置DMA传输3.2.3 定时器触发配置 四、常见问题与优化建议4.1 …

基于PyQt5与Open3D的轻量化BIM工具开发指南(下)‌

‌基于PyQt5与Open3D的轻量化BIM工具开发指南(下)‌ ‌——参数化建模、数据导出与性能优化‌ 【跳转】基于PyQt5与Open3D的轻量化BIM工具开发指南(上)‌ ‌四、详细实现步骤(Part 2)‌ ‌3. 参数化建模…

Pytest项目_day01(HTTP接口)

HTTP HTTP是一个协议(服务器传输超文本到浏览器的传送协议),是基于TCP/IP通信协议来传输数据(HTML文件,图片文件,查询结果等)。 访问域名 例如www.baidu.com就是百度的域名,我们想…

在vue项目中,使用Patch请求,实现根据id修改某张发票的日结状态

目录 前言 一.问题描述 二.后端实现 1.分析 2.检查后端拦截器,看看是否允许接收Patch类型的请求 3.编写Dto 4.编写controller层 5.编写service层 6.mapper层 7.使用apifox,测试后端接口的可用性 三.前端实现 1.封装api(本质是ax…

某快餐店用户市场数据挖掘与可视化

1、必要库的载入 import pandas as pd import matplotlib.pyplot as plt import seaborn as sns2、加载并清洗数据 # 2.1 加载数据 df pd.read_csv(/home/mw/input/survey6263/mcdonalds.csv)# 2.2 数据清洗 # 2.2.1 检查缺失值 print(缺失值情况:) print(df.isn…

[C++面试] 标准容器面试点

一、入门 1、vector和list的区别 [C面试] vector 面试点总结 vector 是动态数组,它将元素存储在连续的内存空间中。支持随机访问,即可以通过下标快速访问任意位置的元素,时间复杂度为 O(1),准确点是均摊O(1)。但在中间或开头插…

单片机学完开发板,如何继续提升自己的技能?

很多人学完开发板后都会卡在一个尴尬的阶段:觉得自己会的东西不少,但又不知道下一步该干啥。会点C语言,能烧录程序,能点亮LED,玩转按键,搞定串口等等,能用开发板做点小玩意儿,但面对…

明基PD2700U显示器无法调节图像模式

现象:明基PD2700U显示器无法调节图像模式,如下图: 目前未找到根本原因,推测可能是下面的原因: 1、安装了远程桌面软件:向日葵、虚拟显示器 2、显卡插入了接口,但是没接显示器 解决办法&#xf…

基于FPGA轨道交通6U机箱CPCI脉冲板板卡

板卡简介: 本板为脉冲板,脉冲板主要执行CPU下达的指令,通过实现各种控制算法来调节PWM,然后输出光纤PWM信号来驱动变频器功率模块以达到控制电机的目的。 性能规格: 电源:DC5V;15V FPGA&…

如何通过 Airbyte 将数据摄取到 Elasticsearch

作者:来自 Elastic Andre Luiz Airbyte 是一个数据集成工具,可自动化并可扩展地将信息从各种来源传输到不同的目的地。它使你能够从 API、数据库和其他系统提取数据,并将其加载到 Elasticsearch 等平台,以实现高级搜索和高效分析。…

如何用DeepSeek进行项目管理?AI重构项目全生命周期的实践指南

一、项目管理的核心工作范畴 现代项目管理包含六大核心模块,构成完整管理闭环: 1. 需求管理(20%工作量) 案例:某电商平台"双11"大促项目需整合23个部门的142项需求 关键动作:需求收集→优先级…

vue3 引入element-plus组件后,发现输入的时候没有提示,而且鼠标移到el-button显示unknown的简单解决方法

1、element-plus官方地址 一个 Vue 3 UI 框架 | Element Plus 2、安装 安装 | Element Plus 3、安装插件unplugin-vue-components、unplugin-auto-import并配制 快速开始 | Element Plus 4、输入关键词没有提示及ElButton:unknown的处理 1)装个扩展插件&#xf…