diff options
-rw-r--r-- | source/blender/src/transform_snap.c | 551 |
1 files changed, 328 insertions, 223 deletions
diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index 04ca5b08755..d16308f17ae 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -737,136 +737,6 @@ void TargetSnapClosest(TransInfo *t) } /*================================================================*/ - -/* find snapping point on face, return 1 on success */ -int snapFace(MFace *face, EditFace *efa, MVert *verts, float *intersect, float *loc, float *no) -{ - MVert *v[4]; - EditVert *eve[4]; - int totvert; - int result = 0; - - v[0] = verts + face->v1; - v[1] = verts + face->v2; - v[2] = verts + face->v3; - - if (face->v4) - { - v[3] = verts + face->v4; - totvert = 4; - } - else - { - v[3] = NULL; - totvert = 3; - } - - if (efa) - { - eve[0] = efa->v1; - eve[1] = efa->v2; - eve[2] = efa->v3; - eve[3] = efa->v4; - } - - switch(G.scene->snap_mode) - { - case SCE_SNAP_MODE_VERTEX: - { - float min_dist = FLT_MAX; - int i; - - for(i = 0; i < totvert; i++) - { - - if (efa == NULL || (eve[i]->f1 & SELECT) == 0) - { - float vert_dist = VecLenf(v[i]->co, intersect); - - if (vert_dist < min_dist) - { - result = 1; - - min_dist = vert_dist; - - VECCOPY(loc, v[i]->co); - NormalShortToFloat(no, v[i]->no); - } - } - } - break; - } - case SCE_SNAP_MODE_EDGE: - { - float min_dist = FLT_MAX; - int i; - - for(i = 0; i < totvert; i++) - { - MVert *v1, *v2; - EditVert *eve1, *eve2; - - v1 = v[i]; - v2 = v[(i + 1) % totvert]; - - eve1 = eve[i]; - eve2 = eve[(i + 1) % totvert]; - - if (efa == NULL || ((eve1->f1 & SELECT) == 0 && (eve2->f1 & SELECT) == 0)) - { - float edge_loc[3]; - float vec[3]; - float mul; - float edge_dist; - - VecSubf(edge_loc, v2->co, v1->co); - VecSubf(vec, intersect, v1->co); - - mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc); - - VecMulf(edge_loc, mul); - VecAddf(edge_loc, edge_loc, v1->co); - - edge_dist = VecLenf(edge_loc, intersect); - - if (edge_dist < min_dist) - { - float n1[3], n2[3]; - result = 1; - - min_dist = edge_dist; - - VECCOPY(loc, edge_loc); - - NormalShortToFloat(n1, v1->no); - NormalShortToFloat(n2, v2->no); - VecLerpf(no, n1, n2, mul); - Normalize(no); - } - } - } - break; - } - case SCE_SNAP_MODE_FACE: - { - if (efa == NULL || ((efa->f1 & SELECT) == 0)) - { - result = 1; - - VECCOPY(loc, intersect); - - if (totvert == 4) - CalcNormFloat4(v[0]->co, v[1]->co, v[2]->co, v[3]->co, no); - else - CalcNormFloat(v[0]->co, v[1]->co, v[2]->co, no); - } - break; - } - } - - return result; -} - 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; @@ -891,7 +761,7 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta Mat4Mul3Vecfl(imat, ray_normal_local); - /* If number of vert is more than an arbitrary limit, + /* If number of vert is more than an arbitrary limit, * test against boundbox first * */ if (totface > 16) { @@ -900,117 +770,219 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta } if (test == 1) { - MVert *verts = dm->getVertArray(dm); - MFace *faces = dm->getFaceArray(dm); - int *index_array = NULL; - int index = 0; - int i; - if (EditMesh) + switch (G.scene->snap_mode) { - 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; - } + 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 (index == ORIGINDEX_NONE) + if (EditMesh) { - test = 0; + index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX); + EM_init_index_arrays(0, 0, 1); } - else - { - efa = EM_get_face_for_index(index); + + for( i = 0; i < totface; i++) { + EditFace *efa = NULL; + MFace *f = faces + i; + float lambda; + int result; - if (efa && efa->f1 & SELECT) + test = 1; /* reset for every face */ + + if (EditMesh) { - test = 0; + 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->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]; - VECCOPY(intersect, ray_normal_local); - VecMulf(intersect, lambda); - VecAddf(intersect, intersect, ray_start_local); - if (snapFace(f, efa, verts, intersect, location, normal)) - { - float new_depth; - int screen_loc[2]; - int new_dist; - - 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 (test) + { + result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL); - if (new_dist <= *dist && new_depth < *depth) - { - *depth = new_depth; - retval = 1; + if (result) { + float location[3], normal[3]; + float intersect[3]; + float new_depth; + int screen_loc[2]; + int new_dist; - VECCOPY(loc, location); - VECCOPY(no, normal); + VECCOPY(intersect, ray_normal_local); + VecMulf(intersect, lambda); + VecAddf(intersect, intersect, ray_start_local); - Mat3MulVecfl(timat, no); - Normalize(no); - - project_int(loc, screen_loc); + 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); - *dist = new_dist; - } + 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) + + if (EditMesh) { - result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL); + 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; - if (result) { - float location[3], normal[3]; - float intersect[3]; + test = 1; /* reset for every vert */ + + if (EditMesh) + { + if (index_array) + { + index = index_array[i]; + } + else + { + index = i; + } - VECCOPY(intersect, ray_normal_local); - VecMulf(intersect, lambda); - VecAddf(intersect, intersect, ray_start_local); - - if (snapFace(f, efa, verts, intersect, location, normal)) - { + if (index == ORIGINDEX_NONE) + { + test = 0; + } + else + { + eve = EM_get_vert_for_index(index); + + if (eve && 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); + 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]); @@ -1021,8 +993,8 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta retval = 1; VECCOPY(loc, location); - VECCOPY(no, normal); + NormalShortToFloat(no, v->no); Mat3MulVecfl(timat, no); Normalize(no); @@ -1031,12 +1003,145 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta } } } + + 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->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; } - } - - if (EditMesh) - { - EM_free_index_arrays(); } } } |