14#include <lagrange/Attribute.h>
15#include <lagrange/SurfaceMesh.h>
16#include <lagrange/attribute_names.h>
17#include <lagrange/utils/assert.h>
18#include <lagrange/views.h>
49template <
typename Scalar,
typename Index>
53 const std::vector<Eigen::Transform<Scalar, 3, Eigen::TransformTraits::Affine>>& transforms,
54 const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>& weights,
55 const Eigen::Matrix<Scalar, Eigen::Dynamic, 1>& weight_complement = {})
60 (weight_complement.rows() == 0) || (weight_complement.rows() == mesh.get_num_vertices()));
62 const Index num_vertices = mesh.get_num_vertices();
63 const size_t num_handles = transforms.size();
69 for (Index v = 0; v < num_vertices; ++v) {
70 const Eigen::Matrix<Scalar, 3, 1> orig = original_view.row(v);
72 for (
size_t h = 0; h < num_handles; ++h) {
73 Scalar weight = weights(v, h);
75 verts.row(v) += weight * (transforms[h] * orig);
79 if (weight_complement.rows() > 0 && weight_complement(v) > 0) {
80 verts.row(v) += (weight_complement(v) * orig);
81 weight_sum += weight_complement(v);
84 verts.row(v) /= weight_sum;
97template <
typename Scalar,
typename Index>
101 const std::vector<Eigen::Transform<Scalar, 3, Eigen::TransformTraits::Affine>>& transforms)
106 auto& weight_attr = mesh.template get_attribute<Scalar>(weight_id);
108 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> weights =
matrix_view(weight_attr);
113template <
typename Scalar,
typename Index>
120 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>
weights;
126 Eigen::Matrix<Index, Eigen::Dynamic, Eigen::Dynamic>
indices;
140template <
typename Scalar,
typename Index>
142 const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>& weights,
144 const Eigen::Matrix<Scalar, Eigen::Dynamic, 1>& weight_complement =
145 Eigen::Matrix<Scalar, Eigen::Dynamic, 1>())
147 const Index num_vertices = Index(weights.rows());
148 const Index num_handles = Index(weights.cols());
149 Index num_implicit_handle = 0;
152 if (weight_complement.rows() > 0 &&
153 weight_complement.maxCoeff() > std::numeric_limits<Scalar>::epsilon()) {
156 num_implicit_handle = 1;
160 const Index num_handles_max = Index(n) - num_implicit_handle;
161 const Index num_handles_used = std::min(num_handles, num_handles_max);
165 result.
weights.resize(num_vertices, n);
166 result.
indices.resize(num_vertices, n);
167 if (num_handles < Index(n)) {
173 if (num_handles <= num_handles_max) {
176 for (Index i = 0; i < num_vertices; ++i) {
177 for (Index j = 0; j < num_handles; ++j) {
179 result.
weights(i, j) = weights(i, j);
186 for (Index i = 0; i < num_vertices; ++i) {
187 std::vector<Index> tmp(num_handles);
188 std::iota(tmp.begin(), tmp.end(), 0);
191 tmp.begin() + num_handles_used,
193 [&weights, i](
const Index a,
const Index b) ->
bool {
194 return weights(i, a) > weights(i, b);
197 for (Index j = 0; j < num_handles_used; ++j) {
199 result.
weights(i, j) = weights(i, tmp[j]);
204 if (num_implicit_handle > 0) {
206 for (Index i = 0; i < num_vertices; ++i) {
207 result.
indices(i, num_handles_used) = num_handles_used;
208 result.
weights(i, num_handles_used) = weight_complement(i);
213 if (num_handles > num_handles_max) {
214 for (Index i = 0; i < num_vertices; ++i) {
232template <
typename Scalar,
typename Index,
typename WeightScalar = Scalar>
235 const Eigen::Matrix<WeightScalar, Eigen::Dynamic, Eigen::Dynamic>& weights)
237 return mesh.template create_attribute<WeightScalar>(
242 {weights.data(), size_t(weights.size())});
257 typename WeightScalar =
Scalar,
258 typename WeightIndex = Index>
261 const Eigen::Matrix<WeightScalar, Eigen::Dynamic, Eigen::Dynamic>& weights,
265 auto bone_id = mesh.template create_attribute<WeightIndex>(
269 result.indices.cols(),
270 {result.indices.data(), size_t(result.indices.size())});
272 auto weight_id = mesh.template create_attribute<WeightScalar>(
276 result.weights.cols(),
277 {result.weights.data(), size_t(result.weights.size())});
278 return {bone_id, weight_id};
Derived attribute class that stores the actual information.
Definition Attribute.h:153
A general purpose polygonal mesh class.
Definition SurfaceMesh.h:66
uint32_t AttributeId
Identified to be used to access an attribute.
Definition AttributeFwd.h:73
constexpr AttributeId invalid_attribute_id()
Invalid attribute id.
Definition AttributeFwd.h:76
@ Vector
Mesh attribute can have any number of channels (including 1 channel).
Definition AttributeFwd.h:55
@ Scalar
Mesh attribute must have exactly 1 channel.
Definition AttributeFwd.h:56
@ Vertex
Per-vertex mesh attributes.
Definition AttributeFwd.h:28
ConstRowMatrixView< ValueType > matrix_view(const Attribute< ValueType > &attribute)
Returns a read-only view of a given attribute in the form of an Eigen matrix.
Definition views.cpp:35
RowMatrixView< Scalar > vertex_ref(SurfaceMesh< Scalar, Index > &mesh)
Returns a writable view of the mesh vertices in the form of an Eigen matrix.
Definition views.cpp:150
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:174
nullptr_t, size_t, ptrdiff_t basic_ostream bad_weak_ptr extent, remove_extent, is_array,...
Definition attribute_string_utils.h:21
lagrange::AttributeId weights_to_mesh_attribute(SurfaceMesh< Scalar, Index > &mesh, const Eigen::Matrix< WeightScalar, Eigen::Dynamic, Eigen::Dynamic > &weights)
Imports the weights matrix as weight attributes of the mesh.
Definition skinning.h:233
std::pair< lagrange::AttributeId, lagrange::AttributeId > weights_to_indexed_mesh_attribute(SurfaceMesh< Scalar, Index > &mesh, const Eigen::Matrix< WeightScalar, Eigen::Dynamic, Eigen::Dynamic > &weights, int n)
Imports the weights matrix as indexed weight attributes of the mesh.
Definition skinning.h:259
void skinning_deform(SurfaceMesh< Scalar, Index > &mesh, const lagrange::Attribute< Scalar > &original_vertices, const std::vector< Eigen::Transform< Scalar, 3, Eigen::TransformTraits::Affine > > &transforms, const Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > &weights, const Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > &weight_complement={})
Performs linear blend skinning deformation on a mesh.
Definition skinning.h:50
SkinningExtractNResult< Scalar, Index > skinning_extract_n(const Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > &weights, int n, const Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > &weight_complement=Eigen::Matrix< Scalar, Eigen::Dynamic, 1 >())
From a weight matrix |V| x |H|, constructs a weight matrix |V| x n, where n is an arbitrary contraint...
Definition skinning.h:141
static constexpr std::string_view indexed_weight
Indexed skinning weights, with a fixed number (typically 4) specified for each vertex.
Definition attribute_names.h:69
static constexpr std::string_view weight
Skinning weights, with all joints specified for each vertex.
Definition attribute_names.h:63
static constexpr std::string_view indexed_joint
Indexed skinning index, with a fixed number (typically 4) specified for each vertex.
Definition attribute_names.h:75