diff options
author | Campbell Barton <ideasman42@gmail.com> | 2011-11-29 06:58:38 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2011-11-29 06:58:38 +0400 |
commit | 9e39a66c938cd8cc3be8e054fdacf2ab9e8b7aa8 (patch) | |
tree | 5ac81576f22d7d97549412fd63691df95fcdde7f | |
parent | b25f2386d0adfc33d5d7ea3398e10a791a9a6798 (diff) |
fix for duplifaces with quads/ngons, bmesh was using triangulated faces so each quad would result in 2 duplis.
-rw-r--r-- | source/blender/blenkernel/BKE_mesh.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/anim.c | 100 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh.c | 48 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_mesh.c | 24 |
4 files changed, 107 insertions, 68 deletions
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index e525ce13ade..7c902cbf2ff 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -84,6 +84,9 @@ void mesh_calc_poly_normal(struct MPoly *mpoly, struct MLoop *loopstart, void mesh_calc_poly_center(struct MPoly *mpoly, struct MLoop *loopstart, struct MVert *mvarray, float cent[3]); +float mesh_calc_poly_area(struct MPoly *mpoly, struct MLoop *loopstart, + struct MVert *mvarray, float polynormal[3]); + void unlink_mesh(struct Mesh *me); void free_mesh(struct Mesh *me, int unlink); struct Mesh *add_mesh(const char *name); diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 33df6132c13..4ebdd40a8fd 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -1012,11 +1012,12 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa DupliObject *dob; DerivedMesh *dm; Mesh *me= par->data; - MTFace *mtface; - MFace *mface; + MLoopUV *mloopuv; + MPoly *mpoly, *mp; + MLoop *mloop; MVert *mvert; float pmat[4][4], imat[3][3], (*orco)[3] = NULL, w; - int lay, oblay, totface, a; + int lay, oblay, totface, totloop, a; Scene *sce = NULL; Group *group = NULL; GroupObject *go = NULL; @@ -1033,18 +1034,24 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa int totvert; dm= editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); - totface= dm->getNumTessFaces(dm); - mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp"); - dm->copyTessFaceArray(dm, mface); + totface= dm->getNumFaces(dm); + mpoly= MEM_mallocN(sizeof(MPoly)*totface, "mface temp"); + dm->copyPolyArray(dm, mpoly); + + totloop= dm->numLoopData; /* BMESH_TODO, we should have an api function for this! */ + mloop= MEM_mallocN(sizeof(MLoop)*totloop, "mloop temp"); + dm->copyLoopArray(dm, mloop); + totvert= dm->getNumVerts(dm); mvert= MEM_mallocN(sizeof(MVert)*totvert, "mvert temp"); dm->copyVertArray(dm, mvert); } else { dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH); - - totface= dm->getNumTessFaces(dm); - mface= dm->getTessFaceArray(dm); + + totface= dm->getNumFaces(dm); + mpoly= dm->getPolyArray(dm); + mloop= dm->getLoopArray(dm); mvert= dm->getVertArray(dm); } @@ -1052,11 +1059,11 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa orco= (float(*)[3])get_mesh_orco_verts(par); transform_mesh_orco_verts(me, orco, me->totvert, 0); - mtface= me->mtface; + mloopuv= me->mloopuv; } else { orco= NULL; - mtface= NULL; + mloopuv= NULL; } /* having to loop on scene OR group objects is NOT FUN */ @@ -1100,22 +1107,36 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa /* mballs have a different dupli handling */ if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ - for(a=0; a<totface; a++) { - int mv1 = mface[a].v1; - int mv2 = mface[a].v2; - int mv3 = mface[a].v3; - int mv4 = mface[a].v4; - float *v1= mvert[mv1].co; - float *v2= mvert[mv2].co; - float *v3= mvert[mv3].co; - float *v4= (mv4)? mvert[mv4].co: NULL; + for(a=0, mp= mpoly; a<totface; a++, mp++) { + int mv1; + int mv2; + int mv3; + /* int mv4; */ /* UNUSED */ + float *v1; + float *v2; + float *v3; + /* float *v4; */ /* UNUSED */ float cent[3], quat[4], mat[3][3], mat3[3][3], tmat[4][4], obmat[4][4]; + MLoop *loopstart= mloop + mp->loopstart; + + if (mp->totloop < 3) { + /* highly unlikely but to be safe */ + continue; + } + else { + v1= mvert[(mv1= loopstart[0].v)].co; + v2= mvert[(mv2= loopstart[1].v)].co; + v3= mvert[(mv3= loopstart[2].v)].co; + /* + if (mp->totloop > 3) { + v4= mvert[(mv4= loopstart[3].v)].co; + } + */ + } /* translation */ - if(v4) - cent_quad_v3(cent, v1, v2, v3, v4); - else - cent_tri_v3(cent, v1, v2, v3); + mesh_calc_poly_center(mp, loopstart, mvert, cent); + mul_m4_v3(pmat, cent); sub_v3_v3v3(cent, cent, pmat[3]); @@ -1131,7 +1152,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa /* scale */ if(par->transflag & OB_DUPLIFACES_SCALE) { - float size= v4? area_quad_v3(v1, v2, v3, v4): area_tri_v3(v1, v2, v3); + float size= mesh_calc_poly_area(mp, loopstart, mvert, NULL); size= sqrtf(size) * par->dupfacesca; mul_m3_fl(mat, size); } @@ -1144,27 +1165,19 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa dob= new_dupli_object(lb, ob, obmat, par->lay, a, OB_DUPLIFACES, animated); if(G.rendering) { - w= (mv4)? 0.25f: 1.0f/3.0f; + w= 1.0f / (float)mp->totloop; if(orco) { - madd_v3_v3v3fl(dob->orco, dob->orco, orco[mv1], w); - madd_v3_v3v3fl(dob->orco, dob->orco, orco[mv2], w); - madd_v3_v3v3fl(dob->orco, dob->orco, orco[mv3], w); - if(mv4) - madd_v3_v3v3fl(dob->orco, dob->orco, orco[mv4], w); + int j; + for (j = 0; j < mpoly->totloop; j++) { + madd_v3_v3fl(dob->orco, orco[loopstart[j].v], w); + } } - if(mtface) { - dob->uv[0] += w*mtface[a].uv[0][0]; - dob->uv[1] += w*mtface[a].uv[0][1]; - dob->uv[0] += w*mtface[a].uv[1][0]; - dob->uv[1] += w*mtface[a].uv[1][1]; - dob->uv[0] += w*mtface[a].uv[2][0]; - dob->uv[1] += w*mtface[a].uv[2][1]; - - if(mv4) { - dob->uv[0] += w*mtface[a].uv[3][0]; - dob->uv[1] += w*mtface[a].uv[3][1]; + if(mloopuv) { + int j; + for (j = 0; j < mpoly->totloop; j++) { + madd_v2_v2fl(dob->orco, mloopuv[loopstart[j].v].uv, w); } } } @@ -1188,7 +1201,8 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa } if(em) { - MEM_freeN(mface); + MEM_freeN(mpoly); + MEM_freeN(mloop); MEM_freeN(mvert); } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 67fb6775a55..f1dd519a326 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2542,13 +2542,13 @@ void mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart, static void mesh_calc_ngon_center(MPoly *mpoly, MLoop *loopstart, MVert *mvert, float cent[3]) { - const float fac= 1.0f / (float)mpoly->totloop; + const float w= 1.0f / (float)mpoly->totloop; int i; zero_v3(cent); for (i = 0; i < mpoly->totloop; i++) { - madd_v3_v3fl(cent, mvert[(loopstart++)->v].co, fac); + madd_v3_v3fl(cent, mvert[(loopstart++)->v].co, w); } } @@ -2575,6 +2575,50 @@ void mesh_calc_poly_center(MPoly *mpoly, MLoop *loopstart, } } +/* note, passing polynormal is only a speedup so we can skip calculating it */ +float mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, + MVert *mvarray, float polynormal[3]) +{ + if (mpoly->totloop == 3) { + return area_tri_v3(mvarray[loopstart[0].v].co, + mvarray[loopstart[1].v].co, + mvarray[loopstart[2].v].co + ); + } + else if (mpoly->totloop == 4) { + return area_quad_v3(mvarray[loopstart[0].v].co, + mvarray[loopstart[1].v].co, + mvarray[loopstart[2].v].co, + mvarray[loopstart[3].v].co + ); + } + else { + int i; + float area, polynorm_local[3], (*vertexcos)[3] = NULL; + float *no= polynormal ? polynormal : polynorm_local; + BLI_array_staticdeclare(vertexcos, 10); + + BLI_array_growitems(vertexcos, mpoly->totloop); + + /* pack vertex cos into an array for area_poly_v3 */ + for (i = 0; i < mpoly->totloop; i++) { + copy_v3_v3(vertexcos[i], mvarray[(loopstart++)->v].co); + } + + /* need normal for area_poly_v3 as well */ + if (polynormal == NULL) { + mesh_calc_poly_normal(mpoly, loopstart, mvarray, no); + } + + /* finally calculate the area */ + area = area_poly_v3(mpoly->totloop, vertexcos, no); + + BLI_array_free(vertexcos); + + return area; + } +} + /* basic vertex data functions */ int minmax_mesh(Mesh *me, float min[3], float max[3]) { diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index d25a2e0cc61..d08e3f71625 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -220,30 +220,8 @@ static float rna_MeshPolygon_area_get(PointerRNA *ptr) { Mesh *me = (Mesh*)ptr->id.data; MPoly *mp = (MPoly*)ptr->data; - MVert *mv; - MLoop *ml; - int i, j; - float area, polynorm[3], (*vertexcos)[3] = NULL; - BLI_array_staticdeclare(vertexcos, 10); - - BLI_array_growitems(vertexcos, mp->totloop); - - /* pack vertex cos into an array for area_poly_v3 */ - for (i = mp->loopstart, j = 0; j < mp->totloop; i++, j++) { - ml = &me->mloop[i]; - mv = &me->mvert[ml->v]; - copy_v3_v3(vertexcos[j], mv->co); - } - - /* need normal for area_poly_v3 as well */ - rna_MeshPolygon_normal_get(ptr, polynorm); - - /* finally calculate the area */ - area = area_poly_v3(mp->totloop, vertexcos, polynorm); - - BLI_array_free(vertexcos); - return area; + return mesh_calc_poly_area(mp, me->mloop+mp->loopstart, me->mvert, NULL); } static void rna_MeshFace_normal_get(PointerRNA *ptr, float *values) |