diff options
Diffstat (limited to 'source/blender/src/transform_snap.c')
-rw-r--r-- | source/blender/src/transform_snap.c | 1282 |
1 files changed, 0 insertions, 1282 deletions
diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c deleted file mode 100644 index e7937e72c2b..00000000000 --- a/source/blender/src/transform_snap.c +++ /dev/null @@ -1,1282 +0,0 @@ -/** - * $Id: - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Martin Poirier - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include <stdlib.h> -#include <math.h> -#include <stdio.h> - -#include "PIL_time.h" - -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_meshdata_types.h" // Temporary, for snapping to other unselected meshes -#include "DNA_space_types.h" -#include "DNA_screen_types.h" -#include "DNA_userdef_types.h" -#include "DNA_view3d_types.h" - -#include "BLI_arithb.h" -#include "BLI_editVert.h" - -#include "BDR_drawobject.h" - -#include "editmesh.h" -#include "BIF_editsima.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" -#include "BIF_mywindow.h" -#include "BIF_resources.h" -#include "BIF_screen.h" -#include "BIF_editsima.h" -#include "BIF_drawimage.h" -#include "BIF_editmesh.h" - -#include "BKE_global.h" -#include "BKE_utildefines.h" -#include "BKE_DerivedMesh.h" -#include "BKE_object.h" -#include "BKE_anim.h" /* for duplis */ - -#include "BSE_view.h" - -#include "MEM_guardedalloc.h" - -#include "transform.h" -#include "mydevice.h" /* for KEY defines */ -#include "blendef.h" /* for selection modes */ - -/********************* PROTOTYPES ***********************/ - -void setSnappingCallback(TransInfo *t); - -void ApplySnapTranslation(TransInfo *t, float vec[3]); -void ApplySnapRotation(TransInfo *t, float *vec); -void ApplySnapResize(TransInfo *t, float *vec); - -void CalcSnapGrid(TransInfo *t, float *vec); -void CalcSnapGeometry(TransInfo *t, float *vec); - -void TargetSnapMedian(TransInfo *t); -void TargetSnapCenter(TransInfo *t); -void TargetSnapClosest(TransInfo *t); -void TargetSnapActive(TransInfo *t); - -float RotationBetween(TransInfo *t, float p1[3], float p2[3]); -float TranslationBetween(TransInfo *t, float p1[3], float p2[3]); -float ResizeBetween(TransInfo *t, float p1[3], float p2[3]); - -/* Modes */ -#define NOT_SELECTED 0 -#define NOT_ACTIVE 1 -int snapObjects(int *dist, float *loc, float *no, int mode); - - -/****************** IMPLEMENTATIONS *********************/ - -int BIF_snappingSupported(void) -{ - int status = 0; - - if (G.obedit == NULL || G.obedit->type==OB_MESH) /* only support object or mesh */ - { - status = 1; - } - - return status; -} - -void drawSnapping(TransInfo *t) -{ - if ((t->tsnap.status & (SNAP_ON|POINT_INIT|TARGET_INIT)) == (SNAP_ON|POINT_INIT|TARGET_INIT) && - (G.qual & LR_CTRLKEY)) { - - char col[4]; - BIF_GetThemeColor3ubv(TH_TRANSFORM, col); - glColor4ub(col[0], col[1], col[2], 128); - - if (t->spacetype==SPACE_VIEW3D) { - float unitmat[4][4]; - float size; - - glDisable(GL_DEPTH_TEST); - - size = get_drawsize(G.vd, t->tsnap.snapPoint); - - size *= 0.5f * BIF_GetThemeValuef(TH_VERTEX_SIZE); - - glPushMatrix(); - - glTranslatef(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]); - - /* draw normal if needed */ - if (usingSnappingNormal(t) && validSnappingNormal(t)) - { - glBegin(GL_LINES); - glVertex3f(0, 0, 0); - glVertex3f(t->tsnap.snapNormal[0], t->tsnap.snapNormal[1], t->tsnap.snapNormal[2]); - glEnd(); - } - - /* sets view screen aligned */ - glRotatef( -360.0f*saacos(G.vd->viewquat[0])/(float)M_PI, G.vd->viewquat[1], G.vd->viewquat[2], G.vd->viewquat[3]); - - Mat4One(unitmat); - drawcircball(GL_LINE_LOOP, unitmat[3], size, unitmat); - - glPopMatrix(); - - if(G.vd->zbuf) glEnable(GL_DEPTH_TEST); - } else if (t->spacetype==SPACE_IMAGE) { - /*This will not draw, and Im nor sure why - campbell */ - - /* - float xuser_asp, yuser_asp; - int wi, hi; - float w, h; - - calc_image_view(G.sima, 'f'); // float - myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax); - glLoadIdentity(); - - aspect_sima(G.sima, &xuser_asp, &yuser_asp); - - transform_width_height_tface_uv(&wi, &hi); - w = (((float)wi)/256.0f)*G.sima->zoom * xuser_asp; - h = (((float)hi)/256.0f)*G.sima->zoom * yuser_asp; - - cpack(0xFFFFFF); - glTranslatef(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], 0.0f); - - //glRectf(0,0,1,1); - - setlinestyle(0); - cpack(0x0); - fdrawline(-0.020/w, 0, -0.1/w, 0); - fdrawline(0.1/w, 0, .020/w, 0); - fdrawline(0, -0.020/h, 0, -0.1/h); - fdrawline(0, 0.1/h, 0, 0.020/h); - - glTranslatef(-t->tsnap.snapPoint[0], -t->tsnap.snapPoint[1], 0.0f); - setlinestyle(0); - */ - - } - } -} - -int handleSnapping(TransInfo *t, int event) -{ - int status = 0; - - if (BIF_snappingSupported() && event == TABKEY && (G.qual & LR_SHIFTKEY) == LR_SHIFTKEY) - { - /* toggle snap and reinit */ - G.scene->snap_flag ^= SCE_SNAP; - initSnapping(t); - status = 1; - } - - return status; -} - -void applySnapping(TransInfo *t, float *vec) -{ - if ((t->tsnap.status & SNAP_ON) && - (G.qual & LR_CTRLKEY)) - { - double current = PIL_check_seconds_timer(); - - // Time base quirky code to go around findnearest slowness - /* !TODO! add exception for object mode, no need to slow it down then */ - if (current - t->tsnap.last >= 0.1) - { - t->tsnap.calcSnap(t, vec); - t->tsnap.targetSnap(t); - - t->tsnap.last = current; - } - if ((t->tsnap.status & (POINT_INIT|TARGET_INIT)) == (POINT_INIT|TARGET_INIT)) - { - t->tsnap.applySnap(t, vec); - } - } -} - -void resetSnapping(TransInfo *t) -{ - t->tsnap.status = 0; - t->tsnap.modePoint = 0; - t->tsnap.modeTarget = 0; - t->tsnap.last = 0; - t->tsnap.applySnap = NULL; - - t->tsnap.snapNormal[0] = 0; - t->tsnap.snapNormal[1] = 0; - t->tsnap.snapNormal[2] = 0; -} - -int usingSnappingNormal(TransInfo *t) -{ - if (G.scene->snap_flag & SCE_SNAP_ROTATE) - { - return 1; - } - else - { - return 0; - } -} - -int validSnappingNormal(TransInfo *t) -{ - if ((t->tsnap.status & (POINT_INIT|TARGET_INIT)) == (POINT_INIT|TARGET_INIT)) - { - if (Inpf(t->tsnap.snapNormal, t->tsnap.snapNormal) > 0) - { - return 1; - } - } - - return 0; -} - -void initSnapping(TransInfo *t) -{ - resetSnapping(t); - - if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && // Only 3D view or UV - (t->flag & T_CAMERA) == 0) { // Not with camera selected - setSnappingCallback(t); - - /* Edit mode */ - if (t->tsnap.applySnap != NULL && // A snapping function actually exist - (G.scene->snap_flag & SCE_SNAP) && // Only if the snap flag is on - (G.obedit != NULL && G.obedit->type==OB_MESH) && // Temporary limited to edit mode meshes - ((t->flag & T_PROP_EDIT) == 0) ) // No PET, obviously - { - t->tsnap.status |= SNAP_ON; - t->tsnap.modePoint = SNAP_GEO; - } - /* Object mode */ - else if (t->tsnap.applySnap != NULL && // A snapping function actually exist - (G.scene->snap_flag & SCE_SNAP) && // Only if the snap flag is on - (G.obedit == NULL) ) // Object Mode - { - t->tsnap.status |= SNAP_ON; - t->tsnap.modePoint = SNAP_GEO; - } - else - { - /* Grid if snap is not possible */ - t->tsnap.modePoint = SNAP_GRID; - } - } - else - { - /* Always grid outside of 3D view */ - t->tsnap.modePoint = SNAP_GRID; - } -} - -void setSnappingCallback(TransInfo *t) -{ - t->tsnap.calcSnap = CalcSnapGeometry; - - switch(G.scene->snap_target) - { - case SCE_SNAP_TARGET_CLOSEST: - t->tsnap.modeTarget = SNAP_CLOSEST; - t->tsnap.targetSnap = TargetSnapClosest; - break; - case SCE_SNAP_TARGET_CENTER: - t->tsnap.modeTarget = SNAP_CENTER; - t->tsnap.targetSnap = TargetSnapCenter; - break; - case SCE_SNAP_TARGET_MEDIAN: - t->tsnap.modeTarget = SNAP_MEDIAN; - t->tsnap.targetSnap = TargetSnapMedian; - break; - case SCE_SNAP_TARGET_ACTIVE: - t->tsnap.modeTarget = SNAP_ACTIVE; - t->tsnap.targetSnap = TargetSnapActive; - break; - - } - - switch (t->mode) - { - case TFM_TRANSLATION: - t->tsnap.applySnap = ApplySnapTranslation; - t->tsnap.distance = TranslationBetween; - break; - case TFM_ROTATION: - t->tsnap.applySnap = ApplySnapRotation; - t->tsnap.distance = RotationBetween; - - // Can't do TARGET_CENTER with rotation, use TARGET_MEDIAN instead - if (G.scene->snap_target == SCE_SNAP_TARGET_CENTER) { - t->tsnap.modeTarget = SNAP_MEDIAN; - t->tsnap.targetSnap = TargetSnapMedian; - } - break; - case TFM_RESIZE: - t->tsnap.applySnap = ApplySnapResize; - t->tsnap.distance = ResizeBetween; - - // Can't do TARGET_CENTER with resize, use TARGET_MEDIAN instead - if (G.scene->snap_target == SCE_SNAP_TARGET_CENTER) { - t->tsnap.modeTarget = SNAP_MEDIAN; - t->tsnap.targetSnap = TargetSnapMedian; - } - break; - default: - t->tsnap.applySnap = NULL; - break; - } -} - -/********************** APPLY **************************/ - -void ApplySnapTranslation(TransInfo *t, float vec[3]) -{ - VecSubf(vec, t->tsnap.snapPoint, t->tsnap.snapTarget); -} - -void ApplySnapRotation(TransInfo *t, float *vec) -{ - if (t->tsnap.modeTarget == SNAP_CLOSEST) { - *vec = t->tsnap.dist; - } - else { - *vec = RotationBetween(t, t->tsnap.snapTarget, t->tsnap.snapPoint); - } -} - -void ApplySnapResize(TransInfo *t, float vec[3]) -{ - if (t->tsnap.modeTarget == SNAP_CLOSEST) { - vec[0] = vec[1] = vec[2] = t->tsnap.dist; - } - else { - vec[0] = vec[1] = vec[2] = ResizeBetween(t, t->tsnap.snapTarget, t->tsnap.snapPoint); - } -} - -/********************** DISTANCE **************************/ - -float TranslationBetween(TransInfo *t, float p1[3], float p2[3]) -{ - return VecLenf(p1, p2); -} - -float RotationBetween(TransInfo *t, float p1[3], float p2[3]) -{ - float angle, start[3], end[3], center[3]; - - VECCOPY(center, t->center); - if(t->flag & (T_EDIT|T_POSE)) { - Object *ob= G.obedit?G.obedit:t->poseobj; - Mat4MulVecfl(ob->obmat, center); - } - - VecSubf(start, p1, center); - VecSubf(end, p2, center); - - // Angle around a constraint axis (error prone, will need debug) - if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { - float axis[3], tmp[3]; - - t->con.applyRot(t, NULL, axis, NULL); - - Projf(tmp, end, axis); - VecSubf(end, end, tmp); - - Projf(tmp, start, axis); - VecSubf(start, start, tmp); - - Normalize(end); - Normalize(start); - - Crossf(tmp, start, end); - - if (Inpf(tmp, axis) < 0.0) - angle = -acos(Inpf(start, end)); - else - angle = acos(Inpf(start, end)); - } - else { - float mtx[3][3]; - - Mat3CpyMat4(mtx, t->viewmat); - - Mat3MulVecfl(mtx, end); - Mat3MulVecfl(mtx, start); - - angle = atan2(start[1],start[0]) - atan2(end[1],end[0]); - } - - if (angle > M_PI) { - angle = angle - 2 * M_PI; - } - else if (angle < -(M_PI)) { - angle = 2 * M_PI + angle; - } - - return angle; -} - -float ResizeBetween(TransInfo *t, float p1[3], float p2[3]) -{ - float d1[3], d2[3], center[3]; - - VECCOPY(center, t->center); - if(t->flag & (T_EDIT|T_POSE)) { - Object *ob= G.obedit?G.obedit:t->poseobj; - Mat4MulVecfl(ob->obmat, center); - } - - VecSubf(d1, p1, center); - VecSubf(d2, p2, center); - - if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { - Mat3MulVecfl(t->con.pmtx, d1); - Mat3MulVecfl(t->con.pmtx, d2); - } - - return VecLength(d2) / VecLength(d1); -} - -/********************** CALC **************************/ - -void CalcSnapGrid(TransInfo *t, float *vec) -{ - snapGridAction(t, t->tsnap.snapPoint, BIG_GEARS); -} - -void CalcSnapGeometry(TransInfo *t, float *vec) -{ - /* Object mode */ - if (G.obedit == NULL) - { - if (t->spacetype == SPACE_VIEW3D) - { - float vec[3]; - float no[3]; - int found = 0; - int dist = 40; // Use a user defined value here - - found = snapObjects(&dist, vec, no, NOT_SELECTED); - if (found == 1) - { - float tangent[3]; - - VecSubf(tangent, vec, t->tsnap.snapPoint); - tangent[2] = 0; - - if (Inpf(tangent, tangent) > 0) - { - VECCOPY(t->tsnap.snapTangent, tangent); - } - - VECCOPY(t->tsnap.snapPoint, vec); - VECCOPY(t->tsnap.snapNormal, no); - - t->tsnap.status |= POINT_INIT; - } - else - { - t->tsnap.status &= ~POINT_INIT; - } - } - } - /* Mesh edit mode */ - else if (G.obedit != NULL && G.obedit->type==OB_MESH) - { - if (t->spacetype == SPACE_VIEW3D) - { - float vec[3]; - float no[3]; - int found = 0; - int dist = 40; // Use a user defined value here - - found = snapObjects(&dist, vec, no, NOT_ACTIVE); - if (found == 1) - { - VECCOPY(t->tsnap.snapPoint, vec); - VECCOPY(t->tsnap.snapNormal, no); - - t->tsnap.status |= POINT_INIT; - } - else - { - t->tsnap.status &= ~POINT_INIT; - } - } - else if (t->spacetype == SPACE_IMAGE) - { /* same as above but for UV's */ - MTFace *nearesttf=NULL; - float aspx, aspy; - int face_corner; - - find_nearest_uv(&nearesttf, NULL, NULL, &face_corner); - - if (nearesttf != NULL) - { - VECCOPY2D(t->tsnap.snapPoint, nearesttf->uv[face_corner]); - - transform_aspect_ratio_tface_uv(&aspx, &aspy); - t->tsnap.snapPoint[0] *= aspx; - t->tsnap.snapPoint[1] *= aspy; - - //Mat4MulVecfl(G.obedit->obmat, t->tsnap.snapPoint); - - t->tsnap.status |= POINT_INIT; - } - else - { - t->tsnap.status &= ~POINT_INIT; - } - } - } -} - -/********************** TARGET **************************/ - -void TargetSnapCenter(TransInfo *t) -{ - // Only need to calculate once - if ((t->tsnap.status & TARGET_INIT) == 0) - { - VECCOPY(t->tsnap.snapTarget, t->center); - if(t->flag & (T_EDIT|T_POSE)) { - Object *ob= G.obedit?G.obedit:t->poseobj; - Mat4MulVecfl(ob->obmat, t->tsnap.snapTarget); - } - - t->tsnap.status |= TARGET_INIT; - } -} - -void TargetSnapActive(TransInfo *t) -{ - // Only need to calculate once - if ((t->tsnap.status & TARGET_INIT) == 0) - { - TransData *td = NULL; - TransData *active_td = NULL; - int i; - - for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) - { - if (td->flag & TD_ACTIVE) - { - active_td = td; - break; - } - } - - if (active_td) - { - VECCOPY(t->tsnap.snapTarget, active_td->center); - - if(t->flag & (T_EDIT|T_POSE)) { - Object *ob= G.obedit?G.obedit:t->poseobj; - Mat4MulVecfl(ob->obmat, t->tsnap.snapTarget); - } - - t->tsnap.status |= TARGET_INIT; - } - /* No active, default to median */ - else - { - t->tsnap.modeTarget = SNAP_MEDIAN; - t->tsnap.targetSnap = TargetSnapMedian; - TargetSnapMedian(t); - } - } -} - -void TargetSnapMedian(TransInfo *t) -{ - // Only need to calculate once - if ((t->tsnap.status & TARGET_INIT) == 0) - { - TransData *td = NULL; - int i; - - t->tsnap.snapTarget[0] = 0; - t->tsnap.snapTarget[1] = 0; - t->tsnap.snapTarget[2] = 0; - - for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) - { - VecAddf(t->tsnap.snapTarget, t->tsnap.snapTarget, td->center); - } - - VecMulf(t->tsnap.snapTarget, 1.0 / t->total); - - if(t->flag & (T_EDIT|T_POSE)) { - Object *ob= G.obedit?G.obedit:t->poseobj; - Mat4MulVecfl(ob->obmat, t->tsnap.snapTarget); - } - - t->tsnap.status |= TARGET_INIT; - } -} - -void TargetSnapClosest(TransInfo *t) -{ - // Only valid if a snap point has been selected - if (t->tsnap.status & POINT_INIT) - { - TransData *closest = NULL, *td = NULL; - - /* Object mode */ - if (t->flag & T_OBJECT) - { - int i; - for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) - { - struct BoundBox *bb = object_get_boundbox(td->ob); - - /* use boundbox if possible */ - if (bb) - { - int j; - - for (j = 0; j < 8; j++) { - float loc[3]; - float dist; - - VECCOPY(loc, bb->vec[j]); - Mat4MulVecfl(td->ext->obmat, loc); - - dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); - - if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist)) - { - VECCOPY(t->tsnap.snapTarget, loc); - closest = td; - t->tsnap.dist = dist; - } - } - } - /* use element center otherwise */ - else - { - float loc[3]; - float dist; - - VECCOPY(loc, td->center); - - dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); - - if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist)) - { - VECCOPY(t->tsnap.snapTarget, loc); - closest = td; - t->tsnap.dist = dist; - } - } - } - } - else - { - int i; - for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) - { - float loc[3]; - float dist; - - VECCOPY(loc, td->center); - - if(t->flag & (T_EDIT|T_POSE)) { - Object *ob= G.obedit?G.obedit:t->poseobj; - Mat4MulVecfl(ob->obmat, loc); - } - - dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); - - if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist)) - { - VECCOPY(t->tsnap.snapTarget, loc); - closest = td; - t->tsnap.dist = dist; - } - } - } - - t->tsnap.status |= TARGET_INIT; - } -} -/*================================================================*/ - -int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth, short EditMesh) -{ - int retval = 0; - int totvert = dm->getNumVerts(dm); - int totface = dm->getNumFaces(dm); - - if (totvert > 0) { - float imat[4][4]; - float timat[3][3]; /* transpose inverse matrix for normals */ - float ray_start_local[3], ray_normal_local[3]; - int test = 1; - - Mat4Invert(imat, obmat); - - Mat3CpyMat4(timat, imat); - Mat3Transp(timat); - - VECCOPY(ray_start_local, ray_start); - VECCOPY(ray_normal_local, ray_normal); - - Mat4MulVecfl(imat, ray_start_local); - Mat4Mul3Vecfl(imat, ray_normal_local); - - - /* If number of vert is more than an arbitrary limit, - * test against boundbox first - * */ - if (totface > 16) { - struct BoundBox *bb = object_get_boundbox(ob); - test = ray_hit_boundbox(bb, ray_start_local, ray_normal_local); - } - - if (test == 1) { - - switch (G.scene->snap_mode) - { - case SCE_SNAP_MODE_FACE: - { - MVert *verts = dm->getVertArray(dm); - MFace *faces = dm->getFaceArray(dm); - int *index_array = NULL; - int index = 0; - int i; - - if (EditMesh) - { - index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX); - EM_init_index_arrays(0, 0, 1); - } - - for( i = 0; i < totface; i++) { - EditFace *efa = NULL; - MFace *f = faces + i; - float lambda; - int result; - - test = 1; /* reset for every face */ - - if (EditMesh) - { - if (index_array) - { - index = index_array[i]; - } - else - { - index = i; - } - - if (index == ORIGINDEX_NONE) - { - test = 0; - } - else - { - efa = EM_get_face_for_index(index); - - if (efa && (efa->h || (efa->v1->f & SELECT) || (efa->v2->f & SELECT) || (efa->v3->f & SELECT) || (efa->v4 && efa->v4->f & SELECT))) - { - test = 0; - } - } - } - - - if (test) - { - result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL); - - if (result) { - float location[3], normal[3]; - float intersect[3]; - float new_depth; - int screen_loc[2]; - int new_dist; - - VECCOPY(intersect, ray_normal_local); - VecMulf(intersect, lambda); - VecAddf(intersect, intersect, ray_start_local); - - VECCOPY(location, intersect); - - if (f->v4) - CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal); - else - CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal); - - Mat4MulVecfl(obmat, location); - - new_depth = VecLenf(location, ray_start); - - project_int(location, screen_loc); - new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); - - if (new_dist <= *dist && new_depth < *depth) - { - *depth = new_depth; - retval = 1; - - VECCOPY(loc, location); - VECCOPY(no, normal); - - Mat3MulVecfl(timat, no); - Normalize(no); - - *dist = new_dist; - } - } - - if (f->v4 && result == 0) - { - result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL); - - if (result) { - float location[3], normal[3]; - float intersect[3]; - float new_depth; - int screen_loc[2]; - int new_dist; - - VECCOPY(intersect, ray_normal_local); - VecMulf(intersect, lambda); - VecAddf(intersect, intersect, ray_start_local); - - VECCOPY(location, intersect); - - if (f->v4) - CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal); - else - CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal); - - Mat4MulVecfl(obmat, location); - - new_depth = VecLenf(location, ray_start); - - project_int(location, screen_loc); - new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); - - if (new_dist <= *dist && new_depth < *depth) - { - *depth = new_depth; - retval = 1; - - VECCOPY(loc, location); - VECCOPY(no, normal); - - Mat3MulVecfl(timat, no); - Normalize(no); - - *dist = new_dist; - } - } - } - } - } - - if (EditMesh) - { - EM_free_index_arrays(); - } - break; - } - case SCE_SNAP_MODE_VERTEX: - { - MVert *verts = dm->getVertArray(dm); - int *index_array = NULL; - int index = 0; - int i; - - if (EditMesh) - { - index_array = dm->getVertDataArray(dm, CD_ORIGINDEX); - EM_init_index_arrays(1, 0, 0); - } - - for( i = 0; i < totvert; i++) { - EditVert *eve = NULL; - MVert *v = verts + i; - - test = 1; /* reset for every vert */ - - if (EditMesh) - { - if (index_array) - { - index = index_array[i]; - } - else - { - index = i; - } - - if (index == ORIGINDEX_NONE) - { - test = 0; - } - else - { - eve = EM_get_vert_for_index(index); - - if (eve && (eve->h || (eve->f & SELECT))) - { - test = 0; - } - } - } - - - if (test) - { - float dvec[3]; - - VecSubf(dvec, v->co, ray_start_local); - - if (Inpf(ray_normal_local, dvec) > 0) - { - float location[3]; - float new_depth; - int screen_loc[2]; - int new_dist; - - VECCOPY(location, v->co); - - Mat4MulVecfl(obmat, location); - - new_depth = VecLenf(location, ray_start); - - project_int(location, screen_loc); - new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); - - if (new_dist <= *dist && new_depth < *depth) - { - *depth = new_depth; - retval = 1; - - VECCOPY(loc, location); - - NormalShortToFloat(no, v->no); - Mat3MulVecfl(timat, no); - Normalize(no); - - *dist = new_dist; - } - } - } - } - - if (EditMesh) - { - EM_free_index_arrays(); - } - break; - } - case SCE_SNAP_MODE_EDGE: - { - MVert *verts = dm->getVertArray(dm); - MEdge *edges = dm->getEdgeArray(dm); - int totedge = dm->getNumEdges(dm); - int *index_array = NULL; - int index = 0; - int i; - - if (EditMesh) - { - index_array = dm->getEdgeDataArray(dm, CD_ORIGINDEX); - EM_init_index_arrays(0, 1, 0); - } - - for( i = 0; i < totedge; i++) { - EditEdge *eed = NULL; - MEdge *e = edges + i; - - test = 1; /* reset for every vert */ - - if (EditMesh) - { - if (index_array) - { - index = index_array[i]; - } - else - { - index = i; - } - - if (index == ORIGINDEX_NONE) - { - test = 0; - } - else - { - eed = EM_get_edge_for_index(index); - - if (eed && (eed->h || (eed->v1->f & SELECT) || (eed->v2->f & SELECT))) - { - test = 0; - } - } - } - - - if (test) - { - float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3]; - int result; - - VECCOPY(ray_end, ray_normal_local); - VecMulf(ray_end, 2000); - VecAddf(ray_end, ray_start_local, ray_end); - - result = LineIntersectLine(verts[e->v1].co, verts[e->v2].co, ray_start_local, ray_end, intersect, dvec); /* dvec used but we don't care about result */ - - if (result) - { - float edge_loc[3], vec[3]; - float mul; - - /* check for behind ray_start */ - VecSubf(dvec, intersect, ray_start_local); - - VecSubf(edge_loc, verts[e->v1].co, verts[e->v2].co); - VecSubf(vec, intersect, verts[e->v2].co); - - mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc); - - if (mul > 1) { - mul = 1; - VECCOPY(intersect, verts[e->v1].co); - } - else if (mul < 0) { - mul = 0; - VECCOPY(intersect, verts[e->v2].co); - } - - if (Inpf(ray_normal_local, dvec) > 0) - { - float location[3]; - float new_depth; - int screen_loc[2]; - int new_dist; - - VECCOPY(location, intersect); - - Mat4MulVecfl(obmat, location); - - new_depth = VecLenf(location, ray_start); - - project_int(location, screen_loc); - new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); - - if (new_dist <= *dist && new_depth < *depth) - { - float n1[3], n2[3]; - - *depth = new_depth; - retval = 1; - - VecSubf(edge_loc, verts[e->v1].co, verts[e->v2].co); - VecSubf(vec, intersect, verts[e->v2].co); - - mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc); - - NormalShortToFloat(n1, verts[e->v1].no); - NormalShortToFloat(n2, verts[e->v2].no); - VecLerpf(no, n2, n1, mul); - Normalize(no); - - VECCOPY(loc, location); - - Mat3MulVecfl(timat, no); - Normalize(no); - - *dist = new_dist; - } - } - } - } - } - - if (EditMesh) - { - EM_free_index_arrays(); - } - break; - } - } - } - } - - return retval; -} - -int snapObjects(int *dist, float *loc, float *no, int mode) { - Base *base; - float depth = FLT_MAX; - int retval = 0; - short mval[2]; - float ray_start[3], ray_normal[3]; - - getmouseco_areawin(mval); - viewray(mval, ray_start, ray_normal); - - if (mode == NOT_ACTIVE) - { - DerivedMesh *dm; - Object *ob = G.obedit; - - dm = editmesh_get_derived_cage(CD_MASK_BAREMESH); - - retval = snapDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth, 1); - - dm->release(dm); - } - - base= FIRSTBASE; - for ( base = FIRSTBASE; base != NULL; base = base->next ) { - if ( BASE_SELECTABLE(base) && (base->flag & (BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA)) == 0 && ((mode == NOT_SELECTED && (base->flag & (SELECT|BA_WAS_SEL)) == 0) || (mode == NOT_ACTIVE && base != BASACT)) ) { - Object *ob = base->object; - - if (ob->transflag & OB_DUPLI) - { - DupliObject *dupli_ob; - ListBase *lb = object_duplilist(G.scene, ob); - - for(dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) - { - Object *ob = dupli_ob->ob; - - if (ob->type == OB_MESH) { - DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); - int val; - - val = snapDerivedMesh(ob, dm, dupli_ob->mat, ray_start, ray_normal, mval, loc, no, dist, &depth, 0); - - retval = retval || val; - - dm->release(dm); - } - } - - free_object_duplilist(lb); - } - - if (ob->type == OB_MESH) { - DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); - int val; - - val = snapDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth, 0); - - retval = retval || val; - - dm->release(dm); - } - } - } - - return retval; -} - -/*================================================================*/ - -static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], GearsType action); - - -void snapGridAction(TransInfo *t, float *val, GearsType action) { - float fac[3]; - - fac[NO_GEARS] = t->snap[0]; - fac[BIG_GEARS] = t->snap[1]; - fac[SMALL_GEARS] = t->snap[2]; - - applyGrid(t, val, t->idx_max, fac, action); -} - - -void snapGrid(TransInfo *t, float *val) { - int invert; - GearsType action; - - // Only do something if using Snap to Grid - if (t->tsnap.modePoint != SNAP_GRID) - return; - - if(t->mode==TFM_ROTATION || t->mode==TFM_WARP || t->mode==TFM_TILT || t->mode==TFM_TRACKBALL || t->mode==TFM_BONE_ROLL) - invert = U.flag & USER_AUTOROTGRID; - else if(t->mode==TFM_RESIZE || t->mode==TFM_SHEAR || t->mode==TFM_BONESIZE || t->mode==TFM_SHRINKFATTEN || t->mode==TFM_CURVE_SHRINKFATTEN) - invert = U.flag & USER_AUTOSIZEGRID; - else - invert = U.flag & USER_AUTOGRABGRID; - - if(invert) { - action = (G.qual & LR_CTRLKEY) ? NO_GEARS: BIG_GEARS; - } - else { - action = (G.qual & LR_CTRLKEY) ? BIG_GEARS : NO_GEARS; - } - - if (action == BIG_GEARS && (G.qual & LR_SHIFTKEY)) { - action = SMALL_GEARS; - } - - snapGridAction(t, val, action); -} - - -static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], GearsType action) -{ - int i; - float asp[3] = {1.0f, 1.0f, 1.0f}; // TODO: Remove hard coded limit here (3) - - // Early bailing out if no need to snap - if (fac[action] == 0.0) - return; - - /* evil hack - snapping needs to be adapted for image aspect ratio */ - if((t->spacetype==SPACE_IMAGE) && (t->mode==TFM_TRANSLATION)) { - transform_aspect_ratio_tface_uv(asp, asp+1); - } - - for (i=0; i<=max_index; i++) { - val[i]= fac[action]*asp[i]*(float)floor(val[i]/(fac[action]*asp[i]) +.5); - } -} |