static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *pdr, float *density, float *vec, float *age) { pdr->squared_radius = pd->radius*pd->radius; pdr->density = density; pdr->point_data = pd->point_data; pdr->falloff_type = pd->falloff_type; pdr->vec = vec; pdr->age = age; pdr->softness = pd->falloff_softness; pdr->noise_influence = pd->noise_influence; pdr->point_data_used = point_data_used(pd); pdr->offset = (pdr->point_data_used & POINT_DATA_VEL)?pd->totpoints*3:0; }
int pointdensitytex(Tex *tex, float *texvec, TexResult *texres) { int retval = TEX_INT; PointDensity *pd = tex->pd; PointDensityRangeData pdr; float density=0.0f, age=0.0f, time=0.0f; float vec[3] = {0.0f, 0.0f, 0.0f}, co[3]; float col[4]; float turb, noise_fac; int num=0; texres->tin = 0.0f; if ((!pd) || (!pd->point_tree)) return 0; init_pointdensityrangedata(pd, &pdr, &density, vec, &age, (pd->flag&TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : NULL), pd->falloff_speed_scale*0.001f); noise_fac = pd->noise_fac * 0.5f; /* better default */ VECCOPY(co, texvec); if (point_data_used(pd)) { /* does a BVH lookup to find accumulated density and additional point data * * stores particle velocity vector in 'vec', and particle lifetime in 'time' */ num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr); if (num > 0) { age /= num; mul_v3_fl(vec, 1.0f/num); } /* reset */ density = vec[0] = vec[1] = vec[2] = 0.0f; } if (pd->flag & TEX_PD_TURBULENCE) { if (pd->noise_influence == TEX_PD_NOISE_AGE) { turb = BLI_gTurbulence(pd->noise_size, texvec[0]+age, texvec[1]+age, texvec[2]+age, pd->noise_depth, 0, pd->noise_basis); } else if (pd->noise_influence == TEX_PD_NOISE_TIME) { time = R.cfra / (float)R.r.efra; turb = BLI_gTurbulence(pd->noise_size, texvec[0]+time, texvec[1]+time, texvec[2]+time, pd->noise_depth, 0, pd->noise_basis); //turb = BLI_turbulence(pd->noise_size, texvec[0]+time, texvec[1]+time, texvec[2]+time, pd->noise_depth); } else { turb = BLI_gTurbulence(pd->noise_size, texvec[0]+vec[0], texvec[1]+vec[1], texvec[2]+vec[2], pd->noise_depth, 0, pd->noise_basis); } turb -= 0.5f; /* re-center 0.0-1.0 range around 0 to prevent offsetting result */ /* now we have an offset coordinate to use for the density lookup */ co[0] = texvec[0] + noise_fac * turb; co[1] = texvec[1] + noise_fac * turb; co[2] = texvec[2] + noise_fac * turb; } /* BVH query with the potentially perturbed coordinates */ num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr); if (num > 0) { age /= num; mul_v3_fl(vec, 1.0f/num); } texres->tin = density; BRICONT; if (pd->color_source == TEX_PD_COLOR_CONSTANT) return retval; retval |= TEX_RGB; switch (pd->color_source) { case TEX_PD_COLOR_PARTAGE: if (pd->coba) { if (do_colorband(pd->coba, age, col)) { texres->talpha= 1; VECCOPY(&texres->tr, col); texres->tin *= col[3]; texres->ta = texres->tin; } } break; case TEX_PD_COLOR_PARTSPEED: { float speed = len_v3(vec) * pd->speed_scale; if (pd->coba) { if (do_colorband(pd->coba, speed, col)) { texres->talpha= 1; VECCOPY(&texres->tr, col); texres->tin *= col[3]; texres->ta = texres->tin; } } break; } case TEX_PD_COLOR_PARTVEL: texres->talpha= 1; mul_v3_fl(vec, pd->speed_scale); VECCOPY(&texres->tr, vec); texres->ta = texres->tin; break; case TEX_PD_COLOR_CONSTANT: default: texres->tr = texres->tg = texres->tb = texres->ta = 1.0f; break; } BRICONTRGB; return retval; /* if (texres->nor!=NULL) { texres->nor[0] = texres->nor[1] = texres->nor[2] = 0.0f; } */ }
static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, ParticleSystem *psys) { DerivedMesh* dm; ParticleKey state; ParticleSimulationData sim= {NULL}; ParticleData *pa=NULL; float cfra = BKE_curframe(re->scene); int i, childexists; int total_particles, offset=0; int data_used = point_data_used(pd); float partco[3]; float obview[4][4]; /* init everything */ if (!psys || !ob || !pd) return; mul_m4_m4m4(obview, re->viewinv, ob->obmat); /* Just to create a valid rendering context for particles */ psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, 0); dm = mesh_create_derived_render(re->scene, ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL); if ( !psys_check_enabled(ob, psys)) { psys_render_restore(ob, psys); return; } sim.scene= re->scene; sim.ob= ob; sim.psys= psys; /* in case ob->imat isn't up-to-date */ invert_m4_m4(ob->imat, ob->obmat); total_particles = psys->totpart+psys->totchild; psys->lattice=psys_get_lattice(&sim); pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6); alloc_point_data(pd, total_particles, data_used); pd->totpoints = total_particles; if (data_used & POINT_DATA_VEL) offset = pd->totpoints*3; if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) childexists = 1; for (i=0, pa=psys->particles; i < total_particles; i++, pa++) { state.time = cfra; if(psys_get_particle_state(&sim, i, &state, 0)) { VECCOPY(partco, state.co); if (pd->psys_cache_space == TEX_PD_OBJECTSPACE) mul_m4_v3(ob->imat, partco); else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) { sub_v3_v3(partco, ob->loc); } else { /* TEX_PD_WORLDSPACE */ } BLI_bvhtree_insert(pd->point_tree, i, partco, 1); if (data_used & POINT_DATA_VEL) { pd->point_data[i*3 + 0] = state.vel[0]; pd->point_data[i*3 + 1] = state.vel[1]; pd->point_data[i*3 + 2] = state.vel[2]; } if (data_used & POINT_DATA_LIFE) { float pa_time; if (i < psys->totpart) { pa_time = (cfra - pa->time)/pa->lifetime; } else { ChildParticle *cpa= (psys->child + i) - psys->totpart; float pa_birthtime, pa_dietime; pa_time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime); } pd->point_data[offset + i] = pa_time; } } } BLI_bvhtree_balance(pd->point_tree); dm->release(dm); if(psys->lattice){ end_latt_deform(psys->lattice); psys->lattice=0; } psys_render_restore(ob, psys); }
static int pointdensity(PointDensity *pd, const float texvec[3], TexResult *texres, float *r_age, float r_vec[3]) { int retval = TEX_INT; PointDensityRangeData pdr; float density = 0.0f, age = 0.0f, time = 0.0f; float vec[3] = {0.0f, 0.0f, 0.0f}, co[3]; float turb, noise_fac; int num = 0; texres->tin = 0.0f; if ((!pd) || (!pd->point_tree)) return 0; init_pointdensityrangedata(pd, &pdr, &density, vec, &age, (pd->flag & TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : NULL), pd->falloff_speed_scale * 0.001f); noise_fac = pd->noise_fac * 0.5f; /* better default */ copy_v3_v3(co, texvec); if (point_data_used(pd)) { /* does a BVH lookup to find accumulated density and additional point data * * stores particle velocity vector in 'vec', and particle lifetime in 'time' */ num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr); if (num > 0) { age /= num; mul_v3_fl(vec, 1.0f / num); } /* reset */ density = vec[0] = vec[1] = vec[2] = 0.0f; } if (pd->flag & TEX_PD_TURBULENCE) { if (pd->noise_influence == TEX_PD_NOISE_AGE) { turb = BLI_gTurbulence(pd->noise_size, texvec[0] + age, texvec[1] + age, texvec[2] + age, pd->noise_depth, 0, pd->noise_basis); } else if (pd->noise_influence == TEX_PD_NOISE_TIME) { time = R.r.cfra / (float)R.r.efra; turb = BLI_gTurbulence(pd->noise_size, texvec[0] + time, texvec[1] + time, texvec[2] + time, pd->noise_depth, 0, pd->noise_basis); //turb = BLI_turbulence(pd->noise_size, texvec[0]+time, texvec[1]+time, texvec[2]+time, pd->noise_depth); } else { turb = BLI_gTurbulence(pd->noise_size, texvec[0] + vec[0], texvec[1] + vec[1], texvec[2] + vec[2], pd->noise_depth, 0, pd->noise_basis); } turb -= 0.5f; /* re-center 0.0-1.0 range around 0 to prevent offsetting result */ /* now we have an offset coordinate to use for the density lookup */ co[0] = texvec[0] + noise_fac * turb; co[1] = texvec[1] + noise_fac * turb; co[2] = texvec[2] + noise_fac * turb; } /* BVH query with the potentially perturbed coordinates */ num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr); if (num > 0) { age /= num; mul_v3_fl(vec, 1.0f / num); } texres->tin = density; if (r_age != NULL) { *r_age = age; } if (r_vec != NULL) { copy_v3_v3(r_vec, vec); } return retval; }
static void pointdensity_cache_psys(Scene *scene, PointDensity *pd, Object *ob, ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy) { DerivedMesh *dm; ParticleKey state; ParticleCacheKey *cache; ParticleSimulationData sim = {NULL}; ParticleData *pa = NULL; float cfra = BKE_scene_frame_get(scene); int i /*, childexists*/ /* UNUSED */; int total_particles, offset = 0; int data_used = point_data_used(pd); float partco[3]; /* init everything */ if (!psys || !ob || !pd) { return; } /* Just to create a valid rendering context for particles */ psys_render_set(ob, psys, viewmat, winmat, winx, winy, 0); dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); if ( !psys_check_enabled(ob, psys)) { psys_render_restore(ob, psys); return; } sim.scene = scene; sim.ob = ob; sim.psys = psys; sim.psmd = psys_get_modifier(ob, psys); /* in case ob->imat isn't up-to-date */ invert_m4_m4(ob->imat, ob->obmat); total_particles = psys->totpart + psys->totchild; psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6); alloc_point_data(pd, total_particles, data_used); pd->totpoints = total_particles; if (data_used & POINT_DATA_VEL) { offset = pd->totpoints * 3; } #if 0 /* UNUSED */ if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) childexists = 1; #endif for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) { if (psys->part->type == PART_HAIR) { /* hair particles */ if (i < psys->totpart && psys->pathcache) cache = psys->pathcache[i]; else if (i >= psys->totpart && psys->childcache) cache = psys->childcache[i - psys->totpart]; else continue; cache += cache->segments; /* use endpoint */ copy_v3_v3(state.co, cache->co); zero_v3(state.vel); state.time = 0.0f; } else { /* emitter particles */ state.time = cfra; if (!psys_get_particle_state(&sim, i, &state, 0)) continue; if (data_used & POINT_DATA_LIFE) { if (i < psys->totpart) { state.time = (cfra - pa->time) / pa->lifetime; } else { ChildParticle *cpa = (psys->child + i) - psys->totpart; float pa_birthtime, pa_dietime; state.time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime); } } } copy_v3_v3(partco, state.co); if (pd->psys_cache_space == TEX_PD_OBJECTSPACE) mul_m4_v3(ob->imat, partco); else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) { sub_v3_v3(partco, ob->loc); } else { /* TEX_PD_WORLDSPACE */ } BLI_bvhtree_insert(pd->point_tree, i, partco, 1); if (data_used & POINT_DATA_VEL) { pd->point_data[i * 3 + 0] = state.vel[0]; pd->point_data[i * 3 + 1] = state.vel[1]; pd->point_data[i * 3 + 2] = state.vel[2]; } if (data_used & POINT_DATA_LIFE) { pd->point_data[offset + i] = state.time; } } BLI_bvhtree_balance(pd->point_tree); dm->release(dm); if (psys->lattice_deform_data) { end_latt_deform(psys->lattice_deform_data); psys->lattice_deform_data = NULL; } psys_render_restore(ob, psys); }