使用 glFrustum 进行离轴投影

2024-04-02

我正在尝试使用 OpenGL 对场景进行离轴投影,并且我阅读了该文档罗伯特·库伊马的离轴投影 http://csc.lsu.edu/~kooima/pdfs/gen-perspective.pdf现在对实际需要做什么有了更好的了解,但仍然有一些部分我觉得很棘手。我了解到OpenGL的离轴投影代码如下:

Code 1:

glMatrixMode(GL_PROJECTION);  
    glLoadIdentity();            
    glFrustum(fNear*(-fFov * ratio + headX),  
              fNear*(fFov * ratio + headX),  
              fNear*(-fFov + headY),  
              fNear*(fFov + headY),  
              fNear, fFar);  
          
    glMatrixMode(GL_MODELVIEW);  
    glLoadIdentity();  
    gluLookAt(headX*headZ, headY*headZ, 0, headX*headZ, headY*headZ, -1, 0, 1, 0);
    glTranslatef(0.0,0.0,headZ);

如果这是一个正常的透视投影,用户位于屏幕的中心,那么据我理解,这是相当容易理解的。

               Screen  
                   |
                   |  h = H/2
                   |  
x----- n -----------
                   |
                   |  h = H/2
                   |

当用户位于 x 且距屏幕的距离为 n 时,顶部、底部坐标为圆台计算如下:(假设 theta 是视野 (fov)我想假设为30度)

h = n * tan (theta/2);
tanValue = DEG_TO_RAD * theta/2;
[EDIT Line additon here>>]: fFov = tan(tanValue);
h = n * tan (tanValue);

因此,顶部和底部(否定顶部的值)都是为圆台论据。左边的现在是左/右。

Now, Aspect Ratio, r = ofGetWidth()/ofGetHeight();
Right = n * (fFov * r); , where r is the aspect ratio [Edit1>> Was written tanValue*r earlier here]

Question1) 上面的 (tanValue*r) 是否得到水平视场角然后应用相同的方法来获得左/右值?

   双 msX = (double)ofGetMouseX();
双 msY = (double)ofGetMouseY();
双 scrWidth = (double)ofGetWidth();
双 scrHeight = (double)ofGetHeight();

headX = (msX / scrWidth) - 0.5;
headY = ((scrHeight - msY) / scrHeight) - 0.5;
头Z = -2.0;

现在,考虑离轴投影,我们有headX and headY计算的位置(此处使用鼠标而不是实际用户的头部):

Question2) headX 和 y 是如何计算的?从上面减去 -0.5 有什么用?我观察到,随着 msX 和 msY 的变化,它使 x 值达到(-0.5 到 0.5),y 值达到(0.5 到 -0.5)。

Question3)在上面的代码(代码1)中,headY是如何添加到计算出的tan(fov/2)值中的?

-fFov + headY
fFov + headY

这个价值给我们带来了什么? -fFov是计算出的theta/2的tan值,但是如何直接添加headY呢?

-fFov * ratio + headX
-fFov * ratio + headX

上面如何给我们一个值,当乘以 n(近值)时,我们可以得到离轴投影的不对称 glFrustum 调用的左和右?

Question4)我知道必须为视点完成 glLookAt 将平截头体的顶点移动到用户眼睛所在的位置(在本例中为鼠标所在的位置)。注意上面代码中的一行:

gluLookAt(headX*headZ, headY*headZ, 0, headX*headZ, headY*headZ, -1, 0, 1, 0);

How is headX*headZ给我眼睛的展示,headY*headZ给我可以使用的眼睛的 y 位置gluLookAt() here?

编辑:此处添加完整的问题描述:Pastebin.com/BiSHXspb http://pastebin.com/BiSHXspb


你已经制作了这张漂亮的 ASCII 艺术图

               Screen  
                   B
                   |  h = H/2
                   |  
x----- n ----------A
                   |
                   |  h = H/2
                   B'

