Adds basic tests for BuildCameraRay and uses viewport instead of renderer for width and height.
This was SVN commit r25085.
This commit is contained in:
parent
30432574fa
commit
c4d5729c73
@ -187,9 +187,11 @@ void CCamera::GetViewQuad(float dist, Quad& quad) const
|
||||
|
||||
void CCamera::BuildCameraRay(int px, int py, CVector3D& origin, CVector3D& dir) const
|
||||
{
|
||||
ENSURE(m_ProjType == ProjectionType::PERSPECTIVE || m_ProjType == ProjectionType::ORTHO);
|
||||
|
||||
// Coordinates relative to the camera plane.
|
||||
const float dx = static_cast<float>(px) / g_Renderer.GetWidth();
|
||||
const float dy = 1.0f - static_cast<float>(py) / g_Renderer.GetHeight();
|
||||
const float dx = static_cast<float>(px) / m_ViewPort.m_Width;
|
||||
const float dy = 1.0f - static_cast<float>(py) / m_ViewPort.m_Height;
|
||||
|
||||
Quad points;
|
||||
GetViewQuad(m_FarPlane, points);
|
||||
@ -199,14 +201,21 @@ void CCamera::BuildCameraRay(int px, int py, CVector3D& origin, CVector3D& dir)
|
||||
point = m_Orientation.Transform(point);
|
||||
|
||||
// Get world space position of mouse point at the far clipping plane.
|
||||
CVector3D basisX = points[1] - points[0];
|
||||
CVector3D basisY = points[3] - points[0];
|
||||
CVector3D targetPoint = points[0] + (basisX * dx) + (basisY * dy);
|
||||
const CVector3D basisX = points[1] - points[0];
|
||||
const CVector3D basisY = points[3] - points[0];
|
||||
|
||||
origin = m_Orientation.GetTranslation();
|
||||
|
||||
// Build direction for the camera origin to the target point.
|
||||
dir = targetPoint - origin;
|
||||
if (m_ProjType == ProjectionType::PERSPECTIVE)
|
||||
{
|
||||
// Build direction for the camera origin to the target point.
|
||||
origin = m_Orientation.GetTranslation();
|
||||
CVector3D targetPoint = points[0] + (basisX * dx) + (basisY * dy);
|
||||
dir = targetPoint - origin;
|
||||
}
|
||||
else if (m_ProjType == ProjectionType::ORTHO)
|
||||
{
|
||||
origin = m_Orientation.GetTranslation() + (basisX * (dx - 0.5f)) + (basisY * (dy - 0.5f));
|
||||
dir = m_Orientation.GetIn();
|
||||
}
|
||||
dir.Normalize();
|
||||
}
|
||||
|
||||
@ -218,8 +227,8 @@ void CCamera::GetScreenCoordinates(const CVector3D& world, float& x, float& y) c
|
||||
|
||||
x = screenspace.X / screenspace.W;
|
||||
y = screenspace.Y / screenspace.W;
|
||||
x = (x + 1) * 0.5f * g_Renderer.GetWidth();
|
||||
y = (1 - y) * 0.5f * g_Renderer.GetHeight();
|
||||
x = (x + 1) * 0.5f * m_ViewPort.m_Width;
|
||||
y = (1 - y) * 0.5f * m_ViewPort.m_Height;
|
||||
}
|
||||
|
||||
CVector3D CCamera::GetWorldCoordinates(int px, int py, bool aboveWater) const
|
||||
|
@ -85,10 +85,8 @@ class CCamera
|
||||
// Returns a quad of view in camera space at given distance from camera.
|
||||
void GetViewQuad(float dist, Quad& quad) const;
|
||||
|
||||
// Build a ray passing through the screen coordinate (px, py) and the camera
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BuildCameraRay: calculate origin and ray direction of a ray through
|
||||
// the pixel (px,py) on the screen
|
||||
// Builds a ray passing through the screen coordinate (px, py), calculates
|
||||
// origin and direction of the ray.
|
||||
void BuildCameraRay(int px, int py, CVector3D& origin, CVector3D& dir) const;
|
||||
|
||||
// General helpers that seem to fit here
|
||||
|
@ -126,15 +126,18 @@ public:
|
||||
std::fabs(p1.m_Norm.Z - p2.m_Norm.Z) < EPS;
|
||||
}
|
||||
|
||||
void CompareVectors(const CVector3D& vector1, const CVector3D& vector2, const float EPS)
|
||||
{
|
||||
TS_ASSERT_DELTA(vector1.X, vector2.X, EPS);
|
||||
TS_ASSERT_DELTA(vector1.Y, vector2.Y, EPS);
|
||||
TS_ASSERT_DELTA(vector1.Z, vector2.Z, EPS);
|
||||
}
|
||||
|
||||
void CompareQuads(const CCamera::Quad& quad, const CCamera::Quad& expectedQuad)
|
||||
{
|
||||
const float EPS = 1e-4f;
|
||||
for (size_t index = 0; index < expectedQuad.size(); ++index)
|
||||
{
|
||||
TS_ASSERT_DELTA(quad[index].X, expectedQuad[index].X, EPS);
|
||||
TS_ASSERT_DELTA(quad[index].Y, expectedQuad[index].Y, EPS);
|
||||
TS_ASSERT_DELTA(quad[index].Z, expectedQuad[index].Z, EPS);
|
||||
}
|
||||
CompareVectors(quad[index], expectedQuad[index], EPS);
|
||||
}
|
||||
|
||||
void CompareQuadsInWorldSpace(const CCamera& camera, const CCamera::Quad& quad, const CCamera::Quad& expectedQuad)
|
||||
@ -145,9 +148,7 @@ public:
|
||||
// Transform quad points from camera space to world space.
|
||||
CVector3D point = camera.GetOrientation().Transform(quad[index]);
|
||||
|
||||
TS_ASSERT_DELTA(point.X, expectedQuad[index].X, EPS);
|
||||
TS_ASSERT_DELTA(point.Y, expectedQuad[index].Y, EPS);
|
||||
TS_ASSERT_DELTA(point.Z, expectedQuad[index].Z, EPS);
|
||||
CompareVectors(point, expectedQuad[index], EPS);
|
||||
}
|
||||
}
|
||||
|
||||
@ -280,4 +281,64 @@ public:
|
||||
};
|
||||
CompareQuadsInWorldSpace(camera, farQuad, expectedWorldSpaceFarQuad);
|
||||
}
|
||||
|
||||
void test_perspective_screen_rays()
|
||||
{
|
||||
const float EPS = 1e-4f;
|
||||
const std::vector<SViewPort> viewPorts = {
|
||||
SViewPort{0, 0, 512, 512},
|
||||
SViewPort{0, 0, 1024, 768},
|
||||
SViewPort{0, 0, 1440, 2536},
|
||||
};
|
||||
for (const SViewPort& viewPort : viewPorts)
|
||||
{
|
||||
const CVector3D cameraPosition(10.0f, 20.0f, 10.0f);
|
||||
const CVector3D cameraDirection(CVector3D(0.0f, -1.0f, 1.0f).Normalized());
|
||||
CCamera camera;
|
||||
camera.SetViewPort(viewPort);
|
||||
camera.LookAt(
|
||||
cameraPosition,
|
||||
cameraPosition + cameraDirection * 10.0f,
|
||||
CVector3D(0.0f, 1.0f, 1.0f).Normalized()
|
||||
);
|
||||
camera.SetPerspectiveProjection(1.0f, 101.0f, DEGTORAD(90.0f));
|
||||
|
||||
CVector3D origin, dir;
|
||||
camera.BuildCameraRay(viewPort.m_Width / 2, viewPort.m_Height / 2, origin, dir);
|
||||
const CVector3D expectedOrigin = cameraPosition;
|
||||
const CVector3D expectedDir = cameraDirection;
|
||||
CompareVectors(origin, expectedOrigin, EPS);
|
||||
CompareVectors(dir, expectedDir, EPS);
|
||||
}
|
||||
}
|
||||
|
||||
void test_ortho_screen_rays()
|
||||
{
|
||||
const float EPS = 1e-4f;
|
||||
const std::vector<SViewPort> viewPorts = {
|
||||
SViewPort{0, 0, 512, 512},
|
||||
SViewPort{0, 0, 1024, 768},
|
||||
SViewPort{0, 0, 1440, 2536},
|
||||
};
|
||||
for (const SViewPort& viewPort : viewPorts)
|
||||
{
|
||||
const CVector3D cameraPosition(10.0f, 20.0f, 10.0f);
|
||||
const CVector3D cameraDirection(CVector3D(0.0f, -1.0f, 1.0f).Normalized());
|
||||
CCamera camera;
|
||||
camera.SetViewPort(viewPort);
|
||||
camera.LookAt(
|
||||
cameraPosition,
|
||||
cameraPosition + cameraDirection * 10.0f,
|
||||
CVector3D(0.0f, 1.0f, 1.0f).Normalized()
|
||||
);
|
||||
camera.SetOrthoProjection(2.0f, 128.0f, 10.0f);
|
||||
|
||||
CVector3D origin, dir;
|
||||
camera.BuildCameraRay(viewPort.m_Width / 2, viewPort.m_Height / 2, origin, dir);
|
||||
const CVector3D expectedOrigin = cameraPosition;
|
||||
const CVector3D expectedDir = cameraDirection;
|
||||
CompareVectors(origin, expectedOrigin, EPS);
|
||||
CompareVectors(dir, expectedDir, EPS);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user