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>2008-06-23 03:21:29 +0400
committerMartin Poirier <theeth@yahoo.com>2008-06-23 03:21:29 +0400
commit7a55f52b1bddc389dca1d456dafb79751abcc9c1 (patch)
treeb09c2b5120f4309ba9194ae78a0069bfd4b9122e /source/blender/src
parentb22d3e615d75232ba0ac3327acb4c1b0101e77a4 (diff)
Transform Snapping
Snap to edges and vertice without have to go through faces. This means you can import floor plans and use the edges as snapping guides and other sort of fun things. The bounding box test still needs padding though.
Diffstat (limited to 'source/blender/src')
-rw-r--r--source/blender/src/transform_snap.c551
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();
}
}
}