Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/armature/meshlaplacian.c
| Context not available. | |||||
| #include "BLF_translation.h" | #include "BLF_translation.h" | ||||
| #include "BKE_cdderivedmesh.h" /*needed for creating a DM for looptri access*/ | |||||
| #include "BKE_DerivedMesh.h" | #include "BKE_DerivedMesh.h" | ||||
| #include "BKE_modifier.h" | #include "BKE_modifier.h" | ||||
| #include "BKE_mesh.h" | #include "BKE_mesh.h" | ||||
| Context not available. | |||||
| EdgeHash *edgehash; /* edge hash for construction */ | EdgeHash *edgehash; /* edge hash for construction */ | ||||
| struct HeatWeighting { | struct HeatWeighting { | ||||
| MFace *mface; | const MLoopTri *mlooptri; | ||||
| MLoop* mloop; /* needed to find vertices by index */ | |||||
| int totvert; | int totvert; | ||||
| int totface; | int tottri; | ||||
| float (*verts)[3]; /* vertex coordinates */ | float (*verts)[3]; /* vertex coordinates */ | ||||
| float (*vnors)[3]; /* vertex normals */ | float (*vnors)[3]; /* vertex normals */ | ||||
| Context not available. | |||||
| float *mindist; /* minimum distance to a bone for all vertices */ | float *mindist; /* minimum distance to a bone for all vertices */ | ||||
| BVHTree *bvhtree; /* ray tracing acceleration structure */ | BVHTree *bvhtree; /* ray tracing acceleration structure */ | ||||
| MFace **vface; /* a face that the vertex belongs to */ | const MLoopTri **vltree; /* a looptri that the vertex belongs to */ | ||||
| } heat; | } heat; | ||||
| #ifdef RIGID_DEFORM | #ifdef RIGID_DEFORM | ||||
| Context not available. | |||||
| static void bvh_callback(void *userdata, int index, const BVHTreeRay *UNUSED(ray), BVHTreeRayHit *hit) | static void bvh_callback(void *userdata, int index, const BVHTreeRay *UNUSED(ray), BVHTreeRayHit *hit) | ||||
| { | { | ||||
| BVHCallbackUserData *data = (struct BVHCallbackUserData *)userdata; | BVHCallbackUserData *data = (struct BVHCallbackUserData *)userdata; | ||||
| MFace *mf = data->sys->heat.mface + index; | const MLoopTri *mlt = data->sys->heat.mlooptri + index; | ||||
| MLoop *ml = data->sys->heat.mloop; | |||||
| float (*verts)[3] = data->sys->heat.verts; | float (*verts)[3] = data->sys->heat.verts; | ||||
| float lambda, uv[2], n[3], dir[3]; | float lambda, uv[2], n[3], dir[3]; | ||||
| float vert[3][3]; | |||||
| mul_v3_v3fl(dir, data->vec, hit->dist); | mul_v3_v3fl(dir, data->vec, hit->dist); | ||||
| copy_v3_v3(vert[0], verts[(&ml[mlt->tri[0]])->v]); | |||||
| if (isect_ray_tri_v3(data->start, dir, verts[mf->v1], verts[mf->v2], verts[mf->v3], &lambda, uv)) { | copy_v3_v3(vert[1], verts[(&ml[mlt->tri[1]])->v]); | ||||
campbellbarton: Better just to copy the points to the floats, instead of the floats themselves. | |||||
| normal_tri_v3(n, verts[mf->v1], verts[mf->v2], verts[mf->v3]); | copy_v3_v3(vert[2], verts[(&ml[mlt->tri[2]])->v]); | ||||
| if (lambda < 1.0f && dot_v3v3(n, data->vec) < -1e-5f) { | |||||
| hit->index = index; | if (isect_ray_tri_v3(data->start, dir, UNPACK3(vert), &lambda, uv)) { | ||||
| hit->dist *= lambda; | normal_tri_v3(n, UNPACK3(vert)); | ||||
| } | |||||
| } | |||||
| mul_v3_v3fl(dir, data->vec, hit->dist); | |||||
| if (isect_ray_tri_v3(data->start, dir, verts[mf->v1], verts[mf->v3], verts[mf->v4], &lambda, uv)) { | |||||
| normal_tri_v3(n, verts[mf->v1], verts[mf->v3], verts[mf->v4]); | |||||
| if (lambda < 1.0f && dot_v3v3(n, data->vec) < -1e-5f) { | if (lambda < 1.0f && dot_v3v3(n, data->vec) < -1e-5f) { | ||||
| hit->index = index; | hit->index = index; | ||||
| hit->dist *= lambda; | hit->dist *= lambda; | ||||
| Context not available. | |||||
| /* Raytracing for vertex to bone/vertex visibility */ | /* Raytracing for vertex to bone/vertex visibility */ | ||||
| static void heat_ray_tree_create(LaplacianSystem *sys) | static void heat_ray_tree_create(LaplacianSystem *sys) | ||||
| { | { | ||||
| MFace *mface = sys->heat.mface; | const MLoopTri *mlooptri = sys->heat.mlooptri; | ||||
| MLoop *mloop = sys->heat.mloop; | |||||
| float (*verts)[3] = sys->heat.verts; | float (*verts)[3] = sys->heat.verts; | ||||
| int totface = sys->heat.totface; | int tottri = sys->heat.tottri; | ||||
| int totvert = sys->heat.totvert; | int totvert = sys->heat.totvert; | ||||
| int a; | int a; | ||||
Not Done Inline Actions4 isnt referring to quads here. campbellbarton: 4 isnt referring to quads here. | |||||
| sys->heat.bvhtree = BLI_bvhtree_new(totface, 0.0f, 4, 6); | sys->heat.bvhtree = BLI_bvhtree_new(tottri, 0.0f, 4, 6); //XXX set 3 or keep 4 ? | ||||
| sys->heat.vface = MEM_callocN(sizeof(MFace *) * totvert, "HeatVFaces"); | sys->heat.vltree = MEM_callocN(sizeof(MLoopTri *) * totvert, "HeatVFaces"); | ||||
| for (a = 0; a < totface; a++) { | for (a = 0; a < tottri; a++) { | ||||
| MFace *mf = mface + a; | const MLoopTri *mlt = mlooptri + a; | ||||
| float bb[6]; | float bb[6]; | ||||
| int vert_index[3]; | |||||
| vert_index[0] = (&mloop[mlt->tri[0]])->v; | |||||
| vert_index[1] = (&mloop[mlt->tri[1]])->v; | |||||
| vert_index[2] = (&mloop[mlt->tri[2]])->v; | |||||
| INIT_MINMAX(bb, bb + 3); | INIT_MINMAX(bb, bb + 3); | ||||
| minmax_v3v3_v3(bb, bb + 3, verts[mf->v1]); | minmax_v3v3_v3(bb, bb + 3, verts[vert_index[0]]); | ||||
| minmax_v3v3_v3(bb, bb + 3, verts[mf->v2]); | minmax_v3v3_v3(bb, bb + 3, verts[vert_index[1]]); | ||||
| minmax_v3v3_v3(bb, bb + 3, verts[mf->v3]); | minmax_v3v3_v3(bb, bb + 3, verts[vert_index[2]]); | ||||
| if (mf->v4) { | |||||
| minmax_v3v3_v3(bb, bb + 3, verts[mf->v4]); | |||||
| } | |||||
| BLI_bvhtree_insert(sys->heat.bvhtree, a, bb, 2); | BLI_bvhtree_insert(sys->heat.bvhtree, a, bb, 2); | ||||
| //Setup inverse pointers to use on isect.orig | //Setup inverse pointers to use on isect.orig | ||||
| sys->heat.vface[mf->v1] = mf; | sys->heat.vltree[vert_index[0]] = mlt; | ||||
| sys->heat.vface[mf->v2] = mf; | sys->heat.vltree[vert_index[1]] = mlt; | ||||
| sys->heat.vface[mf->v3] = mf; | sys->heat.vltree[vert_index[2]] = mlt; | ||||
| if (mf->v4) sys->heat.vface[mf->v4] = mf; | |||||
| } | } | ||||
| BLI_bvhtree_balance(sys->heat.bvhtree); | BLI_bvhtree_balance(sys->heat.bvhtree); | ||||
| Context not available. | |||||
| { | { | ||||
| BVHTreeRayHit hit; | BVHTreeRayHit hit; | ||||
| BVHCallbackUserData data; | BVHCallbackUserData data; | ||||
| MFace *mface; | const MLoopTri *mlt = NULL; | ||||
| float end[3]; | float end[3]; | ||||
| int visible; | int visible; | ||||
| mface = sys->heat.vface[vertex]; | mlt = sys->heat.vltree[vertex]; | ||||
| if (!mface) | if (!mlt) | ||||
| return 1; | return 1; | ||||
| data.sys = sys; | data.sys = sys; | ||||
| Context not available. | |||||
| static void heat_laplacian_create(LaplacianSystem *sys) | static void heat_laplacian_create(LaplacianSystem *sys) | ||||
| { | { | ||||
| MFace *mface = sys->heat.mface, *mf; | const MLoopTri *mlooptri = sys->heat.mlooptri, *mlt; | ||||
| int totface = sys->heat.totface; | MLoop *mloop = sys->heat.mloop; | ||||
| int tottri = sys->heat.tottri; | |||||
| int totvert = sys->heat.totvert; | int totvert = sys->heat.totvert; | ||||
| int a; | int a; | ||||
| Context not available. | |||||
| for (a = 0; a < totvert; a++) | for (a = 0; a < totvert; a++) | ||||
| laplacian_add_vertex(sys, sys->heat.verts[a], 0); | laplacian_add_vertex(sys, sys->heat.verts[a], 0); | ||||
| for (a = 0, mf = mface; a < totface; a++, mf++) { | for (a = 0, mlt = mlooptri; a < tottri; a++, mlt++) { | ||||
| laplacian_add_triangle(sys, mf->v1, mf->v2, mf->v3); | int index[3]; | ||||
Not Done Inline ActionsNote, better do: mloop[mlt->tri[0]].v here. campbellbarton: Note, better do: `mloop[mlt->tri[0]].v` here. | |||||
| if (mf->v4) | index[0] = (&mloop[mlt->tri[0]])->v; | ||||
| laplacian_add_triangle(sys, mf->v1, mf->v3, mf->v4); | index[1] = (&mloop[mlt->tri[1]])->v; | ||||
| index[2] = (&mloop[mlt->tri[2]])->v; | |||||
| laplacian_add_triangle(sys, UNPACK3(index)); | |||||
| } | } | ||||
| /* for distance computation in set_H */ | /* for distance computation in set_H */ | ||||
| Context not available. | |||||
| static void heat_system_free(LaplacianSystem *sys) | static void heat_system_free(LaplacianSystem *sys) | ||||
| { | { | ||||
| BLI_bvhtree_free(sys->heat.bvhtree); | BLI_bvhtree_free(sys->heat.bvhtree); | ||||
| MEM_freeN(sys->heat.vface); | MEM_freeN(sys->heat.vltree); | ||||
| MEM_freeN(sys->heat.mindist); | MEM_freeN(sys->heat.mindist); | ||||
| MEM_freeN(sys->heat.H); | MEM_freeN(sys->heat.H); | ||||
| Context not available. | |||||
| MVert *mvert = me->mvert; | MVert *mvert = me->mvert; | ||||
| bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; | bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; | ||||
| bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; | bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; | ||||
| DerivedMesh *dm = CDDM_from_mesh(me); | |||||
| *err_str = NULL; | *err_str = NULL; | ||||
| Context not available. | |||||
| /* create laplacian */ | /* create laplacian */ | ||||
| sys = laplacian_system_construct_begin(me->totvert, tottri, 1); | sys = laplacian_system_construct_begin(me->totvert, tottri, 1); | ||||
| sys->heat.mface = me->mface; | DM_ensure_looptri(dm); | ||||
| sys->heat.totface = me->totface; | |||||
| sys->heat.totvert = me->totvert; | //XXX change either mesh (big impact) or quickly use a DM here ? or assemble an MLoopTri array ... hmm | ||||
| sys->heat.mlooptri = dm->getLoopTriArray(dm); | |||||
| sys->heat.tottri = dm->getNumLoopTri(dm); | |||||
| sys->heat.mloop = dm->getLoopArray(dm); | |||||
campbellbartonAuthorUnsubmitted Done Inline ActionsYou don't need to use a derived-mesh, just calculate looptri's directly, see cdDM_getPBVH campbellbarton: You don't need to use a derived-mesh, just calculate looptri's directly, see `cdDM_getPBVH` | |||||
| sys->heat.totvert = dm->getNumVerts(dm); | |||||
| sys->heat.verts = verts; | sys->heat.verts = verts; | ||||
| sys->heat.root = root; | sys->heat.root = root; | ||||
| sys->heat.tip = tip; | sys->heat.tip = tip; | ||||
| Context not available. | |||||
| heat_system_free(sys); | heat_system_free(sys); | ||||
| laplacian_system_delete(sys); | laplacian_system_delete(sys); | ||||
| dm->needsFree = 1; | |||||
| dm->release(dm); | |||||
| } | } | ||||
| #ifdef RIGID_DEFORM | #ifdef RIGID_DEFORM | ||||
| Context not available. | |||||
Better just to copy the points to the floats, instead of the floats themselves.