|
Blender
V2.59
|
00001 /* 00002 * $Id: particle_object.c 35362 2011-03-05 10:29:10Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2009 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * Contributor(s): Blender Foundation 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <stdlib.h> 00034 #include <string.h> 00035 00036 #include "MEM_guardedalloc.h" 00037 00038 #include "DNA_meshdata_types.h" 00039 #include "DNA_modifier_types.h" 00040 #include "DNA_scene_types.h" 00041 00042 #include "BLI_math.h" 00043 #include "BLI_listbase.h" 00044 #include "BLI_utildefines.h" 00045 00046 #include "BKE_context.h" 00047 #include "BKE_depsgraph.h" 00048 #include "BKE_DerivedMesh.h" 00049 #include "BKE_cdderivedmesh.h" 00050 #include "BKE_global.h" 00051 #include "BKE_main.h" 00052 #include "BKE_particle.h" 00053 #include "BKE_pointcache.h" 00054 00055 00056 #include "RNA_access.h" 00057 #include "RNA_define.h" 00058 00059 #include "WM_api.h" 00060 #include "WM_types.h" 00061 00062 #include "ED_particle.h" 00063 #include "ED_screen.h" 00064 00065 #include "physics_intern.h" 00066 00067 /********************** particle system slot operators *********************/ 00068 00069 static int particle_system_add_exec(bContext *C, wmOperator *UNUSED(op)) 00070 { 00071 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 00072 Scene *scene = CTX_data_scene(C); 00073 00074 if(!scene || !ob) 00075 return OPERATOR_CANCELLED; 00076 00077 object_add_particle_system(scene, ob, NULL); 00078 00079 WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); 00080 WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob); 00081 00082 return OPERATOR_FINISHED; 00083 } 00084 00085 void OBJECT_OT_particle_system_add(wmOperatorType *ot) 00086 { 00087 /* identifiers */ 00088 ot->name= "Add Particle System Slot"; 00089 ot->idname= "OBJECT_OT_particle_system_add"; 00090 ot->description="Add a particle system"; 00091 00092 /* api callbacks */ 00093 ot->poll= ED_operator_object_active_editable; 00094 ot->exec= particle_system_add_exec; 00095 00096 /* flags */ 00097 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00098 } 00099 00100 static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op)) 00101 { 00102 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 00103 Scene *scene = CTX_data_scene(C); 00104 int mode_orig = ob->mode; 00105 if(!scene || !ob) 00106 return OPERATOR_CANCELLED; 00107 00108 object_remove_particle_system(scene, ob); 00109 00110 /* possible this isn't the active object 00111 * object_remove_particle_system() clears the mode on the last psys 00112 * */ 00113 if(mode_orig & OB_MODE_PARTICLE_EDIT) 00114 if((ob->mode & OB_MODE_PARTICLE_EDIT)==0) 00115 if(scene->basact && scene->basact->object==ob) 00116 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL); 00117 00118 WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); 00119 WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob); 00120 00121 return OPERATOR_FINISHED; 00122 } 00123 00124 void OBJECT_OT_particle_system_remove(wmOperatorType *ot) 00125 { 00126 /* identifiers */ 00127 ot->name= "Remove Particle System Slot"; 00128 ot->idname= "OBJECT_OT_particle_system_remove"; 00129 ot->description="Remove the selected particle system"; 00130 00131 /* api callbacks */ 00132 ot->poll= ED_operator_object_active_editable; 00133 ot->exec= particle_system_remove_exec; 00134 00135 /* flags */ 00136 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00137 } 00138 00139 /********************** new particle settings operator *********************/ 00140 00141 static int psys_poll(bContext *C) 00142 { 00143 PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); 00144 return (ptr.data != NULL); 00145 } 00146 00147 static int new_particle_settings_exec(bContext *C, wmOperator *UNUSED(op)) 00148 { 00149 Scene *scene = CTX_data_scene(C); 00150 Main *bmain= CTX_data_main(C); 00151 ParticleSystem *psys; 00152 ParticleSettings *part = NULL; 00153 Object *ob; 00154 PointerRNA ptr; 00155 00156 ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); 00157 00158 psys = ptr.data; 00159 00160 /* add or copy particle setting */ 00161 if(psys->part) 00162 part= psys_copy_settings(psys->part); 00163 else 00164 part= psys_new_settings("ParticleSettings", bmain); 00165 00166 ob= ptr.id.data; 00167 00168 if(psys->part) 00169 psys->part->id.us--; 00170 00171 psys->part = part; 00172 00173 psys_check_boid_data(psys); 00174 00175 DAG_scene_sort(bmain, scene); 00176 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 00177 00178 WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); 00179 00180 return OPERATOR_FINISHED; 00181 } 00182 00183 void PARTICLE_OT_new(wmOperatorType *ot) 00184 { 00185 /* identifiers */ 00186 ot->name= "New Particle Settings"; 00187 ot->idname= "PARTICLE_OT_new"; 00188 ot->description="Add new particle settings"; 00189 00190 /* api callbacks */ 00191 ot->exec= new_particle_settings_exec; 00192 ot->poll= psys_poll; 00193 00194 /* flags */ 00195 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00196 } 00197 00198 /********************** keyed particle target operators *********************/ 00199 00200 static int new_particle_target_exec(bContext *C, wmOperator *UNUSED(op)) 00201 { 00202 Main *bmain = CTX_data_main(C); 00203 Scene *scene = CTX_data_scene(C); 00204 PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); 00205 ParticleSystem *psys= ptr.data; 00206 Object *ob = ptr.id.data; 00207 00208 ParticleTarget *pt; 00209 00210 if(!psys) 00211 return OPERATOR_CANCELLED; 00212 00213 pt = psys->targets.first; 00214 for(; pt; pt=pt->next) 00215 pt->flag &= ~PTARGET_CURRENT; 00216 00217 pt = MEM_callocN(sizeof(ParticleTarget), "keyed particle target"); 00218 00219 pt->flag |= PTARGET_CURRENT; 00220 pt->psys = 1; 00221 00222 BLI_addtail(&psys->targets, pt); 00223 00224 DAG_scene_sort(bmain, scene); 00225 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 00226 00227 WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); 00228 00229 return OPERATOR_FINISHED; 00230 } 00231 00232 void PARTICLE_OT_new_target(wmOperatorType *ot) 00233 { 00234 /* identifiers */ 00235 ot->name= "New Particle Target"; 00236 ot->idname= "PARTICLE_OT_new_target"; 00237 ot->description="Add a new particle target"; 00238 00239 /* api callbacks */ 00240 ot->exec= new_particle_target_exec; 00241 00242 /* flags */ 00243 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00244 } 00245 00246 static int remove_particle_target_exec(bContext *C, wmOperator *UNUSED(op)) 00247 { 00248 Main *bmain = CTX_data_main(C); 00249 Scene *scene = CTX_data_scene(C); 00250 PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); 00251 ParticleSystem *psys= ptr.data; 00252 Object *ob = ptr.id.data; 00253 00254 ParticleTarget *pt; 00255 00256 if(!psys) 00257 return OPERATOR_CANCELLED; 00258 00259 pt = psys->targets.first; 00260 for(; pt; pt=pt->next) { 00261 if(pt->flag & PTARGET_CURRENT) { 00262 BLI_remlink(&psys->targets, pt); 00263 MEM_freeN(pt); 00264 break; 00265 } 00266 00267 } 00268 pt = psys->targets.last; 00269 00270 if(pt) 00271 pt->flag |= PTARGET_CURRENT; 00272 00273 DAG_scene_sort(bmain, scene); 00274 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 00275 00276 WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); 00277 00278 return OPERATOR_FINISHED; 00279 } 00280 00281 void PARTICLE_OT_target_remove(wmOperatorType *ot) 00282 { 00283 /* identifiers */ 00284 ot->name= "Remove Particle Target"; 00285 ot->idname= "PARTICLE_OT_target_remove"; 00286 ot->description="Remove the selected particle target"; 00287 00288 /* api callbacks */ 00289 ot->exec= remove_particle_target_exec; 00290 00291 /* flags */ 00292 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00293 } 00294 00295 /************************ move up particle target operator *********************/ 00296 00297 static int target_move_up_exec(bContext *C, wmOperator *UNUSED(op)) 00298 { 00299 PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); 00300 ParticleSystem *psys= ptr.data; 00301 Object *ob = ptr.id.data; 00302 ParticleTarget *pt; 00303 00304 if(!psys) 00305 return OPERATOR_CANCELLED; 00306 00307 pt = psys->targets.first; 00308 for(; pt; pt=pt->next) { 00309 if(pt->flag & PTARGET_CURRENT && pt->prev) { 00310 BLI_remlink(&psys->targets, pt); 00311 BLI_insertlink(&psys->targets, pt->prev->prev, pt); 00312 00313 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 00314 WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); 00315 break; 00316 } 00317 } 00318 00319 return OPERATOR_FINISHED; 00320 } 00321 00322 void PARTICLE_OT_target_move_up(wmOperatorType *ot) 00323 { 00324 ot->name= "Move Up Target"; 00325 ot->idname= "PARTICLE_OT_target_move_up"; 00326 ot->description= "Move particle target up in the list"; 00327 00328 ot->exec= target_move_up_exec; 00329 00330 /* flags */ 00331 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00332 } 00333 00334 /************************ move down particle target operator *********************/ 00335 00336 static int target_move_down_exec(bContext *C, wmOperator *UNUSED(op)) 00337 { 00338 PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); 00339 ParticleSystem *psys= ptr.data; 00340 Object *ob = ptr.id.data; 00341 ParticleTarget *pt; 00342 00343 if(!psys) 00344 return OPERATOR_CANCELLED; 00345 pt = psys->targets.first; 00346 for(; pt; pt=pt->next) { 00347 if(pt->flag & PTARGET_CURRENT && pt->next) { 00348 BLI_remlink(&psys->targets, pt); 00349 BLI_insertlink(&psys->targets, pt->next, pt); 00350 00351 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 00352 WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); 00353 break; 00354 } 00355 } 00356 00357 return OPERATOR_FINISHED; 00358 } 00359 00360 void PARTICLE_OT_target_move_down(wmOperatorType *ot) 00361 { 00362 ot->name= "Move Down Target"; 00363 ot->idname= "PARTICLE_OT_target_move_down"; 00364 ot->description= "Move particle target down in the list"; 00365 00366 ot->exec= target_move_down_exec; 00367 00368 /* flags */ 00369 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00370 } 00371 00372 /************************ move up particle dupliweight operator *********************/ 00373 00374 static int dupliob_move_up_exec(bContext *C, wmOperator *UNUSED(op)) 00375 { 00376 PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); 00377 ParticleSystem *psys= ptr.data; 00378 ParticleSettings *part; 00379 ParticleDupliWeight *dw; 00380 00381 if(!psys) 00382 return OPERATOR_CANCELLED; 00383 00384 part = psys->part; 00385 for(dw=part->dupliweights.first; dw; dw=dw->next) { 00386 if(dw->flag & PART_DUPLIW_CURRENT && dw->prev) { 00387 BLI_remlink(&part->dupliweights, dw); 00388 BLI_insertlink(&part->dupliweights, dw->prev->prev, dw); 00389 00390 WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL); 00391 break; 00392 } 00393 } 00394 00395 return OPERATOR_FINISHED; 00396 } 00397 00398 void PARTICLE_OT_dupliob_move_up(wmOperatorType *ot) 00399 { 00400 ot->name= "Move Up Dupli Object"; 00401 ot->idname= "PARTICLE_OT_dupliob_move_up"; 00402 ot->description= "Move dupli object up in the list"; 00403 00404 ot->exec= dupliob_move_up_exec; 00405 00406 /* flags */ 00407 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00408 } 00409 00410 /********************** particle dupliweight operators *********************/ 00411 00412 static int copy_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op)) 00413 { 00414 PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); 00415 ParticleSystem *psys= ptr.data; 00416 ParticleSettings *part; 00417 ParticleDupliWeight *dw; 00418 00419 if(!psys) 00420 return OPERATOR_CANCELLED; 00421 part = psys->part; 00422 for(dw=part->dupliweights.first; dw; dw=dw->next) { 00423 if(dw->flag & PART_DUPLIW_CURRENT) { 00424 dw->flag &= ~PART_DUPLIW_CURRENT; 00425 dw = MEM_dupallocN(dw); 00426 dw->flag |= PART_DUPLIW_CURRENT; 00427 BLI_addhead(&part->dupliweights, dw); 00428 00429 WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL); 00430 break; 00431 } 00432 } 00433 00434 return OPERATOR_FINISHED; 00435 } 00436 00437 void PARTICLE_OT_dupliob_copy(wmOperatorType *ot) 00438 { 00439 /* identifiers */ 00440 ot->name= "Copy Particle Dupliob"; 00441 ot->idname= "PARTICLE_OT_dupliob_copy"; 00442 ot->description="Duplicate the current dupliobject"; 00443 00444 /* api callbacks */ 00445 ot->exec= copy_particle_dupliob_exec; 00446 00447 /* flags */ 00448 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00449 } 00450 00451 static int remove_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op)) 00452 { 00453 PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); 00454 ParticleSystem *psys= ptr.data; 00455 ParticleSettings *part; 00456 ParticleDupliWeight *dw; 00457 00458 if(!psys) 00459 return OPERATOR_CANCELLED; 00460 00461 part = psys->part; 00462 for(dw=part->dupliweights.first; dw; dw=dw->next) { 00463 if(dw->flag & PART_DUPLIW_CURRENT) { 00464 BLI_remlink(&part->dupliweights, dw); 00465 MEM_freeN(dw); 00466 break; 00467 } 00468 00469 } 00470 dw = part->dupliweights.last; 00471 00472 if(dw) 00473 dw->flag |= PART_DUPLIW_CURRENT; 00474 00475 WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL); 00476 00477 return OPERATOR_FINISHED; 00478 } 00479 00480 void PARTICLE_OT_dupliob_remove(wmOperatorType *ot) 00481 { 00482 /* identifiers */ 00483 ot->name= "Remove Particle Dupliobject"; 00484 ot->idname= "PARTICLE_OT_dupliob_remove"; 00485 ot->description="Remove the selected dupliobject"; 00486 00487 /* api callbacks */ 00488 ot->exec= remove_particle_dupliob_exec; 00489 00490 /* flags */ 00491 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00492 } 00493 00494 /************************ move down particle dupliweight operator *********************/ 00495 00496 static int dupliob_move_down_exec(bContext *C, wmOperator *UNUSED(op)) 00497 { 00498 PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); 00499 ParticleSystem *psys= ptr.data; 00500 ParticleSettings *part; 00501 ParticleDupliWeight *dw; 00502 00503 if(!psys) 00504 return OPERATOR_CANCELLED; 00505 00506 part = psys->part; 00507 for(dw=part->dupliweights.first; dw; dw=dw->next) { 00508 if(dw->flag & PART_DUPLIW_CURRENT && dw->next) { 00509 BLI_remlink(&part->dupliweights, dw); 00510 BLI_insertlink(&part->dupliweights, dw->next, dw); 00511 00512 WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL); 00513 break; 00514 } 00515 } 00516 00517 return OPERATOR_FINISHED; 00518 } 00519 00520 void PARTICLE_OT_dupliob_move_down(wmOperatorType *ot) 00521 { 00522 ot->name= "Move Down Dupli Object"; 00523 ot->idname= "PARTICLE_OT_dupliob_move_down"; 00524 ot->description= "Move dupli object down in the list"; 00525 00526 ot->exec= dupliob_move_down_exec; 00527 00528 /* flags */ 00529 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00530 } 00531 00532 /************************ connect/disconnect hair operators *********************/ 00533 00534 static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys) 00535 { 00536 ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys); 00537 ParticleEditSettings *pset= PE_settings(scene); 00538 ParticleData *pa; 00539 PTCacheEdit *edit; 00540 PTCacheEditPoint *point; 00541 PTCacheEditKey *ekey = NULL; 00542 HairKey *key; 00543 int i, k; 00544 float hairmat[4][4]; 00545 00546 if(!ob || !psys || psys->flag & PSYS_GLOBAL_HAIR) 00547 return; 00548 00549 if(!psys->part || psys->part->type != PART_HAIR) 00550 return; 00551 00552 edit = psys->edit; 00553 point= edit ? edit->points : NULL; 00554 00555 for(i=0, pa=psys->particles; i<psys->totpart; i++,pa++) { 00556 if(point) { 00557 ekey = point->keys; 00558 point++; 00559 } 00560 00561 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); 00562 00563 for(k=0,key=pa->hair; k<pa->totkey; k++,key++) { 00564 mul_m4_v3(hairmat,key->co); 00565 00566 if(ekey) { 00567 ekey->flag &= ~PEK_USE_WCO; 00568 ekey++; 00569 } 00570 } 00571 } 00572 00573 psys_free_path_cache(psys, psys->edit); 00574 00575 psys->flag |= PSYS_GLOBAL_HAIR; 00576 00577 if(ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_PUFF)) 00578 pset->brushtype = PE_BRUSH_NONE; 00579 00580 PE_update_object(scene, ob, 0); 00581 } 00582 00583 static int disconnect_hair_exec(bContext *C, wmOperator *op) 00584 { 00585 Scene *scene= CTX_data_scene(C); 00586 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 00587 PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); 00588 ParticleSystem *psys= NULL; 00589 int all = RNA_boolean_get(op->ptr, "all"); 00590 00591 if(!ob) 00592 return OPERATOR_CANCELLED; 00593 00594 if(all) { 00595 for(psys=ob->particlesystem.first; psys; psys=psys->next) { 00596 disconnect_hair(scene, ob, psys); 00597 } 00598 } 00599 else { 00600 psys = ptr.data; 00601 disconnect_hair(scene, ob, psys); 00602 } 00603 00604 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 00605 WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); 00606 00607 return OPERATOR_FINISHED; 00608 } 00609 00610 void PARTICLE_OT_disconnect_hair(wmOperatorType *ot) 00611 { 00612 ot->name= "Disconnect Hair"; 00613 ot->description= "Disconnect hair from the emitter mesh"; 00614 ot->idname= "PARTICLE_OT_disconnect_hair"; 00615 00616 ot->exec= disconnect_hair_exec; 00617 00618 /* flags */ 00619 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00620 00621 RNA_def_boolean(ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh"); 00622 } 00623 00624 static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) 00625 { 00626 ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys); 00627 ParticleData *pa; 00628 PTCacheEdit *edit; 00629 PTCacheEditPoint *point; 00630 PTCacheEditKey *ekey = NULL; 00631 HairKey *key; 00632 BVHTreeFromMesh bvhtree= {NULL}; 00633 BVHTreeNearest nearest; 00634 MFace *mface; 00635 DerivedMesh *dm = NULL; 00636 int numverts; 00637 int i, k; 00638 float hairmat[4][4], imat[4][4]; 00639 float v[4][3], vec[3]; 00640 00641 if(!psys || !psys->part || psys->part->type != PART_HAIR) 00642 return; 00643 00644 edit= psys->edit; 00645 point= edit ? edit->points : NULL; 00646 00647 if(psmd->dm->deformedOnly) 00648 /* we don't want to mess up psmd->dm when converting to global coordinates below */ 00649 dm= CDDM_copy(psmd->dm); 00650 else 00651 dm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); 00652 00653 numverts = dm->getNumVerts (dm); 00654 00655 /* convert to global coordinates */ 00656 for (i=0; i<numverts; i++) 00657 mul_m4_v3(ob->obmat, CDDM_get_vert(dm, i)->co); 00658 00659 bvhtree_from_mesh_faces(&bvhtree, dm, 0.0, 2, 6); 00660 00661 for(i=0, pa= psys->particles; i<psys->totpart; i++,pa++) { 00662 key = pa->hair; 00663 00664 nearest.index = -1; 00665 nearest.dist = FLT_MAX; 00666 00667 BLI_bvhtree_find_nearest(bvhtree.tree, key->co, &nearest, bvhtree.nearest_callback, &bvhtree); 00668 00669 if(nearest.index == -1) { 00670 if (G.f & G_DEBUG) 00671 printf("No nearest point found for hair root!"); 00672 continue; 00673 } 00674 00675 mface = CDDM_get_face(dm,nearest.index); 00676 00677 copy_v3_v3(v[0], CDDM_get_vert(dm,mface->v1)->co); 00678 copy_v3_v3(v[1], CDDM_get_vert(dm,mface->v2)->co); 00679 copy_v3_v3(v[2], CDDM_get_vert(dm,mface->v3)->co); 00680 if(mface->v4) { 00681 copy_v3_v3(v[3], CDDM_get_vert(dm,mface->v4)->co); 00682 interp_weights_poly_v3( pa->fuv,v, 4, nearest.co); 00683 } 00684 else 00685 interp_weights_poly_v3( pa->fuv,v, 3, nearest.co); 00686 00687 pa->num = nearest.index; 00688 pa->num_dmcache = psys_particle_dm_face_lookup(ob,psmd->dm,pa->num,pa->fuv,NULL); 00689 00690 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); 00691 invert_m4_m4(imat,hairmat); 00692 00693 VECSUB(vec, nearest.co, key->co); 00694 00695 if(point) { 00696 ekey = point->keys; 00697 point++; 00698 } 00699 00700 for(k=0,key=pa->hair; k<pa->totkey; k++,key++) { 00701 VECADD(key->co, key->co, vec); 00702 mul_m4_v3(imat,key->co); 00703 00704 if(ekey) { 00705 ekey->flag |= PEK_USE_WCO; 00706 ekey++; 00707 } 00708 } 00709 } 00710 00711 free_bvhtree_from_mesh(&bvhtree); 00712 dm->release(dm); 00713 00714 psys_free_path_cache(psys, psys->edit); 00715 00716 psys->flag &= ~PSYS_GLOBAL_HAIR; 00717 00718 PE_update_object(scene, ob, 0); 00719 } 00720 00721 static int connect_hair_exec(bContext *C, wmOperator *op) 00722 { 00723 Scene *scene= CTX_data_scene(C); 00724 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 00725 PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); 00726 ParticleSystem *psys= NULL; 00727 int all = RNA_boolean_get(op->ptr, "all"); 00728 00729 if(!ob) 00730 return OPERATOR_CANCELLED; 00731 00732 if(all) { 00733 for(psys=ob->particlesystem.first; psys; psys=psys->next) { 00734 connect_hair(scene, ob, psys); 00735 } 00736 } 00737 else { 00738 psys = ptr.data; 00739 connect_hair(scene, ob, psys); 00740 } 00741 00742 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 00743 WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); 00744 00745 return OPERATOR_FINISHED; 00746 } 00747 00748 void PARTICLE_OT_connect_hair(wmOperatorType *ot) 00749 { 00750 ot->name= "Connect Hair"; 00751 ot->description= "Connect hair to the emitter mesh"; 00752 ot->idname= "PARTICLE_OT_connect_hair"; 00753 00754 ot->exec= connect_hair_exec; 00755 00756 /* flags */ 00757 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00758 00759 RNA_def_boolean(ot->srna, "all", 0, "All hair", "Connect all hair systems to the emitter mesh"); 00760 } 00761