Blender  V3.3
multires_reshape_apply_base.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2020 Blender Foundation. All rights reserved. */
3 
8 #include "multires_reshape.h"
9 
10 #include "MEM_guardedalloc.h"
11 
12 #include "DNA_mesh_types.h"
13 #include "DNA_meshdata_types.h"
14 #include "DNA_modifier_types.h"
15 #include "DNA_object_types.h"
16 
17 #include "BLI_listbase.h"
18 #include "BLI_math_vector.h"
19 
20 #include "BKE_customdata.h"
21 #include "BKE_lib_id.h"
22 #include "BKE_mesh.h"
23 #include "BKE_mesh_mapping.h"
24 #include "BKE_mesh_runtime.h"
25 #include "BKE_multires.h"
26 #include "BKE_subdiv_eval.h"
27 
28 #include "DEG_depsgraph_query.h"
29 
31 {
32  Mesh *base_mesh = reshape_context->base_mesh;
33  const MLoop *mloop = base_mesh->mloop;
34  MVert *mvert = base_mesh->mvert;
35  for (int loop_index = 0; loop_index < base_mesh->totloop; ++loop_index) {
36  const MLoop *loop = &mloop[loop_index];
37  MVert *vert = &mvert[loop->v];
38 
39  GridCoord grid_coord;
40  grid_coord.grid_index = loop_index;
41  grid_coord.u = 1.0f;
42  grid_coord.v = 1.0f;
43 
44  float P[3];
45  float tangent_matrix[3][3];
46  multires_reshape_evaluate_limit_at_grid(reshape_context, &grid_coord, P, tangent_matrix);
47 
49  reshape_context, &grid_coord);
50  float D[3];
51  mul_v3_m3v3(D, tangent_matrix, grid_element.displacement);
52 
53  add_v3_v3v3(vert->co, P, D);
54  }
55 }
56 
57 /* Assumes no is normalized; return value's sign is negative if v is on the other side of the
58  * plane. */
59 static float v3_dist_from_plane(const float v[3], const float center[3], const float no[3])
60 {
61  float s[3];
62  sub_v3_v3v3(s, v, center);
63  return dot_v3v3(s, no);
64 }
65 
67 {
68  Mesh *base_mesh = reshape_context->base_mesh;
69 
70  MeshElemMap *pmap;
71  int *pmap_mem;
73  &pmap_mem,
74  base_mesh->mpoly,
75  base_mesh->mloop,
76  base_mesh->totvert,
77  base_mesh->totpoly,
78  base_mesh->totloop);
79 
80  float(*origco)[3] = MEM_calloc_arrayN(
81  base_mesh->totvert, sizeof(float[3]), "multires apply base origco");
82  for (int i = 0; i < base_mesh->totvert; i++) {
83  copy_v3_v3(origco[i], base_mesh->mvert[i].co);
84  }
85 
86  for (int i = 0; i < base_mesh->totvert; i++) {
87  float avg_no[3] = {0, 0, 0}, center[3] = {0, 0, 0}, push[3];
88 
89  /* Don't adjust vertices not used by at least one poly. */
90  if (!pmap[i].count) {
91  continue;
92  }
93 
94  /* Find center. */
95  int tot = 0;
96  for (int j = 0; j < pmap[i].count; j++) {
97  const MPoly *p = &base_mesh->mpoly[pmap[i].indices[j]];
98 
99  /* This double counts, not sure if that's bad or good. */
100  for (int k = 0; k < p->totloop; k++) {
101  const int vndx = base_mesh->mloop[p->loopstart + k].v;
102  if (vndx != i) {
103  add_v3_v3(center, origco[vndx]);
104  tot++;
105  }
106  }
107  }
108  mul_v3_fl(center, 1.0f / tot);
109 
110  /* Find normal. */
111  for (int j = 0; j < pmap[i].count; j++) {
112  const MPoly *p = &base_mesh->mpoly[pmap[i].indices[j]];
113  MPoly fake_poly;
114  MLoop *fake_loops;
115  float(*fake_co)[3];
116  float no[3];
117 
118  /* Set up poly, loops, and coords in order to call BKE_mesh_calc_poly_normal_coords(). */
119  fake_poly.totloop = p->totloop;
120  fake_poly.loopstart = 0;
121  fake_loops = MEM_malloc_arrayN(p->totloop, sizeof(MLoop), "fake_loops");
122  fake_co = MEM_malloc_arrayN(p->totloop, sizeof(float[3]), "fake_co");
123 
124  for (int k = 0; k < p->totloop; k++) {
125  const int vndx = base_mesh->mloop[p->loopstart + k].v;
126 
127  fake_loops[k].v = k;
128 
129  if (vndx == i) {
130  copy_v3_v3(fake_co[k], center);
131  }
132  else {
133  copy_v3_v3(fake_co[k], origco[vndx]);
134  }
135  }
136 
137  BKE_mesh_calc_poly_normal_coords(&fake_poly, fake_loops, (const float(*)[3])fake_co, no);
138  MEM_freeN(fake_loops);
139  MEM_freeN(fake_co);
140 
141  add_v3_v3(avg_no, no);
142  }
143  normalize_v3(avg_no);
144 
145  /* Push vertex away from the plane. */
146  const float dist = v3_dist_from_plane(base_mesh->mvert[i].co, center, avg_no);
147  copy_v3_v3(push, avg_no);
148  mul_v3_fl(push, dist);
149  add_v3_v3(base_mesh->mvert[i].co, push);
150  }
151 
152  MEM_freeN(origco);
153  MEM_freeN(pmap);
154  MEM_freeN(pmap_mem);
155 
156  /* Vertices were moved around, need to update normals after all the vertices are updated
157  * Probably this is possible to do in the loop above, but this is rather tricky because
158  * we don't know all needed vertices' coordinates there yet. */
159  BKE_mesh_tag_coords_changed(base_mesh);
160 }
161 
163 {
164  BKE_subdiv_eval_refine_from_mesh(reshape_context->subdiv, reshape_context->base_mesh, NULL);
165 }
166 
168 {
169  struct Depsgraph *depsgraph = reshape_context->depsgraph;
170  Object *object = reshape_context->object;
171  MultiresModifierData *mmd = reshape_context->mmd;
173  BLI_assert(object != NULL);
174  BLI_assert(mmd != NULL);
175 
177  depsgraph, object, mmd, NULL);
178 
180  reshape_context->subdiv, reshape_context->base_mesh, deformed_verts);
181 
182  MEM_freeN(deformed_verts);
183 }
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
void BKE_mesh_tag_coords_changed(struct Mesh *mesh)
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:249
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:46
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:897
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:35
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:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
static float P(float k)
Definition: math_interp.c:25
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:13