| 53 | } |
| 54 | |
| 55 | void VertexNormalAttribute::compute_vertex_normals_from_edge(Mesh& mesh) { |
| 56 | const size_t dim = mesh.get_dim(); |
| 57 | assert(dim == 2); |
| 58 | const size_t num_vertices = mesh.get_num_vertices(); |
| 59 | const size_t num_faces = mesh.get_num_faces(); |
| 60 | const size_t vertex_per_face = mesh.get_vertex_per_face(); |
| 61 | |
| 62 | const VectorF& normals = get_attribute(mesh, "face_normal"); |
| 63 | |
| 64 | VectorF& v_normals = m_values; |
| 65 | v_normals = VectorF::Zero(dim * num_vertices); |
| 66 | |
| 67 | for (size_t i=0; i<num_faces; i++) { |
| 68 | VectorI face = mesh.get_face(i); |
| 69 | for (size_t j=0; j<vertex_per_face; j++) { |
| 70 | size_t prev = (j-1+vertex_per_face) % vertex_per_face; |
| 71 | size_t next = (j+1) % vertex_per_face; |
| 72 | Vector2F prev_edge = mesh.get_vertex(face[j]) - |
| 73 | mesh.get_vertex(face[prev]); |
| 74 | Vector2F next_edge = mesh.get_vertex(face[next]) - |
| 75 | mesh.get_vertex(face[j]); |
| 76 | |
| 77 | Vector3F n = normals.segment(i*3, 3); |
| 78 | Vector3F e1(prev_edge[0], prev_edge[1], 0); |
| 79 | Vector3F e2(next_edge[0], next_edge[1], 0); |
| 80 | Vector3F n1 = e1.cross(n); |
| 81 | Vector3F n2 = e2.cross(n); |
| 82 | |
| 83 | v_normals.segment(face[j]*dim, dim) += (n1 + n2).segment(0, dim); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | for (size_t i=0; i<num_vertices; i++) { |
| 88 | Float norm = v_normals.segment(i*dim, dim).norm(); |
| 89 | if (norm > 1e-6) { |
| 90 | v_normals.segment(i*dim, dim) /= norm; |
| 91 | } |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | const VectorF& VertexNormalAttribute::get_attribute(Mesh& mesh, const std::string& attr_name) { |
| 96 | if (!mesh.has_attribute(attr_name)) { |
nothing calls this directly
no test coverage detected