VR 全景模式OpenGL原理

VR 全景模式OpenGL原理

VR 全景模式原理

VR 全景模式原理将画面渲染到球面上,相当于从球心去观察内部球面,观察到的画面 360 度无死角,与普通播平面渲染的本质区别在渲染图像部分,画面渲染到一个矩形平面上,而全景需要将画面渲染到球面,利用 OpenGL 构建一个球体。OpenGL ES 中所有 3D 物体均是由三角形构成的,构建一个球体只需要利用球坐标系中的经度角、维度角以及半径计算出球面点的三维坐标,最后这些坐标点构成一个个小矩形,每个矩形就可以分成 2 个三角形。
在这里插入图片描述

纬度和经度的含义:

1、首先,纬度是地球表面上某一点与赤道之间的角度,取值范围为-90度到+90度。经度是地球表面上某一点与本初子午线之间的角度,取值范围为-180度到+180度。
2、将纬度和经度转换为弧度表示。OpenGL中的数学函数通常使用弧度作为单位,因此需要将纬度和经度从角度转换为弧度。可以使用以下公式进行转换:
弧度 = 角度 * π / 180
3、根据转换后的纬度和经度计算右手世界坐标。右手世界坐标系是OpenGL中常用的坐标系,其中x轴指向右侧,y轴指向上方,z轴指向观察者的反方向。
首先,根据纬度和经度计算球面上的点的坐标。可以使用以下公式:

  • x = cos(纬度) cos(经度)
  • y = sin(纬度)
  • z = cos(纬度) sin(经度)
x=r*cosθ*sinsβ
y=r*sinθ
y=r*cosθ*cosβ

在这里插入图片描述

球体网格实现

// 这个函数 `createSphere` 用于根据指定的参数在3D空间中生成一个球体网格。void VR_FullViewSphere3D::createSphere(float radius, int rings, int sectors, void *tag)
{// 定义必要的变量和常数float PI            = M3D_PI;float nowradius     = radius;int longtitude      = rings;int latitude        = sectors;float longtiRatio   = 1.0f;float latiRatio     = 2.0f;// 计算所需的顶点、纹理坐标和索引的总数int numPoints      = longtitude * (latitude + 1) * 3;int numTexcoords   = longtitude * (latitude + 1) * 2;int numIndices     = (longtitude - 1) * latitude * 6;// 为顶点数据、纹理坐标和索引分配内存m_vertexs1   = (float *)malloc(sizeof(float) * numPoints);m_texcoords1 = (float *)malloc(sizeof(float) * numTexcoords);m_indices1   = (short *)malloc(sizeof(short) * numIndices);int t = 0, v = 0, counter = 0;float theta = 0.0f, phi = 0.0f;// 生成顶点和纹理坐标for (int i = 0; i < longtitude; i++) {phi = (PI / 2 - i / (longtitude - 1 + 0.0) * PI) * longtiRatio;for (int j = 0; j < latitude + 1; j++) {theta = (j / (latitude + 0.0) * PI - PI / 2) * latiRatio;float r = -nowradius * (float)cosf(phi);float x = r * (float)sinf(theta);float y = nowradius * (float)sinf(phi);float z = r * (float)cosf(theta);// 分配顶点坐标m_vertexs1[v++] = x;  // X轴m_vertexs1[v++] = y;  // Y轴m_vertexs1[v++] = z;  // Z轴// 分配纹理坐标m_texcoords1[t++] = 1.0f - (float)((j + 0.0) / (latitude + 0.0)); // X轴m_texcoords1[t++] = (float)((i + 0.0) / (longtitude - 1.0));       // Y轴}}// 生成三角形的索引for (int i = 0; i < longtitude - 1; i++) {for (int j = 0; j < latitude; j++) {// 第一个三角形m_indices1[counter++] = (short)(i * (latitude + 1) + j);    // 上顶点m_indices1[counter++] = (short)(i * (latitude + 1) + j + 1); // 右上顶点m_indices1[counter++] = (short)((i + 1) * (latitude + 1) + j); // 下顶点// 第二个三角形m_indices1[counter++] = (short)((i + 1) * (latitude + 1) + j);m_indices1[counter++] = (short)(i * (latitude + 1) + j + 1);m_indices1[counter++] = (short)((i + 1) * (latitude + 1) + j + 1); // 右下顶点}}m_NumIndices = numIndices; // 存储生成的索引总数
}

这个方法根据给定的半径、环数和扇区数,在3D空间中创建一个球体网格。它计算用于渲染球体的顶点、纹理坐标和索引。

在计算球体的纬度角度(phi) 落在 [-π/2, π/2] 的范围时,也就是-90度到+90度,采用了如下的计算方式:

phi = (PI / 2 - i / (longtitude - 1 + 0.0) * PI) * longtiRatio;

这里的目的是为了在球体上均匀生成经线(经度)并控制其分布。详细解释如下:

  • (longtitude - 1 + 0.0):这里将(longtitude - 1)是类似计算机语言数组下标0开始,目的是为了避免整数相除后得到的结果被截断成整数。
  • i / (longtitude - 1 + 0.0):这一部分将当前经线编号i映射到一个范围在[0, 1]之间的值。当i=0时,表示顶端纬度,i=longtitude-1时表示底端纬度。
  • (PI / 2 - i / (longtitude - 1 + 0.0) * PI):根据上述得到的比例值,乘以π并减去π/2,可以将范围从[0, 1]映射到[π/2, -π/2]之间,即从顶端到底端的纬度范围。
  • longtiRatio:这个参数用于调节经度方向上的角度变化,影响经线所在的位置。

