| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2007 Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 08:08:12 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup bmesh | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Functions for interpolating data across the surface of a mesh. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_meshdata_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-28 10:38:25 +00:00
										 |  |  | #include "BLI_alloca.h"
 | 
					
						
							| 
									
										
										
										
											2017-11-26 13:06:39 +01:00
										 |  |  | #include "BLI_linklist.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | #include "BLI_math.h"
 | 
					
						
							| 
									
										
										
										
											2017-11-26 13:06:39 +01:00
										 |  |  | #include "BLI_memarena.h"
 | 
					
						
							|  |  |  | #include "BLI_task.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-05 17:56:54 +00:00
										 |  |  | #include "BKE_customdata.h"
 | 
					
						
							|  |  |  | #include "BKE_multires.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | #include "bmesh.h"
 | 
					
						
							| 
									
										
										
										
											2012-03-08 03:25:53 +00:00
										 |  |  | #include "intern/bmesh_private.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-01 13:53:25 +10:00
										 |  |  | /* edge and vertex share, currently there's no need to have different logic */ | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  | static void bm_data_interp_from_elem(CustomData *data_layer, | 
					
						
							|  |  |  |                                      const BMElem *ele_src_1, | 
					
						
							|  |  |  |                                      const BMElem *ele_src_2, | 
					
						
							|  |  |  |                                      BMElem *ele_dst, | 
					
						
							|  |  |  |                                      const float fac) | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   if (ele_src_1->head.data && ele_src_2->head.data) { | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     /* first see if we can avoid interpolation */ | 
					
						
							|  |  |  |     if (fac <= 0.0f) { | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |       if (ele_src_1 == ele_dst) { | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |         /* do nothing */ | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2014-09-24 18:50:29 +10:00
										 |  |  |         CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data); | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |         CustomData_bmesh_copy_data( | 
					
						
							|  |  |  |             data_layer, data_layer, ele_src_1->head.data, &ele_dst->head.data); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (fac >= 1.0f) { | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |       if (ele_src_2 == ele_dst) { | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |         /* do nothing */ | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2014-09-24 18:50:29 +10:00
										 |  |  |         CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data); | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |         CustomData_bmesh_copy_data( | 
					
						
							|  |  |  |             data_layer, data_layer, ele_src_2->head.data, &ele_dst->head.data); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     else { | 
					
						
							| 
									
										
										
										
											2015-02-23 13:51:55 +11:00
										 |  |  |       const void *src[2]; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       float w[2]; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |       src[0] = ele_src_1->head.data; | 
					
						
							|  |  |  |       src[1] = ele_src_2->head.data; | 
					
						
							| 
									
										
										
										
											2012-05-03 19:57:24 +00:00
										 |  |  |       w[0] = 1.0f - fac; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       w[1] = fac; | 
					
						
							| 
									
										
										
										
											2012-08-23 09:20:15 +00:00
										 |  |  |       CustomData_bmesh_interp(data_layer, src, w, NULL, 2, ele_dst->head.data); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-23 05:19:40 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * \brief Data, Interp From Verts | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |  * Interpolates per-vertex data from two sources to \a v_dst | 
					
						
							| 
									
										
										
										
											2012-08-23 05:19:40 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \note This is an exact match to #BM_data_interp_from_edges | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  | void BM_data_interp_from_verts( | 
					
						
							|  |  |  |     BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac) | 
					
						
							| 
									
										
										
										
											2012-08-23 05:19:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   bm_data_interp_from_elem( | 
					
						
							|  |  |  |       &bm->vdata, (const BMElem *)v_src_1, (const BMElem *)v_src_2, (BMElem *)v_dst, fac); | 
					
						
							| 
									
										
										
										
											2012-08-23 05:19:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * \brief Data, Interp From Edges | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |  * Interpolates per-edge data from two sources to \a e_dst. | 
					
						
							| 
									
										
										
										
											2012-08-23 05:19:40 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \note This is an exact match to #BM_data_interp_from_verts | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  | void BM_data_interp_from_edges( | 
					
						
							|  |  |  |     BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac) | 
					
						
							| 
									
										
										
										
											2012-08-23 05:19:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   bm_data_interp_from_elem( | 
					
						
							|  |  |  |       &bm->edata, (const BMElem *)e_src_1, (const BMElem *)e_src_2, (BMElem *)e_dst, fac); | 
					
						
							| 
									
										
										
										
											2012-08-23 05:19:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-29 06:55:10 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * \brief Data Vert Average | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Sets all the customdata (e.g. vert, loop) associated with a vert | 
					
						
							|  |  |  |  * to the average of the face regions surrounding it. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void UNUSED_FUNCTION(BM_Data_Vert_Average)(BMesh *UNUSED(bm), BMFace *UNUSED(f)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   // BMIter iter;
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2012-02-29 06:55:10 +00:00
										 |  |  |  * \brief Data Face-Vert Edge Interp | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |  * Walks around the faces of \a e and interpolates | 
					
						
							|  |  |  |  * the loop data between two sources. | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  | void BM_data_interp_face_vert_edge(BMesh *bm, | 
					
						
							|  |  |  |                                    const BMVert *v_src_1, | 
					
						
							|  |  |  |                                    const BMVert *UNUSED(v_src_2), | 
					
						
							|  |  |  |                                    BMVert *v, | 
					
						
							|  |  |  |                                    BMEdge *e, | 
					
						
							|  |  |  |                                    const float fac) | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   float w[2]; | 
					
						
							| 
									
										
										
										
											2013-03-09 17:12:24 +00:00
										 |  |  |   BMLoop *l_v1 = NULL, *l_v = NULL, *l_v2 = NULL; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   BMLoop *l_iter = NULL; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   if (!e->l) { | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   w[1] = 1.0f - fac; | 
					
						
							|  |  |  |   w[0] = fac; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   l_iter = e->l; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   do { | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |     if (l_iter->v == v_src_1) { | 
					
						
							| 
									
										
										
										
											2013-03-09 17:12:24 +00:00
										 |  |  |       l_v1 = l_iter; | 
					
						
							|  |  |  |       l_v = l_v1->next; | 
					
						
							|  |  |  |       l_v2 = l_v->next; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else if (l_iter->v == v) { | 
					
						
							| 
									
										
										
										
											2013-03-09 17:12:24 +00:00
										 |  |  |       l_v1 = l_iter->next; | 
					
						
							|  |  |  |       l_v = l_iter; | 
					
						
							|  |  |  |       l_v2 = l_iter->prev; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 13:51:55 +11:00
										 |  |  |     if (!l_v1 || !l_v2) { | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       return; | 
					
						
							| 
									
										
										
										
											2015-02-23 13:51:55 +11:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:37:53 +02:00
										 |  |  |     const void *src[2]; | 
					
						
							|  |  |  |     src[0] = l_v1->head.data; | 
					
						
							|  |  |  |     src[1] = l_v2->head.data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_v->head.data); | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   } while ((l_iter = l_iter->radial_next) != e->l); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2012-02-29 06:55:10 +00:00
										 |  |  |  * \brief Data Interp From Face | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-02-29 06:55:10 +00:00
										 |  |  |  * projects target onto source, and pulls interpolated customdata from | 
					
						
							|  |  |  |  * source. | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-02-29 06:55:10 +00:00
										 |  |  |  * \note Only handles loop customdata. multires is handled. | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-02-23 13:51:55 +11:00
										 |  |  | void BM_face_interp_from_face_ex(BMesh *bm, | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |                                  BMFace *f_dst, | 
					
						
							|  |  |  |                                  const BMFace *f_src, | 
					
						
							|  |  |  |                                  const bool do_vertex, | 
					
						
							| 
									
										
										
										
											2015-02-23 13:51:55 +11:00
										 |  |  |                                  const void **blocks_l, | 
					
						
							|  |  |  |                                  const void **blocks_v, | 
					
						
							|  |  |  |                                  float (*cos_2d)[2], | 
					
						
							|  |  |  |                                  float axis_mat[3][3]) | 
					
						
							| 
									
										
										
										
											2013-04-07 11:41:37 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   BMLoop *l_iter; | 
					
						
							|  |  |  |   BMLoop *l_first; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   float *w = BLI_array_alloca(w, f_src->len); | 
					
						
							| 
									
										
										
										
											2013-04-07 11:41:37 +00:00
										 |  |  |   float co[2]; | 
					
						
							|  |  |  |   int i; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   if (f_src != f_dst) { | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |     BM_elem_attrs_copy(bm, bm, f_src, f_dst); | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-07 11:41:37 +00:00
										 |  |  |   /* interpolate */ | 
					
						
							|  |  |  |   i = 0; | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst); | 
					
						
							| 
									
										
										
										
											2013-04-07 11:41:37 +00:00
										 |  |  |   do { | 
					
						
							|  |  |  |     mul_v2_m3v3(co, axis_mat, l_iter->v->co); | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |     interp_weights_poly_v2(w, cos_2d, f_src->len, co); | 
					
						
							|  |  |  |     CustomData_bmesh_interp(&bm->ldata, blocks_l, w, NULL, f_src->len, l_iter->head.data); | 
					
						
							| 
									
										
										
										
											2013-04-10 23:25:44 +00:00
										 |  |  |     if (do_vertex) { | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |       CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, f_src->len, l_iter->v->head.data); | 
					
						
							| 
									
										
										
										
											2013-04-10 23:25:44 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-03-05 09:16:12 +11:00
										 |  |  |   } while ((void)i++, (l_iter = l_iter->next) != l_first); | 
					
						
							| 
									
										
										
										
											2013-04-07 11:41:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  | void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex) | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   BMLoop *l_iter; | 
					
						
							|  |  |  |   BMLoop *l_first; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   const void **blocks_l = BLI_array_alloca(blocks_l, f_src->len); | 
					
						
							|  |  |  |   const void **blocks_v = do_vertex ? BLI_array_alloca(blocks_v, f_src->len) : NULL; | 
					
						
							|  |  |  |   float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len); | 
					
						
							| 
									
										
										
										
											2013-04-07 02:10:15 +00:00
										 |  |  |   float axis_mat[3][3]; /* use normal to transform into 2d xy coords */ | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   int i; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-07 02:10:15 +00:00
										 |  |  |   /* convert the 3d coords into 2d for projection */ | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   BLI_assert(BM_face_is_normal_valid(f_src)); | 
					
						
							|  |  |  |   axis_dominant_v3_to_m3(axis_mat, f_src->no); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   i = 0; | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   l_iter = l_first = BM_FACE_FIRST_LOOP(f_src); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   do { | 
					
						
							| 
									
										
										
										
											2013-04-07 02:10:15 +00:00
										 |  |  |     mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co); | 
					
						
							| 
									
										
										
										
											2013-04-10 23:25:44 +00:00
										 |  |  |     blocks_l[i] = l_iter->head.data; | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |     if (do_vertex) { | 
					
						
							|  |  |  |       blocks_v[i] = l_iter->v->head.data; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-03-05 09:16:12 +11:00
										 |  |  |   } while ((void)i++, (l_iter = l_iter->next) != l_first); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   BM_face_interp_from_face_ex(bm, f_dst, f_src, do_vertex, blocks_l, blocks_v, cos_2d, axis_mat); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-29 06:55:10 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * \brief Multires Interpolation | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * mdisps is a grid of displacements, ordered thus: | 
					
						
							| 
									
										
										
										
											2012-08-13 15:17:15 +00:00
										 |  |  |  * <pre> | 
					
						
							| 
									
										
										
										
											2012-02-29 06:55:10 +00:00
										 |  |  |  *      v1/center----v4/next -> x | 
					
						
							|  |  |  |  *          |           | | 
					
						
							|  |  |  |  *          |           | | 
					
						
							|  |  |  |  *       v2/prev------v3/cur | 
					
						
							|  |  |  |  *          | | 
					
						
							|  |  |  |  *          V | 
					
						
							|  |  |  |  *          y | 
					
						
							| 
									
										
										
										
											2012-08-13 15:17:15 +00:00
										 |  |  |  * </pre> | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-04-25 20:15:20 +10:00
										 |  |  | static int compute_mdisp_quad(const BMLoop *l, | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |                               const float l_f_center[3], | 
					
						
							|  |  |  |                               float v1[3], | 
					
						
							|  |  |  |                               float v2[3], | 
					
						
							|  |  |  |                               float v3[3], | 
					
						
							|  |  |  |                               float v4[3], | 
					
						
							| 
									
										
										
										
											2015-04-25 20:15:20 +10:00
										 |  |  |                               float e1[3], | 
					
						
							|  |  |  |                               float e2[3]) | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |   float n[3], p[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     float cent[3]; | 
					
						
							|  |  |  |     /* computer center */ | 
					
						
							| 
									
										
										
										
											2018-12-14 10:54:11 +11:00
										 |  |  |     BM_face_calc_center_median(l->f, cent); | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |     BLI_assert(equals_v3v3(cent, l_f_center)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-05-03 19:57:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-30 14:22:49 +00:00
										 |  |  |   mid_v3_v3v3(p, l->prev->v->co, l->v->co); | 
					
						
							|  |  |  |   mid_v3_v3v3(n, l->next->v->co, l->v->co); | 
					
						
							| 
									
										
										
										
											2018-06-04 08:48:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |   copy_v3_v3(v1, l_f_center); | 
					
						
							| 
									
										
										
										
											2012-02-21 17:24:05 +00:00
										 |  |  |   copy_v3_v3(v2, p); | 
					
						
							|  |  |  |   copy_v3_v3(v3, l->v->co); | 
					
						
							|  |  |  |   copy_v3_v3(v4, n); | 
					
						
							| 
									
										
										
										
											2018-06-04 08:48:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-21 17:24:05 +00:00
										 |  |  |   sub_v3_v3v3(e1, v2, v1); | 
					
						
							|  |  |  |   sub_v3_v3v3(e2, v3, v4); | 
					
						
							| 
									
										
										
										
											2018-06-04 08:48:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-25 20:15:20 +10:00
										 |  |  | static bool quad_co(const float v1[3], | 
					
						
							|  |  |  |                     const float v2[3], | 
					
						
							|  |  |  |                     const float v3[3], | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |                     const float v4[3], | 
					
						
							|  |  |  |                     const float p[3], | 
					
						
							|  |  |  |                     const float n[3], | 
					
						
							|  |  |  |                     float r_uv[2]) | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   float projverts[5][3], n2[3]; | 
					
						
							| 
									
										
										
										
											2020-08-07 22:36:11 +10:00
										 |  |  |   const float origin[2] = {0.0f, 0.0f}; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* project points into 2d along normal */ | 
					
						
							| 
									
										
										
										
											2012-02-21 17:24:05 +00:00
										 |  |  |   copy_v3_v3(projverts[0], v1); | 
					
						
							|  |  |  |   copy_v3_v3(projverts[1], v2); | 
					
						
							|  |  |  |   copy_v3_v3(projverts[2], v3); | 
					
						
							|  |  |  |   copy_v3_v3(projverts[3], v4); | 
					
						
							|  |  |  |   copy_v3_v3(projverts[4], p); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   normal_quad_v3(n2, projverts[0], projverts[1], projverts[2], projverts[3]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-09 06:04:17 +00:00
										 |  |  |   if (dot_v3v3(n, n2) < -FLT_EPSILON) { | 
					
						
							| 
									
										
										
										
											2015-11-04 04:01:15 +11:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* rotate */ | 
					
						
							|  |  |  |   poly_rotate_plane(n, projverts, 5); | 
					
						
							| 
									
										
										
										
											2014-04-16 21:04:17 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   /* subtract origin */ | 
					
						
							|  |  |  |   for (i = 0; i < 4; i++) { | 
					
						
							| 
									
										
										
										
											2015-11-04 04:01:15 +11:00
										 |  |  |     sub_v2_v2(projverts[i], projverts[4]); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-04 04:01:15 +11:00
										 |  |  |   if (!isect_point_quad_v2(origin, projverts[0], projverts[1], projverts[2], projverts[3])) { | 
					
						
							|  |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-04 04:01:15 +11:00
										 |  |  |   resolve_quad_uv_v2(r_uv, origin, projverts[0], projverts[3], projverts[2], projverts[1]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return true; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-07 22:56:13 +10:00
										 |  |  | static void mdisp_axis_from_quad(const float v1[3], | 
					
						
							| 
									
										
										
										
											2019-09-14 08:10:50 +10:00
										 |  |  |                                  const float v2[3], | 
					
						
							| 
									
										
										
										
											2015-04-25 20:15:20 +10:00
										 |  |  |                                  float UNUSED(v3[3]), | 
					
						
							| 
									
										
										
										
											2019-09-14 08:10:50 +10:00
										 |  |  |                                  const float v4[3], | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |                                  float r_axis_x[3], | 
					
						
							|  |  |  |                                  float r_axis_y[3]) | 
					
						
							| 
									
										
										
										
											2012-02-21 17:23:03 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |   sub_v3_v3v3(r_axis_x, v4, v1); | 
					
						
							|  |  |  |   sub_v3_v3v3(r_axis_y, v2, v1); | 
					
						
							| 
									
										
										
										
											2012-02-21 17:23:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |   normalize_v3(r_axis_x); | 
					
						
							|  |  |  |   normalize_v3(r_axis_y); | 
					
						
							| 
									
										
										
										
											2012-02-21 17:23:03 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* tl is loop to project onto, l is loop whose internal displacement, co, is being
 | 
					
						
							|  |  |  |  * projected.  x and y are location in loop's mdisps grid of point co. */ | 
					
						
							| 
									
										
										
										
											2015-04-25 20:15:20 +10:00
										 |  |  | static bool mdisp_in_mdispquad(BMLoop *l_src, | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |                                BMLoop *l_dst, | 
					
						
							|  |  |  |                                const float l_dst_f_center[3], | 
					
						
							|  |  |  |                                const float p[3], | 
					
						
							|  |  |  |                                int res, | 
					
						
							|  |  |  |                                float r_axis_x[3], | 
					
						
							|  |  |  |                                float r_axis_y[3], | 
					
						
							|  |  |  |                                float r_uv[2]) | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-02-21 17:24:05 +00:00
										 |  |  |   float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3]; | 
					
						
							|  |  |  |   float eps = FLT_EPSILON * 4000; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   if (is_zero_v3(l_src->v->no)) { | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |     BM_vert_normal_update_all(l_src->v); | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (is_zero_v3(l_dst->v->no)) { | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |     BM_vert_normal_update_all(l_dst->v); | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |   compute_mdisp_quad(l_dst, l_dst_f_center, v1, v2, v3, v4, e1, e2); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   /* expand quad a bit */ | 
					
						
							| 
									
										
										
										
											2017-01-10 17:46:31 -02:00
										 |  |  |   mid_v3_v3v3v3v3(c, v1, v2, v3, v4); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-21 17:24:05 +00:00
										 |  |  |   sub_v3_v3(v1, c); | 
					
						
							|  |  |  |   sub_v3_v3(v2, c); | 
					
						
							|  |  |  |   sub_v3_v3(v3, c); | 
					
						
							|  |  |  |   sub_v3_v3(v4, c); | 
					
						
							| 
									
										
										
										
											2012-05-03 19:57:24 +00:00
										 |  |  |   mul_v3_fl(v1, 1.0f + eps); | 
					
						
							|  |  |  |   mul_v3_fl(v2, 1.0f + eps); | 
					
						
							|  |  |  |   mul_v3_fl(v3, 1.0f + eps); | 
					
						
							|  |  |  |   mul_v3_fl(v4, 1.0f + eps); | 
					
						
							| 
									
										
										
										
											2012-02-21 17:24:05 +00:00
										 |  |  |   add_v3_v3(v1, c); | 
					
						
							|  |  |  |   add_v3_v3(v2, c); | 
					
						
							|  |  |  |   add_v3_v3(v3, c); | 
					
						
							|  |  |  |   add_v3_v3(v4, c); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   if (!quad_co(v1, v2, v3, v4, p, l_src->v->no, r_uv)) { | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |   mul_v2_fl(r_uv, (float)(res - 1)); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |   mdisp_axis_from_quad(v1, v2, v3, v4, r_axis_x, r_axis_y); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-25 20:15:20 +10:00
										 |  |  | static float bm_loop_flip_equotion(float mat[2][2], | 
					
						
							|  |  |  |                                    float b[2], | 
					
						
							|  |  |  |                                    const float target_axis_x[3], | 
					
						
							|  |  |  |                                    const float target_axis_y[3], | 
					
						
							|  |  |  |                                    const float coord[3], | 
					
						
							|  |  |  |                                    int i, | 
					
						
							|  |  |  |                                    int j) | 
					
						
							| 
									
										
										
										
											2012-02-21 17:23:32 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   mat[0][0] = target_axis_x[i]; | 
					
						
							|  |  |  |   mat[0][1] = target_axis_y[i]; | 
					
						
							|  |  |  |   mat[1][0] = target_axis_x[j]; | 
					
						
							|  |  |  |   mat[1][1] = target_axis_y[j]; | 
					
						
							|  |  |  |   b[0] = coord[i]; | 
					
						
							|  |  |  |   b[1] = coord[j]; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-01 16:37:05 +10:00
										 |  |  |   return cross_v2v2(mat[0], mat[1]); | 
					
						
							| 
									
										
										
										
											2012-02-21 17:23:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-25 20:15:20 +10:00
										 |  |  | static void bm_loop_flip_disp(const float source_axis_x[3], | 
					
						
							|  |  |  |                               const float source_axis_y[3], | 
					
						
							|  |  |  |                               const float target_axis_x[3], | 
					
						
							|  |  |  |                               const float target_axis_y[3], | 
					
						
							|  |  |  |                               float disp[3]) | 
					
						
							| 
									
										
										
										
											2012-02-21 17:23:03 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   float vx[3], vy[3], coord[3]; | 
					
						
							| 
									
										
										
										
											2012-02-21 17:23:32 +00:00
										 |  |  |   float n[3], vec[3]; | 
					
						
							|  |  |  |   float b[2], mat[2][2], d; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-21 17:23:03 +00:00
										 |  |  |   mul_v3_v3fl(vx, source_axis_x, disp[0]); | 
					
						
							|  |  |  |   mul_v3_v3fl(vy, source_axis_y, disp[1]); | 
					
						
							|  |  |  |   add_v3_v3v3(coord, vx, vy); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-21 17:23:32 +00:00
										 |  |  |   /* project displacement from source grid plane onto target grid plane */ | 
					
						
							|  |  |  |   cross_v3_v3v3(n, target_axis_x, target_axis_y); | 
					
						
							|  |  |  |   project_v3_v3v3(vec, coord, n); | 
					
						
							|  |  |  |   sub_v3_v3v3(coord, coord, vec); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-28 19:10:53 +00:00
										 |  |  |   d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 1); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-03 19:57:24 +00:00
										 |  |  |   if (fabsf(d) < 1e-4f) { | 
					
						
							| 
									
										
										
										
											2012-02-28 19:10:53 +00:00
										 |  |  |     d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 2); | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |     if (fabsf(d) < 1e-4f) { | 
					
						
							| 
									
										
										
										
											2012-02-28 19:10:53 +00:00
										 |  |  |       d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 1, 2); | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-02-21 17:23:32 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-25 20:58:03 +00:00
										 |  |  |   disp[0] = (b[0] * mat[1][1] - mat[0][1] * b[1]) / d; | 
					
						
							|  |  |  |   disp[1] = (mat[0][0] * b[1] - b[0] * mat[1][0]) / d; | 
					
						
							| 
									
										
										
										
											2012-02-21 17:23:03 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-26 13:06:39 +01:00
										 |  |  | typedef struct BMLoopInterpMultiresData { | 
					
						
							|  |  |  |   BMLoop *l_dst; | 
					
						
							|  |  |  |   BMLoop *l_src_first; | 
					
						
							|  |  |  |   int cd_loop_mdisp_offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   MDisps *md_dst; | 
					
						
							|  |  |  |   const float *f_src_center; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   float *axis_x, *axis_y; | 
					
						
							|  |  |  |   float *v1, *v4; | 
					
						
							|  |  |  |   float *e1, *e2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int res; | 
					
						
							|  |  |  |   float d; | 
					
						
							|  |  |  | } BMLoopInterpMultiresData; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-10 12:49:51 +01:00
										 |  |  | static void loop_interp_multires_cb(void *__restrict userdata, | 
					
						
							| 
									
										
										
										
											2018-01-10 12:53:59 +01:00
										 |  |  |                                     const int ix, | 
					
						
							| 
									
										
										
										
											2019-07-30 14:56:47 +02:00
										 |  |  |                                     const TaskParallelTLS *__restrict UNUSED(tls)) | 
					
						
							| 
									
										
										
										
											2017-11-26 13:06:39 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   BMLoopInterpMultiresData *data = userdata; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BMLoop *l_first = data->l_src_first; | 
					
						
							|  |  |  |   BMLoop *l_dst = data->l_dst; | 
					
						
							|  |  |  |   const int cd_loop_mdisp_offset = data->cd_loop_mdisp_offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   MDisps *md_dst = data->md_dst; | 
					
						
							|  |  |  |   const float *f_src_center = data->f_src_center; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   float *axis_x = data->axis_x; | 
					
						
							|  |  |  |   float *axis_y = data->axis_y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   float *v1 = data->v1; | 
					
						
							|  |  |  |   float *v4 = data->v4; | 
					
						
							|  |  |  |   float *e1 = data->e1; | 
					
						
							|  |  |  |   float *e2 = data->e2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const int res = data->res; | 
					
						
							|  |  |  |   const float d = data->d; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   float x = d * ix, y; | 
					
						
							|  |  |  |   int iy; | 
					
						
							|  |  |  |   for (y = 0.0f, iy = 0; iy < res; y += d, iy++) { | 
					
						
							|  |  |  |     BMLoop *l_iter = l_first; | 
					
						
							|  |  |  |     float co1[3], co2[3], co[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     madd_v3_v3v3fl(co1, v1, e1, y); | 
					
						
							|  |  |  |     madd_v3_v3v3fl(co2, v4, e2, y); | 
					
						
							|  |  |  |     interp_v3_v3v3(co, co1, co2, x); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |       MDisps *md_src; | 
					
						
							|  |  |  |       float src_axis_x[3], src_axis_y[3]; | 
					
						
							|  |  |  |       float uv[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) { | 
					
						
							|  |  |  |         old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]); | 
					
						
							|  |  |  |         bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md_dst->disps[iy * res + ix]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } while ((l_iter = l_iter->next) != l_first); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  | void BM_loop_interp_multires_ex(BMesh *UNUSED(bm), | 
					
						
							|  |  |  |                                 BMLoop *l_dst, | 
					
						
							|  |  |  |                                 const BMFace *f_src, | 
					
						
							|  |  |  |                                 const float f_dst_center[3], | 
					
						
							|  |  |  |                                 const float f_src_center[3], | 
					
						
							|  |  |  |                                 const int cd_loop_mdisp_offset) | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-07-11 01:28:27 +00:00
										 |  |  |   MDisps *md_dst; | 
					
						
							| 
									
										
										
										
											2017-11-26 13:06:39 +01:00
										 |  |  |   float v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3]; | 
					
						
							| 
									
										
										
										
											2012-02-21 17:23:03 +00:00
										 |  |  |   float axis_x[3], axis_y[3]; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-11 01:28:27 +00:00
										 |  |  |   /* ignore 2-edged faces */ | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   if (UNLIKELY(l_dst->f->len < 3)) { | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-11 01:28:27 +00:00
										 |  |  |   md_dst = BM_ELEM_CD_GET_VOID_P(l_dst, cd_loop_mdisp_offset); | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |   compute_mdisp_quad(l_dst, f_dst_center, v1, v2, v3, v4, e1, e2); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-11 01:28:27 +00:00
										 |  |  |   /* if no disps data allocate a new grid, the size of the first grid in f_src. */ | 
					
						
							|  |  |  |   if (!md_dst->totdisp) { | 
					
						
							| 
									
										
										
										
											2015-04-28 21:17:48 +10:00
										 |  |  |     const MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-11 01:28:27 +00:00
										 |  |  |     md_dst->totdisp = md_src->totdisp; | 
					
						
							|  |  |  |     md_dst->level = md_src->level; | 
					
						
							|  |  |  |     if (md_dst->totdisp) { | 
					
						
							| 
									
										
										
										
											2020-08-08 13:29:21 +10:00
										 |  |  |       md_dst->disps = MEM_callocN(sizeof(float[3]) * md_dst->totdisp, __func__); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       return; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-21 17:23:03 +00:00
										 |  |  |   mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-26 13:06:39 +01:00
										 |  |  |   const int res = (int)sqrt(md_dst->totdisp); | 
					
						
							|  |  |  |   BMLoopInterpMultiresData data = { | 
					
						
							|  |  |  |       .l_dst = l_dst, | 
					
						
							|  |  |  |       .l_src_first = BM_FACE_FIRST_LOOP(f_src), | 
					
						
							|  |  |  |       .cd_loop_mdisp_offset = cd_loop_mdisp_offset, | 
					
						
							|  |  |  |       .md_dst = md_dst, | 
					
						
							|  |  |  |       .f_src_center = f_src_center, | 
					
						
							|  |  |  |       .axis_x = axis_x, | 
					
						
							|  |  |  |       .axis_y = axis_y, | 
					
						
							|  |  |  |       .v1 = v1, | 
					
						
							|  |  |  |       .v4 = v4, | 
					
						
							|  |  |  |       .e1 = e1, | 
					
						
							|  |  |  |       .e2 = e2, | 
					
						
							| 
									
										
										
										
											2019-01-07 00:06:58 +11:00
										 |  |  |       .res = res, | 
					
						
							|  |  |  |       .d = 1.0f / (float)(res - 1), | 
					
						
							| 
									
										
										
										
											2017-11-26 13:06:39 +01:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2019-07-30 14:56:47 +02:00
										 |  |  |   TaskParallelSettings settings; | 
					
						
							| 
									
										
										
										
											2018-01-08 11:35:48 +01:00
										 |  |  |   BLI_parallel_range_settings_defaults(&settings); | 
					
						
							|  |  |  |   settings.use_threading = (res > 5); | 
					
						
							|  |  |  |   BLI_task_parallel_range(0, res, &data, loop_interp_multires_cb, &settings); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * project the multires grid in target onto f_src's set of multires grids | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-05 06:03:26 +11:00
										 |  |  |   if (cd_loop_mdisp_offset != -1) { | 
					
						
							|  |  |  |     float f_dst_center[3]; | 
					
						
							|  |  |  |     float f_src_center[3]; | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-14 10:54:11 +11:00
										 |  |  |     BM_face_calc_center_median(l_dst->f, f_dst_center); | 
					
						
							|  |  |  |     BM_face_calc_center_median(f_src, f_src_center); | 
					
						
							| 
									
										
										
										
											2015-11-05 06:03:26 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  |     BM_loop_interp_multires_ex(bm, l_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-03 20:30:54 +11:00
										 |  |  | void BM_face_interp_multires_ex(BMesh *bm, | 
					
						
							|  |  |  |                                 BMFace *f_dst, | 
					
						
							|  |  |  |                                 const BMFace *f_src, | 
					
						
							|  |  |  |                                 const float f_dst_center[3], | 
					
						
							|  |  |  |                                 const float f_src_center[3], | 
					
						
							|  |  |  |                                 const int cd_loop_mdisp_offset) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   BMLoop *l_iter, *l_first; | 
					
						
							|  |  |  |   l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst); | 
					
						
							|  |  |  |   do { | 
					
						
							|  |  |  |     BM_loop_interp_multires_ex( | 
					
						
							|  |  |  |         bm, l_iter, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset); | 
					
						
							|  |  |  |   } while ((l_iter = l_iter->next) != l_first); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-05 06:03:26 +11:00
										 |  |  |   if (cd_loop_mdisp_offset != -1) { | 
					
						
							|  |  |  |     float f_dst_center[3]; | 
					
						
							|  |  |  |     float f_src_center[3]; | 
					
						
							| 
									
										
										
										
											2015-11-03 20:30:54 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-14 10:54:11 +11:00
										 |  |  |     BM_face_calc_center_median(f_dst, f_dst_center); | 
					
						
							|  |  |  |     BM_face_calc_center_median(f_src, f_src_center); | 
					
						
							| 
									
										
										
										
											2015-11-05 06:03:26 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  |     BM_face_interp_multires_ex(bm, f_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-11-03 20:30:54 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-28 18:28:30 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2012-10-20 20:36:51 +00:00
										 |  |  |  * smooths boundaries between multires grids, | 
					
						
							| 
									
										
										
										
											2012-02-28 18:28:30 +00:00
										 |  |  |  * including some borders in adjacent faces | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-07-11 01:28:27 +00:00
										 |  |  |   const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   BMLoop *l; | 
					
						
							|  |  |  |   BMIter liter; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   if (cd_loop_mdisp_offset == -1) { | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  |   BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { | 
					
						
							| 
									
										
										
										
											2013-07-11 01:28:27 +00:00
										 |  |  |     MDisps *mdp = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_mdisp_offset); | 
					
						
							|  |  |  |     MDisps *mdl = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset); | 
					
						
							|  |  |  |     MDisps *mdn = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_mdisp_offset); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     float co1[3]; | 
					
						
							|  |  |  |     int sides; | 
					
						
							|  |  |  |     int y; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-02 18:51:31 +10:00
										 |  |  |     /**
 | 
					
						
							|  |  |  |      * mdisps is a grid of displacements, ordered thus: | 
					
						
							|  |  |  |      * <pre> | 
					
						
							|  |  |  |      *                    v4/next | 
					
						
							|  |  |  |      *                      | | 
					
						
							|  |  |  |      *  |      v1/cent-----mid2 ---> x | 
					
						
							|  |  |  |      *  |         |         | | 
					
						
							|  |  |  |      *  |         |         | | 
					
						
							|  |  |  |      * v2/prev---mid1-----v3/cur | 
					
						
							|  |  |  |      *            | | 
					
						
							|  |  |  |      *            V | 
					
						
							|  |  |  |      *            y | 
					
						
							|  |  |  |      * </pre> | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     sides = (int)sqrt(mdp->totdisp); | 
					
						
							|  |  |  |     for (y = 0; y < sides; y++) { | 
					
						
							| 
									
										
										
										
											2012-10-30 14:22:49 +00:00
										 |  |  |       mid_v3_v3v3(co1, mdn->disps[y * sides], mdl->disps[y]); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       copy_v3_v3(mdn->disps[y * sides], co1); | 
					
						
							|  |  |  |       copy_v3_v3(mdl->disps[y], co1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  |   BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { | 
					
						
							| 
									
										
										
										
											2013-07-11 01:28:27 +00:00
										 |  |  |     MDisps *mdl1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     MDisps *mdl2; | 
					
						
							|  |  |  |     float co1[3], co2[3], co[3]; | 
					
						
							|  |  |  |     int sides; | 
					
						
							|  |  |  |     int y; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-02 18:51:31 +10:00
										 |  |  |     /**
 | 
					
						
							|  |  |  |      * mdisps is a grid of displacements, ordered thus: | 
					
						
							|  |  |  |      * <pre> | 
					
						
							|  |  |  |      *                    v4/next | 
					
						
							|  |  |  |      *                      | | 
					
						
							|  |  |  |      *  |      v1/cent-----mid2 ---> x | 
					
						
							|  |  |  |      *  |         |         | | 
					
						
							|  |  |  |      *  |         |         | | 
					
						
							|  |  |  |      * v2/prev---mid1-----v3/cur | 
					
						
							|  |  |  |      *            | | 
					
						
							|  |  |  |      *            V | 
					
						
							|  |  |  |      *            y | 
					
						
							|  |  |  |      * </pre> | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |     if (l->radial_next == l) { | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       continue; | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |     if (l->radial_next->v == l->v) { | 
					
						
							| 
									
										
										
										
											2013-07-11 01:28:27 +00:00
										 |  |  |       mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next, cd_loop_mdisp_offset); | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2013-07-11 01:28:27 +00:00
										 |  |  |       mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next->next, cd_loop_mdisp_offset); | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     sides = (int)sqrt(mdl1->totdisp); | 
					
						
							|  |  |  |     for (y = 0; y < sides; y++) { | 
					
						
							|  |  |  |       int a1, a2, o1, o2; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       if (l->v != l->radial_next->v) { | 
					
						
							|  |  |  |         a1 = sides * y + sides - 2; | 
					
						
							|  |  |  |         a2 = (sides - 2) * sides + y; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |         o1 = sides * y + sides - 1; | 
					
						
							|  |  |  |         o2 = (sides - 1) * sides + y; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							|  |  |  |         a1 = sides * y + sides - 2; | 
					
						
							|  |  |  |         a2 = sides * y + sides - 2; | 
					
						
							|  |  |  |         o1 = sides * y + sides - 1; | 
					
						
							|  |  |  |         o2 = sides * y + sides - 1; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       /* magic blending numbers, hardcoded! */ | 
					
						
							|  |  |  |       add_v3_v3v3(co1, mdl1->disps[a1], mdl2->disps[a2]); | 
					
						
							|  |  |  |       mul_v3_fl(co1, 0.18); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       add_v3_v3v3(co2, mdl1->disps[o1], mdl2->disps[o2]); | 
					
						
							|  |  |  |       mul_v3_fl(co2, 0.32); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       add_v3_v3v3(co, co1, co2); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       copy_v3_v3(mdl1->disps[o1], co); | 
					
						
							|  |  |  |       copy_v3_v3(mdl2->disps[o2], co); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-28 18:28:30 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |  * projects a single loop, target, onto f_src for customdata interpolation. multires is handled. | 
					
						
							| 
									
										
										
										
											2012-02-28 18:28:30 +00:00
										 |  |  |  * if do_vertex is true, target's vert data will also get interpolated. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  | void BM_loop_interp_from_face( | 
					
						
							|  |  |  |     BMesh *bm, BMLoop *l_dst, const BMFace *f_src, const bool do_vertex, const bool do_multires) | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   BMLoop *l_iter; | 
					
						
							|  |  |  |   BMLoop *l_first; | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   const void **vblocks = do_vertex ? BLI_array_alloca(vblocks, f_src->len) : NULL; | 
					
						
							|  |  |  |   const void **blocks = BLI_array_alloca(blocks, f_src->len); | 
					
						
							|  |  |  |   float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len); | 
					
						
							|  |  |  |   float *w = BLI_array_alloca(w, f_src->len); | 
					
						
							| 
									
										
										
										
											2013-04-07 02:10:15 +00:00
										 |  |  |   float axis_mat[3][3]; /* use normal to transform into 2d xy coords */ | 
					
						
							| 
									
										
										
										
											2013-01-07 21:42:40 +00:00
										 |  |  |   float co[2]; | 
					
						
							| 
									
										
										
										
											2013-04-07 02:10:15 +00:00
										 |  |  |   int i; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-01 17:45:27 +10:00
										 |  |  |   /* Convert the 3d coords into 2d for projection. */ | 
					
						
							|  |  |  |   float axis_dominant[3]; | 
					
						
							|  |  |  |   if (!is_zero_v3(f_src->no)) { | 
					
						
							|  |  |  |     BLI_assert(BM_face_is_normal_valid(f_src)); | 
					
						
							|  |  |  |     copy_v3_v3(axis_dominant, f_src->no); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     /* Rare case in which all the vertices of the face are aligned.
 | 
					
						
							|  |  |  |      * Get a random axis that is orthogonal to the tangent. */ | 
					
						
							|  |  |  |     float vec[3]; | 
					
						
							|  |  |  |     BM_face_calc_tangent_auto(f_src, vec); | 
					
						
							|  |  |  |     ortho_v3_v3(axis_dominant, vec); | 
					
						
							|  |  |  |     normalize_v3(axis_dominant); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   axis_dominant_v3_to_m3(axis_mat, axis_dominant); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   i = 0; | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   l_iter = l_first = BM_FACE_FIRST_LOOP(f_src); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   do { | 
					
						
							| 
									
										
										
										
											2013-04-07 02:10:15 +00:00
										 |  |  |     mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     blocks[i] = l_iter->head.data; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     if (do_vertex) { | 
					
						
							|  |  |  |       vblocks[i] = l_iter->v->head.data; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-03-05 09:16:12 +11:00
										 |  |  |   } while ((void)i++, (l_iter = l_iter->next) != l_first); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   mul_v2_m3v3(co, axis_mat, l_dst->v->co); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   /* interpolate */ | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   interp_weights_poly_v2(w, cos_2d, f_src->len, co); | 
					
						
							|  |  |  |   CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, f_src->len, l_dst->head.data); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   if (do_vertex) { | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |     CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, f_src->len, l_dst->v->head.data); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   if (do_multires) { | 
					
						
							| 
									
										
										
										
											2015-11-03 18:28:13 +11:00
										 |  |  |     BM_loop_interp_multires(bm, l_dst, f_src); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  | void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src) | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   BMLoop *l_iter; | 
					
						
							|  |  |  |   BMLoop *l_first; | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   const void **blocks = BLI_array_alloca(blocks, f_src->len); | 
					
						
							|  |  |  |   float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len); | 
					
						
							|  |  |  |   float *w = BLI_array_alloca(w, f_src->len); | 
					
						
							| 
									
										
										
										
											2013-04-07 02:10:15 +00:00
										 |  |  |   float axis_mat[3][3]; /* use normal to transform into 2d xy coords */ | 
					
						
							|  |  |  |   float co[2]; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   int i; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-07 02:10:15 +00:00
										 |  |  |   /* convert the 3d coords into 2d for projection */ | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   BLI_assert(BM_face_is_normal_valid(f_src)); | 
					
						
							|  |  |  |   axis_dominant_v3_to_m3(axis_mat, f_src->no); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   i = 0; | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   l_iter = l_first = BM_FACE_FIRST_LOOP(f_src); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   do { | 
					
						
							| 
									
										
										
										
											2013-04-07 02:10:15 +00:00
										 |  |  |     mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     blocks[i] = l_iter->v->head.data; | 
					
						
							| 
									
										
										
										
											2016-03-05 09:16:12 +11:00
										 |  |  |   } while ((void)i++, (l_iter = l_iter->next) != l_first); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   mul_v2_m3v3(co, axis_mat, v_dst->co); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   /* interpolate */ | 
					
						
							| 
									
										
										
										
											2015-02-23 15:55:48 +11:00
										 |  |  |   interp_weights_poly_v2(w, cos_2d, f_src->len, co); | 
					
						
							|  |  |  |   CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, f_src->len, v_dst->head.data); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   BMIter iter; | 
					
						
							|  |  |  |   BLI_mempool *oldpool = olddata->pool; | 
					
						
							|  |  |  |   void *block; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   if (data == &bm->vdata) { | 
					
						
							|  |  |  |     BMVert *eve; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-01 22:17:04 +00:00
										 |  |  |     CustomData_bmesh_init_pool(data, bm->totvert, BM_VERT); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  |     BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       block = NULL; | 
					
						
							|  |  |  |       CustomData_bmesh_set_default(data, &block); | 
					
						
							|  |  |  |       CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block); | 
					
						
							|  |  |  |       CustomData_bmesh_free_block(olddata, &eve->head.data); | 
					
						
							|  |  |  |       eve->head.data = block; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (data == &bm->edata) { | 
					
						
							|  |  |  |     BMEdge *eed; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-01 22:17:04 +00:00
										 |  |  |     CustomData_bmesh_init_pool(data, bm->totedge, BM_EDGE); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  |     BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       block = NULL; | 
					
						
							|  |  |  |       CustomData_bmesh_set_default(data, &block); | 
					
						
							|  |  |  |       CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block); | 
					
						
							|  |  |  |       CustomData_bmesh_free_block(olddata, &eed->head.data); | 
					
						
							|  |  |  |       eed->head.data = block; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-03-01 22:17:04 +00:00
										 |  |  |   else if (data == &bm->ldata) { | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     BMIter liter; | 
					
						
							|  |  |  |     BMFace *efa; | 
					
						
							|  |  |  |     BMLoop *l; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-01 22:17:04 +00:00
										 |  |  |     CustomData_bmesh_init_pool(data, bm->totloop, BM_LOOP); | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  |     BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { | 
					
						
							|  |  |  |       BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |         block = NULL; | 
					
						
							|  |  |  |         CustomData_bmesh_set_default(data, &block); | 
					
						
							| 
									
										
										
										
											2012-03-01 22:17:04 +00:00
										 |  |  |         CustomData_bmesh_copy_data(olddata, data, l->head.data, &block); | 
					
						
							|  |  |  |         CustomData_bmesh_free_block(olddata, &l->head.data); | 
					
						
							|  |  |  |         l->head.data = block; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2012-03-01 22:17:04 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (data == &bm->pdata) { | 
					
						
							|  |  |  |     BMFace *efa; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-01 22:17:04 +00:00
										 |  |  |     CustomData_bmesh_init_pool(data, bm->totface, BM_FACE); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  |     BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2012-03-01 22:17:04 +00:00
										 |  |  |       block = NULL; | 
					
						
							|  |  |  |       CustomData_bmesh_set_default(data, &block); | 
					
						
							|  |  |  |       CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block); | 
					
						
							|  |  |  |       CustomData_bmesh_free_block(olddata, &efa->head.data); | 
					
						
							|  |  |  |       efa->head.data = block; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-03-01 22:17:04 +00:00
										 |  |  |   else { | 
					
						
							|  |  |  |     /* should never reach this! */ | 
					
						
							|  |  |  |     BLI_assert(0); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   if (oldpool) { | 
					
						
							| 
									
										
										
										
											2020-09-30 20:09:02 +10:00
										 |  |  |     /* this should never happen but can when dissolve fails - T28960. */ | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     BLI_assert(data->pool != oldpool); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |     BLI_mempool_destroy(oldpool); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BM_data_layer_add(BMesh *bm, CustomData *data, int type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   CustomData olddata; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   olddata = *data; | 
					
						
							| 
									
										
										
										
											2014-01-12 22:27:55 +11:00
										 |  |  |   olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* the pool is now owned by olddata and must not be shared */ | 
					
						
							|  |  |  |   data->pool = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   CustomData_add_layer(data, type, CD_DEFAULT, NULL, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   update_data_blocks(bm, &olddata, data); | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   if (olddata.layers) { | 
					
						
							|  |  |  |     MEM_freeN(olddata.layers); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   CustomData olddata; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   olddata = *data; | 
					
						
							| 
									
										
										
										
											2014-01-12 22:27:55 +11:00
										 |  |  |   olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* the pool is now owned by olddata and must not be shared */ | 
					
						
							|  |  |  |   data->pool = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   CustomData_add_layer_named(data, type, CD_DEFAULT, NULL, 0, name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   update_data_blocks(bm, &olddata, data); | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   if (olddata.layers) { | 
					
						
							|  |  |  |     MEM_freeN(olddata.layers); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BM_data_layer_free(BMesh *bm, CustomData *data, int type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   CustomData olddata; | 
					
						
							| 
									
										
										
										
											2013-04-29 20:21:19 +00:00
										 |  |  |   bool has_layer; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   olddata = *data; | 
					
						
							| 
									
										
										
										
											2014-01-12 22:27:55 +11:00
										 |  |  |   olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* the pool is now owned by olddata and must not be shared */ | 
					
						
							|  |  |  |   data->pool = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-29 20:21:19 +00:00
										 |  |  |   has_layer = CustomData_free_layer_active(data, type, 0); | 
					
						
							|  |  |  |   /* assert because its expensive to realloc - better not do if layer isnt present */ | 
					
						
							|  |  |  |   BLI_assert(has_layer != false); | 
					
						
							| 
									
										
										
										
											2015-02-23 13:55:11 +01:00
										 |  |  |   UNUSED_VARS_NDEBUG(has_layer); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   update_data_blocks(bm, &olddata, data); | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   if (olddata.layers) { | 
					
						
							|  |  |  |     MEM_freeN(olddata.layers); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   CustomData olddata; | 
					
						
							| 
									
										
										
										
											2013-04-29 20:21:19 +00:00
										 |  |  |   bool has_layer; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   olddata = *data; | 
					
						
							| 
									
										
										
										
											2014-01-12 22:27:55 +11:00
										 |  |  |   olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL; | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* the pool is now owned by olddata and must not be shared */ | 
					
						
							|  |  |  |   data->pool = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-29 20:21:19 +00:00
										 |  |  |   has_layer = CustomData_free_layer(data, type, 0, CustomData_get_layer_index_n(data, type, n)); | 
					
						
							|  |  |  |   /* assert because its expensive to realloc - better not do if layer isnt present */ | 
					
						
							|  |  |  |   BLI_assert(has_layer != false); | 
					
						
							| 
									
										
										
										
											2015-02-23 13:55:11 +01:00
										 |  |  |   UNUSED_VARS_NDEBUG(has_layer); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   update_data_blocks(bm, &olddata, data); | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   if (olddata.layers) { | 
					
						
							|  |  |  |     MEM_freeN(olddata.layers); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 18:54:14 +00:00
										 |  |  | void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   BMIter iter; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 18:54:14 +00:00
										 |  |  |   if (&bm->vdata == data) { | 
					
						
							|  |  |  |     BMVert *eve; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 18:54:14 +00:00
										 |  |  |     BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2012-05-22 12:03:56 +00:00
										 |  |  |       void *ptr = CustomData_bmesh_get_n(data, eve->head.data, type, src_n); | 
					
						
							|  |  |  |       CustomData_bmesh_set_n(data, eve->head.data, type, dst_n, ptr); | 
					
						
							| 
									
										
										
										
											2012-04-30 18:54:14 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (&bm->edata == data) { | 
					
						
							|  |  |  |     BMEdge *eed; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 18:54:14 +00:00
										 |  |  |     BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2012-05-22 12:03:56 +00:00
										 |  |  |       void *ptr = CustomData_bmesh_get_n(data, eed->head.data, type, src_n); | 
					
						
							|  |  |  |       CustomData_bmesh_set_n(data, eed->head.data, type, dst_n, ptr); | 
					
						
							| 
									
										
										
										
											2012-04-30 18:54:14 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (&bm->pdata == data) { | 
					
						
							|  |  |  |     BMFace *efa; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 18:54:14 +00:00
										 |  |  |     BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2012-05-22 12:03:56 +00:00
										 |  |  |       void *ptr = CustomData_bmesh_get_n(data, efa->head.data, type, src_n); | 
					
						
							|  |  |  |       CustomData_bmesh_set_n(data, efa->head.data, type, dst_n, ptr); | 
					
						
							| 
									
										
										
										
											2012-04-30 18:54:14 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (&bm->ldata == data) { | 
					
						
							|  |  |  |     BMIter liter; | 
					
						
							|  |  |  |     BMFace *efa; | 
					
						
							|  |  |  |     BMLoop *l; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 18:54:14 +00:00
										 |  |  |     BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { | 
					
						
							|  |  |  |       BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | 
					
						
							| 
									
										
										
										
											2012-05-22 12:03:56 +00:00
										 |  |  |         void *ptr = CustomData_bmesh_get_n(data, l->head.data, type, src_n); | 
					
						
							|  |  |  |         CustomData_bmesh_set_n(data, l->head.data, type, dst_n, ptr); | 
					
						
							| 
									
										
										
										
											2012-04-30 18:54:14 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     /* should never reach this! */ | 
					
						
							|  |  |  |     BLI_assert(0); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | float BM_elem_float_data_get(CustomData *cd, void *element, int type) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-04-27 00:23:36 +10:00
										 |  |  |   const float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type); | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  |   return f ? *f : 0.0f; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type); | 
					
						
							| 
									
										
										
										
											2019-03-27 17:14:36 +11:00
										 |  |  |   if (f) { | 
					
						
							|  |  |  |     *f = val; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-02-19 18:31:04 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Loop interpolation functions: BM_vert_loop_groups_data_layer_***
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Handling loop custom-data such as UV's, while keeping contiguous fans is rather tedious. | 
					
						
							|  |  |  |  * Especially when a verts loops can have multiple CustomData layers, | 
					
						
							|  |  |  |  * and each layer can have multiple (different) contiguous fans. | 
					
						
							|  |  |  |  * Said differently, a single vertices loops may span multiple UV islands. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * These functions snapshot vertices loops, storing each contiguous fan in its own group. | 
					
						
							|  |  |  |  * The caller can manipulate the loops, then re-combine the CustomData values. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * While these functions don't explicitly handle multiple layers at once, | 
					
						
							|  |  |  |  * the caller can simply store its own list. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \note Currently they are averaged back together (weighted by loop angle) | 
					
						
							|  |  |  |  * but we could copy add other methods to re-combine CustomData-Loop-Fans. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct LoopWalkCtx { | 
					
						
							|  |  |  |   /* same for all groups */ | 
					
						
							|  |  |  |   int type; | 
					
						
							|  |  |  |   int cd_layer_offset; | 
					
						
							| 
									
										
										
										
											2015-02-23 15:44:28 +11:00
										 |  |  |   const float *loop_weights; | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   MemArena *arena; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   /* --- Per loop fan vars --- */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   /* reference for this contiguous fan */ | 
					
						
							|  |  |  |   const void *data_ref; | 
					
						
							|  |  |  |   int data_len; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |   /* accumulate 'LoopGroupCD.weight' to make unit length */ | 
					
						
							|  |  |  |   float weight_accum; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   /* both arrays the size of the 'BM_vert_face_count(v)'
 | 
					
						
							|  |  |  |    * each contiguous fan gets a slide of these arrays */ | 
					
						
							|  |  |  |   void **data_array; | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |   int *data_index_array; | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   float *weight_array; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Store vars to pass into 'CustomData_bmesh_interp' */ | 
					
						
							|  |  |  | struct LoopGroupCD { | 
					
						
							|  |  |  |   /* direct customdata pointer array */ | 
					
						
							|  |  |  |   void **data; | 
					
						
							|  |  |  |   /* weights (aligned with 'data') */ | 
					
						
							|  |  |  |   float *data_weights; | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |   /* index-in-face */ | 
					
						
							|  |  |  |   int *data_index; | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   /* number of loops in the fan */ | 
					
						
							|  |  |  |   int data_len; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void bm_loop_walk_add(struct LoopWalkCtx *lwc, BMLoop *l) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-02-23 15:44:28 +11:00
										 |  |  |   const int i = BM_elem_index_get(l); | 
					
						
							|  |  |  |   const float w = lwc->loop_weights[i]; | 
					
						
							| 
									
										
										
										
											2017-10-24 17:05:10 +11:00
										 |  |  |   BM_elem_flag_disable(l, BM_ELEM_INTERNAL_TAG); | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   lwc->data_array[lwc->data_len] = BM_ELEM_CD_GET_VOID_P(l, lwc->cd_layer_offset); | 
					
						
							| 
									
										
										
										
											2015-02-23 15:44:28 +11:00
										 |  |  |   lwc->data_index_array[lwc->data_len] = i; | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   lwc->weight_array[lwc->data_len] = w; | 
					
						
							|  |  |  |   lwc->weight_accum += w; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   lwc->data_len += 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * called recursively, keep stack-usage minimal. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \note called for fan matching so we're pretty much safe not to break the stack | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void bm_loop_walk_data(struct LoopWalkCtx *lwc, BMLoop *l_walk) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-02-13 11:01:47 +11:00
										 |  |  |   int i; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   BLI_assert(CustomData_data_equals( | 
					
						
							|  |  |  |       lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_walk, lwc->cd_layer_offset))); | 
					
						
							| 
									
										
										
										
											2017-10-24 17:05:10 +11:00
										 |  |  |   BLI_assert(BM_elem_flag_test(l_walk, BM_ELEM_INTERNAL_TAG)); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   bm_loop_walk_add(lwc, l_walk); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-13 11:01:47 +11:00
										 |  |  |   /* recurse around this loop-fan (in both directions) */ | 
					
						
							|  |  |  |   for (i = 0; i < 2; i++) { | 
					
						
							|  |  |  |     BMLoop *l_other = ((i == 0) ? l_walk : l_walk->prev)->radial_next; | 
					
						
							|  |  |  |     if (l_other->radial_next != l_other) { | 
					
						
							|  |  |  |       if (l_other->v != l_walk->v) { | 
					
						
							|  |  |  |         l_other = l_other->next; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       BLI_assert(l_other->v == l_walk->v); | 
					
						
							| 
									
										
										
										
											2017-10-24 17:05:10 +11:00
										 |  |  |       if (BM_elem_flag_test(l_other, BM_ELEM_INTERNAL_TAG)) { | 
					
						
							| 
									
										
										
										
											2015-02-13 11:01:47 +11:00
										 |  |  |         if (CustomData_data_equals( | 
					
						
							|  |  |  |                 lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_other, lwc->cd_layer_offset))) { | 
					
						
							|  |  |  |           bm_loop_walk_data(lwc, l_other); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 15:44:28 +11:00
										 |  |  | LinkNode *BM_vert_loop_groups_data_layer_create( | 
					
						
							| 
									
										
										
										
											2015-02-23 13:55:11 +01:00
										 |  |  |     BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, MemArena *arena) | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  | { | 
					
						
							|  |  |  |   struct LoopWalkCtx lwc; | 
					
						
							|  |  |  |   LinkNode *groups = NULL; | 
					
						
							|  |  |  |   BMLoop *l; | 
					
						
							|  |  |  |   BMIter liter; | 
					
						
							|  |  |  |   int loop_num; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   lwc.type = bm->ldata.layers[layer_n].type; | 
					
						
							|  |  |  |   lwc.cd_layer_offset = bm->ldata.layers[layer_n].offset; | 
					
						
							| 
									
										
										
										
											2015-02-23 15:44:28 +11:00
										 |  |  |   lwc.loop_weights = loop_weights; | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   lwc.arena = arena; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 17:05:10 +11:00
										 |  |  |   /* Enable 'BM_ELEM_INTERNAL_TAG', leaving the flag clean on completion. */ | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   loop_num = 0; | 
					
						
							|  |  |  |   BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { | 
					
						
							| 
									
										
										
										
											2017-10-24 17:05:10 +11:00
										 |  |  |     BM_elem_flag_enable(l, BM_ELEM_INTERNAL_TAG); | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |     BM_elem_index_set(l, loop_num); /* set_dirty! */ | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |     loop_num++; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |   bm->elem_index_dirty |= BM_LOOP; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   lwc.data_len = 0; | 
					
						
							|  |  |  |   lwc.data_array = BLI_memarena_alloc(lwc.arena, sizeof(void *) * loop_num); | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |   lwc.data_index_array = BLI_memarena_alloc(lwc.arena, sizeof(int) * loop_num); | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   lwc.weight_array = BLI_memarena_alloc(lwc.arena, sizeof(float) * loop_num); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { | 
					
						
							| 
									
										
										
										
											2017-10-24 17:05:10 +11:00
										 |  |  |     if (BM_elem_flag_test(l, BM_ELEM_INTERNAL_TAG)) { | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |       struct LoopGroupCD *lf = BLI_memarena_alloc(lwc.arena, sizeof(*lf)); | 
					
						
							|  |  |  |       int len_prev = lwc.data_len; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |       lwc.data_ref = BM_ELEM_CD_GET_VOID_P(l, lwc.cd_layer_offset); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |       /* assign len-last */ | 
					
						
							|  |  |  |       lf->data = &lwc.data_array[lwc.data_len]; | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |       lf->data_index = &lwc.data_index_array[lwc.data_len]; | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |       lf->data_weights = &lwc.weight_array[lwc.data_len]; | 
					
						
							|  |  |  |       lwc.weight_accum = 0.0f; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |       /* new group */ | 
					
						
							|  |  |  |       bm_loop_walk_data(&lwc, l); | 
					
						
							|  |  |  |       lf->data_len = lwc.data_len - len_prev; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |       if (LIKELY(lwc.weight_accum != 0.0f)) { | 
					
						
							|  |  |  |         mul_vn_fl(lf->data_weights, lf->data_len, 1.0f / lwc.weight_accum); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2015-05-05 17:08:29 +10:00
										 |  |  |         copy_vn_fl(lf->data_weights, lf->data_len, 1.0f / (float)lf->data_len); | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |       BLI_linklist_prepend_arena(&groups, lf, lwc.arena); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   BLI_assert(lwc.data_len == loop_num); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   return groups; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  | static void bm_vert_loop_groups_data_layer_merge__single(BMesh *bm, | 
					
						
							| 
									
										
										
										
											2015-02-23 13:43:09 +11:00
										 |  |  |                                                          void *lf_p, | 
					
						
							|  |  |  |                                                          int layer_n, | 
					
						
							|  |  |  |                                                          void *data_tmp) | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  | { | 
					
						
							|  |  |  |   struct LoopGroupCD *lf = lf_p; | 
					
						
							| 
									
										
										
										
											2015-02-23 13:43:09 +11:00
										 |  |  |   const int type = bm->ldata.layers[layer_n].type; | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |   int i; | 
					
						
							|  |  |  |   const float *data_weights; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   data_weights = lf->data_weights; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 13:43:09 +11:00
										 |  |  |   CustomData_bmesh_interp_n( | 
					
						
							|  |  |  |       &bm->ldata, (const void **)lf->data, data_weights, NULL, lf->data_len, data_tmp, layer_n); | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; i < lf->data_len; i++) { | 
					
						
							| 
									
										
										
										
											2015-02-23 13:43:09 +11:00
										 |  |  |     CustomData_copy_elements(type, data_tmp, lf->data[i], 1); | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void bm_vert_loop_groups_data_layer_merge_weights__single( | 
					
						
							| 
									
										
										
										
											2015-02-23 13:43:09 +11:00
										 |  |  |     BMesh *bm, void *lf_p, const int layer_n, void *data_tmp, const float *loop_weights) | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  | { | 
					
						
							|  |  |  |   struct LoopGroupCD *lf = lf_p; | 
					
						
							| 
									
										
										
										
											2015-02-23 13:43:09 +11:00
										 |  |  |   const int type = bm->ldata.layers[layer_n].type; | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   int i; | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |   const float *data_weights; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |   /* re-weight */ | 
					
						
							|  |  |  |   float *temp_weights = BLI_array_alloca(temp_weights, lf->data_len); | 
					
						
							|  |  |  |   float weight_accum = 0.0f; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |   for (i = 0; i < lf->data_len; i++) { | 
					
						
							|  |  |  |     float w = loop_weights[lf->data_index[i]] * lf->data_weights[i]; | 
					
						
							|  |  |  |     temp_weights[i] = w; | 
					
						
							|  |  |  |     weight_accum += w; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |   if (LIKELY(weight_accum != 0.0f)) { | 
					
						
							|  |  |  |     mul_vn_fl(temp_weights, lf->data_len, 1.0f / weight_accum); | 
					
						
							|  |  |  |     data_weights = temp_weights; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     data_weights = lf->data_weights; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 13:43:09 +11:00
										 |  |  |   CustomData_bmesh_interp_n( | 
					
						
							|  |  |  |       &bm->ldata, (const void **)lf->data, data_weights, NULL, lf->data_len, data_tmp, layer_n); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   for (i = 0; i < lf->data_len; i++) { | 
					
						
							| 
									
										
										
										
											2015-02-23 13:43:09 +11:00
										 |  |  |     CustomData_copy_elements(type, data_tmp, lf->data[i], 1); | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Take existing custom data and merge each fan's data. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-02-23 13:43:09 +11:00
										 |  |  | void BM_vert_loop_groups_data_layer_merge(BMesh *bm, LinkNode *groups, const int layer_n) | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-02-23 13:43:09 +11:00
										 |  |  |   const int type = bm->ldata.layers[layer_n].type; | 
					
						
							|  |  |  |   const int size = CustomData_sizeof(type); | 
					
						
							| 
									
										
										
										
											2015-02-23 15:40:43 +11:00
										 |  |  |   void *data_tmp = alloca(size); | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  |   do { | 
					
						
							| 
									
										
										
										
											2015-02-23 13:43:09 +11:00
										 |  |  |     bm_vert_loop_groups_data_layer_merge__single(bm, groups->link, layer_n, data_tmp); | 
					
						
							| 
									
										
										
										
											2015-02-11 19:40:54 +11:00
										 |  |  |   } while ((groups = groups->next)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * A version of #BM_vert_loop_groups_data_layer_merge | 
					
						
							|  |  |  |  * that takes an array of loop-weights (aligned with #BM_LOOPS_OF_VERT iterator) | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-02-23 13:55:11 +01:00
										 |  |  | void BM_vert_loop_groups_data_layer_merge_weights(BMesh *bm, | 
					
						
							|  |  |  |                                                   LinkNode *groups, | 
					
						
							|  |  |  |                                                   const int layer_n, | 
					
						
							|  |  |  |                                                   const float *loop_weights) | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-02-23 13:43:09 +11:00
										 |  |  |   const int type = bm->ldata.layers[layer_n].type; | 
					
						
							|  |  |  |   const int size = CustomData_sizeof(type); | 
					
						
							| 
									
										
										
										
											2015-02-23 15:40:43 +11:00
										 |  |  |   void *data_tmp = alloca(size); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |   do { | 
					
						
							| 
									
										
										
										
											2015-02-23 13:43:09 +11:00
										 |  |  |     bm_vert_loop_groups_data_layer_merge_weights__single( | 
					
						
							|  |  |  |         bm, groups->link, layer_n, data_tmp, loop_weights); | 
					
						
							| 
									
										
										
										
											2015-02-16 18:49:18 +11:00
										 |  |  |   } while ((groups = groups->next)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 13:55:11 +01:00
										 |  |  | /** \} */ |