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 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): Martin Poirier 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <stdlib.h> 00034 #include <math.h> 00035 #include <float.h> 00036 #include <stdio.h> 00037 00038 #include "PIL_time.h" 00039 00040 #include "DNA_armature_types.h" 00041 #include "DNA_scene_types.h" 00042 #include "DNA_object_types.h" 00043 #include "DNA_meshdata_types.h" // Temporary, for snapping to other unselected meshes 00044 #include "DNA_space_types.h" 00045 #include "DNA_screen_types.h" 00046 #include "DNA_view3d_types.h" 00047 #include "DNA_windowmanager_types.h" 00048 00049 #include "RNA_access.h" 00050 00051 #include "BLI_math.h" 00052 #include "BLI_editVert.h" 00053 #include "BLI_blenlib.h" 00054 #include "BLI_utildefines.h" 00055 00056 //#include "BDR_drawobject.h" 00057 // 00058 //#include "editmesh.h" 00059 //#include "BIF_editsima.h" 00060 #include "BIF_gl.h" 00061 //#include "BIF_mywindow.h" 00062 //#include "BIF_screen.h" 00063 //#include "BIF_editsima.h" 00064 //#include "BIF_drawimage.h" 00065 //#include "BIF_editmesh.h" 00066 00067 #include "BKE_DerivedMesh.h" 00068 #include "BKE_object.h" 00069 #include "BKE_anim.h" /* for duplis */ 00070 #include "BKE_context.h" 00071 00072 #include "ED_armature.h" 00073 #include "ED_image.h" 00074 #include "ED_mesh.h" 00075 #include "ED_uvedit.h" 00076 #include "ED_view3d.h" 00077 00078 #include "WM_types.h" 00079 00080 #include "UI_resources.h" 00081 #include "UI_view2d.h" 00082 00083 #include "MEM_guardedalloc.h" 00084 00085 #include "transform.h" 00086 00087 //#include "blendef.h" /* for selection modes */ 00088 00089 #define USE_BVH_FACE_SNAP 00090 00091 /********************* PROTOTYPES ***********************/ 00092 00093 static void setSnappingCallback(TransInfo *t); 00094 00095 static void ApplySnapTranslation(TransInfo *t, float vec[3]); 00096 static void ApplySnapRotation(TransInfo *t, float *vec); 00097 static void ApplySnapResize(TransInfo *t, float vec[2]); 00098 00099 /* static void CalcSnapGrid(TransInfo *t, float *vec); */ 00100 static void CalcSnapGeometry(TransInfo *t, float *vec); 00101 00102 static void TargetSnapMedian(TransInfo *t); 00103 static void TargetSnapCenter(TransInfo *t); 00104 static void TargetSnapClosest(TransInfo *t); 00105 static void TargetSnapActive(TransInfo *t); 00106 00107 static float RotationBetween(TransInfo *t, float p1[3], float p2[3]); 00108 static float TranslationBetween(TransInfo *t, float p1[3], float p2[3]); 00109 static float ResizeBetween(TransInfo *t, float p1[3], float p2[3]); 00110 00111 00112 /****************** IMPLEMENTATIONS *********************/ 00113 00114 #if 0 00115 int BIF_snappingSupported(Object *obedit) 00116 { 00117 int status = 0; 00118 00119 if (obedit == NULL || ELEM4(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE)) /* only support object mesh, armature, curves */ 00120 { 00121 status = 1; 00122 } 00123 00124 return status; 00125 } 00126 #endif 00127 00128 int validSnap(TransInfo *t) 00129 { 00130 return (t->tsnap.status & (POINT_INIT|TARGET_INIT)) == (POINT_INIT|TARGET_INIT) || 00131 (t->tsnap.status & (MULTI_POINTS|TARGET_INIT)) == (MULTI_POINTS|TARGET_INIT); 00132 } 00133 00134 int activeSnap(TransInfo *t) 00135 { 00136 return (t->modifiers & (MOD_SNAP|MOD_SNAP_INVERT)) == MOD_SNAP || (t->modifiers & (MOD_SNAP|MOD_SNAP_INVERT)) == MOD_SNAP_INVERT; 00137 } 00138 00139 void drawSnapping(const struct bContext *C, TransInfo *t) 00140 { 00141 if (validSnap(t) && activeSnap(t)) 00142 { 00143 00144 unsigned char col[4], selectedCol[4], activeCol[4]; 00145 UI_GetThemeColor3ubv(TH_TRANSFORM, col); 00146 col[3]= 128; 00147 00148 UI_GetThemeColor3ubv(TH_SELECT, selectedCol); 00149 selectedCol[3]= 128; 00150 00151 UI_GetThemeColor3ubv(TH_ACTIVE, activeCol); 00152 activeCol[3]= 192; 00153 00154 if (t->spacetype == SPACE_VIEW3D) { 00155 TransSnapPoint *p; 00156 View3D *v3d = CTX_wm_view3d(C); 00157 RegionView3D *rv3d = CTX_wm_region_view3d(C); 00158 float imat[4][4]; 00159 float size; 00160 00161 glDisable(GL_DEPTH_TEST); 00162 00163 size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); 00164 00165 invert_m4_m4(imat, rv3d->viewmat); 00166 00167 for (p = t->tsnap.points.first; p; p = p->next) { 00168 if (p == t->tsnap.selectedPoint) { 00169 glColor4ubv(selectedCol); 00170 } else { 00171 glColor4ubv(col); 00172 } 00173 00174 drawcircball(GL_LINE_LOOP, p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat); 00175 } 00176 00177 if (t->tsnap.status & POINT_INIT) { 00178 glColor4ubv(activeCol); 00179 00180 drawcircball(GL_LINE_LOOP, t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat); 00181 } 00182 00183 /* draw normal if needed */ 00184 if (usingSnappingNormal(t) && validSnappingNormal(t)) 00185 { 00186 glColor4ubv(activeCol); 00187 00188 glBegin(GL_LINES); 00189 glVertex3f(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]); 00190 glVertex3f( t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0], 00191 t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1], 00192 t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]); 00193 glEnd(); 00194 } 00195 00196 if(v3d->zbuf) 00197 glEnable(GL_DEPTH_TEST); 00198 } 00199 else if (t->spacetype==SPACE_IMAGE) 00200 { 00201 /*This will not draw, and Im nor sure why - campbell */ 00202 00203 /* 00204 float xuser_asp, yuser_asp; 00205 int wi, hi; 00206 float w, h; 00207 00208 calc_image_view(G.sima, 'f'); // float 00209 myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax); 00210 glLoadIdentity(); 00211 00212 ED_space_image_aspect(t->sa->spacedata.first, &xuser_aspx, &yuser_asp); 00213 ED_space_image_width(t->sa->spacedata.first, &wi, &hi); 00214 w = (((float)wi)/256.0f)*G.sima->zoom * xuser_asp; 00215 h = (((float)hi)/256.0f)*G.sima->zoom * yuser_asp; 00216 00217 cpack(0xFFFFFF); 00218 glTranslatef(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], 0.0f); 00219 00220 //glRectf(0,0,1,1); 00221 00222 setlinestyle(0); 00223 cpack(0x0); 00224 fdrawline(-0.020/w, 0, -0.1/w, 0); 00225 fdrawline(0.1/w, 0, .020/w, 0); 00226 fdrawline(0, -0.020/h, 0, -0.1/h); 00227 fdrawline(0, 0.1/h, 0, 0.020/h); 00228 00229 glTranslatef(-t->tsnap.snapPoint[0], -t->tsnap.snapPoint[1], 0.0f); 00230 setlinestyle(0); 00231 */ 00232 00233 } 00234 } 00235 } 00236 00237 int handleSnapping(TransInfo *t, wmEvent *event) 00238 { 00239 int status = 0; 00240 00241 #if 0 // XXX need a proper selector for all snap mode 00242 if (BIF_snappingSupported(t->obedit) && event->type == TABKEY && event->shift) 00243 { 00244 /* toggle snap and reinit */ 00245 t->settings->snap_flag ^= SCE_SNAP; 00246 initSnapping(t, NULL); 00247 status = 1; 00248 } 00249 #endif 00250 if (event->type == MOUSEMOVE) 00251 { 00252 status |= updateSelectedSnapPoint(t); 00253 } 00254 00255 return status; 00256 } 00257 00258 void applyProject(TransInfo *t) 00259 { 00260 /* XXX FLICKER IN OBJECT MODE */ 00261 if ((t->tsnap.project) && activeSnap(t) && (t->flag & T_NO_PROJECT) == 0) 00262 { 00263 TransData *td = t->data; 00264 float tvec[3]; 00265 float imat[4][4]; 00266 int i; 00267 00268 if(t->flag & (T_EDIT|T_POSE)) { 00269 Object *ob = t->obedit?t->obedit:t->poseobj; 00270 invert_m4_m4(imat, ob->obmat); 00271 } 00272 00273 for(i = 0 ; i < t->total; i++, td++) { 00274 float iloc[3], loc[3], no[3]; 00275 float mval[2]; 00276 int dist = 1000; 00277 00278 if (td->flag & TD_NOACTION) 00279 break; 00280 00281 if (td->flag & TD_SKIP) 00282 continue; 00283 00284 copy_v3_v3(iloc, td->loc); 00285 if (t->flag & (T_EDIT|T_POSE)) 00286 { 00287 Object *ob = t->obedit?t->obedit:t->poseobj; 00288 mul_m4_v3(ob->obmat, iloc); 00289 } 00290 else if (t->flag & T_OBJECT) 00291 { 00292 td->ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; 00293 object_handle_update(t->scene, td->ob); 00294 copy_v3_v3(iloc, td->ob->obmat[3]); 00295 } 00296 00297 project_float(t->ar, iloc, mval); 00298 00299 if (snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.modeSelect)) 00300 { 00301 // if(t->flag & (T_EDIT|T_POSE)) { 00302 // mul_m4_v3(imat, loc); 00303 // } 00304 // 00305 sub_v3_v3v3(tvec, loc, iloc); 00306 00307 mul_m3_v3(td->smtx, tvec); 00308 00309 add_v3_v3(td->loc, tvec); 00310 } 00311 00312 //XXX constraintTransLim(t, td); 00313 } 00314 } 00315 } 00316 00317 void applySnapping(TransInfo *t, float *vec) 00318 { 00319 /* project is not applied this way */ 00320 if (t->tsnap.project) 00321 return; 00322 00323 if (t->tsnap.status & SNAP_FORCED) 00324 { 00325 t->tsnap.targetSnap(t); 00326 00327 t->tsnap.applySnap(t, vec); 00328 } 00329 else if ((t->tsnap.mode != SCE_SNAP_MODE_INCREMENT) && activeSnap(t)) 00330 { 00331 double current = PIL_check_seconds_timer(); 00332 00333 // Time base quirky code to go around findnearest slowness 00334 /* !TODO! add exception for object mode, no need to slow it down then */ 00335 if (current - t->tsnap.last >= 0.01) 00336 { 00337 t->tsnap.calcSnap(t, vec); 00338 t->tsnap.targetSnap(t); 00339 00340 t->tsnap.last = current; 00341 } 00342 if (validSnap(t)) 00343 { 00344 t->tsnap.applySnap(t, vec); 00345 } 00346 } 00347 } 00348 00349 void resetSnapping(TransInfo *t) 00350 { 00351 t->tsnap.status = 0; 00352 t->tsnap.align = 0; 00353 t->tsnap.project = 0; 00354 t->tsnap.mode = 0; 00355 t->tsnap.modeSelect = 0; 00356 t->tsnap.target = 0; 00357 t->tsnap.last = 0; 00358 t->tsnap.applySnap = NULL; 00359 00360 t->tsnap.snapNormal[0] = 0; 00361 t->tsnap.snapNormal[1] = 0; 00362 t->tsnap.snapNormal[2] = 0; 00363 } 00364 00365 int usingSnappingNormal(TransInfo *t) 00366 { 00367 return t->tsnap.align; 00368 } 00369 00370 int validSnappingNormal(TransInfo *t) 00371 { 00372 if (validSnap(t)) 00373 { 00374 if (dot_v3v3(t->tsnap.snapNormal, t->tsnap.snapNormal) > 0) 00375 { 00376 return 1; 00377 } 00378 } 00379 00380 return 0; 00381 } 00382 00383 static void initSnappingMode(TransInfo *t) 00384 { 00385 ToolSettings *ts = t->settings; 00386 Object *obedit = t->obedit; 00387 Scene *scene = t->scene; 00388 00389 /* force project off when not supported */ 00390 if (ts->snap_mode != SCE_SNAP_MODE_FACE) 00391 { 00392 t->tsnap.project = 0; 00393 } 00394 00395 t->tsnap.mode = ts->snap_mode; 00396 00397 if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && // Only 3D view or UV 00398 (t->flag & T_CAMERA) == 0) { // Not with camera selected in camera view 00399 setSnappingCallback(t); 00400 00401 /* Edit mode */ 00402 if (t->tsnap.applySnap != NULL && // A snapping function actually exist 00403 (obedit != NULL && ELEM4(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE)) ) // Temporary limited to edit mode meshes, armature, curves 00404 { 00405 /* Exclude editmesh if using proportional edit */ 00406 if ((obedit->type == OB_MESH) && (t->flag & T_PROP_EDIT)) 00407 { 00408 t->tsnap.modeSelect = SNAP_NOT_OBEDIT; 00409 } 00410 else 00411 { 00412 t->tsnap.modeSelect = t->tsnap.snap_self ? SNAP_ALL : SNAP_NOT_OBEDIT; 00413 } 00414 } 00415 /* Particles edit mode*/ 00416 else if (t->tsnap.applySnap != NULL && // A snapping function actually exist 00417 (obedit == NULL && BASACT && BASACT->object && BASACT->object->mode & OB_MODE_PARTICLE_EDIT )) 00418 { 00419 t->tsnap.modeSelect = SNAP_ALL; 00420 } 00421 /* Object mode */ 00422 else if (t->tsnap.applySnap != NULL && // A snapping function actually exist 00423 (obedit == NULL) ) // Object Mode 00424 { 00425 t->tsnap.modeSelect = SNAP_NOT_SELECTED; 00426 } 00427 else 00428 { 00429 /* Grid if snap is not possible */ 00430 t->tsnap.mode = SCE_SNAP_MODE_INCREMENT; 00431 } 00432 } 00433 else 00434 { 00435 /* Always grid outside of 3D view */ 00436 t->tsnap.mode = SCE_SNAP_MODE_INCREMENT; 00437 } 00438 } 00439 00440 void initSnapping(TransInfo *t, wmOperator *op) 00441 { 00442 ToolSettings *ts = t->settings; 00443 short snap_target = t->settings->snap_target; 00444 00445 resetSnapping(t); 00446 00447 /* if snap property exists */ 00448 if (op && RNA_struct_find_property(op->ptr, "snap") && RNA_struct_property_is_set(op->ptr, "snap")) 00449 { 00450 if (RNA_boolean_get(op->ptr, "snap")) 00451 { 00452 t->modifiers |= MOD_SNAP; 00453 00454 if (RNA_struct_property_is_set(op->ptr, "snap_target")) 00455 { 00456 snap_target = RNA_enum_get(op->ptr, "snap_target"); 00457 } 00458 00459 if (RNA_struct_property_is_set(op->ptr, "snap_point")) 00460 { 00461 RNA_float_get_array(op->ptr, "snap_point", t->tsnap.snapPoint); 00462 t->tsnap.status |= SNAP_FORCED|POINT_INIT; 00463 } 00464 00465 /* snap align only defined in specific cases */ 00466 if (RNA_struct_find_property(op->ptr, "snap_align")) 00467 { 00468 t->tsnap.align = RNA_boolean_get(op->ptr, "snap_align"); 00469 RNA_float_get_array(op->ptr, "snap_normal", t->tsnap.snapNormal); 00470 normalize_v3(t->tsnap.snapNormal); 00471 } 00472 00473 if (RNA_struct_find_property(op->ptr, "use_snap_project")) 00474 { 00475 t->tsnap.project = RNA_boolean_get(op->ptr, "use_snap_project"); 00476 } 00477 00478 if (RNA_struct_find_property(op->ptr, "use_snap_self")) 00479 { 00480 t->tsnap.snap_self = RNA_boolean_get(op->ptr, "use_snap_self"); 00481 } 00482 } 00483 } 00484 /* use scene defaults only when transform is modal */ 00485 else if (t->flag & T_MODAL) 00486 { 00487 if(ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) 00488 { 00489 if (ts->snap_flag & SCE_SNAP) { 00490 t->modifiers |= MOD_SNAP; 00491 } 00492 00493 t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) == SCE_SNAP_ROTATE); 00494 t->tsnap.project = ((t->settings->snap_flag & SCE_SNAP_PROJECT) == SCE_SNAP_PROJECT); 00495 t->tsnap.snap_self = !((t->settings->snap_flag & SCE_SNAP_NO_SELF) == SCE_SNAP_NO_SELF); 00496 t->tsnap.peel = ((t->settings->snap_flag & SCE_SNAP_PROJECT) == SCE_SNAP_PROJECT); 00497 } 00498 } 00499 00500 t->tsnap.target = snap_target; 00501 00502 initSnappingMode(t); 00503 } 00504 00505 static void setSnappingCallback(TransInfo *t) 00506 { 00507 t->tsnap.calcSnap = CalcSnapGeometry; 00508 00509 switch(t->tsnap.target) 00510 { 00511 case SCE_SNAP_TARGET_CLOSEST: 00512 t->tsnap.targetSnap = TargetSnapClosest; 00513 break; 00514 case SCE_SNAP_TARGET_CENTER: 00515 t->tsnap.targetSnap = TargetSnapCenter; 00516 break; 00517 case SCE_SNAP_TARGET_MEDIAN: 00518 t->tsnap.targetSnap = TargetSnapMedian; 00519 break; 00520 case SCE_SNAP_TARGET_ACTIVE: 00521 t->tsnap.targetSnap = TargetSnapActive; 00522 break; 00523 00524 } 00525 00526 switch (t->mode) 00527 { 00528 case TFM_TRANSLATION: 00529 t->tsnap.applySnap = ApplySnapTranslation; 00530 t->tsnap.distance = TranslationBetween; 00531 break; 00532 case TFM_ROTATION: 00533 t->tsnap.applySnap = ApplySnapRotation; 00534 t->tsnap.distance = RotationBetween; 00535 00536 // Can't do TARGET_CENTER with rotation, use TARGET_MEDIAN instead 00537 if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) { 00538 t->tsnap.target = SCE_SNAP_TARGET_MEDIAN; 00539 t->tsnap.targetSnap = TargetSnapMedian; 00540 } 00541 break; 00542 case TFM_RESIZE: 00543 t->tsnap.applySnap = ApplySnapResize; 00544 t->tsnap.distance = ResizeBetween; 00545 00546 // Can't do TARGET_CENTER with resize, use TARGET_MEDIAN instead 00547 if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) { 00548 t->tsnap.target = SCE_SNAP_TARGET_MEDIAN; 00549 t->tsnap.targetSnap = TargetSnapMedian; 00550 } 00551 break; 00552 default: 00553 t->tsnap.applySnap = NULL; 00554 break; 00555 } 00556 } 00557 00558 void addSnapPoint(TransInfo *t) 00559 { 00560 if (t->tsnap.status & POINT_INIT) { 00561 TransSnapPoint *p = MEM_callocN(sizeof(TransSnapPoint), "SnapPoint"); 00562 00563 t->tsnap.selectedPoint = p; 00564 00565 copy_v3_v3(p->co, t->tsnap.snapPoint); 00566 00567 BLI_addtail(&t->tsnap.points, p); 00568 00569 t->tsnap.status |= MULTI_POINTS; 00570 } 00571 } 00572 00573 int updateSelectedSnapPoint(TransInfo *t) 00574 { 00575 int status = 0; 00576 if (t->tsnap.status & MULTI_POINTS) { 00577 TransSnapPoint *p, *closest_p = NULL; 00578 int closest_dist = 0; 00579 int screen_loc[2]; 00580 00581 for( p = t->tsnap.points.first; p; p = p->next ) { 00582 int dx, dy; 00583 int dist; 00584 00585 project_int(t->ar, p->co, screen_loc); 00586 00587 dx = t->mval[0] - screen_loc[0]; 00588 dy = t->mval[1] - screen_loc[1]; 00589 00590 dist = dx * dx + dy * dy; 00591 00592 if (dist < 100 && (closest_p == NULL || closest_dist > dist)) { 00593 closest_p = p; 00594 closest_dist = dist; 00595 } 00596 } 00597 00598 if (closest_p) { 00599 status = t->tsnap.selectedPoint == closest_p ? 0 : 1; 00600 t->tsnap.selectedPoint = closest_p; 00601 } 00602 } 00603 00604 return status; 00605 } 00606 00607 void removeSnapPoint(TransInfo *t) 00608 { 00609 if (t->tsnap.status & MULTI_POINTS) { 00610 updateSelectedSnapPoint(t); 00611 00612 if (t->tsnap.selectedPoint) { 00613 BLI_freelinkN(&t->tsnap.points, t->tsnap.selectedPoint); 00614 00615 if (t->tsnap.points.first == NULL) { 00616 t->tsnap.status &= ~MULTI_POINTS; 00617 } 00618 00619 t->tsnap.selectedPoint = NULL; 00620 } 00621 00622 } 00623 } 00624 00625 void getSnapPoint(TransInfo *t, float vec[3]) 00626 { 00627 if (t->tsnap.points.first) { 00628 TransSnapPoint *p; 00629 int total = 0; 00630 00631 vec[0] = vec[1] = vec[2] = 0; 00632 00633 for (p = t->tsnap.points.first; p; p = p->next, total++) { 00634 add_v3_v3(vec, p->co); 00635 } 00636 00637 if (t->tsnap.status & POINT_INIT) { 00638 add_v3_v3(vec, t->tsnap.snapPoint); 00639 total++; 00640 } 00641 00642 mul_v3_fl(vec, 1.0f / total); 00643 } else { 00644 copy_v3_v3(vec, t->tsnap.snapPoint); 00645 } 00646 } 00647 00648 /********************** APPLY **************************/ 00649 00650 static void ApplySnapTranslation(TransInfo *t, float vec[3]) 00651 { 00652 float point[3]; 00653 getSnapPoint(t, point); 00654 sub_v3_v3v3(vec, point, t->tsnap.snapTarget); 00655 } 00656 00657 static void ApplySnapRotation(TransInfo *t, float *vec) 00658 { 00659 if (t->tsnap.target == SCE_SNAP_TARGET_CLOSEST) { 00660 *vec = t->tsnap.dist; 00661 } 00662 else { 00663 float point[3]; 00664 getSnapPoint(t, point); 00665 *vec = RotationBetween(t, t->tsnap.snapTarget, point); 00666 } 00667 } 00668 00669 static void ApplySnapResize(TransInfo *t, float vec[3]) 00670 { 00671 if (t->tsnap.target == SCE_SNAP_TARGET_CLOSEST) { 00672 vec[0] = vec[1] = vec[2] = t->tsnap.dist; 00673 } 00674 else { 00675 float point[3]; 00676 getSnapPoint(t, point); 00677 vec[0] = vec[1] = vec[2] = ResizeBetween(t, t->tsnap.snapTarget, point); 00678 } 00679 } 00680 00681 /********************** DISTANCE **************************/ 00682 00683 static float TranslationBetween(TransInfo *UNUSED(t), float p1[3], float p2[3]) 00684 { 00685 return len_v3v3(p1, p2); 00686 } 00687 00688 static float RotationBetween(TransInfo *t, float p1[3], float p2[3]) 00689 { 00690 float angle, start[3], end[3], center[3]; 00691 00692 copy_v3_v3(center, t->center); 00693 if(t->flag & (T_EDIT|T_POSE)) { 00694 Object *ob= t->obedit?t->obedit:t->poseobj; 00695 mul_m4_v3(ob->obmat, center); 00696 } 00697 00698 sub_v3_v3v3(start, p1, center); 00699 sub_v3_v3v3(end, p2, center); 00700 00701 // Angle around a constraint axis (error prone, will need debug) 00702 if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { 00703 float axis[3], tmp[3]; 00704 00705 t->con.applyRot(t, NULL, axis, NULL); 00706 00707 project_v3_v3v3(tmp, end, axis); 00708 sub_v3_v3v3(end, end, tmp); 00709 00710 project_v3_v3v3(tmp, start, axis); 00711 sub_v3_v3v3(start, start, tmp); 00712 00713 normalize_v3(end); 00714 normalize_v3(start); 00715 00716 cross_v3_v3v3(tmp, start, end); 00717 00718 if (dot_v3v3(tmp, axis) < 0.0f) 00719 angle = -acos(dot_v3v3(start, end)); 00720 else 00721 angle = acos(dot_v3v3(start, end)); 00722 } 00723 else { 00724 float mtx[3][3]; 00725 00726 copy_m3_m4(mtx, t->viewmat); 00727 00728 mul_m3_v3(mtx, end); 00729 mul_m3_v3(mtx, start); 00730 00731 angle = atan2(start[1],start[0]) - atan2(end[1],end[0]); 00732 } 00733 00734 if (angle > (float)M_PI) { 00735 angle = angle - 2 * (float)M_PI; 00736 } 00737 else if (angle < -((float)M_PI)) { 00738 angle = 2.0f * (float)M_PI + angle; 00739 } 00740 00741 return angle; 00742 } 00743 00744 static float ResizeBetween(TransInfo *t, float p1[3], float p2[3]) 00745 { 00746 float d1[3], d2[3], center[3], len_d1; 00747 00748 copy_v3_v3(center, t->center); 00749 if(t->flag & (T_EDIT|T_POSE)) { 00750 Object *ob= t->obedit?t->obedit:t->poseobj; 00751 mul_m4_v3(ob->obmat, center); 00752 } 00753 00754 sub_v3_v3v3(d1, p1, center); 00755 sub_v3_v3v3(d2, p2, center); 00756 00757 if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { 00758 mul_m3_v3(t->con.pmtx, d1); 00759 mul_m3_v3(t->con.pmtx, d2); 00760 } 00761 00762 len_d1 = len_v3(d1); 00763 00764 return len_d1 != 0.0f ? len_v3(d2) / len_d1 : 1; 00765 } 00766 00767 /********************** CALC **************************/ 00768 00769 static void UNUSED_FUNCTION(CalcSnapGrid)(TransInfo *t, float *UNUSED(vec)) 00770 { 00771 snapGridAction(t, t->tsnap.snapPoint, BIG_GEARS); 00772 } 00773 00774 static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) 00775 { 00776 if (t->spacetype == SPACE_VIEW3D) 00777 { 00778 float loc[3]; 00779 float no[3]; 00780 float mval[2]; 00781 int found = 0; 00782 int dist = SNAP_MIN_DISTANCE; // Use a user defined value here 00783 00784 mval[0] = t->mval[0]; 00785 mval[1] = t->mval[1]; 00786 00787 if (t->tsnap.mode == SCE_SNAP_MODE_VOLUME) 00788 { 00789 ListBase depth_peels; 00790 DepthPeel *p1, *p2; 00791 float *last_p = NULL; 00792 float max_dist = FLT_MAX; 00793 float p[3] = {0.0f, 0.0f, 0.0f}; 00794 00795 depth_peels.first = depth_peels.last = NULL; 00796 00797 peelObjectsTransForm(t, &depth_peels, mval); 00798 00799 // if (LAST_SNAP_POINT_VALID) 00800 // { 00801 // last_p = LAST_SNAP_POINT; 00802 // } 00803 // else 00804 // { 00805 last_p = t->tsnap.snapPoint; 00806 // } 00807 00808 00809 for (p1 = depth_peels.first; p1; p1 = p1->next) 00810 { 00811 if (p1->flag == 0) 00812 { 00813 float vec[3]; 00814 float new_dist; 00815 00816 p2 = NULL; 00817 p1->flag = 1; 00818 00819 /* if peeling objects, take the first and last from each object */ 00820 if (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) 00821 { 00822 DepthPeel *peel; 00823 for (peel = p1->next; peel; peel = peel->next) 00824 { 00825 if (peel->ob == p1->ob) 00826 { 00827 peel->flag = 1; 00828 p2 = peel; 00829 } 00830 } 00831 } 00832 /* otherwise, pair first with second and so on */ 00833 else 00834 { 00835 for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next) 00836 { 00837 /* nothing to do here */ 00838 } 00839 } 00840 00841 if (p2) 00842 { 00843 p2->flag = 1; 00844 00845 add_v3_v3v3(vec, p1->p, p2->p); 00846 mul_v3_fl(vec, 0.5f); 00847 } 00848 else 00849 { 00850 copy_v3_v3(vec, p1->p); 00851 } 00852 00853 if (last_p == NULL) 00854 { 00855 copy_v3_v3(p, vec); 00856 max_dist = 0; 00857 break; 00858 } 00859 00860 new_dist = len_v3v3(last_p, vec); 00861 00862 if (new_dist < max_dist) 00863 { 00864 copy_v3_v3(p, vec); 00865 max_dist = new_dist; 00866 } 00867 } 00868 } 00869 00870 if (max_dist != FLT_MAX) 00871 { 00872 copy_v3_v3(loc, p); 00873 /* XXX, is there a correct normal in this case ???, for now just z up */ 00874 no[0]= 0.0; 00875 no[1]= 0.0; 00876 no[2]= 1.0; 00877 found = 1; 00878 } 00879 00880 BLI_freelistN(&depth_peels); 00881 } 00882 else 00883 { 00884 found = snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.modeSelect); 00885 } 00886 00887 if (found == 1) 00888 { 00889 float tangent[3]; 00890 00891 sub_v3_v3v3(tangent, loc, t->tsnap.snapPoint); 00892 tangent[2] = 0; 00893 00894 if (dot_v3v3(tangent, tangent) > 0) 00895 { 00896 copy_v3_v3(t->tsnap.snapTangent, tangent); 00897 } 00898 00899 copy_v3_v3(t->tsnap.snapPoint, loc); 00900 copy_v3_v3(t->tsnap.snapNormal, no); 00901 00902 t->tsnap.status |= POINT_INIT; 00903 } 00904 else 00905 { 00906 t->tsnap.status &= ~POINT_INIT; 00907 } 00908 } 00909 else if (t->spacetype == SPACE_IMAGE && t->obedit != NULL && t->obedit->type==OB_MESH) 00910 { /* same as above but for UV's */ 00911 /* same as above but for UV's */ 00912 Image *ima= ED_space_image(t->sa->spacedata.first); 00913 float aspx, aspy, co[2]; 00914 00915 UI_view2d_region_to_view(&t->ar->v2d, t->mval[0], t->mval[1], co, co+1); 00916 00917 if(ED_uvedit_nearest_uv(t->scene, t->obedit, ima, co, t->tsnap.snapPoint)) 00918 { 00919 ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy); 00920 t->tsnap.snapPoint[0] *= aspx; 00921 t->tsnap.snapPoint[1] *= aspy; 00922 00923 t->tsnap.status |= POINT_INIT; 00924 } 00925 else 00926 { 00927 t->tsnap.status &= ~POINT_INIT; 00928 } 00929 } 00930 } 00931 00932 /********************** TARGET **************************/ 00933 00934 static void TargetSnapCenter(TransInfo *t) 00935 { 00936 // Only need to calculate once 00937 if ((t->tsnap.status & TARGET_INIT) == 0) 00938 { 00939 copy_v3_v3(t->tsnap.snapTarget, t->center); 00940 if(t->flag & (T_EDIT|T_POSE)) { 00941 Object *ob= t->obedit?t->obedit:t->poseobj; 00942 mul_m4_v3(ob->obmat, t->tsnap.snapTarget); 00943 } 00944 00945 t->tsnap.status |= TARGET_INIT; 00946 } 00947 } 00948 00949 static void TargetSnapActive(TransInfo *t) 00950 { 00951 // Only need to calculate once 00952 if ((t->tsnap.status & TARGET_INIT) == 0) 00953 { 00954 TransData *td = NULL; 00955 TransData *active_td = NULL; 00956 int i; 00957 00958 for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) 00959 { 00960 if (td->flag & TD_ACTIVE) 00961 { 00962 active_td = td; 00963 break; 00964 } 00965 } 00966 00967 if (active_td) 00968 { 00969 copy_v3_v3(t->tsnap.snapTarget, active_td->center); 00970 00971 if(t->flag & (T_EDIT|T_POSE)) { 00972 Object *ob= t->obedit?t->obedit:t->poseobj; 00973 mul_m4_v3(ob->obmat, t->tsnap.snapTarget); 00974 } 00975 00976 t->tsnap.status |= TARGET_INIT; 00977 } 00978 /* No active, default to median */ 00979 else 00980 { 00981 t->tsnap.target = SCE_SNAP_TARGET_MEDIAN; 00982 t->tsnap.targetSnap = TargetSnapMedian; 00983 TargetSnapMedian(t); 00984 } 00985 } 00986 } 00987 00988 static void TargetSnapMedian(TransInfo *t) 00989 { 00990 // Only need to calculate once 00991 if ((t->tsnap.status & TARGET_INIT) == 0) 00992 { 00993 TransData *td = NULL; 00994 int i; 00995 00996 t->tsnap.snapTarget[0] = 0; 00997 t->tsnap.snapTarget[1] = 0; 00998 t->tsnap.snapTarget[2] = 0; 00999 01000 for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) 01001 { 01002 add_v3_v3(t->tsnap.snapTarget, td->center); 01003 } 01004 01005 mul_v3_fl(t->tsnap.snapTarget, 1.0 / i); 01006 01007 if(t->flag & (T_EDIT|T_POSE)) { 01008 Object *ob= t->obedit?t->obedit:t->poseobj; 01009 mul_m4_v3(ob->obmat, t->tsnap.snapTarget); 01010 } 01011 01012 t->tsnap.status |= TARGET_INIT; 01013 } 01014 } 01015 01016 static void TargetSnapClosest(TransInfo *t) 01017 { 01018 // Only valid if a snap point has been selected 01019 if (t->tsnap.status & POINT_INIT) 01020 { 01021 TransData *closest = NULL, *td = NULL; 01022 01023 /* Object mode */ 01024 if (t->flag & T_OBJECT) 01025 { 01026 int i; 01027 for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) 01028 { 01029 struct BoundBox *bb = object_get_boundbox(td->ob); 01030 01031 /* use boundbox if possible */ 01032 if (bb) 01033 { 01034 int j; 01035 01036 for (j = 0; j < 8; j++) { 01037 float loc[3]; 01038 float dist; 01039 01040 copy_v3_v3(loc, bb->vec[j]); 01041 mul_m4_v3(td->ext->obmat, loc); 01042 01043 dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); 01044 01045 if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist)) 01046 { 01047 copy_v3_v3(t->tsnap.snapTarget, loc); 01048 closest = td; 01049 t->tsnap.dist = dist; 01050 } 01051 } 01052 } 01053 /* use element center otherwise */ 01054 else 01055 { 01056 float loc[3]; 01057 float dist; 01058 01059 copy_v3_v3(loc, td->center); 01060 01061 dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); 01062 01063 if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist)) 01064 { 01065 copy_v3_v3(t->tsnap.snapTarget, loc); 01066 closest = td; 01067 t->tsnap.dist = dist; 01068 } 01069 } 01070 } 01071 } 01072 else 01073 { 01074 int i; 01075 for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) 01076 { 01077 float loc[3]; 01078 float dist; 01079 01080 copy_v3_v3(loc, td->center); 01081 01082 if(t->flag & (T_EDIT|T_POSE)) { 01083 Object *ob= t->obedit?t->obedit:t->poseobj; 01084 mul_m4_v3(ob->obmat, loc); 01085 } 01086 01087 dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); 01088 01089 if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist)) 01090 { 01091 copy_v3_v3(t->tsnap.snapTarget, loc); 01092 closest = td; 01093 t->tsnap.dist = dist; 01094 } 01095 } 01096 } 01097 01098 t->tsnap.status |= TARGET_INIT; 01099 } 01100 } 01101 /*================================================================*/ 01102 #ifndef USE_BVH_FACE_SNAP 01103 static int snapFace(ARegion *ar, float v1co[3], float v2co[3], float v3co[3], float *v4co, float mval[2], float ray_start[3], float ray_start_local[3], float ray_normal_local[3], float obmat[][4], float timat[][3], float loc[3], float no[3], int *dist, float *depth) 01104 { 01105 float lambda; 01106 int result; 01107 int retval = 0; 01108 01109 result = isect_ray_tri_threshold_v3(ray_start_local, ray_normal_local, v1co, v2co, v3co, &lambda, NULL, 0.001); 01110 01111 if (result) { 01112 float location[3], normal[3]; 01113 float intersect[3]; 01114 float new_depth; 01115 int screen_loc[2]; 01116 int new_dist; 01117 01118 copy_v3_v3(intersect, ray_normal_local); 01119 mul_v3_fl(intersect, lambda); 01120 add_v3_v3(intersect, ray_start_local); 01121 01122 copy_v3_v3(location, intersect); 01123 01124 if (v4co) 01125 normal_quad_v3( normal,v1co, v2co, v3co, v4co); 01126 else 01127 normal_tri_v3( normal,v1co, v2co, v3co); 01128 01129 mul_m4_v3(obmat, location); 01130 01131 new_depth = len_v3v3(location, ray_start); 01132 01133 project_int(ar, location, screen_loc); 01134 new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]); 01135 01136 if (new_dist <= *dist && new_depth < *depth) 01137 { 01138 *depth = new_depth; 01139 retval = 1; 01140 01141 copy_v3_v3(loc, location); 01142 copy_v3_v3(no, normal); 01143 01144 mul_m3_v3(timat, no); 01145 normalize_v3(no); 01146 01147 *dist = new_dist; 01148 } 01149 } 01150 01151 return retval; 01152 } 01153 #endif 01154 01155 static int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], float obmat[][4], float timat[][3], 01156 const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2], 01157 float r_loc[3], float r_no[3], int *r_dist, float *r_depth) 01158 { 01159 float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3]; 01160 int result; 01161 int retval = 0; 01162 01163 copy_v3_v3(ray_end, ray_normal_local); 01164 mul_v3_fl(ray_end, 2000); 01165 add_v3_v3v3(ray_end, ray_start_local, ray_end); 01166 01167 result = isect_line_line_v3(v1co, v2co, ray_start_local, ray_end, intersect, dvec); /* dvec used but we don't care about result */ 01168 01169 if (result) 01170 { 01171 float edge_loc[3], vec[3]; 01172 float mul; 01173 01174 /* check for behind ray_start */ 01175 sub_v3_v3v3(dvec, intersect, ray_start_local); 01176 01177 sub_v3_v3v3(edge_loc, v1co, v2co); 01178 sub_v3_v3v3(vec, intersect, v2co); 01179 01180 mul = dot_v3v3(vec, edge_loc) / dot_v3v3(edge_loc, edge_loc); 01181 01182 if (mul > 1) { 01183 mul = 1; 01184 copy_v3_v3(intersect, v1co); 01185 } 01186 else if (mul < 0) { 01187 mul = 0; 01188 copy_v3_v3(intersect, v2co); 01189 } 01190 01191 if (dot_v3v3(ray_normal_local, dvec) > 0) 01192 { 01193 float location[3]; 01194 float new_depth; 01195 int screen_loc[2]; 01196 int new_dist; 01197 01198 copy_v3_v3(location, intersect); 01199 01200 mul_m4_v3(obmat, location); 01201 01202 new_depth = len_v3v3(location, ray_start); 01203 01204 project_int(ar, location, screen_loc); 01205 new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]); 01206 01207 /* 10% threshold if edge is closer but a bit further 01208 * this takes care of series of connected edges a bit slanted w.r.t the viewport 01209 * otherwise, it would stick to the verts of the closest edge and not slide along merrily 01210 * */ 01211 if (new_dist <= *r_dist && new_depth < *r_depth * 1.001f) 01212 { 01213 float n1[3], n2[3]; 01214 01215 *r_depth = new_depth; 01216 retval = 1; 01217 01218 sub_v3_v3v3(edge_loc, v1co, v2co); 01219 sub_v3_v3v3(vec, intersect, v2co); 01220 01221 mul = dot_v3v3(vec, edge_loc) / dot_v3v3(edge_loc, edge_loc); 01222 01223 if (r_no) 01224 { 01225 normal_short_to_float_v3(n1, v1no); 01226 normal_short_to_float_v3(n2, v2no); 01227 interp_v3_v3v3(r_no, n2, n1, mul); 01228 mul_m3_v3(timat, r_no); 01229 normalize_v3(r_no); 01230 } 01231 01232 copy_v3_v3(r_loc, location); 01233 01234 *r_dist = new_dist; 01235 } 01236 } 01237 } 01238 01239 return retval; 01240 } 01241 01242 static int snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[][4], float timat[][3], 01243 const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2], 01244 float r_loc[3], float r_no[3], int *r_dist, float *r_depth) 01245 { 01246 int retval = 0; 01247 float dvec[3]; 01248 01249 sub_v3_v3v3(dvec, vco, ray_start_local); 01250 01251 if (dot_v3v3(ray_normal_local, dvec) > 0) 01252 { 01253 float location[3]; 01254 float new_depth; 01255 int screen_loc[2]; 01256 int new_dist; 01257 01258 copy_v3_v3(location, vco); 01259 01260 mul_m4_v3(obmat, location); 01261 01262 new_depth = len_v3v3(location, ray_start); 01263 01264 project_int(ar, location, screen_loc); 01265 new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]); 01266 01267 if (new_dist <= *r_dist && new_depth < *r_depth) 01268 { 01269 *r_depth = new_depth; 01270 retval = 1; 01271 01272 copy_v3_v3(r_loc, location); 01273 01274 if (r_no) 01275 { 01276 normal_short_to_float_v3(r_no, vno); 01277 mul_m3_v3(timat, r_no); 01278 normalize_v3(r_no); 01279 } 01280 01281 *r_dist = new_dist; 01282 } 01283 } 01284 01285 return retval; 01286 } 01287 01288 static int snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float obmat[][4], 01289 const float ray_start[3], const float ray_normal[3], const float mval[2], 01290 float r_loc[3], float *UNUSED(r_no), int *r_dist, float *r_depth) 01291 { 01292 float imat[4][4]; 01293 float ray_start_local[3], ray_normal_local[3]; 01294 int retval = 0; 01295 01296 invert_m4_m4(imat, obmat); 01297 01298 copy_v3_v3(ray_start_local, ray_start); 01299 copy_v3_v3(ray_normal_local, ray_normal); 01300 01301 mul_m4_v3(imat, ray_start_local); 01302 mul_mat3_m4_v3(imat, ray_normal_local); 01303 01304 if(arm->edbo) 01305 { 01306 EditBone *eBone; 01307 01308 for (eBone=arm->edbo->first; eBone; eBone=eBone->next) { 01309 if (eBone->layer & arm->layer) { 01310 /* skip hidden or moving (selected) bones */ 01311 if ((eBone->flag & (BONE_HIDDEN_A|BONE_ROOTSEL|BONE_TIPSEL))==0) { 01312 switch (snap_mode) 01313 { 01314 case SCE_SNAP_MODE_VERTEX: 01315 retval |= snapVertex(ar, eBone->head, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth); 01316 retval |= snapVertex(ar, eBone->tail, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth); 01317 break; 01318 case SCE_SNAP_MODE_EDGE: 01319 retval |= snapEdge(ar, eBone->head, NULL, eBone->tail, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth); 01320 break; 01321 } 01322 } 01323 } 01324 } 01325 } 01326 else if (ob->pose && ob->pose->chanbase.first) 01327 { 01328 bPoseChannel *pchan; 01329 Bone *bone; 01330 01331 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { 01332 bone= pchan->bone; 01333 /* skip hidden bones */ 01334 if (bone && !(bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))) { 01335 float *head_vec = pchan->pose_head; 01336 float *tail_vec = pchan->pose_tail; 01337 01338 switch (snap_mode) 01339 { 01340 case SCE_SNAP_MODE_VERTEX: 01341 retval |= snapVertex(ar, head_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth); 01342 retval |= snapVertex(ar, tail_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth); 01343 break; 01344 case SCE_SNAP_MODE_EDGE: 01345 retval |= snapEdge(ar, head_vec, NULL, tail_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth); 01346 break; 01347 } 01348 } 01349 } 01350 } 01351 01352 return retval; 01353 } 01354 01355 static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, EditMesh *em, float obmat[][4], 01356 const float ray_start[3], const float ray_normal[3], const float mval[2], 01357 float r_loc[3], float r_no[3], int *r_dist, float *r_depth) 01358 { 01359 int retval = 0; 01360 int totvert = dm->getNumVerts(dm); 01361 int totface = dm->getNumFaces(dm); 01362 01363 if (totvert > 0) { 01364 float imat[4][4]; 01365 float timat[3][3]; /* transpose inverse matrix for normals */ 01366 float ray_start_local[3], ray_normal_local[3]; 01367 int test = 1; 01368 01369 invert_m4_m4(imat, obmat); 01370 01371 copy_m3_m4(timat, imat); 01372 transpose_m3(timat); 01373 01374 copy_v3_v3(ray_start_local, ray_start); 01375 copy_v3_v3(ray_normal_local, ray_normal); 01376 01377 mul_m4_v3(imat, ray_start_local); 01378 mul_mat3_m4_v3(imat, ray_normal_local); 01379 01380 01381 /* If number of vert is more than an arbitrary limit, 01382 * test against boundbox first 01383 * */ 01384 if (totface > 16) { 01385 struct BoundBox *bb = object_get_boundbox(ob); 01386 test = ray_hit_boundbox(bb, ray_start_local, ray_normal_local); 01387 } 01388 01389 if (test == 1) { 01390 01391 switch (snap_mode) 01392 { 01393 case SCE_SNAP_MODE_FACE: 01394 { 01395 #ifdef USE_BVH_FACE_SNAP // Added for durian 01396 BVHTreeRayHit hit; 01397 BVHTreeFromMesh treeData; 01398 01399 /* local scale in normal direction */ 01400 float local_scale = len_v3(ray_normal_local); 01401 01402 treeData.em_evil= em; 01403 bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 4, 6); 01404 01405 hit.index = -1; 01406 hit.dist = *r_depth * (*r_depth == FLT_MAX ? 1.0f : local_scale); 01407 01408 if(treeData.tree && BLI_bvhtree_ray_cast(treeData.tree, ray_start_local, ray_normal_local, 0.0f, &hit, treeData.raycast_callback, &treeData) != -1) 01409 { 01410 if(hit.dist/local_scale <= *r_depth) { 01411 *r_depth= hit.dist/local_scale; 01412 copy_v3_v3(r_loc, hit.co); 01413 copy_v3_v3(r_no, hit.no); 01414 01415 /* back to worldspace */ 01416 mul_m4_v3(obmat, r_loc); 01417 copy_v3_v3(r_no, hit.no); 01418 01419 mul_m3_v3(timat, r_no); 01420 normalize_v3(r_no); 01421 01422 retval |= 1; 01423 } 01424 } 01425 break; 01426 01427 #else 01428 MVert *verts = dm->getVertArray(dm); 01429 MFace *faces = dm->getFaceArray(dm); 01430 int *index_array = NULL; 01431 int index = 0; 01432 int i; 01433 01434 if (em != NULL) 01435 { 01436 index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX); 01437 EM_init_index_arrays(em, 0, 0, 1); 01438 } 01439 01440 for( i = 0; i < totface; i++) { 01441 EditFace *efa = NULL; 01442 MFace *f = faces + i; 01443 01444 test = 1; /* reset for every face */ 01445 01446 if (em != NULL) 01447 { 01448 if (index_array) 01449 { 01450 index = index_array[i]; 01451 } 01452 else 01453 { 01454 index = i; 01455 } 01456 01457 if (index == ORIGINDEX_NONE) 01458 { 01459 test = 0; 01460 } 01461 else 01462 { 01463 efa = EM_get_face_for_index(index); 01464 01465 if (efa && (efa->h || (efa->v1->f & SELECT) || (efa->v2->f & SELECT) || (efa->v3->f & SELECT) || (efa->v4 && efa->v4->f & SELECT))) 01466 { 01467 test = 0; 01468 } 01469 } 01470 } 01471 01472 01473 if (test) 01474 { 01475 int result; 01476 float *v4co = NULL; 01477 01478 if (f->v4) 01479 { 01480 v4co = verts[f->v4].co; 01481 } 01482 01483 result = snapFace(ar, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, v4co, mval, ray_start, ray_start_local, ray_normal_local, obmat, timat, loc, no, dist, depth); 01484 retval |= result; 01485 01486 if (f->v4 && result == 0) 01487 { 01488 retval |= snapFace(ar, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, verts[f->v2].co, mval, ray_start, ray_start_local, ray_normal_local, obmat, timat, loc, no, dist, depth); 01489 } 01490 } 01491 } 01492 01493 if (em != NULL) 01494 { 01495 EM_free_index_arrays(); 01496 } 01497 #endif 01498 break; 01499 } 01500 case SCE_SNAP_MODE_VERTEX: 01501 { 01502 MVert *verts = dm->getVertArray(dm); 01503 int *index_array = NULL; 01504 int index = 0; 01505 int i; 01506 01507 if (em != NULL) 01508 { 01509 index_array = dm->getVertDataArray(dm, CD_ORIGINDEX); 01510 EM_init_index_arrays(em, 1, 0, 0); 01511 } 01512 01513 for( i = 0; i < totvert; i++) { 01514 EditVert *eve = NULL; 01515 MVert *v = verts + i; 01516 01517 test = 1; /* reset for every vert */ 01518 01519 if (em != NULL) 01520 { 01521 if (index_array) 01522 { 01523 index = index_array[i]; 01524 } 01525 else 01526 { 01527 index = i; 01528 } 01529 01530 if (index == ORIGINDEX_NONE) 01531 { 01532 test = 0; 01533 } 01534 else 01535 { 01536 eve = EM_get_vert_for_index(index); 01537 01538 if (eve && (eve->h || (eve->f & SELECT))) 01539 { 01540 test = 0; 01541 } 01542 } 01543 } 01544 01545 01546 if (test) 01547 { 01548 retval |= snapVertex(ar, v->co, v->no, obmat, timat, ray_start, ray_start_local, ray_normal_local, mval, r_loc, r_no, r_dist, r_depth); 01549 } 01550 } 01551 01552 if (em != NULL) 01553 { 01554 EM_free_index_arrays(); 01555 } 01556 break; 01557 } 01558 case SCE_SNAP_MODE_EDGE: 01559 { 01560 MVert *verts = dm->getVertArray(dm); 01561 MEdge *edges = dm->getEdgeArray(dm); 01562 int totedge = dm->getNumEdges(dm); 01563 int *index_array = NULL; 01564 int index = 0; 01565 int i; 01566 01567 if (em != NULL) 01568 { 01569 index_array = dm->getEdgeDataArray(dm, CD_ORIGINDEX); 01570 EM_init_index_arrays(em, 0, 1, 0); 01571 } 01572 01573 for( i = 0; i < totedge; i++) { 01574 EditEdge *eed = NULL; 01575 MEdge *e = edges + i; 01576 01577 test = 1; /* reset for every vert */ 01578 01579 if (em != NULL) 01580 { 01581 if (index_array) 01582 { 01583 index = index_array[i]; 01584 } 01585 else 01586 { 01587 index = i; 01588 } 01589 01590 if (index == ORIGINDEX_NONE) 01591 { 01592 test = 0; 01593 } 01594 else 01595 { 01596 eed = EM_get_edge_for_index(index); 01597 01598 if (eed && (eed->h || (eed->v1->f & SELECT) || (eed->v2->f & SELECT))) 01599 { 01600 test = 0; 01601 } 01602 } 01603 } 01604 01605 01606 if (test) 01607 { 01608 retval |= snapEdge(ar, verts[e->v1].co, verts[e->v1].no, verts[e->v2].co, verts[e->v2].no, obmat, timat, ray_start, ray_start_local, ray_normal_local, mval, r_loc, r_no, r_dist, r_depth); 01609 } 01610 } 01611 01612 if (em != NULL) 01613 { 01614 EM_free_index_arrays(); 01615 } 01616 break; 01617 } 01618 } 01619 } 01620 } 01621 01622 return retval; 01623 } 01624 01625 static int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obmat[][4], 01626 const float ray_start[3], const float ray_normal[3], const float mval[2], 01627 float r_loc[3], float r_no[3], int *r_dist, float *r_depth) 01628 { 01629 ToolSettings *ts= scene->toolsettings; 01630 int retval = 0; 01631 01632 if (ob->type == OB_MESH) { 01633 EditMesh *em; 01634 DerivedMesh *dm; 01635 01636 if (editobject) 01637 { 01638 em = ((Mesh *)ob->data)->edit_mesh; 01639 /* dm = editmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH); */ 01640 dm = editmesh_get_derived_base(ob, em); /* limitation, em & dm MUST have the same number of faces */ 01641 } 01642 else 01643 { 01644 em = NULL; 01645 dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); 01646 } 01647 01648 retval = snapDerivedMesh(ts->snap_mode, ar, ob, dm, em, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, r_depth); 01649 01650 dm->release(dm); 01651 } 01652 else if (ob->type == OB_ARMATURE) 01653 { 01654 retval = snapArmature(ts->snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, r_depth); 01655 } 01656 01657 return retval; 01658 } 01659 01660 static int snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, const float mval[2], 01661 int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) 01662 { 01663 Base *base; 01664 float depth = FLT_MAX; 01665 int retval = 0; 01666 float ray_start[3], ray_normal[3]; 01667 01668 ED_view3d_win_to_ray(ar, v3d, mval, ray_start, ray_normal); 01669 01670 if (mode == SNAP_ALL && obedit) 01671 { 01672 Object *ob = obedit; 01673 01674 retval |= snapObject(scene, ar, ob, 1, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, &depth); 01675 } 01676 01677 /* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA 01678 * which makes the loop skip it, even the derived mesh will never change 01679 * 01680 * To solve that problem, we do it first as an exception. 01681 * */ 01682 base= BASACT; 01683 if(base && base->object && base->object->mode & OB_MODE_PARTICLE_EDIT) 01684 { 01685 Object *ob = base->object; 01686 retval |= snapObject(scene, ar, ob, 0, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, &depth); 01687 } 01688 01689 for ( base = FIRSTBASE; base != NULL; base = base->next ) { 01690 if ( (BASE_VISIBLE(v3d, base)) && 01691 (base->flag & (BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA)) == 0 && 01692 01693 ( (mode == SNAP_NOT_SELECTED && (base->flag & (SELECT|BA_WAS_SEL)) == 0) || 01694 (ELEM(mode, SNAP_ALL, SNAP_NOT_OBEDIT) && base != BASACT)) ) 01695 { 01696 Object *ob = base->object; 01697 01698 if (ob->transflag & OB_DUPLI) 01699 { 01700 DupliObject *dupli_ob; 01701 ListBase *lb = object_duplilist(scene, ob); 01702 01703 for(dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) 01704 { 01705 Object *dob = dupli_ob->ob; 01706 01707 retval |= snapObject(scene, ar, dob, 0, dupli_ob->mat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, &depth); 01708 } 01709 01710 free_object_duplilist(lb); 01711 } 01712 01713 retval |= snapObject(scene, ar, ob, 0, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, &depth); 01714 } 01715 } 01716 01717 return retval; 01718 } 01719 01720 int snapObjectsTransform(TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) 01721 { 01722 return snapObjects(t->scene, t->view, t->ar, t->obedit, mval, r_dist, r_loc, r_no, mode); 01723 } 01724 01725 int snapObjectsContext(bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) 01726 { 01727 ScrArea *sa = CTX_wm_area(C); 01728 View3D *v3d = sa->spacedata.first; 01729 01730 return snapObjects(CTX_data_scene(C), v3d, CTX_wm_region(C), CTX_data_edit_object(C), mval, r_dist, r_loc, r_no, mode); 01731 } 01732 01733 /******************** PEELING *********************************/ 01734 01735 01736 static int cmpPeel(void *arg1, void *arg2) 01737 { 01738 DepthPeel *p1 = arg1; 01739 DepthPeel *p2 = arg2; 01740 int val = 0; 01741 01742 if (p1->depth < p2->depth) 01743 { 01744 val = -1; 01745 } 01746 else if (p1->depth > p2->depth) 01747 { 01748 val = 1; 01749 } 01750 01751 return val; 01752 } 01753 01754 static void removeDoublesPeel(ListBase *depth_peels) 01755 { 01756 DepthPeel *peel; 01757 01758 for (peel = depth_peels->first; peel; peel = peel->next) 01759 { 01760 DepthPeel *next_peel = peel->next; 01761 01762 if (next_peel && ABS(peel->depth - next_peel->depth) < 0.0015f) 01763 { 01764 peel->next = next_peel->next; 01765 01766 if (next_peel->next) 01767 { 01768 next_peel->next->prev = peel; 01769 } 01770 01771 MEM_freeN(next_peel); 01772 } 01773 } 01774 } 01775 01776 static void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float no[3], Object *ob) 01777 { 01778 DepthPeel *peel = MEM_callocN(sizeof(DepthPeel), "DepthPeel"); 01779 01780 peel->depth = depth; 01781 peel->ob = ob; 01782 copy_v3_v3(peel->p, p); 01783 copy_v3_v3(peel->no, no); 01784 01785 BLI_addtail(depth_peels, peel); 01786 01787 peel->flag = 0; 01788 } 01789 01790 static int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], 01791 const float ray_start[3], const float ray_normal[3], const float UNUSED(mval[2]), 01792 ListBase *depth_peels) 01793 { 01794 int retval = 0; 01795 int totvert = dm->getNumVerts(dm); 01796 int totface = dm->getNumFaces(dm); 01797 01798 if (totvert > 0) { 01799 float imat[4][4]; 01800 float timat[3][3]; /* transpose inverse matrix for normals */ 01801 float ray_start_local[3], ray_normal_local[3]; 01802 int test = 1; 01803 01804 invert_m4_m4(imat, obmat); 01805 01806 copy_m3_m4(timat, imat); 01807 transpose_m3(timat); 01808 01809 copy_v3_v3(ray_start_local, ray_start); 01810 copy_v3_v3(ray_normal_local, ray_normal); 01811 01812 mul_m4_v3(imat, ray_start_local); 01813 mul_mat3_m4_v3(imat, ray_normal_local); 01814 01815 01816 /* If number of vert is more than an arbitrary limit, 01817 * test against boundbox first 01818 * */ 01819 if (totface > 16) { 01820 struct BoundBox *bb = object_get_boundbox(ob); 01821 test = ray_hit_boundbox(bb, ray_start_local, ray_normal_local); 01822 } 01823 01824 if (test == 1) { 01825 MVert *verts = dm->getVertArray(dm); 01826 MFace *faces = dm->getFaceArray(dm); 01827 int i; 01828 01829 for( i = 0; i < totface; i++) { 01830 MFace *f = faces + i; 01831 float lambda; 01832 int result; 01833 01834 01835 result = isect_ray_tri_threshold_v3(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL, 0.001); 01836 01837 if (result) { 01838 float location[3], normal[3]; 01839 float intersect[3]; 01840 float new_depth; 01841 01842 copy_v3_v3(intersect, ray_normal_local); 01843 mul_v3_fl(intersect, lambda); 01844 add_v3_v3(intersect, ray_start_local); 01845 01846 copy_v3_v3(location, intersect); 01847 01848 if (f->v4) 01849 normal_quad_v3( normal,verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co); 01850 else 01851 normal_tri_v3( normal,verts[f->v1].co, verts[f->v2].co, verts[f->v3].co); 01852 01853 mul_m4_v3(obmat, location); 01854 01855 new_depth = len_v3v3(location, ray_start); 01856 01857 mul_m3_v3(timat, normal); 01858 normalize_v3(normal); 01859 01860 addDepthPeel(depth_peels, new_depth, location, normal, ob); 01861 } 01862 01863 if (f->v4 && result == 0) 01864 { 01865 result = isect_ray_tri_threshold_v3(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL, 0.001); 01866 01867 if (result) { 01868 float location[3], normal[3]; 01869 float intersect[3]; 01870 float new_depth; 01871 01872 copy_v3_v3(intersect, ray_normal_local); 01873 mul_v3_fl(intersect, lambda); 01874 add_v3_v3(intersect, ray_start_local); 01875 01876 copy_v3_v3(location, intersect); 01877 01878 if (f->v4) 01879 normal_quad_v3( normal,verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co); 01880 else 01881 normal_tri_v3( normal,verts[f->v1].co, verts[f->v2].co, verts[f->v3].co); 01882 01883 mul_m4_v3(obmat, location); 01884 01885 new_depth = len_v3v3(location, ray_start); 01886 01887 mul_m3_v3(timat, normal); 01888 normalize_v3(normal); 01889 01890 addDepthPeel(depth_peels, new_depth, location, normal, ob); 01891 } 01892 } 01893 } 01894 } 01895 } 01896 01897 return retval; 01898 } 01899 01900 static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase *depth_peels, const float mval[2]) 01901 { 01902 Base *base; 01903 int retval = 0; 01904 float ray_start[3], ray_normal[3]; 01905 01906 ED_view3d_win_to_ray(ar, v3d, mval, ray_start, ray_normal); 01907 01908 for ( base = scene->base.first; base != NULL; base = base->next ) { 01909 if ( BASE_SELECTABLE(v3d, base) ) { 01910 Object *ob = base->object; 01911 01912 if (ob->transflag & OB_DUPLI) 01913 { 01914 DupliObject *dupli_ob; 01915 ListBase *lb = object_duplilist(scene, ob); 01916 01917 for(dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) 01918 { 01919 Object *dob = dupli_ob->ob; 01920 01921 if (dob->type == OB_MESH) { 01922 EditMesh *em; 01923 DerivedMesh *dm = NULL; 01924 int val; 01925 01926 if (dob != obedit) 01927 { 01928 dm = mesh_get_derived_final(scene, dob, CD_MASK_BAREMESH); 01929 01930 val = peelDerivedMesh(dob, dm, dob->obmat, ray_start, ray_normal, mval, depth_peels); 01931 } 01932 else 01933 { 01934 em = ((Mesh *)dob->data)->edit_mesh; 01935 dm = editmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH); 01936 01937 val = peelDerivedMesh(dob, dm, dob->obmat, ray_start, ray_normal, mval, depth_peels); 01938 } 01939 01940 retval = retval || val; 01941 01942 dm->release(dm); 01943 } 01944 } 01945 01946 free_object_duplilist(lb); 01947 } 01948 01949 if (ob->type == OB_MESH) { 01950 EditMesh *em; 01951 DerivedMesh *dm = NULL; 01952 int val; 01953 01954 if (ob != obedit) 01955 { 01956 dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); 01957 01958 val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels); 01959 } 01960 else 01961 { 01962 em = ((Mesh *)ob->data)->edit_mesh; 01963 dm = editmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH); 01964 01965 val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels); 01966 } 01967 01968 retval = retval || val; 01969 01970 dm->release(dm); 01971 } 01972 } 01973 } 01974 01975 BLI_sortlist(depth_peels, cmpPeel); 01976 removeDoublesPeel(depth_peels); 01977 01978 return retval; 01979 } 01980 01981 int peelObjectsTransForm(TransInfo *t, ListBase *depth_peels, const float mval[2]) 01982 { 01983 return peelObjects(t->scene, t->view, t->ar, t->obedit, depth_peels, mval); 01984 } 01985 01986 int peelObjectsContext(bContext *C, ListBase *depth_peels, const float mval[2]) 01987 { 01988 ScrArea *sa = CTX_wm_area(C); 01989 View3D *v3d = sa->spacedata.first; 01990 01991 return peelObjects(CTX_data_scene(C), v3d, CTX_wm_region(C), CTX_data_edit_object(C), depth_peels, mval); 01992 } 01993 01994 /*================================================================*/ 01995 01996 static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], GearsType action); 01997 01998 01999 void snapGridAction(TransInfo *t, float *val, GearsType action) 02000 { 02001 float fac[3]; 02002 02003 fac[NO_GEARS] = t->snap[0]; 02004 fac[BIG_GEARS] = t->snap[1]; 02005 fac[SMALL_GEARS] = t->snap[2]; 02006 02007 applyGrid(t, val, t->idx_max, fac, action); 02008 } 02009 02010 02011 void snapGrid(TransInfo *t, float *val) 02012 { 02013 GearsType action; 02014 02015 // Only do something if using Snap to Grid 02016 if (t->tsnap.mode != SCE_SNAP_MODE_INCREMENT) 02017 return; 02018 02019 action = activeSnap(t) ? BIG_GEARS : NO_GEARS; 02020 02021 if (action == BIG_GEARS && (t->modifiers & MOD_PRECISION)) { 02022 action = SMALL_GEARS; 02023 } 02024 02025 snapGridAction(t, val, action); 02026 } 02027 02028 02029 static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], GearsType action) 02030 { 02031 int i; 02032 float asp[3] = {1.0f, 1.0f, 1.0f}; // TODO: Remove hard coded limit here (3) 02033 02034 if(max_index > 2) { 02035 printf("applyGrid: invalid index %d, clamping\n", max_index); 02036 max_index= 2; 02037 } 02038 02039 // Early bailing out if no need to snap 02040 if (fac[action] == 0.0f) 02041 return; 02042 02043 /* evil hack - snapping needs to be adapted for image aspect ratio */ 02044 if((t->spacetype==SPACE_IMAGE) && (t->mode==TFM_TRANSLATION)) { 02045 ED_space_image_uv_aspect(t->sa->spacedata.first, asp, asp+1); 02046 } 02047 02048 for (i=0; i<=max_index; i++) { 02049 val[i]= fac[action]*asp[i]*(float)floor(val[i]/(fac[action]*asp[i]) +0.5f); 02050 } 02051 }