Add ability to edit the pixel center offset for the projection matrix

This commit is contained in:
Rob Ewbank 2023-02-10 13:54:01 +00:00
parent 201f27a902
commit 4b6990aae0
8 changed files with 37 additions and 7 deletions

View File

@ -321,6 +321,21 @@ void Scene::SetCameraZNear(ComponentRef ref, float v) {
warn("Invalid camera component");
}
void Scene::SetCameraCenterOffset(ComponentRef ref, const Vec2 & offset) {
if (auto *c = GetComponent_(cameras, ref))
c->center_offset = offset;
else
warn("Invalid camera component");
}
Vec2 Scene::GetCameraCenterOffset(ComponentRef ref) const {
if (const auto *c = GetComponent_(cameras, ref))
return c->center_offset;
warn("Invalid camera component");
return {};
}
bool Camera::IsValid() const { return scene_ref && scene_ref->scene ? scene_ref->scene->IsValidCameraRef(ref) : false; }
float Camera::GetZNear() const {
@ -488,6 +503,13 @@ void Camera::SetSize(float v) {
warn("Orphaned camera component");
}
void Camera::SetCenterOffset(const Vec2 & offset) {
if (scene_ref && scene_ref->scene)
scene_ref->scene->SetCameraCenterOffset(ref, offset);
else
warn("Orphaned camera component");
}
Camera Scene::CreateCamera(const float znear, const float zfar, const float fov) { return {scene_ref, cameras.add_ref({{znear, zfar}, fov, false})}; }
Camera Scene::CreateOrthographicCamera(const float znear, const float zfar, const float size) {

View File

@ -92,6 +92,8 @@ struct Camera { // 16B on 64 bit
void SetIsOrthographic(bool v);
float GetSize() const;
void SetSize(float v);
void SetCenterOffset(const Vec2 & offset);
Vec2 GetCenterOffset() const;
intrusive_shared_ptr_st<SceneRef> scene_ref;
ComponentRef ref;

View File

@ -72,10 +72,10 @@ ViewState ComputeOrthographicViewState(const Mat4 &world, float size, float znea
return {frustum, proj, view};
}
ViewState ComputePerspectiveViewState(const Mat4 &world, float fov, float znear, float zfar, const Vec2 &aspect_ratio, const Vec2 &offset) {
ViewState ComputePerspectiveViewState(const Mat4 &world, float fov, float znear, float zfar, const Vec2 &aspect_ratio, const Vec2 &offset, const Vec2 & center_offset) {
const bgfx::Caps *caps = bgfx::getCaps();
const auto view = InverseFast(world);
const auto proj = ComputePerspectiveProjectionMatrix(znear, zfar, FovToZoomFactor(fov), aspect_ratio, offset);
const auto proj = ComputePerspectiveProjectionMatrix(znear, zfar, FovToZoomFactor(fov), aspect_ratio, offset, center_offset);
const auto frustum = MakeFrustum(proj, world);
return {frustum, proj, view};
}

View File

@ -59,7 +59,7 @@ struct ViewState {
};
ViewState ComputeOrthographicViewState(const Mat4 &world, float size, float znear, float zfar, const Vec2 &aspect_ratio, const Vec2 &offset = {});
ViewState ComputePerspectiveViewState(const Mat4 &world, float fov, float znear, float zfar, const Vec2 &aspect_ratio, const Vec2 &offset = {});
ViewState ComputePerspectiveViewState(const Mat4 &world, float fov, float znear, float zfar, const Vec2 &aspect_ratio, const Vec2 &offset = {}, const Vec2 &center_offset = {});
Mat4 ComputeBillboardMat4(const Vec3 &pos, const ViewState &view_state, const Vec3 &scale = {1, 1, 1});

View File

@ -245,7 +245,7 @@ ViewState Scene::ComputeCameraViewState(NodeRef ref, const Vec2 &aspect_ratio) c
if (auto cam_ = GetComponent_(cameras, node_->components[NCI_Camera])) {
const auto &world = transform_worlds[trs_ref.idx];
return cam_->ortho ? ComputeOrthographicViewState(world, cam_->size, cam_->zrange.znear, cam_->zrange.zfar, aspect_ratio)
: ComputePerspectiveViewState(world, cam_->fov, cam_->zrange.znear, cam_->zrange.zfar, aspect_ratio);
: ComputePerspectiveViewState(world, cam_->fov, cam_->zrange.znear, cam_->zrange.zfar, aspect_ratio, cam_->center_offset);
} else {
warn("Invalid node camera");
}

View File

@ -308,6 +308,8 @@ public:
void SetCameraSize(ComponentRef ref, float v);
bool GetCameraIsOrthographic(ComponentRef ref) const;
void SetCameraIsOrthographic(ComponentRef ref, const bool &v);
void SetCameraCenterOffset(ComponentRef ref, const Vec2 & offset);
Vec2 GetCameraCenterOffset(ComponentRef ref) const;
Camera CreateCamera(float znear, float zfar, float fov = Deg(45.f));
Camera CreateOrthographicCamera(float znear, float zfar, float size = 1.f);
@ -739,6 +741,7 @@ private:
float fov{Deg(40.f)};
bool ortho{false};
float size{1.f};
Vec2 center_offset{0.f, 0.f};
};
struct Object_ {

View File

@ -26,14 +26,17 @@ Mat44 ComputeOrthographicProjectionMatrix(float znear, float zfar, float size, c
return {2.f / size / aspect_ratio.x, 0, 0, 0, 0, 2.f / size / aspect_ratio.y, 0, 0, 0, 0, qA, 0, offset.x, offset.y, qB, 1};
}
Mat44 ComputePerspectiveProjectionMatrix(float znear, float zfar, float zoom_factor, const Vec2 &aspect_ratio, const Vec2 &offset) {
Mat44 ComputePerspectiveProjectionMatrix(float znear, float zfar, float zoom_factor, const Vec2 &aspect_ratio, const Vec2 &offset, const Vec2 &centerOffset) {
const NDCInfos &ndc_infos = GetNDCInfos();
const float qA = ndc_infos.homogeneous_depth ? ((zfar + znear) / (zfar - znear)) : (zfar / (zfar - znear));
const float qB = ndc_infos.homogeneous_depth ? (-2 * zfar * znear / (zfar - znear)) : (-qA * znear);
return {zoom_factor / aspect_ratio.x, 0, 0, 0, 0, zoom_factor / aspect_ratio.y, 0, 0, 0, 0, qA, 1, offset.x, offset.y, qB, 0};
return {zoom_factor / aspect_ratio.x, 0, 0, 0, 0, zoom_factor / aspect_ratio.y, 0, 0, centerOffset.x, centerOffset.y, qA, 1, offset.x, offset.y, qB, 0};
}
Mat44 Compute2DProjectionMatrix(float znear, float zfar, float res_x, float res_y, bool y_up) {
const NDCInfos &ndc_infos = GetNDCInfos();

View File

@ -45,7 +45,7 @@ Mat44 ComputeOrthographicProjectionMatrix(float znear, float zfar, float size, c
@see ZoomFactorToFov, FovToZoomFactor, ComputeAspectRatioX and ComputeAspectRatioY.
*/
Mat44 ComputePerspectiveProjectionMatrix(float znear, float zfar, float zoom_factor, const Vec2 &aspect_ratio, const Vec2 &offset = Vec2::Zero);
Mat44 ComputePerspectiveProjectionMatrix(float znear, float zfar, float zoom_factor, const Vec2 &aspect_ratio, const Vec2 &offset = Vec2::Zero, const Vec2 &centerOffset = Vec2::Zero);
/// Returns a projection matrix from a 2D space to the 3D world, as required by SetViewTransform() for example.
Mat44 Compute2DProjectionMatrix(float znear, float zfar, float res_x, float res_y, bool y_up);