Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/physics/particle_edit.c
| Show First 20 Lines • Show All 772 Lines • ▼ Show 20 Lines | static void foreach_mouse_hit_key_iter(void *__restrict iter_data_v, | ||||
| PEData *data = iter_data->data; | PEData *data = iter_data->data; | ||||
| PTCacheEdit *edit = data->edit; | PTCacheEdit *edit = data->edit; | ||||
| PTCacheEditPoint *point = &edit->points[iter]; | PTCacheEditPoint *point = &edit->points[iter]; | ||||
| if (point->flag & PEP_HIDE) { | if (point->flag & PEP_HIDE) { | ||||
| return; | return; | ||||
| } | } | ||||
| ParticleSystem *psys = edit->psys; | ParticleSystem *psys = edit->psys; | ||||
| ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval; | ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval; | ||||
| Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval); | |||||
| ParticleEditSettings *pset = PE_settings(data->scene); | ParticleEditSettings *pset = PE_settings(data->scene); | ||||
| const int selected = iter_data->selected; | const int selected = iter_data->selected; | ||||
| float mat[4][4], imat[4][4]; | float mat[4][4], imat[4][4]; | ||||
| unit_m4(mat); | unit_m4(mat); | ||||
| unit_m4(imat); | unit_m4(imat); | ||||
| if (pset->selectmode == SCE_SELECT_END) { | if (pset->selectmode == SCE_SELECT_END) { | ||||
| if (point->totkey) { | if (point->totkey) { | ||||
| /* only do end keys */ | /* only do end keys */ | ||||
| PTCacheEditKey *key = point->keys + point->totkey - 1; | PTCacheEditKey *key = point->keys + point->totkey - 1; | ||||
| if (selected == 0 || key->flag & PEK_SELECT) { | if (selected == 0 || key->flag & PEK_SELECT) { | ||||
| float mouse_distance; | float mouse_distance; | ||||
| if (key_inside_circle(data, data->rad, KEY_WCO, &mouse_distance)) { | if (key_inside_circle(data, data->rad, KEY_WCO, &mouse_distance)) { | ||||
| if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { | if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { | ||||
| psys_mat_hair_to_global( | psys_mat_hair_to_global( | ||||
| data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, mat); | data->ob, mesh_final, psys->part->from, psys->particles + iter, mat); | ||||
| invert_m4_m4(imat, mat); | invert_m4_m4(imat, mat); | ||||
| } | } | ||||
| iter_data->func(data, mat, imat, iter, point->totkey - 1, key, mouse_distance); | iter_data->func(data, mat, imat, iter, point->totkey - 1, key, mouse_distance); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* do all keys */ | /* do all keys */ | ||||
| PTCacheEditKey *key; | PTCacheEditKey *key; | ||||
| int k; | int k; | ||||
| LOOP_VISIBLE_KEYS | LOOP_VISIBLE_KEYS | ||||
| { | { | ||||
| if (selected == 0 || key->flag & PEK_SELECT) { | if (selected == 0 || key->flag & PEK_SELECT) { | ||||
| float mouse_distance; | float mouse_distance; | ||||
| if (key_inside_circle(data, data->rad, KEY_WCO, &mouse_distance)) { | if (key_inside_circle(data, data->rad, KEY_WCO, &mouse_distance)) { | ||||
| if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { | if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { | ||||
| psys_mat_hair_to_global( | psys_mat_hair_to_global( | ||||
| data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, mat); | data->ob, mesh_final, psys->part->from, psys->particles + iter, mat); | ||||
| invert_m4_m4(imat, mat); | invert_m4_m4(imat, mat); | ||||
| } | } | ||||
| iter_data->func(data, mat, imat, iter, k, key, mouse_distance); | iter_data->func(data, mat, imat, iter, k, key, mouse_distance); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) | ||||
| PARTICLE_P; | PARTICLE_P; | ||||
| float mat[4][4], co[3]; | float mat[4][4], co[3]; | ||||
| int index, totpart; | int index, totpart; | ||||
| edit = psys->edit; | edit = psys->edit; | ||||
| psmd_eval = edit->psmd_eval; | psmd_eval = edit->psmd_eval; | ||||
| totpart = psys->totpart; | totpart = psys->totpart; | ||||
| if (!psmd_eval->mesh_final) { | Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval); | ||||
| if (!mesh_final) { | |||||
| return; | return; | ||||
| } | } | ||||
| tree = BLI_kdtree_3d_new(totpart); | tree = BLI_kdtree_3d_new(totpart); | ||||
| /* insert particles into kd tree */ | /* insert particles into kd tree */ | ||||
| LOOP_PARTICLES | LOOP_PARTICLES | ||||
| { | { | ||||
| key = pa->hair; | key = pa->hair; | ||||
| psys_mat_hair_to_orco(ob, psmd_eval->mesh_final, psys->part->from, pa, mat); | psys_mat_hair_to_orco(ob, mesh_final, psys->part->from, pa, mat); | ||||
| copy_v3_v3(co, key->co); | copy_v3_v3(co, key->co); | ||||
| mul_m4_v3(mat, co); | mul_m4_v3(mat, co); | ||||
| BLI_kdtree_3d_insert(tree, p, co); | BLI_kdtree_3d_insert(tree, p, co); | ||||
| } | } | ||||
| BLI_kdtree_3d_balance(tree); | BLI_kdtree_3d_balance(tree); | ||||
| /* lookup particles and set in mirror cache */ | /* lookup particles and set in mirror cache */ | ||||
| if (!edit->mirror_cache) { | if (!edit->mirror_cache) { | ||||
| edit->mirror_cache = MEM_callocN(sizeof(int) * totpart, "PE mirror cache"); | edit->mirror_cache = MEM_callocN(sizeof(int) * totpart, "PE mirror cache"); | ||||
| } | } | ||||
| LOOP_PARTICLES | LOOP_PARTICLES | ||||
| { | { | ||||
| key = pa->hair; | key = pa->hair; | ||||
| psys_mat_hair_to_orco(ob, psmd_eval->mesh_final, psys->part->from, pa, mat); | psys_mat_hair_to_orco(ob, mesh_final, psys->part->from, pa, mat); | ||||
| copy_v3_v3(co, key->co); | copy_v3_v3(co, key->co); | ||||
| mul_m4_v3(mat, co); | mul_m4_v3(mat, co); | ||||
| co[0] = -co[0]; | co[0] = -co[0]; | ||||
| index = BLI_kdtree_3d_find_nearest(tree, co, &nearest); | index = BLI_kdtree_3d_find_nearest(tree, co, &nearest); | ||||
| /* this needs a custom threshold still, duplicated for editmode mirror */ | /* this needs a custom threshold still, duplicated for editmode mirror */ | ||||
| if (index != -1 && index != p && (nearest.dist <= 0.0002f)) { | if (index != -1 && index != p && (nearest.dist <= 0.0002f)) { | ||||
| ▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | static void PE_apply_mirror(Object *ob, ParticleSystem *psys) | ||||
| POINT_P; | POINT_P; | ||||
| if (!psys) { | if (!psys) { | ||||
| return; | return; | ||||
| } | } | ||||
| edit = psys->edit; | edit = psys->edit; | ||||
| psmd_eval = edit->psmd_eval; | psmd_eval = edit->psmd_eval; | ||||
| Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval); | |||||
| if (!psmd_eval->mesh_final) { | if (!mesh_final) { | ||||
| return; | return; | ||||
| } | } | ||||
| if (!edit->mirror_cache) { | if (!edit->mirror_cache) { | ||||
| PE_update_mirror_cache(ob, psys); | PE_update_mirror_cache(ob, psys); | ||||
| } | } | ||||
| if (!edit->mirror_cache) { | if (!edit->mirror_cache) { | ||||
| return; /* something went wrong */ | return; /* something went wrong */ | ||||
| } | } | ||||
| /* we delay settings the PARS_EDIT_RECALC for mirrored particles | /* we delay settings the PARS_EDIT_RECALC for mirrored particles | ||||
| * to avoid doing mirror twice */ | * to avoid doing mirror twice */ | ||||
| LOOP_POINTS | LOOP_POINTS | ||||
| { | { | ||||
| if (point->flag & PEP_EDIT_RECALC) { | if (point->flag & PEP_EDIT_RECALC) { | ||||
| PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL); | PE_mirror_particle(ob, mesh_final, psys, psys->particles + p, NULL); | ||||
| if (edit->mirror_cache[p] != -1) { | if (edit->mirror_cache[p] != -1) { | ||||
| edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC; | edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| LOOP_POINTS | LOOP_POINTS | ||||
| Show All 33 Lines | static void deflect_emitter_iter(void *__restrict iter_data_v, | ||||
| ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval; | ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval; | ||||
| PTCacheEditKey *key; | PTCacheEditKey *key; | ||||
| int k; | int k; | ||||
| float hairimat[4][4], hairmat[4][4]; | float hairimat[4][4], hairmat[4][4]; | ||||
| int index; | int index; | ||||
| float *vec, *nor, dvec[3], dot, dist_1st = 0.0f; | float *vec, *nor, dvec[3], dot, dist_1st = 0.0f; | ||||
| const float dist = iter_data->dist; | const float dist = iter_data->dist; | ||||
| const float emitterdist = iter_data->emitterdist; | const float emitterdist = iter_data->emitterdist; | ||||
| psys_mat_hair_to_object( | Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval); | ||||
| object, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, hairmat); | psys_mat_hair_to_object(object, mesh_final, psys->part->from, psys->particles + iter, hairmat); | ||||
| LOOP_KEYS | LOOP_KEYS | ||||
| { | { | ||||
| mul_m4_v3(hairmat, key->co); | mul_m4_v3(hairmat, key->co); | ||||
| } | } | ||||
| LOOP_KEYS | LOOP_KEYS | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit) | ||||
| if (edit == NULL || edit->psys == NULL || (pset->flag & PE_DEFLECT_EMITTER) == 0 || | if (edit == NULL || edit->psys == NULL || (pset->flag & PE_DEFLECT_EMITTER) == 0 || | ||||
| (edit->psys->flag & PSYS_GLOBAL_HAIR)) { | (edit->psys->flag & PSYS_GLOBAL_HAIR)) { | ||||
| return; | return; | ||||
| } | } | ||||
| psys = edit->psys; | psys = edit->psys; | ||||
| if (!edit->psmd_eval->mesh_final) { | Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(edit->psmd_eval); | ||||
| if (!mesh_final) { | |||||
| return; | return; | ||||
| } | } | ||||
| DeflectEmitterIter iter_data; | DeflectEmitterIter iter_data; | ||||
| iter_data.object = ob; | iter_data.object = ob; | ||||
| iter_data.psys = psys; | iter_data.psys = psys; | ||||
| iter_data.edit = edit; | iter_data.edit = edit; | ||||
| iter_data.dist = dist; | iter_data.dist = dist; | ||||
| ▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | LOOP_EDITED_POINTS | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* calculate a tree for finding nearest emitter's vertice */ | /* calculate a tree for finding nearest emitter's vertice */ | ||||
| void recalc_emitter_field(Depsgraph *UNUSED(depsgraph), Object *UNUSED(ob), ParticleSystem *psys) | void recalc_emitter_field(Depsgraph *UNUSED(depsgraph), Object *UNUSED(ob), ParticleSystem *psys) | ||||
| { | { | ||||
| PTCacheEdit *edit = psys->edit; | PTCacheEdit *edit = psys->edit; | ||||
| Mesh *mesh = edit->psmd_eval->mesh_final; | Mesh *mesh = BKE_particle_modifier_mesh_final_get(edit->psmd_eval); | ||||
| float *vec, *nor; | float *vec, *nor; | ||||
| int i, totface /*, totvert*/; | int i, totface /*, totvert*/; | ||||
| if (!mesh) { | if (!mesh) { | ||||
| return; | return; | ||||
| } | } | ||||
| if (edit->emitter_cosnos) { | if (edit->emitter_cosnos) { | ||||
| ▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | |||||
| void update_world_cos(Depsgraph *UNUSED(depsgraph), Object *ob, PTCacheEdit *edit) | void update_world_cos(Depsgraph *UNUSED(depsgraph), Object *ob, PTCacheEdit *edit) | ||||
| { | { | ||||
| ParticleSystem *psys = edit->psys; | ParticleSystem *psys = edit->psys; | ||||
| ParticleSystemModifierData *psmd_eval = edit->psmd_eval; | ParticleSystemModifierData *psmd_eval = edit->psmd_eval; | ||||
| POINT_P; | POINT_P; | ||||
| KEY_K; | KEY_K; | ||||
| float hairmat[4][4]; | float hairmat[4][4]; | ||||
| if (psys == 0 || psys->edit == 0 || psmd_eval->mesh_final == NULL) { | Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval); | ||||
| if (psys == 0 || psys->edit == 0 || mesh_final == NULL) { | |||||
| return; | return; | ||||
| } | } | ||||
| LOOP_POINTS | LOOP_POINTS | ||||
| { | { | ||||
| if (!(psys->flag & PSYS_GLOBAL_HAIR)) { | if (!(psys->flag & PSYS_GLOBAL_HAIR)) { | ||||
| psys_mat_hair_to_global( | psys_mat_hair_to_global(ob, mesh_final, psys->part->from, psys->particles + p, hairmat); | ||||
| ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, hairmat); | |||||
| } | } | ||||
| LOOP_KEYS | LOOP_KEYS | ||||
| { | { | ||||
| copy_v3_v3(key->world_co, key->co); | copy_v3_v3(key->world_co, key->co); | ||||
| if (!(psys->flag & PSYS_GLOBAL_HAIR)) { | if (!(psys->flag & PSYS_GLOBAL_HAIR)) { | ||||
| mul_m4_v3(hairmat, key->world_co); | mul_m4_v3(hairmat, key->world_co); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 755 Lines • ▼ Show 20 Lines | int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const int sel_op) | ||||
| /* only for depths */ | /* only for depths */ | ||||
| PE_set_view3d_data(C, &data); | PE_set_view3d_data(C, &data); | ||||
| if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | ||||
| data.is_changed |= PE_deselect_all_visible_ex(edit); | data.is_changed |= PE_deselect_all_visible_ex(edit); | ||||
| } | } | ||||
| Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval); | |||||
| LOOP_VISIBLE_POINTS | LOOP_VISIBLE_POINTS | ||||
| { | { | ||||
| if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR)) { | if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR)) { | ||||
| psys_mat_hair_to_global( | psys_mat_hair_to_global(ob, mesh_final, psys->part->from, psys->particles + p, mat); | ||||
| ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat); | |||||
| } | } | ||||
| if (pset->selectmode == SCE_SELECT_POINT) { | if (pset->selectmode == SCE_SELECT_POINT) { | ||||
| LOOP_KEYS | LOOP_KEYS | ||||
| { | { | ||||
| copy_v3_v3(co, key->co); | copy_v3_v3(co, key->co); | ||||
| mul_m4_v3(mat, co); | mul_m4_v3(mat, co); | ||||
| const bool is_select = key->flag & PEK_SELECT; | const bool is_select = key->flag & PEK_SELECT; | ||||
| ▲ Show 20 Lines • Show All 449 Lines • ▼ Show 20 Lines | static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror) | ||||
| POINT_P; | POINT_P; | ||||
| PTCacheEditPoint *npoint = 0, *new_points = 0; | PTCacheEditPoint *npoint = 0, *new_points = 0; | ||||
| ParticleSystemModifierData *psmd_eval; | ParticleSystemModifierData *psmd_eval; | ||||
| int i, new_totpart = psys->totpart, removed = 0; | int i, new_totpart = psys->totpart, removed = 0; | ||||
| if (mirror) { | if (mirror) { | ||||
| /* mirror tags */ | /* mirror tags */ | ||||
| psmd_eval = edit->psmd_eval; | psmd_eval = edit->psmd_eval; | ||||
| Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval); | |||||
| LOOP_TAGGED_POINTS | LOOP_TAGGED_POINTS | ||||
| { | { | ||||
| PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL); | PE_mirror_particle(ob, mesh_final, psys, psys->particles + p, NULL); | ||||
| } | } | ||||
| } | } | ||||
| LOOP_TAGGED_POINTS | LOOP_TAGGED_POINTS | ||||
| { | { | ||||
| new_totpart--; | new_totpart--; | ||||
| removed++; | removed++; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | static void remove_tagged_keys(Depsgraph *depsgraph, Object *ob, ParticleSystem *psys) | ||||
| PTCacheEditKey *nkey, *new_keys; | PTCacheEditKey *nkey, *new_keys; | ||||
| short new_totkey; | short new_totkey; | ||||
| if (pe_x_mirror(ob)) { | if (pe_x_mirror(ob)) { | ||||
| /* mirror key tags */ | /* mirror key tags */ | ||||
| ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); | ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); | ||||
| ParticleSystemModifierData *psmd_eval = (ParticleSystemModifierData *)modifier_get_evaluated( | ParticleSystemModifierData *psmd_eval = (ParticleSystemModifierData *)modifier_get_evaluated( | ||||
| depsgraph, ob, &psmd->modifier); | depsgraph, ob, &psmd->modifier); | ||||
| Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval); | |||||
| LOOP_POINTS | LOOP_POINTS | ||||
| { | { | ||||
| LOOP_TAGGED_KEYS | LOOP_TAGGED_KEYS | ||||
| { | { | ||||
| PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL); | PE_mirror_particle(ob, mesh_final, psys, psys->particles + p, NULL); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| LOOP_POINTS | LOOP_POINTS | ||||
| { | { | ||||
| new_totkey = point->totkey; | new_totkey = point->totkey; | ||||
| ▲ Show 20 Lines • Show All 210 Lines • ▼ Show 20 Lines | static int remove_doubles_exec(bContext *C, wmOperator *op) | ||||
| if (psys->flag & PSYS_GLOBAL_HAIR) { | if (psys->flag & PSYS_GLOBAL_HAIR) { | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| edit = psys->edit; | edit = psys->edit; | ||||
| psmd_eval = edit->psmd_eval; | psmd_eval = edit->psmd_eval; | ||||
| totremoved = 0; | totremoved = 0; | ||||
| Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval); | |||||
| do { | do { | ||||
| removed = 0; | removed = 0; | ||||
| tree = BLI_kdtree_3d_new(psys->totpart); | tree = BLI_kdtree_3d_new(psys->totpart); | ||||
| /* insert particles into kd tree */ | /* insert particles into kd tree */ | ||||
| LOOP_SELECTED_POINTS | LOOP_SELECTED_POINTS | ||||
| { | { | ||||
| psys_mat_hair_to_object( | psys_mat_hair_to_object(ob, mesh_final, psys->part->from, psys->particles + p, mat); | ||||
| ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat); | |||||
| copy_v3_v3(co, point->keys->co); | copy_v3_v3(co, point->keys->co); | ||||
| mul_m4_v3(mat, co); | mul_m4_v3(mat, co); | ||||
| BLI_kdtree_3d_insert(tree, p, co); | BLI_kdtree_3d_insert(tree, p, co); | ||||
| } | } | ||||
| BLI_kdtree_3d_balance(tree); | BLI_kdtree_3d_balance(tree); | ||||
| /* tag particles to be removed */ | /* tag particles to be removed */ | ||||
| LOOP_SELECTED_POINTS | LOOP_SELECTED_POINTS | ||||
| { | { | ||||
| psys_mat_hair_to_object( | psys_mat_hair_to_object(ob, mesh_final, psys->part->from, psys->particles + p, mat); | ||||
| ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat); | |||||
| copy_v3_v3(co, point->keys->co); | copy_v3_v3(co, point->keys->co); | ||||
| mul_m4_v3(mat, co); | mul_m4_v3(mat, co); | ||||
| totn = BLI_kdtree_3d_find_nearest_n(tree, co, nearest, 10); | totn = BLI_kdtree_3d_find_nearest_n(tree, co, nearest, 10); | ||||
| for (n = 0; n < totn; n++) { | for (n = 0; n < totn; n++) { | ||||
| /* this needs a custom threshold still */ | /* this needs a custom threshold still */ | ||||
| if (nearest[n].index > p && nearest[n].dist < threshold) { | if (nearest[n].index > p && nearest[n].dist < threshold) { | ||||
| ▲ Show 20 Lines • Show All 246 Lines • ▼ Show 20 Lines | static void PE_mirror_x(Scene *scene, Object *ob, int tagged) | ||||
| int *mirrorfaces = NULL; | int *mirrorfaces = NULL; | ||||
| int rotation, totpart, newtotpart; | int rotation, totpart, newtotpart; | ||||
| if (psys->flag & PSYS_GLOBAL_HAIR) { | if (psys->flag & PSYS_GLOBAL_HAIR) { | ||||
| return; | return; | ||||
| } | } | ||||
| psmd_eval = edit->psmd_eval; | psmd_eval = edit->psmd_eval; | ||||
| if (!psmd_eval->mesh_final) { | Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval); | ||||
| Mesh *mesh_original = BKE_particle_modifier_mesh_original_get(psmd_eval); | |||||
| if (!mesh_final) { | |||||
| return; | return; | ||||
| } | } | ||||
| const bool use_dm_final_indices = (psys->part->use_modifier_stack && | const bool use_dm_final_indices = (psys->part->use_modifier_stack && | ||||
| !psmd_eval->mesh_final->runtime.deformed_only); | !mesh_final->runtime.deformed_only); | ||||
| /* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */ | /* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */ | ||||
| BKE_mesh_tessface_ensure(me); | BKE_mesh_tessface_ensure(me); | ||||
| /* NOTE: In case psys uses Mesh tessface indices, we mirror final Mesh itself, not orig mesh. | /* NOTE: In case psys uses Mesh tessface indices, we mirror final Mesh itself, not orig mesh. | ||||
| * Avoids an (impossible) mesh -> orig -> mesh tessface indices conversion. */ | * Avoids an (impossible) mesh -> orig -> mesh tessface indices conversion. */ | ||||
| mirrorfaces = mesh_get_x_mirror_faces( | mirrorfaces = mesh_get_x_mirror_faces(ob, NULL, use_dm_final_indices ? mesh_final : NULL); | ||||
| ob, NULL, use_dm_final_indices ? psmd_eval->mesh_final : NULL); | |||||
| if (!edit->mirror_cache) { | if (!edit->mirror_cache) { | ||||
| PE_update_mirror_cache(ob, psys); | PE_update_mirror_cache(ob, psys); | ||||
| } | } | ||||
| totpart = psys->totpart; | totpart = psys->totpart; | ||||
| newtotpart = psys->totpart; | newtotpart = psys->totpart; | ||||
| LOOP_VISIBLE_POINTS | LOOP_VISIBLE_POINTS | ||||
| { | { | ||||
| pa = psys->particles + p; | pa = psys->particles + p; | ||||
| if (!tagged) { | if (!tagged) { | ||||
| if (point_is_selected(point)) { | if (point_is_selected(point)) { | ||||
| if (edit->mirror_cache[p] != -1) { | if (edit->mirror_cache[p] != -1) { | ||||
| /* already has a mirror, don't need to duplicate */ | /* already has a mirror, don't need to duplicate */ | ||||
| PE_mirror_particle(ob, psmd_eval->mesh_final, psys, pa, NULL); | PE_mirror_particle(ob, mesh_final, psys, pa, NULL); | ||||
| continue; | continue; | ||||
| } | } | ||||
| else { | else { | ||||
| point->flag |= PEP_TAG; | point->flag |= PEP_TAG; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if ((point->flag & PEP_TAG) && mirrorfaces[pa->num * 2] != -1) { | if ((point->flag & PEP_TAG) && mirrorfaces[pa->num * 2] != -1) { | ||||
| newtotpart++; | newtotpart++; | ||||
| } | } | ||||
| } | } | ||||
| if (newtotpart != psys->totpart) { | if (newtotpart != psys->totpart) { | ||||
| MFace *mtessface = use_dm_final_indices ? psmd_eval->mesh_final->mface : me->mface; | MFace *mtessface = use_dm_final_indices ? mesh_final->mface : me->mface; | ||||
| /* allocate new arrays and copy existing */ | /* allocate new arrays and copy existing */ | ||||
| new_pars = MEM_callocN(newtotpart * sizeof(ParticleData), "ParticleData new"); | new_pars = MEM_callocN(newtotpart * sizeof(ParticleData), "ParticleData new"); | ||||
| new_points = MEM_callocN(newtotpart * sizeof(PTCacheEditPoint), "PTCacheEditPoint new"); | new_points = MEM_callocN(newtotpart * sizeof(PTCacheEditPoint), "PTCacheEditPoint new"); | ||||
| if (psys->particles) { | if (psys->particles) { | ||||
| memcpy(new_pars, psys->particles, totpart * sizeof(ParticleData)); | memcpy(new_pars, psys->particles, totpart * sizeof(ParticleData)); | ||||
| MEM_freeN(psys->particles); | MEM_freeN(psys->particles); | ||||
| ▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | for (p = 0, point = edit->points; p < totpart; p++, point++) { | ||||
| * same as DMCACHE_NOTFOUND. */ | * same as DMCACHE_NOTFOUND. */ | ||||
| newpa->num = mirrorfaces[pa_num * 2]; | newpa->num = mirrorfaces[pa_num * 2]; | ||||
| if (use_dm_final_indices) { | if (use_dm_final_indices) { | ||||
| newpa->num_dmcache = DMCACHE_ISCHILD; | newpa->num_dmcache = DMCACHE_ISCHILD; | ||||
| } | } | ||||
| else { | else { | ||||
| newpa->num_dmcache = psys_particle_dm_face_lookup( | newpa->num_dmcache = psys_particle_dm_face_lookup( | ||||
| psmd_eval->mesh_final, psmd_eval->mesh_original, newpa->num, newpa->fuv, NULL); | mesh_final, mesh_original, newpa->num, newpa->fuv, NULL); | ||||
| } | } | ||||
| /* update edit key pointers */ | /* update edit key pointers */ | ||||
| key = newpoint->keys; | key = newpoint->keys; | ||||
| for (k = 0, hkey = newpa->hair; k < newpa->totkey; k++, hkey++, key++) { | for (k = 0, hkey = newpa->hair; k < newpa->totkey; k++, hkey++, key++) { | ||||
| key->co = hkey->co; | key->co = hkey->co; | ||||
| key->time = &hkey->time; | key->time = &hkey->time; | ||||
| } | } | ||||
| /* map key positions as mirror over x axis */ | /* map key positions as mirror over x axis */ | ||||
| PE_mirror_particle(ob, psmd_eval->mesh_final, psys, pa, newpa); | PE_mirror_particle(ob, mesh_final, psys, pa, newpa); | ||||
| newpa++; | newpa++; | ||||
| newpoint++; | newpoint++; | ||||
| } | } | ||||
| } | } | ||||
| LOOP_POINTS | LOOP_POINTS | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 662 Lines • ▼ Show 20 Lines | if (particle_intersect_mesh(depsgraph, | ||||
| co2, | co2, | ||||
| &min_d, | &min_d, | ||||
| &add_pars[iter].num_dmcache, | &add_pars[iter].num_dmcache, | ||||
| add_pars[iter].fuv, | add_pars[iter].fuv, | ||||
| 0, | 0, | ||||
| 0, | 0, | ||||
| 0, | 0, | ||||
| 0)) { | 0)) { | ||||
| if (psys->part->use_modifier_stack && !psmd_eval->mesh_final->runtime.deformed_only) { | Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval); | ||||
| Mesh *mesh_original = BKE_particle_modifier_mesh_original_get(psmd_eval); | |||||
| if (psys->part->use_modifier_stack && !mesh_final->runtime.deformed_only) { | |||||
| add_pars[iter].num = add_pars[iter].num_dmcache; | add_pars[iter].num = add_pars[iter].num_dmcache; | ||||
| add_pars[iter].num_dmcache = DMCACHE_ISCHILD; | add_pars[iter].num_dmcache = DMCACHE_ISCHILD; | ||||
| } | } | ||||
| else if (iter_data->mesh == psmd_eval->mesh_original) { | else if (iter_data->mesh == mesh_original) { | ||||
| /* Final DM is not same topology as orig mesh, | /* Final DM is not same topology as orig mesh, | ||||
| * we have to map num_dmcache to real final dm. */ | * we have to map num_dmcache to real final dm. */ | ||||
| add_pars[iter].num = add_pars[iter].num_dmcache; | add_pars[iter].num = add_pars[iter].num_dmcache; | ||||
| add_pars[iter].num_dmcache = psys_particle_dm_face_lookup(psmd_eval->mesh_final, | add_pars[iter].num_dmcache = psys_particle_dm_face_lookup( | ||||
| psmd_eval->mesh_original, | mesh_final, mesh_original, add_pars[iter].num, add_pars[iter].fuv, NULL); | ||||
| add_pars[iter].num, | |||||
| add_pars[iter].fuv, | |||||
| NULL); | |||||
| } | } | ||||
| else { | else { | ||||
| add_pars[iter].num = add_pars[iter].num_dmcache; | add_pars[iter].num = add_pars[iter].num_dmcache; | ||||
| } | } | ||||
| if (add_pars[iter].num != DMCACHE_NOTFOUND) { | if (add_pars[iter].num != DMCACHE_NOTFOUND) { | ||||
| tls->num_added++; | tls->num_added++; | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | static int brush_add(const bContext *C, PEData *data, short number) | ||||
| sim.depsgraph = depsgraph; | sim.depsgraph = depsgraph; | ||||
| sim.scene = scene; | sim.scene = scene; | ||||
| sim.ob = ob; | sim.ob = ob; | ||||
| sim.psys = psys; | sim.psys = psys; | ||||
| sim.psmd = psmd_eval; | sim.psmd = psmd_eval; | ||||
| timestep = psys_get_timestep(&sim); | timestep = psys_get_timestep(&sim); | ||||
| if (psys->part->use_modifier_stack || psmd_eval->mesh_final->runtime.deformed_only) { | Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval); | ||||
| mesh = psmd_eval->mesh_final; | if (psys->part->use_modifier_stack || mesh_final->runtime.deformed_only) { | ||||
| mesh = mesh_final; | |||||
| } | } | ||||
| else { | else { | ||||
| mesh = psmd_eval->mesh_original; | mesh = BKE_particle_modifier_mesh_original_get(psmd_eval); | ||||
| } | } | ||||
| BLI_assert(mesh); | BLI_assert(mesh); | ||||
| /* Calculate positions of new particles to add, based on brush intersection | /* Calculate positions of new particles to add, based on brush intersection | ||||
| * with object. New particle data is assigned to a corresponding to check | * with object. New particle data is assigned to a corresponding to check | ||||
| * index element of add_pars array. This means, that add_pars is a sparse | * index element of add_pars array. This means, that add_pars is a sparse | ||||
| * array. | * array. | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | if (edit->mirror_cache) { | ||||
| edit->mirror_cache = NULL; | edit->mirror_cache = NULL; | ||||
| } | } | ||||
| /* create tree for interpolation */ | /* create tree for interpolation */ | ||||
| if (pset->flag & PE_INTERPOLATE_ADDED && psys->totpart) { | if (pset->flag & PE_INTERPOLATE_ADDED && psys->totpart) { | ||||
| tree = BLI_kdtree_3d_new(psys->totpart); | tree = BLI_kdtree_3d_new(psys->totpart); | ||||
| for (i = 0, pa = psys->particles; i < totpart; i++, pa++) { | for (i = 0, pa = psys->particles; i < totpart; i++, pa++) { | ||||
| psys_particle_on_dm(psmd_eval->mesh_final, | psys_particle_on_dm(mesh_final, | ||||
| psys->part->from, | psys->part->from, | ||||
| pa->num, | pa->num, | ||||
| pa->num_dmcache, | pa->num_dmcache, | ||||
| pa->fuv, | pa->fuv, | ||||
| pa->foffset, | pa->foffset, | ||||
| cur_co, | cur_co, | ||||
| 0, | 0, | ||||
| 0, | 0, | ||||
| Show All 40 Lines | for (i = totpart; i < newtotpart; i++, pa++, point++) { | ||||
| if (tree) { | if (tree) { | ||||
| ParticleData *ppa; | ParticleData *ppa; | ||||
| HairKey *thkey; | HairKey *thkey; | ||||
| ParticleKey key3[3]; | ParticleKey key3[3]; | ||||
| KDTreeNearest_3d ptn[3]; | KDTreeNearest_3d ptn[3]; | ||||
| int w, maxw; | int w, maxw; | ||||
| float maxd, totw = 0.0, weight[3]; | float maxd, totw = 0.0, weight[3]; | ||||
| psys_particle_on_dm(psmd_eval->mesh_final, | psys_particle_on_dm(mesh_final, | ||||
| psys->part->from, | psys->part->from, | ||||
| pa->num, | pa->num, | ||||
| pa->num_dmcache, | pa->num_dmcache, | ||||
| pa->fuv, | pa->fuv, | ||||
| pa->foffset, | pa->foffset, | ||||
| co1, | co1, | ||||
| 0, | 0, | ||||
| 0, | 0, | ||||
| ▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | for (i = totpart; i < newtotpart; i++, pa++, point++) { | ||||
| else { | else { | ||||
| for (k = 0, hkey = pa->hair; k < pset->totaddkey; k++, hkey++) { | for (k = 0, hkey = pa->hair; k < pset->totaddkey; k++, hkey++) { | ||||
| madd_v3_v3v3fl(hkey->co, pa->state.co, pa->state.vel, k * framestep * timestep); | madd_v3_v3v3fl(hkey->co, pa->state.co, pa->state.vel, k * framestep * timestep); | ||||
| hkey->time += k * framestep; | hkey->time += k * framestep; | ||||
| hkey->weight = 1.f - (float)k / (float)(pset->totaddkey - 1); | hkey->weight = 1.f - (float)k / (float)(pset->totaddkey - 1); | ||||
| } | } | ||||
| } | } | ||||
| for (k = 0, hkey = pa->hair; k < pset->totaddkey; k++, hkey++) { | for (k = 0, hkey = pa->hair; k < pset->totaddkey; k++, hkey++) { | ||||
| psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, pa, hairmat); | psys_mat_hair_to_global(ob, mesh_final, psys->part->from, pa, hairmat); | ||||
| invert_m4_m4(imat, hairmat); | invert_m4_m4(imat, hairmat); | ||||
| mul_m4_v3(imat, hkey->co); | mul_m4_v3(imat, hkey->co); | ||||
| } | } | ||||
| } | } | ||||
| if (tree) { | if (tree) { | ||||
| BLI_kdtree_3d_free(tree); | BLI_kdtree_3d_free(tree); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | for (step = 1; step <= tot_steps; step++) { | ||||
| if (pset->flag & PE_KEEP_LENGTHS) { | if (pset->flag & PE_KEEP_LENGTHS) { | ||||
| recalc_lengths(edit); | recalc_lengths(edit); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case PE_BRUSH_PUFF: { | case PE_BRUSH_PUFF: { | ||||
| if (edit->psys) { | if (edit->psys) { | ||||
| data.mesh = psmd_eval->mesh_final; | data.mesh = BKE_particle_modifier_mesh_final_get(psmd_eval); | ||||
| data.mval = mval; | data.mval = mval; | ||||
| data.rad = pe_brush_size_get(scene, brush); | data.rad = pe_brush_size_get(scene, brush); | ||||
| data.select = selected; | data.select = selected; | ||||
| data.pufffac = (brush->strength - 0.5f) * 2.0f; | data.pufffac = (brush->strength - 0.5f) * 2.0f; | ||||
| if (data.pufffac < 0.0f) { | if (data.pufffac < 0.0f) { | ||||
| data.pufffac = 1.0f - 9.0f * data.pufffac; | data.pufffac = 1.0f - 9.0f * data.pufffac; | ||||
| } | } | ||||
| Show All 40 Lines | for (step = 1; step <= tot_steps; step++) { | ||||
| mul_v3_fl(data.vec, 1.0f / (float)data.tot); | mul_v3_fl(data.vec, 1.0f / (float)data.tot); | ||||
| foreach_mouse_hit_key(&data, brush_smooth_do, selected); | foreach_mouse_hit_key(&data, brush_smooth_do, selected); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case PE_BRUSH_WEIGHT: { | case PE_BRUSH_WEIGHT: { | ||||
| if (edit->psys) { | if (edit->psys) { | ||||
| data.mesh = psmd_eval->mesh_final; | data.mesh = BKE_particle_modifier_mesh_final_get(psmd_eval); | ||||
| data.mval = mval; | data.mval = mval; | ||||
| data.rad = pe_brush_size_get(scene, brush); | data.rad = pe_brush_size_get(scene, brush); | ||||
| data.weightfac = brush->strength; /* note that this will never be zero */ | data.weightfac = brush->strength; /* note that this will never be zero */ | ||||
| foreach_mouse_hit_key(&data, BKE_brush_weight_get, selected); | foreach_mouse_hit_key(&data, BKE_brush_weight_get, selected); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 357 Lines • ▼ Show 20 Lines | int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3]) | ||||
| } | } | ||||
| else { | else { | ||||
| unit_m4(mat); | unit_m4(mat); | ||||
| } | } | ||||
| LOOP_VISIBLE_POINTS | LOOP_VISIBLE_POINTS | ||||
| { | { | ||||
| if (psys) { | if (psys) { | ||||
| psys_mat_hair_to_global( | Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval); | ||||
| ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat); | psys_mat_hair_to_global(ob, mesh_final, psys->part->from, psys->particles + p, mat); | ||||
| } | } | ||||
| LOOP_SELECTED_KEYS | LOOP_SELECTED_KEYS | ||||
| { | { | ||||
| copy_v3_v3(co, key->co); | copy_v3_v3(co, key->co); | ||||
| mul_m4_v3(mat, co); | mul_m4_v3(mat, co); | ||||
| DO_MINMAX(co, min, max); | DO_MINMAX(co, min, max); | ||||
| ok = 1; | ok = 1; | ||||
| Show All 24 Lines | void PE_create_particle_edit( | ||||
| HairKey *hkey; | HairKey *hkey; | ||||
| int totpoint; | int totpoint; | ||||
| if (psmd != NULL) { | if (psmd != NULL) { | ||||
| psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(ob_eval, psmd->modifier.name); | psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(ob_eval, psmd->modifier.name); | ||||
| } | } | ||||
| /* no psmd->dm happens in case particle system modifier is not enabled */ | /* no psmd->dm happens in case particle system modifier is not enabled */ | ||||
| if (!(psys && psmd && psmd_eval->mesh_final) && !cache) { | Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval); | ||||
| if (!(psys && psmd && mesh_final) && !cache) { | |||||
| return; | return; | ||||
| } | } | ||||
| if (cache && cache->flag & PTCACHE_DISK_CACHE) { | if (cache && cache->flag & PTCACHE_DISK_CACHE) { | ||||
| return; | return; | ||||
| } | } | ||||
| if (psys == NULL && (cache && BLI_listbase_is_empty(&cache->mem_cache))) { | if (psys == NULL && (cache && BLI_listbase_is_empty(&cache->mem_cache))) { | ||||
| ▲ Show 20 Lines • Show All 381 Lines • Show Last 20 Lines | |||||