视野定义为角度fov = angle((x,B), (x,B'))在屏幕“线”的两个尖端 B、B' 和点 x 之间形成。三角函数Tangens(tan) 定义为

h/n = tan( angle((x,A), (x,B)) )

自从length(A, B) == length(A, B') == h == H/2我们知道

H/(2·n) == tan( fov ) == tan( angle((x,B), (x,B')) ) == tan( 2·angle((x,A), (x,B)) )

由于在三角学中角度以弧度给出,但大多数人更喜欢度数,因此您可能必须将度数转换为弧度。

所以我们只对屏幕跨度的一半感兴趣(=h)我们必须将角度减半。如果我们想接受度数,请将其转换为弧度。这就是这个表达的意思。

tanValue = DEG_TO_RAD * theta/2;

然后我们用它来计算h by

h = tan(tanValue) * n

FOV 是针对屏幕的水平还是垂直跨度取决于场跨度的方式H随纵横比缩放。

headX 和 y 是如何计算的?从上面减去 -0.5 有什么用?我观察到,随着 msX 和 msY 的变化,它使 x 值达到(-0.5 到 0.5),y 值达到(0.5 到 -0.5)。

您给出的计算假设屏幕空间坐标在 [0, screenWidth] × [0, screenHeight] 范围内。然而,由于我们在标准化范围 [-1, 1]² 中进行平截头体计算,我们希望将设备绝对鼠标坐标转换为标准化中心相对坐标。这允许指定相对于标准化近平面尺寸的轴偏移。这是偏移量为 0 时的样子(图中网格的距离为 0.1 单位):

应用 X 偏移 -0.5 后,它看起来像这样(橙色轮廓),您可以看到近平面的左边缘已移动到 -0.5。

现在,简单地想象网格是您的屏幕,您的鼠标指针将像这样在平面边界附近的投影平截头体周围拖动。

这个价值给我们带来了什么? -fFov是计算出的theta/2的tan值,但是如何直接添加headY呢?

因为 fFov 不是角度而是跨度H/2 = h在你的 ASCII 艺术图片中。和headX and headY是标准化近投影平面中的相对位移。

headX怎么样headZ 给我眼睛的展示,headYheadZ 给了我眼睛的 yPosition,我可以在 gluLookAt() 中使用它吗?

您引用的代码似乎是该帐户的临时解决方案,以强调效果。在真实的头部跟踪立体系统中,您的做法略有不同。从技术上来说headZ应该用于计算近平面距离或从中导出。

无论如何,主要思想是,头部位于距投影平面一定距离的位置,并且中心点以投影的相对单位移动。所以你必须相对缩放头X、头Y与实际头部到投影平面的距离进行顶点校正。

根据评论/请求进行更新

到目前为止,我们在将视场 (fov) 转换为屏幕跨度时仅考虑了一维。为了使图像不失真,近剪裁平面的[左,右]/[下,上]范围的纵横比必须与视口宽度/高度的纵横比匹配。

如果我们选择将 FoV 角度定义为垂直 FoV,则近裁剪平面范围的水平尺寸就是用 with/height 纵横比缩放的垂直近裁剪平面范围的尺寸。

这对于离轴投影来说没什么特别的,但可以在每个透视投影辅助函数中找到;对比一下gluPerspective的源码供参考:

void GLAPIENTRY
gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
{
   GLdouble xmin, xmax, ymin, ymax;

   ymax = zNear * tan(fovy * M_PI / 360.0); // M_PI / 360.0 == DEG_TO_RAD
   ymin = -ymax;

   xmin = ymin * aspect;
   xmax = ymax * aspect;

   glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
}

如果我们认为近裁剪平面范围为 [-aspect, aspect]×[-1, 1] 那么当然headX位置不在标准化范围 [-1, 1] 内,但也必须在范围 [-aspect,aspect] 内给出。

如果您查看链接的论文,您会发现对于每个屏幕,跟踪器报告的头部位置都会转换为absolute相对于屏幕的坐标。


两周前,我有机会测试了一种名为“Z 空间”的显示系统,其中偏振立体显示器与头部跟踪器相结合,创建了一个离轴平截头体/观察组合,与您在显示器前面的物理头部位置相匹配。展示。它还提供了一支“笔”来与您面前的 3D 场景进行交互。这是我过去几年见过的最令人印象深刻的事情之一,我目前正在恳求我的老板给我们买一件:)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 glFrustum 进行离轴投影 的相关文章

  • “字符串”是什么意思?信息'

    我刚刚在查看定义时发现了这个PlatformNotSupportedException class 什么是string message意思是 据我所知是 是缩写Nullable lt gt but Nullable lt gt 只能应用于结
  • dup2() 和 exec()

    include
  • binary_log_types.h:没有这样的文件或目录

    我正在编译一个小型 mysql C 项目并且 遇到以下错误 C Program Files x86 MySQL MySQL Server 5 7 include mysql com h 22 30 fatal error binary lo
  • 动态选择和更新 LINQ 结果集中的列值

    我有一个场景 其中存在 LINQ 结果集 我使用了以下查询 var stockDetails from d in db BloodBanks where d bbUserName Session username ToString sele
  • 在目标 VS 安装时,VSIX 扩展内部使用的 WPF-Log4Net 未输出日志

    当 Log4net 在 VSIX 扩展中使用并安装在另一个目标 VS 上时 它不会记录日志 我有一个 WPF 解决方案 我下载了 log4net dll 添加了 log4net config 并将 复制到输出目录 值设置为 始终复制 log
  • 我的 WPF 应用程序未触发 MainWindow_Loaded

    我目前正在关注Pluralsight C Fundamentals Part 1并在Classes and Objects视频部分指导我在 Visual Studio 中创建一个新的 WPF 应用程序并填写代码 这导致以下结果 namesp
  • 为什么我不能从对中返回 unique_ptr?

    为什么我不能从对中返回 unique ptr include
  • 试图使用加密来混淆我的项目打破了它

    我试图尝试不同的混淆选项 为了做到这一点 我首先尝试了加密货币 以下是我遵循的步骤 打开加密向导并选择一些选项 选择我的解决方案文件 完成向导后 我看到有些 Dll 被很好地混淆了 但我的项目现在无法构建 我注意到的两件事是 我的文件夹中有
  • 证明字符串算法[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 修改正在运行的可执行文件的资源内容

    All 我将应用程序设置存储在资源中 当我的程序首次加载时 我使用 WinAPI 读取指定的资源 然后我解析检索到的字节数据 这对我来说完美无缺 现在假设用户更改了我的应用程序中的设置 他 她检查复选框控件 我想将更新的设置保存到我的资源中
  • 将授权标头添加到 Web 参考

    我正在尝试向客户端的网络服务发出请求 我不知道客户端的底层平台 我使用 添加 Web 引用 在 Visual Studio 2010 中使用了客户端的 WSDL 并生成了我的代理类 称为 ContactService 我现在需要将如下所示的
  • 为什么 httpRuntime targetFramework="4.5" 禁止抓取 .ASPXAUTH cookie?

    当我的 web config 具有以下 httpRuntime 时 我的控制器无法获取 cookie ASPXAUTH 它似乎能够获取任何其他 cookie 无论带或不带句点前缀 如果我删除下面的行 它就可以正常工作
  • C 中的链表数组:初始化和插入?

    我需要创建一个链表数组 如图所示 这就是我到目前为止所做的 typedef struct Node int data struct Node next Node int main void Node link 5 for int q 0 q
  • Request.Form 和 Request.QueryString 之间的区别?

    有人可以告诉我两者之间的确切区别吗Request Form and Request QueryString 我知道一个区别 比如 如果HTTP请求方式为POST 则用户提交的数据在申请表 收藏 如果HTTP请求方法是GET 则用户提交的数据
  • 为什么必须通过 this 指针访问模板基类成员?

    如果下面的类不是模板 我可以简单地拥有x in the derived班级 但是 通过下面的代码 我have to use this gt x Why template
  • 返回 ICollection 而不是 List 的真正优势是什么? [复制]

    这个问题在这里已经有答案了 我读过几篇博客文章 提到对于公共 API 我们应该始终返回 ICollection 或 IEnumerable 而不是 List 返回 ICollection 而不是 List 的真正优势是什么 Thanks 复
  • 用于 nmap 输出的 C++ xml 解析器

    我是 nmap 的新手 我在 nmap 教程中看到 https nmap org book man output html https nmap org book man output html oX 选项可用于获取 xml 格式的 nma
  • Networkx 中 Louvain 分区的可视化

    请帮助我更改 Louvain 聚类算法结果的可视化 我从网站上获取了代码https github com taynaud python louvain https github com taynaud python louvain我可以重写
  • 替换全局热键

    我有一个位于托盘中的应用程序 我想定义多个热键来触发我的程序中的事件 我从 AaronLS 在这个问题中的出色回答中找到了灵感 使用C 设置全局热键 https stackoverflow com a 27309185 3064934 如果
  • DataGridView 捕获用户行选择

    我在处理选择时遇到问题DataGridView 我的网格视图包含一个金额列 表单上有一个文本框 应显示所选网格视图行的总数 因此 我需要在用户选择 取消选择 gridview 行时捕获事件并相应地计算 添加 减去 金额 我找到了两种方法 使

随机推荐

  • 按名称调用 Django celery 任务

    我需要从models py调用一个celery任务 在tasks py中 唯一的问题是 tasks py导入models py 所以我无法从models py导入tasks py 有没有什么方法可以仅使用名称来调用 celery 任务 而无
  • 将多个数组作为参数传递给 Bash 脚本?

    我看过 但只看到了脚本中传递的一个数组的答案 我想将多个数组传递给 bash 脚本 该脚本将它们分配为单独的变量 如下所示 myScript sh array1 array2 array3 这样 var1 array1 and var2 a
  • Java 和 C++ 中的简单变量

    我在一些资料中看到这样一句话 在 Java 中 简单数据类型 例如 int 和 char 的运行方式与 C 中一样 我想知道 Java 和 C 中它们实际上是不同的 在C 中 像Java中的基元这样的简单变量也被分配了一个内存地址 因此C
  • 使用 SQL 获取每小时统计信息

    我们有一张桌子 名字 员工注册 有字段 employeeNo employeeName Registered on Here 注册日期是一个时间戳 我们要求在几天内按小时进行注册 例如 08 年 1 月 1 日 12 点 下午 1 点 15
  • C# 为 ++ 运算符生成 IL - 前缀/后缀表示法何时以及为何更快

    由于这个问题是关于增量运算符和前缀 后缀表示法的速度差异 我将非常仔细地描述这个问题 以免 Eric Lippert 发现它并激怒我 有关我为什么要问的更多信息和更多详细信息 请访问http www codeproject com KB c
  • Silverlight:拉伸到 StackPanel 中的剩余空间

    我有一个带有两个元素的垂直 StackPanel 一个按钮和一个列表框 如何让列表框拉伸到剩余页面高度
  • 将一个 Artifactory 连接到另一个 Artifactory

    我们的设置包括一个全公司范围的 Artifactory 它保存内部构建的工件 并出去获取公开可用的工件 我正在尝试在我们的位置建立一个本地 Artifactory 它将通过常规互联网获取公开可用的工件 但会连接到公司范围内的 Artifac
  • Python open("x", "r") 函数,我如何知道或控制文件应该具有哪种编码?

    如果 python 脚本使用open filename r 函数打开并随后读取文本文件的内容 我如何知道该文件应该具有哪种编码 请注意 由于我是从自己的程序执行此脚本 因此如果有任何方法可以通过环境变量来控制它 那么这对我来说就足够了 顺便
  • Python 中子类化 string.Template 的示例?

    尽管我在文档中看到了多次这样做的参考 但我还没有找到在 Python 中子类化 string Template 的好例子 网上有这方面的例子吗 我想将 更改为不同的字符 并且可能更改标识符的正则表达式 来自蟒蛇docs http docs
  • 谷歌应用程序引擎中的 OAuth

    我正在尝试在 python 上的谷歌应用程序引擎中实现 Oauth 对于我的应用程序 我使用 gae 会话和我的模型来验证用户身份 这对我来说会更有帮助 如果你能提供一些例子 您可能想查看以下资源 The App Engine OAuth
  • 如何测量 Spark 上查询的执行时间

    我需要测量 Apache Spark Bluemix 上查询的执行时间 我尝试过的 import time startTimeQuery time clock df sqlContext sql query df show endTimeQ
  • iOS:跨viewControllers在导航栏下方添加视图

    我有一个这样的项目 但我试图弄清楚如何在整个导航栏的导航栏下方添加横幅 以便在需要时可以将其隐藏 你们中有人知道我该怎么做吗 在主视图控制器中实现协议UINavigationControllerDelegate并在选择器中navigatio
  • in_array() 无法按预期工作[重复]

    这个问题在这里已经有答案了 对于这个数组 options Array 0 gt 0 1 gt 1 2 gt 2 PHP 返回 TRUE this gt assertTrue in array Bug options TRUE this gt
  • .NET 的 SFTP 库 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • OpenLayers 标记图标问题

    我正在我的网站中创建 OSM 地图 并使用 openlayer 添加一些标记 我的问题是我总是得到相同的标记图标
  • 有没有办法重置 Julia 中的当前工作目录?

    假设当前工作目录是C 保存 jl文件的目录 然后我将cwd切换到一些子文件夹来执行一些任务 有没有办法直接将cwd重置回C 之后 即最初的cwd 或者 是否可以独立于当前工作目录来定位正在运行的 jl 文件所在的目录 无需事先将 cwd 保
  • 如何在页面中自动刷新Cognito Token

    我使用 AWS Cognito 服务进行身份验证 在我的 Angular 7 应用程序中 我使用 Amplify Auth 来保护我的页面 如果用户在不同页面之间导航 Amplify 将自动处理令牌刷新 并且他们不会看到令牌过期 如果用户长
  • Pydev 显示未解决的导入,但脚本运行?

    我正在使用 PyDev 我正在尝试将我的项目类组织到包中 例如在一个文件夹中 我有一个模块 libraries fund price library py 在我的项目的另一个文件中 我尝试使用以下方式导入 from libraries fu
  • 如何提取文本中使用的关键字? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的
  • 使用 glFrustum 进行离轴投影

    我正在尝试使用 OpenGL 对场景进行离轴投影 并且我阅读了该文档罗伯特 库伊马的离轴投影 http csc lsu edu kooima pdfs gen perspective pdf现在对实际需要做什么有了更好的了解 但仍然有一些部