Shrinkwrap: Use OpenSubdiv instead of legacy DerivedMesh
The title says it pretty much all: the shrinkwrap modifier is no longer dependent on the legacy DerivedMesh. The benefits for doing this are: - The DerivedMesh is closer to be removed from the codebase. - Only base vertices are subdivided which could result in better performance and memory usage. - Proper crease support (for edges and vertices). The downside of using OpenSubdiv is that the topology refiner might be expensive to calculate, so for meshes with a lot of extraordinary faces (such as n-gons, triangles) the performance will be worse. Pull Request: https://projects.blender.org/blender/blender/pulls/143706
This commit is contained in:
committed by
Sergey Sharybin
parent
8e9c68f6a3
commit
cda9ff445f
@@ -27,14 +27,16 @@
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_mesh_legacy_derived_mesh.hh"
|
||||
#include "BKE_modifier.hh"
|
||||
#include "BKE_shrinkwrap.hh"
|
||||
#include "BKE_subdiv.hh"
|
||||
|
||||
#include "BKE_deform.hh"
|
||||
#include "BKE_editmesh.hh"
|
||||
#include "BKE_mesh.hh" /* for OMP limits. */
|
||||
#include "BKE_mesh_wrapper.hh"
|
||||
#include "BKE_subdiv.hh"
|
||||
#include "BKE_subdiv_deform.hh"
|
||||
#include "BKE_subsurf.hh"
|
||||
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
@@ -1335,9 +1337,39 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
|
||||
0, calc->numVerts, &data, shrinkwrap_calc_nearest_surface_point_cb_ex, &settings);
|
||||
}
|
||||
|
||||
static blender::Array<blender::float3> shrinkwrap_calc_subdivided_positions(
|
||||
Mesh *mesh, const int subdivision_level)
|
||||
{
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
|
||||
Array<float3> positions = mesh->vert_positions();
|
||||
|
||||
subdiv::Settings settings{};
|
||||
settings.is_simple = false;
|
||||
settings.is_adaptive = false;
|
||||
settings.level = subdivision_level;
|
||||
settings.use_creases = true;
|
||||
|
||||
/* Default subdivision surface modifier settings:
|
||||
* - UV Smooth:Keep Corners.
|
||||
* - BoundarySmooth: All. */
|
||||
settings.vtx_boundary_interpolation = subdiv::SUBDIV_VTX_BOUNDARY_EDGE_ONLY;
|
||||
settings.fvar_linear_interpolation =
|
||||
subdiv::SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_AND_JUNCTIONS;
|
||||
|
||||
subdiv::Subdiv *subdiv = subdiv::update_from_mesh(nullptr, &settings, mesh);
|
||||
if (subdiv) {
|
||||
subdiv::deform_coarse_vertices(subdiv, mesh, positions);
|
||||
subdiv::free(subdiv);
|
||||
}
|
||||
|
||||
return positions;
|
||||
}
|
||||
|
||||
void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd,
|
||||
const ModifierEvalContext *ctx,
|
||||
Scene *scene,
|
||||
Scene * /*scene*/,
|
||||
Object *ob,
|
||||
Mesh *mesh,
|
||||
const MDeformVert *dvert,
|
||||
@@ -1345,9 +1377,8 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd,
|
||||
float (*vertexCos)[3],
|
||||
int numVerts)
|
||||
{
|
||||
|
||||
DerivedMesh *ss_mesh = nullptr;
|
||||
ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData;
|
||||
blender::Array<blender::float3> subdivided_positions;
|
||||
|
||||
/* remove loop dependencies on derived meshes (TODO should this be done elsewhere?) */
|
||||
if (smd->target == ob) {
|
||||
@@ -1387,35 +1418,8 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd,
|
||||
|
||||
/* Using vertices positions/normals as if a subsurface was applied */
|
||||
if (smd->subsurfLevels) {
|
||||
SubsurfModifierData ssmd = {{nullptr}};
|
||||
ssmd.subdivType = ME_CC_SUBSURF; /* catmull clark */
|
||||
ssmd.levels = smd->subsurfLevels; /* levels */
|
||||
|
||||
/* TODO: to be moved to Mesh once we are done with changes in subsurf code. */
|
||||
DerivedMesh *dm = CDDM_from_mesh(mesh);
|
||||
|
||||
ss_mesh = subsurf_make_derived_from_derived(
|
||||
dm,
|
||||
&ssmd,
|
||||
scene,
|
||||
nullptr,
|
||||
(ob->mode & OB_MODE_EDIT) ? SUBSURF_IN_EDIT_MODE : SubsurfFlags(0));
|
||||
|
||||
if (ss_mesh) {
|
||||
calc.vert_positions = reinterpret_cast<float(*)[3]>(ss_mesh->getVertArray(ss_mesh));
|
||||
if (calc.vert_positions) {
|
||||
/* TRICKY: this code assumes subsurface will have the transformed original vertices
|
||||
* in their original order at the end of the vert array. */
|
||||
calc.vert_positions = calc.vert_positions + ss_mesh->getNumVerts(ss_mesh) -
|
||||
dm->getNumVerts(dm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Just to make sure we are not leaving any memory behind */
|
||||
BLI_assert(ssmd.emCache == nullptr);
|
||||
BLI_assert(ssmd.mCache == nullptr);
|
||||
|
||||
dm->release(dm);
|
||||
subdivided_positions = shrinkwrap_calc_subdivided_positions(mesh, smd->subsurfLevels);
|
||||
calc.vert_positions = reinterpret_cast<float(*)[3]>(subdivided_positions.data());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1442,11 +1446,6 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd,
|
||||
|
||||
BKE_shrinkwrap_free_tree(&tree);
|
||||
}
|
||||
|
||||
/* free memory */
|
||||
if (ss_mesh) {
|
||||
ss_mesh->release(ss_mesh);
|
||||
}
|
||||
}
|
||||
|
||||
void shrinkwrapParams_deform(const ShrinkwrapParams ¶ms,
|
||||
|
||||
Reference in New Issue
Block a user