2013-12-12 16:26:11 +11:00
|
|
|
/*
|
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* Contributor(s): Blender Foundation
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** \file blender/blenkernel/intern/mesh_mapping.c
|
|
|
|
* \ingroup bke
|
|
|
|
*
|
|
|
|
* Functions for accessing mesh connectivity data.
|
|
|
|
* eg: polys connected to verts, UV's connected to verts.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "DNA_meshdata_types.h"
|
2015-04-09 16:12:20 +02:00
|
|
|
#include "DNA_vec_types.h"
|
2013-12-12 16:26:11 +11:00
|
|
|
|
2015-04-09 16:12:20 +02:00
|
|
|
#include "BLI_buffer.h"
|
2013-12-12 16:26:11 +11:00
|
|
|
#include "BLI_utildefines.h"
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
#include "BLI_bitmap.h"
|
2013-12-12 16:26:11 +11:00
|
|
|
#include "BLI_math.h"
|
|
|
|
|
|
|
|
#include "BKE_mesh_mapping.h"
|
2013-12-12 17:11:27 +11:00
|
|
|
#include "BKE_customdata.h"
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
#include "BLI_memarena.h"
|
2013-12-12 16:26:11 +11:00
|
|
|
|
|
|
|
#include "BLI_strict_flags.h"
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/** \name Mesh Connectivity Mapping
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ngon version wip, based on BM_uv_vert_map_create */
|
|
|
|
/* this replaces the non bmesh function (in trunk) which takes MTFace's, if we ever need it back we could
|
|
|
|
* but for now this replaces it because its unused. */
|
|
|
|
|
2015-05-17 23:04:34 +10:00
|
|
|
UvVertMap *BKE_mesh_uv_vert_map_create(
|
|
|
|
struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv,
|
|
|
|
unsigned int totpoly, unsigned int totvert,
|
|
|
|
const float limit[2], const bool selected, const bool use_winding)
|
2013-12-12 16:26:11 +11:00
|
|
|
{
|
|
|
|
UvVertMap *vmap;
|
|
|
|
UvMapVert *buf;
|
|
|
|
MPoly *mp;
|
|
|
|
unsigned int a;
|
|
|
|
int i, totuv, nverts;
|
|
|
|
|
2015-09-04 01:04:37 +02:00
|
|
|
bool *winding = NULL;
|
2015-04-09 16:12:20 +02:00
|
|
|
BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, 32);
|
2013-12-12 16:26:11 +11:00
|
|
|
|
2015-04-09 16:17:51 +02:00
|
|
|
totuv = 0;
|
|
|
|
|
2013-12-12 16:26:11 +11:00
|
|
|
/* generate UvMapVert array */
|
|
|
|
mp = mpoly;
|
|
|
|
for (a = 0; a < totpoly; a++, mp++)
|
|
|
|
if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL)))
|
|
|
|
totuv += mp->totloop;
|
|
|
|
|
|
|
|
if (totuv == 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
vmap = (UvVertMap *)MEM_callocN(sizeof(*vmap), "UvVertMap");
|
|
|
|
buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * (size_t)totuv, "UvMapVert");
|
2015-06-20 19:28:51 +10:00
|
|
|
vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totvert, "UvMapVert*");
|
|
|
|
if (use_winding) {
|
|
|
|
winding = MEM_callocN(sizeof(*winding) * totpoly, "winding");
|
|
|
|
}
|
2013-12-12 16:26:11 +11:00
|
|
|
|
|
|
|
if (!vmap->vert || !vmap->buf) {
|
|
|
|
BKE_mesh_uv_vert_map_free(vmap);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
mp = mpoly;
|
|
|
|
for (a = 0; a < totpoly; a++, mp++) {
|
|
|
|
if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) {
|
2015-09-04 01:04:37 +02:00
|
|
|
float (*tf_uv)[2] = NULL;
|
2015-06-20 19:28:51 +10:00
|
|
|
|
|
|
|
if (use_winding) {
|
2015-10-04 14:14:28 +11:00
|
|
|
tf_uv = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, (size_t)mp->totloop);
|
2015-06-20 19:28:51 +10:00
|
|
|
}
|
2015-04-09 16:12:20 +02:00
|
|
|
|
2013-12-12 16:26:11 +11:00
|
|
|
nverts = mp->totloop;
|
|
|
|
|
|
|
|
for (i = 0; i < nverts; i++) {
|
|
|
|
buf->tfindex = (unsigned char)i;
|
|
|
|
buf->f = a;
|
|
|
|
buf->separate = 0;
|
|
|
|
buf->next = vmap->vert[mloop[mp->loopstart + i].v];
|
|
|
|
vmap->vert[mloop[mp->loopstart + i].v] = buf;
|
2015-04-09 16:12:20 +02:00
|
|
|
|
2015-06-20 19:28:51 +10:00
|
|
|
if (use_winding) {
|
|
|
|
copy_v2_v2(tf_uv[i], mloopuv[mpoly[a].loopstart + i].uv);
|
|
|
|
}
|
|
|
|
|
2013-12-12 16:26:11 +11:00
|
|
|
buf++;
|
|
|
|
}
|
2015-04-09 16:12:20 +02:00
|
|
|
|
2015-06-20 19:28:51 +10:00
|
|
|
if (use_winding) {
|
2017-10-20 14:03:22 +11:00
|
|
|
winding[a] = cross_poly_v2(tf_uv, (unsigned int)nverts) > 0;
|
2015-06-20 19:28:51 +10:00
|
|
|
}
|
2013-12-12 16:26:11 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* sort individual uvs for each vert */
|
|
|
|
for (a = 0; a < totvert; a++) {
|
|
|
|
UvMapVert *newvlist = NULL, *vlist = vmap->vert[a];
|
|
|
|
UvMapVert *iterv, *v, *lastv, *next;
|
|
|
|
float *uv, *uv2, uvdiff[2];
|
|
|
|
|
|
|
|
while (vlist) {
|
|
|
|
v = vlist;
|
|
|
|
vlist = vlist->next;
|
|
|
|
v->next = newvlist;
|
|
|
|
newvlist = v;
|
|
|
|
|
|
|
|
uv = mloopuv[mpoly[v->f].loopstart + v->tfindex].uv;
|
|
|
|
lastv = NULL;
|
|
|
|
iterv = vlist;
|
|
|
|
|
|
|
|
while (iterv) {
|
|
|
|
next = iterv->next;
|
|
|
|
|
|
|
|
uv2 = mloopuv[mpoly[iterv->f].loopstart + iterv->tfindex].uv;
|
|
|
|
sub_v2_v2v2(uvdiff, uv2, uv);
|
|
|
|
|
|
|
|
|
2015-04-09 16:12:20 +02:00
|
|
|
if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1] &&
|
2015-06-20 19:28:51 +10:00
|
|
|
(!use_winding || winding[iterv->f] == winding[v->f]))
|
2015-04-09 16:12:20 +02:00
|
|
|
{
|
2013-12-12 16:26:11 +11:00
|
|
|
if (lastv) lastv->next = next;
|
|
|
|
else vlist = next;
|
|
|
|
iterv->next = newvlist;
|
|
|
|
newvlist = iterv;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
lastv = iterv;
|
|
|
|
|
|
|
|
iterv = next;
|
|
|
|
}
|
|
|
|
|
|
|
|
newvlist->separate = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
vmap->vert[a] = newvlist;
|
|
|
|
}
|
|
|
|
|
2017-06-02 15:38:04 +10:00
|
|
|
if (use_winding) {
|
2015-06-20 19:28:51 +10:00
|
|
|
MEM_freeN(winding);
|
|
|
|
}
|
|
|
|
|
2015-04-09 16:12:20 +02:00
|
|
|
BLI_buffer_free(&tf_uv_buf);
|
|
|
|
|
2013-12-12 16:26:11 +11:00
|
|
|
return vmap;
|
|
|
|
}
|
|
|
|
|
|
|
|
UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v)
|
|
|
|
{
|
|
|
|
return vmap->vert[v];
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
|
|
|
|
{
|
|
|
|
if (vmap) {
|
|
|
|
if (vmap->vert) MEM_freeN(vmap->vert);
|
|
|
|
if (vmap->buf) MEM_freeN(vmap->buf);
|
|
|
|
MEM_freeN(vmap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
/**
|
|
|
|
* Generates a map where the key is the vertex and the value is a list
|
|
|
|
* of polys or loops that use that vertex as a corner. The lists are allocated
|
|
|
|
* from one memory pool.
|
|
|
|
*
|
|
|
|
* Wrapped by #BKE_mesh_vert_poly_map_create & BKE_mesh_vert_loop_map_create
|
|
|
|
*/
|
|
|
|
static void mesh_vert_poly_or_loop_map_create(
|
|
|
|
MeshElemMap **r_map, int **r_mem,
|
|
|
|
const MPoly *mpoly, const MLoop *mloop,
|
|
|
|
int totvert, int totpoly, int totloop, const bool do_loops)
|
2013-12-12 16:26:11 +11:00
|
|
|
{
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, __func__);
|
2013-12-12 16:26:11 +11:00
|
|
|
int *indices, *index_iter;
|
|
|
|
int i, j;
|
|
|
|
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
indices = index_iter = MEM_mallocN(sizeof(int) * (size_t)totloop, __func__);
|
2013-12-12 16:26:11 +11:00
|
|
|
|
|
|
|
/* Count number of polys for each vertex */
|
|
|
|
for (i = 0; i < totpoly; i++) {
|
|
|
|
const MPoly *p = &mpoly[i];
|
|
|
|
|
|
|
|
for (j = 0; j < p->totloop; j++)
|
|
|
|
map[mloop[p->loopstart + j].v].count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Assign indices mem */
|
|
|
|
for (i = 0; i < totvert; i++) {
|
|
|
|
map[i].indices = index_iter;
|
|
|
|
index_iter += map[i].count;
|
|
|
|
|
|
|
|
/* Reset 'count' for use as index in last loop */
|
|
|
|
map[i].count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Find the users */
|
|
|
|
for (i = 0; i < totpoly; i++) {
|
|
|
|
const MPoly *p = &mpoly[i];
|
|
|
|
|
|
|
|
for (j = 0; j < p->totloop; j++) {
|
|
|
|
unsigned int v = mloop[p->loopstart + j].v;
|
|
|
|
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
map[v].indices[map[v].count] = do_loops ? p->loopstart + j : i;
|
2013-12-12 16:26:11 +11:00
|
|
|
map[v].count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*r_map = map;
|
|
|
|
*r_mem = indices;
|
|
|
|
}
|
|
|
|
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
/**
|
|
|
|
* Generates a map where the key is the vertex and the value is a list of polys that use that vertex as a corner.
|
|
|
|
* The lists are allocated from one memory pool.
|
|
|
|
*/
|
|
|
|
void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem,
|
|
|
|
const MPoly *mpoly, const MLoop *mloop,
|
|
|
|
int totvert, int totpoly, int totloop)
|
|
|
|
{
|
|
|
|
mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a map where the key is the vertex and the value is a list of loops that use that vertex as a corner.
|
|
|
|
* The lists are allocated from one memory pool.
|
|
|
|
*/
|
|
|
|
void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, int **r_mem,
|
|
|
|
const MPoly *mpoly, const MLoop *mloop,
|
|
|
|
int totvert, int totpoly, int totloop)
|
|
|
|
{
|
|
|
|
mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, true);
|
|
|
|
}
|
|
|
|
|
2016-05-21 12:38:02 +02:00
|
|
|
/**
|
|
|
|
* Generates a map where the key is the edge and the value is a list of looptris that use that edge.
|
|
|
|
* The lists are allocated from one memory pool.
|
|
|
|
*/
|
|
|
|
void BKE_mesh_vert_looptri_map_create(
|
|
|
|
MeshElemMap **r_map, int **r_mem,
|
|
|
|
const MVert *UNUSED(mvert), const int totvert,
|
|
|
|
const MLoopTri *mlooptri, const int totlooptri,
|
|
|
|
const MLoop *mloop, const int UNUSED(totloop))
|
|
|
|
{
|
|
|
|
MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, __func__);
|
|
|
|
int *indices = MEM_mallocN(sizeof(int) * (size_t)totlooptri * 3, __func__);
|
|
|
|
int *index_step;
|
|
|
|
const MLoopTri *mlt;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* count face users */
|
|
|
|
for (i = 0, mlt = mlooptri; i < totlooptri; mlt++, i++) {
|
|
|
|
for (int j = 3; j--;) {
|
|
|
|
map[mloop[mlt->tri[j]].v].count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create offsets */
|
|
|
|
index_step = indices;
|
|
|
|
for (i = 0; i < totvert; i++) {
|
|
|
|
map[i].indices = index_step;
|
|
|
|
index_step += map[i].count;
|
|
|
|
|
|
|
|
/* re-count, using this as an index below */
|
|
|
|
map[i].count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* assign looptri-edge users */
|
|
|
|
for (i = 0, mlt = mlooptri; i < totlooptri; mlt++, i++) {
|
|
|
|
for (int j = 3; j--;) {
|
|
|
|
MeshElemMap *map_ele = &map[mloop[mlt->tri[j]].v];
|
|
|
|
map_ele->indices[map_ele->count++] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*r_map = map;
|
|
|
|
*r_mem = indices;
|
|
|
|
}
|
|
|
|
|
2015-04-28 14:15:27 +02:00
|
|
|
/**
|
|
|
|
* Generates a map where the key is the vertex and the value is a list of edges that use that vertex as an endpoint.
|
|
|
|
* The lists are allocated from one memory pool.
|
|
|
|
*/
|
2013-12-12 16:26:11 +11:00
|
|
|
void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem,
|
|
|
|
const MEdge *medge, int totvert, int totedge)
|
|
|
|
{
|
|
|
|
MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, "vert-edge map");
|
|
|
|
int *indices = MEM_mallocN(sizeof(int[2]) * (size_t)totedge, "vert-edge map mem");
|
|
|
|
int *i_pt = indices;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Count number of edges for each vertex */
|
|
|
|
for (i = 0; i < totedge; i++) {
|
|
|
|
map[medge[i].v1].count++;
|
|
|
|
map[medge[i].v2].count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Assign indices mem */
|
|
|
|
for (i = 0; i < totvert; i++) {
|
|
|
|
map[i].indices = i_pt;
|
|
|
|
i_pt += map[i].count;
|
|
|
|
|
|
|
|
/* Reset 'count' for use as index in last loop */
|
|
|
|
map[i].count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Find the users */
|
|
|
|
for (i = 0; i < totedge; i++) {
|
|
|
|
const unsigned int v[2] = {medge[i].v1, medge[i].v2};
|
|
|
|
|
|
|
|
map[v[0]].indices[map[v[0]].count] = i;
|
|
|
|
map[v[1]].indices[map[v[1]].count] = i;
|
|
|
|
|
|
|
|
map[v[0]].count++;
|
|
|
|
map[v[1]].count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*r_map = map;
|
|
|
|
*r_mem = indices;
|
|
|
|
}
|
|
|
|
|
2016-03-22 22:07:45 +11:00
|
|
|
/**
|
|
|
|
* A version of #BKE_mesh_vert_edge_map_create that references connected vertices directly (not their edges).
|
|
|
|
*/
|
|
|
|
void BKE_mesh_vert_edge_vert_map_create(
|
|
|
|
MeshElemMap **r_map, int **r_mem,
|
|
|
|
const MEdge *medge, int totvert, int totedge)
|
|
|
|
{
|
|
|
|
MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, "vert-edge map");
|
|
|
|
int *indices = MEM_mallocN(sizeof(int[2]) * (size_t)totedge, "vert-edge map mem");
|
|
|
|
int *i_pt = indices;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Count number of edges for each vertex */
|
|
|
|
for (i = 0; i < totedge; i++) {
|
|
|
|
map[medge[i].v1].count++;
|
|
|
|
map[medge[i].v2].count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Assign indices mem */
|
|
|
|
for (i = 0; i < totvert; i++) {
|
|
|
|
map[i].indices = i_pt;
|
|
|
|
i_pt += map[i].count;
|
|
|
|
|
|
|
|
/* Reset 'count' for use as index in last loop */
|
|
|
|
map[i].count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Find the users */
|
|
|
|
for (i = 0; i < totedge; i++) {
|
|
|
|
const unsigned int v[2] = {medge[i].v1, medge[i].v2};
|
|
|
|
|
|
|
|
map[v[0]].indices[map[v[0]].count] = (int)v[1];
|
|
|
|
map[v[1]].indices[map[v[1]].count] = (int)v[0];
|
|
|
|
|
|
|
|
map[v[0]].count++;
|
|
|
|
map[v[1]].count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*r_map = map;
|
|
|
|
*r_mem = indices;
|
|
|
|
}
|
|
|
|
|
2016-07-21 16:30:57 +02:00
|
|
|
/**
|
|
|
|
* Generates a map where the key is the edge and the value is a list of loops that use that edge.
|
|
|
|
* Loops indices of a same poly are contiguous and in winding order.
|
|
|
|
* The lists are allocated from one memory pool.
|
|
|
|
*/
|
|
|
|
void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, int **r_mem,
|
|
|
|
const MEdge *UNUSED(medge), const int totedge,
|
|
|
|
const MPoly *mpoly, const int totpoly,
|
|
|
|
const MLoop *mloop, const int totloop)
|
|
|
|
{
|
|
|
|
MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totedge, "edge-poly map");
|
|
|
|
int *indices = MEM_mallocN(sizeof(int) * (size_t)totloop * 2, "edge-poly map mem");
|
|
|
|
int *index_step;
|
|
|
|
const MPoly *mp;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* count face users */
|
|
|
|
for (i = 0, mp = mpoly; i < totpoly; mp++, i++) {
|
|
|
|
const MLoop *ml;
|
|
|
|
int j = mp->totloop;
|
|
|
|
for (ml = &mloop[mp->loopstart]; j--; ml++) {
|
|
|
|
map[ml->e].count += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create offsets */
|
|
|
|
index_step = indices;
|
|
|
|
for (i = 0; i < totedge; i++) {
|
|
|
|
map[i].indices = index_step;
|
|
|
|
index_step += map[i].count;
|
|
|
|
|
|
|
|
/* re-count, using this as an index below */
|
|
|
|
map[i].count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* assign loop-edge users */
|
|
|
|
for (i = 0, mp = mpoly; i < totpoly; mp++, i++) {
|
|
|
|
const MLoop *ml;
|
|
|
|
MeshElemMap *map_ele;
|
|
|
|
const int max_loop = mp->loopstart + mp->totloop;
|
|
|
|
int j = mp->loopstart;
|
|
|
|
for (ml = &mloop[j]; j < max_loop; j++, ml++) {
|
|
|
|
map_ele = &map[ml->e];
|
|
|
|
map_ele->indices[map_ele->count++] = j;
|
|
|
|
map_ele->indices[map_ele->count++] = j + 1;
|
|
|
|
}
|
|
|
|
/* last edge/loop of poly, must point back to first loop! */
|
|
|
|
map_ele->indices[map_ele->count - 1] = mp->loopstart;
|
|
|
|
}
|
|
|
|
|
|
|
|
*r_map = map;
|
|
|
|
*r_mem = indices;
|
|
|
|
}
|
|
|
|
|
2015-04-28 14:15:27 +02:00
|
|
|
/**
|
|
|
|
* Generates a map where the key is the edge and the value is a list of polygons that use that edge.
|
|
|
|
* The lists are allocated from one memory pool.
|
|
|
|
*/
|
2013-12-12 16:26:11 +11:00
|
|
|
void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem,
|
|
|
|
const MEdge *UNUSED(medge), const int totedge,
|
|
|
|
const MPoly *mpoly, const int totpoly,
|
|
|
|
const MLoop *mloop, const int totloop)
|
|
|
|
{
|
|
|
|
MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totedge, "edge-poly map");
|
|
|
|
int *indices = MEM_mallocN(sizeof(int) * (size_t)totloop, "edge-poly map mem");
|
|
|
|
int *index_step;
|
|
|
|
const MPoly *mp;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* count face users */
|
|
|
|
for (i = 0, mp = mpoly; i < totpoly; mp++, i++) {
|
|
|
|
const MLoop *ml;
|
|
|
|
int j = mp->totloop;
|
|
|
|
for (ml = &mloop[mp->loopstart]; j--; ml++) {
|
|
|
|
map[ml->e].count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create offsets */
|
|
|
|
index_step = indices;
|
|
|
|
for (i = 0; i < totedge; i++) {
|
|
|
|
map[i].indices = index_step;
|
|
|
|
index_step += map[i].count;
|
|
|
|
|
|
|
|
/* re-count, using this as an index below */
|
|
|
|
map[i].count = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* assign poly-edge users */
|
|
|
|
for (i = 0, mp = mpoly; i < totpoly; mp++, i++) {
|
|
|
|
const MLoop *ml;
|
|
|
|
int j = mp->totloop;
|
|
|
|
for (ml = &mloop[mp->loopstart]; j--; ml++) {
|
|
|
|
MeshElemMap *map_ele = &map[ml->e];
|
|
|
|
map_ele->indices[map_ele->count++] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*r_map = map;
|
|
|
|
*r_mem = indices;
|
|
|
|
}
|
|
|
|
|
2013-12-12 17:11:27 +11:00
|
|
|
/**
|
|
|
|
* This function creates a map so the source-data (vert/edge/loop/poly)
|
|
|
|
* can loop over the destination data (using the destination arrays origindex).
|
|
|
|
*
|
|
|
|
* This has the advantage that it can operate on any data-types.
|
|
|
|
*
|
|
|
|
* \param totsource The total number of elements the that \a final_origindex points to.
|
|
|
|
* \param totfinal The size of \a final_origindex
|
|
|
|
* \param final_origindex The size of the final array.
|
|
|
|
*
|
|
|
|
* \note ``totsource`` could be ``totpoly``,
|
|
|
|
* ``totfinal`` could be ``tottessface`` and ``final_origindex`` its ORIGINDEX customdata.
|
|
|
|
* This would allow an MPoly to loop over its tessfaces.
|
|
|
|
*/
|
|
|
|
void BKE_mesh_origindex_map_create(MeshElemMap **r_map, int **r_mem,
|
|
|
|
const int totsource,
|
|
|
|
const int *final_origindex, const int totfinal)
|
|
|
|
{
|
|
|
|
MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totsource, "poly-tessface map");
|
|
|
|
int *indices = MEM_mallocN(sizeof(int) * (size_t)totfinal, "poly-tessface map mem");
|
|
|
|
int *index_step;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* count face users */
|
|
|
|
for (i = 0; i < totfinal; i++) {
|
|
|
|
if (final_origindex[i] != ORIGINDEX_NONE) {
|
|
|
|
BLI_assert(final_origindex[i] < totsource);
|
|
|
|
map[final_origindex[i]].count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create offsets */
|
|
|
|
index_step = indices;
|
|
|
|
for (i = 0; i < totsource; i++) {
|
|
|
|
map[i].indices = index_step;
|
|
|
|
index_step += map[i].count;
|
|
|
|
|
|
|
|
/* re-count, using this as an index below */
|
|
|
|
map[i].count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* assign poly-tessface users */
|
|
|
|
for (i = 0; i < totfinal; i++) {
|
|
|
|
if (final_origindex[i] != ORIGINDEX_NONE) {
|
|
|
|
MeshElemMap *map_ele = &map[final_origindex[i]];
|
|
|
|
map_ele->indices[map_ele->count++] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*r_map = map;
|
|
|
|
*r_mem = indices;
|
|
|
|
}
|
2013-12-12 16:26:11 +11:00
|
|
|
|
2015-07-23 15:08:27 +10:00
|
|
|
/**
|
|
|
|
* A version of #BKE_mesh_origindex_map_create that takes a looptri array.
|
|
|
|
* Making a poly -> looptri map.
|
|
|
|
*/
|
|
|
|
void BKE_mesh_origindex_map_create_looptri(
|
|
|
|
MeshElemMap **r_map, int **r_mem,
|
|
|
|
const MPoly *mpoly, const int mpoly_num,
|
|
|
|
const MLoopTri *looptri, const int looptri_num)
|
|
|
|
{
|
|
|
|
MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)mpoly_num, "poly-tessface map");
|
|
|
|
int *indices = MEM_mallocN(sizeof(int) * (size_t)looptri_num, "poly-tessface map mem");
|
|
|
|
int *index_step;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* create offsets */
|
|
|
|
index_step = indices;
|
|
|
|
for (i = 0; i < mpoly_num; i++) {
|
|
|
|
map[i].indices = index_step;
|
|
|
|
index_step += ME_POLY_TRI_TOT(&mpoly[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* assign poly-tessface users */
|
|
|
|
for (i = 0; i < looptri_num; i++) {
|
|
|
|
MeshElemMap *map_ele = &map[looptri[i].poly];
|
|
|
|
map_ele->indices[map_ele->count++] = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
*r_map = map;
|
|
|
|
*r_mem = indices;
|
|
|
|
}
|
|
|
|
|
2013-12-12 16:26:11 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
/** \name Mesh loops/poly islands.
|
|
|
|
* Used currently for UVs and 'smooth groups'.
|
2013-12-12 16:26:11 +11:00
|
|
|
* \{ */
|
|
|
|
|
2015-04-28 14:15:27 +02:00
|
|
|
/**
|
|
|
|
* Callback deciding whether the given poly/loop/edge define an island boundary or not.
|
2013-12-12 16:26:11 +11:00
|
|
|
*/
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
typedef bool (*MeshRemap_CheckIslandBoundary)(
|
|
|
|
const struct MPoly *mpoly, const struct MLoop *mloop, const struct MEdge *medge,
|
2016-07-21 16:53:00 +02:00
|
|
|
const int nbr_egde_users, void *user_data);
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
|
|
|
|
static void poly_edge_loop_islands_calc(
|
|
|
|
const MEdge *medge, const int totedge, const MPoly *mpoly, const int totpoly,
|
|
|
|
const MLoop *mloop, const int totloop, MeshElemMap *edge_poly_map,
|
2016-07-21 16:53:00 +02:00
|
|
|
const bool use_bitflags, MeshRemap_CheckIslandBoundary edge_boundary_check, void *edge_boundary_check_data,
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
int **r_poly_groups, int *r_totgroup, BLI_bitmap **r_edge_borders, int *r_totedgeborder)
|
2013-12-12 16:26:11 +11:00
|
|
|
{
|
|
|
|
int *poly_groups;
|
|
|
|
int *poly_stack;
|
|
|
|
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
BLI_bitmap *edge_borders = NULL;
|
|
|
|
int num_edgeborders = 0;
|
|
|
|
|
2013-12-12 16:26:11 +11:00
|
|
|
int poly_prev = 0;
|
|
|
|
const int temp_poly_group_id = 3; /* Placeholder value. */
|
|
|
|
const int poly_group_id_overflowed = 5; /* Group we could not find any available bit, will be reset to 0 at end */
|
|
|
|
int tot_group = 0;
|
|
|
|
bool group_id_overflow = false;
|
|
|
|
|
|
|
|
/* map vars */
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
int *edge_poly_mem = NULL;
|
2013-12-12 16:26:11 +11:00
|
|
|
|
|
|
|
if (totpoly == 0) {
|
|
|
|
*r_totgroup = 0;
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
*r_poly_groups = NULL;
|
|
|
|
if (r_edge_borders) {
|
|
|
|
*r_edge_borders = NULL;
|
|
|
|
*r_totedgeborder = 0;
|
|
|
|
}
|
|
|
|
return;
|
2013-12-12 16:26:11 +11:00
|
|
|
}
|
|
|
|
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
if (r_edge_borders) {
|
|
|
|
edge_borders = BLI_BITMAP_NEW(totedge, __func__);
|
|
|
|
*r_totedgeborder = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!edge_poly_map) {
|
|
|
|
BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem,
|
|
|
|
medge, totedge, mpoly, totpoly, mloop, totloop);
|
|
|
|
}
|
2013-12-12 16:26:11 +11:00
|
|
|
|
|
|
|
poly_groups = MEM_callocN(sizeof(int) * (size_t)totpoly, __func__);
|
|
|
|
poly_stack = MEM_mallocN(sizeof(int) * (size_t)totpoly, __func__);
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
int poly;
|
|
|
|
int bit_poly_group_mask = 0;
|
|
|
|
int poly_group_id;
|
|
|
|
int ps_curr_idx = 0, ps_end_idx = 0; /* stack indices */
|
|
|
|
|
|
|
|
for (poly = poly_prev; poly < totpoly; poly++) {
|
|
|
|
if (poly_groups[poly] == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (poly == totpoly) {
|
|
|
|
/* all done */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
poly_group_id = use_bitflags ? temp_poly_group_id : ++tot_group;
|
|
|
|
|
|
|
|
/* start searching from here next time */
|
|
|
|
poly_prev = poly + 1;
|
|
|
|
|
|
|
|
poly_groups[poly] = poly_group_id;
|
|
|
|
poly_stack[ps_end_idx++] = poly;
|
|
|
|
|
|
|
|
while (ps_curr_idx != ps_end_idx) {
|
|
|
|
const MPoly *mp;
|
|
|
|
const MLoop *ml;
|
|
|
|
int j;
|
|
|
|
|
|
|
|
poly = poly_stack[ps_curr_idx++];
|
|
|
|
BLI_assert(poly_groups[poly] == poly_group_id);
|
|
|
|
|
|
|
|
mp = &mpoly[poly];
|
|
|
|
for (ml = &mloop[mp->loopstart], j = mp->totloop; j--; ml++) {
|
|
|
|
/* loop over poly users */
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
const int me_idx = (int)ml->e;
|
|
|
|
const MEdge *me = &medge[me_idx];
|
|
|
|
const MeshElemMap *map_ele = &edge_poly_map[me_idx];
|
2014-04-27 00:20:13 +10:00
|
|
|
const int *p = map_ele->indices;
|
2013-12-12 16:26:11 +11:00
|
|
|
int i = map_ele->count;
|
2016-07-21 16:53:00 +02:00
|
|
|
if (!edge_boundary_check(mp, ml, me, i, edge_boundary_check_data)) {
|
2013-12-12 16:26:11 +11:00
|
|
|
for (; i--; p++) {
|
|
|
|
/* if we meet other non initialized its a bug */
|
|
|
|
BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id));
|
|
|
|
|
|
|
|
if (poly_groups[*p] == 0) {
|
|
|
|
poly_groups[*p] = poly_group_id;
|
|
|
|
poly_stack[ps_end_idx++] = *p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
else {
|
|
|
|
if (edge_borders && !BLI_BITMAP_TEST(edge_borders, me_idx)) {
|
|
|
|
BLI_BITMAP_ENABLE(edge_borders, me_idx);
|
|
|
|
num_edgeborders++;
|
|
|
|
}
|
|
|
|
if (use_bitflags) {
|
|
|
|
/* Find contiguous smooth groups already assigned, these are the values we can't reuse! */
|
|
|
|
for (; i--; p++) {
|
|
|
|
int bit = poly_groups[*p];
|
|
|
|
if (!ELEM(bit, 0, poly_group_id, poly_group_id_overflowed) &&
|
|
|
|
!(bit_poly_group_mask & bit))
|
|
|
|
{
|
|
|
|
bit_poly_group_mask |= bit;
|
|
|
|
}
|
2013-12-12 16:26:11 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* And now, we have all our poly from current group in poly_stack (from 0 to (ps_end_idx - 1)), as well as
|
|
|
|
* all smoothgroups bits we can't use in bit_poly_group_mask.
|
|
|
|
*/
|
|
|
|
if (use_bitflags) {
|
|
|
|
int i, *p, gid_bit = 0;
|
|
|
|
poly_group_id = 1;
|
|
|
|
|
|
|
|
/* Find first bit available! */
|
|
|
|
for (; (poly_group_id & bit_poly_group_mask) && (gid_bit < 32); gid_bit++) {
|
|
|
|
poly_group_id <<= 1; /* will 'overflow' on last possible iteration. */
|
|
|
|
}
|
|
|
|
if (UNLIKELY(gid_bit > 31)) {
|
|
|
|
/* All bits used in contiguous smooth groups, we can't do much!
|
|
|
|
* Note: this is *very* unlikely - theoretically, four groups are enough, I don't think we can reach
|
|
|
|
* this goal with such a simple algo, but I don't think either we'll never need all 32 groups!
|
|
|
|
*/
|
|
|
|
printf("Warning, could not find an available id for current smooth group, faces will me marked "
|
|
|
|
"as out of any smooth group...\n");
|
|
|
|
poly_group_id = poly_group_id_overflowed; /* Can't use 0, will have to set them to this value later. */
|
|
|
|
group_id_overflow = true;
|
|
|
|
}
|
|
|
|
if (gid_bit > tot_group) {
|
|
|
|
tot_group = gid_bit;
|
|
|
|
}
|
|
|
|
/* And assign the final smooth group id to that poly group! */
|
|
|
|
for (i = ps_end_idx, p = poly_stack; i--; p++) {
|
|
|
|
poly_groups[*p] = poly_group_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-13 10:32:59 +02:00
|
|
|
if (use_bitflags) {
|
|
|
|
/* used bits are zero-based. */
|
|
|
|
tot_group++;
|
|
|
|
}
|
|
|
|
|
2013-12-12 16:26:11 +11:00
|
|
|
if (UNLIKELY(group_id_overflow)) {
|
|
|
|
int i = totpoly, *gid = poly_groups;
|
|
|
|
for (; i--; gid++) {
|
|
|
|
if (*gid == poly_group_id_overflowed) {
|
|
|
|
*gid = 0;
|
|
|
|
}
|
|
|
|
}
|
2014-10-13 10:32:59 +02:00
|
|
|
/* Using 0 as group id adds one more group! */
|
|
|
|
tot_group++;
|
2013-12-12 16:26:11 +11:00
|
|
|
}
|
|
|
|
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
if (edge_poly_mem) {
|
|
|
|
MEM_freeN(edge_poly_map);
|
|
|
|
MEM_freeN(edge_poly_mem);
|
|
|
|
}
|
2013-12-12 16:26:11 +11:00
|
|
|
MEM_freeN(poly_stack);
|
|
|
|
|
2014-10-13 10:32:59 +02:00
|
|
|
*r_totgroup = tot_group;
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
*r_poly_groups = poly_groups;
|
|
|
|
if (r_edge_borders) {
|
|
|
|
*r_edge_borders = edge_borders;
|
|
|
|
*r_totedgeborder = num_edgeborders;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool poly_is_island_boundary_smooth_cb(
|
2016-07-21 16:53:00 +02:00
|
|
|
const MPoly *mp, const MLoop *UNUSED(ml), const MEdge *me, const int nbr_egde_users, void *UNUSED(user_data))
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
{
|
|
|
|
/* Edge is sharp if its poly is sharp, or edge itself is sharp, or edge is not used by exactly two polygons. */
|
|
|
|
return (!(mp->flag & ME_SMOOTH) || (me->flag & ME_SHARP) || (nbr_egde_users != 2));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculate smooth groups from sharp edges.
|
|
|
|
*
|
|
|
|
* \param r_totgroup The total number of groups, 1 or more.
|
|
|
|
* \return Polygon aligned array of group index values (bitflags if use_bitflags is true), starting at 1
|
|
|
|
* (0 being used as 'invalid' flag).
|
|
|
|
* Note it's callers's responsibility to MEM_freeN returned array.
|
|
|
|
*/
|
|
|
|
int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
|
|
|
|
const MPoly *mpoly, const int totpoly,
|
|
|
|
const MLoop *mloop, const int totloop,
|
|
|
|
int *r_totgroup, const bool use_bitflags)
|
|
|
|
{
|
|
|
|
int *poly_groups = NULL;
|
|
|
|
|
|
|
|
poly_edge_loop_islands_calc(
|
|
|
|
medge, totedge, mpoly, totpoly, mloop, totloop, NULL, use_bitflags,
|
2016-07-21 16:53:00 +02:00
|
|
|
poly_is_island_boundary_smooth_cb, NULL, &poly_groups, r_totgroup, NULL, NULL);
|
2013-12-12 16:26:11 +11:00
|
|
|
|
|
|
|
return poly_groups;
|
|
|
|
}
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
|
|
|
|
#define MISLAND_DEFAULT_BUFSIZE 64
|
|
|
|
|
|
|
|
void BKE_mesh_loop_islands_init(
|
|
|
|
MeshIslandStore *island_store,
|
|
|
|
const short item_type, const int items_num, const short island_type, const short innercut_type)
|
|
|
|
{
|
|
|
|
MemArena *mem = island_store->mem;
|
|
|
|
|
|
|
|
if (mem == NULL) {
|
|
|
|
mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
|
|
|
|
island_store->mem = mem;
|
|
|
|
}
|
|
|
|
/* else memarena should be cleared */
|
|
|
|
|
|
|
|
BLI_assert(ELEM(item_type, MISLAND_TYPE_VERT, MISLAND_TYPE_EDGE, MISLAND_TYPE_POLY, MISLAND_TYPE_LOOP));
|
|
|
|
BLI_assert(ELEM(island_type, MISLAND_TYPE_VERT, MISLAND_TYPE_EDGE, MISLAND_TYPE_POLY, MISLAND_TYPE_LOOP));
|
|
|
|
|
|
|
|
island_store->item_type = item_type;
|
|
|
|
island_store->items_to_islands_num = items_num;
|
|
|
|
island_store->items_to_islands = BLI_memarena_alloc(mem, sizeof(*island_store->items_to_islands) * (size_t)items_num);
|
|
|
|
|
|
|
|
island_store->island_type = island_type;
|
|
|
|
island_store->islands_num_alloc = MISLAND_DEFAULT_BUFSIZE;
|
|
|
|
island_store->islands = BLI_memarena_alloc(mem, sizeof(*island_store->islands) * island_store->islands_num_alloc);
|
|
|
|
|
|
|
|
island_store->innercut_type = innercut_type;
|
|
|
|
island_store->innercuts = BLI_memarena_alloc(mem, sizeof(*island_store->innercuts) * island_store->islands_num_alloc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_mesh_loop_islands_clear(MeshIslandStore *island_store)
|
|
|
|
{
|
|
|
|
island_store->item_type = MISLAND_TYPE_NONE;
|
|
|
|
island_store->items_to_islands_num = 0;
|
|
|
|
island_store->items_to_islands = NULL;
|
|
|
|
|
|
|
|
island_store->island_type = MISLAND_TYPE_NONE;
|
|
|
|
island_store->islands_num = 0;
|
|
|
|
island_store->islands = NULL;
|
|
|
|
|
|
|
|
island_store->innercut_type = MISLAND_TYPE_NONE;
|
|
|
|
island_store->innercuts = NULL;
|
|
|
|
|
|
|
|
if (island_store->mem) {
|
|
|
|
BLI_memarena_clear(island_store->mem);
|
|
|
|
}
|
|
|
|
|
|
|
|
island_store->islands_num_alloc = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_mesh_loop_islands_free(MeshIslandStore *island_store)
|
|
|
|
{
|
|
|
|
if (island_store->mem) {
|
|
|
|
BLI_memarena_free(island_store->mem);
|
|
|
|
island_store->mem = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_mesh_loop_islands_add(
|
|
|
|
MeshIslandStore *island_store, const int item_num, int *items_indices,
|
|
|
|
const int num_island_items, int *island_item_indices,
|
|
|
|
const int num_innercut_items, int *innercut_item_indices)
|
|
|
|
{
|
|
|
|
MemArena *mem = island_store->mem;
|
|
|
|
|
|
|
|
MeshElemMap *isld, *innrcut;
|
|
|
|
const int curr_island_idx = island_store->islands_num++;
|
|
|
|
const size_t curr_num_islands = (size_t)island_store->islands_num;
|
|
|
|
int i = item_num;
|
|
|
|
|
|
|
|
while (i--) {
|
|
|
|
island_store->items_to_islands[items_indices[i]] = curr_island_idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UNLIKELY(curr_num_islands > island_store->islands_num_alloc)) {
|
|
|
|
MeshElemMap **islds, **innrcuts;
|
|
|
|
|
|
|
|
island_store->islands_num_alloc *= 2;
|
|
|
|
islds = BLI_memarena_alloc(mem, sizeof(*islds) * island_store->islands_num_alloc);
|
|
|
|
memcpy(islds, island_store->islands, sizeof(*islds) * (curr_num_islands - 1));
|
|
|
|
island_store->islands = islds;
|
|
|
|
|
|
|
|
innrcuts = BLI_memarena_alloc(mem, sizeof(*innrcuts) * island_store->islands_num_alloc);
|
|
|
|
memcpy(innrcuts, island_store->innercuts, sizeof(*innrcuts) * (curr_num_islands - 1));
|
|
|
|
island_store->innercuts = innrcuts;
|
|
|
|
}
|
|
|
|
|
|
|
|
island_store->islands[curr_island_idx] = isld = BLI_memarena_alloc(mem, sizeof(*isld));
|
|
|
|
isld->count = num_island_items;
|
|
|
|
isld->indices = BLI_memarena_alloc(mem, sizeof(*isld->indices) * (size_t)num_island_items);
|
|
|
|
memcpy(isld->indices, island_item_indices, sizeof(*isld->indices) * (size_t)num_island_items);
|
|
|
|
|
|
|
|
island_store->innercuts[curr_island_idx] = innrcut = BLI_memarena_alloc(mem, sizeof(*innrcut));
|
|
|
|
innrcut->count = num_innercut_items;
|
|
|
|
innrcut->indices = BLI_memarena_alloc(mem, sizeof(*innrcut->indices) * (size_t)num_innercut_items);
|
|
|
|
memcpy(innrcut->indices, innercut_item_indices, sizeof(*innrcut->indices) * (size_t)num_innercut_items);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: I'm not sure edge seam flag is enough to define UV islands? Maybe we should also consider UVmaps values
|
|
|
|
* themselves (i.e. different UV-edges for a same mesh-edge => boundary edge too?).
|
|
|
|
* Would make things much more complex though, and each UVMap would then need its own mesh mapping,
|
|
|
|
* not sure we want that at all!
|
|
|
|
*/
|
2016-07-21 16:53:00 +02:00
|
|
|
typedef struct MeshCheckIslandBoundaryUv {
|
|
|
|
const MLoop *loops;
|
|
|
|
const MLoopUV *luvs;
|
|
|
|
const MeshElemMap *edge_loop_map;
|
|
|
|
} MeshCheckIslandBoundaryUv;
|
|
|
|
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
static bool mesh_check_island_boundary_uv(
|
2016-07-21 16:53:00 +02:00
|
|
|
const MPoly *UNUSED(mp), const MLoop *ml, const MEdge *me,
|
|
|
|
const int UNUSED(nbr_egde_users), void *user_data)
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
{
|
2016-07-21 16:53:00 +02:00
|
|
|
if (user_data) {
|
|
|
|
const MeshCheckIslandBoundaryUv *data = user_data;
|
|
|
|
const MLoop *loops = data->loops;
|
|
|
|
const MLoopUV *luvs = data->luvs;
|
|
|
|
const MeshElemMap *edge_to_loops = &data->edge_loop_map[ml->e];
|
|
|
|
|
|
|
|
BLI_assert(edge_to_loops->count >= 2 && (edge_to_loops->count % 2) == 0);
|
|
|
|
|
|
|
|
const unsigned int v1 = loops[edge_to_loops->indices[0]].v;
|
|
|
|
const unsigned int v2 = loops[edge_to_loops->indices[1]].v;
|
|
|
|
const float *uvco_v1 = luvs[edge_to_loops->indices[0]].uv;
|
|
|
|
const float *uvco_v2 = luvs[edge_to_loops->indices[1]].uv;
|
|
|
|
for (int i = 2; i < edge_to_loops->count; i += 2) {
|
|
|
|
if (loops[edge_to_loops->indices[i]].v == v1) {
|
|
|
|
if (!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i]].uv) ||
|
|
|
|
!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i + 1]].uv))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BLI_assert(loops[edge_to_loops->indices[i]].v == v2);
|
2016-07-25 09:31:56 +02:00
|
|
|
UNUSED_VARS_NDEBUG(v2);
|
2016-07-21 16:53:00 +02:00
|
|
|
if (!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i]].uv) ||
|
|
|
|
!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i + 1]].uv))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Edge is UV boundary if tagged as seam. */
|
|
|
|
return (me->flag & ME_SEAM) != 0;
|
|
|
|
}
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
}
|
|
|
|
|
2016-07-21 16:53:00 +02:00
|
|
|
static bool mesh_calc_islands_loop_poly_uv(
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
MVert *UNUSED(verts), const int UNUSED(totvert),
|
|
|
|
MEdge *edges, const int totedge,
|
|
|
|
MPoly *polys, const int totpoly,
|
|
|
|
MLoop *loops, const int totloop,
|
2016-07-21 16:53:00 +02:00
|
|
|
const MLoopUV *luvs,
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
MeshIslandStore *r_island_store)
|
|
|
|
{
|
|
|
|
int *poly_groups = NULL;
|
|
|
|
int num_poly_groups;
|
|
|
|
|
|
|
|
/* map vars */
|
|
|
|
MeshElemMap *edge_poly_map;
|
|
|
|
int *edge_poly_mem;
|
|
|
|
|
2016-07-21 16:53:00 +02:00
|
|
|
MeshElemMap *edge_loop_map;
|
|
|
|
int *edge_loop_mem;
|
|
|
|
|
|
|
|
MeshCheckIslandBoundaryUv edge_boundary_check_data;
|
|
|
|
|
2015-02-20 17:09:40 +11:00
|
|
|
int *poly_indices;
|
|
|
|
int *loop_indices;
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
int num_pidx, num_lidx;
|
|
|
|
|
|
|
|
/* Those are used to detect 'inner cuts', i.e. edges that are borders, and yet have two or more polys of
|
|
|
|
* a same group using them (typical case: seam used to unwrap properly a cylinder). */
|
2015-07-24 05:04:33 +10:00
|
|
|
BLI_bitmap *edge_borders = NULL;
|
|
|
|
int num_edge_borders = 0;
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
char *edge_border_count = NULL;
|
|
|
|
int *edge_innercut_indices = NULL;
|
|
|
|
int num_einnercuts = 0;
|
|
|
|
|
|
|
|
int grp_idx, p_idx, pl_idx, l_idx;
|
|
|
|
|
|
|
|
BKE_mesh_loop_islands_clear(r_island_store);
|
|
|
|
BKE_mesh_loop_islands_init(r_island_store, MISLAND_TYPE_LOOP, totloop, MISLAND_TYPE_POLY, MISLAND_TYPE_EDGE);
|
|
|
|
|
|
|
|
BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem,
|
|
|
|
edges, totedge, polys, totpoly, loops, totloop);
|
|
|
|
|
2016-07-21 16:53:00 +02:00
|
|
|
if (luvs) {
|
|
|
|
BKE_mesh_edge_loop_map_create(&edge_loop_map, &edge_loop_mem,
|
|
|
|
edges, totedge, polys, totpoly, loops, totloop);
|
|
|
|
edge_boundary_check_data.loops = loops;
|
|
|
|
edge_boundary_check_data.luvs = luvs;
|
|
|
|
edge_boundary_check_data.edge_loop_map = edge_loop_map;
|
|
|
|
}
|
|
|
|
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
poly_edge_loop_islands_calc(
|
2016-07-21 16:53:00 +02:00
|
|
|
edges, totedge, polys, totpoly, loops, totloop, edge_poly_map, false,
|
|
|
|
mesh_check_island_boundary_uv, luvs ? &edge_boundary_check_data : NULL,
|
|
|
|
&poly_groups, &num_poly_groups, &edge_borders, &num_edge_borders);
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
|
|
|
|
if (!num_poly_groups) {
|
|
|
|
/* Should never happen... */
|
2015-07-24 05:04:33 +10:00
|
|
|
MEM_freeN(edge_poly_map);
|
|
|
|
MEM_freeN(edge_poly_mem);
|
|
|
|
|
|
|
|
if (edge_borders) {
|
|
|
|
MEM_freeN(edge_borders);
|
|
|
|
}
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num_edge_borders) {
|
|
|
|
edge_border_count = MEM_mallocN(sizeof(*edge_border_count) * (size_t)totedge, __func__);
|
|
|
|
edge_innercut_indices = MEM_mallocN(sizeof(*edge_innercut_indices) * (size_t)num_edge_borders, __func__);
|
|
|
|
}
|
|
|
|
|
2015-02-20 17:09:40 +11:00
|
|
|
poly_indices = MEM_mallocN(sizeof(*poly_indices) * (size_t)totpoly, __func__);
|
|
|
|
loop_indices = MEM_mallocN(sizeof(*loop_indices) * (size_t)totloop, __func__);
|
|
|
|
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
/* Note: here we ignore '0' invalid group - this should *never* happen in this case anyway? */
|
|
|
|
for (grp_idx = 1; grp_idx <= num_poly_groups; grp_idx++) {
|
|
|
|
num_pidx = num_lidx = 0;
|
|
|
|
if (num_edge_borders) {
|
|
|
|
num_einnercuts = 0;
|
|
|
|
memset(edge_border_count, 0, sizeof(*edge_border_count) * (size_t)totedge);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (p_idx = 0; p_idx < totpoly; p_idx++) {
|
|
|
|
MPoly *mp;
|
|
|
|
|
|
|
|
if (poly_groups[p_idx] != grp_idx) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
mp = &polys[p_idx];
|
|
|
|
poly_indices[num_pidx++] = p_idx;
|
|
|
|
for (l_idx = mp->loopstart, pl_idx = 0; pl_idx < mp->totloop; l_idx++, pl_idx++) {
|
|
|
|
MLoop *ml = &loops[l_idx];
|
|
|
|
loop_indices[num_lidx++] = l_idx;
|
|
|
|
if (num_edge_borders && BLI_BITMAP_TEST(edge_borders, ml->e) && (edge_border_count[ml->e] < 2)) {
|
|
|
|
edge_border_count[ml->e]++;
|
|
|
|
if (edge_border_count[ml->e] == 2) {
|
|
|
|
edge_innercut_indices[num_einnercuts++] = (int)ml->e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BKE_mesh_loop_islands_add(r_island_store, num_lidx, loop_indices, num_pidx, poly_indices,
|
|
|
|
num_einnercuts, edge_innercut_indices);
|
|
|
|
}
|
|
|
|
|
2015-07-24 05:04:33 +10:00
|
|
|
MEM_freeN(edge_poly_map);
|
|
|
|
MEM_freeN(edge_poly_mem);
|
|
|
|
|
2016-07-21 16:53:00 +02:00
|
|
|
if (luvs) {
|
|
|
|
MEM_freeN(edge_loop_map);
|
|
|
|
MEM_freeN(edge_loop_mem);
|
|
|
|
}
|
|
|
|
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
MEM_freeN(poly_indices);
|
|
|
|
MEM_freeN(loop_indices);
|
|
|
|
MEM_freeN(poly_groups);
|
2015-07-24 05:04:33 +10:00
|
|
|
|
|
|
|
if (edge_borders) {
|
|
|
|
MEM_freeN(edge_borders);
|
|
|
|
}
|
|
|
|
|
BKE: Add 'mesh remap' code.
This is the (big!) core of mesh transfer data, it defines a set of structures
to represent a mapping of mesh elements (verts, edges, polys of loops) between
two arbitrary meshes, and code to compute such mappings.
No similarity is required between source and destination meshes (though results
when using complete different meshes are rather unlikely to be useful!).
This code is not bound to data transfer, it is defined to be as generic as possible,
and easy to reuse or extend as needs arise.
Several methods of mapping generation are defined for each element type,
we probably will have to adjust that in future (remove useless ones, add
new ones...).
For loops, you can also define islands (for UVs e.g.) so that loops of a same
destination polygon do not 'spread' across several source islands.
Heavily reviewed and enhanced by Campbell, thanks a lot!
2015-01-09 18:23:17 +01:00
|
|
|
if (num_edge_borders) {
|
|
|
|
MEM_freeN(edge_border_count);
|
|
|
|
MEM_freeN(edge_innercut_indices);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-07-21 16:53:00 +02:00
|
|
|
/**
|
|
|
|
* Calculate 'generic' UV islands, i.e. based only on actual geometry data (edge seams), not some UV layers coordinates.
|
|
|
|
*/
|
|
|
|
bool BKE_mesh_calc_islands_loop_poly_edgeseam(
|
|
|
|
MVert *verts, const int totvert,
|
|
|
|
MEdge *edges, const int totedge,
|
|
|
|
MPoly *polys, const int totpoly,
|
|
|
|
MLoop *loops, const int totloop,
|
|
|
|
MeshIslandStore *r_island_store)
|
|
|
|
{
|
|
|
|
return mesh_calc_islands_loop_poly_uv(
|
|
|
|
verts, totvert, edges, totedge, polys, totpoly, loops, totloop, NULL, r_island_store);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculate UV islands.
|
|
|
|
*
|
|
|
|
* \note If no MLoopUV layer is passed, we only consider edges tagged as seams as UV boundaries.
|
|
|
|
* This has the advantages of simplicity, and being valid/common to all UV maps.
|
|
|
|
* However, it means actual UV islands whithout matching UV seams will not be handled correctly...
|
|
|
|
* If a valid UV layer is passed as \a luvs parameter, UV coordinates are also used to detect islands boundaries.
|
|
|
|
*
|
|
|
|
* \note All this could be optimized...
|
|
|
|
* Not sure it would be worth the more complex code, though, those loops are supposed to be really quick to do...
|
|
|
|
*/
|
|
|
|
bool BKE_mesh_calc_islands_loop_poly_uvmap(
|
|
|
|
MVert *verts, const int totvert,
|
|
|
|
MEdge *edges, const int totedge,
|
|
|
|
MPoly *polys, const int totpoly,
|
|
|
|
MLoop *loops, const int totloop,
|
|
|
|
const MLoopUV *luvs,
|
|
|
|
MeshIslandStore *r_island_store)
|
|
|
|
{
|
|
|
|
BLI_assert(luvs != NULL);
|
|
|
|
return mesh_calc_islands_loop_poly_uv(
|
|
|
|
verts, totvert, edges, totedge, polys, totpoly, loops, totloop, luvs, r_island_store);
|
|
|
|
}
|
|
|
|
|
2013-12-12 16:26:11 +11:00
|
|
|
/** \} */
|