Blender V5.0
transform_convert_mesh_vert_cdata.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_math_matrix.h"
10#include "BLI_math_vector.h"
11
12#include "BKE_context.hh"
13#include "BKE_editmesh.hh"
14
15#include "DEG_depsgraph.hh"
16
17#include "transform.hh"
19
20#include "transform_convert.hh"
21
22namespace blender::ed::transform {
23
24/* -------------------------------------------------------------------- */
27
28static float *mesh_cdata_transdata_center(const TransIslandData *island_data,
29 const int island_index,
30 BMVert *eve)
31{
32 if (island_data->center && island_index != -1) {
33 return island_data->center[island_index];
34 }
35 return eve->co;
36}
37
39 BMVert *eve,
40 float *weight,
41 const TransIslandData *island_data,
42 const int island_index)
43{
45
46 td->val = weight;
47 td->ival = *weight;
48
50 td->flag |= TD_SELECTED;
51 }
52
53 copy_v3_v3(td->center, mesh_cdata_transdata_center(island_data, island_index, eve));
54 td->extra = eve;
55}
56
58{
61 BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
62 BMesh *bm = em->bm;
63 BMVert *eve;
64 BMIter iter;
65 float mtx[3][3], smtx[3][3];
66 int a;
67 const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
68
69 TransIslandData island_data = {nullptr};
70 TransMeshDataCrazySpace crazyspace_data = {nullptr};
71
72 /* Support other objects using proportional editing to adjust these, unless connected is
73 * enabled. */
74 if ((!prop_mode || (prop_mode & T_PROP_CONNECTED)) && (bm->totvertsel == 0)) {
75 continue;
76 }
77
78 int cd_offset = -1;
79 if (t->mode == TFM_BWEIGHT) {
80 if (!CustomData_has_layer_named(&bm->vdata, CD_PROP_FLOAT, "bevel_weight_vert")) {
81 BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_FLOAT, "bevel_weight_vert");
82 }
83 cd_offset = CustomData_get_offset_named(&bm->vdata, CD_PROP_FLOAT, "bevel_weight_vert");
84 }
85 else {
86 if (!CustomData_has_layer_named(&bm->vdata, CD_PROP_FLOAT, "crease_vert")) {
87 BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_FLOAT, "crease_vert");
88 }
89 cd_offset = CustomData_get_offset_named(&bm->vdata, CD_PROP_FLOAT, "crease_vert");
90 }
91
92 if (cd_offset == -1) {
93 continue;
94 }
95
96 int data_len = 0;
97 if (prop_mode) {
98 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
100 data_len++;
101 }
102 }
103 }
104 else {
105 data_len = bm->totvertsel;
106 }
107
108 if (data_len == 0) {
109 continue;
110 }
111
112 const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
113 if (is_island_center) {
114 /* In this specific case, near-by vertices will need to know
115 * the island of the nearest connected vertex. */
116 const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) &&
119
120 const bool calc_island_center = false;
121 const bool calc_island_axismtx = false;
122
124 em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data);
125 }
126
127 copy_m3_m4(mtx, tc->obedit->object_to_world().ptr());
128 /* We use a pseudo-inverse so that when one of the axes is scaled to 0,
129 * matrix inversion still works and we can still moving along the other. */
131
132 /* Original index of our connected vertex when connected distances are calculated.
133 * Optional, allocate if needed. */
134 int *dists_index = nullptr;
135 float *dists = nullptr;
136 if (prop_mode & T_PROP_CONNECTED) {
137 dists = MEM_malloc_arrayN<float>(bm->totvert, __func__);
138 if (is_island_center) {
139 dists_index = MEM_malloc_arrayN<int>(bm->totvert, __func__);
140 }
141 transform_convert_mesh_connectivity_distance(em->bm, mtx, dists, dists_index);
142 }
143
144 /* Detect CrazySpace [tm]. */
145 transform_convert_mesh_crazyspace_detect(t, tc, em, &crazyspace_data);
146
147 /* Create TransData. */
148 BLI_assert(data_len >= 1);
149 tc->data_len = data_len;
150 tc->data = MEM_calloc_arrayN<TransData>(data_len, "TransObData(Mesh EditMode)");
151
152 TransData *td = tc->data;
153 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
155 continue;
156 }
157
158 int island_index = -1;
159 if (island_data.island_vert_map) {
160 const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
161 island_index = island_data.island_vert_map[connected_index];
162 }
163
164 float *weight = static_cast<float *>(BM_ELEM_CD_GET_VOID_P(eve, cd_offset));
165 if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
166 mesh_cdata_transdata_create((TransDataBasic *)td, eve, weight, &island_data, island_index);
167
169 createSpaceNormal(td->axismtx, eve->no);
170 }
171 else {
172 /* Setting normals. */
173 copy_v3_v3(td->axismtx[2], eve->no);
174 td->axismtx[0][0] = td->axismtx[0][1] = td->axismtx[0][2] = td->axismtx[1][0] =
175 td->axismtx[1][1] = td->axismtx[1][2] = 0.0f;
176 }
177
178 if (prop_mode) {
179 if (prop_mode & T_PROP_CONNECTED) {
180 td->dist = dists[a];
181 }
182 else {
183 td->dist = FLT_MAX;
184 }
185 }
186
187 /* CrazySpace. */
189 mtx,
190 smtx,
191 !crazyspace_data.defmats.is_empty() ? crazyspace_data.defmats[a].ptr() : nullptr,
192 crazyspace_data.quats && BM_elem_flag_test(eve, BM_ELEM_TAG) ?
193 crazyspace_data.quats[a] :
194 nullptr,
195 td);
196
197 td++;
198 }
199 }
200
203 if (dists) {
204 MEM_freeN(dists);
205 }
206 if (dists_index) {
207 MEM_freeN(dists_index);
208 }
209 }
210}
211
213/* -------------------------------------------------------------------- */
216
218{
220 DEG_id_tag_update(static_cast<ID *>(tc->obedit->data), ID_RECALC_GEOMETRY);
221 }
222}
223
225
227 /*flags*/ (T_EDIT | T_POINTS),
228 /*create_trans_data*/ createTransMeshVertCData,
229 /*recalc_data*/ recalcData_mesh_cdata,
230 /*special_aftertrans_update*/ nullptr,
231};
232
233} // namespace blender::ed::transform
bool CustomData_has_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:61
#define BLI_assert(a)
Definition BLI_assert.h:46
void pseudoinverse_m3_m3(float inverse[3][3], const float mat[3][3], float epsilon)
void copy_m3_m4(float m1[3][3], const float m2[4][4])
#define PSEUDOINVERSE_EPSILON
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define ELEM(...)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ CD_PROP_FLOAT
@ SCE_SELECT_VERTEX
@ V3D_AROUND_LOCAL_ORIGINS
@ BM_ELEM_HIDDEN
@ BM_ELEM_SELECT
@ BM_ELEM_TAG
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
#define BM_elem_flag_test(ele, hflag)
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const StringRef name)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_VERTS_OF_MESH
BMesh * bm
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static void mesh_cdata_transdata_create(TransDataBasic *td, BMVert *eve, float *weight, const TransIslandData *island_data, const int island_index)
static void createTransMeshVertCData(bContext *, TransInfo *t)
void transform_convert_mesh_islanddata_free(TransIslandData *island_data)
void transform_convert_mesh_crazyspace_free(TransMeshDataCrazySpace *r_crazyspace_data)
static float * mesh_cdata_transdata_center(const TransIslandData *island_data, const int island_index, BMVert *eve)
void transform_convert_mesh_crazyspace_detect(TransInfo *t, TransDataContainer *tc, BMEditMesh *em, TransMeshDataCrazySpace *r_crazyspace_data)
void transform_convert_mesh_crazyspace_transdata_set(const float mtx[3][3], const float smtx[3][3], const float defmat[3][3], const float quat[4], TransData *r_td)
static void recalcData_mesh_cdata(TransInfo *t)
bool createSpaceNormal(float mat[3][3], const float normal[3])
void transform_convert_mesh_connectivity_distance(BMesh *bm, const float mtx[3][3], float *dists, int *index)
void transform_convert_mesh_islands_calc(BMEditMesh *em, bool calc_single_islands, bool calc_island_center, bool calc_island_axismtx, TransIslandData *r_island_data)
#define FLT_MAX
Definition stdcycles.h:14
short selectmode
float co[3]
float no[3]
Definition DNA_ID.h:414
#define T_PROP_EDIT_ALL
Definition transform.hh:28
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
Definition transform.hh:42
conversion and adaptation of different datablocks to a common struct.