Fix for mirroring issues in particle mode, where the particles were
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 11 Dec 2007 20:02:21 +0000 (20:02 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 11 Dec 2007 20:02:21 +0000 (20:02 +0000)
not mirrored exactly, though the problem is not completely solved.
The way local frames are computed for particles is still not fully
symmetric, which shows especially on long hairs...

Also made the shift+o subsurf switch work recursively into
dupli-groups, did only the first level before.

source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/particle.c
source/blender/src/editobject.c
source/blender/src/editparticle.c
source/blender/src/meshtools.c

index 556ba19d7d74eabb8e286f139d7819d8984a2bea..be0a04ba563363b8f325c82a49e8812c42f55b5e 100644 (file)
@@ -63,7 +63,7 @@ void make_local_mesh(struct Mesh *me);
 void boundbox_mesh(struct Mesh *me, float *loc, float *size);
 void tex_space_mesh(struct Mesh *me);
 float *get_mesh_orco_verts(struct Object *ob);
-void transform_mesh_orco_verts(struct Mesh *me, float (*orco)[3], int totvert);
+void transform_mesh_orco_verts(struct Mesh *me, float (*orco)[3], int totvert, int invert);
 void test_index_face(struct MFace *mface, struct CustomData *mfdata, int mfindex, int nr);
 struct Mesh *get_mesh(struct Object *ob);
 void set_mesh(struct Object *ob, struct Mesh *me);
index 713f595d09d83750d756aaac861c915d9b8999a5..4cc134476e4010dc3dfab4d94a43b13f28213f5d 100644 (file)
@@ -1861,7 +1861,7 @@ static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
        else
                orco= (float(*)[3])get_mesh_orco_verts(ob);
 
-       transform_mesh_orco_verts(ob->data, orco, totvert);
+       transform_mesh_orco_verts(ob->data, orco, totvert, 0);
 
        if((layerorco = DM_get_vert_data_layer(dm, CD_ORCO))) {
                memcpy(layerorco, orco, sizeof(float)*totvert);
index f57daae811ff09d9cd770b6ff3752025544ea498..79a8afedf3f4855eea5c6bcc7d0f3070ab65b980 100644 (file)
@@ -515,18 +515,28 @@ float *get_mesh_orco_verts(Object *ob)
        return (float*)vcos;
 }
 
-void transform_mesh_orco_verts(Mesh *me, float (*orco)[3], int totvert)
+void transform_mesh_orco_verts(Mesh *me, float (*orco)[3], int totvert, int invert)
 {
        float loc[3], size[3];
        int a;
 
        mesh_get_texspace(me->texcomesh?me->texcomesh:me, loc, NULL, size);
 
-       for(a=0; a<totvert; a++) {
-               float *co = orco[a];
-               co[0] = (co[0]-loc[0])/size[0];
-               co[1] = (co[1]-loc[1])/size[1];
-               co[2] = (co[2]-loc[2])/size[2];
+       if(invert) {
+               for(a=0; a<totvert; a++) {
+                       float *co = orco[a];
+                       co[0] = co[0]*size[0] + loc[0];
+                       co[1] = co[1]*size[1] + loc[1];
+                       co[2] = co[2]*size[2] + loc[2];
+               }
+       }
+       else {
+               for(a=0; a<totvert; a++) {
+                       float *co = orco[a];
+                       co[0] = (co[0]-loc[0])/size[0];
+                       co[1] = (co[1]-loc[1])/size[1];
+                       co[2] = (co[2]-loc[2])/size[2];
+               }
        }
 }
 
index 639a982460062d2d0ce1dc7897e1d28eef68b339..154ca9a57160c83b40f0a09bd74c40e43c722260 100644 (file)
@@ -76,6 +76,7 @@
 #include "BKE_depsgraph.h"
 #include "BKE_bad_level_calls.h"
 #include "BKE_modifier.h"
+#include "BKE_mesh.h"
 
 #include "blendef.h"
 #include "RE_render_ext.h"
@@ -2240,9 +2241,9 @@ static void triatomat(float *v1, float *v2, float *v3, float (*uv)[2], float mat
        Crossf(mat[0], mat[1], mat[2]);
 }
 
-static void psys_face_mat(DerivedMesh *dm, ParticleData *pa, float mat[][4], int orco)
+static void psys_face_mat(Object *ob, DerivedMesh *dm, ParticleData *pa, float mat[][4], int orco)
 {
-       float v1[3], v2[3], v3[3];
+       float v[3][3];
        MFace *mface;
        OrigSpaceFace *osface;
        float (*orcodata)[3];
@@ -2255,24 +2256,28 @@ static void psys_face_mat(DerivedMesh *dm, ParticleData *pa, float mat[][4], int
        osface=dm->getFaceData(dm,i,CD_ORIGSPACE);
        
        if(orco && (orcodata=dm->getVertDataArray(dm, CD_ORCO))) {
-               VECCOPY(v1, orcodata[mface->v1]);
-               VECCOPY(v2, orcodata[mface->v2]);
-               VECCOPY(v3, orcodata[mface->v3]);
+               VECCOPY(v[0], orcodata[mface->v1]);
+               VECCOPY(v[1], orcodata[mface->v2]);
+               VECCOPY(v[2], orcodata[mface->v3]);
+
+               /* ugly hack to use non-transformed orcos, since only those
+                * give symmetric results for mirroring in particle mode */
+               transform_mesh_orco_verts(ob->data, v, 3, 1);
        }
        else {
-               dm->getVertCo(dm,mface->v1,v1);
-               dm->getVertCo(dm,mface->v2,v2);
-               dm->getVertCo(dm,mface->v3,v3);
+               dm->getVertCo(dm,mface->v1,v[0]);
+               dm->getVertCo(dm,mface->v2,v[1]);
+               dm->getVertCo(dm,mface->v3,v[2]);
        }
 
-       triatomat(v1, v2, v3, (osface)? osface->uv: NULL, mat);
+       triatomat(v[0], v[1], v[2], (osface)? osface->uv: NULL, mat);
 }
 
 void psys_mat_hair_to_object(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[][4])
 {
        float vec[3];
 
-       psys_face_mat(dm, pa, hairmat, 0);
+       psys_face_mat(0, dm, pa, hairmat, 0);
        psys_particle_on_dm(ob, dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, 0, 0);
        VECCOPY(hairmat[3],vec);
 }
@@ -2281,8 +2286,11 @@ void psys_mat_hair_to_orco(Object *ob, DerivedMesh *dm, short from, ParticleData
 {
        float vec[3], orco[3];
 
-       psys_face_mat(dm, pa, hairmat, 1);
+       psys_face_mat(ob, dm, pa, hairmat, 1);
        psys_particle_on_dm(ob, dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, orco, 0);
+
+       /* see psys_face_mat for why this function is called */
+       transform_mesh_orco_verts(ob->data, orco, 1, 1);
        VECCOPY(hairmat[3],orco);
 }
 
@@ -2338,7 +2346,7 @@ void psys_vec_rot_to_face(DerivedMesh *dm, ParticleData *pa, float *vec)//to_geo
 {
        float mat[4][4];
 
-       psys_face_mat(dm, pa, mat, 0);
+       psys_face_mat(0, dm, pa, mat, 0);
        Mat4Transp(mat); /* cheap inverse for rotation matrix */
        Mat4Mul3Vecfl(mat, vec);
 }
index 1bf3fe7ea7278bedfe3a0e4ed072b98c2b60521a..193bd0f46c43e8ed766bd61e4e15e7713c1e2b45 100644 (file)
@@ -2822,44 +2822,51 @@ void convertmenu(void)
         * level==-1 then toggle subsurf, else set to level.
      * *set allows to toggle multiple selections
         */
-static void object_flip_subdivison(Object *ob, int *set, int level, int mode)
+static void object_flip_subdivison(Object *ob, int *set, int level, int mode, int ingroup)
 {
        ModifierData *md;
 
-       if(ob->type!=OB_MESH)
-               return;
-       
-       md = modifiers_findByType(ob, eModifierType_Subsurf);
-       
-       if (md) {
-               SubsurfModifierData *smd = (SubsurfModifierData*) md;
-
-               if (level == -1) {
-                       if(*set == -1) 
-                               *set= smd->modifier.mode&(mode);
-                                                                                 
-                       if (*set) {
-                               smd->modifier.mode &= ~(mode);
+       if(ob->type==OB_MESH) {
+               md = modifiers_findByType(ob, eModifierType_Subsurf);
+               
+               if (md) {
+                       SubsurfModifierData *smd = (SubsurfModifierData*) md;
+
+                       if (level == -1) {
+                               if(*set == -1) 
+                                       *set= smd->modifier.mode&(mode);
+                                                                                         
+                               if (*set) {
+                                       smd->modifier.mode &= ~(mode);
+                               } else {
+                                       smd->modifier.mode |= (mode);
+                               }
                        } else {
-                               smd->modifier.mode |= (mode);
+                               smd->levels = level;
                        }
-               } else {
-                       smd->levels = level;
-               }
-       } 
-       else if(*set != 0) {
-               SubsurfModifierData *smd = (SubsurfModifierData*) modifier_new(eModifierType_Subsurf);
+               } 
+               else if(!ingroup && *set != 0) {
+                       SubsurfModifierData *smd = (SubsurfModifierData*) modifier_new(eModifierType_Subsurf);
 
-               BLI_addtail(&ob->modifiers, smd);
+                       BLI_addtail(&ob->modifiers, smd);
 
-               if (level!=-1) {
-                       smd->levels = level;
+                       if (level!=-1) {
+                               smd->levels = level;
+                       }
+                       
+                       if(*set == -1)
+                               *set= 1;
                }
-               
-               if(*set == -1)
-                       *set= 1;
+
+               ob->recalc |= OB_RECALC_DATA;
+       }
+
+       if(ob->dup_group) {
+               GroupObject *go;
+
+               for(go= ob->dup_group->gobject.first; go; go= go->next)
+                       object_flip_subdivison(go->ob, set, level, mode, 1);
        }
-       ob->recalc |= OB_RECALC_DATA;
 }
 
 /* Change subdivision properties of mesh object ob, if
@@ -2877,18 +2884,9 @@ void flip_subdivison(int level)
        else
                mode= eModifierMode_Render|eModifierMode_Realtime;
        
-       for(base= G.scene->base.first; base; base= base->next) {
-               if(((level==-1) && (TESTBASE(base))) || (TESTBASELIB(base))) {
-                       object_flip_subdivison(base->object, &set, level, mode);
-                       
-                       if(base->object->dup_group) {
-                               GroupObject *go;
-                               for(go= base->object->dup_group->gobject.first; go; go= go->next)
-                                       if( modifiers_findByType(go->ob, eModifierType_Subsurf))        /* only when exists */
-                                               object_flip_subdivison(go->ob, &set, level, mode);
-                       }
-               }
-       }
+       for(base= G.scene->base.first; base; base= base->next)
+               if(((level==-1) && (TESTBASE(base))) || (TESTBASELIB(base)))
+                       object_flip_subdivison(base->object, &set, level, mode, 0);
        
        countall();
        allqueue(REDRAWVIEW3D, 0);
index 3611efed995fbe1c77ec4a9c2c0da3013f91b160..411a45d0a538875326123e664fb69be681cb476e 100644 (file)
@@ -56,6 +56,7 @@
 
 #include "BKE_global.h"
 #include "BKE_object.h"
+#include "BKE_mesh.h"
 #include "BKE_modifier.h"
 #include "BKE_particle.h"
 #include "BKE_scene.h"
@@ -560,7 +561,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
        /* lookup particles and set in mirror cache */
        if(!edit->mirror_cache)
                edit->mirror_cache= MEM_callocN(sizeof(int)*totpart, "PE mirror cache");
-
+       
        LOOP_PARTICLES(i,pa) {
                psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat);
                VECCOPY(co, pa->hair[0].co);
@@ -599,11 +600,11 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys
        edit= psys->edit;
        i= pa - psys->particles;
 
+       if(!edit->mirror_cache)
+               PE_update_mirror_cache(ob, psys);
+
        /* find mirrored particle if needed */
        if(!mpa) {
-               if(!edit->mirror_cache)
-                       PE_update_mirror_cache(ob, psys);
-
                mi= edit->mirror_cache[i];
                if(mi == -1)
                        return;
index 6bda8d36158c4fed79c155376c038dbd5e49f6e4..bcf07c9b594b85e514858bb1eb0bf4f35d4a7343 100644 (file)
@@ -725,6 +725,7 @@ static struct {
        MocNode **table;
        float offs[3], div[3];
        float (*orco)[3];
+       float orcoloc[3];
 } MeshOctree = {NULL, {0, 0, 0}, {0, 0, 0}, NULL};
 
 /* mode is 's' start, or 'e' end, or 'u' use */
@@ -767,6 +768,7 @@ long mesh_octree_table(Object *ob, float *co, char mode)
                        int a, totvert;
                        
                        MeshOctree.orco= mesh_getRefKeyCos(me, &totvert);
+                       mesh_get_texspace(me, MeshOctree.orcoloc, NULL, NULL);
                        
                        for(a=0, mvert= me->mvert; a<me->totvert; a++, mvert++) {
                                co= (MeshOctree.orco)? MeshOctree.orco[a]: mvert->co;
@@ -838,7 +840,9 @@ int mesh_get_x_mirror_vert(Object *ob, int index)
        float vec[3];
        
        if(MeshOctree.orco) {
-               vec[0]= -MeshOctree.orco[index][0];
+               float *loc= MeshOctree.orcoloc;
+
+               vec[0]= -(MeshOctree.orco[index][0] + loc[0]) - loc[0];
                vec[1]= MeshOctree.orco[index][1];
                vec[2]= MeshOctree.orco[index][2];
        }
@@ -920,7 +924,6 @@ int *mesh_get_x_mirror_faces(Object *ob)
        MFace mirrormf, *mf, *hashmf, *mface= me->mface;
        GHash *fhash;
        int *mirrorverts, *mirrorfaces;
-       float vec[3];
        int a;
 
        mirrorverts= MEM_callocN(sizeof(int)*me->totvert, "MirrorVerts");
@@ -928,19 +931,8 @@ int *mesh_get_x_mirror_faces(Object *ob)
 
        mesh_octree_table(ob, NULL, 's');
 
-       for(a=0, mv=mvert; a<me->totvert; a++, mv++) {
-               if(MeshOctree.orco) {
-                       vec[0]= -MeshOctree.orco[a][0];
-                       vec[1]= MeshOctree.orco[a][1];
-                       vec[2]= MeshOctree.orco[a][2];
-               }
-               else {
-                       vec[0]= -mv->co[0];
-                       vec[1]= mv->co[1];
-                       vec[2]= mv->co[2];
-               }
-               mirrorverts[a]= mesh_octree_table(ob, vec, 'u');
-       }
+       for(a=0, mv=mvert; a<me->totvert; a++, mv++)
+               mirrorverts[a]= mesh_get_x_mirror_vert(ob, a);
 
        mesh_octree_table(ob, NULL, 'e');