Blender V4.5
multires_reshape_apply_base.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "multires_reshape.hh"
10
11#include "MEM_guardedalloc.h"
12
13#include "DNA_mesh_types.h"
14
15#include "BLI_math_matrix.h"
16#include "BLI_math_vector.h"
17
18#include "BKE_mesh.hh"
19#include "BKE_multires.hh"
20#include "BKE_subdiv_eval.hh"
21
23{
24 Mesh *base_mesh = reshape_context->base_mesh;
25 blender::MutableSpan<blender::float3> base_positions = base_mesh->vert_positions_for_write();
26 /* Update the context in case the vertices were duplicated. */
27 reshape_context->base_positions = base_positions;
28
29 const blender::Span<int> corner_verts = reshape_context->base_corner_verts;
30 for (const int loop_index : corner_verts.index_range()) {
31
32 GridCoord grid_coord;
33 grid_coord.grid_index = loop_index;
34 grid_coord.u = 1.0f;
35 grid_coord.v = 1.0f;
36
37 float P[3];
38 float tangent_matrix[3][3];
39 multires_reshape_evaluate_limit_at_grid(reshape_context, &grid_coord, P, tangent_matrix);
40
42 reshape_context, &grid_coord);
43 float D[3];
44 mul_v3_m3v3(D, tangent_matrix, grid_element.displacement);
45
46 add_v3_v3v3(base_positions[corner_verts[loop_index]], P, D);
47 }
48}
49
50/* Assumes no is normalized; return value's sign is negative if v is on the other side of the
51 * plane. */
52static float v3_dist_from_plane(const float v[3], const float center[3], const float no[3])
53{
54 float s[3];
55 sub_v3_v3v3(s, v, center);
56 return dot_v3v3(s, no);
57}
58
60{
61 Mesh *base_mesh = reshape_context->base_mesh;
62 blender::MutableSpan<blender::float3> base_positions = base_mesh->vert_positions_for_write();
63 /* Update the context in case the vertices were duplicated. */
64 reshape_context->base_positions = base_positions;
65 const blender::GroupedSpan<int> vert_to_face_map = base_mesh->vert_to_face_map();
66
67 float(*origco)[3] = MEM_calloc_arrayN<float[3]>(base_mesh->verts_num, __func__);
68 for (int i = 0; i < base_mesh->verts_num; i++) {
69 copy_v3_v3(origco[i], base_positions[i]);
70 }
71
72 for (int i = 0; i < base_mesh->verts_num; i++) {
73 float avg_no[3] = {0, 0, 0}, center[3] = {0, 0, 0}, push[3];
74
75 /* Don't adjust vertices not used by at least one face. */
76 if (!vert_to_face_map[i].size()) {
77 continue;
78 }
79
80 /* Find center. */
81 int tot = 0;
82 for (const int face : vert_to_face_map[i]) {
83 /* This double counts, not sure if that's bad or good. */
84 for (const int corner : reshape_context->base_faces[face]) {
85 const int vndx = reshape_context->base_corner_verts[corner];
86 if (vndx != i) {
87 add_v3_v3(center, origco[vndx]);
88 tot++;
89 }
90 }
91 }
92 mul_v3_fl(center, 1.0f / tot);
93
94 /* Find normal. */
95 for (int j = 0; j < vert_to_face_map[i].size(); j++) {
96 const blender::IndexRange face = reshape_context->base_faces[vert_to_face_map[i][j]];
97
98 /* Set up face, loops, and coords in order to call #bke::mesh::face_normal_calc(). */
99 blender::Array<int> face_verts(face.size());
101
102 for (int k = 0; k < face.size(); k++) {
103 const int vndx = reshape_context->base_corner_verts[face[k]];
104
105 face_verts[k] = k;
106
107 if (vndx == i) {
108 copy_v3_v3(fake_co[k], center);
109 }
110 else {
111 copy_v3_v3(fake_co[k], origco[vndx]);
112 }
113 }
114
115 const blender::float3 no = blender::bke::mesh::face_normal_calc(fake_co, face_verts);
116 add_v3_v3(avg_no, no);
117 }
118 normalize_v3(avg_no);
119
120 /* Push vertex away from the plane. */
121 const float dist = v3_dist_from_plane(base_positions[i], center, avg_no);
122 copy_v3_v3(push, avg_no);
123 mul_v3_fl(push, dist);
124 add_v3_v3(base_positions[i], push);
125 }
126
127 MEM_freeN(origco);
128
129 /* Vertices were moved around, need to update normals after all the vertices are updated
130 * Probably this is possible to do in the loop above, but this is rather tricky because
131 * we don't know all needed vertices' coordinates there yet. */
132 base_mesh->tag_positions_changed();
133}
134
136{
138 reshape_context->subdiv, reshape_context->base_mesh, {});
139}
140
142{
143 Depsgraph *depsgraph = reshape_context->depsgraph;
144 Object *object = reshape_context->object;
145 MultiresModifierData *mmd = reshape_context->mmd;
146 BLI_assert(depsgraph != nullptr);
147 BLI_assert(object != nullptr);
148 BLI_assert(mmd != nullptr);
149
150 blender::Array<blender::float3> deformed_verts =
152
154 reshape_context->subdiv, reshape_context->base_mesh, deformed_verts);
155}
blender::Array< blender::float3 > BKE_multires_create_deformed_base_mesh_vert_coords(Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd)
Definition multires.cc:237
#define D
#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])
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])
MINLINE float normalize_v3(float n[3])
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr int64_t size() const
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
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)
float3 face_normal_calc(Span< float3 > vert_positions, Span< int > face_verts)
bool eval_refine_from_mesh(Subdiv *subdiv, const Mesh *mesh, Span< float3 > coarse_vert_positions)
VecBase< float, 3 > float3
int verts_num
blender::bke::subdiv::Subdiv * subdiv
blender::OffsetIndices< int > base_faces
blender::Span< blender::float3 > base_positions
blender::Span< int > base_corner_verts
MultiresModifierData * mmd
i
Definition text_draw.cc:230