1#include "dynamic_mesh.h"
3#include <cgv/math/ftransform.h>
4#include <cgv/math/inv.h>
15 blend_shapes.push_back(bs);
16 return uint32_t(blend_shapes.size() - 1);
21 blend_shape_data.push_back(d);
26 blend_shape_indices.push_back(i);
31 const auto& bs = blend_shapes[bi];
33 case blend_shape_mode::direct:
37 case blend_shape_mode::indexed:
38 for (
idx_type i = bs.blend_shape_index_range[0]; i < bs.blend_shape_index_range[1]; ++i)
39 if (blend_shape_indices[i] == vi)
42 case blend_shape_mode::range_indexed:
43 for (
idx_type i = bs.blend_shape_index_range[0]; i < bs.blend_shape_index_range[1]; i+=2)
44 if (blend_shape_indices[i] <= vi && vi < blend_shape_indices[i+1])
53 const auto& bs = blend_shapes[bi];
55 case blend_shape_mode::direct:
56 return blend_shape_data[bi*this->get_nr_positions()+vi];
57 case blend_shape_mode::indexed:
58 for (
idx_type i = bs.blend_shape_index_range[0]; i < bs.blend_shape_index_range[1]; ++i)
59 if (blend_shape_indices[i] == vi)
60 return blend_shape_data[i];
62 case blend_shape_mode::range_indexed:
63 for (
idx_type off = 0, i = bs.blend_shape_index_range[0]; i < bs.blend_shape_index_range[1];
64 off += blend_shape_indices[i+1]-blend_shape_indices[i], i+=2)
65 if (blend_shape_indices[i] <= vi && vi < blend_shape_indices[i+1])
66 return blend_shape_data[off + vi- blend_shape_indices[i]];
74 return blend_shapes.size();
82void dynamic_mesh<T>::begin_vertex_weight_vertex()
84 vertex_weight_index_begins.push_back(uint32_t(vertex_weight_data.size()));
89 switch (weight_mode) {
90 case vertex_weight_mode::dense:
91 return uint32_t(vi * get_nr_joints());
92 case vertex_weight_mode::sparse:
93 return vertex_weight_index_begins[vi];
94 case vertex_weight_mode::fixed:
95 return uint32_t(vi * max_nr_weights_per_vertex);
102 switch (weight_mode) {
103 case vertex_weight_mode::dense:
104 return uint32_t((vi+1)*get_nr_joints());
105 case vertex_weight_mode::sparse:
106 return uint32_t(vi >= vertex_weight_index_begins.size() ? vertex_weight_data.size() : vertex_weight_index_begins[vi]);
107 case vertex_weight_mode::fixed:
108 return uint32_t((vi+1)*max_nr_weights_per_vertex);
115 switch (weight_mode) {
116 case vertex_weight_mode::dense:
117 return vertex_weight_data[vi * get_nr_joints() + ji];
119 for (
idx_type i = vertex_weight_begin(vi); i < vertex_weight_end(vi); ++i)
120 if (vertex_weight_indices[i] == ji)
121 return vertex_weight_data[i];
130 vertex_weight_data.push_back(w);
135 vertex_weight_indices.push_back(i);
140 return vertex_weight_data.size();
143size_t dynamic_mesh<T>::get_nr_vertex_weight_indices()
const
145 return vertex_weight_indices.size();
154 const vec3_type& translation,
const std::vector<vec3_type>& target_spin_vectors)
const
156 std::vector<mat3_type> target_rotations;
157 for (
const auto& sv : target_spin_vectors)
158 target_rotations.push_back(cgv::math::rotate3s<T>(sv));
159 return compute_joint_transformations(reference_joint_locations, translation, target_rotations);
163 const vec3_type& translation,
const std::vector<mat3_type>& target_rotations)
const
166 std::vector<mat4_type> Is, Ts;
167 mat4_type I = cgv::math::identity4<float>();
169 t = reference_joint_locations.front();
171 Ts.push_back(pose4(target_rotations.front(), t + translation));
173 for (ji = 1; ji < target_rotations.size(); ++ji) {
174 t = reference_joint_locations[ji] - reference_joint_locations[joint_parents[ji]];
176 Ts.push_back(pose4(target_rotations[ji], t));
179 for (ji = 1; ji < target_rotations.size(); ++ji) {
180 Is[ji] = Is[joint_parents[ji]] * Is[ji];
181 Ts[ji] = Ts[joint_parents[ji]] * Ts[ji];
184 for (ji = 0; ji < target_rotations.size(); ++ji)
185 Ts[ji] = Ts[ji] * inv(Is[ji]);
195 this->positions = reference_positions;
196 if (use_parallel_implementation) {
200 std::vector<const vec3_type*> bs_ptrs;
201 int n = this->get_nr_positions();
202 for (
size_t bi = blend_shape_offset; bi < weights.size() + blend_shape_offset; ++bi) {
203 const auto& bs = blend_shapes[bi];
204 assert(bs.mode == blend_shape_mode::direct);
205 assert(bs.blend_shape_data_range[1] - bs.blend_shape_data_range[0] == n);
206 bs_ptrs.push_back(&blend_shape_data[bs.blend_shape_data_range[0]]);
209#pragma omp parallel for
210 for (
int vi = 0; vi < n; ++vi) {
212 for (
int wi = 0; wi < weights.size(); ++wi)
213 p += weights[wi]*bs_ptrs[wi][vi];
214 this->position(vi) += p;
218 for (
idx_type bi = blend_shape_offset, wi = 0; wi < weights.size(); ++wi, ++bi) {
219 const auto& bs = blend_shapes[bi];
221 case blend_shape_mode::direct:
222 for (
int j=0, i = bs.blend_shape_data_range[0]; i < int(bs.blend_shape_data_range[1]); ++i, ++j)
223 this->positions[j] += weights[wi] * blend_shape_data[i];
225 case blend_shape_mode::indexed:
226 for (uint32_t i = bs.blend_shape_data_range[0], j = bs.blend_shape_index_range[0]; i < bs.blend_shape_data_range[1]; ++i, ++j)
227 this->positions[blend_shape_indices[j]] += weights[wi] * blend_shape_data[i];
229 case blend_shape_mode::range_indexed:
230 for (uint32_t i = bs.blend_shape_data_range[0], j = bs.blend_shape_index_range[0]; j < bs.blend_shape_index_range[1]; j += 2)
231 for (uint32_t k = blend_shape_indices[j]; k < blend_shape_indices[j + 1]; ++k, ++i)
232 this->positions[k] += weights[wi] * blend_shape_data[i];
241 return intermediate_positions;
247 return joint_parents;
252 return joint_parents;
257 reference_positions = this->positions;
262 intermediate_positions = this->positions;
267 this->positions = intermediate_positions;
273 std::vector<vec3_type> tmp;
274 if (mode == lbs_source_mode::position)
275 tmp = this->positions;
276 const std::vector<vec3_type>& P = mode == lbs_source_mode::position ? tmp : (
277 mode == lbs_source_mode::intermediate ? intermediate_positions : reference_positions);
278 switch (weight_mode) {
279 case vertex_weight_mode::dense:
280 for (
size_t pi = 0, wi = 0; pi < P.size(); ++pi) {
283 for (
unsigned ji = 0; ji < joint_parents.size(); ++ji, ++wi)
284 q += vertex_weight_data[wi] * (joint_matrices[ji] * p);
288 case vertex_weight_mode::sparse:
289 for (
size_t pi = 0; pi < P.size(); ++pi) {
292 size_t beg = vertex_weight_index_begins[pi];
293 size_t end = pi+1 < P.size() ? vertex_weight_index_begins[pi+1] : vertex_weight_indices.size();
294 for (
size_t wi = beg; wi < end; ++wi)
295 q += vertex_weight_data[wi] * (joint_matrices[vertex_weight_indices[wi]] * p);
299 case vertex_weight_mode::fixed:
300 for (
size_t pi = 0; pi < P.size(); ++pi) {
303 size_t beg = vertex_weight_index_begins[pi];
304 size_t end = pi + 1 < P.size() ? vertex_weight_index_begins[pi + 1] : vertex_weight_indices.size();
305 for (
size_t wi = beg; wi < end; ++wi)
306 q += vertex_weight_data[wi] * (joint_matrices[vertex_weight_indices[wi]] * p);
complete implementation of method actions that only call one method when entering a node
fvec< T, N > & col(unsigned j)
reference a column of the matrix as a vector
A vector with zero based index.