综上所述,这种计算方式能够确保在球体表面上沿着经线均匀生成点,并且通过调节longtiRatio参数,可以控制经线的分布密度或者改变球面形状。

在计算球体的经度角度(theta)落在 [-π, π] 的范围时,也就是-180度到+180度,采用了如下的计算方式:

theta = (j / (latitude + 0.0) * PI - PI / 2) * latiRatio;

这里的目的是为了在球体上均匀生成纬线(纬度)并控制其分布。详细解释如下:

  • (latitude + 0.0):将latitude转换为浮点数,以避免整数相除后结果被截断成整数。
  • j / (latitude + 0.0):将当前纬线编号j映射到一个范围在[0, 1]之间的值。当j=0时,表示经线从左侧开始,j=latitude时表示经线到达右侧。
  • (j / (latitude + 0.0) * PI - PI / 2):将上述比例乘以π并减去π/2,将范围从[0, 1]映射到[-π/2, π/2]之间,即从左侧到右侧的经线范围。
  • latiRatio:此参数用于调节纬度方向上的角度变化,影响纬线所在的位置,latiRatio=2实现-180度到+180度。

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

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

相关文章

Linux--文件(2)-重定向和文件缓冲

命令行中的重定向符号 介绍和使用 在Linux的命令行中&#xff0c;重定向符号用于将命令的输入或输出重定向到文件或设备。 常见的重定向符号&#xff1a; 1.“>“符号&#xff1a;将命令的标准输出重定向到指定文件中&#xff0c;并覆盖原有的内容。 2.”>>“符号&a…

解决ipconfig不能使用的问题

问题所示&#xff1a;ipconfig不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 解决办法如下: 1.右击此电脑&#xff0c;点击属性设置&#xff1a; 2.点击高级系统设置 3.点击进入环境变量 4.在系统变量中进行设置&#xff0c;双击PATH进行配置 5.点击新建&am…

绝地求生 实事求是的优化 比增加更多玩法更有效

想必很多老玩家都知道&#xff0c;最初的绝地求生&#xff0c;那样才是最刺激 最好玩的 当然那时候大家都菜 也没有多少外挂 但是后面 为了迎合少部分玩家需求&#xff0c;而进行一些无所需要的改动&#xff0c;而增加一些繁琐而又关紧要的功能&#xff0c; 彻底失去了很多玩家…

【漏洞复现】大华DSS数字监控系统文件读取漏洞

Nx01 产品简介 大华DSS数字监控系统是一个在通用安防视频监控系统基础上设计开发的系统&#xff0c;除了具有普通安防视频监控系统的实时监视、云台操作、录像回放、报警处理、设备治理等功能外&#xff0c;更注重用户使用的便利性。 Nx02 漏洞描述 大华DSS数字监控系统downlo…

展馆设计中展示创造力和创新思维的关联

1、创新科技展示区 在科技展馆设计中可以设置创新科技展示区&#xff0c;展示科技在不同领域的创新应用。该区域可以展示各种前沿科技产品、研发成果和创新项目。通过展示科技的创新性和实用性&#xff0c;观众可以了解到科技如何推动人类创造力的发展和创新思维的实践。 2、创…

企业出海WAS安全自动化解决方案

随着企业出海的日益激烈&#xff0c;安全风险正在成为企业日益关注的问题之一&#xff0c;九河云携手AWS带来了使用Amazon WAF 与 Amazon Shield 的 CloudFront安全自动化。Aws WAF是一种web应用防火墙&#xff0c;可帮助保护客户的web应用程序或api免遭常规web漏洞的攻击。Aws…

微服务架构SpringCloud(2)

热点参数限流 注&#xff1a;热点参数限流默认是对Springmvc资源无效&#xff1b; 隔离和降级 1.开启feign.sentinel.enabletrue 2.FeignClient(fallbackFactory) 3.创建一个类并实现FallbackFactory接口 4.加入依赖 <!--添加Sentienl依赖--><dependency><gro…

消息队列-kafka-消息发送流程(源码跟踪)

官方网址 源码&#xff1a;https://kafka.apache.org/downloads 快速开始&#xff1a;https://kafka.apache.org/documentation/#gettingStarted springcloud整合 发送消息流程 主线程&#xff1a;主线程只负责组织消息&#xff0c;如果是同步发送会阻塞&#xff0c;如果是异…

机器学习的算法及原理

机器学习算法原理是一种让计算机通过数据学习并做出预测或决策的方法。这些算法可以分为几种主要类型&#xff0c;包括监督学习、无监督学习和强化学习。以下是这些类型中一些常见的算法及其基本原理&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业…

利用excel文件增量同步一个库的数据并自动校正两端数据库条数不一致

利用excel文件增量同步一个库的数据并自动校正两端数据库条数不一致 现在有sqlserver和mysql两个库上的表在进行同步&#xff0c;sqlserver上的是源表&#xff0c;mysql上是目标表。 我们就把sqlserver上的数据同步到mysql上 mysql 是没有数据的。 sqlserver的三个表只是创建了…

基于springboot+vue的周边游平台个人管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

计网面试题整理下

1. HTTP常见的状态码有哪些&#xff1f; 常见状态码&#xff1a; 200&#xff1a;服务器已成功处理了请求。 通常&#xff0c;这表示服务器提供了请求的网页。301 &#xff1a; (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时&am…