使用球体模型模拟相机成像:地面与天空的可见性判断与纹理映射

在传统相机模拟中,地面通常被建模为一个平面(Plane),这在低空场景下是合理的。但在更大视场范围或远距观察时,地球的曲率不可忽视。因此,我们需要将地面模型从平面升级为球体,并基于球面与光线的几何关系判断每个像素是否看到地面或天空,并进行地面贴图映射。

本文将介绍完整的数学推导与 C++ 实现逻辑,适用于任何高度、视角和分辨率的相机建模。

一、模型定义

1.1 地球模型

我们将地球建模为一个完美球体:

  • 地球半径(单位:米):
    R=6371000

  • 地球球心坐标(世界坐标系原点):
    O=(0,0,0)

  • 地面贴图采用等距圆柱投影(Equirectangular projection)

1.2 相机定义

  • 相机位置在球心正上方,高度为H:

  • 相机方向向量(单位向量):

  • 水平方向X、垂直方向Y、视轴方向Z构成相机坐标系:

  • 相机分辨率为 (W, H),视场角为fov。

二、光线生成与交点判断

2.1 像素对应的光线生成

对于每个像素 (i, j),我们将其映射为归一化视场坐标:

  • 水平范围 [-1, 1],垂直范围 [-1, 1]

  • 假设视场角为fov,焦距为:

则该像素对应的相机坐标为:

再通过相机基向量转换为世界方向:

得到从相机发出的世界坐标系下的光线:

2.2 光线与球体求交

地球表面满足球面方程:

将光线代入球面方程,得到一元二次方程:

展开并整理为:

  • :光线未击中地球,像素显示天空

  • :光线击中地球,交点为:

(若 则交点在背后,也认为看向天空)

三、纹理映射(球坐标转二维纹理)

3.1 世界坐标 → 球坐标

交点为:

转换为球坐标(经纬度):

  • 经度(longitude):

  • 纬度(latitude):

3.2 球坐标 → 贴图坐标 (u, v)

将经纬度映射为贴图坐标(归一化到[0, 1]):

四、C++ 实现核心逻辑

cv::Vec3b tracePixelRay(int px, int py, int W, int H, double fov, const cv::Vec3d& camPos, const cv::Vec3d& X, const cv::Vec3d& Y, const cv::Vec3d& Z, const cv::Mat& texture)
{double aspect = double(W) / H;double fx = (W / 2.0) / tan(fov / 2.0);double fy = fx;double x = (px - W / 2.0) / fx;double y = (H / 2.0 - py) / fy;cv::Vec3d dir_cam = cv::normalize(cv::Vec3d(x, y, -1));cv::Vec3d dir_world = cv::normalize(X * dir_cam[0] + Y * dir_cam[1] + Z * dir_cam[2]);// 光线-球面求交double R = 6371000.0;double a = 1.0;double b = 2.0 * camPos.dot(dir_world);double c = camPos.dot(camPos) - R * R;double delta = b * b - 4 * a * c;if (delta < 0) return cv::Vec3b(0, 0, 0); // 天空double t = (-b - sqrt(delta)) / (2 * a);if (t <= 0) return cv::Vec3b(0, 0, 0); // 相机后方// 计算交点cv::Vec3d P = camPos + t * dir_world;double theta = atan2(P[1], P[0]);double phi = acos(P[2] / R);double u = (theta + CV_PI) / (2 * CV_PI);double v = phi / CV_PI;int tex_u = u * texture.cols;int tex_v = v * texture.rows;tex_u = std::clamp(tex_u, 0, texture.cols - 1);tex_v = std::clamp(tex_v, 0, texture.rows - 1);return texture.at<cv::Vec3b>(tex_v, tex_u);
}

五、主循环调用

cv::Mat render(int W, int H, double fov_rad, double height, const cv::Vec3d& D_view, const cv::Mat& texture)
{double R = 6371000.0;cv::Vec3d camPos = cv::Vec3d(0, 0, R + height);cv::Vec3d up = cv::Vec3d(0, 1, 0);cv::Vec3d Z = -cv::normalize(D_view);cv::Vec3d X = cv::normalize(up.cross(Z));cv::Vec3d Y = Z.cross(X);cv::Mat img(H, W, CV_8UC3);for (int j = 0; j < H; ++j){for (int i = 0; i < W; ++i){img.at<cv::Vec3b>(j, i) = tracePixelRay(i, j, W, H, fov_rad, camPos, X, Y, Z, texture);}}return img;
}

