Blender  V2.93
multires_reshape_apply_base.c
Go to the documentation of this file.
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 
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 
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 
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. */
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 
83 {
84  Mesh *base_mesh = reshape_context->base_mesh;
85 
86  MeshElemMap *pmap;
87  int *pmap_mem;
89  &pmap_mem,
90  base_mesh->mpoly,
91  base_mesh->mloop,
92  base_mesh->totvert,
93  base_mesh->totpoly,
94  base_mesh->totloop);
95 
96  float(*origco)[3] = MEM_calloc_arrayN(
97  base_mesh->totvert, sizeof(float[3]), "multires apply base origco");
98  for (int i = 0; i < base_mesh->totvert; i++) {
99  copy_v3_v3(origco[i], base_mesh->mvert[i].co);
100  }
101 
102  for (int i = 0; i < base_mesh->totvert; i++) {
103  float avg_no[3] = {0, 0, 0}, center[3] = {0, 0, 0}, push[3];
104 
105  /* Don't adjust vertices not used by at least one poly. */
106  if (!pmap[i].count) {
107  continue;
108  }
109 
110  /* Find center. */
111  int tot = 0;
112  for (int j = 0; j < pmap[i].count; j++) {
113  const MPoly *p = &base_mesh->mpoly[pmap[i].indices[j]];
114 
115  /* This double counts, not sure if that's bad or good. */
116  for (int k = 0; k < p->totloop; k++) {
117  const int vndx = base_mesh->mloop[p->loopstart + k].v;
118  if (vndx != i) {
119  add_v3_v3(center, origco[vndx]);
120  tot++;
121  }
122  }
123  }
124  mul_v3_fl(center, 1.0f / tot);
125 
126  /* Find normal. */
127  for (int j = 0; j < pmap[i].count; j++) {
128  const MPoly *p = &base_mesh->mpoly[pmap[i].indices[j]];
129  MPoly fake_poly;
130  MLoop *fake_loops;
131  float(*fake_co)[3];
132  float no[3];
133 
134  /* Set up poly, loops, and coords in order to call BKE_mesh_calc_poly_normal_coords(). */
135  fake_poly.totloop = p->totloop;
136  fake_poly.loopstart = 0;
137  fake_loops = MEM_malloc_arrayN(p->totloop, sizeof(MLoop), "fake_loops");
138  fake_co = MEM_malloc_arrayN(p->totloop, sizeof(float[3]), "fake_co");
139 
140  for (int k = 0; k < p->totloop; k++) {
141  const int vndx = base_mesh->mloop[p->loopstart + k].v;
142 
143  fake_loops[k].v = k;
144 
145  if (vndx == i) {
146  copy_v3_v3(fake_co[k], center);
147  }
148  else {
149  copy_v3_v3(fake_co[k], origco[vndx]);
150  }
151  }
152 
153  BKE_mesh_calc_poly_normal_coords(&fake_poly, fake_loops, (const float(*)[3])fake_co, no);
154  MEM_freeN(fake_loops);
155  MEM_freeN(fake_co);
156 
157  add_v3_v3(avg_no, no);
158  }
159  normalize_v3(avg_no);
160 
161  /* Push vertex away from the plane. */
162  const float dist = v3_dist_from_plane(base_mesh->mvert[i].co, center, avg_no);
163  copy_v3_v3(push, avg_no);
164  mul_v3_fl(push, dist);
165  add_v3_v3(base_mesh->mvert[i].co, push);
166  }
167 
168  MEM_freeN(origco);
169  MEM_freeN(pmap);
170  MEM_freeN(pmap_mem);
171 
172  /* Vertices were moved around, need to update normals after all the vertices are updated
173  * Probably this is possible to do in the loop above, but this is rather tricky because
174  * we don't know all needed vertices' coordinates there yet. */
175  BKE_mesh_calc_normals(base_mesh);
176 }
177 
179 {
180  BKE_subdiv_eval_refine_from_mesh(reshape_context->subdiv, reshape_context->base_mesh, NULL);
181 }
182 
184 {
185  struct Depsgraph *depsgraph = reshape_context->depsgraph;
186  Object *object = reshape_context->object;
187  MultiresModifierData *mmd = reshape_context->mmd;
189  BLI_assert(object != NULL);
190  BLI_assert(mmd != NULL);
191 
193  depsgraph, object, mmd, NULL);
194 
196  reshape_context->subdiv, reshape_context->base_mesh, deformed_verts);
197 
198  MEM_freeN(deformed_verts);
199 }
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
void BKE_mesh_calc_normals(struct Mesh *me)
void BKE_mesh_calc_poly_normal_coords(const struct MPoly *mpoly, const struct MLoop *loopstart, const float(*vertex_coords)[3], float r_no[3])
void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem, const struct MPoly *mpoly, const struct MLoop *mloop, int totvert, int totpoly, int totloop)
float(* BKE_multires_create_deformed_base_mesh_vert_coords(struct Depsgraph *depsgraph, struct Object *object, struct MultiresModifierData *mmd, int *r_num_deformed_verts))[3]
Definition: multires.c:265
bool BKE_subdiv_eval_refine_from_mesh(struct Subdiv *subdiv, const struct Mesh *mesh, const float(*coarse_vertex_cos)[3])
#define BLI_assert(a)
Definition: BLI_assert.h:58
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:901
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
Object is a sort of wrapper for general info.
NSNotificationCenter * center
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v
const Depsgraph * depsgraph
int count
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:46
static float P(float k)
Definition: math_interp.c:41
ReshapeConstGridElement multires_reshape_orig_grid_element_for_grid_coord(const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord)
void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord, float r_P[3], float r_tangent_matrix[3][3])
void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape_context)
static float v3_dist_from_plane(const float v[3], const float center[3], const float no[3])
void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshape_context)
void multires_reshape_apply_base_update_mesh_coords(MultiresReshapeContext *reshape_context)
void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *reshape_context)
unsigned int v
float co[3]
struct MVert * mvert
int totvert
struct MLoop * mloop
int totpoly
int totloop
struct MPoly * mpoly
struct MultiresModifierData * mmd
struct Object * object
struct Depsgraph * depsgraph
struct Subdiv * subdiv
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:29