Skip to content

Commit 55942f5

Browse files
sergeyvfxSergey Sharybin
authored andcommitted
Armature: Switch envelope weight calculation to the new subdiv code
There should be minimal user-measurable changes since the old algorithm is not the same as OpenSubdiv. For example now creases (both edge and vertex ones) are properly supported. This allows to have less dependencies on the old subdivision surface code which ideally will be removed soon. Pull Request: https://projects.blender.org/blender/blender/pulls/143712
1 parent d6cc9a0 commit 55942f5

File tree

3 files changed

+57
-9
lines changed

3 files changed

+57
-9
lines changed

source/blender/blenkernel/BKE_subdiv_mesh.hh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,11 @@ float3 mesh_interpolate_position_on_edge(Span<float3> coarse_positions,
4545
bool is_simple,
4646
float u);
4747

48+
/**
49+
* Calculate positions position of the given mesh vertices at the limit surface of the mesh.
50+
*
51+
* The limit_positions is to be sized at exactly the number of the base mesh vertices.
52+
*/
53+
void calculate_limit_positions(Mesh *mesh, MutableSpan<float3> limit_positions);
54+
4855
} // namespace blender::bke::subdiv

source/blender/blenkernel/intern/subdiv_mesh.cc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "BKE_mesh.hh"
2121
#include "BKE_mesh_mapping.hh"
2222
#include "BKE_subdiv.hh"
23+
#include "BKE_subdiv_deform.hh"
2324
#include "BKE_subdiv_eval.hh"
2425
#include "BKE_subdiv_foreach.hh"
2526
#include "BKE_subdiv_mesh.hh"
@@ -1246,4 +1247,35 @@ Mesh *subdiv_to_mesh(Subdiv *subdiv, const ToMeshSettings *settings, const Mesh
12461247

12471248
/** \} */
12481249

1250+
/* -------------------------------------------------------------------- */
1251+
/** \name Limit surface
1252+
* \{ */
1253+
1254+
void calculate_limit_positions(Mesh *mesh, MutableSpan<float3> limit_positions)
1255+
{
1256+
BLI_assert(mesh->verts_num == limit_positions.size());
1257+
1258+
limit_positions.copy_from(mesh->vert_positions());
1259+
1260+
Settings settings{};
1261+
settings.is_simple = false;
1262+
settings.is_adaptive = true;
1263+
settings.level = 1;
1264+
settings.use_creases = true;
1265+
1266+
/* Default subdivision surface modifier settings:
1267+
* - UV Smooth:Keep Corners.
1268+
* - BoundarySmooth: All. */
1269+
settings.vtx_boundary_interpolation = SUBDIV_VTX_BOUNDARY_EDGE_ONLY;
1270+
settings.fvar_linear_interpolation = SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_AND_JUNCTIONS;
1271+
1272+
Subdiv *subdiv = update_from_mesh(nullptr, &settings, mesh);
1273+
if (subdiv) {
1274+
deform_coarse_vertices(subdiv, mesh, limit_positions);
1275+
free(subdiv);
1276+
}
1277+
}
1278+
1279+
/** \} */
1280+
12491281
} // namespace blender::bke::subdiv

source/blender/editors/armature/armature_skinning.cc

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "BKE_object.hh"
2828
#include "BKE_object_deform.h"
2929
#include "BKE_report.hh"
30+
#include "BKE_subdiv_mesh.hh"
3031
#include "BKE_subsurf.hh"
3132

3233
#include "DEG_depsgraph.hh"
@@ -199,7 +200,7 @@ static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
199200

200201
static void envelope_bone_weighting(Object *ob,
201202
Mesh *mesh,
202-
float (*verts)[3],
203+
const blender::Span<blender::float3> verts,
203204
int numbones,
204205
Bone **bonelist,
205206
bDeformGroup **dgrouplist,
@@ -298,7 +299,8 @@ static void add_verts_to_dgroups(ReportList *reports,
298299
bPoseChannel *pchan;
299300
Mesh *mesh;
300301
Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = nullptr;
301-
float(*root)[3], (*tip)[3], (*verts)[3];
302+
float(*root)[3], (*tip)[3];
303+
blender::Array<blender::float3> verts;
302304
bool *selected;
303305
int numbones, vertsfilled = 0, segments = 0;
304306
const bool wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
@@ -412,23 +414,23 @@ static void add_verts_to_dgroups(ReportList *reports,
412414

413415
/* create verts */
414416
mesh = static_cast<Mesh *>(ob->data);
415-
verts = static_cast<float(*)[3]>(
416-
MEM_callocN(mesh->verts_num * sizeof(*verts), "closestboneverts"));
417+
verts.reinitialize(mesh->verts_num);
417418

418419
if (wpmode) {
419420
/* if in weight paint mode, use final verts from evaluated mesh */
420421
const Object *ob_eval = DEG_get_evaluated(depsgraph, ob);
421422
const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
422423
if (mesh_eval) {
423-
BKE_mesh_foreach_mapped_vert_coords_get(mesh_eval, verts, mesh->verts_num);
424+
BKE_mesh_foreach_mapped_vert_coords_get(
425+
mesh_eval, reinterpret_cast<float(*)[3]>(verts.data()), mesh->verts_num);
424426
vertsfilled = 1;
425427
}
426428
}
427429
else if (BKE_modifiers_findby_type(ob, eModifierType_Subsurf)) {
428430
/* Is subdivision-surface on? Lets use the verts on the limit surface then.
429431
* = same amount of vertices as mesh, but vertices moved to the
430432
* subdivision-surfaced position, like for 'optimal'. */
431-
subsurf_calculate_limit_positions(mesh, verts);
433+
blender::bke::subdiv::calculate_limit_positions(mesh, verts);
432434
vertsfilled = 1;
433435
}
434436

@@ -445,8 +447,16 @@ static void add_verts_to_dgroups(ReportList *reports,
445447
if (heat) {
446448
const char *error = nullptr;
447449

448-
heat_bone_weighting(
449-
ob, mesh, verts, numbones, dgrouplist, dgroupflip, root, tip, selected, &error);
450+
heat_bone_weighting(ob,
451+
mesh,
452+
reinterpret_cast<float(*)[3]>(verts.data()),
453+
numbones,
454+
dgrouplist,
455+
dgroupflip,
456+
root,
457+
tip,
458+
selected,
459+
&error);
450460
if (error) {
451461
BKE_report(reports, RPT_WARNING, error);
452462
}
@@ -475,7 +485,6 @@ static void add_verts_to_dgroups(ReportList *reports,
475485
MEM_freeN(root);
476486
MEM_freeN(tip);
477487
MEM_freeN(selected);
478-
MEM_freeN(verts);
479488
}
480489

481490
void ED_object_vgroup_calc_from_armature(ReportList *reports,

0 commit comments

Comments
 (0)