25TriangleMesh::recalc_normals (
bool face,
bool vertex)
32 this->face_normals.clear();
33 this->face_normals.reserve(this->faces.size() / 3);
38 this->vertex_normals.clear();
39 this->vertex_normals.resize(this->vertices.size(),
math::Vec3f(0.0f));
45 for (std::size_t i = 0; i < this->faces.size(); i += 3)
48 std::size_t ia = this->faces[i + 0];
49 std::size_t ib = this->faces[i + 1];
50 std::size_t ic = this->faces[i + 2];
64 float fnl = fn.
norm();
83 this->face_normals.push_back(fn);
86 if (fnl != 0.0f && vertex)
88 float abl = ab.
norm();
89 float bcl = bc.
norm();
90 float cal = ca.
norm();
96 float ratio1 = (ab / abl).dot(-ca / cal);
97 float ratio2 = (-ab / abl).dot(bc / bcl);
98 float ratio3 = (ca / cal).dot(-bc / bcl);
99 float angle1 = std::acos(
math::clamp(ratio1, -1.0f, 1.0f));
100 float angle2 = std::acos(
math::clamp(ratio2, -1.0f, 1.0f));
101 float angle3 = std::acos(
math::clamp(ratio3, -1.0f, 1.0f));
107 this->vertex_normals[ia] += fn * angle1;
108 this->vertex_normals[ib] += fn * angle2;
109 this->vertex_normals[ic] += fn * angle3;
113 std::cout <<
"NAN error in " << __FILE__ <<
":" << __LINE__
114 <<
": " << angle1 <<
" / " << angle2 <<
" / " << angle3
115 <<
" (" << abl <<
" / " << bcl <<
" / " << cal <<
")"
116 <<
" [" << ratio1 <<
" / " << ratio2 <<
" / " << ratio3
130 this->face_normals.push_back(fnl ? fn / fnl : fn);
133 if (fnl != 0.0f && vertex)
135 this->vertex_normals[ia] += fn;
136 this->vertex_normals[ib] += fn;
137 this->vertex_normals[ic] += fn;
147 for (std::size_t i = 0; i < this->vertex_normals.size(); ++i)
149 float vnl = this->vertex_normals[i].
norm();
151 this->vertex_normals[i] /= vnl;
158 std::cout <<
"Warning: Zero-length normals detected: "
159 << zlfn <<
" face normals, " << zlvn <<
" vertex normals"
166TriangleMesh::ensure_normals (
bool face,
bool vertex)
168 bool need_face_recalc = (face
169 && this->face_normals.size() != this->faces.size() / 3);
170 bool need_vertex_recalc = (vertex
171 && this->vertex_normals.size() != this->vertices.size());
172 this->recalc_normals(need_face_recalc, need_vertex_recalc);
180 if (delete_list.size() != this->vertices.size())
181 throw std::invalid_argument(
"Delete list does not match vertex list");
183 if (this->has_vertex_normals())
185 if (this->has_vertex_colors())
187 if (this->has_vertex_confidences())
189 if (this->has_vertex_values())
191 if (this->has_vertex_texcoords())
199TriangleMesh::delete_vertices_fix_faces (
DeleteList const& dlist)
201 if (dlist.size() != this->vertices.size())
202 throw std::invalid_argument(
"Delete list does not match vertex list");
205 std::vector<std::size_t> idxshift(this->vertices.size(), 0);
206 std::size_t num_deleted = 0;
207 for (std::size_t i = 0; i < this->vertices.size(); ++i)
209 idxshift[i] = num_deleted;
210 if (dlist[i] ==
true)
215 for (std::size_t i = 0; i < this->faces.size(); i += 3)
217 if (dlist[faces[i + 0]] || dlist[faces[i + 1]] || dlist[faces[i + 2]])
225 faces[i + 0] -= idxshift[faces[i + 0]];
226 faces[i + 1] -= idxshift[faces[i + 1]];
227 faces[i + 2] -= idxshift[faces[i + 2]];
232 this->delete_vertices(dlist);
233 this->delete_invalid_faces();
248TriangleMesh::delete_invalid_faces (
void)
252 std::size_t vi = this->faces.size();
256 while (ii < this->faces.size() && is_valid_triangle(&this->faces[ii]))
260 while (vi > ii && !is_valid_triangle(&this->faces[vi]))
265 std::swap(this->faces[vi + 0], this->faces[ii + 0]);
266 std::swap(this->faces[vi + 1], this->faces[ii + 1]);
267 std::swap(this->faces[vi + 2], this->faces[ii + 2]);
269 this->faces.resize(ii);
275TriangleMesh::get_byte_size (
void)
const
277 std::size_t s_verts = this->vertices.capacity() *
sizeof(
math::Vec3f);
278 std::size_t s_faces = this->faces.capacity() *
sizeof(
VertexID);
279 std::size_t s_vnorm = this->vertex_normals.capacity() *
sizeof(
math::Vec3f);
280 std::size_t s_fnorm = this->face_normals.capacity() *
sizeof(
math::Vec3f);
281 std::size_t s_color = this->vertex_colors.capacity() *
sizeof(
math::Vec3f);
282 return s_verts + s_faces + s_vnorm + s_fnorm + s_color;
T const & clamp(T const &v, T const &min=T(0), T const &max=T(1))
Returns value 'v' clamped to the interval specified by 'min' and 'max'.