如何计算 ScreenToWorld 坐标?
How to calculate ScreenToWorld coordinates?
我有一个包含我的视图状态的对象,我希望能够将世界坐标转换为屏幕坐标,这很有效。但是我也希望能够从屏幕坐标转换为世界坐标,我有以下代码:
#include <glm/glm.hpp>
#include <gmock/gmock.h>
class CoordinateSpace
{
public:
CoordinateSpace(int w, int h)
{
mW = w;
mH = h;
}
glm::vec2 WorldToScreen(const glm::vec2& worldPos)
{
return ((mProjection * mView) * glm::vec4(worldPos, 1, 1)) * glm::vec4(mW / 2, -mH / 2, 1, 1) + glm::vec4(mW / 2, mH / 2, 0, 0);
}
glm::vec2 ScreenToWorld(const glm::vec2& screenPos)
{
return (glm::inverse(mProjection * mView) * glm::vec4(screenPos, 1, 1)) * glm::vec4(mW / 2, -mH / 2, 1, 1) + glm::vec4(mW / 2, mH / 2, 0, 0);
}
void UpdateCamera()
{
glm::mat4 target_projection = glm::ortho(
-mScreenSize.x / 2.0f,
mScreenSize.x / 2.0f,
mScreenSize.y / 2.0f,
-mScreenSize.y / 2.0f,
-1.0f,
1.0f);
glm::mat4 camMat = glm::translate(glm::mat4(1.0f), glm::vec3(-mCameraPosition, 0));
mView = camMat;
mProjection = target_projection;
}
glm::vec2 mScreenSize = glm::vec2;
glm::vec2 mCameraPosition = glm::vec2;
protected:
int mW = 0;
int mH = 0;
// 2d ortho projection
glm::mat4 mProjection;
// camera location into the world
glm::mat4 mView;
};
TEST(CoordinateSpace, Conversion)
{
CoordinateSpace coords(640, 480);
coords.mCameraPosition = { 0.0f, 0.0f };
coords.mScreenSize = { 640.0f, 480.0f };
coords.UpdateCamera();
const glm::vec2 actual1 = coords.WorldToScreen({ 50.0f, 100.0f });
ASSERT_EQ(glm::round((640.0f/2)+50.0f), glm::round(actual1.x));
ASSERT_EQ(glm::round((480.0f/2)+100.0f), glm::round(actual1.y));
const glm::vec2 actual2 = coords.ScreenToWorld(actual1);
ASSERT_EQ(glm::round(50.0f), glm::round(actual2.x));
ASSERT_EQ(glm::round(100.0f), glm::round(actual2.y));
}
而不是 50.0f
我得到 5.12032e+06
,如何正确计算 ScreenToWorld
?
假设您有:
屏幕位置 = ((PROJ * VIEW) * WORLDPOS) * A + B;
使用代数来隔离 WORLDPOS,我认为这会起作用:
WORLDPOS = ((SCREENPOS - B) / A) * INV(PROJ*VIEW)
所以:
return glm::inverse(mProjection * mView) * ((screenPos - glm::vec4(mW / 2, mH / 2, 0, 0)) / glm::vec4 (mW / 2, -mH / 2, 1, 1));
我有一个包含我的视图状态的对象,我希望能够将世界坐标转换为屏幕坐标,这很有效。但是我也希望能够从屏幕坐标转换为世界坐标,我有以下代码:
#include <glm/glm.hpp>
#include <gmock/gmock.h>
class CoordinateSpace
{
public:
CoordinateSpace(int w, int h)
{
mW = w;
mH = h;
}
glm::vec2 WorldToScreen(const glm::vec2& worldPos)
{
return ((mProjection * mView) * glm::vec4(worldPos, 1, 1)) * glm::vec4(mW / 2, -mH / 2, 1, 1) + glm::vec4(mW / 2, mH / 2, 0, 0);
}
glm::vec2 ScreenToWorld(const glm::vec2& screenPos)
{
return (glm::inverse(mProjection * mView) * glm::vec4(screenPos, 1, 1)) * glm::vec4(mW / 2, -mH / 2, 1, 1) + glm::vec4(mW / 2, mH / 2, 0, 0);
}
void UpdateCamera()
{
glm::mat4 target_projection = glm::ortho(
-mScreenSize.x / 2.0f,
mScreenSize.x / 2.0f,
mScreenSize.y / 2.0f,
-mScreenSize.y / 2.0f,
-1.0f,
1.0f);
glm::mat4 camMat = glm::translate(glm::mat4(1.0f), glm::vec3(-mCameraPosition, 0));
mView = camMat;
mProjection = target_projection;
}
glm::vec2 mScreenSize = glm::vec2;
glm::vec2 mCameraPosition = glm::vec2;
protected:
int mW = 0;
int mH = 0;
// 2d ortho projection
glm::mat4 mProjection;
// camera location into the world
glm::mat4 mView;
};
TEST(CoordinateSpace, Conversion)
{
CoordinateSpace coords(640, 480);
coords.mCameraPosition = { 0.0f, 0.0f };
coords.mScreenSize = { 640.0f, 480.0f };
coords.UpdateCamera();
const glm::vec2 actual1 = coords.WorldToScreen({ 50.0f, 100.0f });
ASSERT_EQ(glm::round((640.0f/2)+50.0f), glm::round(actual1.x));
ASSERT_EQ(glm::round((480.0f/2)+100.0f), glm::round(actual1.y));
const glm::vec2 actual2 = coords.ScreenToWorld(actual1);
ASSERT_EQ(glm::round(50.0f), glm::round(actual2.x));
ASSERT_EQ(glm::round(100.0f), glm::round(actual2.y));
}
而不是 50.0f
我得到 5.12032e+06
,如何正确计算 ScreenToWorld
?
假设您有:
屏幕位置 = ((PROJ * VIEW) * WORLDPOS) * A + B;
使用代数来隔离 WORLDPOS,我认为这会起作用:
WORLDPOS = ((SCREENPOS - B) / A) * INV(PROJ*VIEW)
所以:
return glm::inverse(mProjection * mView) * ((screenPos - glm::vec4(mW / 2, mH / 2, 0, 0)) / glm::vec4 (mW / 2, -mH / 2, 1, 1));