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;
    }
}