Files
test2/intern/slim/intern/area_compensation.cpp
Lukasz Czyz 788bc5158e UV: add support for the SLIM unwrapping algorithm
Integrate an existing implementation of the SLIM unwrapping algorithm
into Blender. More info about SLIM here:
https://igl.ethz.ch/projects/slim/

This commit is based on the integration code written by Aurel Gruber
for Blender 2.7x (unfinished and never merged with the main branch).

This commit is based on Aurel's code, rebased and further improved.

Details:

- Unwrap has been moved into a sub-menu,
  slim unwrapping is exposed as: "Minimum Stretch".
- Live unwrap with SLIM refines the solutions using a timer.
- When using SLIM there are options to:
  - Set the number of iterations.
  - Weight the influence using vertex weights.
- SLIM can be disabled using the `WITH_UV_SLIM` build option.

Co-authored-by: Aurel Gruber <aurel.gruber@infix.ch>

Ref !114545
2024-09-21 16:48:53 +10:00

95 lines
2.8 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_slim
*/
#include "BLI_assert.h"
#include <Eigen/Dense>
#include "area_compensation.h"
#include "doublearea.h"
#include "slim.h"
using namespace Eigen;
namespace slim {
static void correct_geometry_size(double surface_area_to_map_area_ratio,
MatrixXd &vertex_positions,
double desired_surface_area_to_map_ration)
{
BLI_assert(surface_area_to_map_area_ratio > 0);
double sqrt_of_ratio = sqrt(surface_area_to_map_area_ratio / desired_surface_area_to_map_ration);
vertex_positions = vertex_positions / sqrt_of_ratio;
}
template<typename VertexPositionType, typename FaceIndicesType>
static double compute_surface_area(const VertexPositionType v, const FaceIndicesType f)
{
Eigen::VectorXd doubled_area_of_triangles;
doublearea(v, f, doubled_area_of_triangles);
double area_of_map = doubled_area_of_triangles.sum() / 2;
return area_of_map;
}
void correct_map_surface_area_if_necessary(SLIMData &slim_data)
{
if (!slim_data.valid) {
return;
}
bool mesh_surface_area_was_corrected = (slim_data.expectedSurfaceAreaOfResultingMap != 0);
int number_of_pinned_vertices = slim_data.b.rows();
bool no_pinned_vertices_exist = number_of_pinned_vertices == 0;
bool needs_area_correction = mesh_surface_area_was_corrected && no_pinned_vertices_exist;
if (!needs_area_correction) {
return;
}
double area_ofresulting_map = compute_surface_area(slim_data.V_o, slim_data.F);
if (!area_ofresulting_map) {
return;
}
double resulting_area_to_expected_area_ratio = area_ofresulting_map /
slim_data.expectedSurfaceAreaOfResultingMap;
double desired_ratio = 1.0;
correct_geometry_size(resulting_area_to_expected_area_ratio, slim_data.V_o, desired_ratio);
}
void correct_mesh_surface_area_if_necessary(SLIMData &slim_data)
{
BLI_assert(slim_data.valid);
int number_of_pinned_vertices = slim_data.b.rows();
bool pinned_vertices_exist = number_of_pinned_vertices > 0;
bool needs_area_correction = slim_data.skipInitialization || pinned_vertices_exist;
if (!needs_area_correction) {
return;
}
double area_of_preinitialized_map = compute_surface_area(slim_data.V_o, slim_data.F);
if (!area_of_preinitialized_map) {
return;
}
if (area_of_preinitialized_map < 0) {
area_of_preinitialized_map *= -1;
}
slim_data.expectedSurfaceAreaOfResultingMap = area_of_preinitialized_map;
double surface_area_of3d_mesh = compute_surface_area(slim_data.V, slim_data.F);
double surface_area_to_map_area_ratio = surface_area_of3d_mesh / area_of_preinitialized_map;
double desired_ratio = 1.0;
correct_geometry_size(surface_area_to_map_area_ratio, slim_data.V, desired_ratio);
}
} // namespace slim