fix for duplifaces with quads/ngons, bmesh was using triangulated faces so each quad...
authorCampbell Barton <ideasman42@gmail.com>
Tue, 29 Nov 2011 02:58:38 +0000 (02:58 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 29 Nov 2011 02:58:38 +0000 (02:58 +0000)
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/mesh.c
source/blender/makesrna/intern/rna_mesh.c

index e525ce13ade5dd24c832b0bc75fa0848d04a489b..7c902cbf2ff4aa6aa2e72929f6dedf5c7dcb6faa 100644 (file)
@@ -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);
index 33df6132c1328674576f8527264343b14ed836ed..4ebdd40a8fda6beef08209cd06158307d5fd54b6 100644 (file)
@@ -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);
        }
 
index 67fb6775a556e9a0c2da0c7daa5341578ca5fb58..f1dd519a3268645e6ca51209ffd264c2997cc55f 100644 (file)
@@ -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])
 {
index d25a2e0cc61449f36dc9e6daa0a5c7bc5a2171df..d08e3f7162562da4c26ec3df702f1748f24a4cda 100644 (file)
@@ -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)