eos 1.4.0
Loading...
Searching...
No Matches
vertex_visibility.hpp
1/*
2 * eos - A 3D Morphable Model fitting library written in modern C++11/14.
3 *
4 * File: include/eos/render/vertex_visibility.hpp
5 *
6 * Copyright 2019, 2020, 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_RENDER_VERTEX_VISIBILITY_HPP
23#define EOS_RENDER_VERTEX_VISIBILITY_HPP
24
25#include "eos/render/detail/RayDirection.hpp"
26#include "eos/render/ray_triangle_intersect.hpp"
27
28#include "Eigen/Core"
29
30#include <array>
31#include <vector>
32#include <algorithm>
33
34namespace eos {
35namespace render {
36
52inline bool is_vertex_visible(const Eigen::Vector3f& probe_vertex,
53 const std::vector<Eigen::Vector3f>& mesh_vertices,
54 const std::vector<std::array<int, 3>>& mesh_triangle_vertex_indices,
55 detail::RayDirection ray_direction_type)
56{
57 using Eigen::Vector3f;
58
59 bool visible = true;
60 const Vector3f ray_origin = probe_vertex;
61 const Vector3f ray_direction = [&ray_direction_type, &probe_vertex]() {
62 if (ray_direction_type == detail::RayDirection::Parallel)
63 {
64 // For orthographic cameras, shoot towards the user with a parallel ray:
65 return Vector3f(0, 0, 1);
66 } else
67 {
68 // For perspective cameras, we shoot the ray from the vertex towards the camera origin (which
69 // is at (0, 0, 0)):
70 return Vector3f(-probe_vertex);
71 }
72 }();
73
74 // We check in a brute-force manner whether the ray hits any triangles, by looping through all the
75 // triangles, for each vertex of the mesh. This is a very slow way to do this, of course. We should
76 // better use an AABB tree.
77 // For every triangle of the rotated mesh:
78 for (const auto& tri : mesh_triangle_vertex_indices)
79 {
80 const auto& v0 = mesh_vertices[tri[0]];
81 const auto& v1 = mesh_vertices[tri[1]];
82 const auto& v2 = mesh_vertices[tri[2]];
83
84 const auto intersect =
85 ray_triangle_intersect(ray_origin, ray_direction, v0, v1, v2, false);
86 // first is bool intersect, second is the distance t
87 if (intersect.first == true)
88 {
89 // We've hit a triangle. Ray hit its own triangle. If it's behind the ray origin, ignore the
90 // intersection:
91 // Check if in front or behind?
92 if (intersect.second.value() <= 1e-4)
93 {
94 continue; // the intersection is behind the vertex, we don't care about it
95 }
96 // Otherwise, we've hit a genuine triangle, and the vertex is not visible:
97 visible = false;
98 break;
99 }
100 }
101 return visible;
102};
103
118inline std::vector<bool>
119compute_per_vertex_self_occlusion(const std::vector<Eigen::Vector3f>& viewspace_vertices,
120 const std::vector<std::array<int, 3>>& triangle_vertex_indices,
121 detail::RayDirection ray_direction_type)
122{
123 // We are already given vertices in view space (or we should not transform them).
124 std::vector<bool> per_vertex_visibility;
125 for (const auto& vertex : viewspace_vertices)
126 {
127 const bool visible =
128 is_vertex_visible(vertex, viewspace_vertices, triangle_vertex_indices, ray_direction_type);
129 per_vertex_visibility.push_back(visible);
130 }
131 return per_vertex_visibility;
132};
133
147inline std::vector<bool>
148compute_per_vertex_self_occlusion(const std::vector<Eigen::Vector3f>& vertices,
149 const std::vector<std::array<int, 3>>& triangle_vertex_indices,
150 const Eigen::Matrix4f& modelview, detail::RayDirection ray_direction_type)
151{
152 std::vector<Eigen::Vector3f> viewspace_vertices;
153 std::for_each(std::begin(vertices), std::end(vertices), [&viewspace_vertices, &modelview](const auto& v) {
154 const Eigen::Vector4f transformed_vertex = modelview * v.homogeneous();
155 viewspace_vertices.push_back(transformed_vertex.head<3>());
156 });
157
158 return compute_per_vertex_self_occlusion(viewspace_vertices, triangle_vertex_indices, ray_direction_type);
159};
160
161} // namespace render
162} // namespace eos
163
164#endif /* EOS_RENDER_VERTEX_VISIBILITY_HPP */
std::pair< bool, cpp17::optional< float > > ray_triangle_intersect(const Eigen::Vector3f &ray_origin, const Eigen::Vector3f &ray_direction, const Eigen::Vector3f &v0, const Eigen::Vector3f &v1, const Eigen::Vector3f &v2, bool enable_backculling)
Computes the intersection of the given ray with the given triangle.
Definition: ray_triangle_intersect.hpp:57
bool is_vertex_visible(const Eigen::Vector3f &probe_vertex, const std::vector< Eigen::Vector3f > &mesh_vertices, const std::vector< std::array< int, 3 > > &mesh_triangle_vertex_indices, detail::RayDirection ray_direction_type)
Definition: vertex_visibility.hpp:52
std::vector< bool > compute_per_vertex_self_occlusion(const std::vector< Eigen::Vector3f > &viewspace_vertices, const std::vector< std::array< int, 3 > > &triangle_vertex_indices, detail::RayDirection ray_direction_type)
Definition: vertex_visibility.hpp:119
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.