Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Poirier <theeth@yahoo.com>2009-02-25 00:25:36 +0300
committerMartin Poirier <theeth@yahoo.com>2009-02-25 00:25:36 +0300
commitaa7c45c190db386e05f9ebee00275bc5e35db99a (patch)
treec6ddbc219255e883cfe2df51548663513d3eae39
parent57c7200a65a5fcfaa3a7c110ff3b2aecc7cde16f (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.c449
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;
+ }
}
}