Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): Blender Foundation, Campbell Barton 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 */ 00025 00032 #include <math.h> 00033 #include <string.h> 00034 00035 #include "MEM_guardedalloc.h" 00036 00037 #include "BLI_blenlib.h" 00038 #include "BLI_math.h" 00039 #include "BLI_heap.h" 00040 #include "BLI_edgehash.h" 00041 #include "BLI_editVert.h" 00042 #include "BLI_utildefines.h" 00043 00044 #include "IMB_imbuf_types.h" 00045 #include "IMB_imbuf.h" 00046 00047 #include "DNA_meshdata_types.h" 00048 #include "DNA_object_types.h" 00049 #include "DNA_scene_types.h" 00050 00051 #include "BKE_DerivedMesh.h" 00052 #include "BKE_global.h" 00053 #include "BKE_mesh.h" 00054 #include "BKE_context.h" 00055 00056 #include "BIF_gl.h" 00057 00058 #include "ED_mesh.h" 00059 #include "ED_screen.h" 00060 #include "ED_view3d.h" 00061 00062 #include "WM_api.h" 00063 #include "WM_types.h" 00064 00065 /* own include */ 00066 #include "mesh_intern.h" 00067 00068 /* copy the face flags, most importantly selection from the mesh to the final derived mesh, 00069 * use in object mode when selecting faces (while painting) */ 00070 void paintface_flush_flags(Object *ob) 00071 { 00072 Mesh *me= get_mesh(ob); 00073 DerivedMesh *dm= ob->derivedFinal; 00074 MFace *faces, *mf, *mf_orig; 00075 int *index_array = NULL; 00076 int totface; 00077 int i; 00078 00079 if(me==NULL || dm==NULL) 00080 return; 00081 00082 index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX); 00083 00084 if(!index_array) 00085 return; 00086 00087 faces = dm->getFaceArray(dm); 00088 totface = dm->getNumFaces(dm); 00089 00090 mf= faces; 00091 00092 for (i= 0; i<totface; i++, mf++) { /* loop over derived mesh faces */ 00093 mf_orig= me->mface + index_array[i]; 00094 mf->flag= mf_orig->flag; 00095 } 00096 } 00097 00098 /* returns 0 if not found, otherwise 1 */ 00099 static int facesel_face_pick(struct bContext *C, Mesh *me, const int mval[2], unsigned int *index, short rect) 00100 { 00101 ViewContext vc; 00102 view3d_set_viewcontext(C, &vc); 00103 00104 if (!me || me->totface==0) 00105 return 0; 00106 00107 // XXX if (v3d->flag & V3D_INVALID_BACKBUF) { 00108 // XXX drawview.c! check_backbuf(); 00109 // XXX persp(PERSP_VIEW); 00110 // XXX } 00111 00112 if (rect) { 00113 /* sample rect to increase changes of selecting, so that when clicking 00114 on an edge in the backbuf, we can still select a face */ 00115 00116 int dist; 00117 *index = view3d_sample_backbuf_rect(&vc, mval, 3, 1, me->totface+1, &dist,0,NULL, NULL); 00118 } 00119 else { 00120 /* sample only on the exact position */ 00121 *index = view3d_sample_backbuf(&vc, mval[0], mval[1]); 00122 } 00123 00124 if ((*index)<=0 || (*index)>(unsigned int)me->totface) 00125 return 0; 00126 00127 (*index)--; 00128 00129 return 1; 00130 } 00131 00132 /* last_sel, use em->act_face otherwise get the last selected face in the editselections 00133 * at the moment, last_sel is mainly useful for gaking sure the space image dosnt flicker */ 00134 MTFace *EM_get_active_mtface(EditMesh *em, EditFace **act_efa, MCol **mcol, int sloppy) 00135 { 00136 EditFace *efa = NULL; 00137 00138 if(!EM_texFaceCheck(em)) 00139 return NULL; 00140 00141 efa = EM_get_actFace(em, sloppy); 00142 00143 if (efa) { 00144 if (mcol) { 00145 if (CustomData_has_layer(&em->fdata, CD_MCOL)) 00146 *mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); 00147 else 00148 *mcol = NULL; 00149 } 00150 if (act_efa) *act_efa = efa; 00151 return CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00152 } 00153 if (act_efa) *act_efa= NULL; 00154 if(mcol) *mcol = NULL; 00155 return NULL; 00156 } 00157 00158 void paintface_hide(Object *ob, const int unselected) 00159 { 00160 Mesh *me; 00161 MFace *mface; 00162 int a; 00163 00164 me= get_mesh(ob); 00165 if(me==NULL || me->totface==0) return; 00166 00167 mface= me->mface; 00168 a= me->totface; 00169 while(a--) { 00170 if((mface->flag & ME_HIDE) == 0) { 00171 if(unselected) { 00172 if( (mface->flag & ME_FACE_SEL)==0) mface->flag |= ME_HIDE; 00173 } 00174 else { 00175 if( (mface->flag & ME_FACE_SEL)) mface->flag |= ME_HIDE; 00176 } 00177 } 00178 if(mface->flag & ME_HIDE) mface->flag &= ~ME_FACE_SEL; 00179 00180 mface++; 00181 } 00182 00183 paintface_flush_flags(ob); 00184 } 00185 00186 00187 void paintface_reveal(Object *ob) 00188 { 00189 Mesh *me; 00190 MFace *mface; 00191 int a; 00192 00193 me= get_mesh(ob); 00194 if(me==NULL || me->totface==0) return; 00195 00196 mface= me->mface; 00197 a= me->totface; 00198 while(a--) { 00199 if(mface->flag & ME_HIDE) { 00200 mface->flag |= ME_FACE_SEL; 00201 mface->flag -= ME_HIDE; 00202 } 00203 mface++; 00204 } 00205 00206 paintface_flush_flags(ob); 00207 } 00208 00209 /* Set tface seams based on edge data, uses hash table to find seam edges. */ 00210 00211 static void hash_add_face(EdgeHash *ehash, MFace *mf) 00212 { 00213 BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL); 00214 BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL); 00215 if(mf->v4) { 00216 BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL); 00217 BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL); 00218 } 00219 else 00220 BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL); 00221 } 00222 00223 00224 static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index) 00225 { 00226 MFace *mf; 00227 int a, doit=1, mark=0; 00228 char *linkflag; 00229 EdgeHash *ehash, *seamhash; 00230 MEdge *med; 00231 00232 ehash= BLI_edgehash_new(); 00233 seamhash = BLI_edgehash_new(); 00234 linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv"); 00235 00236 for(med=me->medge, a=0; a < me->totedge; a++, med++) 00237 if(med->flag & ME_SEAM) 00238 BLI_edgehash_insert(seamhash, med->v1, med->v2, NULL); 00239 00240 if (mode==0 || mode==1) { 00241 /* only put face under cursor in array */ 00242 mf= ((MFace*)me->mface) + index; 00243 hash_add_face(ehash, mf); 00244 linkflag[index]= 1; 00245 } 00246 else { 00247 /* fill array by selection */ 00248 mf= me->mface; 00249 for(a=0; a<me->totface; a++, mf++) { 00250 if(mf->flag & ME_HIDE); 00251 else if(mf->flag & ME_FACE_SEL) { 00252 hash_add_face(ehash, mf); 00253 linkflag[a]= 1; 00254 } 00255 } 00256 } 00257 00258 while(doit) { 00259 doit= 0; 00260 00261 /* expand selection */ 00262 mf= me->mface; 00263 for(a=0; a<me->totface; a++, mf++) { 00264 if(mf->flag & ME_HIDE) 00265 continue; 00266 00267 if(!linkflag[a]) { 00268 mark= 0; 00269 00270 if(!BLI_edgehash_haskey(seamhash, mf->v1, mf->v2)) 00271 if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2)) 00272 mark= 1; 00273 if(!BLI_edgehash_haskey(seamhash, mf->v2, mf->v3)) 00274 if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3)) 00275 mark= 1; 00276 if(mf->v4) { 00277 if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v4)) 00278 if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4)) 00279 mark= 1; 00280 if(!BLI_edgehash_haskey(seamhash, mf->v4, mf->v1)) 00281 if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1)) 00282 mark= 1; 00283 } 00284 else if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v1)) 00285 if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1)) 00286 mark = 1; 00287 00288 if(mark) { 00289 linkflag[a]= 1; 00290 hash_add_face(ehash, mf); 00291 doit= 1; 00292 } 00293 } 00294 } 00295 00296 } 00297 00298 BLI_edgehash_free(ehash, NULL); 00299 BLI_edgehash_free(seamhash, NULL); 00300 00301 if(mode==0 || mode==2) { 00302 for(a=0, mf=me->mface; a<me->totface; a++, mf++) 00303 if(linkflag[a]) 00304 mf->flag |= ME_FACE_SEL; 00305 else 00306 mf->flag &= ~ME_FACE_SEL; 00307 } 00308 else if(mode==1) { 00309 for(a=0, mf=me->mface; a<me->totface; a++, mf++) 00310 if(linkflag[a] && (mf->flag & ME_FACE_SEL)) 00311 break; 00312 00313 if (a<me->totface) { 00314 for(a=0, mf=me->mface; a<me->totface; a++, mf++) 00315 if(linkflag[a]) 00316 mf->flag &= ~ME_FACE_SEL; 00317 } 00318 else { 00319 for(a=0, mf=me->mface; a<me->totface; a++, mf++) 00320 if(linkflag[a]) 00321 mf->flag |= ME_FACE_SEL; 00322 } 00323 } 00324 00325 MEM_freeN(linkflag); 00326 } 00327 00328 void paintface_select_linked(bContext *UNUSED(C), Object *ob, int UNUSED(mval[2]), int mode) 00329 { 00330 Mesh *me; 00331 unsigned int index=0; 00332 00333 me = get_mesh(ob); 00334 if(me==NULL || me->totface==0) return; 00335 00336 if (mode==0 || mode==1) { 00337 // XXX - Causes glitches, not sure why 00338 /* 00339 if (!facesel_face_pick(C, me, mval, &index, 1)) 00340 return; 00341 */ 00342 } 00343 00344 select_linked_tfaces_with_seams(mode, me, index); 00345 00346 paintface_flush_flags(ob); 00347 } 00348 00349 void paintface_deselect_all_visible(Object *ob, int action, short flush_flags) 00350 { 00351 Mesh *me; 00352 MFace *mface; 00353 int a; 00354 00355 me= get_mesh(ob); 00356 if(me==NULL) return; 00357 00358 if(action == SEL_INVERT) { 00359 mface= me->mface; 00360 a= me->totface; 00361 while(a--) { 00362 if((mface->flag & ME_HIDE) == 0) { 00363 mface->flag ^= ME_FACE_SEL; 00364 } 00365 mface++; 00366 } 00367 } 00368 else { 00369 if (action == SEL_TOGGLE) { 00370 action = SEL_SELECT; 00371 00372 mface= me->mface; 00373 a= me->totface; 00374 while(a--) { 00375 if((mface->flag & ME_HIDE) == 0 && mface->flag & ME_FACE_SEL) { 00376 action = SEL_DESELECT; 00377 break; 00378 } 00379 mface++; 00380 } 00381 } 00382 00383 mface= me->mface; 00384 a= me->totface; 00385 while(a--) { 00386 if((mface->flag & ME_HIDE) == 0) { 00387 switch (action) { 00388 case SEL_SELECT: 00389 mface->flag |= ME_FACE_SEL; 00390 break; 00391 case SEL_DESELECT: 00392 mface->flag &= ~ME_FACE_SEL; 00393 break; 00394 case SEL_INVERT: 00395 mface->flag ^= ME_FACE_SEL; 00396 break; 00397 } 00398 } 00399 mface++; 00400 } 00401 } 00402 00403 if(flush_flags) { 00404 paintface_flush_flags(ob); 00405 } 00406 } 00407 00408 int paintface_minmax(Object *ob, float *min, float *max) 00409 { 00410 Mesh *me= get_mesh(ob); 00411 MFace *mf; 00412 MVert *mv; 00413 int a, ok=0; 00414 float vec[3]; 00415 00416 if(me==NULL) 00417 return ok; 00418 00419 mv= me->mvert; 00420 mf= me->mface; 00421 for (a=me->totface; a>0; a--, mf++) { 00422 if ((mf->flag & ME_HIDE || !(mf->flag & ME_FACE_SEL)) == 0) { 00423 int i= mf->v4 ? 3:2; 00424 do { 00425 mul_v3_m4v3(vec, ob->obmat, (mv + (*(&mf->v1 + i)))->co); 00426 DO_MINMAX(vec, min, max); 00427 } while (i--); 00428 ok= 1; 00429 } 00430 } 00431 return ok; 00432 } 00433 00434 /* ******************** edge loop shortest path ********************* */ 00435 00436 #define ME_SEAM_DONE 2 /* reuse this flag */ 00437 00438 static float edgetag_cut_cost(int e1, int e2, int vert) 00439 { 00440 EditVert *v = EM_get_vert_for_index(vert); 00441 EditEdge *eed1 = EM_get_edge_for_index(e1), *eed2 = EM_get_edge_for_index(e2); 00442 EditVert *v1 = EM_get_vert_for_index( (eed1->v1->tmp.l == vert)? eed1->v2->tmp.l: eed1->v1->tmp.l ); 00443 EditVert *v2 = EM_get_vert_for_index( (eed2->v1->tmp.l == vert)? eed2->v2->tmp.l: eed2->v1->tmp.l ); 00444 float cost, d1[3], d2[3]; 00445 00446 cost = len_v3v3(v1->co, v->co); 00447 cost += len_v3v3(v->co, v2->co); 00448 00449 sub_v3_v3v3(d1, v->co, v1->co); 00450 sub_v3_v3v3(d2, v2->co, v->co); 00451 00452 cost = cost + 0.5f*cost*(2.0f - fabsf(d1[0]*d2[0] + d1[1]*d2[1] + d1[2]*d2[2])); 00453 00454 return cost; 00455 } 00456 00457 static void edgetag_add_adjacent(Heap *heap, int mednum, int vertnum, int *nedges, int *edges, int *prevedge, float *cost) 00458 { 00459 int startadj, endadj = nedges[vertnum+1]; 00460 00461 for (startadj = nedges[vertnum]; startadj < endadj; startadj++) { 00462 int adjnum = edges[startadj]; 00463 EditEdge *eedadj = EM_get_edge_for_index(adjnum); 00464 float newcost; 00465 00466 if (eedadj->f2 & ME_SEAM_DONE) 00467 continue; 00468 00469 newcost = cost[mednum] + edgetag_cut_cost(mednum, adjnum, vertnum); 00470 00471 if (cost[adjnum] > newcost) { 00472 cost[adjnum] = newcost; 00473 prevedge[adjnum] = mednum; 00474 BLI_heap_insert(heap, newcost, SET_INT_IN_POINTER(adjnum)); 00475 } 00476 } 00477 } 00478 00479 void edgetag_context_set(Scene *scene, EditEdge *eed, int val) 00480 { 00481 00482 switch (scene->toolsettings->edge_mode) { 00483 case EDGE_MODE_SELECT: 00484 EM_select_edge(eed, val); 00485 break; 00486 case EDGE_MODE_TAG_SEAM: 00487 if (val) {eed->seam = 255;} 00488 else {eed->seam = 0;} 00489 break; 00490 case EDGE_MODE_TAG_SHARP: 00491 if (val) {eed->sharp = 1;} 00492 else {eed->sharp = 0;} 00493 break; 00494 case EDGE_MODE_TAG_CREASE: 00495 if (val) {eed->crease = 1.0f;} 00496 else {eed->crease = 0.0f;} 00497 break; 00498 case EDGE_MODE_TAG_BEVEL: 00499 if (val) {eed->bweight = 1.0f;} 00500 else {eed->bweight = 0.0f;} 00501 break; 00502 } 00503 } 00504 00505 int edgetag_context_check(Scene *scene, EditEdge *eed) 00506 { 00507 switch (scene->toolsettings->edge_mode) { 00508 case EDGE_MODE_SELECT: 00509 return (eed->f & SELECT) ? 1 : 0; 00510 case EDGE_MODE_TAG_SEAM: 00511 return eed->seam ? 1 : 0; 00512 case EDGE_MODE_TAG_SHARP: 00513 return eed->sharp ? 1 : 0; 00514 case EDGE_MODE_TAG_CREASE: 00515 return eed->crease ? 1 : 0; 00516 case EDGE_MODE_TAG_BEVEL: 00517 return eed->bweight ? 1 : 0; 00518 } 00519 return 0; 00520 } 00521 00522 00523 int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge *target) 00524 { 00525 EditEdge *eed; 00526 EditVert *ev; 00527 00528 Heap *heap; 00529 float *cost; 00530 int a, totvert=0, totedge=0, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0; 00531 00532 00533 /* we need the vert */ 00534 for (ev= em->verts.first, totvert=0; ev; ev= ev->next) { 00535 ev->tmp.l = totvert; 00536 totvert++; 00537 } 00538 00539 for (eed= em->edges.first; eed; eed = eed->next) { 00540 eed->f2 = 0; 00541 if (eed->h) { 00542 eed->f2 |= ME_SEAM_DONE; 00543 } 00544 eed->tmp.l = totedge; 00545 totedge++; 00546 } 00547 00548 /* alloc */ 00549 nedges = MEM_callocN(sizeof(*nedges)*totvert+1, "SeamPathNEdges"); 00550 edges = MEM_mallocN(sizeof(*edges)*totedge*2, "SeamPathEdges"); 00551 prevedge = MEM_mallocN(sizeof(*prevedge)*totedge, "SeamPathPrevious"); 00552 cost = MEM_mallocN(sizeof(*cost)*totedge, "SeamPathCost"); 00553 00554 /* count edges, compute adjacent edges offsets and fill adjacent edges */ 00555 for (eed= em->edges.first; eed; eed = eed->next) { 00556 nedges[eed->v1->tmp.l+1]++; 00557 nedges[eed->v2->tmp.l+1]++; 00558 } 00559 00560 for (a=1; a<totvert; a++) { 00561 int newswap = nedges[a+1]; 00562 nedges[a+1] = nedgeswap + nedges[a]; 00563 nedgeswap = newswap; 00564 } 00565 nedges[0] = nedges[1] = 0; 00566 00567 for (a=0, eed= em->edges.first; eed; a++, eed = eed->next) { 00568 edges[nedges[eed->v1->tmp.l+1]++] = a; 00569 edges[nedges[eed->v2->tmp.l+1]++] = a; 00570 00571 cost[a] = 1e20f; 00572 prevedge[a] = -1; 00573 } 00574 00575 /* regular dijkstra shortest path, but over edges instead of vertices */ 00576 heap = BLI_heap_new(); 00577 BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(source->tmp.l)); 00578 cost[source->tmp.l] = 0.0f; 00579 00580 EM_init_index_arrays(em, 1, 1, 0); 00581 00582 00583 while (!BLI_heap_empty(heap)) { 00584 mednum = GET_INT_FROM_POINTER(BLI_heap_popmin(heap)); 00585 eed = EM_get_edge_for_index( mednum ); 00586 00587 if (mednum == target->tmp.l) 00588 break; 00589 00590 if (eed->f2 & ME_SEAM_DONE) 00591 continue; 00592 00593 eed->f2 |= ME_SEAM_DONE; 00594 00595 edgetag_add_adjacent(heap, mednum, eed->v1->tmp.l, nedges, edges, prevedge, cost); 00596 edgetag_add_adjacent(heap, mednum, eed->v2->tmp.l, nedges, edges, prevedge, cost); 00597 } 00598 00599 00600 MEM_freeN(nedges); 00601 MEM_freeN(edges); 00602 MEM_freeN(cost); 00603 BLI_heap_free(heap, NULL); 00604 00605 for (eed= em->edges.first; eed; eed = eed->next) { 00606 eed->f2 &= ~ME_SEAM_DONE; 00607 } 00608 00609 if (mednum != target->tmp.l) { 00610 MEM_freeN(prevedge); 00611 EM_free_index_arrays(); 00612 return 0; 00613 } 00614 00615 /* follow path back to source and mark as seam */ 00616 if (mednum == target->tmp.l) { 00617 short allseams = 1; 00618 00619 mednum = target->tmp.l; 00620 do { 00621 eed = EM_get_edge_for_index( mednum ); 00622 if (!edgetag_context_check(scene, eed)) { 00623 allseams = 0; 00624 break; 00625 } 00626 mednum = prevedge[mednum]; 00627 } while (mednum != source->tmp.l); 00628 00629 mednum = target->tmp.l; 00630 do { 00631 eed = EM_get_edge_for_index( mednum ); 00632 if (allseams) 00633 edgetag_context_set(scene, eed, 0); 00634 else 00635 edgetag_context_set(scene, eed, 1); 00636 mednum = prevedge[mednum]; 00637 } while (mednum != -1); 00638 } 00639 00640 MEM_freeN(prevedge); 00641 EM_free_index_arrays(); 00642 return 1; 00643 } 00644 00645 /* *************************************** */ 00646 #if 0 00647 static void seam_edgehash_insert_face(EdgeHash *ehash, MFace *mf) 00648 { 00649 BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL); 00650 BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL); 00651 if (mf->v4) { 00652 BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL); 00653 BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL); 00654 } 00655 else 00656 BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL); 00657 } 00658 00659 void seam_mark_clear_tface(Scene *scene, short mode) 00660 { 00661 Mesh *me; 00662 MFace *mf; 00663 MEdge *med; 00664 int a; 00665 00666 me= get_mesh(OBACT); 00667 if(me==0 || me->totface==0) return; 00668 00669 if (mode == 0) 00670 mode = pupmenu("Seams%t|Mark Border Seam %x1|Clear Seam %x2"); 00671 00672 if (mode != 1 && mode != 2) 00673 return; 00674 00675 if (mode == 2) { 00676 EdgeHash *ehash = BLI_edgehash_new(); 00677 00678 for (a=0, mf=me->mface; a<me->totface; a++, mf++) 00679 if (!(mf->flag & ME_HIDE) && (mf->flag & ME_FACE_SEL)) 00680 seam_edgehash_insert_face(ehash, mf); 00681 00682 for (a=0, med=me->medge; a<me->totedge; a++, med++) 00683 if (BLI_edgehash_haskey(ehash, med->v1, med->v2)) 00684 med->flag &= ~ME_SEAM; 00685 00686 BLI_edgehash_free(ehash, NULL); 00687 } 00688 else { 00689 /* mark edges that are on both selected and deselected faces */ 00690 EdgeHash *ehash1 = BLI_edgehash_new(); 00691 EdgeHash *ehash2 = BLI_edgehash_new(); 00692 00693 for (a=0, mf=me->mface; a<me->totface; a++, mf++) { 00694 if ((mf->flag & ME_HIDE) || !(mf->flag & ME_FACE_SEL)) 00695 seam_edgehash_insert_face(ehash1, mf); 00696 else 00697 seam_edgehash_insert_face(ehash2, mf); 00698 } 00699 00700 for (a=0, med=me->medge; a<me->totedge; a++, med++) 00701 if (BLI_edgehash_haskey(ehash1, med->v1, med->v2) && 00702 BLI_edgehash_haskey(ehash2, med->v1, med->v2)) 00703 med->flag |= ME_SEAM; 00704 00705 BLI_edgehash_free(ehash1, NULL); 00706 BLI_edgehash_free(ehash2, NULL); 00707 } 00708 00709 // XXX if (G.rt == 8) 00710 // unwrap_lscm(1); 00711 00712 me->drawflag |= ME_DRAWSEAMS; 00713 } 00714 #endif 00715 00716 int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], int extend) 00717 { 00718 Mesh *me; 00719 MFace *mface, *msel; 00720 unsigned int a, index; 00721 00722 /* Get the face under the cursor */ 00723 me = get_mesh(ob); 00724 00725 if (!facesel_face_pick(C, me, mval, &index, 1)) 00726 return 0; 00727 00728 msel= (((MFace*)me->mface)+index); 00729 if (msel->flag & ME_HIDE) return 0; 00730 00731 /* clear flags */ 00732 mface = me->mface; 00733 a = me->totface; 00734 if (!extend) { 00735 while (a--) { 00736 mface->flag &= ~ME_FACE_SEL; 00737 mface++; 00738 } 00739 } 00740 00741 me->act_face = (int)index; 00742 00743 if (extend) { 00744 if (msel->flag & ME_FACE_SEL) 00745 msel->flag &= ~ME_FACE_SEL; 00746 else 00747 msel->flag |= ME_FACE_SEL; 00748 } 00749 else msel->flag |= ME_FACE_SEL; 00750 00751 /* image window redraw */ 00752 00753 paintface_flush_flags(ob); 00754 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data); 00755 ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views 00756 return 1; 00757 } 00758 00759 int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend) 00760 { 00761 Mesh *me; 00762 MFace *mface; 00763 struct ImBuf *ibuf; 00764 unsigned int *rt; 00765 int a, index; 00766 char *selar; 00767 int sx= rect->xmax-rect->xmin+1; 00768 int sy= rect->ymax-rect->ymin+1; 00769 00770 me= get_mesh(vc->obact); 00771 00772 if(me==NULL || me->totface==0 || sx*sy <= 0) 00773 return OPERATOR_CANCELLED; 00774 00775 selar= MEM_callocN(me->totface+1, "selar"); 00776 00777 if (extend == 0 && select) 00778 paintface_deselect_all_visible(vc->obact, SEL_DESELECT, FALSE); 00779 00780 view3d_validate_backbuf(vc); 00781 00782 ibuf = IMB_allocImBuf(sx,sy,32,IB_rect); 00783 rt = ibuf->rect; 00784 glReadPixels(rect->xmin+vc->ar->winrct.xmin, rect->ymin+vc->ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); 00785 if(ENDIAN_ORDER==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf); 00786 00787 a= sx*sy; 00788 while(a--) { 00789 if(*rt) { 00790 index= WM_framebuffer_to_index(*rt); 00791 if(index<=me->totface) selar[index]= 1; 00792 } 00793 rt++; 00794 } 00795 00796 mface= me->mface; 00797 for(a=1; a<=me->totface; a++, mface++) { 00798 if(selar[a]) { 00799 if(mface->flag & ME_HIDE); 00800 else { 00801 if(select) mface->flag |= ME_FACE_SEL; 00802 else mface->flag &= ~ME_FACE_SEL; 00803 } 00804 } 00805 } 00806 00807 IMB_freeImBuf(ibuf); 00808 MEM_freeN(selar); 00809 00810 #ifdef __APPLE__ 00811 glReadBuffer(GL_BACK); 00812 #endif 00813 00814 paintface_flush_flags(vc->obact); 00815 00816 return OPERATOR_FINISHED; 00817 } 00818 00819 00820 /* ********************* MESH VERTEX MIRR TOPO LOOKUP *************** */ 00821 /* note, this is not the best place for the function to be but moved 00822 * here to for the purpose of syncing with bmesh */ 00823 00824 typedef int MirrTopoHash_t; 00825 00826 typedef struct MirrTopoVert_t { 00827 MirrTopoHash_t hash; 00828 int v_index; 00829 } MirrTopoVert_t; 00830 00831 static int mirrtopo_hash_sort(const void *l1, const void *l2) 00832 { 00833 if ((MirrTopoHash_t)(intptr_t)l1 > (MirrTopoHash_t)(intptr_t)l2 ) return 1; 00834 else if ((MirrTopoHash_t)(intptr_t)l1 < (MirrTopoHash_t)(intptr_t)l2 ) return -1; 00835 return 0; 00836 } 00837 00838 static int mirrtopo_vert_sort(const void *v1, const void *v2) 00839 { 00840 if (((MirrTopoVert_t *)v1)->hash > ((MirrTopoVert_t *)v2)->hash ) return 1; 00841 else if (((MirrTopoVert_t *)v1)->hash < ((MirrTopoVert_t *)v2)->hash ) return -1; 00842 return 0; 00843 } 00844 00845 int ED_mesh_mirrtopo_recalc_check(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store) 00846 { 00847 int totvert; 00848 int totedge; 00849 00850 if (me->edit_mesh) { 00851 totvert = me->edit_mesh->totvert; 00852 totedge = me->edit_mesh->totedge; 00853 } 00854 else { 00855 totvert = me->totvert; 00856 totedge = me->totedge; 00857 } 00858 00859 if( (mesh_topo_store->index_lookup==NULL) || 00860 (mesh_topo_store->prev_ob_mode != ob_mode) || 00861 (totvert != mesh_topo_store->prev_vert_tot) || 00862 (totedge != mesh_topo_store->prev_edge_tot)) 00863 { 00864 return TRUE; 00865 } 00866 else { 00867 return FALSE; 00868 } 00869 00870 } 00871 00872 void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store, 00873 const short skip_em_vert_array_init) 00874 { 00875 MEdge *medge; 00876 EditMesh *em = me->edit_mesh; 00877 void **eve_tmp_back = NULL; /* some of the callers are using eve->tmp so restore after */ 00878 00879 /* editmode*/ 00880 EditEdge *eed; 00881 00882 int a, last; 00883 int totvert, totedge; 00884 int tot_unique = -1, tot_unique_prev = -1; 00885 00886 MirrTopoHash_t *topo_hash = NULL; 00887 MirrTopoHash_t *topo_hash_prev = NULL; 00888 MirrTopoVert_t *topo_pairs; 00889 00890 intptr_t *index_lookup; /* direct access to mesh_topo_store->index_lookup */ 00891 00892 /* reallocate if needed */ 00893 ED_mesh_mirrtopo_free(mesh_topo_store); 00894 00895 mesh_topo_store->prev_ob_mode = ob_mode; 00896 00897 if(em) { 00898 EditVert *eve; 00899 totvert = 0; 00900 eve_tmp_back = MEM_mallocN(em->totvert * sizeof(void *), "TopoMirr"); 00901 for(eve = em->verts.first; eve; eve = eve->next) { 00902 eve_tmp_back[totvert]= eve->tmp.p; 00903 eve->tmp.l = totvert++; 00904 } 00905 } 00906 else { 00907 totvert = me->totvert; 00908 } 00909 00910 topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr"); 00911 00912 /* Initialize the vert-edge-user counts used to detect unique topology */ 00913 if(em) { 00914 totedge = 0; 00915 00916 for(eed=em->edges.first; eed; eed = eed->next, totedge++) { 00917 topo_hash[eed->v1->tmp.l]++; 00918 topo_hash[eed->v2->tmp.l]++; 00919 } 00920 } 00921 else { 00922 totedge = me->totedge; 00923 00924 for(a=0, medge=me->medge; a < me->totedge; a++, medge++) { 00925 topo_hash[medge->v1]++; 00926 topo_hash[medge->v2]++; 00927 } 00928 } 00929 00930 topo_hash_prev = MEM_dupallocN(topo_hash); 00931 00932 tot_unique_prev = -1; 00933 while(1) { 00934 /* use the number of edges per vert to give verts unique topology IDs */ 00935 00936 if(em) { 00937 for(eed=em->edges.first; eed; eed = eed->next) { 00938 topo_hash[eed->v1->tmp.l] += topo_hash_prev[eed->v2->tmp.l]; 00939 topo_hash[eed->v2->tmp.l] += topo_hash_prev[eed->v1->tmp.l]; 00940 } 00941 } 00942 else { 00943 for(a=0, medge=me->medge; a<me->totedge; a++, medge++) { 00944 /* This can make really big numbers, wrapping around here is fine */ 00945 topo_hash[medge->v1] += topo_hash_prev[medge->v2]; 00946 topo_hash[medge->v2] += topo_hash_prev[medge->v1]; 00947 } 00948 } 00949 memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert); 00950 00951 /* sort so we can count unique values */ 00952 qsort(topo_hash_prev, totvert, sizeof(MirrTopoHash_t), mirrtopo_hash_sort); 00953 00954 tot_unique = 1; /* account for skiping the first value */ 00955 for(a=1; a<totvert; a++) { 00956 if (topo_hash_prev[a-1] != topo_hash_prev[a]) { 00957 tot_unique++; 00958 } 00959 } 00960 00961 if (tot_unique <= tot_unique_prev) { 00962 /* Finish searching for unique valus when 1 loop dosnt give a 00963 * higher number of unique values compared to the previous loop */ 00964 break; 00965 } 00966 else { 00967 tot_unique_prev = tot_unique; 00968 } 00969 /* Copy the hash calculated this iter, so we can use them next time */ 00970 memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert); 00971 } 00972 00973 /* restore eve->tmp.* */ 00974 if(eve_tmp_back) { 00975 EditVert *eve; 00976 totvert = 0; 00977 for(eve = em->verts.first; eve; eve = eve->next) { 00978 eve->tmp.p = eve_tmp_back[totvert++]; 00979 } 00980 00981 MEM_freeN(eve_tmp_back); 00982 eve_tmp_back = NULL; 00983 } 00984 00985 00986 /* Hash/Index pairs are needed for sorting to find index pairs */ 00987 topo_pairs = MEM_callocN( sizeof(MirrTopoVert_t) * totvert, "MirrTopoPairs"); 00988 00989 /* since we are looping through verts, initialize these values here too */ 00990 index_lookup = MEM_mallocN(totvert * sizeof(*index_lookup), "mesh_topo_lookup"); 00991 00992 if(em) { 00993 if (skip_em_vert_array_init == FALSE) { 00994 EM_init_index_arrays(em, 1, 0, 0); 00995 } 00996 } 00997 00998 00999 for(a=0; a<totvert; a++) { 01000 topo_pairs[a].hash = topo_hash[a]; 01001 topo_pairs[a].v_index = a; 01002 01003 /* initialize lookup */ 01004 index_lookup[a] = -1; 01005 } 01006 01007 qsort(topo_pairs, totvert, sizeof(MirrTopoVert_t), mirrtopo_vert_sort); 01008 01009 /* Since the loop starts at 2, we must define the last index where the hash's differ */ 01010 last = ((totvert >= 2) && (topo_pairs[0].hash == topo_pairs[1].hash)) ? 0 : 1; 01011 01012 /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2, 01013 * but you cant ever access the last 'a' index of MirrTopoPairs */ 01014 for(a=2; a <= totvert; a++) { 01015 /* printf("I %d %ld %d\n", (a-last), MirrTopoPairs[a ].hash, MirrTopoPairs[a ].vIndex ); */ 01016 if ((a==totvert) || (topo_pairs[a-1].hash != topo_pairs[a].hash)) { 01017 if (a-last==2) { 01018 if(em) { 01019 index_lookup[topo_pairs[a-1].v_index] = (intptr_t)EM_get_vert_for_index(topo_pairs[a-2].v_index); 01020 index_lookup[topo_pairs[a-2].v_index] = (intptr_t)EM_get_vert_for_index(topo_pairs[a-1].v_index); 01021 } 01022 else { 01023 index_lookup[topo_pairs[a-1].v_index] = topo_pairs[a-2].v_index; 01024 index_lookup[topo_pairs[a-2].v_index] = topo_pairs[a-1].v_index; 01025 } 01026 } 01027 last = a; 01028 } 01029 } 01030 if(em) { 01031 if (skip_em_vert_array_init == FALSE) { 01032 EM_free_index_arrays(); 01033 } 01034 } 01035 01036 MEM_freeN(topo_pairs); 01037 topo_pairs = NULL; 01038 01039 MEM_freeN(topo_hash); 01040 MEM_freeN(topo_hash_prev); 01041 01042 mesh_topo_store->index_lookup = index_lookup; 01043 mesh_topo_store->prev_vert_tot = totvert; 01044 mesh_topo_store->prev_edge_tot = totedge; 01045 } 01046 01047 void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store) 01048 { 01049 if (mesh_topo_store->index_lookup) { 01050 MEM_freeN(mesh_topo_store->index_lookup); 01051 } 01052 mesh_topo_store->index_lookup = NULL; 01053 mesh_topo_store->prev_vert_tot = -1; 01054 mesh_topo_store->prev_edge_tot = -1; 01055 }