diff options
author | Martin Poirier <theeth@yahoo.com> | 2009-02-25 00:25:36 +0300 |
---|---|---|
committer | Martin Poirier <theeth@yahoo.com> | 2009-02-25 00:25:36 +0300 |
commit | aa7c45c190db386e05f9ebee00275bc5e35db99a (patch) | |
tree | c6ddbc219255e883cfe2df51548663513d3eae39 | |
parent | 57c7200a65a5fcfaa3a7c110ff3b2aecc7cde16f (diff) |
Snaping cleanup, removing a lot of duplicate code.
Snapping to armatures: non-editmode armatures only, rest pose only, ... (this is mostly work in progress code).
-rw-r--r-- | source/blender/src/transform_snap.c | 449 |
1 files changed, 259 insertions, 190 deletions
diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index 1f21bda3b59..3353c209d67 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -33,6 +33,7 @@ #include "PIL_time.h" +#include "DNA_armature_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_meshdata_types.h" // Temporary, for snapping to other unselected meshes @@ -815,6 +816,244 @@ void TargetSnapClosest(TransInfo *t) } /*================================================================*/ +int snapFace(float v1co[3], float v2co[3], float v3co[3], float *v4co, short 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) +{ + float lambda; + int result; + int retval = 0; + + result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, v1co, v2co, v3co, &lambda, NULL, 0.001); + + 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 (v4co) + CalcNormFloat4(v1co, v2co, v3co, v4co, normal); + else + CalcNormFloat(v1co, v2co, v3co, 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; + } + } + + return retval; +} + +int snapEdge(float v1co[3], short v1no[3], float v2co[3], short v2no[3], short 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) +{ + float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3]; + int result; + int retval = 0; + + VECCOPY(ray_end, ray_normal_local); + VecMulf(ray_end, 2000); + VecAddf(ray_end, ray_start_local, ray_end); + + result = LineIntersectLine(v1co, v2co, 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, v1co, v2co); + VecSubf(vec, intersect, v2co); + + mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc); + + if (mul > 1) { + mul = 1; + VECCOPY(intersect, v1co); + } + else if (mul < 0) { + mul = 0; + VECCOPY(intersect, v2co); + } + + 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]); + + /* 10% threshold if edge is closer but a bit further + * this takes care of series of connected edges a bit slanted w.r.t the viewport + * otherwise, it would stick to the verts of the closest edge and not slide along merrily + * */ + if (new_dist <= *dist && new_depth < *depth * 1.01) + { + float n1[3], n2[3]; + + *depth = new_depth; + retval = 1; + + VecSubf(edge_loc, v1co, v2co); + VecSubf(vec, intersect, v2co); + + mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc); + + if (no) + { + NormalShortToFloat(n1, v1no); + NormalShortToFloat(n2, v2no); + VecLerpf(no, n2, n1, mul); + Mat3MulVecfl(timat, no); + Normalize(no); + } + + VECCOPY(loc, location); + + *dist = new_dist; + } + } + } + + return retval; +} + +int snapVertex(float vco[3], short vno[3], short 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) +{ + int retval = 0; + float dvec[3]; + + VecSubf(dvec, vco, 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, vco); + + 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); + + if (no) + { + NormalShortToFloat(no, vno); + Mat3MulVecfl(timat, no); + Normalize(no); + } + + *dist = new_dist; + } + } + + return retval; +} + +int snapArmature(Object *ob, bArmature *ar, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth) +{ + Bone *b = ar->bonebase.first; + float imat[4][4]; + float ray_start_local[3], ray_normal_local[3]; + int retval = 0; + + Mat4Invert(imat, obmat); + + VECCOPY(ray_start_local, ray_start); + VECCOPY(ray_normal_local, ray_normal); + + Mat4MulVecfl(imat, ray_start_local); + Mat4Mul3Vecfl(imat, ray_normal_local); + + while(b) + { + switch (G.scene->snap_mode) + { + case SCE_SNAP_MODE_VERTEX: + retval |= snapVertex(b->arm_head, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); + retval |= snapVertex(b->arm_tail, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); + break; + case SCE_SNAP_MODE_EDGE: + retval |= snapEdge(b->arm_head, NULL, b->arm_tail, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); + break; + } + + + if (b->childbase.first != NULL) + { + b = b->childbase.first; + } + else + { + while(1) + { + if (b->next != NULL) + { + b = b->next; + break; + } + else if (b->parent != NULL) + { + b = b->parent; + } + else /* nothing to go to */ + { + b = NULL; + break; + } + } + } + } + + return retval; +} + 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; @@ -868,8 +1107,6 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta for( i = 0; i < totface; i++) { EditFace *efa = NULL; MFace *f = faces + i; - float lambda; - int result; test = 1; /* reset for every face */ @@ -902,91 +1139,20 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta if (test) { - result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL, 0.001); + int result; + float *v4co = 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) + { + v4co = verts[f->v4].co; } - + + result = snapFace(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); + retval |= result; + if (f->v4 && result == 0) { - result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL, 0.001); - - 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; - } - } + retval |= snapFace(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); } } } @@ -1045,40 +1211,7 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta 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; - } - } + retval |= snapVertex(v->co, v->no, mval, ray_start, ray_start_local, ray_normal_local, obmat, timat, loc, no, dist, depth); } } @@ -1138,79 +1271,7 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta 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; - } - } - } + retval |= snapEdge(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); } } @@ -1302,6 +1363,14 @@ int snapObjects(int *dist, float *loc, float *no, SnapMode mode) { dm->release(dm); } + else if (ob->type == OB_ARMATURE) + { + int val; + + val = snapArmature(ob, ob->data, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth); + + retval = retval || val; + } } } |