Add this file

This commit is contained in:
Joseph Eagar 2021-03-26 14:23:31 -07:00
parent 215c346017
commit 7be027075f
1 changed files with 193 additions and 0 deletions

View File

@ -0,0 +1,193 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2021 by Joseph Eagar
* All rights reserved.
* Implements curvature analysis for sculpt tools
*/
/** \file
* \ingroup edsculpt
*/
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_dial_2d.h"
#include "BLI_ghash.h"
#include "BLI_gsqueue.h"
#include "BLI_hash.h"
#include "BLI_math.h"
#include "BLI_math_color_blend.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
#include "PIL_time.h"
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_brush.h"
#include "BKE_ccg.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_image.h"
#include "BKE_kelvinlet.h"
#include "BKE_key.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_mirror.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_pbvh.h"
#include "BKE_pointcache.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_subdiv_ccg.h"
#include "BKE_subsurf.h"
#include "DEG_depsgraph.h"
#include "IMB_colormanagement.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
#include "WM_api.h"
#include "WM_message.h"
#include "WM_toolsystem.h"
#include "WM_types.h"
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
#include "ED_space_api.h"
#include "ED_view3d.h"
#include "paint_intern.h"
#include "sculpt_intern.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "bmesh.h"
#include "bmesh_tools.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
/*
If you're working with uniform triangle tesselations, the math for
calculating principle curvatures reduces to doing an eigen decomposition
of the smoothed normal covariance matrix.
The normal covariance matrix is just:
nx*nx nx*ny nx*nz
ny*nx ny*ny ny*nz
nz*nx nz*ny nz*nz
To find principle curvatures, simply subtract neighboring covariance matrices.
You can do this over any number of neighborhood rings to get more accurate result
*/
BLI_INLINE void normal_covariance(float mat[3][3], float no[3])
{
mat[0][0] = no[0] * no[0];
mat[0][1] = no[0] * no[1];
mat[0][2] = no[0] * no[2];
mat[1][0] = no[1] * no[0];
mat[1][1] = no[1] * no[1];
mat[1][2] = no[1] * no[2];
mat[2][0] = no[2] * no[0];
mat[2][1] = no[2] * no[1];
mat[2][2] = no[2] * no[2];
}
bool SCULPT_calc_principle_curvatures(SculptSession *ss,
SculptVertRef vertex,
SculptCurvatureData *out)
{
SculptVertexNeighborIter ni;
float nmat[3][3], nmat2[3][3];
float no[3], no2[3];
memset(out, 0, sizeof(SculptCurvatureData));
SCULPT_vertex_normal_get(ss, vertex, no);
normal_covariance(nmat, no);
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
SCULPT_vertex_normal_get(ss, ni.vertex, no2);
sub_v3_v3(no2, no);
normal_covariance(nmat2, no2);
add_m3_m3m3(nmat, nmat, nmat2);
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
if (true || !BLI_eigen_solve_selfadjoint_m3(nmat, out->ks, out->principle)) {
//do simple power solve in one direction
float t[3];
float t2[3];
SCULPT_vertex_normal_get(ss, vertex, no);
copy_v3_v3(t, no);
for (int i = 0; i < 15; i++) {
if (i > 0) {
normalize_v3(t);
if (i > 1 && len_squared_v3v3(t, t2) < 0.0001) {
break;
}
copy_v3_v3(t2, t);
}
mul_m3_v3(nmat, t);
}
out->ks[1] = normalize_v3(t);
copy_v3_v3(out->principle[1], t);
cross_v3_v3v3(out->principle[0], out->principle[1], no);
normalize_v3(out->principle[0]);
}
return true;
}