void VertexNormalAttribute::compute_vertex_normals_from_face(Mesh& mesh) { const size_t dim = mesh.get_dim(); const size_t num_vertices = mesh.get_num_vertices(); const size_t num_faces = mesh.get_num_faces(); const size_t vertex_per_face = mesh.get_vertex_per_face(); const VectorF& normals = get_attribute(mesh, "face_normal"); const VectorF& areas = get_attribute(mesh, "face_area"); assert(normals.size() == 3 * num_faces); assert(areas.size() == num_faces); VectorF& v_normals = m_values; v_normals = VectorF::Zero(dim * num_vertices); for (size_t i=0; i<num_faces; i++) { VectorI face = mesh.get_face(i); assert(face.size() == vertex_per_face); VectorF face_normal = normals.segment(i*dim, dim); Float face_area = areas[i]; for (size_t j=0; j<vertex_per_face; j++) { size_t vi = face[j]; v_normals.segment(vi*dim, dim) += face_normal * face_area; } } for (size_t i=0; i<num_vertices; i++) { VectorF n = v_normals.segment(dim*i, dim); Float n_len = n.norm(); if (n_len > 0.0) n /= n_len; v_normals.segment(dim*i, dim) = n; } }