[Bf-committers] Perspective mode knife subdivide patch
Matthew H. Plough
mplough at Princeton.EDU
Mon Feb 28 00:02:24 CET 2005
Hooray! After ages and eons (and a bit of a graphics course), I've
finally fixed the incorrect knife subdivide functionality in perspective
mode. I've attached a patch.
I created the patch file with this command:
Administrator at mplough /cygdrive/c/projects/bfblender/blender
$ cvs diff -u source/blender/src/editmesh_loop.c >patch_file
Matt
-------------- next part --------------
Index: source/blender/src/editmesh_loop.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/src/editmesh_loop.c,v
retrieving revision 1.11
diff -u -r1.11 editmesh_loop.c
--- source/blender/src/editmesh_loop.c 28 Dec 2004 05:38:56 -0000 1.11
+++ source/blender/src/editmesh_loop.c 27 Feb 2005 22:54:19 -0000
@@ -540,15 +540,17 @@
/* prototype */
short seg_intersect(struct EditEdge * e, CutCurve *c, int len);
+short persp_intersect(EditEdge *e, CutCurve *c, int len);
+float line_band_intersect(float p0[3], float p1[3], float r0[3], float r1[3], float r2[3]);
void KnifeSubdivide(char mode)
{
EditMesh *em = G.editMesh;
int oldcursor, len=0;
short isect=0;
- CutCurve *curve;
- EditEdge *eed;
- Window *win;
+ CutCurve *curve;
+ EditEdge *eed;
+ Window *win;
if (G.obedit==0) return;
@@ -560,7 +562,7 @@
if (mode==KNIFE_PROMPT) {
short val= pupmenu("Cut Type %t|Exact Line%x1|Midpoints%x2");
if(val<1) return;
- mode= val; // warning, mode is char, pupmenu returns -1 with ESC
+ mode= val; /* warning, mode is char, pupmenu returns -1 with ESC */
}
calc_meshverts_ext(); /*Update screen coords for current window */
@@ -575,14 +577,15 @@
curve=get_mouse_trail(&len, TRAIL_MIXED);
if (curve && len && mode){
- eed= em->edges.first;
- while(eed) {
+ eed= em->edges.first;
+ while(eed) {
if( eed->f & SELECT ){
- isect=seg_intersect(eed, curve, len);
+ if(!G.vd->persp) isect=seg_intersect(eed, curve, len);
+ else isect= persp_intersect(eed, curve, len);
if (isect) eed->f2= 1;
else eed->f2=0;
eed->f1= isect;
- //printf("isect=%i\n", isect);
+ /*printf("isect=%i\n", isect);*/
}
else {
eed->f2=0;
@@ -717,6 +720,124 @@
}
return(isect);
}
+
+/**
+ * persp_intersect
+ *
+ * Performs the function of seg_intersect when the view is in perspective mode
+*/
+
+short persp_intersect(EditEdge *e, CutCurve *c, int len) {
+ short isect;
+ int i;
+ float perc;
+ float ray1[3], ray2[3];
+ float eye[3], mat[3][3], imat[3][3], vec[4], vec_s[2];
+
+ isect=0;
+
+ initgrabz(0,0,0);
+
+ /* all points need to be transformed to object space */
+ Mat3CpyMat4(mat, G.obedit->obmat);
+ Mat3Inv(imat, mat);
+
+ VecCopyf(eye, G.vd->viewinv[3]);
+ VecSubf(eye, eye, G.obedit->obmat[3]);
+ Mat3MulVecfl(imat, eye);
+
+ vec[0]=vec[1]=vec[2]=0.0;
+ vec[3]=1.0;
+ project_float(vec, vec_s);
+
+ window_to_3d(ray1, c[0].x - vec_s[0], c[0].y - vec_s[1]);
+ VecSubf(ray1, ray1, G.obedit->obmat[3]);
+ Mat3MulVecfl(imat, ray1);
+
+ for(i=1; i<len; i++) {
+ window_to_3d(ray2, c[i].x - vec_s[0], c[i].y - vec_s[1]);
+ /* and transform to object space... */
+ VecSubf(ray2, ray2, G.obedit->obmat[3]);
+ Mat3MulVecfl(imat, ray2);
+ perc = line_band_intersect(e->v1->co, e->v2->co, eye, ray1, ray2);
+ if(perc >= 0) {
+ isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */
+ break;
+ }
+ VecCopyf(ray1, ray2);
+ }
+ return isect;
+}
+
+
+#define EPSILON (1e-6)
+
+/**
+ * line_band_intersect
+ *
+ * A modified line-plane intersect. Checks to see if line intersects plane
+ * and checks if the intersection point lies between two rays in the plane.
+ *
+ * p0, p1 -- points on line
+ * r0 -- origin of two rays that define the plane
+ * r1, r2 -- points along the two rays
+ *
+ * Returns negative if intersect does not occur.
+ * Else returns the percentage of the way from p0 to p1 where intersection occurs
+**/
+
+
+float line_band_intersect(float p0[3], float p1[3], float r0[3], float r1[3], float r2[3]) {
+ float ray1[3], ray2[3], pnor[3], linedir[3], v[3], pI[3];
+ float t; /* 0 <= t <= 1 for intersection to occur on segment */
+ float res1, res2, cross1[3], cross2[3], in1[3], in2[3];
+
+ /* calculate plane normal of unit length */
+ VecSubf(ray1, r1, r0);
+ VecSubf(ray2, r2, r0);
+ Crossf(pnor, ray1, ray2);
+ Normalise(pnor);
+
+ /* http://softsurfer.com/Archive/algorithm_0105/algorithm_0105.htm
+ describes a nice algorithm that uses only dot products. */
+
+ VecSubf(linedir, p1, p0); /* don't normalize! */
+ t = Inpf(pnor, linedir);
+
+ /* t could be negative -- careful! */
+ if(fabs(t) <= EPSILON) /* plane and line are parallel */
+ return -1.0f;
+
+ VecSubf(v, r0, p0);
+ t = Inpf(pnor, v) / t;
+
+ if(t <= 0.0 || t >= 1.0) /* not in the segment */
+ return -1.0f;
+
+
+ VecMulf(linedir, t);
+ VecAddf(pI, p0, linedir);
+
+ VecSubf(cross1, r1, r0);
+ VecSubf(cross2, pI, r1);
+ Crossf(in1, cross1, cross2);
+ Normalise(in1);
+ res1 = Inpf(pnor, in1);
+
+
+ VecSubf(cross1, r2, r0);
+ VecSubf(cross2, pI, r2);
+ Crossf(in2, cross1, cross2);
+ Normalise(in2);
+ res2 = Inpf(pnor, in2);
+
+ printf("%.2f, %.2f\n", res1, res2);
+
+ if((res1 > 0 && res2 < 0) || (res1 < 0 && res2 > 0))
+ return t;
+ return -1.0f;
+}
+#undef EPSILON
/* ******************** LOOP ******************************************* */
More information about the Bf-committers
mailing list