Fix for [#26372] Objects as PS Hair displays and renders differently
* Grid distribution isn't really suited for hair, so this is now disabled. * Setting a jittered distribution with particles/face = 1 now creates particles on the center of faces. * Quite a bit of cleanup of the whole particle distribution code.
This commit is contained in:
parent
3e8c838a99
commit
f89fc824aa
|
@ -242,7 +242,7 @@ void psys_get_particle_on_path(struct ParticleSimulationData *sim, int pa_num, s
|
|||
int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, int always);
|
||||
|
||||
/* for anim.c */
|
||||
void psys_get_dupli_texture(struct Object *ob, struct ParticleSettings *part, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, float *uv, float *orco);
|
||||
void psys_get_dupli_texture(struct ParticleSystem *psys, struct ParticleSettings *part, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, float *uv, float *orco);
|
||||
void psys_get_dupli_path_transform(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ChildParticle *cpa, struct ParticleCacheKey *cache, float mat[][4], float *scale);
|
||||
|
||||
ParticleThread *psys_threads_create(struct ParticleSimulationData *sim);
|
||||
|
|
|
@ -1346,8 +1346,6 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
|
|||
/* for groups, pick the object based on settings */
|
||||
if(part->draw&PART_DRAW_RAND_GR)
|
||||
b= BLI_rand() % totgroup;
|
||||
else if(part->from==PART_FROM_PARTICLE)
|
||||
b= pa_num % totgroup;
|
||||
else
|
||||
b= a % totgroup;
|
||||
|
||||
|
@ -1402,7 +1400,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
|
|||
dob= new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS, animated);
|
||||
copy_m4_m4(dob->omat, obcopylist[b].obmat);
|
||||
if(G.rendering)
|
||||
psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
|
||||
psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1434,7 +1432,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
|
|||
dob= new_dupli_object(lb, ob, mat, ob->lay, counter, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated);
|
||||
copy_m4_m4(dob->omat, oldobmat);
|
||||
if(G.rendering)
|
||||
psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
|
||||
psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2407,7 +2407,7 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
|
|||
steps = (int)pow(2.0, (double)pset->draw_step);
|
||||
}
|
||||
|
||||
if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
|
||||
if(totchild && part->childtype==PART_CHILD_FACES){
|
||||
totparent=(int)(totchild*part->parents*0.3);
|
||||
|
||||
if(G.rendering && part->child_nbr && part->ren_child_nbr)
|
||||
|
@ -2449,16 +2449,14 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
|
|||
psys->lattice = psys_get_lattice(&ctx->sim);
|
||||
|
||||
/* cache all relevant vertex groups if they exist */
|
||||
if(part->from!=PART_FROM_PARTICLE){
|
||||
ctx->vg_length = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_LENGTH);
|
||||
ctx->vg_clump = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_CLUMP);
|
||||
ctx->vg_kink = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_KINK);
|
||||
ctx->vg_rough1 = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGH1);
|
||||
ctx->vg_rough2 = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGH2);
|
||||
ctx->vg_roughe = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGHE);
|
||||
if(psys->part->flag & PART_CHILD_EFFECT)
|
||||
ctx->vg_effector = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_EFFECTOR);
|
||||
}
|
||||
ctx->vg_length = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_LENGTH);
|
||||
ctx->vg_clump = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_CLUMP);
|
||||
ctx->vg_kink = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_KINK);
|
||||
ctx->vg_rough1 = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGH1);
|
||||
ctx->vg_rough2 = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGH2);
|
||||
ctx->vg_roughe = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGHE);
|
||||
if(psys->part->flag & PART_CHILD_EFFECT)
|
||||
ctx->vg_effector = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_EFFECTOR);
|
||||
|
||||
/* set correct ipo timing */
|
||||
#if 0 // XXX old animation system
|
||||
|
@ -2912,8 +2910,8 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
|
|||
if(ma && (psys->part->draw & PART_DRAW_MAT_COL))
|
||||
VECCOPY(col, &ma->r)
|
||||
|
||||
if(psys->part->from!=PART_FROM_PARTICLE && !(psys->flag & PSYS_GLOBAL_HAIR)) {
|
||||
if(!(psys->part->flag & PART_CHILD_EFFECT))
|
||||
if((psys->flag & PSYS_GLOBAL_HAIR)==0) {
|
||||
if((psys->part->flag & PART_CHILD_EFFECT)==0)
|
||||
vg_effector = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_EFFECTOR);
|
||||
|
||||
if(!psys->totchild)
|
||||
|
@ -4042,7 +4040,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
|
|||
if(state->time < 0.0f)
|
||||
t = psys_get_child_time(psys, cpa, -state->time, NULL, NULL);
|
||||
|
||||
if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
|
||||
if(totchild && part->childtype==PART_CHILD_FACES){
|
||||
/* part->parents could still be 0 so we can't test with totparent */
|
||||
between=1;
|
||||
}
|
||||
|
@ -4192,7 +4190,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
|
|||
if(!psys->totchild)
|
||||
return 0;
|
||||
|
||||
if(part->from != PART_FROM_PARTICLE && part->childtype == PART_CHILD_FACES){
|
||||
if(part->childtype == PART_CHILD_FACES){
|
||||
if(!(psys->flag & PSYS_KEYED))
|
||||
return 0;
|
||||
|
||||
|
@ -4314,13 +4312,15 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
|
|||
}
|
||||
}
|
||||
|
||||
void psys_get_dupli_texture(Object *UNUSED(ob), ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float *uv, float *orco)
|
||||
void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float *uv, float *orco)
|
||||
{
|
||||
MFace *mface;
|
||||
MTFace *mtface;
|
||||
float loc[3];
|
||||
int num;
|
||||
|
||||
uv[0] = uv[1] = 0.f;
|
||||
|
||||
if(cpa) {
|
||||
if(part->childtype == PART_CHILD_FACES) {
|
||||
mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
|
||||
|
@ -4329,43 +4329,36 @@ void psys_get_dupli_texture(Object *UNUSED(ob), ParticleSettings *part, Particle
|
|||
mtface += cpa->num;
|
||||
psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv);
|
||||
}
|
||||
else
|
||||
uv[0]= uv[1]= 0.0f;
|
||||
|
||||
psys_particle_on_emitter(psmd,PART_FROM_FACE,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,0,0,0,orco,0);
|
||||
return;
|
||||
}
|
||||
else
|
||||
uv[0]= uv[1]= 0.0f;
|
||||
|
||||
psys_particle_on_emitter(psmd,
|
||||
(part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE,
|
||||
cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,0,0,0,orco,0);
|
||||
}
|
||||
else {
|
||||
if(part->from == PART_FROM_FACE) {
|
||||
mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
|
||||
num= pa->num_dmcache;
|
||||
|
||||
if(num == DMCACHE_NOTFOUND)
|
||||
num= pa->num;
|
||||
|
||||
if (num >= psmd->dm->getNumFaces(psmd->dm)) {
|
||||
/* happens when simplify is enabled
|
||||
* gives invalid coords but would crash otherwise */
|
||||
num= DMCACHE_NOTFOUND;
|
||||
}
|
||||
|
||||
if(mtface && num != DMCACHE_NOTFOUND) {
|
||||
mface= psmd->dm->getFaceData(psmd->dm, num, CD_MFACE);
|
||||
mtface += num;
|
||||
psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
|
||||
}
|
||||
else
|
||||
uv[0]= uv[1]= 0.0f;
|
||||
else {
|
||||
pa = psys->particles + cpa->pa[0];
|
||||
}
|
||||
else
|
||||
uv[0]= uv[1]= 0.0f;
|
||||
|
||||
psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,orco,0);
|
||||
}
|
||||
|
||||
if(part->from == PART_FROM_FACE) {
|
||||
mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
|
||||
num= pa->num_dmcache;
|
||||
|
||||
if(num == DMCACHE_NOTFOUND)
|
||||
num= pa->num;
|
||||
|
||||
if (num >= psmd->dm->getNumFaces(psmd->dm)) {
|
||||
/* happens when simplify is enabled
|
||||
* gives invalid coords but would crash otherwise */
|
||||
num= DMCACHE_NOTFOUND;
|
||||
}
|
||||
|
||||
if(mtface && num != DMCACHE_NOTFOUND) {
|
||||
mface= psmd->dm->getFaceData(psmd->dm, num, CD_MFACE);
|
||||
mtface += num;
|
||||
psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
|
||||
}
|
||||
}
|
||||
|
||||
psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,orco,0);
|
||||
}
|
||||
|
||||
void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale)
|
||||
|
@ -4380,7 +4373,7 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa
|
|||
len= normalize_v3(vec);
|
||||
|
||||
if(psys->part->rotmode) {
|
||||
if(!pa)
|
||||
if(pa == NULL)
|
||||
pa= psys->particles+cpa->pa[0];
|
||||
|
||||
vec_to_quat( q,xvec, ob->trackflag, ob->upflag);
|
||||
|
@ -4391,12 +4384,13 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa
|
|||
mul_m4_m4m4(mat, obrotmat, qmat);
|
||||
}
|
||||
else {
|
||||
if(pa == NULL && psys->part->childflat != PART_CHILD_FACES)
|
||||
pa = psys->particles + cpa->pa[0];
|
||||
|
||||
if(pa)
|
||||
psys_particle_on_emitter(psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0);
|
||||
else
|
||||
psys_particle_on_emitter(psmd,
|
||||
(psys->part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE,
|
||||
cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,nor,0,0,0,0);
|
||||
psys_particle_on_emitter(psmd,PART_FROM_FACE,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,nor,0,0,0,0);
|
||||
|
||||
copy_m3_m4(nmat, ob->imat);
|
||||
transpose_m3(nmat);
|
||||
|
|
|
@ -329,6 +329,10 @@ static void alloc_child_particles(ParticleSystem *psys, int tot)
|
|||
}
|
||||
}
|
||||
|
||||
/************************************************/
|
||||
/* Distribution */
|
||||
/************************************************/
|
||||
|
||||
void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
|
||||
{
|
||||
/* use for building derived mesh mapping info:
|
||||
|
@ -405,7 +409,35 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
|
|||
}
|
||||
}
|
||||
|
||||
static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys)
|
||||
static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, ParticleSystem *psys)
|
||||
{
|
||||
ChildParticle *cpa = psys->child;
|
||||
int i, p;
|
||||
int child_nbr= get_psys_child_number(scene, psys);
|
||||
int totpart= get_psys_tot_child(scene, psys);
|
||||
|
||||
alloc_child_particles(psys, totpart);
|
||||
|
||||
for(i=0; i<child_nbr; i++){
|
||||
for(p=0; p<psys->totpart; p++,cpa++){
|
||||
float length=2.0;
|
||||
cpa->parent=p;
|
||||
|
||||
/* create even spherical distribution inside unit sphere */
|
||||
while(length>=1.0f){
|
||||
cpa->fuv[0]=2.0f*BLI_frand()-1.0f;
|
||||
cpa->fuv[1]=2.0f*BLI_frand()-1.0f;
|
||||
cpa->fuv[2]=2.0f*BLI_frand()-1.0f;
|
||||
length=len_v3(cpa->fuv);
|
||||
}
|
||||
|
||||
cpa->num=-1;
|
||||
}
|
||||
}
|
||||
/* dmcache must be updated for parent particles if children from faces is used */
|
||||
psys_calc_dmcache(ob, finaldm, psys);
|
||||
}
|
||||
static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
|
||||
{
|
||||
ParticleData *pa=NULL;
|
||||
float min[3], max[3], delta[3], d;
|
||||
|
@ -686,7 +718,7 @@ static void psys_uv_to_w(float u, float v, int quad, float *w)
|
|||
}
|
||||
|
||||
/* Find the index in "sum" array before "value" is crossed. */
|
||||
static int binary_search_distribution(float *sum, int n, float value)
|
||||
static int distribute_binary_search(float *sum, int n, float value)
|
||||
{
|
||||
int mid, low=0, high=n;
|
||||
|
||||
|
@ -716,13 +748,11 @@ static int binary_search_distribution(float *sum, int n, float value)
|
|||
|
||||
/* note: this function must be thread safe, for from == PART_FROM_CHILD */
|
||||
#define ONLY_WORKING_WITH_PA_VERTS 0
|
||||
static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p)
|
||||
static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p)
|
||||
{
|
||||
ParticleThreadContext *ctx= thread->ctx;
|
||||
Object *ob= ctx->sim.ob;
|
||||
DerivedMesh *dm= ctx->dm;
|
||||
ParticleData *tpa;
|
||||
/* ParticleSettings *part= ctx->sim.psys->part; */
|
||||
float *v1, *v2, *v3, *v4, nor[3], orco1[3], co1[3], co2[3], nor1[3];
|
||||
float cur_d, min_d, randu, randv;
|
||||
int from= ctx->from;
|
||||
|
@ -760,9 +790,17 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
|
|||
|
||||
switch(distr){
|
||||
case PART_DISTR_JIT:
|
||||
ctx->jitoff[i] = fmod(ctx->jitoff[i],(float)ctx->jitlevel);
|
||||
psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv);
|
||||
ctx->jitoff[i]++;
|
||||
if(ctx->jitlevel == 1) {
|
||||
if(mface->v4)
|
||||
psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
|
||||
else
|
||||
psys_uv_to_w(0.33333f, 0.33333f, mface->v4, pa->fuv);
|
||||
}
|
||||
else {
|
||||
ctx->jitoff[i] = fmod(ctx->jitoff[i],(float)ctx->jitlevel);
|
||||
psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv);
|
||||
ctx->jitoff[i]++;
|
||||
}
|
||||
break;
|
||||
case PART_DISTR_RAND:
|
||||
randu= rng_getFloat(thread->rng);
|
||||
|
@ -828,15 +866,6 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
|
|||
}
|
||||
}
|
||||
}
|
||||
else if(from == PART_FROM_PARTICLE) {
|
||||
tpa=ctx->tpars+ctx->index[p];
|
||||
pa->num=ctx->index[p];
|
||||
pa->fuv[0]=tpa->fuv[0];
|
||||
pa->fuv[1]=tpa->fuv[1];
|
||||
/* abusing foffset a little for timing in near reaction */
|
||||
pa->foffset=ctx->weight[ctx->index[p]];
|
||||
ctx->weight[ctx->index[p]]+=ctx->maxweight;
|
||||
}
|
||||
else if(from == PART_FROM_CHILD) {
|
||||
MFace *mf;
|
||||
|
||||
|
@ -870,7 +899,6 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
|
|||
|
||||
maxd=ptn[maxw-1].dist;
|
||||
mind=ptn[0].dist;
|
||||
/*dd=maxd-mind;*/ /*UNUSED*/
|
||||
|
||||
/* the weights here could be done better */
|
||||
for(w=0; w<maxw; w++){
|
||||
|
@ -906,7 +934,7 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
|
|||
rng_skip(thread->rng, rng_skip_tot);
|
||||
}
|
||||
|
||||
static void *exec_distribution(void *data)
|
||||
static void *distribute_threads_exec_cb(void *data)
|
||||
{
|
||||
ParticleThread *thread= (ParticleThread*)data;
|
||||
ParticleSystem *psys= thread->ctx->sim.psys;
|
||||
|
@ -923,7 +951,7 @@ static void *exec_distribution(void *data)
|
|||
rng_skip(thread->rng, PSYS_RND_DIST_SKIP * thread->ctx->skip[p]);
|
||||
|
||||
if((p+thread->num) % thread->tot == 0)
|
||||
psys_thread_distribute_particle(thread, NULL, cpa, p);
|
||||
distribute_threads_exec(thread, NULL, cpa, p);
|
||||
else /* thread skip */
|
||||
rng_skip(thread->rng, PSYS_RND_DIST_SKIP);
|
||||
}
|
||||
|
@ -932,7 +960,7 @@ static void *exec_distribution(void *data)
|
|||
totpart= psys->totpart;
|
||||
pa= psys->particles + thread->num;
|
||||
for(p=thread->num; p<totpart; p+=thread->tot, pa+=thread->tot)
|
||||
psys_thread_distribute_particle(thread, pa, NULL, p);
|
||||
distribute_threads_exec(thread, pa, NULL, p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -940,7 +968,7 @@ static void *exec_distribution(void *data)
|
|||
|
||||
/* not thread safe, but qsort doesn't take userdata argument */
|
||||
static int *COMPARE_ORIG_INDEX = NULL;
|
||||
static int compare_orig_index(const void *p1, const void *p2)
|
||||
static int distribute_compare_orig_index(const void *p1, const void *p2)
|
||||
{
|
||||
int index1 = COMPARE_ORIG_INDEX[*(const int*)p1];
|
||||
int index2 = COMPARE_ORIG_INDEX[*(const int*)p2];
|
||||
|
@ -961,44 +989,54 @@ static int compare_orig_index(const void *p1, const void *p2)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* creates a distribution of coordinates on a DerivedMesh */
|
||||
/* */
|
||||
/* 1. lets check from what we are emitting */
|
||||
/* 2. now we know that we have something to emit from so */
|
||||
/* let's calculate some weights */
|
||||
/* 2.1 from even distribution */
|
||||
/* 2.2 and from vertex groups */
|
||||
/* 3. next we determine the indexes of emitting thing that */
|
||||
/* the particles will have */
|
||||
/* 4. let's do jitter if we need it */
|
||||
/* 5. now we're ready to set the indexes & distributions to */
|
||||
/* the particles */
|
||||
/* 6. and we're done! */
|
||||
static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from)
|
||||
{
|
||||
if(from == PART_FROM_CHILD) {
|
||||
ChildParticle *cpa;
|
||||
int p, totchild = get_psys_tot_child(scene, psys);
|
||||
|
||||
if(psys->child && totchild) {
|
||||
for(p=0,cpa=psys->child; p<totchild; p++,cpa++){
|
||||
cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]= 0.0;
|
||||
cpa->foffset= 0.0f;
|
||||
cpa->parent=0;
|
||||
cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
|
||||
cpa->num= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
PARTICLE_P;
|
||||
LOOP_PARTICLES {
|
||||
pa->fuv[0]=pa->fuv[1]=pa->fuv[2]= pa->fuv[3]= 0.0;
|
||||
pa->foffset= 0.0f;
|
||||
pa->num= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Creates a distribution of coordinates on a DerivedMesh */
|
||||
/* This is to denote functionality that does not yet work with mesh - only derived mesh */
|
||||
static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from)
|
||||
static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from)
|
||||
{
|
||||
ParticleThreadContext *ctx= threads[0].ctx;
|
||||
Object *ob= ctx->sim.ob;
|
||||
ParticleSystem *psys= ctx->sim.psys;
|
||||
Object *tob;
|
||||
ParticleData *pa=0, *tpars= 0;
|
||||
ParticleSettings *part;
|
||||
ParticleSystem *tpsys;
|
||||
ParticleSeam *seams= 0;
|
||||
ChildParticle *cpa=0;
|
||||
KDTree *tree=0;
|
||||
DerivedMesh *dm= NULL;
|
||||
float *jit= NULL;
|
||||
int i, seed, p=0, totthread= threads[0].tot;
|
||||
int /*no_distr=0,*/ cfrom=0;
|
||||
int tot=0, totpart, *index=0, children=0, totseam=0;
|
||||
//int *vertpart=0;
|
||||
int cfrom=0;
|
||||
int totelem=0, totpart, *particle_element=0, children=0, totseam=0;
|
||||
int jitlevel= 1, distr;
|
||||
float *weight=0,*sum=0,*jitoff=0;
|
||||
float cur, maxweight=0.0, tweight, totweight, co[3], nor[3], orco[3], ornor[3];
|
||||
float *element_weight=NULL,*element_sum=NULL,*jitter_offset=NULL, *vweight=NULL;
|
||||
float cur, maxweight=0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3], ornor[3];
|
||||
|
||||
if(ob==0 || psys==0 || psys->part==0)
|
||||
if(ELEM3(NULL, ob, psys, psys->part))
|
||||
return 0;
|
||||
|
||||
part=psys->part;
|
||||
|
@ -1012,81 +1050,63 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
|
|||
return 0;
|
||||
}
|
||||
|
||||
BLI_srandom(31415926 + psys->seed);
|
||||
|
||||
if(from==PART_FROM_CHILD){
|
||||
distr=PART_DISTR_RAND;
|
||||
BLI_srandom(31415926 + psys->seed + psys->child_seed);
|
||||
|
||||
if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
|
||||
dm= finaldm;
|
||||
children=1;
|
||||
|
||||
tree=BLI_kdtree_new(totpart);
|
||||
|
||||
for(p=0,pa=psys->particles; p<totpart; p++,pa++){
|
||||
psys_particle_on_dm(dm,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,ornor);
|
||||
transform_mesh_orco_verts((Mesh*)ob->data, &orco, 1, 1);
|
||||
BLI_kdtree_insert(tree, p, orco, ornor);
|
||||
}
|
||||
|
||||
BLI_kdtree_balance(tree);
|
||||
|
||||
totpart=get_psys_tot_child(scene, psys);
|
||||
cfrom=from=PART_FROM_FACE;
|
||||
}
|
||||
else{
|
||||
/* no need to figure out distribution */
|
||||
int child_nbr= get_psys_child_number(scene, psys);
|
||||
|
||||
totpart= get_psys_tot_child(scene, psys);
|
||||
alloc_child_particles(psys, totpart);
|
||||
cpa=psys->child;
|
||||
for(i=0; i<child_nbr; i++){
|
||||
for(p=0; p<psys->totpart; p++,cpa++){
|
||||
float length=2.0;
|
||||
cpa->parent=p;
|
||||
|
||||
/* create even spherical distribution inside unit sphere */
|
||||
while(length>=1.0f){
|
||||
cpa->fuv[0]=2.0f*BLI_frand()-1.0f;
|
||||
cpa->fuv[1]=2.0f*BLI_frand()-1.0f;
|
||||
cpa->fuv[2]=2.0f*BLI_frand()-1.0f;
|
||||
length=len_v3(cpa->fuv);
|
||||
}
|
||||
|
||||
cpa->num=-1;
|
||||
}
|
||||
}
|
||||
/* dmcache must be updated for parent particles if children from faces is used */
|
||||
psys_calc_dmcache(ob, finaldm, psys);
|
||||
|
||||
/* First handle special cases */
|
||||
if(from == PART_FROM_CHILD) {
|
||||
/* Simple children */
|
||||
if(part->childtype != PART_CHILD_FACES) {
|
||||
BLI_srandom(31415926 + psys->seed + psys->child_seed);
|
||||
distribute_simple_children(scene, ob, finaldm, psys);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
dm= CDDM_from_mesh((Mesh*)ob->data, ob);
|
||||
|
||||
/* special handling of grid distribution */
|
||||
else {
|
||||
/* Grid distribution */
|
||||
if(part->distr==PART_DISTR_GRID && from != PART_FROM_VERT){
|
||||
distribute_particles_in_grid(dm,psys);
|
||||
BLI_srandom(31415926 + psys->seed);
|
||||
dm= CDDM_from_mesh((Mesh*)ob->data, ob);
|
||||
distribute_grid(dm,psys);
|
||||
dm->release(dm);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create trees and original coordinates if needed */
|
||||
if(from == PART_FROM_CHILD) {
|
||||
distr=PART_DISTR_RAND;
|
||||
BLI_srandom(31415926 + psys->seed + psys->child_seed);
|
||||
dm= finaldm;
|
||||
children=1;
|
||||
|
||||
totpart = get_psys_tot_child(scene, psys);
|
||||
cfrom = from = PART_FROM_FACE;
|
||||
|
||||
tree=BLI_kdtree_new(totpart);
|
||||
|
||||
for(p=0,pa=psys->particles; p<totpart; p++,pa++){
|
||||
psys_particle_on_dm(dm,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,ornor);
|
||||
transform_mesh_orco_verts((Mesh*)ob->data, &orco, 1, 1);
|
||||
BLI_kdtree_insert(tree, p, orco, ornor);
|
||||
}
|
||||
|
||||
BLI_kdtree_balance(tree);
|
||||
}
|
||||
else {
|
||||
distr = part->distr;
|
||||
BLI_srandom(31415926 + psys->seed);
|
||||
|
||||
dm= CDDM_from_mesh((Mesh*)ob->data, ob);
|
||||
|
||||
/* we need orco for consistent distributions */
|
||||
DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob));
|
||||
|
||||
distr=part->distr;
|
||||
|
||||
if(from==PART_FROM_VERT){
|
||||
if(from == PART_FROM_VERT) {
|
||||
MVert *mv= dm->getVertDataArray(dm, CD_MVERT);
|
||||
float (*orcodata)[3]= dm->getVertDataArray(dm, CD_ORCO);
|
||||
int totvert = dm->getNumVerts(dm);
|
||||
|
||||
tree=BLI_kdtree_new(totvert);
|
||||
|
||||
for(p=0; p<totvert; p++){
|
||||
for(p=0; p<totvert; p++) {
|
||||
if(orcodata) {
|
||||
VECCOPY(co,orcodata[p])
|
||||
transform_mesh_orco_verts((Mesh*)ob->data, &co, 1, 1);
|
||||
|
@ -1100,73 +1120,33 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
|
|||
}
|
||||
}
|
||||
|
||||
/* 1. */
|
||||
switch(from){
|
||||
case PART_FROM_VERT:
|
||||
tot = dm->getNumVerts(dm);
|
||||
break;
|
||||
case PART_FROM_VOLUME:
|
||||
case PART_FROM_FACE:
|
||||
tot = dm->getNumFaces(dm);
|
||||
break;
|
||||
case PART_FROM_PARTICLE:
|
||||
if(psys->target_ob)
|
||||
tob=psys->target_ob;
|
||||
else
|
||||
tob=ob;
|
||||
/* Get total number of emission elements and allocate needed arrays */
|
||||
totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumFaces(dm);
|
||||
|
||||
if((tpsys=BLI_findlink(&tob->particlesystem,psys->target_psys-1))){
|
||||
tpars=tpsys->particles;
|
||||
tot=tpsys->totpart;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(totelem == 0){
|
||||
distribute_invalid(scene, psys, children ? PART_FROM_CHILD : 0);
|
||||
|
||||
if(tot==0){
|
||||
/*no_distr=1;*/ /*UNUSED*/
|
||||
if(children){
|
||||
if(G.f & G_DEBUG)
|
||||
fprintf(stderr,"Particle child distribution error: Nothing to emit from!\n");
|
||||
if(psys->child) {
|
||||
for(p=0,cpa=psys->child; p<totpart; p++,cpa++){
|
||||
cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]= 0.0;
|
||||
cpa->foffset= 0.0f;
|
||||
cpa->parent=0;
|
||||
cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
|
||||
cpa->num= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(G.f & G_DEBUG)
|
||||
fprintf(stderr,"Particle distribution error: Nothing to emit from!\n");
|
||||
for(p=0,pa=psys->particles; p<totpart; p++,pa++){
|
||||
pa->fuv[0]=pa->fuv[1]=pa->fuv[2]= pa->fuv[3]= 0.0;
|
||||
pa->foffset= 0.0f;
|
||||
pa->num= -1;
|
||||
}
|
||||
}
|
||||
if(G.f & G_DEBUG)
|
||||
fprintf(stderr,"Particle distribution error: Nothing to emit from!\n");
|
||||
|
||||
if(dm != finaldm) dm->release(dm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 2. */
|
||||
element_weight = MEM_callocN(sizeof(float)*totelem, "particle_distribution_weights");
|
||||
particle_element= MEM_callocN(sizeof(int)*totpart, "particle_distribution_indexes");
|
||||
element_sum = MEM_callocN(sizeof(float)*(totelem+1), "particle_distribution_sum");
|
||||
jitter_offset = MEM_callocN(sizeof(float)*totelem, "particle_distribution_jitoff");
|
||||
|
||||
weight=MEM_callocN(sizeof(float)*tot, "particle_distribution_weights");
|
||||
index=MEM_callocN(sizeof(int)*totpart, "particle_distribution_indexes");
|
||||
sum=MEM_callocN(sizeof(float)*(tot+1), "particle_distribution_sum");
|
||||
jitoff=MEM_callocN(sizeof(float)*tot, "particle_distribution_jitoff");
|
||||
|
||||
/* 2.1 */
|
||||
if((part->flag&PART_EDISTR || children) && ELEM(from,PART_FROM_PARTICLE,PART_FROM_VERT)==0){
|
||||
/* Calculate weights from face areas */
|
||||
if((part->flag&PART_EDISTR || children) && from != PART_FROM_VERT){
|
||||
MVert *v1, *v2, *v3, *v4;
|
||||
float totarea=0.0, co1[3], co2[3], co3[3], co4[3];
|
||||
float totarea=0.f, co1[3], co2[3], co3[3], co4[3];
|
||||
float (*orcodata)[3];
|
||||
|
||||
orcodata= dm->getVertDataArray(dm, CD_ORCO);
|
||||
|
||||
for(i=0; i<tot; i++){
|
||||
for(i=0; i<totelem; i++){
|
||||
MFace *mf=dm->getFaceData(dm,i,CD_MFACE);
|
||||
|
||||
if(orcodata) {
|
||||
|
@ -1176,6 +1156,10 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
|
|||
transform_mesh_orco_verts((Mesh*)ob->data, &co1, 1, 1);
|
||||
transform_mesh_orco_verts((Mesh*)ob->data, &co2, 1, 1);
|
||||
transform_mesh_orco_verts((Mesh*)ob->data, &co3, 1, 1);
|
||||
if(mf->v4) {
|
||||
VECCOPY(co4, orcodata[mf->v4]);
|
||||
transform_mesh_orco_verts((Mesh*)ob->data, &co4, 1, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
v1= (MVert*)dm->getVertData(dm,mf->v1,CD_MVERT);
|
||||
|
@ -1184,156 +1168,133 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
|
|||
VECCOPY(co1, v1->co);
|
||||
VECCOPY(co2, v2->co);
|
||||
VECCOPY(co3, v3->co);
|
||||
}
|
||||
|
||||
if (mf->v4){
|
||||
if(orcodata) {
|
||||
VECCOPY(co4, orcodata[mf->v4]);
|
||||
transform_mesh_orco_verts((Mesh*)ob->data, &co4, 1, 1);
|
||||
}
|
||||
else {
|
||||
if(mf->v4) {
|
||||
v4= (MVert*)dm->getVertData(dm,mf->v4,CD_MVERT);
|
||||
VECCOPY(co4, v4->co);
|
||||
}
|
||||
cur= area_quad_v3(co1, co2, co3, co4);
|
||||
}
|
||||
else
|
||||
cur= area_tri_v3(co1, co2, co3);
|
||||
|
||||
if(cur>maxweight)
|
||||
maxweight=cur;
|
||||
|
||||
weight[i]= cur;
|
||||
totarea+=cur;
|
||||
cur = mf->v4 ? area_quad_v3(co1, co2, co3, co4) : area_tri_v3(co1, co2, co3);
|
||||
|
||||
if(cur > maxweight)
|
||||
maxweight = cur;
|
||||
|
||||
element_weight[i] = cur;
|
||||
totarea += cur;
|
||||
}
|
||||
|
||||
for(i=0; i<tot; i++)
|
||||
weight[i] /= totarea;
|
||||
for(i=0; i<totelem; i++)
|
||||
element_weight[i] /= totarea;
|
||||
|
||||
maxweight /= totarea;
|
||||
}
|
||||
else if(from==PART_FROM_PARTICLE){
|
||||
float val=(float)tot/(float)totpart;
|
||||
for(i=0; i<tot; i++)
|
||||
weight[i]=val;
|
||||
maxweight=val;
|
||||
}
|
||||
else{
|
||||
float min=1.0f/(float)(MIN2(tot,totpart));
|
||||
for(i=0; i<tot; i++)
|
||||
weight[i]=min;
|
||||
float min=1.0f/(float)(MIN2(totelem,totpart));
|
||||
for(i=0; i<totelem; i++)
|
||||
element_weight[i]=min;
|
||||
maxweight=min;
|
||||
}
|
||||
|
||||
/* 2.2 */
|
||||
if(ELEM3(from,PART_FROM_VERT,PART_FROM_FACE,PART_FROM_VOLUME)){
|
||||
float *vweight= psys_cache_vgroup(dm,psys,PSYS_VG_DENSITY);
|
||||
/* Calculate weights from vgroup */
|
||||
vweight = psys_cache_vgroup(dm,psys,PSYS_VG_DENSITY);
|
||||
|
||||
if(vweight){
|
||||
if(from==PART_FROM_VERT) {
|
||||
for(i=0;i<tot; i++)
|
||||
weight[i]*=vweight[i];
|
||||
}
|
||||
else { /* PART_FROM_FACE / PART_FROM_VOLUME */
|
||||
for(i=0;i<tot; i++){
|
||||
MFace *mf=dm->getFaceData(dm,i,CD_MFACE);
|
||||
tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3];
|
||||
|
||||
if(mf->v4) {
|
||||
tweight += vweight[mf->v4];
|
||||
tweight /= 4.0;
|
||||
}
|
||||
else {
|
||||
tweight /= 3.0;
|
||||
}
|
||||
|
||||
weight[i]*=tweight;
|
||||
}
|
||||
}
|
||||
MEM_freeN(vweight);
|
||||
if(vweight){
|
||||
if(from==PART_FROM_VERT) {
|
||||
for(i=0;i<totelem; i++)
|
||||
element_weight[i]*=vweight[i];
|
||||
}
|
||||
else { /* PART_FROM_FACE / PART_FROM_VOLUME */
|
||||
for(i=0;i<totelem; i++){
|
||||
MFace *mf=dm->getFaceData(dm,i,CD_MFACE);
|
||||
tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3];
|
||||
|
||||
if(mf->v4) {
|
||||
tweight += vweight[mf->v4];
|
||||
tweight /= 4.0;
|
||||
}
|
||||
else {
|
||||
tweight /= 3.0;
|
||||
}
|
||||
|
||||
element_weight[i]*=tweight;
|
||||
}
|
||||
}
|
||||
MEM_freeN(vweight);
|
||||
}
|
||||
|
||||
/* 3. */
|
||||
/* Calculate total weight of all elements */
|
||||
totweight= 0.0f;
|
||||
for(i=0;i<tot; i++)
|
||||
totweight += weight[i];
|
||||
for(i=0;i<totelem; i++)
|
||||
totweight += element_weight[i];
|
||||
|
||||
if(totweight > 0.0f)
|
||||
totweight= 1.0f/totweight;
|
||||
inv_totweight = (totweight > 0.f ? 1.f/totweight : 0.f);
|
||||
|
||||
sum[0]= 0.0f;
|
||||
for(i=0;i<tot; i++)
|
||||
sum[i+1]= sum[i]+weight[i]*totweight;
|
||||
/* Calculate cumulative weights */
|
||||
element_sum[0]= 0.0f;
|
||||
for(i=0; i<totelem; i++)
|
||||
element_sum[i+1]= element_sum[i] + element_weight[i] * inv_totweight;
|
||||
|
||||
/* Finally assign elements to particles */
|
||||
if((part->flag&PART_TRAND) || (part->simplify_flag&PART_SIMPLIFY_ENABLE)) {
|
||||
float pos;
|
||||
|
||||
for(p=0; p<totpart; p++) {
|
||||
/* In theory sys[tot] should be 1.0, but due to float errors this is not necessarily always true, so scale pos accordingly. */
|
||||
pos= BLI_frand() * sum[tot];
|
||||
index[p]= binary_search_distribution(sum, tot, pos);
|
||||
index[p]= MIN2(tot-1, index[p]);
|
||||
jitoff[index[p]]= pos;
|
||||
/* In theory element_sum[totelem] should be 1.0, but due to float errors this is not necessarily always true, so scale pos accordingly. */
|
||||
pos= BLI_frand() * element_sum[totelem];
|
||||
particle_element[p]= distribute_binary_search(element_sum, totelem, pos);
|
||||
particle_element[p]= MIN2(totelem-1, particle_element[p]);
|
||||
jitter_offset[particle_element[p]]= pos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
double step, pos;
|
||||
|
||||
step= (totpart <= 1)? 0.5: 1.0/(totpart-1);
|
||||
pos= 1e-16f; /* tiny offset to avoid zero weight face */
|
||||
step= (totpart < 2) ? 0.5 : 1.0/(double)totpart;
|
||||
pos= 1e-16; /* tiny offset to avoid zero weight face */
|
||||
i= 0;
|
||||
|
||||
for(p=0; p<totpart; p++, pos+=step) {
|
||||
while((i < tot) && (pos > sum[i+1]))
|
||||
while((i < totelem) && (pos > element_sum[i+1]))
|
||||
i++;
|
||||
|
||||
index[p]= MIN2(tot-1, i);
|
||||
particle_element[p]= MIN2(totelem-1, i);
|
||||
|
||||
/* avoid zero weight face */
|
||||
if(p == totpart-1 && weight[index[p]] == 0.0f)
|
||||
index[p]= index[p-1];
|
||||
if(p == totpart-1 && element_weight[particle_element[p]] == 0.0f)
|
||||
particle_element[p]= particle_element[p-1];
|
||||
|
||||
jitoff[index[p]]= pos;
|
||||
jitter_offset[particle_element[p]]= pos;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(sum);
|
||||
MEM_freeN(element_sum);
|
||||
|
||||
/* for hair, sort by origindex, allows optimizations in rendering */
|
||||
/* however with virtual parents the children need to be in random order */
|
||||
/* For hair, sort by origindex (allows optimizations in rendering), */
|
||||
/* however with virtual parents the children need to be in random order. */
|
||||
if(part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents!=0.0)) {
|
||||
if(from != PART_FROM_PARTICLE) {
|
||||
COMPARE_ORIG_INDEX = NULL;
|
||||
|
||||
if(from == PART_FROM_VERT) {
|
||||
if(dm->numVertData)
|
||||
COMPARE_ORIG_INDEX= dm->getVertDataArray(dm, CD_ORIGINDEX);
|
||||
}
|
||||
else {
|
||||
if(dm->numFaceData)
|
||||
COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX);
|
||||
}
|
||||
|
||||
if(COMPARE_ORIG_INDEX) {
|
||||
qsort(particle_element, totpart, sizeof(int), distribute_compare_orig_index);
|
||||
COMPARE_ORIG_INDEX = NULL;
|
||||
|
||||
if(from == PART_FROM_VERT) {
|
||||
if(dm->numVertData)
|
||||
COMPARE_ORIG_INDEX= dm->getVertDataArray(dm, CD_ORIGINDEX);
|
||||
}
|
||||
else {
|
||||
if(dm->numFaceData)
|
||||
COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX);
|
||||
}
|
||||
|
||||
if(COMPARE_ORIG_INDEX) {
|
||||
qsort(index, totpart, sizeof(int), compare_orig_index);
|
||||
COMPARE_ORIG_INDEX = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* weights are no longer used except for FROM_PARTICLE, which needs them zeroed for indexing */
|
||||
if(from==PART_FROM_PARTICLE){
|
||||
for(i=0; i<tot; i++)
|
||||
weight[i]=0.0f;
|
||||
}
|
||||
|
||||
/* 4. */
|
||||
/* Create jittering if needed */
|
||||
if(distr==PART_DISTR_JIT && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
|
||||
jitlevel= part->userjit;
|
||||
|
||||
if(jitlevel == 0) {
|
||||
jitlevel= totpart/tot;
|
||||
jitlevel= totpart/totelem;
|
||||
if(part->flag & PART_EDISTR) jitlevel*= 2; /* looks better in general, not very scietific */
|
||||
if(jitlevel<3) jitlevel= 3;
|
||||
}
|
||||
|
@ -1350,16 +1311,16 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
|
|||
BLI_array_randomize(jit, 2*sizeof(float), jitlevel, psys->seed); /* for custom jit or even distribution */
|
||||
}
|
||||
|
||||
/* 5. */
|
||||
/* Setup things for threaded distribution */
|
||||
ctx->tree= tree;
|
||||
ctx->seams= seams;
|
||||
ctx->totseam= totseam;
|
||||
ctx->sim.psys= psys;
|
||||
ctx->index= index;
|
||||
ctx->index= particle_element;
|
||||
ctx->jit= jit;
|
||||
ctx->jitlevel= jitlevel;
|
||||
ctx->jitoff= jitoff;
|
||||
ctx->weight= weight;
|
||||
ctx->jitoff= jitter_offset;
|
||||
ctx->weight= element_weight;
|
||||
ctx->maxweight= maxweight;
|
||||
ctx->from= (children)? PART_FROM_CHILD: from;
|
||||
ctx->cfrom= cfrom;
|
||||
|
@ -1394,14 +1355,14 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
|
|||
|
||||
pthreads= psys_threads_create(sim);
|
||||
|
||||
if(!psys_threads_init_distribution(pthreads, sim->scene, finaldm, from)) {
|
||||
if(!distribute_threads_init_data(pthreads, sim->scene, finaldm, from)) {
|
||||
psys_threads_free(pthreads);
|
||||
return;
|
||||
}
|
||||
|
||||
totthread= pthreads[0].tot;
|
||||
if(totthread > 1) {
|
||||
BLI_init_threads(&threads, exec_distribution, totthread);
|
||||
BLI_init_threads(&threads, distribute_threads_exec_cb, totthread);
|
||||
|
||||
for(i=0; i<totthread; i++)
|
||||
BLI_insert_thread(&threads, &pthreads[i]);
|
||||
|
@ -1409,7 +1370,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
|
|||
BLI_end_threads(&threads);
|
||||
}
|
||||
else
|
||||
exec_distribution(&pthreads[0]);
|
||||
distribute_threads_exec_cb(&pthreads[0]);
|
||||
|
||||
psys_calc_dmcache(sim->ob, finaldm, sim->psys);
|
||||
|
||||
|
@ -1423,17 +1384,11 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
|
|||
/* ready for future use, to emit particles without geometry */
|
||||
static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSED(from))
|
||||
{
|
||||
ParticleSystem *psys = sim->psys;
|
||||
PARTICLE_P;
|
||||
distribute_invalid(sim->scene, sim->psys, 0);
|
||||
|
||||
fprintf(stderr,"Shape emission not yet possible!\n");
|
||||
|
||||
LOOP_PARTICLES {
|
||||
pa->fuv[0]=pa->fuv[1]=pa->fuv[2]=pa->fuv[3]= 0.0;
|
||||
pa->foffset= 0.0f;
|
||||
pa->num= -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void distribute_particles(ParticleSimulationData *sim, int from)
|
||||
{
|
||||
PARTICLE_PSMD;
|
||||
|
@ -1449,16 +1404,9 @@ static void distribute_particles(ParticleSimulationData *sim, int from)
|
|||
distribute_particles_on_shape(sim, from);
|
||||
|
||||
if(distr_error){
|
||||
ParticleSystem *psys = sim->psys;
|
||||
PARTICLE_P;
|
||||
distribute_invalid(sim->scene, sim->psys, from);
|
||||
|
||||
fprintf(stderr,"Particle distribution error!\n");
|
||||
|
||||
LOOP_PARTICLES {
|
||||
pa->fuv[0]=pa->fuv[1]=pa->fuv[2]=pa->fuv[3]= 0.0;
|
||||
pa->foffset= 0.0f;
|
||||
pa->num= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1547,7 +1495,7 @@ void initialize_particle(ParticleSimulationData *sim, ParticleData *pa, int p)
|
|||
|
||||
pa->flag &= ~PARS_UNEXIST;
|
||||
|
||||
if(part->from != PART_FROM_PARTICLE && part->type != PART_FLUID) {
|
||||
if(part->type != PART_FLUID) {
|
||||
psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.f);
|
||||
|
||||
if(ptex.exist < PSYS_FRAND(p+125))
|
||||
|
@ -1628,34 +1576,6 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
|
|||
int p = pa - psys->particles;
|
||||
part=psys->part;
|
||||
|
||||
#if 0 /* deprecated code */
|
||||
if(part->from==PART_FROM_PARTICLE){
|
||||
float speed;
|
||||
ParticleSimulationData tsim= {0};
|
||||
tsim.scene= sim->scene;
|
||||
tsim.ob= psys->target_ob ? psys->target_ob : ob;
|
||||
tsim.psys = BLI_findlink(&tsim.ob->particlesystem, sim->psys->target_psys-1);
|
||||
|
||||
state.time = pa->time;
|
||||
if(pa->num == -1)
|
||||
memset(&state, 0, sizeof(state));
|
||||
else
|
||||
psys_get_particle_state(&tsim, pa->num, &state, 1);
|
||||
psys_get_from_key(&state, loc, nor, rot, 0);
|
||||
|
||||
mul_qt_v3(rot, vtan);
|
||||
mul_qt_v3(rot, utan);
|
||||
|
||||
speed= normalize_v3_v3(p_vel, state.vel);
|
||||
mul_v3_fl(p_vel, dot_v3v3(r_vel, p_vel));
|
||||
VECSUB(p_vel, r_vel, p_vel);
|
||||
normalize_v3(p_vel);
|
||||
mul_v3_fl(p_vel, speed);
|
||||
|
||||
VECCOPY(pa->fuv, loc); /* abusing pa->fuv (not used for "from particle") for storing emit location */
|
||||
}
|
||||
else{
|
||||
#endif
|
||||
/* get precise emitter matrix if particle is born */
|
||||
if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= sim->psys->cfra) {
|
||||
/* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */
|
||||
|
@ -3156,7 +3076,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra)
|
|||
if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
|
||||
distribute_particles(sim, PART_FROM_CHILD);
|
||||
|
||||
if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0)
|
||||
if(part->childtype==PART_CHILD_FACES && part->parents!=0.0)
|
||||
psys_find_parents(sim);
|
||||
}
|
||||
}
|
||||
|
@ -3923,13 +3843,6 @@ static void psys_changed_type(ParticleSimulationData *sim)
|
|||
|
||||
BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys);
|
||||
|
||||
if(part->from == PART_FROM_PARTICLE) {
|
||||
//if(part->type != PART_REACTOR)
|
||||
part->from = PART_FROM_FACE;
|
||||
if(part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT)
|
||||
part->distr = PART_DISTR_JIT;
|
||||
}
|
||||
|
||||
if(part->phystype != PART_PHYS_KEYED)
|
||||
sim->psys->flag &= ~PSYS_KEYED;
|
||||
|
||||
|
@ -3937,6 +3850,9 @@ static void psys_changed_type(ParticleSimulationData *sim)
|
|||
if(ELEM4(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0)
|
||||
part->ren_as = PART_DRAW_PATH;
|
||||
|
||||
if(part->distr == PART_DISTR_GRID)
|
||||
part->distr = PART_DISTR_JIT;
|
||||
|
||||
if(ELEM3(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0)
|
||||
part->draw_as = PART_DRAW_REND;
|
||||
|
||||
|
|
|
@ -339,7 +339,7 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
|
|||
#define PART_FROM_VERT 0
|
||||
#define PART_FROM_FACE 1
|
||||
#define PART_FROM_VOLUME 2
|
||||
#define PART_FROM_PARTICLE 3
|
||||
/* #define PART_FROM_PARTICLE 3 deprecated! */
|
||||
#define PART_FROM_CHILD 4
|
||||
|
||||
/* part->distr */
|
||||
|
|
|
@ -60,7 +60,19 @@ EnumPropertyItem part_reactor_from_items[] = {
|
|||
{PART_FROM_VERT, "VERT", 0, "Verts", ""},
|
||||
{PART_FROM_FACE, "FACE", 0, "Faces", ""},
|
||||
{PART_FROM_VOLUME, "VOLUME", 0, "Volume", ""},
|
||||
{PART_FROM_PARTICLE, "PARTICLE", 0, "Particle", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
EnumPropertyItem part_dist_items[] = {
|
||||
{PART_DISTR_JIT, "JIT", 0, "Jittered", ""},
|
||||
{PART_DISTR_RAND, "RAND", 0, "Random", ""},
|
||||
{PART_DISTR_GRID, "GRID", 0, "Grid", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
EnumPropertyItem part_hair_dist_items[] = {
|
||||
{PART_DISTR_JIT, "JIT", 0, "Jittered", ""},
|
||||
{PART_DISTR_RAND, "RAND", 0, "Random", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -665,6 +677,16 @@ static EnumPropertyItem *rna_Particle_from_itemf(bContext *C, PointerRNA *ptr, i
|
|||
return part_from_items;
|
||||
}
|
||||
|
||||
static EnumPropertyItem *rna_Particle_dist_itemf(bContext *C, PointerRNA *ptr, int *free)
|
||||
{
|
||||
ParticleSettings *part = ptr->id.data;
|
||||
|
||||
if(part->type==PART_HAIR)
|
||||
return part_hair_dist_items;
|
||||
else
|
||||
return part_dist_items;
|
||||
}
|
||||
|
||||
static EnumPropertyItem *rna_Particle_draw_as_itemf(bContext *C, PointerRNA *ptr, int *free)
|
||||
{
|
||||
ParticleSettings *part = ptr->id.data;
|
||||
|
@ -1361,13 +1383,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
|
|||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static EnumPropertyItem dist_items[] = {
|
||||
{PART_DISTR_JIT, "JIT", 0, "Jittered", ""},
|
||||
{PART_DISTR_RAND, "RAND", 0, "Random", ""},
|
||||
{PART_DISTR_GRID, "GRID", 0, "Grid", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static EnumPropertyItem phys_type_items[] = {
|
||||
{PART_PHYS_NO, "NO", 0, "No", ""},
|
||||
{PART_PHYS_NEWTON, "NEWTON", 0, "Newtonian", ""},
|
||||
|
@ -1609,7 +1624,9 @@ static void rna_def_particle_settings(BlenderRNA *brna)
|
|||
prop= RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "distr");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_enum_items(prop, dist_items);
|
||||
RNA_def_property_enum_items(prop, part_dist_items);
|
||||
RNA_def_property_enum_items(prop, part_draw_as_items);
|
||||
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Particle_dist_itemf");
|
||||
RNA_def_property_ui_text(prop, "Distribution", "How to distribute particles on selected element");
|
||||
RNA_def_property_update(prop, 0, "rna_Particle_reset");
|
||||
|
||||
|
|
|
@ -1713,25 +1713,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
|
|||
bb.totnum = totpart+totchild;
|
||||
bb.uv_split = part->bb_uv_split;
|
||||
}
|
||||
|
||||
#if 0 // XXX old animation system
|
||||
/* 2.3 setup time */
|
||||
if(part->flag&PART_ABS_TIME && part->ipo) {
|
||||
calc_ipo(part->ipo, cfra);
|
||||
execute_ipo((ID *)part, part->ipo);
|
||||
}
|
||||
|
||||
if(part->flag & PART_GLOB_TIME)
|
||||
#endif // XXX old animation system
|
||||
|
||||
///* 2.4 setup reactors */
|
||||
// if(part->type == PART_REACTOR){
|
||||
// psys_get_reactor_target(ob, psys, &tob, &tpsys);
|
||||
// if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){
|
||||
// psmd = psys_get_modifier(tob,tpsys);
|
||||
// tpart = tpsys->part;
|
||||
// }
|
||||
// }
|
||||
|
||||
/* 2.5 setup matrices */
|
||||
mul_m4_m4m4(mat, ob->obmat, re->viewmat);
|
||||
|
@ -1828,7 +1809,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
|
|||
hasize = ma->hasize;
|
||||
|
||||
/* get orco */
|
||||
if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){
|
||||
if(tpsys && part->phystype==PART_PHYS_NO){
|
||||
tpa=tpsys->particles+pa->num;
|
||||
psys_particle_on_emitter(psmd,tpart->from,tpa->num,pa->num_dmcache,tpa->fuv,tpa->foffset,co,nor,0,0,sd.orco,0);
|
||||
}
|
||||
|
@ -1892,7 +1873,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
|
|||
}
|
||||
|
||||
/* get uvco & mcol */
|
||||
if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES) {
|
||||
if(part->childtype==PART_CHILD_FACES) {
|
||||
get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm, cpa->fuv, cpa->num, &sd);
|
||||
}
|
||||
else {
|
||||
|
|
Loading…
Reference in New Issue