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