Fix for mirroring issues in particle mode, where the particles were
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.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
if(ob->type==OB_MESH) {
|
||||
md = modifiers_findByType(ob, eModifierType_Subsurf);
|
||||
|
||||
md = modifiers_findByType(ob, eModifierType_Subsurf);
|
||||
if (md) {
|
||||
SubsurfModifierData *smd = (SubsurfModifierData*) md;
|
||||
|
||||
if (md) {
|
||||
SubsurfModifierData *smd = (SubsurfModifierData*) md;
|
||||
if (level == -1) {
|
||||
if(*set == -1)
|
||||
*set= smd->modifier.mode&(mode);
|
||||
|
||||
if (level == -1) {
|
||||
if(*set == -1)
|
||||
*set= smd->modifier.mode&(mode);
|
||||
|
||||
if (*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);
|
||||
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
|
||||
@@ -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');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user