- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我想在 OpenGL
中从屏幕坐标转换为世界坐标.我正在使用 glm
为此目的(我也在使用 glfw
)
这是我的代码:
static void mouse_callback(GLFWwindow* window, int button, int action, int mods)
{
if (button == GLFW_MOUSE_BUTTON_LEFT) {
if(GLFW_PRESS == action){
int height = 768, width =1024;
double xpos,ypos,zpos;
glfwGetCursorPos(window, &xpos, &ypos);
glReadPixels(xpos, ypos, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &zpos);
glm::mat4 m_projection = glm::perspective(glm::radians(45.0f), (float)(1024/768), 0.1f, 1000.0f);
glm::vec3 win(xpos,height - ypos, zpos);
glm::vec4 viewport(0.0f,0.0f,(float)width, (float)height);
glm::vec3 world = glm::unProject(win, mesh.getView() * mesh.getTransform(),m_projection,viewport);
std::cout << "screen " << xpos << " " << ypos << " " << zpos << std::endl;
std::cout << "world " << world.x << " " << world.y << " " << world.z << std::endl;
}
}
}
glm::unProject
得到的世界 vector 。具有非常小的 x、y 和 z。如果我使用这个值来平移网格,网格会发生小的平移并且不会跟随鼠标指针。
最佳答案
这个序列有几个问题:
glfwGetCursorPos(window, &xpos, &ypos);
glReadPixels(xpos, ypos, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &zpos);
[...]
glm::vec3 win(xpos,height - ypos, zpos);
glReadPixels
是 GL 函数,因此遵守 GL 的约定,原点位于左下角像素。当您为您的 win
切换到该约定时变量,您仍然使用错误的原点来读取深度缓冲区。ypos
应该在 [0,height-1]
,正确的公式是 height-1 - ypos
,所以你在这里也少了一个。 (我们稍后会看到这也不完全正确。)Pixels and screen coordinates may map 1:1 on your machine, but they won't on every other machine, for example on a Mac with a Retina display. The ratio between screen coordinates and pixels may also change at run-time depending on which monitor the window is currently considered to be on.
glfwGetWindowSize
将返回上述虚拟屏幕坐标中的结果,而 glfwGetFramebufferSize
将返回以像素为单位的实际大小,与 OpenGL 相关。所以基本上,你必须查询两种尺寸,然后才能将鼠标坐标从屏幕坐标适本地缩放到你需要的实际像素。 glReadPixels
使用整数坐标寻址特定像素,整个转换数学使用浮点运算,可以表示任意子像素位置。 GL 的窗口空间被定义为整数坐标代表像素的角点,像素中心位于整数坐标的一半。您的 win
变量将代表所述像素的左下角,但更有用的约定是使用像素中心,因此您最好添加 (0.5f, 0.5f, 0.0f)
的偏移量。至 win
,假设您指向像素中心。 (如果虚拟屏幕坐标的分辨率高于我们的像素,我们可以做得更好,这意味着我们已经获得了鼠标光标的子像素位置,但数学不会改变,因为我们仍然需要切换到GL 的修道院,其中整数表示边界而不是整数表示中心)。请注意,由于我们现在考虑一个来自 [0,w)
的空间。在 x
和 [0,h)
在 y
,这也会影响第 1 点。如果您单击像素 (0,0)
,它将有中心 (0.5, 0.5)
,以及 y
翻转应该是 h-y
所以h-0.5
(访问帧缓冲区像素时,应向下舍入到 h-1
)。 glfwGetWindowSize(win, &screen_w, &screen_h); // better use the callback and cache the values
glfwGetFramebufferSize(win, &pixel_w, &pixel_h); // better use the callback and cache the values
glfwGetCursorPos(window, &xpos, &ypos);
glm::vec2 screen_pos=glm::vec2(xpos, ypos);
glm::vec2 pixel_pos=screen_pos * glm::vec2(pixel_w, pixel_h) / glm::vec2(screen_w, screen_h); // note: not necessarily integer
pixel_pos = pixel_pos + glm::vec2(0.5f, 0.5f); // shift to GL's center convention
glm::vec3 win=glm::vec3(pixel_pos., pixel_h-pixel_pos.y, 0.0f);
glReadPixels( (GLint)win.x, (GLint)win.y, ..., &win.z)
// ... unproject win
what model matrix should I multuply by camera view matrix to form ModelView matrix?
object space -> {MODEL} -> World Space -> {VIEW} -> Eye Space -> {PROJ} -> Clip Space -> {perspective divide} -> NDC -> {Viewport/DepthRange} -> Window Space
that as said in the glm docs (https://glm.g-truc.net/0.9.8/api/a00169.html#ga82a558de3ce42cbeed0f6ec292a4e1b3) the result is returned in object coordinates.
modelView
的参数。 ,但你放什么矩阵完全无关紧要。推杆
view
会有的。
So in order to convert screen to world coordinates I should use a transform matrix from one mesh.
glm::unproject
的矩阵时,它会在内部计算
(V*M)^-1 * P^-1 * ndc_pos
这是
M^-1 * V^-1 & P^-1 * ndc_pos
.如果将结果从对象空间转换回世界空间,则将其乘以
M
再次,导致
M * M^-1 * V^-1 & P^-1 * ndc_pos
,这当然只是
V^-1 & P^-1 * ndc_pos
如果您不输入
M
,您将直接获得首先进入unproject。你只是增加了更多的计算工作,并为数值问题引入了更多的潜力......
关于c++ - 屏幕坐标到世界坐标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45796287/
一个关于Lua和元表的初学者问题,以一个简单的Hello-World为例,涉及len事件,不幸的是它没有返回预期的结果(我使用的是从 Ubuntu 官方存储库安装的 Lua 5.1)。 案子 这是示例
我正在开发一个 OpenGL 应用程序。我需要一个地球自转模型(蓝色的水,绿色的土地)。我的问题不是处理 OpenGL/图形……而是处理数据。 我在哪里可以获得这些数据? (各个国家的边界)。如果
我试图了解在 OpenGL 中创建空间: 对象空间 世界空间 相机空间 投影空间 我对这些阶段的理解是否正确? “立方体”是在笛卡尔坐标系的中心创建的,直接在程序内部输入顶点坐标。 坐标转换为“世界”
我有一个Entity和Bundle的Components,我想附加到将成为第一个实体的子实体的实体上。我可以使用Commands生成带有我的组件的实体,但是我无法获得实际的Entity,这意味着我不能
我想创建一个游戏,它有一个无尽的(实际上是一个非常大的)世界,玩家可以在其中移动。我是否会抽出时间来实现游戏是一回事,但我发现这个想法很有趣,并且希望就如何实现它提供一些意见。 关键是要有一个所有数据
以下代码片段来自维基百科,是标准 Hello World! 的序言! Brainfuck 中的程序... 1. +++++ +++++ initialize counter (
就目前情况而言,这个问题不太适合我们的问答形式。我们期望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、民意调查或扩展讨论。如果您觉得这个问题可以改进并可能重新开放,visit
我正在尝试获取特定日期剩余的确切秒数、分钟数等。这听起来可能很愚蠢,但为什么结果会翻倍呢?这看起来不对,是吗? setInterval(function() { var startDate =
如果我有两个嵌套元素,假设: Foo 然后我对外部元素应用旋转,假设顺时针旋转 45 度: Foo 现在我想将内部 div 向下移动一点。 Foo http://j
在 WindowsForms 世界中,您可以获得可用图像编码器/解码器的列表 System.Drawing.ImageCodecInfo.GetImageDecoders() / GetImageEn
因此,作为我的计算机体系结构类(class)的一部分,我需要熟悉 Assembly,或者至少足够舒适,我正在尝试读取用户的输入然后重新打印(暂时),这是我的我是如何尝试用伪代码来展示它的: 声明 ms
在 HLSL 中有很多矩阵乘法,虽然我了解如何以及在何处使用它们,但我不确定它们是如何导出的或它们的实际目标是什么。 所以我想知道是否有在线资源可以解释这一点,我特别好奇将世界矩阵乘以 View 矩阵
我正在使用 http://jvectormap.owl-hollow.net/ 中的 jVectorMap一切正常。但世界地图的标准尺寸非常小。如果有人想打例如波斯尼亚和黑塞哥维那,他需要大眼镜!有可
我在做游戏。游戏由一个无限平面组成。单位必须在一个离散的正方形上,因此可以使用简单的 Location { x :: Int, y :: Int } 来定位它们。 可能有很多种Unit s。有些可能是
所以我创建了一个顶点着色器,它接受一个角度并计算旋转。尽管模型围绕世界中心而不是它自己的轴/原点旋转,但存在一个问题。 旁注:这是 2D 旋转。 如何让模型绕着自己的轴旋转? 这是我当前的顶点着色器:
所以我创建了一个顶点着色器,它接受一个角度并计算旋转。尽管模型围绕世界中心而不是它自己的轴/原点旋转,但存在一个问题。 旁注:这是 2D 旋转。 如何让模型绕着自己的轴旋转? 这是我当前的顶点着色器:
我最近萌生了创建标签云的想法,就像地球形状的动画一样。我从 ngdc.noaa.gov 中提取了海岸线坐标,并编写了一个小脚本,将其显示在我的浏览器中。现在您可以想象,整个海岸线由大约 48919 个
我使用 3d 模式渲染我的 2d 游戏,因为相机旋转和放大/缩小比 2d 模式容易得多。 现在我遇到了一个我似乎想不出如何解决的问题: 如何使我的世界的 2d 平面以 1 个纹理像素匹配屏幕上的 1
我正在寻找一种简单快捷的方法来清除整个 Phaser 屏幕,就像在 HTML5 canvas 中,您可以通过将 Canvas 的宽度重置为自身来删除所有内容。我无法通过搜索找到任何此类方法 - 只有
是否可以为这样的游戏创建一个 2.5D 世界(双龙)http://www.youtube.com/watch?v=xb9P0YTeq5Y使用box2d? 你知道任何工作示例吗? 预先感谢您的时间。 最
我是一名优秀的程序员,十分优秀!