eos 1.4.0
Loading...
Searching...
No Matches
matrix_projection.hpp
1/*
2 * eos - A 3D Morphable Model fitting library written in modern C++11/14.
3 *
4 * File: include/eos/render/matrix_projection.hpp
5 *
6 * Copyright 2023 Patrik Huber
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20#pragma once
21
22#ifndef EOS_MATRIX_PROJECTION_HPP
23#define EOS_MATRIX_PROJECTION_HPP
24
25#include "Eigen/Core"
26
27#include <cmath>
28
29namespace eos {
30namespace render {
31
51template <typename T>
52Eigen::Matrix4<T> perspective(T fov_y, T aspect, T z_near, T z_far)
53{
54 // Will this assert work? std::abs probably won't work on T?
55 // assert(abs(aspect - std::numeric_limits<T>::epsilon()) > static_cast<T>(0));
56
57 // Note: We want to use std::tan() for floating point types, and for users not using Ceres. However when
58 // using the function with Ceres's auto-diff, we need to use ceres::tan(). We might need an extra "using
59 // ceres::tan" here.
60 using std::tan;
61 const T tan_half_fov_y = tan(fov_y / static_cast<T>(2));
62
63 Eigen::Matrix4<T> result = Eigen::Matrix4<T>::Zero(); // Note: Zero() is correct.
64 result(0, 0) = static_cast<T>(1) / (aspect * tan_half_fov_y);
65 result(1, 1) = static_cast<T>(1) / (tan_half_fov_y);
66 result(2, 2) = -(z_far + z_near) / (z_far - z_near);
67 result(3, 2) = -static_cast<T>(1);
68 result(2, 3) = -(static_cast<T>(2) * z_far * z_near) / (z_far - z_near);
69 return result;
70};
71
88template <typename T>
89Eigen::Matrix4<T> ortho(T left, T right, T bottom, T top)
90{
91 Eigen::Matrix4<T> result = Eigen::Matrix4<T>::Identity();
92 result(0, 0) = static_cast<T>(2) / (right - left);
93 result(1, 1) = static_cast<T>(2) / (top - bottom);
94 result(2, 2) = -static_cast<T>(1);
95 result(0, 3) = -(right + left) / (right - left);
96 result(1, 3) = -(top + bottom) / (top - bottom);
97 return result;
98};
99
117template <typename T>
118Eigen::Matrix4<T> ortho(T left, T right, T bottom, T top, T z_near, T z_far)
119{
120 Eigen::Matrix4<T> result = Eigen::Matrix4<T>::Identity();
121 result(0, 0) = static_cast<T>(2) / (right - left);
122 result(1, 1) = static_cast<T>(2) / (top - bottom);
123 result(2, 2) = -static_cast<T>(2) / (z_far - z_near);
124 result(0, 3) = -(right + left) / (right - left);
125 result(1, 3) = -(top + bottom) / (top - bottom);
126 result(2, 3) = -(z_far + z_near) / (z_far - z_near);
127 return result;
128};
129
147template <typename T>
148Eigen::Vector3<T> project(const Eigen::Vector3<T>& point_3d, const Eigen::Matrix4<T>& modelview_matrix,
149 const Eigen::Matrix4<T>& projection_matrix, const Eigen::Vector4<T>& viewport)
150{
151 Eigen::Vector4<T> projected_point = projection_matrix * modelview_matrix * point_3d.homogeneous();
152 projected_point /= projected_point.w();
153 projected_point =
154 projected_point * static_cast<T>(0.5) +
155 Eigen::Vector4<T>(static_cast<T>(0.5), static_cast<T>(0.5), static_cast<T>(0.5), static_cast<T>(0.5));
156 projected_point.x() = projected_point.x() * T(viewport(2)) + T(viewport(0));
157 projected_point.y() = projected_point.y() * T(viewport(3)) + T(viewport(1));
158
159 // Note: We need the 'template' keyword, as we have a dependent name - 'T' is unknown when the compiler
160 // parses this expression, so we need to tell it that 'head<3>()' is a template function (and not e.g. an
161 // 'operator<' or something like that). We could alternatively rewrite this as:
162 // 'return Eigen::Vector3<T>(projected_point.x(), projected_point.y(), projected_point.z());'
163 return projected_point.template head<3>();
164};
165
166} /* namespace render */
167} /* namespace eos */
168
169#endif /* EOS_MATRIX_PROJECTION_HPP */
Eigen::Matrix4< T > ortho(T left, T right, T bottom, T top)
Creates a 2D orthographic projection matrix.
Definition: matrix_projection.hpp:89
Eigen::Matrix4< T > perspective(T fov_y, T aspect, T z_near, T z_far)
Definition: matrix_projection.hpp:52
Eigen::Vector3< T > project(const Eigen::Vector3< T > &point_3d, const Eigen::Matrix4< T > &modelview_matrix, const Eigen::Matrix4< T > &projection_matrix, const Eigen::Vector4< T > &viewport)
Definition: matrix_projection.hpp:148
core::Image4u render(const core::Mesh &mesh, const Eigen::Matrix4f &model_view_matrix, const Eigen::Matrix4f &projection_matrix, int viewport_width, int viewport_height, bool enable_backface_culling=false, bool enable_near_clipping=true, bool enable_far_clipping=true)
Definition: render.hpp:52
Namespace containing all of eos's 3D model fitting functionality.