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:
Diffstat (limited to 'source/blender/bmesh/intern/bmesh_interp.c')
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c268
1 files changed, 199 insertions, 69 deletions
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index 9e1d1fc6176..3f66cce1c74 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -272,7 +272,8 @@ int isect_ray_tri_threshold_v3_uvw(float p1[3], float d[3], float _v0[3], float
float du = 0, dv = 0;
float v0[3], v1[3], v2[3], c[3];
- /*expand triange a bit*/
+ /*expand triangle a bit*/
+#if 1
cent_tri_v3(c, _v0, _v1, _v2);
sub_v3_v3v3(v0, _v0, c);
sub_v3_v3v3(v1, _v1, c);
@@ -283,6 +284,11 @@ int isect_ray_tri_threshold_v3_uvw(float p1[3], float d[3], float _v0[3], float
add_v3_v3(v0, c);
add_v3_v3(v1, c);
add_v3_v3(v2, c);
+#else
+ copy_v3_v3(v0, _v0);
+ copy_v3_v3(v1, _v1);
+ copy_v3_v3(v2, _v2);
+#endif
sub_v3_v3v3(e1, v1, v0);
sub_v3_v3v3(e2, v2, v0);
@@ -329,20 +335,154 @@ int isect_ray_tri_threshold_v3_uvw(float p1[3], float d[3], float _v0[3], float
return 1;
}
+/* find closest point to p on line through l1,l2 and return lambda,
+ * where (0 <= lambda <= 1) when cp is in the line segement l1,l2
+ */
+static double closest_to_line_v3_d(double cp[3], const double p[3], const double l1[3], const double l2[3])
+{
+ double h[3],u[3],lambda;
+ VECSUB(u, l2, l1);
+ VECSUB(h, p, l1);
+ lambda =INPR(u,h)/INPR(u,u);
+ cp[0] = l1[0] + u[0] * lambda;
+ cp[1] = l1[1] + u[1] * lambda;
+ cp[2] = l1[2] + u[2] * lambda;
+ return lambda;
+}
+
+/* point closest to v1 on line v2-v3 in 3D */
+static void closest_to_line_segment_v3_d(double *closest, double v1[3], double v2[3], double v3[3])
+{
+ double lambda, cp[3];
+
+ lambda= closest_to_line_v3_d(cp,v1, v2, v3);
+
+ if(lambda <= 0.0) {
+ VECCOPY(closest, v2);
+ } else if(lambda >= 1.0) {
+ VECCOPY(closest, v3);
+ } else {
+ VECCOPY(closest, cp);
+ }
+}
+
+static double len_v3v3_d(const double a[3], const double b[3])
+{
+ double d[3];
+
+ VECSUB(d, b, a);
+ return sqrt(INPR(d, d));
+}
+
+/*funnily enough, I think this is identical to face_to_crn_interp, heh*/
+double quad_coord(double aa[3], double bb[3], double cc[3], double dd[3], int a1, int a2)
+{
+ double x, y, z, f1, f2;
+
+ x = aa[a1]*cc[a2]-cc[a1]*aa[a2];
+ y = aa[a1]*dd[a2]+bb[a1]*cc[a2]-cc[a1]*bb[a2]-dd[a1]*aa[a2];
+ z = bb[a1]*dd[a2]-dd[a1]*bb[a2];
+
+
+ if (fabs(2*(x-y+z)) > DBL_EPSILON*1000.0) {
+ f1 = (sqrt(y*y-4.0*x*z) - y + 2.0*z) / (2.0*(x-y+z));
+ f2 = (-sqrt(y*y-4.0*x*z) - y + 2.0*z) / (2.0*(x-y+z));
+ } else f1 = -1;
+
+ if (isnan(f1) || f1 == -1.0) {
+ int i, tot=200;
+ double d, lastd=-1.0;
+
+ //return -1.0f;
+#if 0
+ double co[3], p[3] = {0.0, 0.0, 0.0};
+ closest_to_line_segment_v3_d(co, p, aa, bb);
+
+ return len_v3v3_d(bb, co) / len_v3v3_d(aa, bb);
+#endif
+#if 1
+ f1 = 1.0;
+ f2 = 0.0;
+ for (i=0; i<tot; i++) {
+ double f3, v1[3], v2[3], co[3], p[3] = {0.0, 0.0, 0.0};
+
+ VECINTERP(v1, aa, bb, f1);
+ VECINTERP(v2, cc, dd, f1);
+
+ closest_to_line_segment_v3_d(co, p, v1, v2);
+ d = len_v3v3_d(co, p);
+
+ f3 = f1;
+ if (d < lastd) {
+ f1 += (f1-f2)*0.5;
+ } else {
+ f1 -= (f1-f2)*0.5;
+ }
+
+ f2 = f3;
+ lastd = d;
+ }
+
+ if (d > 0.0000001 || f1 < -FLT_EPSILON*1000 || f1 >= 1.0+FLT_EPSILON*100)
+ return -1.0;
+
+ CLAMP(f1, 0.0, 1.0+DBL_EPSILON);
+ return 1.0 - f1;
+#endif
+ }
+
+ f1 = MIN2(fabs(f1), fabs(f2));
+ CLAMP(f1, 0.0, 1.0+DBL_EPSILON);
+
+ return f1;
+}
+
+void quad_co(float *x, float *y, float v1[3], float v2[3], float v3[3], float v4[3], float p[3], float n[3])
+{
+ float projverts[4][3];
+ double dverts[4][3];
+ int i;
+
+ sub_v3_v3v3(projverts[0], v1, p);
+ sub_v3_v3v3(projverts[1], v2, p);
+ sub_v3_v3v3(projverts[2], v3, p);
+ sub_v3_v3v3(projverts[3], v4, p);
+
+ /*rotate*/
+ poly_rotate_plane(n, projverts, 4);
+
+ /*flatten*/
+ for (i=0; i<4; i++) projverts[i][2] = 0.0f;
+
+ VECCOPY(dverts[0], projverts[0]);
+ VECCOPY(dverts[1], projverts[1]);
+ VECCOPY(dverts[2], projverts[2]);
+ VECCOPY(dverts[3], projverts[3]);
+
+ *y = quad_coord(dverts[1], dverts[0], dverts[2], dverts[3], 0, 1);
+ *x = quad_coord(dverts[2], dverts[1], dverts[3], dverts[0], 0, 1);
+}
+
/*tl is loop to project onto, sl is loop whose internal displacement, co, is being
projected. x and y are location in loop's mdisps grid of co.*/
-static int mdisp_in_mdispquad(BMLoop *l, BMLoop *tl, float p[3], float *x, float *y, int res)
+static int mdisp_in_mdispquad(BMesh *bm, BMLoop *l, BMLoop *tl, float p[3], float *x, float *y, int res)
{
float v1[3], v2[3], c[3], co[3], v3[3], v4[3], e1[3], e2[3];
float w[4], dir[3], uv[4] = {0.0f, 0.0f, 0.0f, 0.0f}, hit[3];
- float lm, eps = FLT_EPSILON*80;
+ float x2, y2, lm, eps = FLT_EPSILON*20;
int ret=0;
+ if (len_v3(l->f->no) < FLT_EPSILON*50)
+ BM_Face_UpdateNormal(bm, l->f);
+
+ if (len_v3(tl->f->no) < FLT_EPSILON*50)
+ BM_Face_UpdateNormal(bm, tl->f);
+
compute_mdisp_quad(tl, v1, v2, v3, v4, e1, e2);
- copy_v3_v3(dir, l->f->no);
+ copy_v3_v3(dir, tl->f->no);
copy_v3_v3(co, dir);
- mul_v3_fl(co, -0.000001);
+ mul_v3_fl(co, -0.001);
add_v3_v3(co, p);
/*four tests, two per triangle, once again normal, once along -normal*/
@@ -356,13 +496,17 @@ static int mdisp_in_mdispquad(BMLoop *l, BMLoop *tl, float p[3], float *x, float
ret = ret || isect_ray_tri_threshold_v3_uvw(co, dir, v1, v3, v4, &lm, uv, eps);
}
- if (!ret || isnan(lm) || (uv[0]+uv[1]+uv[2]+uv[3]) < 1.0-FLT_EPSILON*10)
+ if (!ret)
+ return 0;
+
+ if (isnan(lm))
return 0;
mul_v3_fl(dir, lm);
add_v3_v3v3(hit, co, dir);
/*expand quad a bit*/
+#if 1
cent_quad_v3(c, v1, v2, v3, v4);
sub_v3_v3(v1, c); sub_v3_v3(v2, c);
@@ -371,34 +515,30 @@ static int mdisp_in_mdispquad(BMLoop *l, BMLoop *tl, float p[3], float *x, float
mul_v3_fl(v3, 1.0+eps); mul_v3_fl(v4, 1.0+eps);
add_v3_v3(v1, c); add_v3_v3(v2, c);
add_v3_v3(v3, c); add_v3_v3(v4, c);
+#endif
- interp_weights_face_v3(uv, v1, v2, v3, v4, hit);
-
- *x = ((1.0+FLT_EPSILON)*uv[2] + (1.0+FLT_EPSILON)*uv[3])*(float)(res-1);
- *y = ((1.0+FLT_EPSILON)*uv[1] + (1.0+FLT_EPSILON)*uv[2])*(float)(res-1);
+ quad_co(x, y, v1, v2, v3, v4, hit, tl->f->no);
- return 1;
-}
+ if (isnan(*x) || isnan(*y) || *x == -1.0f || *y == -1.0f) {
+ interp_weights_face_v3(uv, v1, v2, v3, v4, hit);
+
+ x2 = ((1.0+FLT_EPSILON)*uv[2] + (1.0+FLT_EPSILON)*uv[3]);
+ y2 = ((1.0+FLT_EPSILON)*uv[1] + (1.0+FLT_EPSILON)*uv[2]);
-void undo_tangent(MDisps *md, int res, int x, int y, int redo)
-{
-#if 0
- float co[3], tx[3], ty[3], mat[3][3];
+ if (*x == -1.0f || isnan(*x))
+ *x = x2;
+ if (*y == -1.0f || isnan(*y))
+ *y = y2;
+ }
- /* construct tangent space matrix */
- grid_tangent(res, 0, x, y, 0, md->disps, tx);
- normalize_v3(tx);
-
- grid_tangent(res, 0, x, y, 1, md->disps, ty);
- normalize_v3(ty);
+ *x *= res-1-FLT_EPSILON*100;
+ *y *= res-1-FLT_EPSILON*100;
- column_vectors_to_mat3(mat, tx, ty, no);
- if (redo)
- invert_m3(mat);
+ if (fabs(*x-x2) > 1.5 || fabs(*y-y2) > 1.5) {
+ x2 = 1;
+ }
- mul_v3_m3v3(co, mat, md->disps[y*res+x]);
- copy_v3_v3(md->disps[y*res+x], co);
-#endif
+ return 1;
}
static void bmesh_loop_interp_mdisps(BMesh *bm, BMLoop *target, BMFace *source)
@@ -425,22 +565,30 @@ static void bmesh_loop_interp_mdisps(BMesh *bm, BMLoop *target, BMFace *source)
return;
}
- res = (int)(sqrt(mdisps->totdisp)+0.5f);
+ res = (int)sqrt(mdisps->totdisp);
d = 1.0f/(float)(res-1);
for (x=0.0f, ix=0; ix<res; x += d, ix++) {
for (y=0.0f, iy=0; iy<res; y+= d, iy++) {
float co1[3], co2[3], co[3];
+ float xx, yy;
copy_v3_v3(co1, e1);
- mul_v3_fl(co1, y);
+
+ if (!iy) yy = y + FLT_EPSILON*2;
+ else yy = y - FLT_EPSILON*2;
+
+ mul_v3_fl(co1, yy);
add_v3_v3(co1, v1);
copy_v3_v3(co2, e2);
- mul_v3_fl(co2, y);
+ mul_v3_fl(co2, yy);
add_v3_v3(co2, v4);
+ if (!ix) xx = x + FLT_EPSILON*2;
+ else xx = x - FLT_EPSILON*2;
+
sub_v3_v3v3(co, co2, co1);
- mul_v3_fl(co, x);
+ mul_v3_fl(co, xx);
add_v3_v3(co, co1);
l2 = bm_firstfaceloop(source);
@@ -452,33 +600,11 @@ static void bmesh_loop_interp_mdisps(BMesh *bm, BMLoop *target, BMFace *source)
md1 = CustomData_bmesh_get(&bm->ldata, target->head.data, CD_MDISPS);
md2 = CustomData_bmesh_get(&bm->ldata, l2->head.data, CD_MDISPS);
- if (mdisp_in_mdispquad(target, l2, co, &x2, &y2, res)) {
- int i1, j1;
- float tx[3], mat[3][3], ty[3];
-
+ if (mdisp_in_mdispquad(bm, target, l2, co, &x2, &y2, res)) {
ix2 = (int)x2;
iy2 = (int)y2;
- for (i1=ix2-1; i1<ix2+1; i1++) {
- for (j1=iy2-1; j1<iy2+1; j1++) {
- if (i1 < 0 || i1 >= res) continue;
- if (j1 < 0 || j1 >= res) continue;
-
- undo_tangent(md2, res, i1, j1, 0);
- }
- }
-
old_mdisps_bilinear(md1->disps[iy*res+ix], md2->disps, res, x2, y2);
-
- for (i1=ix2-1; i1<ix2+1; i1++) {
- for (j1=iy2-1; j1<iy2+1; j1++) {
- if (i1 < 0 || i1 >= res) continue;
- if (j1 < 0 || j1 >= res) continue;
-
- undo_tangent(md2, res, i1, j1, 1);
- }
- }
-
}
l2 = l2->next;
} while (l2 != bm_firstfaceloop(source));
@@ -491,7 +617,7 @@ void BM_multires_smooth_bounds(BMesh *bm, BMFace *f)
BMLoop *l;
BMIter liter;
- return;//XXX
+ //return;//XXX
if (!CustomData_has_layer(&bm->ldata, CD_MDISPS))
return;
@@ -507,23 +633,27 @@ void BM_multires_smooth_bounds(BMesh *bm, BMFace *f)
/*****
mdisps is a grid of displacements, ordered thus:
- v1/center -- v4/next -> x
- | |
- | |
- v2/prev ---- v3/cur
- |
- V
-
- y
+ v4/next
+ |
+ | v1/cent-mid2 ---> x
+ | | |
+ | | |
+ v2/prev--mid1--v3/cur
+ |
+ V
+ y
*****/
sides = sqrt(mdp->totdisp);
for (y=0; y<sides; y++) {
- add_v3_v3v3(co, mdp->disps[y*sides + sides-1], mdl->disps[y*sides]);
- mul_v3_fl(co, 0.5);
-
- copy_v3_v3(mdp->disps[y*sides + sides-1], co);
- copy_v3_v3(mdl->disps[y*sides], co);
+ //add_v3_v3v3(co, mdp->disps[y*sides + sides-1], mdl->disps[y*sides]);
+ //mul_v3_fl(co, 0.5);
+ copy_v3_v3(co, mdn->disps[y*sides]);
+ copy_v3_v3(mdn->disps[y*sides], mdl->disps[y]);
+ copy_v3_v3(mdl->disps[y], co);
+
+ //copy_v3_v3(mdp->disps[y*sides + sides-1], co);
+ //copy_v3_v3(mdl->disps[y*sides], co);
}
}
}