diff options
Diffstat (limited to 'source/blender/editors/armature/meshlaplacian.c')
-rw-r--r-- | source/blender/editors/armature/meshlaplacian.c | 143 |
1 files changed, 70 insertions, 73 deletions
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index e7efd7936c0..346ed0002bd 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -1113,9 +1113,6 @@ typedef struct MeshDeformBind { /* direct solver */ int *varidx; - - BVHTree *bvhtree; - BVHTreeFromMesh bvhdata; } MeshDeformBind; typedef struct MeshDeformIsect { @@ -1133,9 +1130,8 @@ typedef struct MeshDeformIsect { /* our own triangle intersection, so we can fully control the epsilons and * prevent corner case from going wrong*/ -static int meshdeform_tri_intersect(const float orig[3], const float end[3], const float vert0[3], - const float vert1[3], const float vert2[3], - float r_isectco[3], float r_uvw[3]) +static int meshdeform_tri_intersect(float orig[3], float end[3], float vert0[3], + float vert1[3], float vert2[3], float *isectco, float *uvw) { float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3]; float det, inv_det, u, v, dir[3], isectdir[3]; @@ -1152,10 +1148,8 @@ static int meshdeform_tri_intersect(const float orig[3], const float end[3], con /* if determinant is near zero, ray lies in plane of triangle */ det = dot_v3v3(edge1, pvec); - if (UNLIKELY(det == 0.0f)) { + if (det == 0.0f) return 0; - } - inv_det = 1.0f / det; /* calculate distance from vert0 to ray origin */ @@ -1174,16 +1168,16 @@ static int meshdeform_tri_intersect(const float orig[3], const float end[3], con if (v < -EPSILON || u + v > 1.0f + EPSILON) return 0; - r_isectco[0] = (1.0f - u - v) * vert0[0] + u * vert1[0] + v * vert2[0]; - r_isectco[1] = (1.0f - u - v) * vert0[1] + u * vert1[1] + v * vert2[1]; - r_isectco[2] = (1.0f - u - v) * vert0[2] + u * vert1[2] + v * vert2[2]; + isectco[0] = (1.0f - u - v) * vert0[0] + u * vert1[0] + v * vert2[0]; + isectco[1] = (1.0f - u - v) * vert0[1] + u * vert1[1] + v * vert2[1]; + isectco[2] = (1.0f - u - v) * vert0[2] + u * vert1[2] + v * vert2[2]; - r_uvw[0] = 1.0f - u - v; - r_uvw[1] = u; - r_uvw[2] = v; + uvw[0] = 1.0f - u - v; + uvw[1] = u; + uvw[2] = v; /* check if it is within the length of the line segment */ - sub_v3_v3v3(isectdir, r_isectco, orig); + sub_v3_v3v3(isectdir, isectco, orig); if (dot_v3v3(dir, isectdir) < -EPSILON) return 0; @@ -1194,79 +1188,83 @@ static int meshdeform_tri_intersect(const float orig[3], const float end[3], con return 1; } -static void harmonic_ray_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) - { - void **data = userdata; - MeshDeformBind *mdb = data[1]; - MFace *mface = data[0], *mf; - MeshDeformIsect *isec = data[2]; - float no[3], co[3], end[3], uvw[3], dist, face[4][3]; - - mf = mface + index; - - copy_v3_v3(face[0], mdb->cagecos[mf->v1]); - copy_v3_v3(face[1], mdb->cagecos[mf->v2]); - copy_v3_v3(face[2], mdb->cagecos[mf->v3]); - if (mf->v4) - copy_v3_v3(face[3], mdb->cagecos[mf->v4]); - - add_v3_v3v3(end, isec->start, isec->vec); - - if (!meshdeform_tri_intersect(ray->origin, end, face[0], face[1], face[2], co, uvw)) - if (!mf->v4 || !meshdeform_tri_intersect(ray->origin, end, face[0], face[2], face[3], co, uvw)) - return; - - if (!mf->v4) - normal_tri_v3(no, face[0], face[1], face[2]); - else - normal_quad_v3(no, face[0], face[1], face[2], face[3]); - - dist = len_v3v3(ray->origin, co)/len_v3(isec->vec); - if (dist < hit->dist) { - hit->index = index; - hit->dist = dist; - copy_v3_v3(hit->co, co); - - isec->isect = dot_v3v3(no, ray->direction) <= 0.0; - isec->labda = dist; - isec->face = mf; +static int meshdeform_intersect(MeshDeformBind *mdb, MeshDeformIsect *isec) +{ + MFace *mface; + float face[4][3], co[3], uvw[3], len, nor[3], end[3]; + int f, hit, is = 0, totface; + + isec->labda = 1e10; + + mface = mdb->cagedm->getTessFaceArray(mdb->cagedm); + totface = mdb->cagedm->getNumTessFaces(mdb->cagedm); + + add_v3_v3v3(end, isec->start, isec->vec); + + for (f = 0; f < totface; f++, mface++) { + copy_v3_v3(face[0], mdb->cagecos[mface->v1]); + copy_v3_v3(face[1], mdb->cagecos[mface->v2]); + copy_v3_v3(face[2], mdb->cagecos[mface->v3]); + + if (mface->v4) { + copy_v3_v3(face[3], mdb->cagecos[mface->v4]); + hit = meshdeform_tri_intersect(isec->start, end, face[0], face[1], face[2], co, uvw); + + if (hit) { + normal_tri_v3(nor, face[0], face[1], face[2]); + } + else { + hit = meshdeform_tri_intersect(isec->start, end, face[0], face[2], face[3], co, uvw); + normal_tri_v3(nor, face[0], face[2], face[3]); + } + } + else { + hit = meshdeform_tri_intersect(isec->start, end, face[0], face[1], face[2], co, uvw); + normal_tri_v3(nor, face[0], face[1], face[2]); + } + + if (hit) { + len = len_v3v3(isec->start, co) / len_v3v3(isec->start, end); + if (len < isec->labda) { + isec->labda = len; + isec->face = mface; + isec->isect = (dot_v3v3(isec->vec, nor) <= 0.0f); + is = 1; + } + } } + + return is; } static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, float *co1, float *co2) { MDefBoundIsect *isect; - BVHTreeRayHit hit; - MeshDeformIsect isect_mdef; + MeshDeformIsect isec; float (*cagecos)[3]; - void *data[3] = {mdb->cagedm->getTessFaceArray(mdb->cagedm), mdb, &isect_mdef}; - MFace *mface1 = data[0], *mface; + MFace *mface; float vert[4][3], len, end[3]; static float epsilon[3] = {0, 0, 0}; //1e-4, 1e-4, 1e-4}; /* setup isec */ - memset(&isect_mdef, 0, sizeof(isect_mdef)); - isect_mdef.labda = 1e10f; + memset(&isec, 0, sizeof(isec)); + isec.labda = 1e10f; - add_v3_v3v3(isect_mdef.start, co1, epsilon); + add_v3_v3v3(isec.start, co1, epsilon); add_v3_v3v3(end, co2, epsilon); - sub_v3_v3v3(isect_mdef.vec, end, isect_mdef.start); + sub_v3_v3v3(isec.vec, end, isec.start); - hit.index = -1; - hit.dist = FLT_MAX; - if (BLI_bvhtree_ray_cast(mdb->bvhtree, isect_mdef.start, isect_mdef.vec, - 0.0, &hit, harmonic_ray_callback, data) != -1) - { - len= isect_mdef.labda; - isect_mdef.face = mface = mface1 + hit.index; + if (meshdeform_intersect(mdb, &isec)) { + len = isec.labda; + mface = (MFace *)isec.face; /* create MDefBoundIsect */ isect = BLI_memarena_alloc(mdb->memarena, sizeof(*isect)); /* compute intersection coordinate */ - isect->co[0] = co1[0] + isect_mdef.vec[0] * len; - isect->co[1] = co1[1] + isect_mdef.vec[1] * len; - isect->co[2] = co1[2] + isect_mdef.vec[2] * len; + isect->co[0] = co1[0] + isec.vec[0] * len; + isect->co[1] = co1[1] + isec.vec[1] * len; + isect->co[2] = co1[2] + isec.vec[2] * len; isect->len = len_v3v3(co1, isect->co); if (isect->len < MESHDEFORM_LEN_THRESHOLD) @@ -1278,7 +1276,7 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, float isect->v[3] = mface->v4; isect->nvert = (mface->v4) ? 4 : 3; - isect->facing = isect_mdef.isect; + isect->facing = isec.isect; /* compute mean value coordinates for interpolation */ cagecos = mdb->cagecos; @@ -1768,7 +1766,7 @@ static void harmonic_coordinates_bind(Scene *UNUSED(scene), MeshDeformModifierDa mdb->totalphi = MEM_callocN(sizeof(float) * mdb->size3, "MeshDeformBindTotalPhi"); mdb->boundisect = MEM_callocN(sizeof(*mdb->boundisect) * mdb->size3, "MDefBoundIsect"); mdb->semibound = MEM_callocN(sizeof(int) * mdb->size3, "MDefSemiBound"); - mdb->bvhtree = bvhtree_from_mesh_faces(&mdb->bvhdata, mdb->cagedm, FLT_EPSILON*100, 4, 6); + mdb->inside = MEM_callocN(sizeof(int) * mdb->totvert, "MDefInside"); if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) @@ -1884,7 +1882,6 @@ static void harmonic_coordinates_bind(Scene *UNUSED(scene), MeshDeformModifierDa MEM_freeN(mdb->boundisect); MEM_freeN(mdb->semibound); BLI_memarena_free(mdb->memarena); - free_bvhtree_from_mesh(&mdb->bvhdata); } #if 0 |