[Bf-blender-cvs] [439a6ac27b1] rigid_deform: use namespace
Jacques Lucke
noreply at git.blender.org
Thu Jan 31 19:56:03 CET 2019
Commit: 439a6ac27b1dfe0d09b729dc2ab3ab9bf413da1a
Author: Jacques Lucke
Date: Tue Jan 29 20:20:14 2019 +0100
Branches: rigid_deform
https://developer.blender.org/rB439a6ac27b1dfe0d09b729dc2ab3ab9bf413da1a
use namespace
===================================================================
M source/blender/modifiers/intern/MOD_rigiddeform_system.cc
M source/blender/modifiers/intern/MOD_rigiddeform_system.hpp
M source/blender/modifiers/intern/MOD_rigiddeform_system_wrapper.cc
===================================================================
diff --git a/source/blender/modifiers/intern/MOD_rigiddeform_system.cc b/source/blender/modifiers/intern/MOD_rigiddeform_system.cc
index 3ae6926f477..e3a2825c412 100644
--- a/source/blender/modifiers/intern/MOD_rigiddeform_system.cc
+++ b/source/blender/modifiers/intern/MOD_rigiddeform_system.cc
@@ -26,316 +26,320 @@
#include "MOD_rigiddeform_system.hpp"
#include "BLI_math.h"
-/* expects the anchor indices to be sorted */
-/* (6, [1, 4]) -> [0, 2, 3, 5, 1, 4] */
-static std::vector<uint> sort_vertices_by_anchors(const std::vector<uint> &anchors, uint vertex_amount)
-{
- std::vector<uint> sorted;
-
- int anchor_index = 0;
- for (int i = 0; i < vertex_amount; i++) {
- if (anchor_index < anchors.size() && i == anchors[anchor_index]) {
- anchor_index++;
- continue;
+namespace RigidDeform {
+
+ /* expects the anchor indices to be sorted */
+ /* (6, [1, 4]) -> [0, 2, 3, 5, 1, 4] */
+ static std::vector<uint> sort_vertices_by_anchors(const std::vector<uint> &anchors, uint vertex_amount)
+ {
+ std::vector<uint> sorted;
+
+ int anchor_index = 0;
+ for (int i = 0; i < vertex_amount; i++) {
+ if (anchor_index < anchors.size() && i == anchors[anchor_index]) {
+ anchor_index++;
+ continue;
+ }
+ sorted.push_back(i);
}
- sorted.push_back(i);
+
+ sorted.insert(sorted.end(), anchors.begin(), anchors.end());
+ return sorted;
}
- sorted.insert(sorted.end(), anchors.begin(), anchors.end());
- return sorted;
-}
-
-/* Build Laplace Matrix
- ******************************************/
-
-static std::vector<double> calc_total_weight_per_vertex(
- const std::vector<WeightedEdge> &edges,
- uint vertex_amount)
-{
- std::vector<double> total_weights(vertex_amount, 0);
- for (WeightedEdge edge : edges) {
- total_weights[edge.v1] += edge.weight;
- total_weights[edge.v2] += edge.weight;
+ /* Build Laplace Matrix
+ ******************************************/
+
+ static std::vector<double> calc_total_weight_per_vertex(
+ const std::vector<WeightedEdge> &edges,
+ uint vertex_amount)
+ {
+ std::vector<double> total_weights(vertex_amount, 0);
+ for (WeightedEdge edge : edges) {
+ total_weights[edge.v1] += edge.weight;
+ total_weights[edge.v2] += edge.weight;
+ }
+ return total_weights;
}
- return total_weights;
-}
-
-static std::array<double, 3> triangle_corner_angles(
- Eigen::Vector3d v1, Eigen::Vector3d v2, Eigen::Vector3d v3)
-{
- Eigen::Vector3f v1_f = v1.cast<float>();
- Eigen::Vector3f v2_f = v2.cast<float>();
- Eigen::Vector3f v3_f = v3.cast<float>();
-
- float angles[3];
- angle_tri_v3(angles, v1_f.data(), v2_f.data(), v3_f.data());
- return {angles[0], angles[1], angles[2]};
-}
-
-static inline double cotan(double angle)
-{
- return std::cos(angle) / std::sin(angle);
-}
-
-static std::vector<WeightedEdge> calculate_cotan_edge_weights(
- const Vectors &positions,
- const std::vector<std::array<uint, 3>> &triangles)
-{
- std::vector<WeightedEdge> edges;
-
- for (auto verts : triangles) {
- std::array<double, 3> angles = triangle_corner_angles(
- positions[verts[0]],
- positions[verts[1]],
- positions[verts[2]]);
-
- double w1 = (angles[0] > 0.0001) ? cotan(angles[0]) / 2.0 : 1.0;
- double w2 = (angles[0] > 0.0001) ? cotan(angles[1]) / 2.0 : 1.0;
- double w3 = (angles[0] > 0.0001) ? cotan(angles[2]) / 2.0 : 1.0;
-
- if (w1 > 0) edges.push_back(WeightedEdge(verts[1], verts[2], w1));
- if (w2 > 0) edges.push_back(WeightedEdge(verts[0], verts[2], w2));
- if (w3 > 0) edges.push_back(WeightedEdge(verts[0], verts[1], w3));
+
+ static std::array<double, 3> triangle_corner_angles(
+ Eigen::Vector3d v1, Eigen::Vector3d v2, Eigen::Vector3d v3)
+ {
+ Eigen::Vector3f v1_f = v1.cast<float>();
+ Eigen::Vector3f v2_f = v2.cast<float>();
+ Eigen::Vector3f v3_f = v3.cast<float>();
+
+ float angles[3];
+ angle_tri_v3(angles, v1_f.data(), v2_f.data(), v3_f.data());
+ return {angles[0], angles[1], angles[2]};
}
- return edges;
-}
+ static inline double cotan(double angle)
+ {
+ return std::cos(angle) / std::sin(angle);
+ }
-static std::vector<Triplet> get_laplace_matrix_triplets(
- uint vertex_amount, std::vector<WeightedEdge> &edges)
-{
- auto total_weights = calc_total_weight_per_vertex(edges, vertex_amount);
+ static std::vector<WeightedEdge> calculate_cotan_edge_weights(
+ const Vectors &positions,
+ const std::vector<std::array<uint, 3>> &triangles)
+ {
+ std::vector<WeightedEdge> edges;
+
+ for (auto verts : triangles) {
+ std::array<double, 3> angles = triangle_corner_angles(
+ positions[verts[0]],
+ positions[verts[1]],
+ positions[verts[2]]);
+
+ double w1 = (angles[0] > 0.0001) ? cotan(angles[0]) / 2.0 : 1.0;
+ double w2 = (angles[0] > 0.0001) ? cotan(angles[1]) / 2.0 : 1.0;
+ double w3 = (angles[0] > 0.0001) ? cotan(angles[2]) / 2.0 : 1.0;
+
+ if (w1 > 0) edges.push_back(WeightedEdge(verts[1], verts[2], w1));
+ if (w2 > 0) edges.push_back(WeightedEdge(verts[0], verts[2], w2));
+ if (w3 > 0) edges.push_back(WeightedEdge(verts[0], verts[1], w3));
+ }
+
+ return edges;
+ }
+
+ static std::vector<Triplet> get_laplace_matrix_triplets(
+ uint vertex_amount, std::vector<WeightedEdge> &edges)
+ {
+ auto total_weights = calc_total_weight_per_vertex(edges, vertex_amount);
+
+ std::vector<Triplet> triplets;
+
+ for (int i = 0; i < vertex_amount; i++) {
+ triplets.push_back(Triplet(i, i, total_weights[i]));
+ }
- std::vector<Triplet> triplets;
+ for (WeightedEdge edge : edges) {
+ if (edge.weight == 0) continue;
- for (int i = 0; i < vertex_amount; i++) {
- triplets.push_back(Triplet(i, i, total_weights[i]));
+ triplets.push_back(Triplet(edge.v1, edge.v2, -edge.weight));
+ triplets.push_back(Triplet(edge.v2, edge.v1, -edge.weight));
+ }
+
+ return triplets;
}
- for (WeightedEdge edge : edges) {
- if (edge.weight == 0) continue;
+ ReorderData::ReorderData(const std::vector<uint> &anchors, uint vertex_amount)
+ {
+ m_new_to_orig = sort_vertices_by_anchors(anchors, vertex_amount);
+
+ m_orig_to_new.resize(vertex_amount);
+ for (int i = 0; i < vertex_amount; i++) {
+ m_orig_to_new[m_new_to_orig[i]] = i;
+ }
- triplets.push_back(Triplet(edge.v1, edge.v2, -edge.weight));
- triplets.push_back(Triplet(edge.v2, edge.v1, -edge.weight));
+ this->m_inner_amount = vertex_amount - anchors.size();
}
- return triplets;
-}
-ReorderData::ReorderData(const std::vector<uint> &anchors, uint vertex_amount)
-{
- m_new_to_orig = sort_vertices_by_anchors(anchors, vertex_amount);
+ /* Optimize Rotations
+ *********************************************/
- m_orig_to_new.resize(vertex_amount);
- for (int i = 0; i < vertex_amount; i++) {
- m_orig_to_new[m_new_to_orig[i]] = i;
+ static inline Eigen::Vector3d get_position(
+ uint index,
+ const ReorderData &order,
+ const Vectors &anchor_positions,
+ const Vectors &inner_positions)
+ {
+ if (order.is_inner__orig(index)) {
+ return inner_positions[order.to_new(index)];
+ }
+ else {
+ return anchor_positions[order.to_new_anchor(index)];
+ }
}
- this->m_inner_amount = vertex_amount - anchors.size();
-}
+ std::vector<Eigen::Matrix3d> RigidDeformSystem::optimize_rotations(
+ const Vectors &anchor_positions,
+ const Vectors &new_inner_positions)
+ {
+ std::vector<Eigen::Matrix3d> S(this->vertex_amount());
+ for (uint i = 0; i < S.size(); i++) S[i].setZero();
+ for (WeightedEdge edge : m_edges) {
+ uint v1 = edge.v1;
+ uint v2 = edge.v2;
-/* Optimize Rotations
- *********************************************/
+ Eigen::Vector3d edge_old = m_initial_positions[v1] - m_initial_positions[v2];
-static inline Eigen::Vector3d get_position(
- uint index,
- const ReorderData &order,
- const Vectors &anchor_positions,
- const Vectors &inner_positions)
-{
- if (order.is_inner__orig(index)) {
- return inner_positions[order.to_new(index)];
- }
- else {
- return anchor_positions[order.to_new_anchor(index)];
+ Eigen::Vector3d edge_new_start =
+ get_position(v1, m_order, anchor_positions, new_inner_positions);
+ Eigen::Vector3d edge_new_end =
+ get_position(v2, m_order, anchor_positions, new_inner_positions);
+
+ Eigen::RowVector3d edge_new = edge_new_start - edge_new_end;
+
+ Eigen::Matrix3d mat = edge.weight * edge_old * edge_new;
+ S[v1] += mat;
+ S[v2] += mat;
+ }
+
+ std::vector<Eigen::Matrix3d> R(S.size());
+ for (int i = 0; i < S.size(); i++) {
+ Eigen::JacobiSVD<Eigen::Matrix3d> svd(S[i], Eigen::ComputeFullU | Eigen::ComputeFullV);
+ R[i] = svd.matrixV() * svd.matrixU().transpose();
+ if (R[i].determinant() < 0) {
+ Eigen::Matrix3d U = svd.matrixU();
+ U.col(2) = -U.col(2);
+ R[i] = svd.matrixV() * U.transpose();
+ }
+ }
+
+ return R;
}
-}
-std::vector<Eigen::Matrix3d> RigidDeformSystem::optimize_rotations(
- const Vectors &anchor_positions,
- const Vectors &new_inner_positions)
-{
- std::vector<Eigen::Matrix3d> S(this->vertex_amount());
- for (uint i = 0; i < S.size(); i++) S[i].setZero();
- for (WeightedEdge edge : m_edges) {
- uint v1 = edge.v1;
- uint v2 = edge.v2;
+ /* Optimize Inner Vertex Positions
+ **********************************************/
+
+ Vectors RigidDeformSystem::optimize_inner_positions(
+ const Vectors &anchor_positions,
+ const std::vector<Eigen::Matrix3d> &rotations)
+ {
+ Vectors new_inner_diffs = this->calculate_new_inner_diffs(rotations);
+ return this->solve_for_new_inner_positions(anchor_positions, new_inner_diffs);
+ }
+
+ Vectors RigidDeformSystem::calculate_new_inner_diffs(
+ const std::vector<Eigen::Matrix3d> &rotations)
+ {
+ Vectors new_inner_diffs(m_order.inner_amount());
+ new_inner_diffs.set_zero();
- Eigen::Vector3d edge_old = m_initial_positions[v1] - m_initial_positions[v2];
+ for (WeightedEdge edge : m_edges) {
+ uint v1 = edge.v1;
+ uint v2 = edge.v2;
+ bool v1_is_inner = m_order.is_inner__orig(v1);
+ bool v2_is_inner = m_order.is_inner__orig(v2);
+ if (!(v1_is_inner || v2_is_inner)) continue;
- Eigen::Vector3d edge_new_start =
- get_position(v1, m_order, anchor_positions, new_inner_positions);
- Eigen::Vector3d edge_new_end =
- get_position(v2, m_order, anchor_positions, new_inner_positions);
+ Eigen::Vector3d old_edge = m_initial_positions[v1] - m_initial_positions[v2];
+
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list