| 143 | } |
| 144 | |
| 145 | void PeriodicInflator::update_shape_velocities() { |
| 146 | if (!m_with_shape_velocities) return; |
| 147 | |
| 148 | const size_t num_vertices = m_vertices.rows(); |
| 149 | const size_t num_phantom_vertices = m_phantom_vertices.rows(); |
| 150 | VectorF squared_dists; |
| 151 | VectorI closest_face_indices; |
| 152 | MatrixFr closest_pts; |
| 153 | m_tree->lookup( |
| 154 | m_vertices, squared_dists, closest_face_indices, closest_pts); |
| 155 | |
| 156 | typedef Eigen::Triplet<Float> T; |
| 157 | std::vector<T> entries; |
| 158 | assert(squared_dists.size() == num_vertices); |
| 159 | for (size_t i=0; i<num_vertices; i++) { |
| 160 | Float dist = squared_dists[i]; |
| 161 | if (dist > 1e-6) continue; |
| 162 | size_t face_idx = closest_face_indices[i]; |
| 163 | const VectorI& f = m_phantom_faces.row(face_idx); |
| 164 | Vector3F weight = compute_barycentric_coord( |
| 165 | closest_pts.row(i), |
| 166 | m_phantom_vertices.row(f[0]), |
| 167 | m_phantom_vertices.row(f[1]), |
| 168 | m_phantom_vertices.row(f[2])); |
| 169 | |
| 170 | entries.push_back(T(i, f[0], weight[0])); |
| 171 | entries.push_back(T(i, f[1], weight[1])); |
| 172 | entries.push_back(T(i, f[2], weight[2])); |
| 173 | } |
| 174 | |
| 175 | ZSparseMatrix transform(num_vertices, num_phantom_vertices); |
| 176 | transform.setFromTriplets(entries.begin(), entries.end()); |
| 177 | |
| 178 | for (auto& shape_velocity :m_shape_velocities) { |
| 179 | shape_velocity = transform * shape_velocity; |
| 180 | } |
| 181 | } |
| 182 |
nothing calls this directly
no test coverage detected