Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2020-03-03 14:35:51 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2020-03-13 16:14:56 +0300
commitbc0a0cdf171037cba4076c796e9adb2769382561 (patch)
tree518cf488b585fa0440989e756db10d5c3cd3f6a1 /source/blender/blenkernel/intern/multires.c
parentb0a1af4eb10f6c771a49401e9d0c4c56f6f6d008 (diff)
Multires: Fix Subdivide, Reshape and Apply Base
This change fixes artifacts produced by these operations. On a technical aspect this is done by porting all of the operations to the new subdivision surface implementation which ensures that tangent space used to evaluate modifier and those operations is exactly the same (before modifier will use new code and the operations will still use an old one). The next step is to get sculpting on a non-top level to work, and that actually requires fixes in the undo system.
Diffstat (limited to 'source/blender/blenkernel/intern/multires.c')
-rw-r--r--source/blender/blenkernel/intern/multires.c171
1 files changed, 11 insertions, 160 deletions
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index f3d65f584d1..70061c155d3 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -57,6 +57,8 @@
#include "DEG_depsgraph_query.h"
+#include "multires_reshape.h"
+
#include <math.h>
#include <string.h>
@@ -789,158 +791,7 @@ static DerivedMesh *subsurf_dm_create_local(Scene *scene,
return subsurf_make_derived_from_derived(dm, &smd, scene, NULL, flags);
}
-/* assumes no is normalized; return value's sign is negative if v is on
- * the other side of the plane */
-static float v3_dist_from_plane(float v[3], float center[3], float no[3])
-{
- float s[3];
- sub_v3_v3v3(s, v, center);
- return dot_v3v3(s, no);
-}
-
-void multiresModifier_base_apply(MultiresModifierData *mmd, Scene *scene, Object *ob)
-{
- DerivedMesh *cddm, *dispdm, *origdm;
- Mesh *me;
- const MeshElemMap *pmap;
- float(*origco)[3];
- int i, j, k, offset, totlvl;
-
- multires_force_sculpt_rebuild(ob);
-
- me = BKE_mesh_from_object(ob);
- totlvl = mmd->totlvl;
-
- /* nothing to do */
- if (!totlvl) {
- return;
- }
-
- /* XXX - probably not necessary to regenerate the cddm so much? */
-
- /* generate highest level with displacements */
- cddm = CDDM_from_mesh(me);
- DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
- dispdm = multires_dm_create_local(
- scene, ob, cddm, totlvl, totlvl, 0, 0, MULTIRES_IGNORE_SIMPLIFY);
- cddm->release(cddm);
-
- /* copy the new locations of the base verts into the mesh */
- offset = dispdm->getNumVerts(dispdm) - me->totvert;
- for (i = 0; i < me->totvert; i++) {
- dispdm->getVertCo(dispdm, offset + i, me->mvert[i].co);
- }
-
- /* heuristic to produce a better-fitting base mesh */
-
- cddm = CDDM_from_mesh(me);
- pmap = cddm->getPolyMap(ob, cddm);
- origco = MEM_calloc_arrayN(me->totvert, 3 * sizeof(float), "multires apply base origco");
- for (i = 0; i < me->totvert; i++) {
- copy_v3_v3(origco[i], me->mvert[i].co);
- }
-
- for (i = 0; i < me->totvert; i++) {
- float avg_no[3] = {0, 0, 0}, center[3] = {0, 0, 0}, push[3];
- float dist;
- int tot = 0;
-
- /* don't adjust verts not used by at least one poly */
- if (!pmap[i].count) {
- continue;
- }
-
- /* find center */
- for (j = 0; j < pmap[i].count; j++) {
- const MPoly *p = &me->mpoly[pmap[i].indices[j]];
-
- /* this double counts, not sure if that's bad or good */
- for (k = 0; k < p->totloop; k++) {
- int vndx = me->mloop[p->loopstart + k].v;
- if (vndx != i) {
- add_v3_v3(center, origco[vndx]);
- tot++;
- }
- }
- }
- mul_v3_fl(center, 1.0f / tot);
-
- /* find normal */
- for (j = 0; j < pmap[i].count; j++) {
- const MPoly *p = &me->mpoly[pmap[i].indices[j]];
- MPoly fake_poly;
- MLoop *fake_loops;
- float(*fake_co)[3];
- float no[3];
-
- /* set up poly, loops, and coords in order to call
- * BKE_mesh_calc_poly_normal_coords() */
- fake_poly.totloop = p->totloop;
- fake_poly.loopstart = 0;
- fake_loops = MEM_malloc_arrayN(p->totloop, sizeof(MLoop), "fake_loops");
- fake_co = MEM_malloc_arrayN(p->totloop, 3 * sizeof(float), "fake_co");
-
- for (k = 0; k < p->totloop; k++) {
- int vndx = me->mloop[p->loopstart + k].v;
-
- fake_loops[k].v = k;
-
- if (vndx == i) {
- copy_v3_v3(fake_co[k], center);
- }
- else {
- copy_v3_v3(fake_co[k], origco[vndx]);
- }
- }
-
- BKE_mesh_calc_poly_normal_coords(&fake_poly, fake_loops, (const float(*)[3])fake_co, no);
- MEM_freeN(fake_loops);
- MEM_freeN(fake_co);
-
- add_v3_v3(avg_no, no);
- }
- normalize_v3(avg_no);
-
- /* push vertex away from the plane */
- dist = v3_dist_from_plane(me->mvert[i].co, center, avg_no);
- copy_v3_v3(push, avg_no);
- mul_v3_fl(push, dist);
- add_v3_v3(me->mvert[i].co, push);
- }
-
- MEM_freeN(origco);
- cddm->release(cddm);
-
- /* Vertices were moved around, need to update normals after all the vertices are updated
- * Probably this is possible to do in the loop above, but this is rather tricky because
- * we don't know all needed vertices' coordinates there yet.
- */
- BKE_mesh_calc_normals(me);
-
- /* subdivide the mesh to highest level without displacements */
- cddm = CDDM_from_mesh(me);
- DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
- origdm = subsurf_dm_create_local(scene,
- ob,
- cddm,
- totlvl,
- 0,
- 0,
- mmd->uv_smooth == SUBSURF_UV_SMOOTH_NONE,
- 0,
- false,
- SUBSURF_IGNORE_SIMPLIFY);
- cddm->release(cddm);
-
- /* calc disps */
- multiresModifier_disp_run(
- dispdm, me, NULL, CALC_DISPLACEMENTS, origdm->getGridData(origdm), totlvl);
-
- origdm->release(origdm);
- dispdm->release(dispdm);
-}
-
-static void multires_subdivide(
+static void multires_subdivide_legacy(
MultiresModifierData *mmd, Scene *scene, Object *ob, int totlvl, int updateblock, int simple)
{
Mesh *me = ob->data;
@@ -1038,10 +889,10 @@ static void multires_subdivide(
multires_set_tot_level(ob, mmd, totlvl);
}
-void multiresModifier_subdivide(
+void multiresModifier_subdivide_legacy(
MultiresModifierData *mmd, Scene *scene, Object *ob, int updateblock, int simple)
{
- multires_subdivide(mmd, scene, ob, mmd->totlvl + 1, updateblock, simple);
+ multires_subdivide_legacy(mmd, scene, ob, mmd->totlvl + 1, updateblock, simple);
}
static void grid_tangent(const CCGKey *key, int x, int y, int axis, CCGElem *grid, float t[3])
@@ -2277,7 +2128,8 @@ void multires_load_old(Object *ob, Mesh *me)
multires_load_old_vcols(me);
multires_load_old_face_flags(me);
- /* multiresModifier_subdivide (actually, multires_subdivide) expects polys, not tessfaces! */
+ /* multiresModifier_subdivide_legacy (actually, multires_subdivide_legacy) expects polys, not
+ * tessfaces! */
BKE_mesh_convert_mfaces_to_mpolys(me);
/* Add a multires modifier to the object */
@@ -2289,7 +2141,7 @@ void multires_load_old(Object *ob, Mesh *me)
BLI_insertlinkbefore(&ob->modifiers, md, mmd);
for (i = 0; i < me->mr->level_count - 1; i++) {
- multiresModifier_subdivide(mmd, NULL, ob, 1, 0);
+ multiresModifier_subdivide_legacy(mmd, NULL, ob, 1, 0);
}
mmd->lvl = mmd->totlvl;
@@ -2314,8 +2166,7 @@ void multires_load_old(Object *ob, Mesh *me)
/* If 'ob_src' and 'ob_dst' both have multires modifiers, synchronize them
* such that 'ob_dst' has the same total number of levels as 'ob_src'. */
-void multiresModifier_sync_levels_ex(Scene *scene,
- Object *ob_dst,
+void multiresModifier_sync_levels_ex(Object *ob_dst,
MultiresModifierData *mmd_src,
MultiresModifierData *mmd_dst)
{
@@ -2324,7 +2175,7 @@ void multiresModifier_sync_levels_ex(Scene *scene,
}
if (mmd_src->totlvl > mmd_dst->totlvl) {
- multires_subdivide(mmd_dst, scene, ob_dst, mmd_src->totlvl, false, mmd_dst->simple);
+ multiresModifier_subdivide_to_level(ob_dst, mmd_dst, mmd_src->totlvl);
}
else {
multires_del_higher(mmd_dst, ob_dst, mmd_src->totlvl);
@@ -2346,7 +2197,7 @@ static void multires_sync_levels(Scene *scene, Object *ob_src, Object *ob_dst)
}
if (mmd_src && mmd_dst) {
- multiresModifier_sync_levels_ex(scene, ob_dst, mmd_src, mmd_dst);
+ multiresModifier_sync_levels_ex(ob_dst, mmd_src, mmd_dst);
}
}