Blender V4.3
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
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] = static_cast<float(*)[3]>(
68 MEM_calloc_arrayN(base_mesh->verts_num, sizeof(float[3]), __func__));
69 for (int i = 0; i < base_mesh->verts_num; i++) {
70 copy_v3_v3(origco[i], base_positions[i]);
71 }
72
73 for (int i = 0; i < base_mesh->verts_num; i++) {
74 float avg_no[3] = {0, 0, 0}, center[3] = {0, 0, 0}, push[3];
75
76 /* Don't adjust vertices not used by at least one face. */
77 if (!vert_to_face_map[i].size()) {
78 continue;
79 }
80
81 /* Find center. */
82 int tot = 0;
83 for (const int face : vert_to_face_map[i]) {
84 /* This double counts, not sure if that's bad or good. */
85 for (const int corner : reshape_context->base_faces[face]) {
86 const int vndx = reshape_context->base_corner_verts[corner];
87 if (vndx != i) {
88 add_v3_v3(center, origco[vndx]);
89 tot++;
90 }
91 }
92 }
93 mul_v3_fl(center, 1.0f / tot);
94
95 /* Find normal. */
96 for (int j = 0; j < vert_to_face_map[i].size(); j++) {
97 const blender::IndexRange face = reshape_context->base_faces[vert_to_face_map[i][j]];
98
99 /* Set up face, loops, and coords in order to call #bke::mesh::face_normal_calc(). */
100 blender::Array<int> face_verts(face.size());
101 blender::Array<blender::float3> fake_co(face.size());
102
103 for (int k = 0; k < face.size(); k++) {
104 const int vndx = reshape_context->base_corner_verts[face[k]];
105
106 face_verts[k] = k;
107
108 if (vndx == i) {
109 copy_v3_v3(fake_co[k], center);
110 }
111 else {
112 copy_v3_v3(fake_co[k], origco[vndx]);
113 }
114 }
115
116 const blender::float3 no = blender::bke::mesh::face_normal_calc(fake_co, face_verts);
117 add_v3_v3(avg_no, no);
118 }
119 normalize_v3(avg_no);
120
121 /* Push vertex away from the plane. */
122 const float dist = v3_dist_from_plane(base_positions[i], center, avg_no);
123 copy_v3_v3(push, avg_no);
124 mul_v3_fl(push, dist);
125 add_v3_v3(base_positions[i], push);
126 }
127
128 MEM_freeN(origco);
129
130 /* Vertices were moved around, need to update normals after all the vertices are updated
131 * Probably this is possible to do in the loop above, but this is rather tricky because
132 * we don't know all needed vertices' coordinates there yet. */
133 base_mesh->tag_positions_changed();
134}
135
137{
139 reshape_context->subdiv, reshape_context->base_mesh, {});
140}
141
143{
144 Depsgraph *depsgraph = reshape_context->depsgraph;
145 Object *object = reshape_context->object;
146 MultiresModifierData *mmd = reshape_context->mmd;
147 BLI_assert(depsgraph != nullptr);
148 BLI_assert(object != nullptr);
149 BLI_assert(mmd != nullptr);
150
151 blender::Array<blender::float3> deformed_verts =
153
155 reshape_context->subdiv, reshape_context->base_mesh, deformed_verts);
156}
blender::Array< blender::float3 > BKE_multires_create_deformed_base_mesh_vert_coords(Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd)
Definition multires.cc:244
#define BLI_assert(a)
Definition BLI_assert.h:50
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
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
const Depsgraph * depsgraph
draw_view in_light_buf[] float
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:43
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
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)
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