总结

通过将地面建模为球体并结合光线-球面交点分析,我们能够精确判断每一条视线是否击中地球,实现真实地面与天空的分界。同时,利用等距圆柱投影将地球纹理映射到图像,完成完整可视化。这种方法可广泛应用于卫星成像模拟、导引头视场渲染、地球可视仿真等场景。

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

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

相关文章

Agent自动化与代码智能

核心问题&#xff1a; 现在很多团队做AI系统有个大毛病&#xff1a;只顾追求“高大上”的新技术&#xff08;尤其是AI Agent&#xff09;&#xff0c;不管实际业务需不需要。 结果系统搞得又贵、又复杂、还容易出错。大家被“Agent”这个概念搞晕了&#xff1a;到底啥时候用简单…

SQL141 试卷完成数同比2020年的增长率及排名变化

SQL141 试卷完成数同比2020年的增长率及排名变化 withtemp as (selectexam_id,tag,date(submit_time) as submit_timefromexamination_infoleft join exam_record using (exam_id)wheresubmit_time is not null),2021_temp as (selecttag,count(*) as exam_cnt_21,rank() over…

C语言<数据结构-单链表>

链表是一种常见且重要的数据结构&#xff0c;在 C 语言中&#xff0c;它通过指针将一系列的节点连接起来&#xff0c;每个节点可以存储不同类型的数据。相比数组&#xff0c;链表在插入和删除元素时不需要移动大量数据&#xff0c;具有更好的灵活性&#xff0c;尤其适合处理动态…

archive/tar: unknown file mode ?rwxr-xr-x

这个是我在docker build报错的&#xff0c;这是一个node.js项目。我猜你也是一个node.js下的项目&#xff0c;或者前端项目。 解决方法&#xff1a; .dockerignore里面写一下node_modules就行了。 未能解决&#xff1a;archive/tar&#xff1a;未知文件模式&#xff1f;rwxr-…

【前端】ikun-markdown: 纯js实现markdown到富文本html的转换库

文章目录背景界面当前支持的 Markdown 语法不支持的Markdown 语法代码节选背景 出于兴趣,我使用js实现了一个 markdown语法 -> ast语法树 -> html富文本的库, 其速度应当慢于正则实现的同类js库, 但是语法扩展性更好, 嵌套列表处理起来更方便. 界面 基于此js实现vue组…

【echarts踩坑记录】为什么第二个Y轴最大值不整洁

目录问题复现示意图&#xff1a;解决方法有以下几种&#xff1a;1. 在y轴配置中手动设置max属性&#xff1a;2. 使用ECharts提供的坐标轴标签格式化功能&#xff1a;&#x1f680;写在最后问题复现示意图&#xff1a; 今天在用echarts图表的时候&#xff0c;出现了一个小问题。…

Duplicate cleaner pro 的使用技巧

Duplicate cleaner pro 的使用技巧前言文件去重基本介绍经验之谈目录结构修改盘符起因方法手动分配方法‌数据修改方法安装sqlite-web修改数据库GPU加速安装驱动获取驱动和硬件信息安装CUDA配置环境变量&#xff08;如果是自定义安装&#xff09;创建程序<1>获取参数和命…

数字孪生技术引领UI前端设计新趋势:增强现实与虚拟现实的融合应用

hello宝子们...我们是艾斯视觉擅长ui设计和前端数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩!一、引言&#xff1a;AR 与 VR 的 “割裂” 与数字孪生的 “融合” 契机增强现实&#xff08;AR&…

Qt使用dump文件记录并查找软件奔溃信息详细教程

Qt使用dump文件记录并查找软件奔溃信息一、dump文件概述1、dump文件的基本概念2、dump文件的常见类型3、dump文件的分析工具4、dump文件的应用场景二、具体实现步骤1、下载dbghelp库2、将库添加到自己的工程中3、main.cpp添加代码记录奔溃日志4、编写测试代码5、测试6、结果查看…

UI前端与数字孪生结合案例分享:智慧城市的智慧能源管理系统

hello宝子们...我们是艾斯视觉擅长ui设计、前端开发、数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩!一、引言&#xff1a;能源管理的 “数字孪生革命”智慧城市的能源系统正面临 “供需失衡、损耗…

Android 16系统源码_SplashScreen窗口的创建流程(一)

一 点击桌面图标触发SplashScreen 1.1 点击桌面图标打开应用 点击桌面的短信图标&#xff0c;然后打开短信页面&#xff0c;使用winscope获取数据。从点击短信图标到应用内容完全展开&#xff0c;中间有出现一个标题带有“Splash Screen”字符串的窗口。 二 Splash Screen窗口创…

线性代数学习笔记

矩阵 矩阵是一种非常重要的数学对象,它通常由一个由数字排成的矩形阵列来定义。一个矩阵由若干行和若干列组成,被称为矩阵的行数和列数。一般情况下,矩阵的行数和列数分别用 n n n 和 m m m 表示。<

2025.7.13总结

每次写日记&#xff0c;总觉得自我感受不是很好&#xff0c;脑子总会有许多消极思想。在网上&#xff0c;我曾看到一个关于“人生是一场巨大的事与愿违”&#xff0c;可能&#xff0c;真的是这个样子吧。以前的我&#xff0c;有上进心&#xff0c;有目标感&#xff0c;脚踏实地…

linux-网络-网络管理发展历程

Linux 的网络管理机制经历了多个阶段的发展&#xff0c;从早期的静态配置到现代动态管理工具的出现&#xff0c;反映了 Linux 系统在网络连接、自动化和用户体验方面的不断演进。以下是 Linux 网络管理发展的主要阶段&#xff1a;1. 早期的静态网络配置&#xff08;传统方式&am…

华为 GaussDB :技术特性、应用局限与市场争议

3-5月间&#xff0c;老夫在某学校带了这门课&#xff0c;简单总结一下课程外的看法&#xff1a;华为 GaussDB 作为华为云生态中的核心数据库产品&#xff0c;自推出以来便承载着华为在数据基础设施领域的战略野心。其技术路线既延续了开源数据库的兼容性优势&#xff0c;又深度…

从零开始学习深度学习—水果分类之PyQt5App

一、项目背景⭐&#xff1a;本项目是“从零开始学习深度学习”系列中的第二个实战项目&#xff0c;旨在实现第一个简易App(图像分类任务——水果分类)&#xff0c;进一步地落地AI模型应用&#xff0c;帮助初学者初步了解模型落地。基于PyQt5图形界面的水果图像分类系统&#xf…

小架构step系列13:测试用例的加载

1 概述测试用例的编写要有一些基础的规范&#xff0c;在本文先定义文件名称和测试用例方法名的规范。2 文件加载原理先从源码来看一下测试用例的文件加载原理。2.1 文件的匹配主要是通过注解来扫描测试用例。// 在IDEA测试用例启动时&#xff0c;调用junit-platform-launcher-x…

K8S的CNI之calico插件升级至3.30.2

前言宿主机ping不通K8S的pod&#xff0c;一直存在丢包的现象&#xff0c;排查了防火墙、日志、详细信息等没发现什么问题&#xff0c;最后搜索发现&#xff0c;是因为把K8S的版本升级之后&#xff0c;旧版本的CNI插件不适配原因导致的&#xff0c;于是就把calico也一并升级并且…

Spring Boot RESTful API 设计指南:查询接口规范与最佳实践

Spring Boot RESTful API 设计指南&#xff1a;查询接口规范与最佳实践 引言 在 Spring Boot 开发中&#xff0c;查询接口的设计直接影响着系统的可用性、可维护性和性能。本文将深入探讨如何规范设计查询接口&#xff0c;包括 GET/POST 的选择、参数定义、校验规则等&#xff…

ctfshow萌新题集

记录一下前半部分是能自己写出来的&#xff0c;后半部分是需要提示的&#xff0c;感觉自己归来两年仍是萌新 misc部分 知识点 base家族密文特征 Base16 (Hex) 字符集&#xff1a;0-9, A-F&#xff08;不区分大小写&#xff09;。特征&#xff1a; 长度是 2 的倍数&#xff…