PageRenderTime 41ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/blender-2.63a/source/blender/bmesh/intern/bmesh_interp.c

#
C | 912 lines | 612 code | 162 blank | 138 comment | 108 complexity | b4f757c48fcf1c633879ca9a744eeba9 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, BSD-3-Clause, LGPL-3.0, BSD-2-Clause, Apache-2.0, AGPL-1.0
  1. /*
  2. * ***** BEGIN GPL LICENSE BLOCK *****
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software Foundation,
  16. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. *
  18. * The Original Code is Copyright (C) 2007 Blender Foundation.
  19. * All rights reserved.
  20. *
  21. * The Original Code is: all of this file.
  22. *
  23. * Contributor(s): Geoffrey Bantle.
  24. *
  25. * ***** END GPL LICENSE BLOCK *****
  26. */
  27. /** \file blender/bmesh/intern/bmesh_interp.c
  28. * \ingroup bmesh
  29. *
  30. * Functions for interpolating data across the surface of a mesh.
  31. */
  32. #include "MEM_guardedalloc.h"
  33. #include "DNA_mesh_types.h"
  34. #include "DNA_meshdata_types.h"
  35. #include "BKE_customdata.h"
  36. #include "BKE_multires.h"
  37. #include "BLI_array.h"
  38. #include "BLI_math.h"
  39. #include "bmesh.h"
  40. #include "intern/bmesh_private.h"
  41. /**
  42. * \brief Data, Interp From Verts
  43. *
  44. * Interpolates per-vertex data from two sources to a target.
  45. */
  46. void BM_data_interp_from_verts(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, const float fac)
  47. {
  48. if (v1->head.data && v2->head.data) {
  49. /* first see if we can avoid interpolation */
  50. if (fac <= 0.0f) {
  51. if (v1 == v) {
  52. /* do nothing */
  53. }
  54. else {
  55. CustomData_bmesh_free_block(&bm->vdata, &v->head.data);
  56. CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, v1->head.data, &v->head.data);
  57. }
  58. }
  59. else if (fac >= 1.0f) {
  60. if (v2 == v) {
  61. /* do nothing */
  62. }
  63. else {
  64. CustomData_bmesh_free_block(&bm->vdata, &v->head.data);
  65. CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, v2->head.data, &v->head.data);
  66. }
  67. }
  68. else {
  69. void *src[2];
  70. float w[2];
  71. src[0] = v1->head.data;
  72. src[1] = v2->head.data;
  73. w[0] = 1.0f-fac;
  74. w[1] = fac;
  75. CustomData_bmesh_interp(&bm->vdata, src, w, NULL, 2, v->head.data);
  76. }
  77. }
  78. }
  79. /**
  80. * \brief Data Vert Average
  81. *
  82. * Sets all the customdata (e.g. vert, loop) associated with a vert
  83. * to the average of the face regions surrounding it.
  84. */
  85. static void UNUSED_FUNCTION(BM_Data_Vert_Average)(BMesh *UNUSED(bm), BMFace *UNUSED(f))
  86. {
  87. // BMIter iter;
  88. }
  89. /**
  90. * \brief Data Face-Vert Edge Interp
  91. *
  92. * Walks around the faces of an edge and interpolates the per-face-edge
  93. * data between two sources to a target.
  94. */
  95. void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BMVert *v, BMEdge *e1, const float fac)
  96. {
  97. void *src[2];
  98. float w[2];
  99. BMLoop *v1loop = NULL, *vloop = NULL, *v2loop = NULL;
  100. BMLoop *l_iter = NULL;
  101. if (!e1->l) {
  102. return;
  103. }
  104. w[1] = 1.0f - fac;
  105. w[0] = fac;
  106. l_iter = e1->l;
  107. do {
  108. if (l_iter->v == v1) {
  109. v1loop = l_iter;
  110. vloop = v1loop->next;
  111. v2loop = vloop->next;
  112. }
  113. else if (l_iter->v == v) {
  114. v1loop = l_iter->next;
  115. vloop = l_iter;
  116. v2loop = l_iter->prev;
  117. }
  118. if (!v1loop || !v2loop)
  119. return;
  120. src[0] = v1loop->head.data;
  121. src[1] = v2loop->head.data;
  122. CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, vloop->head.data);
  123. } while ((l_iter = l_iter->radial_next) != e1->l);
  124. }
  125. /**
  126. * \brief Data Interp From Face
  127. *
  128. * projects target onto source, and pulls interpolated customdata from
  129. * source.
  130. *
  131. * \note Only handles loop customdata. multires is handled.
  132. */
  133. void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source)
  134. {
  135. BMLoop *l_iter;
  136. BMLoop *l_first;
  137. void **blocks = NULL;
  138. float (*cos)[3] = NULL, *w = NULL;
  139. BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__);
  140. BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__);
  141. BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__);
  142. int i;
  143. BM_elem_attrs_copy(bm, bm, source, target);
  144. i = 0;
  145. l_iter = l_first = BM_FACE_FIRST_LOOP(source);
  146. do {
  147. copy_v3_v3(cos[i], l_iter->v->co);
  148. blocks[i] = l_iter->head.data;
  149. i++;
  150. } while ((l_iter = l_iter->next) != l_first);
  151. i = 0;
  152. l_iter = l_first = BM_FACE_FIRST_LOOP(target);
  153. do {
  154. interp_weights_poly_v3(w, cos, source->len, l_iter->v->co);
  155. CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, source->len, l_iter->head.data);
  156. i++;
  157. } while ((l_iter = l_iter->next) != l_first);
  158. BLI_array_fixedstack_free(cos);
  159. BLI_array_fixedstack_free(w);
  160. BLI_array_fixedstack_free(blocks);
  161. }
  162. /**
  163. * \brief Multires Interpolation
  164. *
  165. * mdisps is a grid of displacements, ordered thus:
  166. *
  167. * v1/center----v4/next -> x
  168. * | |
  169. * | |
  170. * v2/prev------v3/cur
  171. * |
  172. * V
  173. * y
  174. */
  175. static int compute_mdisp_quad(BMLoop *l, float v1[3], float v2[3], float v3[3], float v4[3],
  176. float e1[3], float e2[3])
  177. {
  178. float cent[3] = {0.0f, 0.0f, 0.0f}, n[3], p[3];
  179. BMLoop *l_first;
  180. BMLoop *l_iter;
  181. /* computer center */
  182. l_iter = l_first = BM_FACE_FIRST_LOOP(l->f);
  183. do {
  184. cent[0] += (float)l_iter->v->co[0];
  185. cent[1] += (float)l_iter->v->co[1];
  186. cent[2] += (float)l_iter->v->co[2];
  187. } while ((l_iter = l_iter->next) != l_first);
  188. mul_v3_fl(cent, (1.0 / (float)l->f->len));
  189. add_v3_v3v3(p, l->prev->v->co, l->v->co);
  190. mul_v3_fl(p, 0.5);
  191. add_v3_v3v3(n, l->next->v->co, l->v->co);
  192. mul_v3_fl(n, 0.5);
  193. copy_v3_v3(v1, cent);
  194. copy_v3_v3(v2, p);
  195. copy_v3_v3(v3, l->v->co);
  196. copy_v3_v3(v4, n);
  197. sub_v3_v3v3(e1, v2, v1);
  198. sub_v3_v3v3(e2, v3, v4);
  199. return 1;
  200. }
  201. /* funnily enough, I think this is identical to face_to_crn_interp, heh */
  202. static float quad_coord(float aa[3], float bb[3], float cc[3], float dd[3], int a1, int a2)
  203. {
  204. float x, y, z, f1;
  205. x = aa[a1] * cc[a2] - cc[a1] * aa[a2];
  206. y = aa[a1] * dd[a2] + bb[a1] * cc[a2] - cc[a1] * bb[a2] - dd[a1] * aa[a2];
  207. z = bb[a1] * dd[a2] - dd[a1] * bb[a2];
  208. if (fabsf(2.0f * (x - y + z)) > FLT_EPSILON * 10.0f) {
  209. float f2;
  210. f1 = (sqrt(y * y - 4.0 * x * z) - y + 2.0 * z) / (2.0 * (x - y + z));
  211. f2 = (-sqrt(y * y - 4.0 * x * z) - y + 2.0 * z) / (2.0 * (x - y + z));
  212. f1 = fabsf(f1);
  213. f2 = fabsf(f2);
  214. f1 = MIN2(f1, f2);
  215. CLAMP(f1, 0.0f, 1.0f + FLT_EPSILON);
  216. }
  217. else {
  218. f1 = -z / (y - 2 * z);
  219. CLAMP(f1, 0.0f, 1.0f + FLT_EPSILON);
  220. if (isnan(f1) || f1 > 1.0 || f1 < 0.0f) {
  221. int i;
  222. for (i = 0; i < 2; i++) {
  223. if (fabsf(aa[i]) < FLT_EPSILON * 100.0f)
  224. return aa[(i + 1) % 2] / fabsf(bb[(i + 1) % 2] - aa[(i + 1) % 2]);
  225. if (fabsf(cc[i]) < FLT_EPSILON * 100.0f)
  226. return cc[(i + 1) % 2] / fabsf(dd[(i + 1) % 2] - cc[(i + 1) % 2]);
  227. }
  228. }
  229. }
  230. return f1;
  231. }
  232. static int quad_co(float *x, float *y, float v1[3], float v2[3], float v3[3], float v4[3],
  233. float p[3], float n[3])
  234. {
  235. float projverts[5][3], n2[3];
  236. float dprojverts[4][3], origin[3] = {0.0f, 0.0f, 0.0f};
  237. int i;
  238. /* project points into 2d along normal */
  239. copy_v3_v3(projverts[0], v1);
  240. copy_v3_v3(projverts[1], v2);
  241. copy_v3_v3(projverts[2], v3);
  242. copy_v3_v3(projverts[3], v4);
  243. copy_v3_v3(projverts[4], p);
  244. normal_quad_v3(n2, projverts[0], projverts[1], projverts[2], projverts[3]);
  245. if (dot_v3v3(n, n2) < -FLT_EPSILON) {
  246. return 0;
  247. }
  248. /* rotate */
  249. poly_rotate_plane(n, projverts, 5);
  250. /* flatten */
  251. for (i = 0; i < 5; i++) {
  252. projverts[i][2] = 0.0f;
  253. }
  254. /* subtract origin */
  255. for (i = 0; i < 4; i++) {
  256. sub_v3_v3(projverts[i], projverts[4]);
  257. }
  258. copy_v3_v3(dprojverts[0], projverts[0]);
  259. copy_v3_v3(dprojverts[1], projverts[1]);
  260. copy_v3_v3(dprojverts[2], projverts[2]);
  261. copy_v3_v3(dprojverts[3], projverts[3]);
  262. if (!isect_point_quad_v2(origin, dprojverts[0], dprojverts[1], dprojverts[2], dprojverts[3])) {
  263. return 0;
  264. }
  265. *y = quad_coord(dprojverts[1], dprojverts[0], dprojverts[2], dprojverts[3], 0, 1);
  266. *x = quad_coord(dprojverts[2], dprojverts[1], dprojverts[3], dprojverts[0], 0, 1);
  267. return 1;
  268. }
  269. static void mdisp_axis_from_quad(float v1[3], float v2[3], float UNUSED(v3[3]), float v4[3],
  270. float axis_x[3], float axis_y[3])
  271. {
  272. sub_v3_v3v3(axis_x, v4, v1);
  273. sub_v3_v3v3(axis_y, v2, v1);
  274. normalize_v3(axis_x);
  275. normalize_v3(axis_y);
  276. }
  277. /* tl is loop to project onto, l is loop whose internal displacement, co, is being
  278. * projected. x and y are location in loop's mdisps grid of point co. */
  279. static int mdisp_in_mdispquad(BMLoop *l, BMLoop *tl, float p[3], float *x, float *y,
  280. int res, float axis_x[3], float axis_y[3])
  281. {
  282. float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3];
  283. float eps = FLT_EPSILON * 4000;
  284. if (len_v3(l->v->no) == 0.0f)
  285. BM_vert_normal_update_all(l->v);
  286. if (len_v3(tl->v->no) == 0.0f)
  287. BM_vert_normal_update_all(tl->v);
  288. compute_mdisp_quad(tl, v1, v2, v3, v4, e1, e2);
  289. /* expand quad a bit */
  290. cent_quad_v3(c, v1, v2, v3, v4);
  291. sub_v3_v3(v1, c); sub_v3_v3(v2, c);
  292. sub_v3_v3(v3, c); sub_v3_v3(v4, c);
  293. mul_v3_fl(v1, 1.0 + eps); mul_v3_fl(v2, 1.0 + eps);
  294. mul_v3_fl(v3, 1.0 + eps); mul_v3_fl(v4, 1.0 + eps);
  295. add_v3_v3(v1, c); add_v3_v3(v2, c);
  296. add_v3_v3(v3, c); add_v3_v3(v4, c);
  297. if (!quad_co(x, y, v1, v2, v3, v4, p, l->v->no))
  298. return 0;
  299. *x *= res - 1;
  300. *y *= res - 1;
  301. mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y);
  302. return 1;
  303. }
  304. static float bm_loop_flip_equotion(float mat[2][2], float b[2], float target_axis_x[3], float target_axis_y[3],
  305. float coord[3], int i, int j)
  306. {
  307. mat[0][0] = target_axis_x[i];
  308. mat[0][1] = target_axis_y[i];
  309. mat[1][0] = target_axis_x[j];
  310. mat[1][1] = target_axis_y[j];
  311. b[0] = coord[i];
  312. b[1] = coord[j];
  313. return mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0];
  314. }
  315. static void bm_loop_flip_disp(float source_axis_x[3], float source_axis_y[3],
  316. float target_axis_x[3], float target_axis_y[3], float disp[3])
  317. {
  318. float vx[3], vy[3], coord[3];
  319. float n[3], vec[3];
  320. float b[2], mat[2][2], d;
  321. mul_v3_v3fl(vx, source_axis_x, disp[0]);
  322. mul_v3_v3fl(vy, source_axis_y, disp[1]);
  323. add_v3_v3v3(coord, vx, vy);
  324. /* project displacement from source grid plane onto target grid plane */
  325. cross_v3_v3v3(n, target_axis_x, target_axis_y);
  326. project_v3_v3v3(vec, coord, n);
  327. sub_v3_v3v3(coord, coord, vec);
  328. d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 1);
  329. if (fabsf(d) < 1e-4) {
  330. d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 2);
  331. if (fabsf(d) < 1e-4)
  332. d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 1, 2);
  333. }
  334. disp[0] = (b[0] * mat[1][1] - mat[0][1] * b[1]) / d;
  335. disp[1] = (mat[0][0] * b[1] - b[0] * mat[1][0]) / d;
  336. }
  337. static void bm_loop_interp_mdisps(BMesh *bm, BMLoop *target, BMFace *source)
  338. {
  339. MDisps *mdisps;
  340. BMLoop *l_iter;
  341. BMLoop *l_first;
  342. float x, y, d, v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3];
  343. int ix, iy, res;
  344. float axis_x[3], axis_y[3];
  345. /* ignore 2-edged faces */
  346. if (target->f->len < 3)
  347. return;
  348. if (!CustomData_has_layer(&bm->ldata, CD_MDISPS))
  349. return;
  350. mdisps = CustomData_bmesh_get(&bm->ldata, target->head.data, CD_MDISPS);
  351. compute_mdisp_quad(target, v1, v2, v3, v4, e1, e2);
  352. /* if no disps data allocate a new grid, the size of the first grid in source. */
  353. if (!mdisps->totdisp) {
  354. MDisps *md2 = CustomData_bmesh_get(&bm->ldata, BM_FACE_FIRST_LOOP(source)->head.data, CD_MDISPS);
  355. mdisps->totdisp = md2->totdisp;
  356. mdisps->level = md2->level;
  357. if (mdisps->totdisp) {
  358. mdisps->disps = MEM_callocN(sizeof(float) * 3 * mdisps->totdisp,
  359. "mdisp->disps in bmesh_loop_intern_mdisps");
  360. }
  361. else {
  362. return;
  363. }
  364. }
  365. mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y);
  366. res = (int)sqrt(mdisps->totdisp);
  367. d = 1.0 / (float)(res - 1);
  368. for (x = 0.0f, ix = 0; ix < res; x += d, ix++) {
  369. for (y = 0.0f, iy = 0; iy < res; y += d, iy++) {
  370. float co1[3], co2[3], co[3];
  371. copy_v3_v3(co1, e1);
  372. mul_v3_fl(co1, y);
  373. add_v3_v3(co1, v1);
  374. copy_v3_v3(co2, e2);
  375. mul_v3_fl(co2, y);
  376. add_v3_v3(co2, v4);
  377. sub_v3_v3v3(co, co2, co1);
  378. mul_v3_fl(co, x);
  379. add_v3_v3(co, co1);
  380. l_iter = l_first = BM_FACE_FIRST_LOOP(source);
  381. do {
  382. float x2, y2;
  383. MDisps *md1, *md2;
  384. float src_axis_x[3], src_axis_y[3];
  385. md1 = CustomData_bmesh_get(&bm->ldata, target->head.data, CD_MDISPS);
  386. md2 = CustomData_bmesh_get(&bm->ldata, l_iter->head.data, CD_MDISPS);
  387. if (mdisp_in_mdispquad(target, l_iter, co, &x2, &y2, res, src_axis_x, src_axis_y)) {
  388. old_mdisps_bilinear(md1->disps[iy * res + ix], md2->disps, res, (float)x2, (float)y2);
  389. bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md1->disps[iy * res + ix]);
  390. break;
  391. }
  392. } while ((l_iter = l_iter->next) != l_first);
  393. }
  394. }
  395. }
  396. /**
  397. * smoothes boundaries between multires grids,
  398. * including some borders in adjacent faces
  399. */
  400. void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
  401. {
  402. BMLoop *l;
  403. BMIter liter;
  404. if (!CustomData_has_layer(&bm->ldata, CD_MDISPS))
  405. return;
  406. BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
  407. MDisps *mdp = CustomData_bmesh_get(&bm->ldata, l->prev->head.data, CD_MDISPS);
  408. MDisps *mdl = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MDISPS);
  409. MDisps *mdn = CustomData_bmesh_get(&bm->ldata, l->next->head.data, CD_MDISPS);
  410. float co1[3];
  411. int sides;
  412. int y;
  413. /*
  414. * mdisps is a grid of displacements, ordered thus:
  415. *
  416. * v4/next
  417. * |
  418. * | v1/cent-----mid2 ---> x
  419. * | | |
  420. * | | |
  421. * v2/prev---mid1-----v3/cur
  422. * |
  423. * V
  424. * y
  425. */
  426. sides = (int)sqrt(mdp->totdisp);
  427. for (y = 0; y < sides; y++) {
  428. add_v3_v3v3(co1, mdn->disps[y * sides], mdl->disps[y]);
  429. mul_v3_fl(co1, 0.5);
  430. copy_v3_v3(mdn->disps[y * sides], co1);
  431. copy_v3_v3(mdl->disps[y], co1);
  432. }
  433. }
  434. BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
  435. MDisps *mdl1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MDISPS);
  436. MDisps *mdl2;
  437. float co1[3], co2[3], co[3];
  438. int sides;
  439. int y;
  440. /*
  441. * mdisps is a grid of displacements, ordered thus:
  442. *
  443. * v4/next
  444. * |
  445. * | v1/cent-----mid2 ---> x
  446. * | | |
  447. * | | |
  448. * v2/prev---mid1-----v3/cur
  449. * |
  450. * V
  451. * y
  452. */
  453. if (l->radial_next == l)
  454. continue;
  455. if (l->radial_next->v == l->v)
  456. mdl2 = CustomData_bmesh_get(&bm->ldata, l->radial_next->head.data, CD_MDISPS);
  457. else
  458. mdl2 = CustomData_bmesh_get(&bm->ldata, l->radial_next->next->head.data, CD_MDISPS);
  459. sides = (int)sqrt(mdl1->totdisp);
  460. for (y = 0; y < sides; y++) {
  461. int a1, a2, o1, o2;
  462. if (l->v != l->radial_next->v) {
  463. a1 = sides * y + sides - 2;
  464. a2 = (sides - 2) * sides + y;
  465. o1 = sides * y + sides - 1;
  466. o2 = (sides - 1) * sides + y;
  467. }
  468. else {
  469. a1 = sides * y + sides - 2;
  470. a2 = sides * y + sides - 2;
  471. o1 = sides * y + sides - 1;
  472. o2 = sides * y + sides - 1;
  473. }
  474. /* magic blending numbers, hardcoded! */
  475. add_v3_v3v3(co1, mdl1->disps[a1], mdl2->disps[a2]);
  476. mul_v3_fl(co1, 0.18);
  477. add_v3_v3v3(co2, mdl1->disps[o1], mdl2->disps[o2]);
  478. mul_v3_fl(co2, 0.32);
  479. add_v3_v3v3(co, co1, co2);
  480. copy_v3_v3(mdl1->disps[o1], co);
  481. copy_v3_v3(mdl2->disps[o2], co);
  482. }
  483. }
  484. }
  485. /**
  486. * project the multires grid in target onto source's set of multires grids
  487. */
  488. void BM_loop_interp_multires(BMesh *bm, BMLoop *target, BMFace *source)
  489. {
  490. bm_loop_interp_mdisps(bm, target, source);
  491. }
  492. /**
  493. * projects a single loop, target, onto source for customdata interpolation. multires is handled.
  494. * if do_vertex is true, target's vert data will also get interpolated.
  495. */
  496. void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
  497. int do_vertex, int do_multires)
  498. {
  499. BMLoop *l_iter;
  500. BMLoop *l_first;
  501. void **blocks = NULL;
  502. void **vblocks = NULL;
  503. float (*cos)[3] = NULL, co[3], *w = NULL;
  504. float cent[3] = {0.0f, 0.0f, 0.0f};
  505. BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__);
  506. BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__);
  507. BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__);
  508. BLI_array_fixedstack_declare(vblocks, BM_NGON_STACK_SIZE, do_vertex ? source->len : 0, __func__);
  509. int i, ax, ay;
  510. BM_elem_attrs_copy(bm, bm, source, target->f);
  511. i = 0;
  512. l_iter = l_first = BM_FACE_FIRST_LOOP(source);
  513. do {
  514. copy_v3_v3(cos[i], l_iter->v->co);
  515. add_v3_v3(cent, cos[i]);
  516. w[i] = 0.0f;
  517. blocks[i] = l_iter->head.data;
  518. if (do_vertex) {
  519. vblocks[i] = l_iter->v->head.data;
  520. }
  521. i++;
  522. } while ((l_iter = l_iter->next) != l_first);
  523. /* find best projection of face XY, XZ or YZ: barycentric weights of
  524. * the 2d projected coords are the same and faster to compute */
  525. axis_dominant_v3(&ax, &ay, source->no);
  526. /* scale source face coordinates a bit, so points sitting directly on an
  527. * edge will work. */
  528. mul_v3_fl(cent, 1.0f / (float)source->len);
  529. for (i = 0; i < source->len; i++) {
  530. float vec[3], tmp[3];
  531. sub_v3_v3v3(vec, cent, cos[i]);
  532. mul_v3_fl(vec, 0.001f);
  533. add_v3_v3(cos[i], vec);
  534. copy_v3_v3(tmp, cos[i]);
  535. cos[i][0] = tmp[ax];
  536. cos[i][1] = tmp[ay];
  537. cos[i][2] = 0.0f;
  538. }
  539. /* interpolate */
  540. co[0] = target->v->co[ax];
  541. co[1] = target->v->co[ay];
  542. co[2] = 0.0f;
  543. interp_weights_poly_v3(w, cos, source->len, co);
  544. CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, source->len, target->head.data);
  545. if (do_vertex) {
  546. CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, source->len, target->v->head.data);
  547. BLI_array_fixedstack_free(vblocks);
  548. }
  549. BLI_array_fixedstack_free(cos);
  550. BLI_array_fixedstack_free(w);
  551. BLI_array_fixedstack_free(blocks);
  552. if (do_multires) {
  553. if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
  554. bm_loop_interp_mdisps(bm, target, source);
  555. }
  556. }
  557. }
  558. void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source)
  559. {
  560. BMLoop *l_iter;
  561. BMLoop *l_first;
  562. void **blocks = NULL;
  563. float (*cos)[3] = NULL, *w = NULL;
  564. float cent[3] = {0.0f, 0.0f, 0.0f};
  565. BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__);
  566. BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__);
  567. BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__);
  568. int i;
  569. i = 0;
  570. l_iter = l_first = BM_FACE_FIRST_LOOP(source);
  571. do {
  572. copy_v3_v3(cos[i], l_iter->v->co);
  573. add_v3_v3(cent, cos[i]);
  574. w[i] = 0.0f;
  575. blocks[i] = l_iter->v->head.data;
  576. i++;
  577. } while ((l_iter = l_iter->next) != l_first);
  578. /* scale source face coordinates a bit, so points sitting directly on an
  579. * edge will work. */
  580. mul_v3_fl(cent, 1.0f / (float)source->len);
  581. for (i = 0; i < source->len; i++) {
  582. float vec[3];
  583. sub_v3_v3v3(vec, cent, cos[i]);
  584. mul_v3_fl(vec, 0.01f);
  585. add_v3_v3(cos[i], vec);
  586. }
  587. /* interpolate */
  588. interp_weights_poly_v3(w, cos, source->len, v->co);
  589. CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, source->len, v->head.data);
  590. BLI_array_fixedstack_free(cos);
  591. BLI_array_fixedstack_free(w);
  592. BLI_array_fixedstack_free(blocks);
  593. }
  594. static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
  595. {
  596. BMIter iter;
  597. BLI_mempool *oldpool = olddata->pool;
  598. void *block;
  599. if (data == &bm->vdata) {
  600. BMVert *eve;
  601. CustomData_bmesh_init_pool(data, bm->totvert, BM_VERT);
  602. BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
  603. block = NULL;
  604. CustomData_bmesh_set_default(data, &block);
  605. CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block);
  606. CustomData_bmesh_free_block(olddata, &eve->head.data);
  607. eve->head.data = block;
  608. }
  609. }
  610. else if (data == &bm->edata) {
  611. BMEdge *eed;
  612. CustomData_bmesh_init_pool(data, bm->totedge, BM_EDGE);
  613. BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
  614. block = NULL;
  615. CustomData_bmesh_set_default(data, &block);
  616. CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block);
  617. CustomData_bmesh_free_block(olddata, &eed->head.data);
  618. eed->head.data = block;
  619. }
  620. }
  621. else if (data == &bm->ldata) {
  622. BMIter liter;
  623. BMFace *efa;
  624. BMLoop *l;
  625. CustomData_bmesh_init_pool(data, bm->totloop, BM_LOOP);
  626. BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
  627. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  628. block = NULL;
  629. CustomData_bmesh_set_default(data, &block);
  630. CustomData_bmesh_copy_data(olddata, data, l->head.data, &block);
  631. CustomData_bmesh_free_block(olddata, &l->head.data);
  632. l->head.data = block;
  633. }
  634. }
  635. }
  636. else if (data == &bm->pdata) {
  637. BMFace *efa;
  638. CustomData_bmesh_init_pool(data, bm->totface, BM_FACE);
  639. BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
  640. block = NULL;
  641. CustomData_bmesh_set_default(data, &block);
  642. CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block);
  643. CustomData_bmesh_free_block(olddata, &efa->head.data);
  644. efa->head.data = block;
  645. }
  646. }
  647. else {
  648. /* should never reach this! */
  649. BLI_assert(0);
  650. }
  651. if (oldpool) {
  652. /* this should never happen but can when dissolve fails - [#28960] */
  653. BLI_assert(data->pool != oldpool);
  654. BLI_mempool_destroy(oldpool);
  655. }
  656. }
  657. void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
  658. {
  659. CustomData olddata;
  660. olddata = *data;
  661. olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers): NULL;
  662. /* the pool is now owned by olddata and must not be shared */
  663. data->pool = NULL;
  664. CustomData_add_layer(data, type, CD_DEFAULT, NULL, 0);
  665. update_data_blocks(bm, &olddata, data);
  666. if (olddata.layers) MEM_freeN(olddata.layers);
  667. }
  668. void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name)
  669. {
  670. CustomData olddata;
  671. olddata = *data;
  672. olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers): NULL;
  673. /* the pool is now owned by olddata and must not be shared */
  674. data->pool = NULL;
  675. CustomData_add_layer_named(data, type, CD_DEFAULT, NULL, 0, name);
  676. update_data_blocks(bm, &olddata, data);
  677. if (olddata.layers) MEM_freeN(olddata.layers);
  678. }
  679. void BM_data_layer_free(BMesh *bm, CustomData *data, int type)
  680. {
  681. CustomData olddata;
  682. olddata = *data;
  683. olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers): NULL;
  684. /* the pool is now owned by olddata and must not be shared */
  685. data->pool = NULL;
  686. CustomData_free_layer_active(data, type, 0);
  687. update_data_blocks(bm, &olddata, data);
  688. if (olddata.layers) MEM_freeN(olddata.layers);
  689. }
  690. void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n)
  691. {
  692. CustomData olddata;
  693. olddata = *data;
  694. olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers): NULL;
  695. /* the pool is now owned by olddata and must not be shared */
  696. data->pool = NULL;
  697. CustomData_free_layer(data, type, 0, CustomData_get_layer_index_n(data, type, n));
  698. update_data_blocks(bm, &olddata, data);
  699. if (olddata.layers) MEM_freeN(olddata.layers);
  700. }
  701. void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n)
  702. {
  703. BMIter iter;
  704. if (&bm->vdata == data) {
  705. BMVert *eve;
  706. BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
  707. void *ptr = CustomData_bmesh_get_n(data, eve->head.data, type, dst_n);
  708. CustomData_bmesh_set_n(data, eve->head.data, type, src_n, ptr);
  709. }
  710. }
  711. else if (&bm->edata == data) {
  712. BMEdge *eed;
  713. BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
  714. void *ptr = CustomData_bmesh_get_n(data, eed->head.data, type, dst_n);
  715. CustomData_bmesh_set_n(data, eed->head.data, type, src_n, ptr);
  716. }
  717. }
  718. else if (&bm->pdata == data) {
  719. BMFace *efa;
  720. BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
  721. void *ptr = CustomData_bmesh_get_n(data, efa->head.data, type, dst_n);
  722. CustomData_bmesh_set_n(data, efa->head.data, type, src_n, ptr);
  723. }
  724. }
  725. else if (&bm->ldata == data) {
  726. BMIter liter;
  727. BMFace *efa;
  728. BMLoop *l;
  729. BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
  730. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  731. void *ptr = CustomData_bmesh_get_n(data, l->head.data, type, dst_n);
  732. CustomData_bmesh_set_n(data, l->head.data, type, src_n, ptr);
  733. }
  734. }
  735. }
  736. else {
  737. /* should never reach this! */
  738. BLI_assert(0);
  739. }
  740. }
  741. float BM_elem_float_data_get(CustomData *cd, void *element, int type)
  742. {
  743. float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
  744. return f ? *f : 0.0f;
  745. }
  746. void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val)
  747. {
  748. float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
  749. if (f) *f = val;
  750. }