diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 649a711a2e2..c45989a6b5b 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -265,6 +265,7 @@ void psys_vec_rot_to_face(struct DerivedMesh *dm, struct ParticleData *pa, float //void psys_vec_rot_from_face(struct DerivedMesh *dm, struct ParticleData *pa, float *vec); void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); +void psys_mat_hair_to_orco(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); float *psys_cache_vgroup(struct DerivedMesh *dm, struct ParticleSystem *psys, int vgroup); void psys_get_texture(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct ParticleSystem *psys, struct ParticleData *pa, struct ParticleTexture *ptex, int event); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 5af88633bad..a086e7b9a0b 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2482,7 +2482,7 @@ static void mesh_build_data(Object *ob, CustomDataMask dataMask) ob->derivedFinal->getMinMax(ob->derivedFinal, min, max); if(!ob->bb) - ob->bb= MEM_mallocN(sizeof(BoundBox), "bb"); + ob->bb= MEM_callocN(sizeof(BoundBox), "bb"); boundbox_set_from_min_max(ob->bb, min, max); ob->derivedFinal->needsFree = 0; @@ -2520,7 +2520,7 @@ static void editmesh_build_data(CustomDataMask dataMask) em->derivedFinal->getMinMax(em->derivedFinal, min, max); if(!G.obedit->bb) - G.obedit->bb= MEM_mallocN(sizeof(BoundBox), "bb"); + G.obedit->bb= MEM_callocN(sizeof(BoundBox), "bb"); boundbox_set_from_min_max(G.obedit->bb, min, max); em->derivedFinal->needsFree = 0; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 034d61e2bc6..c812c794682 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2240,33 +2240,52 @@ 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]) +static void psys_face_mat(DerivedMesh *dm, ParticleData *pa, float mat[][4], int orco) { float v1[3], v2[3], v3[3]; MFace *mface; OrigSpaceFace *osface; + float (*orcodata)[3]; int i = pa->num_dmcache==DMCACHE_NOTFOUND ? pa->num : pa->num_dmcache; if (i==-1 || i >= dm->getNumFaces(dm)) { Mat4One(mat); return; } + mface=dm->getFaceData(dm,i,CD_MFACE); osface=dm->getFaceData(dm,i,CD_ORIGSPACE); - dm->getVertCo(dm,mface->v1,v1); - dm->getVertCo(dm,mface->v2,v2); - dm->getVertCo(dm,mface->v3,v3); + if(orco && (orcodata=dm->getVertDataArray(dm, CD_ORCO))) { + VECCOPY(v1, orcodata[mface->v1]); + VECCOPY(v2, orcodata[mface->v2]); + VECCOPY(v3, orcodata[mface->v3]); + } + else { + dm->getVertCo(dm,mface->v1,v1); + dm->getVertCo(dm,mface->v2,v2); + dm->getVertCo(dm,mface->v3,v3); + } triatomat(v1, v2, v3, (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); + psys_face_mat(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); } +void psys_mat_hair_to_orco(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[][4]) +{ + float vec[3], orco[3]; + + psys_face_mat(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); + VECCOPY(hairmat[3],orco); +} + /* void psys_key_to_geometry(DerivedMesh *dm, ParticleData *pa, ParticleKey *key) { @@ -2319,7 +2338,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); + psys_face_mat(dm, pa, mat, 0); Mat4Transp(mat); /* cheap inverse for rotation matrix */ Mat4Mul3Vecfl(mat, vec); } diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 127f2d427d5..9280b457a4c 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1734,7 +1734,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps StrandRen *strand=0; RNG *rng= 0; float loc[3],loc1[3],loc0[3],vel[3],mat[4][4],nmat[3][3],co[3],nor[3],time; - float *orco=0,*surfnor=0,*uvco=0; + float *orco=0,*surfnor=0,*uvco=0, strandlen=0.0f, curlen=0.0f; float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0); float loc_tex[3], size_tex[3], adapt_angle=0.0, adapt_pix=0.0, random; int i, a, k, max_k=0, totpart, totvlako, totverto, totuv=0, override_uv=-1; @@ -2043,6 +2043,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps orco[2] = (orco[2]-loc_tex[2])/size_tex[2]; } + /* surface normal shading setup */ if(ma->mode_l & MA_STR_SURFDIFF) { Mat3MulVecfl(nmat, nor); surfnor= nor; @@ -2050,7 +2051,8 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps else surfnor= NULL; - if(strandbuf) { /* strand render */ + /* strand render setup */ + if(strandbuf) { strand= RE_findOrAddStrand(re, re->totstrand++); strand->buffer= strandbuf; strand->vert= svert; @@ -2073,9 +2075,17 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps } } + /* strandco computation setup */ + if(path_nbr) { + strandlen= 0.0f; + curlen= 0.0f; + for(k=1; k<=path_nbr; k++) + if(k<=max_k) + strandlen += VecLenf((cache+k-1)->co, (cache+k)->co); + } + for(k=0; k<=path_nbr; k++){ if(path_nbr){ - time=(float)k/(float)path_nbr; if(k<=max_k){ //bti->convert_bake_key(bsys,cache+k,0,(void*)&state); //copy_particle_key(&state,cache+k,0); @@ -2084,6 +2094,10 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps } else continue; + + if(k > 0) + curlen += VecLenf((cache+k-1)->co, (cache+k)->co); + time= curlen/strandlen; } else{ time=0.0f; diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 87306e9fbb5..1d490637222 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -548,11 +548,11 @@ float *RE_strandren_get_uv(Render *re, StrandRen *strand, int n, char **name, in float **uv= node->uv; int size= (n+1)*256; - node->uv= MEM_callocN(size*sizeof(MCol*), "Strand uv"); + node->uv= MEM_callocN(size*sizeof(float*), "Strand uv"); if(uv) { size= node->totuv*256; - memcpy(node->uv, uv, size*sizeof(MCol*)); + memcpy(node->uv, uv, size*sizeof(float*)); MEM_freeN(uv); } diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index a73c4e71a3d..c77a74abe97 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -4706,10 +4706,13 @@ void draw_object(Base *base, int flag) /* xray delay? */ if((flag & DRAW_PICKING)==0 && (base->flag & OB_FROMDUPLI)==0) { - /* xray and transp are set when it is drawing the 2nd/3rd pass */ - if(!G.vd->xray && !G.vd->transp && (ob->dtx & OB_DRAWXRAY)) { - add_view3d_after(G.vd, base, V3D_XRAY); - return; + /* don't do xray in particle mode, need the z-buffer */ + if(!(G.f & G_PARTICLEEDIT)) { + /* xray and transp are set when it is drawing the 2nd/3rd pass */ + if(!G.vd->xray && !G.vd->transp && (ob->dtx & OB_DRAWXRAY)) { + add_view3d_after(G.vd, base, V3D_XRAY); + return; + } } } diff --git a/source/blender/src/editparticle.c b/source/blender/src/editparticle.c index fc839f7e80b..bb88e9624bf 100644 --- a/source/blender/src/editparticle.c +++ b/source/blender/src/editparticle.c @@ -546,7 +546,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) /* insert particles into kd tree */ LOOP_PARTICLES(i,pa) { - psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, mat); + psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat); VECCOPY(co, pa->hair[0].co); Mat4MulVecfl(mat, co); BLI_kdtree_insert(tree, i, co, NULL); @@ -559,7 +559,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) edit->mirror_cache= MEM_callocN(sizeof(int)*totpart, "PE mirror cache"); LOOP_PARTICLES(i,pa) { - psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, mat); + psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat); VECCOPY(co, pa->hair[0].co); Mat4MulVecfl(mat, co); co[0]= -co[0]; @@ -628,8 +628,8 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys } /* mirror positions and tags */ - psys_mat_hair_to_object(ob, dm, psys->part->from, pa, mat); - psys_mat_hair_to_object(ob, dm, psys->part->from, mpa, mmat); + psys_mat_hair_to_orco(ob, dm, psys->part->from, pa, mat); + psys_mat_hair_to_orco(ob, dm, psys->part->from, mpa, mmat); Mat4Invert(immat, mmat); hkey=pa->hair; diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c index 6dc01217b82..6bda8d36158 100644 --- a/source/blender/src/meshtools.c +++ b/source/blender/src/meshtools.c @@ -686,7 +686,7 @@ static void mesh_octree_add_nodes(MocNode **basetable, float *co, float *offs, f } -static long mesh_octree_find_index(MocNode **bt, MVert *mvert, float *co) +static long mesh_octree_find_index(MocNode **bt, float (*orco)[3], MVert *mvert, float *co) { float *vec; int a; @@ -697,7 +697,12 @@ static long mesh_octree_find_index(MocNode **bt, MVert *mvert, float *co) for(a=0; aindex[a]) { /* does mesh verts and editmode, code looks potential dangerous, octree should really be filled OK! */ - if(mvert) { + if(orco) { + vec= orco[(*bt)->index[a]-1]; + if(FloatCompare(vec, co, MOC_THRESH)) + return (*bt)->index[a]-1; + } + else if(mvert) { vec= (mvert+(*bt)->index[a]-1)->co; if(FloatCompare(vec, co, MOC_THRESH)) return (*bt)->index[a]-1; @@ -711,84 +716,116 @@ static long mesh_octree_find_index(MocNode **bt, MVert *mvert, float *co) else return -1; } if( (*bt)->next) - return mesh_octree_find_index(&(*bt)->next, mvert, co); + return mesh_octree_find_index(&(*bt)->next, orco, mvert, co); return -1; } +static struct { + MocNode **table; + float offs[3], div[3]; + float (*orco)[3]; +} MeshOctree = {NULL, {0, 0, 0}, {0, 0, 0}, NULL}; /* mode is 's' start, or 'e' end, or 'u' use */ /* if end, ob can be NULL */ long mesh_octree_table(Object *ob, float *co, char mode) { MocNode **bt; - static MocNode **basetable= NULL; - static float offs[3], div[3]; if(mode=='u') { /* use table */ - if(basetable==NULL) + if(MeshOctree.table==NULL) mesh_octree_table(ob, NULL, 's'); - if(basetable) { + if(MeshOctree.table) { Mesh *me= ob->data; - bt= basetable + mesh_octree_get_base_offs(co, offs, div); + bt= MeshOctree.table + mesh_octree_get_base_offs(co, MeshOctree.offs, MeshOctree.div); if(ob==G.obedit) - return mesh_octree_find_index(bt, NULL, co); + return mesh_octree_find_index(bt, NULL, NULL, co); else - return mesh_octree_find_index(bt, me->mvert, co); + return mesh_octree_find_index(bt, MeshOctree.orco, me->mvert, co); } return -1; } else if(mode=='s') { /* start table */ Mesh *me= ob->data; - BoundBox *bb = mesh_get_bb(ob); + float min[3], max[3]; + + /* we compute own bounding box and don't reuse ob->bb because + * we are using the undeformed coordinates*/ + INIT_MINMAX(min, max); + + if(ob==G.obedit) { + EditVert *eve; + + for(eve= G.editMesh->verts.first; eve; eve= eve->next) + DO_MINMAX(eve->co, min, max) + } + else { + MVert *mvert; + float *co; + int a, totvert; + + MeshOctree.orco= mesh_getRefKeyCos(me, &totvert); + + for(a=0, mvert= me->mvert; atotvert; a++, mvert++) { + co= (MeshOctree.orco)? MeshOctree.orco[a]: mvert->co; + DO_MINMAX(co, min, max); + } + } /* for quick unit coordinate calculus */ - VECCOPY(offs, bb->vec[0]); - offs[0]-= MOC_THRESH; /* we offset it 1 threshold unit extra */ - offs[1]-= MOC_THRESH; - offs[2]-= MOC_THRESH; - - VecSubf(div, bb->vec[6], bb->vec[0]); - div[0]+= 2*MOC_THRESH; /* and divide with 2 threshold unit more extra (try 8x8 unit grid on paint) */ - div[1]+= 2*MOC_THRESH; - div[2]+= 2*MOC_THRESH; + VECCOPY(MeshOctree.offs, min); + MeshOctree.offs[0]-= MOC_THRESH; /* we offset it 1 threshold unit extra */ + MeshOctree.offs[1]-= MOC_THRESH; + MeshOctree.offs[2]-= MOC_THRESH; - VecMulf(div, 1.0f/MOC_RES); - if(div[0]==0.0f) div[0]= 1.0f; - if(div[1]==0.0f) div[1]= 1.0f; - if(div[2]==0.0f) div[2]= 1.0f; + VecSubf(MeshOctree.div, max, min); + MeshOctree.div[0]+= 2*MOC_THRESH; /* and divide with 2 threshold unit more extra (try 8x8 unit grid on paint) */ + MeshOctree.div[1]+= 2*MOC_THRESH; + MeshOctree.div[2]+= 2*MOC_THRESH; + + VecMulf(MeshOctree.div, 1.0f/MOC_RES); + if(MeshOctree.div[0]==0.0f) MeshOctree.div[0]= 1.0f; + if(MeshOctree.div[1]==0.0f) MeshOctree.div[1]= 1.0f; + if(MeshOctree.div[2]==0.0f) MeshOctree.div[2]= 1.0f; - if(basetable) /* happens when entering this call without ending it */ + if(MeshOctree.table) /* happens when entering this call without ending it */ mesh_octree_table(ob, co, 'e'); - basetable= MEM_callocN(MOC_RES*MOC_RES*MOC_RES*sizeof(void *), "sym table"); + MeshOctree.table= MEM_callocN(MOC_RES*MOC_RES*MOC_RES*sizeof(void *), "sym table"); if(ob==G.obedit) { EditVert *eve; for(eve= G.editMesh->verts.first; eve; eve= eve->next) { - mesh_octree_add_nodes(basetable, eve->co, offs, div, (long)(eve)); + mesh_octree_add_nodes(MeshOctree.table, eve->co, MeshOctree.offs, MeshOctree.div, (long)(eve)); } } else { MVert *mvert; - long a; + float *co; + int a; - for(a=1, mvert= me->mvert; a<=me->totvert; a++, mvert++) { - mesh_octree_add_nodes(basetable, mvert->co, offs, div, a); + for(a=0, mvert= me->mvert; atotvert; a++, mvert++) { + co= (MeshOctree.orco)? MeshOctree.orco[a]: mvert->co; + mesh_octree_add_nodes(MeshOctree.table, co, MeshOctree.offs, MeshOctree.div, a+1); } } } else if(mode=='e') { /* end table */ - if(basetable) { + if(MeshOctree.table) { int a; - for(a=0, bt=basetable; adata; - MVert *mvert= me->mvert+index; + MVert *mvert; float vec[3]; - vec[0]= -mvert->co[0]; - vec[1]= mvert->co[1]; - vec[2]= mvert->co[2]; + if(MeshOctree.orco) { + vec[0]= -MeshOctree.orco[index][0]; + vec[1]= MeshOctree.orco[index][1]; + vec[2]= MeshOctree.orco[index][2]; + } + else { + mvert= me->mvert+index; + vec[0]= -mvert->co[0]; + vec[1]= mvert->co[1]; + vec[2]= mvert->co[2]; + } return mesh_octree_table(ob, vec, 'u'); } @@ -884,9 +929,16 @@ int *mesh_get_x_mirror_faces(Object *ob) mesh_octree_table(ob, NULL, 's'); for(a=0, mv=mvert; atotvert; a++, mv++) { - vec[0]= -mv->co[0]; - vec[1]= mv->co[1]; - vec[2]= mv->co[2]; + 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'); }