eos  0.7.1
Mesh.hpp
1 /*
2  * Eos - A 3D Morphable Model fitting library written in modern C++11/14.
3  *
4  * File: include/eos/render/Mesh.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 MESH_HPP_
23 #define MESH_HPP_
24 
25 #include "opencv2/core/core.hpp"
26 
27 #include "boost/filesystem/path.hpp"
28 
29 #include <vector>
30 #include <array>
31 #include <string>
32 #include <cassert>
33 #include <fstream>
34 
35 namespace eos {
36  namespace render {
37 
45 struct Mesh
46 {
47  std::vector<cv::Vec4f> vertices;
48  std::vector<cv::Vec3f> colors;
49  std::vector<cv::Vec2f> texcoords;
50 
51  std::vector<std::array<int, 3>> tvi;
52  std::vector<std::array<int, 3>> tci;
53 };
54 
63 inline void write_obj(Mesh mesh, std::string filename)
64 {
65  assert(mesh.vertices.size() == mesh.colors.size() || mesh.colors.empty());
66 
67  std::ofstream obj_file(filename);
68 
69  if (mesh.colors.empty()) {
70  for (std::size_t i = 0; i < mesh.vertices.size(); ++i) {
71  obj_file << "v " << mesh.vertices[i][0] << " " << mesh.vertices[i][1] << " " << mesh.vertices[i][2] << " " << std::endl;
72  }
73  }
74  else {
75  for (std::size_t i = 0; i < mesh.vertices.size(); ++i) {
76  obj_file << "v " << mesh.vertices[i][0] << " " << mesh.vertices[i][1] << " " << mesh.vertices[i][2] << " " << mesh.colors[i][0] << " " << mesh.colors[i][1] << " " << mesh.colors[i][2] << " " << std::endl;
77  }
78  }
79 
80  for (auto&& v : mesh.tvi) {
81  // Add one because obj starts counting triangle indices at 1
82  obj_file << "f " << v[0] + 1 << " " << v[1] + 1 << " " << v[2] + 1 << std::endl;
83  }
84 
85  return;
86 }
87 
99 inline void write_textured_obj(Mesh mesh, std::string filename)
100 {
101  assert((mesh.vertices.size() == mesh.colors.size() || mesh.colors.empty()) && !mesh.texcoords.empty());
102 
103  std::ofstream obj_file(filename);
104 
105  boost::filesystem::path mtl_filename(filename);
106  mtl_filename.replace_extension(".mtl");
107 
108  obj_file << "mtllib " << mtl_filename.filename().string() << std::endl; // first line of the obj file
109 
110  // same as in write_obj():
111  if (mesh.colors.empty()) {
112  for (std::size_t i = 0; i < mesh.vertices.size(); ++i) {
113  obj_file << "v " << mesh.vertices[i][0] << " " << mesh.vertices[i][1] << " " << mesh.vertices[i][2] << " " << std::endl;
114  }
115  }
116  else {
117  for (std::size_t i = 0; i < mesh.vertices.size(); ++i) {
118  obj_file << "v " << mesh.vertices[i][0] << " " << mesh.vertices[i][1] << " " << mesh.vertices[i][2] << " " << mesh.colors[i][0] << " " << mesh.colors[i][1] << " " << mesh.colors[i][2] << " " << std::endl;
119  }
120  }
121  // end
122 
123  for (std::size_t i = 0; i < mesh.texcoords.size(); ++i) {
124  obj_file << "vt " << mesh.texcoords[i][0] << " " << 1.0f - mesh.texcoords[i][1] << std::endl;
125  // We invert y because Meshlab's uv origin (0, 0) is on the bottom-left
126  }
127 
128  obj_file << "usemtl FaceTexture" << std::endl; // the name of our texture (material) will be 'FaceTexture'
129 
130  for (auto&& v : mesh.tvi) {
131  // This assumes mesh.texcoords.size() == mesh.vertices.size(). The texture indices could theoretically be different (for example in the cube-mapped 3D scan)
132  // Add one because obj starts counting triangle indices at 1
133  obj_file << "f " << v[0] + 1 << "/" << v[0] + 1 << " " << v[1] + 1 << "/" << v[1] + 1 << " " << v[2] + 1 << "/" << v[2] + 1 << std::endl;
134  }
135 
136  std::ofstream mtl_file(mtl_filename.string());
137  boost::filesystem::path texture_filename(filename);
138  texture_filename.replace_extension(".isomap.png");
139 
140  mtl_file << "newmtl FaceTexture" << std::endl;
141  mtl_file << "map_Kd " << texture_filename.filename().string() << std::endl;
142 
143  return;
144 };
145 
146  } /* namespace render */
147 } /* namespace eos */
148 
149 #endif /* MESH_HPP_ */
std::vector< std::array< int, 3 > > tci
Triangle color indices.
Definition: Mesh.hpp:52
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
void write_obj(Mesh mesh, std::string filename)
Writes the given Mesh to an obj file that for example can be read by MeshLab.
Definition: Mesh.hpp:63
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
void write_textured_obj(Mesh mesh, std::string filename)
Writes an obj file of the given Mesh, including texture coordinates, and an mtl file containing a ref...
Definition: Mesh.hpp:99