Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/mesh.c')
-rw-r--r--source/blender/blenkernel/intern/mesh.c1067
1 files changed, 1019 insertions, 48 deletions
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index a5bf39d895c..074860c1076 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -41,15 +41,18 @@
#include "DNA_key_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_ipo_types.h"
+#include "DNA_customdata_types.h"
+#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_editVert.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
-#include "BLI_utildefines.h"
+#include "BLI_scanfill.h"
#include "BKE_animsys.h"
#include "BKE_main.h"
+#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
@@ -63,20 +66,316 @@
#include "BKE_curve.h"
/* -- */
#include "BKE_object.h"
+#include "BKE_tessmesh.h"
+#include "BLI_edgehash.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_math.h"
+#include "BLI_cellalloc.h"
+#include "BLI_array.h"
+#include "BLI_edgehash.h"
+#include "bmesh.h"
+
+enum {
+ MESHCMP_DVERT_WEIGHTMISMATCH = 1,
+ MESHCMP_DVERT_GROUPMISMATCH,
+ MESHCMP_DVERT_TOTGROUPMISMATCH,
+ MESHCMP_LOOPCOLMISMATCH,
+ MESHCMP_LOOPUVMISMATCH,
+ MESHCMP_LOOPMISMATCH,
+ MESHCMP_POLYVERTMISMATCH,
+ MESHCMP_POLYMISMATCH,
+ MESHCMP_EDGEUNKNOWN,
+ MESHCMP_VERTCOMISMATCH,
+ MESHCMP_CDLAYERS_MISMATCH,
+};
-EditMesh *BKE_mesh_get_editmesh(Mesh *me)
+static const char *cmpcode_to_str(int code)
{
- return me->edit_mesh;
+ switch (code) {
+ case MESHCMP_DVERT_WEIGHTMISMATCH:
+ return "Vertex Weight Mismatch";
+ case MESHCMP_DVERT_GROUPMISMATCH:
+ return "Vertex Group Mismatch";
+ case MESHCMP_DVERT_TOTGROUPMISMATCH:
+ return "Vertex Doesn't Belong To Same Number Of Groups";
+ case MESHCMP_LOOPCOLMISMATCH:
+ return "Vertex Color Mismatch";
+ case MESHCMP_LOOPUVMISMATCH:
+ return "UV Mismatch";
+ case MESHCMP_LOOPMISMATCH:
+ return "Loop Mismatch";
+ case MESHCMP_POLYVERTMISMATCH:
+ return "Loop Vert Mismatch In Poly Test";
+ case MESHCMP_POLYMISMATCH:
+ return "Loop Vert Mismatch";
+ case MESHCMP_EDGEUNKNOWN:
+ return "Edge Mismatch";
+ case MESHCMP_VERTCOMISMATCH:
+ return "Vertex Coordinate Mismatch";
+ case MESHCMP_CDLAYERS_MISMATCH:
+ "CustomData Layer Count Mismatch";
+ default:
+ return "Mesh Comparison Code Unknown";
+ }
}
-void BKE_mesh_end_editmesh(Mesh *UNUSED(me), EditMesh *UNUSED(em))
+/*thresh is threshold for comparing vertices, uvs, vertex colors,
+ weights, etc.*/
+static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2, float thresh)
{
+ CustomDataLayer *l1, *l2;
+ int i, i1=0, i2=0, tot, j;
+
+ for (i=0; i<c1->totlayer; i++) {
+ if (ELEM7(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ i1++;
+ }
+
+ for (i=0; i<c2->totlayer; i++) {
+ if (ELEM7(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ i2++;
+ }
+
+ if (i1 != i2)
+ return MESHCMP_CDLAYERS_MISMATCH;
+
+ l1 = c1->layers; l2 = c2->layers;
+ tot = i1;
+ i1 = 0; i2 = 0;
+ for (i=0; i < tot; i++) {
+ while (i1 < c1->totlayer && !ELEM7(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ i1++, l1++;
+
+ while (i2 < c2->totlayer && !ELEM7(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ i2++, l2++;
+
+ if (l1->type == CD_MVERT) {
+ MVert *v1 = l1->data;
+ MVert *v2 = l2->data;
+ int vtot = m1->totvert;
+
+ for (j=0; j<vtot; j++, v1++, v2++) {
+ if (len_v3v3(v1->co, v2->co) > thresh)
+ return MESHCMP_VERTCOMISMATCH;
+ /*I don't care about normals, let's just do coodinates*/
+ }
+ }
+
+ /*we're order-agnostic for edges here*/
+ if (l1->type == CD_MEDGE) {
+ MEdge *e1 = l1->data;
+ MEdge *e2 = l2->data;
+ EdgeHash *eh = BLI_edgehash_new();
+ int etot = m1->totedge;
+
+ for (j=0; j<etot; j++, e1++) {
+ BLI_edgehash_insert(eh, e1->v1, e1->v2, e1);
+ }
+
+ for (j=0; j<etot; j++, e2++) {
+ if (!BLI_edgehash_lookup(eh, e2->v1, e2->v2))
+ return MESHCMP_EDGEUNKNOWN;
+ }
+ BLI_edgehash_free(eh, NULL);
+ }
+
+ if (l1->type == CD_MPOLY) {
+ MPoly *p1 = l1->data;
+ MPoly *p2 = l2->data;
+ int ptot = m1->totpoly;
+
+ for (j=0; j<ptot; j++, p1++, p2++) {
+ MLoop *lp1, *lp2;
+ int k;
+
+ if (p1->totloop != p2->totloop)
+ return MESHCMP_POLYMISMATCH;
+
+ lp1 = m1->mloop + p1->loopstart;
+ lp2 = m2->mloop + p2->loopstart;
+
+ for (k=0; k<p1->totloop; k++, lp1++, lp2++) {
+ if (lp1->v != lp2->v)
+ return MESHCMP_POLYVERTMISMATCH;
+ }
+ }
+ }
+ if (l1->type == CD_MLOOP) {
+ MLoop *lp1 = l1->data;
+ MLoop *lp2 = l2->data;
+ int ltot = m1->totloop;
+
+ for (j=0; j<ltot; j++, lp1++, lp2++) {
+ if (lp1->v != lp2->v)
+ return MESHCMP_LOOPMISMATCH;
+ }
+ }
+ if (l1->type == CD_MLOOPUV) {
+ MLoopUV *lp1 = l1->data;
+ MLoopUV *lp2 = l2->data;
+ int ltot = m1->totloop;
+
+ for (j=0; j<ltot; j++, lp1++, lp2++) {
+ if (len_v2v2(lp1->uv, lp2->uv) > thresh)
+ return MESHCMP_LOOPUVMISMATCH;
+ }
+ }
+
+ if (l1->type == CD_MLOOPCOL) {
+ MLoopCol *lp1 = l1->data;
+ MLoopCol *lp2 = l2->data;
+ int ltot = m1->totloop;
+
+ for (j=0; j<ltot; j++, lp1++, lp2++) {
+ if (ABS(lp1->r - lp2->r) > thresh ||
+ ABS(lp1->g - lp2->g) > thresh ||
+ ABS(lp1->b - lp2->b) > thresh ||
+ ABS(lp1->a - lp2->a) > thresh)
+ {
+ return MESHCMP_LOOPCOLMISMATCH;
+ }
+ }
+ }
+
+ if (l1->type == CD_MDEFORMVERT) {
+ MDeformVert *dv1 = l1->data;
+ MDeformVert *dv2 = l2->data;
+ int dvtot = m1->totvert;
+
+ for (j=0; j<dvtot; j++, dv1++, dv2++) {
+ int k;
+ MDeformWeight *dw1 = dv1->dw, *dw2=dv2->dw;
+
+ if (dv1->totweight != dv2->totweight)
+ return MESHCMP_DVERT_TOTGROUPMISMATCH;
+
+ for (k=0; k<dv1->totweight; k++, dw1++, dw2++) {
+ if (dw1->def_nr != dw2->def_nr)
+ return MESHCMP_DVERT_GROUPMISMATCH;
+ if (ABS(dw1->weight - dw2->weight) > thresh)
+ return MESHCMP_DVERT_WEIGHTMISMATCH;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*used for testing. returns an error string the two meshes don't match*/
+const char *mesh_cmp(Mesh *me1, Mesh *me2, float thresh)
+{
+ int c;
+
+ if (!me1 || !me2)
+ return "Requires two input meshes";
+
+ if (me1->totvert != me2->totvert)
+ return "Number of verts don't match";
+
+ if (me1->totedge != me2->totedge)
+ return "Number of edges don't match";
+
+ if (me1->totpoly != me2->totpoly)
+ return "Number of faces don't match";
+
+ if (me1->totloop !=me2->totloop)
+ return "Number of loops don't match";
+
+ if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1, me2, thresh)))
+ return cmpcode_to_str(c);
+
+ if ((c = customdata_compare(&me1->edata, &me2->edata, me1, me2, thresh)))
+ return cmpcode_to_str(c);
+
+ if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1, me2, thresh)))
+ return cmpcode_to_str(c);
+
+ if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1, me2, thresh)))
+ return cmpcode_to_str(c);
+
+ return NULL;
}
+static void mesh_ensure_tesselation_customdata(Mesh *me)
+{
+ int tottex, totcol;
+
+ tottex = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ totcol = CustomData_number_of_layers(&me->fdata, CD_MCOL);
+
+ if (tottex != CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY) ||
+ totcol != CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL))
+ {
+ CustomData_free(&me->fdata, me->totface);
+
+ me->mface = NULL;
+ me->mtface = NULL;
+ me->mcol = NULL;
+ me->totface = 0;
+
+ memset(&me->fdata, 0, sizeof(&me->fdata));
+
+ CustomData_from_bmeshpoly(&me->fdata, &me->pdata, &me->ldata, me->totface);
+ printf("Warning! Tesselation uvs or vcol data got out of sync, had to reset!\n");
+ }
+}
+
+/*this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or
+ mloopcol and mcol) have the same relative active/render/clone/mask indices.*/
+static void mesh_update_linked_customdata(Mesh *me)
+{
+ int act;
+
+ if (me->edit_btmesh)
+ BMEdit_UpdateLinkedCustomData(me->edit_btmesh);
+
+ mesh_ensure_tesselation_customdata(me);
+
+ if (CustomData_has_layer(&me->pdata, CD_MTEXPOLY)) {
+ act = CustomData_get_active_layer(&me->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, act);
+ CustomData_set_layer_active(&me->fdata, CD_MTFACE, act);
+
+ act = CustomData_get_render_layer(&me->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_render(&me->ldata, CD_MLOOPUV, act);
+ CustomData_set_layer_render(&me->fdata, CD_MTFACE, act);
+
+ act = CustomData_get_clone_layer(&me->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_clone(&me->ldata, CD_MLOOPUV, act);
+ CustomData_set_layer_clone(&me->fdata, CD_MTFACE, act);
+
+ act = CustomData_get_stencil_layer(&me->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_stencil(&me->ldata, CD_MLOOPUV, act);
+ CustomData_set_layer_stencil(&me->fdata, CD_MTFACE, act);
+ }
+
+ if (CustomData_has_layer(&me->ldata, CD_MLOOPCOL)) {
+ act = CustomData_get_active_layer(&me->ldata, CD_MLOOPCOL);
+ CustomData_set_layer_active(&me->fdata, CD_MCOL, act);
+
+ act = CustomData_get_render_layer(&me->ldata, CD_MLOOPCOL);
+ CustomData_set_layer_render(&me->fdata, CD_MCOL, act);
+
+ act = CustomData_get_clone_layer(&me->ldata, CD_MLOOPCOL);
+ CustomData_set_layer_clone(&me->fdata, CD_MCOL, act);
+
+ act = CustomData_get_stencil_layer(&me->ldata, CD_MLOOPCOL);
+ CustomData_set_layer_stencil(&me->fdata, CD_MCOL, act);
+ }
+}
void mesh_update_customdata_pointers(Mesh *me)
{
+ mesh_update_linked_customdata(me);
+
me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
me->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT);
me->msticky = CustomData_get_layer(&me->vdata, CD_MSTICKY);
@@ -86,6 +385,13 @@ void mesh_update_customdata_pointers(Mesh *me)
me->mface = CustomData_get_layer(&me->fdata, CD_MFACE);
me->mcol = CustomData_get_layer(&me->fdata, CD_MCOL);
me->mtface = CustomData_get_layer(&me->fdata, CD_MTFACE);
+
+ me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY);
+ me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP);
+
+ me->mtpoly = CustomData_get_layer(&me->pdata, CD_MTEXPOLY);
+ me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
+ me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
}
/* Note: unlinking is called when me->id.us is 0, question remains how
@@ -116,9 +422,10 @@ void unlink_mesh(Mesh *me)
/* do not free mesh itself */
-void free_mesh(Mesh *me)
+void free_mesh(Mesh *me, int unlink)
{
- unlink_mesh(me);
+ if (unlink)
+ unlink_mesh(me);
if(me->pv) {
if(me->pv->vert_map) MEM_freeN(me->pv->vert_map);
@@ -134,7 +441,9 @@ void free_mesh(Mesh *me)
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->fdata, me->totface);
-
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
+
if(me->adt) {
BKE_free_animdata(&me->id);
me->adt= NULL;
@@ -144,7 +453,7 @@ void free_mesh(Mesh *me)
if(me->bb) MEM_freeN(me->bb);
if(me->mselect) MEM_freeN(me->mselect);
- if(me->edit_mesh) MEM_freeN(me->edit_mesh);
+ if(me->edit_btmesh) MEM_freeN(me->edit_btmesh);
}
void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount)
@@ -159,7 +468,7 @@ void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount)
for (i=0; i<copycount; i++){
if (src[i].dw){
- dst[i].dw = MEM_callocN (sizeof(MDeformWeight)*src[i].totweight, "copy_deformWeight");
+ dst[i].dw = BLI_cellalloc_calloc (sizeof(MDeformWeight)*src[i].totweight, "copy_deformWeight");
memcpy (dst[i].dw, src[i].dw, sizeof (MDeformWeight)*src[i].totweight);
}
}
@@ -178,7 +487,7 @@ void free_dverts(MDeformVert *dvert, int totvert)
/* Free any special data from the verts */
for (i=0; i<totvert; i++){
- if (dvert[i].dw) MEM_freeN (dvert[i].dw);
+ if (dvert[i].dw) BLI_cellalloc_free (dvert[i].dw);
}
MEM_freeN (dvert);
}
@@ -203,6 +512,7 @@ Mesh *copy_mesh(Mesh *me)
{
Mesh *men;
MTFace *tface;
+ MTexPoly *txface;
int a, i;
men= copy_libblock(me);
@@ -216,6 +526,8 @@ Mesh *copy_mesh(Mesh *me)
CustomData_copy(&me->vdata, &men->vdata, CD_MASK_MESH, CD_DUPLICATE, men->totvert);
CustomData_copy(&me->edata, &men->edata, CD_MASK_MESH, CD_DUPLICATE, men->totedge);
CustomData_copy(&me->fdata, &men->fdata, CD_MASK_MESH, CD_DUPLICATE, men->totface);
+ CustomData_copy(&me->ldata, &men->ldata, CD_MASK_MESH, CD_DUPLICATE, men->totloop);
+ CustomData_copy(&me->pdata, &men->pdata, CD_MASK_MESH, CD_DUPLICATE, men->totpoly);
mesh_update_customdata_pointers(men);
/* ensure indirect linked data becomes lib-extern */
@@ -228,9 +540,19 @@ Mesh *copy_mesh(Mesh *me)
id_lib_extern((ID*)tface->tpage);
}
}
-
+
+ for(i=0; i<me->pdata.totlayer; i++) {
+ if(me->pdata.layers[i].type == CD_MTEXPOLY) {
+ txface= (MTexPoly*)me->pdata.layers[i].data;
+
+ for(a=0; a<me->totpoly; a++, txface++)
+ if(txface->tpage)
+ id_lib_extern((ID*)txface->tpage);
+ }
+ }
+
men->mselect= NULL;
- men->edit_mesh= NULL;
+ men->edit_btmesh= NULL;
men->pv= NULL; /* looks like this is no-longer supported but NULL just incase */
men->bb= MEM_dupallocN(men->bb);
@@ -241,27 +563,71 @@ Mesh *copy_mesh(Mesh *me)
return men;
}
-static void expand_local_mesh(Mesh *me)
+BMesh *BKE_mesh_to_bmesh(Mesh *me, Object *ob)
{
- id_lib_extern((ID *)me->texcomesh);
+ BMesh *bm;
+ int allocsize[4] = {512,512,2048,512};
- if(me->mtface) {
- MTFace *tface;
- int a, i;
+ bm = BM_Make_Mesh(ob, allocsize);
- for(i=0; i<me->fdata.totlayer; i++) {
- if(me->fdata.layers[i].type == CD_MTFACE) {
- tface= (MTFace*)me->fdata.layers[i].data;
+ BMO_CallOpf(bm, "mesh_to_bmesh mesh=%p object=%p set_shapekey=%i", me, ob, 1);
- for(a=0; a<me->totface; a++, tface++) {
- if(tface->tpage) {
- id_lib_extern((ID *)tface->tpage);
+ return bm;
+}
+
+static void make_local_tface(Main *bmain, Mesh *me)
+{
+ MTFace *tface;
+ MTexPoly *txface;
+ Image *ima;
+ int a, i;
+
+ for(i=0; i<me->pdata.totlayer; i++) {
+ if(me->pdata.layers[i].type == CD_MTEXPOLY) {
+ txface= (MTexPoly*)me->fdata.layers[i].data;
+
+ for(a=0; a<me->totpoly; a++, txface++) {
+ /* special case: ima always local immediately */
+ if(txface->tpage) {
+ ima= txface->tpage;
+ if(ima->id.lib) {
+ ima->id.lib= 0;
+ ima->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ima, 0);
}
}
}
}
}
+ for(i=0; i<me->fdata.totlayer; i++) {
+ if(me->fdata.layers[i].type == CD_MTFACE) {
+ tface= (MTFace*)me->fdata.layers[i].data;
+
+ for(a=0; a<me->totface; a++, tface++) {
+ /* special case: ima always local immediately */
+ if(tface->tpage) {
+ ima= tface->tpage;
+ if(ima->id.lib) {
+ ima->id.lib= NULL;
+ ima->id.flag= LIB_LOCAL;
+ new_id(&bmain->image, (ID *)ima, NULL);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void expand_local_mesh(Main *bmain, Mesh *me)
+{
+ id_lib_extern((ID *)me->texcomesh);
+
+ if(me->mtface) {
+ /* why is this an exception? - should not really make local when extern'ing - campbell */
+ make_local_tface(bmain, me);
+ }
+
if(me->mat) {
extern_local_matarar(me->mat, me->totcol);
}
@@ -280,8 +646,11 @@ void make_local_mesh(Mesh *me)
if(me->id.lib==NULL) return;
if(me->id.us==1) {
- id_clear_lib_data(&bmain->mesh, (ID *)me);
- expand_local_mesh(me);
+ me->id.lib= NULL;
+ me->id.flag= LIB_LOCAL;
+
+ new_id(&bmain->mesh, (ID *)me, NULL);
+ expand_local_mesh(bmain, me);
return;
}
@@ -293,8 +662,11 @@ void make_local_mesh(Mesh *me)
}
if(local && lib==0) {
- id_clear_lib_data(&bmain->mesh, (ID *)me);
- expand_local_mesh(me);
+ me->id.lib= NULL;
+ me->id.flag= LIB_LOCAL;
+
+ new_id(&bmain->mesh, (ID *)me, NULL);
+ expand_local_mesh(bmain, me);
}
else if(local && lib) {
Mesh *men= copy_mesh(me);
@@ -576,13 +948,17 @@ static void mfaces_strip_loose(MFace *mface, int *totface)
}
/* Create edges based on known verts and faces */
-static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, int UNUSED(totvert), int totface,
+static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, MLoop *allloop,
+ MPoly *allpoly, int UNUSED(totvert), int totface, int UNUSED(totloop), int totpoly,
int old, MEdge **alledge, int *_totedge)
{
+ MPoly *mpoly;
+ MLoop *mloop;
MFace *mface;
MEdge *medge;
+ EdgeHash *hash = BLI_edgehash_new();
struct edgesort *edsort, *ed;
- int a, totedge=0, final=0;
+ int a, b, totedge=0, final=0;
/* we put all edges in array, sort them, and detect doubles that way */
@@ -654,6 +1030,26 @@ static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, int UNUSED(
medge->flag |= ME_EDGERENDER;
MEM_freeN(edsort);
+
+ /*set edge members of mloops*/
+ medge= *alledge;
+ for (a=0; a<*_totedge; a++, medge++) {
+ BLI_edgehash_insert(hash, medge->v1, medge->v2, SET_INT_IN_POINTER(a));
+ }
+
+ mpoly = allpoly;
+ for (a=0; a<totpoly; a++, mpoly++) {
+ mloop = allloop + mpoly->loopstart;
+ for (b=0; b<mpoly->totloop; b++) {
+ int v1, v2;
+
+ v1 = mloop[b].v;
+ v2 = mloop[(b+1)%mpoly->totloop].v;
+ mloop[b].e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(hash, v1, v2));
+ }
+ }
+
+ BLI_edgehash_free(hash, NULL);
}
void make_edges(Mesh *me, int old)
@@ -661,7 +1057,7 @@ void make_edges(Mesh *me, int old)
MEdge *medge;
int totedge=0;
- make_edges_mdata(me->mvert, me->mface, me->totvert, me->totface, old, &medge, &totedge);
+ make_edges_mdata(me->mvert, me->mface, me->mloop, me->mpoly, me->totvert, me->totface, me->totloop, me->totpoly, old, &medge, &totedge);
if(totedge==0) {
/* flag that mesh has edges */
me->medge = medge;
@@ -757,31 +1153,37 @@ void mball_to_mesh(ListBase *lb, Mesh *me)
}
make_edges(me, 0); // all edges
- }
+ convert_mfaces_to_mpolys(me);
+ }
}
/* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */
/* return non-zero on error */
int nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert,
- MEdge **alledge, int *totedge, MFace **allface, int *totface)
+ MEdge **alledge, int *totedge, MFace **allface, MLoop **allloop, MPoly **allpoly,
+ int *totface, int *totloop, int *totpoly)
{
return nurbs_to_mdata_customdb(ob, &ob->disp,
- allvert, totvert, alledge, totedge, allface, totface);
+ allvert, totvert, alledge, totedge, allface, allloop, allpoly, totface, totloop, totpoly);
}
/* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */
/* use specified dispbase */
int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int *_totvert,
- MEdge **alledge, int *_totedge, MFace **allface, int *_totface)
+ MEdge **alledge, int *_totedge, MFace **allface, MLoop **allloop, MPoly **allpoly,
+ int *_totface, int *_totloop, int *_totpoly)
{
DispList *dl;
Curve *cu;
MVert *mvert;
MFace *mface;
+ MPoly *mpoly;
+ MLoop *mloop;
float *data;
int a, b, ofs, vertcount, startvert, totvert=0, totvlak=0;
int p1, p2, p3, p4, *index;
int conv_polys= 0;
+ int i, j;
cu= ob->data;
@@ -820,7 +1222,9 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int
*allvert= mvert= MEM_callocN(sizeof (MVert) * totvert, "nurbs_init mvert");
*allface= mface= MEM_callocN(sizeof (MFace) * totvlak, "nurbs_init mface");
-
+ *allloop = mloop = MEM_callocN(sizeof(MLoop) * totvlak * 4, "nurbs_init mloop");
+ *allpoly = mpoly = MEM_callocN(sizeof(MPoly) * totvlak * 4, "nurbs_init mloop");
+
/* verts and faces */
vertcount= 0;
@@ -958,11 +1362,35 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int
dl= dl->next;
}
-
+
+ mface= *allface;
+ j = 0;
+ for (i=0; i<totvert; i++, mpoly++, mface++) {
+ int k;
+
+ if (!mface->v3) {
+ mpoly--;
+ i--;
+ continue;
+ }
+
+ if (mface >= *allface + totvlak)
+ break;
+
+ mpoly->flag |= mface->flag & ME_SMOOTH;
+ mpoly->loopstart= j;
+ mpoly->totloop= mface->v4 ? 4 : 3;
+ for (k=0; k<mpoly->totloop; k++, mloop++, j++) {
+ mloop->v = (&mface->v1)[k];
+ }
+ }
+
+ *_totpoly= i;
+ *_totloop= j;
*_totvert= totvert;
*_totface= totvlak;
- make_edges_mdata(*allvert, *allface, totvert, totvlak, 0, alledge, _totedge);
+ make_edges_mdata(*allvert, *allface, *allloop, *allpoly, totvert, totvlak, *_totloop, *_totpoly, 0, alledge, _totedge);
mfaces_strip_loose(*allface, _totface);
return 0;
@@ -979,12 +1407,14 @@ void nurbs_to_mesh(Object *ob)
MVert *allvert= NULL;
MEdge *alledge= NULL;
MFace *allface= NULL;
- int totvert, totedge, totface;
+ MLoop *allloop = NULL;
+ MPoly *allpoly = NULL;
+ int totvert, totedge, totface, totloop, totpoly;
cu= ob->data;
if (dm == NULL) {
- if (nurbs_to_mdata (ob, &allvert, &totvert, &alledge, &totedge, &allface, &totface) != 0) {
+ if (nurbs_to_mdata (ob, &allvert, &totvert, &alledge, &totedge, &allface, &allloop, &allpoly, &totface, &totloop, &totpoly) != 0) {
/* Error initializing */
return;
}
@@ -994,15 +1424,19 @@ void nurbs_to_mesh(Object *ob)
me->totvert= totvert;
me->totface= totface;
me->totedge= totedge;
+ me->totloop = totloop;
+ me->totpoly = totpoly;
me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, allvert, me->totvert);
- me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, allface, me->totface);
me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, alledge, me->totedge);
+ me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, allface, me->totface);
+ me->mloop= CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, allloop, me->totloop);
+ me->mpoly= CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, allpoly, me->totpoly);
- mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+ mesh_calc_normals(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL, NULL, 0, NULL, NULL);
} else {
me= add_mesh("Mesh");
- DM_to_mesh(dm, me);
+ DM_to_mesh(dm, me, ob);
}
me->totcol= cu->totcol;
@@ -1063,10 +1497,10 @@ void mesh_to_curve(Scene *scene, Object *ob)
MVert *mverts= dm->getVertArray(dm);
MEdge *med, *medge= dm->getEdgeArray(dm);
- MFace *mf, *mface= dm->getFaceArray(dm);
+ MFace *mf, *mface= dm->getTessFaceArray(dm);
int totedge = dm->getNumEdges(dm);
- int totface = dm->getNumFaces(dm);
+ int totface = dm->getNumTessFaces(dm);
int totedges = 0;
int i, needsFree = 0;
@@ -1229,10 +1663,16 @@ void mesh_to_curve(Scene *scene, Object *ob)
void mesh_delete_material_index(Mesh *me, short index)
{
- MFace *mf;
int i;
- for (i=0, mf=me->mface; i<me->totface; i++, mf++) {
+ for (i=0; i<me->totpoly; i++) {
+ MPoly *mp = &((MPoly*) me->mpoly)[i];
+ if (mp->mat_nr && mp->mat_nr>=index)
+ mp->mat_nr--;
+ }
+
+ for (i=0; i<me->totface; i++) {
+ MFace *mf = &((MFace*) me->mface)[i];
if (mf->mat_nr && mf->mat_nr>=index)
mf->mat_nr--;
}
@@ -1243,6 +1683,16 @@ void mesh_set_smooth_flag(Object *meshOb, int enableSmooth)
Mesh *me = meshOb->data;
int i;
+ for (i=0; i<me->totpoly; i++) {
+ MPoly *mp = &((MPoly*) me->mpoly)[i];
+
+ if (enableSmooth) {
+ mp->flag |= ME_SMOOTH;
+ } else {
+ mp->flag &= ~ME_SMOOTH;
+ }
+ }
+
for (i=0; i<me->totface; i++) {
MFace *mf = &((MFace*) me->mface)[i];
@@ -1253,10 +1703,98 @@ void mesh_set_smooth_flag(Object *meshOb, int enableSmooth)
}
}
- mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+ mesh_calc_normals(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop,
+ me->totpoly, NULL, NULL, 0, NULL, NULL);
}
-void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float (*faceNors_r)[3])
+void mesh_calc_normals(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpolys,
+ int UNUSED(numLoops), int numPolys, float (*polyNors_r)[3], MFace *mfaces, int numFaces,
+ int *origIndexFace, float (*faceNors_r)[3])
+{
+ float (*pnors)[3] = polyNors_r, (*fnors)[3] = faceNors_r;
+ float (*tnorms)[3], (*edgevecbuf)[3];
+ float **vertcos = NULL, **vertnos = NULL;
+ BLI_array_declare(vertcos);
+ BLI_array_declare(vertnos);
+ int i, j, maxPolyVerts = 0;
+ MFace *mf;
+ MPoly *mp;
+ MLoop *ml;
+
+ if (numPolys == 0) {
+ return;
+ }
+
+ mp = mpolys;
+ for (i=0; i<numPolys; i++, mp++) {
+ maxPolyVerts = MAX2(mp->totloop, maxPolyVerts);
+ }
+
+ if (maxPolyVerts == 0) {
+ return;
+ }
+
+ /*first go through and calculate normals for all the polys*/
+ edgevecbuf = MEM_callocN(sizeof(float)*3*maxPolyVerts, "edgevecbuf mesh.c");
+ tnorms = MEM_callocN(sizeof(float)*3*numVerts, "tnorms mesh.c");
+ if (!pnors)
+ pnors = MEM_callocN(sizeof(float)*3*numPolys, "poly_nors mesh.c");
+ if (!fnors)
+ fnors = MEM_callocN(sizeof(float)*3*numFaces, "face nors mesh.c");
+
+ mp = mpolys;
+ for (i=0; i<numPolys; i++, mp++) {
+ mesh_calc_poly_normal(mp, mloop+mp->loopstart, mverts, pnors[i]);
+ ml = mloop + mp->loopstart;
+
+ BLI_array_empty(vertcos);
+ BLI_array_empty(vertnos);
+ for (j=0; j<mp->totloop; j++) {
+ int vindex = ml[j].v;
+ BLI_array_append(vertcos, mverts[vindex].co);
+ BLI_array_append(vertnos, tnorms[vindex]);
+ }
+
+ accumulate_vertex_normals_poly(vertnos, pnors[i], vertcos, edgevecbuf, mp->totloop);
+ }
+
+ /* following Mesh convention; we use vertex coordinate itself for normal in this case */
+ for(i=0; i<numVerts; i++) {
+ MVert *mv= &mverts[i];
+ float *no= tnorms[i];
+
+ if(normalize_v3(no) == 0.0f)
+ normalize_v3_v3(no, mv->co);
+
+ normal_float_to_short_v3(mv->no, no);
+ }
+
+ if (origIndexFace && fnors==faceNors_r && numFaces) {
+ mf = mfaces;
+ for (i=0; i<numFaces; i++, mf++, origIndexFace++) {
+ if (*origIndexFace < numPolys) {
+ VECCOPY(fnors[i], pnors[*origIndexFace]);
+ } else {
+ /*eek, we're not corrusponding to polys*/
+ printf("error in mesh_calc_normals; tesselation face indices are incorrect. normals may look bad.\n");
+ }
+ }
+ }
+
+ BLI_array_free(vertcos);
+ BLI_array_free(vertnos);
+ MEM_freeN(edgevecbuf);
+ MEM_freeN(tnorms);
+ if (fnors != faceNors_r)
+ MEM_freeN(fnors);
+ if (pnors != polyNors_r)
+ MEM_freeN(pnors);
+
+ fnors = pnors = NULL;
+
+}
+
+void mesh_calc_tessface_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float (*faceNors_r)[3])
{
float (*tnorms)[3]= MEM_callocN(numVerts*sizeof(*tnorms), "tnorms");
float (*fnors)[3]= (faceNors_r)? faceNors_r: MEM_callocN(sizeof(*fnors)*numFaces, "meshnormals");
@@ -1294,6 +1832,157 @@ void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces,
MEM_freeN(fnors);
}
+
+static void bmesh_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, int numCol)
+{
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ MFace *mf;
+ int i;
+
+ mf = me->mface + findex;
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_n(&me->fdata, CD_MTFACE, findex, i);
+ texpoly = CustomData_get_n(&me->pdata, CD_MTEXPOLY, findex, i);
+
+ texpoly->tpage = texface->tpage;
+ texpoly->flag = texface->flag;
+ texpoly->transp = texface->transp;
+ texpoly->mode = texface->mode;
+ texpoly->tile = texface->tile;
+ texpoly->unwrap = texface->unwrap;
+
+ mloopuv = CustomData_get_n(&me->ldata, CD_MLOOPUV, loopstart, i);
+ mloopuv->uv[0] = texface->uv[0][0]; mloopuv->uv[1] = texface->uv[0][1]; mloopuv++;
+ mloopuv->uv[0] = texface->uv[1][0]; mloopuv->uv[1] = texface->uv[1][1]; mloopuv++;
+ mloopuv->uv[0] = texface->uv[2][0]; mloopuv->uv[1] = texface->uv[2][1]; mloopuv++;
+
+ if (mf->v4) {
+ mloopuv->uv[0] = texface->uv[3][0]; mloopuv->uv[1] = texface->uv[3][1]; mloopuv++;
+ }
+ }
+
+ for(i=0; i < numCol; i++){
+ mloopcol = CustomData_get_n(&me->ldata, CD_MLOOPCOL, loopstart, i);
+ mcol = CustomData_get_n(&me->fdata, CD_MCOL, findex, i);
+
+ mloopcol->r = mcol[0].r; mloopcol->g = mcol[0].g; mloopcol->b = mcol[0].b; mloopcol->a = mcol[0].a; mloopcol++;
+ mloopcol->r = mcol[1].r; mloopcol->g = mcol[1].g; mloopcol->b = mcol[1].b; mloopcol->a = mcol[1].a; mloopcol++;
+ mloopcol->r = mcol[2].r; mloopcol->g = mcol[2].g; mloopcol->b = mcol[2].b; mloopcol->a = mcol[2].a; mloopcol++;
+ if (mf->v4) {
+ mloopcol->r = mcol[3].r; mloopcol->g = mcol[3].g; mloopcol->b = mcol[3].b; mloopcol->a = mcol[3].a; mloopcol++;
+ }
+ }
+
+ if (CustomData_has_layer(&me->fdata, CD_MDISPS)) {
+ MDisps *ld = CustomData_get(&me->ldata, loopstart, CD_MDISPS);
+ MDisps *fd = CustomData_get(&me->fdata, findex, CD_MDISPS);
+ float (*disps)[3] = fd->disps;
+ int i, tot = mf->v4 ? 4 : 3;
+ int side, corners;
+
+ corners = multires_mdisp_corners(fd);
+
+ if (corners == 0) {
+ /* Empty MDisp layers appear in at least one of the sintel.blend files.
+ Not sure why this happens, but it seems fine to just ignore them here.
+ If corners==0 for a non-empty layer though, something went wrong. */
+ BLI_assert(fd->totdisp == 0);
+ }
+ else {
+ side = sqrt(fd->totdisp / corners);
+
+ for (i=0; i<tot; i++, disps += side*side, ld++) {
+ ld->totdisp = side*side;
+
+ if (ld->disps)
+ BLI_cellalloc_free(ld->disps);
+
+ ld->disps = BLI_cellalloc_calloc(sizeof(float)*3*side*side, "converted loop mdisps");
+ if (fd->disps) {
+ memcpy(ld->disps, disps, sizeof(float)*3*side*side);
+ }
+ }
+ }
+ }
+}
+
+void convert_mfaces_to_mpolys(Mesh *mesh)
+{
+ MFace *mf;
+ MLoop *ml;
+ MPoly *mp;
+ MEdge *me;
+ EdgeHash *eh;
+ int numTex, numCol;
+ int i, j, totloop;
+
+ mesh->totpoly = mesh->totface;
+ mesh->mpoly = MEM_callocN(sizeof(MPoly)*mesh->totpoly, "mpoly converted");
+ CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_ASSIGN, mesh->mpoly, mesh->totpoly);
+
+ numTex = CustomData_number_of_layers(&mesh->fdata, CD_MTFACE);
+ numCol = CustomData_number_of_layers(&mesh->fdata, CD_MCOL);
+
+ totloop = 0;
+ mf = mesh->mface;
+ for (i=0; i<mesh->totface; i++, mf++) {
+ totloop += mf->v4 ? 4 : 3;
+ }
+
+ mesh->totloop = totloop;
+ mesh->mloop = MEM_callocN(sizeof(MLoop)*mesh->totloop, "mloop converted");
+
+ CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_ASSIGN, mesh->mloop, totloop);
+ CustomData_to_bmeshpoly(&mesh->fdata, &mesh->pdata, &mesh->ldata,
+ mesh->totloop, mesh->totpoly);
+
+ eh = BLI_edgehash_new();
+
+ /*build edge hash*/
+ me = mesh->medge;
+ for (i=0; i<mesh->totedge; i++, me++) {
+ BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i));
+ }
+
+ j = 0; /*current loop index*/
+ ml = mesh->mloop;
+ mf = mesh->mface;
+ mp = mesh->mpoly;
+ for (i=0; i<mesh->totface; i++, mf++, mp++) {
+ mp->loopstart = j;
+
+ mp->totloop = mf->v4 ? 4 : 3;
+
+ mp->mat_nr = mf->mat_nr;
+ mp->flag = mf->flag;
+
+ #define ML(v1, v2) {ml->v = mf->v1; ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2)); ml++; j++;}
+
+ ML(v1, v2);
+ ML(v2, v3);
+ if (mf->v4) {
+ ML(v3, v4);
+ ML(v4, v1);
+ } else {
+ ML(v3, v1);
+ }
+
+ #undef ML
+
+ bmesh_corners_to_loops(mesh, i, mp->loopstart, numTex, numCol);
+ }
+
+ /* note, we dont convert FGons at all, these are not even real ngons,
+ * they have their own UV's, colors etc - its more an editing feature. */
+
+ BLI_edgehash_free(eh, NULL);
+}
+
float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3]
{
int i, numVerts = me->totvert;
@@ -1523,6 +2212,288 @@ void mesh_pmv_off(Mesh *me)
}
}
+void mesh_loops_to_tri_corners(CustomData *fdata, CustomData *ldata,
+ CustomData *pdata, int lindex[3], int findex,
+ int polyindex)
+{
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ int i, j, hasWCol = CustomData_has_layer(ldata, CD_WEIGHT_MLOOPCOL);
+ int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+ int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
+ texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i);
+
+ texface->tpage = texpoly->tpage;
+ texface->flag = texpoly->flag;
+ texface->transp = texpoly->transp;
+ texface->mode = texpoly->mode;
+ texface->tile = texpoly->tile;
+ texface->unwrap = texpoly->unwrap;
+
+ for (j=0; j<3; j++) {
+ mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, lindex[j], i);
+ texface->uv[j][0] = mloopuv->uv[0];
+ texface->uv[j][1] = mloopuv->uv[1];
+ }
+ }
+
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_get_n(fdata, CD_MCOL, findex, i);
+
+ for (j=0; j<3; j++) {
+ mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, lindex[j], i);
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ }
+ }
+
+ if (hasWCol) {
+ mcol = CustomData_get(fdata, findex, CD_WEIGHT_MCOL);
+
+ for (j=0; j<3; j++) {
+ mloopcol = CustomData_get(ldata, lindex[j], CD_WEIGHT_MLOOPCOL);
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ }
+ }
+}
+
+/*
+ this function recreates a tesselation.
+ returns number of tesselation faces.
+
+ use_poly_origindex sets whether or not the tesselation faces' origindex
+ layer should point to original poly indices or real poly indices.
+
+ use_face_origindex sets the tesselation faces' origindex layer
+ to point to the tesselation faces themselves, not the polys.
+
+ if both of the above are 0, it'll use the indices of the mpolys of the MPoly
+ data in pdata, and ignore the origindex layer altogether.
+ */
+int mesh_recalcTesselation(CustomData *fdata,
+ CustomData *ldata, CustomData *pdata,
+ MVert *mvert, int totface, int UNUSED(totloop),
+ int totpoly, int use_poly_origindex,
+ int use_face_origindex)
+{
+ MPoly *mp, *mpoly;
+ MLoop *ml, *mloop;
+ MFace *mf = NULL, *mface;
+ BLI_array_declare(mf);
+ EditVert *v, *lastv, *firstv;
+ EditFace *f;
+ BLI_array_declare(origIndex);
+ int i, j, k, lindex[4], *origIndex = NULL, *polyorigIndex;
+ int numTex, numCol;
+
+ mpoly = CustomData_get_layer(pdata, CD_MPOLY);
+ mloop = CustomData_get_layer(ldata, CD_MLOOP);
+
+ numTex = CustomData_number_of_layers(ldata, CD_MLOOPUV);
+ numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+
+ k = 0;
+ mp = mpoly;
+ polyorigIndex = use_poly_origindex? CustomData_get_layer(pdata, CD_ORIGINDEX) : NULL;
+ for (i=0; i<totpoly; i++, mp++) {
+ if (mp->totloop > 2) {
+ ml = mloop + mp->loopstart;
+
+ BLI_begin_edgefill();
+ firstv = NULL;
+ lastv = NULL;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ v = BLI_addfillvert(mvert[ml->v].co);
+ if (polyorigIndex && use_poly_origindex)
+ v->hash = polyorigIndex[i];
+ else
+ v->hash = i;
+
+ v->keyindex = mp->loopstart + j;
+
+ if (lastv)
+ BLI_addfilledge(lastv, v);
+
+ if (!firstv)
+ firstv = v;
+ lastv = v;
+ }
+ BLI_addfilledge(lastv, firstv);
+
+ BLI_edgefill(2);
+ for (f=fillfacebase.first; f; f=f->next) {
+ BLI_array_growone(mf);
+ BLI_array_growone(origIndex);
+
+ /*these are loop indices, they'll be transformed
+ into vert indices later.*/
+ mf[k].v1 = f->v1->keyindex;
+ mf[k].v2 = f->v2->keyindex;
+ mf[k].v3 = f->v3->keyindex;
+
+ /*put poly index in mf->v4*/
+ mf[k].v4 = f->v1->hash;
+
+ mf[k].mat_nr = mp->mat_nr;
+ mf[k].flag = mp->flag;
+ origIndex[k] = use_face_origindex ? k : f->v1->hash;
+
+ k++;
+ }
+
+ BLI_end_edgefill();
+ }
+ }
+
+ CustomData_free(fdata, totface);
+ memset(fdata, 0, sizeof(CustomData));
+ totface = k;
+
+ CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mf, totface);
+ CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, origIndex, totface);
+ CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
+
+ mface = mf;
+ for (i=0; i<totface; i++, mf++) {
+ /*sort loop indices to ensure winding is correct*/
+ if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2);
+ if (mf->v2 > mf->v3) SWAP(int, mf->v2, mf->v3);
+ if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2);
+
+ if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2);
+ if (mf->v2 > mf->v3) SWAP(int, mf->v2, mf->v3);
+ if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2);
+
+ lindex[0] = mf->v1;
+ lindex[1] = mf->v2;
+ lindex[2] = mf->v3;
+
+ /*transform loop indices to vert indices*/
+ mf->v1 = mloop[mf->v1].v;
+ mf->v2 = mloop[mf->v2].v;
+ mf->v3 = mloop[mf->v3].v;
+
+ mesh_loops_to_tri_corners(fdata, ldata, pdata,
+ lindex, i, mf->v4);
+
+ mf->v4 = 0;
+ }
+
+ return totface;
+}
+
+/*
+ * COMPUTE POLY NORMAL
+ *
+ * Computes the normal of a planar
+ * polygon See Graphics Gems for
+ * computing newell normal.
+ *
+*/
+static void mesh_calc_ngon_normal(MPoly *mpoly, MLoop *loopstart,
+ MVert *mvert, float *normal)
+{
+
+ MVert *v1, *v2, *v3;
+ double u[3], v[3], w[3];
+ double n[3] = {0.0, 0.0, 0.0}, l;
+ int i;
+
+ for(i = 0; i < mpoly->totloop; i++){
+ v1 = mvert + loopstart[i].v;
+ v2 = mvert + loopstart[(i+1)%mpoly->totloop].v;
+ v3 = mvert + loopstart[(i+2)%mpoly->totloop].v;
+
+ VECCOPY(u, v1->co);
+ VECCOPY(v, v2->co);
+ VECCOPY(w, v3->co);
+
+ /*this fixes some weird numerical error*/
+ if (i==0) {
+ u[0] += 0.0001f;
+ u[1] += 0.0001f;
+ u[2] += 0.0001f;
+ }
+
+ /* newell's method
+
+ so thats?:
+ (a[1] - b[1]) * (a[2] + b[2]);
+ a[1]*b[2] - b[1]*a[2] - b[1]*b[2] + a[1]*a[2]
+
+ odd. half of that is the cross product. . .what's the
+ other half?
+
+ also could be like a[1]*(b[2] + a[2]) - b[1]*(a[2] - b[2])
+ */
+
+ n[0] += (u[1] - v[1]) * (u[2] + v[2]);
+ n[1] += (u[2] - v[2]) * (u[0] + v[0]);
+ n[2] += (u[0] - v[0]) * (u[1] + v[1]);
+ }
+
+ l = n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+ l = sqrt(l);
+
+ if (l == 0.0) {
+ normal[0] = 0.0f;
+ normal[1] = 0.0f;
+ normal[2] = 1.0f;
+
+ return;
+ } else l = 1.0f / l;
+
+ n[0] *= l;
+ n[1] *= l;
+ n[2] *= l;
+
+ normal[0] = (float) n[0];
+ normal[1] = (float) n[1];
+ normal[2] = (float) n[2];
+
+}
+
+void mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart,
+ MVert *mvarray, float *no)
+{
+ if(mpoly->totloop > 4) {
+ mesh_calc_ngon_normal(mpoly, loopstart, mvarray, no);
+ }
+ else if(mpoly->totloop == 3){
+ MVert *v1, *v2, *v3;
+
+ v1 = mvarray + (loopstart++)->v;
+ v2 = mvarray + (loopstart++)->v;
+ v3 = mvarray + loopstart->v;
+ normal_tri_v3( no,v1->co, v2->co, v3->co);
+ }
+ else if(mpoly->totloop == 4){
+ MVert *v1, *v2, *v3, *v4;
+
+ v1 = mvarray + (loopstart++)->v;
+ v2 = mvarray + (loopstart++)->v;
+ v3 = mvarray + (loopstart++)->v;
+ v4 = mvarray + loopstart->v;
+ normal_quad_v3( no,v1->co, v2->co, v3->co, v4->co);
+ }
+ else{ /*horrible, two sided face!*/
+ no[0] = 0.0;
+ no[1] = 0.0;
+ no[2] = 1.0;
+ }
+}
+
/* basic vertex data functions */
int minmax_mesh(Mesh *me, float min[3], float max[3])
{