1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2020 Blender Foundation.
17  * All rights reserved.
18  */
19 
20 /** \file
21  * \ingroup bke
22  */
23 
24 #include "multires_reshape.h"
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "DNA_mesh_types.h"
29 #include "DNA_meshdata_types.h"
30 #include "DNA_modifier_types.h"
31 #include "DNA_object_types.h"
32 
33 #include "BLI_listbase.h"
34 #include "BLI_math_vector.h"
35 
36 #include "BKE_customdata.h"
37 #include "BKE_lib_id.h"
38 #include "BKE_mesh.h"
39 #include "BKE_mesh_mapping.h"
40 #include "BKE_mesh_runtime.h"
41 #include "BKE_multires.h"
42 #include "BKE_subdiv_eval.h"
43 
44 #include "DEG_depsgraph_query.h"
45 
multires_reshape_apply_base_update_mesh_coords(MultiresReshapeContext * reshape_context)46 void multires_reshape_apply_base_update_mesh_coords(MultiresReshapeContext *reshape_context)
47 {
48   Mesh *base_mesh = reshape_context->base_mesh;
49   const MLoop *mloop = base_mesh->mloop;
50   MVert *mvert = base_mesh->mvert;
51   for (int loop_index = 0; loop_index < base_mesh->totloop; ++loop_index) {
52     const MLoop *loop = &mloop[loop_index];
53     MVert *vert = &mvert[loop->v];
54 
55     GridCoord grid_coord;
56     grid_coord.grid_index = loop_index;
57     grid_coord.u = 1.0f;
58     grid_coord.v = 1.0f;
59 
60     float P[3];
61     float tangent_matrix[3][3];
62     multires_reshape_evaluate_limit_at_grid(reshape_context, &grid_coord, P, tangent_matrix);
63 
64     ReshapeConstGridElement grid_element = multires_reshape_orig_grid_element_for_grid_coord(
65         reshape_context, &grid_coord);
66     float D[3];
67     mul_v3_m3v3(D, tangent_matrix, grid_element.displacement);
68 
69     add_v3_v3v3(vert->co, P, D);
70   }
71 }
72 
73 /* Assumes no is normalized; return value's sign is negative if v is on the other side of the
74  * plane. */
v3_dist_from_plane(const float v[3],const float center[3],const float no[3])75 static float v3_dist_from_plane(const float v[3], const float center[3], const float no[3])
76 {
77   float s[3];
78   sub_v3_v3v3(s, v, center);
79   return dot_v3v3(s, no);
80 }
81 
multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext * reshape_context)82 void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape_context)
83 {
84   if (reshape_context->mmd->simple) {
85     /* Simple subdivisions does not move base mesh verticies, so no refitting is needed. */
86     return;
87   }
88 
89   Mesh *base_mesh = reshape_context->base_mesh;
90 
91   MeshElemMap *pmap;
92   int *pmap_mem;
93   BKE_mesh_vert_poly_map_create(&pmap,
94                                 &pmap_mem,
95                                 base_mesh->mpoly,
96                                 base_mesh->mloop,
97                                 base_mesh->totvert,
98                                 base_mesh->totpoly,
99                                 base_mesh->totloop);
100 
101   float(*origco)[3] = MEM_calloc_arrayN(
102       base_mesh->totvert, sizeof(float[3]), "multires apply base origco");
103   for (int i = 0; i < base_mesh->totvert; i++) {
104     copy_v3_v3(origco[i], base_mesh->mvert[i].co);
105   }
106 
107   for (int i = 0; i < base_mesh->totvert; i++) {
108     float avg_no[3] = {0, 0, 0}, center[3] = {0, 0, 0}, push[3];
109 
110     /* Don't adjust vertices not used by at least one poly. */
111     if (!pmap[i].count) {
112       continue;
113     }
114 
115     /* Find center. */
116     int tot = 0;
117     for (int j = 0; j < pmap[i].count; j++) {
118       const MPoly *p = &base_mesh->mpoly[pmap[i].indices[j]];
119 
120       /* This double counts, not sure if that's bad or good. */
121       for (int k = 0; k < p->totloop; k++) {
122         const int vndx = base_mesh->mloop[p->loopstart + k].v;
123         if (vndx != i) {
124           add_v3_v3(center, origco[vndx]);
125           tot++;
126         }
127       }
128     }
129     mul_v3_fl(center, 1.0f / tot);
130 
131     /* Find normal. */
132     for (int j = 0; j < pmap[i].count; j++) {
133       const MPoly *p = &base_mesh->mpoly[pmap[i].indices[j]];
134       MPoly fake_poly;
135       MLoop *fake_loops;
136       float(*fake_co)[3];
137       float no[3];
138 
139       /* Set up poly, loops, and coords in order to call BKE_mesh_calc_poly_normal_coords(). */
140       fake_poly.totloop = p->totloop;
141       fake_poly.loopstart = 0;
142       fake_loops = MEM_malloc_arrayN(p->totloop, sizeof(MLoop), "fake_loops");
143       fake_co = MEM_malloc_arrayN(p->totloop, sizeof(float[3]), "fake_co");
144 
145       for (int k = 0; k < p->totloop; k++) {
146         const int vndx = base_mesh->mloop[p->loopstart + k].v;
147 
148         fake_loops[k].v = k;
149 
150         if (vndx == i) {
151           copy_v3_v3(fake_co[k], center);
152         }
153         else {
154           copy_v3_v3(fake_co[k], origco[vndx]);
155         }
156       }
157 
158       BKE_mesh_calc_poly_normal_coords(&fake_poly, fake_loops, (const float(*)[3])fake_co, no);
159       MEM_freeN(fake_loops);
160       MEM_freeN(fake_co);
161 
162       add_v3_v3(avg_no, no);
163     }
164     normalize_v3(avg_no);
165 
166     /* Push vertex away from the plane. */
167     const float dist = v3_dist_from_plane(base_mesh->mvert[i].co, center, avg_no);
168     copy_v3_v3(push, avg_no);
169     mul_v3_fl(push, dist);
170     add_v3_v3(base_mesh->mvert[i].co, push);
171   }
172 
173   MEM_freeN(origco);
174   MEM_freeN(pmap);
175   MEM_freeN(pmap_mem);
176 
177   /* Vertices were moved around, need to update normals after all the vertices are updated
178    * Probably this is possible to do in the loop above, but this is rather tricky because
179    * we don't know all needed vertices' coordinates there yet. */
180   BKE_mesh_calc_normals(base_mesh);
181 }
182 
multires_reshape_apply_base_refine_from_base(MultiresReshapeContext * reshape_context)183 void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshape_context)
184 {
185   BKE_subdiv_eval_refine_from_mesh(reshape_context->subdiv, reshape_context->base_mesh, NULL);
186 }
187 
multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext * reshape_context)188 void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *reshape_context)
189 {
190   struct Depsgraph *depsgraph = reshape_context->depsgraph;
191   Object *object = reshape_context->object;
192   MultiresModifierData *mmd = reshape_context->mmd;
193   BLI_assert(depsgraph != NULL);
194   BLI_assert(object != NULL);
195   BLI_assert(mmd != NULL);
196 
197   float(*deformed_verts)[3] = BKE_multires_create_deformed_base_mesh_vert_coords(
198       depsgraph, object, mmd, NULL);
199 
200   BKE_subdiv_eval_refine_from_mesh(
201       reshape_context->subdiv, reshape_context->base_mesh, deformed_verts);
202 
203   MEM_freeN(deformed_verts);
204 }
205