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:
authorCampbell Barton <ideasman42@gmail.com>2011-11-29 06:58:38 +0400
committerCampbell Barton <ideasman42@gmail.com>2011-11-29 06:58:38 +0400
commit9e39a66c938cd8cc3be8e054fdacf2ab9e8b7aa8 (patch)
tree5ac81576f22d7d97549412fd63691df95fcdde7f
parentb25f2386d0adfc33d5d7ea3398e10a791a9a6798 (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.h3
-rw-r--r--source/blender/blenkernel/intern/anim.c100
-rw-r--r--source/blender/blenkernel/intern/mesh.c48
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c24
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)