forked from bartvdbraak/blender
Particles
========= - Normalize strand coordinates over the length of the strand, not cut off when with e.g. length texture control. - Weight paint and particle mode x-mirror now works with deformation and shape keys active. - X-ray is now disabled in particle mode, messed up depth tests.
This commit is contained in:
parent
ff52c8f2d6
commit
51322964f4
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -4706,12 +4706,15 @@ void draw_object(Base *base, int flag)
|
||||
|
||||
/* xray delay? */
|
||||
if((flag & DRAW_PICKING)==0 && (base->flag & OB_FROMDUPLI)==0) {
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* draw keys? */
|
||||
if(base==(G.scene->basact) || (base->flag & (SELECT+BA_WAS_SEL))) {
|
||||
|
@ -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;
|
||||
|
@ -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; a<MOC_NODE_RES; a++) {
|
||||
if((*bt)->index[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; a<me->totvert; 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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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(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;
|
||||
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; a<me->totvert; 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; a<MOC_RES*MOC_RES*MOC_RES; a++, bt++) {
|
||||
for(a=0, bt=MeshOctree.table; a<MOC_RES*MOC_RES*MOC_RES; a++, bt++) {
|
||||
if(*bt) mesh_octree_free_node(bt);
|
||||
}
|
||||
MEM_freeN(basetable);
|
||||
basetable= NULL;
|
||||
MEM_freeN(MeshOctree.table);
|
||||
MeshOctree.table= NULL;
|
||||
}
|
||||
if(MeshOctree.orco) {
|
||||
MEM_freeN(MeshOctree.orco);
|
||||
MeshOctree.orco= NULL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -797,12 +834,20 @@ long mesh_octree_table(Object *ob, float *co, char mode)
|
||||
int mesh_get_x_mirror_vert(Object *ob, int index)
|
||||
{
|
||||
Mesh *me= ob->data;
|
||||
MVert *mvert= me->mvert+index;
|
||||
MVert *mvert;
|
||||
float vec[3];
|
||||
|
||||
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; 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');
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user