eos  0.7.1
render_affine.hpp
1 /*
2  * Eos - A 3D Morphable Model fitting library written in modern C++11/14.
3  *
4  * File: include/eos/render/render_affine.hpp
5  *
6  * Copyright 2014, 2015 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 RENDER_AFFINE_HPP_
23 #define RENDER_AFFINE_HPP_
24 
25 #include "eos/render/detail/render_detail.hpp"
26 #include "eos/render/detail/render_affine_detail.hpp"
27 #include "eos/render/Mesh.hpp"
28 
29 #include "opencv2/core/core.hpp"
30 
31 #include <utility>
32 
33 namespace eos {
34  namespace render {
35 
52 std::pair<cv::Mat, cv::Mat> render_affine(Mesh mesh, cv::Mat affine_camera_matrix, int viewport_width, int viewport_height, bool do_backface_culling = true)
53 {
54  assert(mesh.vertices.size() == mesh.colors.size() || mesh.colors.empty()); // The number of vertices has to be equal for both shape and colour, or, alternatively, it has to be a shape-only model.
55  //assert(mesh.vertices.size() == mesh.texcoords.size() || mesh.texcoords.empty()); // same for the texcoords
56 
57  using cv::Mat;
58  using std::vector;
59 
60  Mat colourbuffer = Mat::zeros(viewport_height, viewport_width, CV_8UC4);
61  Mat depthbuffer = std::numeric_limits<float>::max() * Mat::ones(viewport_height, viewport_width, CV_64FC1);
62 
63  Mat affine_with_z = detail::calculate_affine_z_direction(affine_camera_matrix);
64 
65  vector<detail::Vertex> projected_vertices;
66  projected_vertices.reserve(mesh.vertices.size());
67  for (int i = 0; i < mesh.vertices.size(); ++i) {
68  Mat vertex_screen_coords = affine_with_z * Mat(mesh.vertices[i]);
69  cv::Vec3f vertex_colour;
70  if (mesh.colors.empty()) {
71  vertex_colour = cv::Vec3f(0.5f, 0.5f, 0.5f);
72  }
73  else {
74  vertex_colour = mesh.colors[i];
75  }
76  projected_vertices.push_back(detail::Vertex(vertex_screen_coords, vertex_colour, mesh.texcoords[i]));
77  }
78 
79  // All vertices are screen-coordinates now
80  vector<detail::TriangleToRasterize> triangles_to_raster;
81  for (const auto& tri_indices : mesh.tvi) {
82  if (do_backface_culling) {
83  if (!detail::are_vertices_ccw_in_screen_space(projected_vertices[tri_indices[0]].position, projected_vertices[tri_indices[1]].position, projected_vertices[tri_indices[2]].position))
84  continue; // don't render this triangle
85  }
86 
87  // Get the bounding box of the triangle:
88  // take care: What do we do if all 3 vertices are not visible. Seems to work on a test case.
89  cv::Rect bounding_box = detail::calculate_clipped_bounding_box(projected_vertices[tri_indices[0]].position, projected_vertices[tri_indices[1]].position, projected_vertices[tri_indices[2]].position, viewport_width, viewport_height);
90  auto min_x = bounding_box.x;
91  auto max_x = bounding_box.x + bounding_box.width;
92  auto min_y = bounding_box.y;
93  auto max_y = bounding_box.y + bounding_box.height;
94 
95  if (max_x <= min_x || max_y <= min_y) // Note: Can the width/height of the bbox be negative? Maybe we only need to check for equality here?
96  continue;
97 
98  detail::TriangleToRasterize t;
99  t.min_x = min_x;
100  t.max_x = max_x;
101  t.min_y = min_y;
102  t.max_y = max_y;
103  t.v0 = projected_vertices[tri_indices[0]];
104  t.v1 = projected_vertices[tri_indices[1]];
105  t.v2 = projected_vertices[tri_indices[2]];
106 
107  triangles_to_raster.push_back(t);
108  }
109 
110  // Raster all triangles, i.e. colour the pixel values and write the z-buffer
111  for (auto&& triangle : triangles_to_raster) {
112  detail::raster_triangle_affine(triangle, colourbuffer, depthbuffer);
113  }
114  return std::make_pair(colourbuffer, depthbuffer);
115 };
116 
117 
118  } /* namespace render */
119 } /* namespace eos */
120 
121 #endif /* RENDER_AFFINE_HPP_ */
std::pair< cv::Mat, cv::Mat > render(Mesh mesh, cv::Mat model_view_matrix, cv::Mat projection_matrix, int viewport_width, int viewport_height, const boost::optional< Texture > &texture=boost::none, bool enable_backface_culling=false, bool enable_near_clipping=true, bool enable_far_clipping=true)
Definition: render.hpp:125
std::pair< cv::Mat, cv::Mat > render_affine(Mesh mesh, cv::Mat affine_camera_matrix, int viewport_width, int viewport_height, bool do_backface_culling=true)
Definition: render_affine.hpp:52
Namespace containing all of eos&#39;s 3D model fitting functionality.
std::vector< cv::Vec4f > vertices
3D vertex positions.
Definition: Mesh.hpp:47
std::vector< cv::Vec3f > colors
Colour information for each vertex. Expected to be in RGB order.
Definition: Mesh.hpp:48
This class represents a 3D mesh consisting of vertices, vertex colour information and texture coordin...
Definition: Mesh.hpp:45
std::vector< std::array< int, 3 > > tvi
Triangle vertex indices.
Definition: Mesh.hpp:51
std::vector< cv::Vec2f > texcoords
Texture coordinates for each vertex.
Definition: Mesh.hpp:49