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:
authorCampbell Barton <ideasman42@gmail.com>2013-04-24 03:57:27 +0400
committerCampbell Barton <ideasman42@gmail.com>2013-04-24 03:57:27 +0400
commitb64ec6c51e869ae432a2f2f0ecd28b81f874ce51 (patch)
tree2afc1937885e76aa3bda6de87819418e16380fff /source/blender/blenkernel/intern/bvhutils.c
parenta1ed1dd26b622604a3488e7599943b65817d3411 (diff)
alternate fix for [#24887] - r33294.
Casting a ray onto an editmesh was building a derivedMesh, raytree, then freeing for every ray-cast. Noticed while using ruler+snapping in editmode. Instead of attempting to align the MFace and edit-mesh tessfaces, just use editmesh for ray-casting.
Diffstat (limited to 'source/blender/blenkernel/intern/bvhutils.c')
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c86
1 files changed, 76 insertions, 10 deletions
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index e44b1f4536e..188ee317918 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -394,6 +394,31 @@ static void mesh_faces_nearest_point(void *userdata, int index, const float co[3
} while (t2);
}
+/* copy of function above (warning, should de-duplicate with editmesh_bvh.c) */
+static void editmesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
+{
+ const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
+ BMEditMesh *em = data->em_evil;
+ const BMLoop **ltri = (const BMLoop **)em->looptris[index];
+
+ float *t0, *t1, *t2;
+ t0 = ltri[0]->v->co;
+ t1 = ltri[1]->v->co;
+ t2 = ltri[2]->v->co;
+
+ {
+ float nearest_tmp[3], dist;
+ int vertex, edge;
+
+ dist = nearest_point_in_tri_surface(t0, t1, t2, co, &vertex, &edge, nearest_tmp);
+ if (dist < nearest->dist) {
+ nearest->index = index;
+ nearest->dist = dist;
+ copy_v3_v3(nearest->co, nearest_tmp);
+ normal_tri_v3(nearest->no, t0, t1, t2);
+ }
+ }
+}
/* Callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_faces.
* userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
@@ -434,6 +459,35 @@ static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *r
} while (t2);
}
+/* copy of function above (warning, should de-duplicate with editmesh_bvh.c) */
+static void editmesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
+ BMEditMesh *em = data->em_evil;
+ const BMLoop **ltri = (const BMLoop **)em->looptris[index];
+
+ float *t0, *t1, *t2;
+ t0 = ltri[0]->v->co;
+ t1 = ltri[1]->v->co;
+ t2 = ltri[2]->v->co;
+
+
+ {
+ float dist;
+ if (data->sphere_radius == 0.0f)
+ dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
+ else
+ dist = sphereray_tri_intersection(ray, data->sphere_radius, hit->dist, t0, t1, t2);
+
+ if (dist >= 0 && dist < hit->dist) {
+ hit->index = index;
+ hit->dist = dist;
+ madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
+
+ normal_tri_v3(hit->no, t0, t1, t2);
+ }
+ }
+}
/* Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_edges.
* userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
@@ -521,32 +575,37 @@ BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float
BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
{
BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_FACES);
+ BMEditMesh *em = data->em_evil;
/* Not in cache */
if (tree == NULL) {
int i;
- int numFaces = mesh->getNumTessFaces(mesh);
+ int numFaces;
/* BMESH specific check that we have tessfaces,
* we _could_ tessellate here but rather not - campbell
*
* this assert checks we have tessfaces,
* if not caller should use DM_ensure_tessface() */
- BLI_assert(!(numFaces == 0 && mesh->getNumPolys(mesh) != 0));
+ if (em) {
+ numFaces = em->tottri;
+ }
+ else {
+ numFaces = mesh->getNumTessFaces(mesh);
+ BLI_assert(!(numFaces == 0 && mesh->getNumPolys(mesh) != 0));
+ }
if (numFaces != 0) {
/* Create a bvh-tree of the given target */
+ // printf("%s: building BVH, total=%d\n", __func__, numFaces);
tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis);
if (tree != NULL) {
- BMEditMesh *em = data->em_evil;
if (em) {
/* data->em_evil is only set for snapping, and only for the mesh of the object
* which is currently open in edit mode. When set, the bvhtree should not contain
* faces that will interfere with snapping (e.g. faces that are hidden/selected
* or faces that have selected verts).*/
- /* XXX, for snap only, em & dm are assumed to be aligned, since dm is the em's cage */
-
/* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden
* and/or selected. Even if the faces themselves are not selected for the snapped
* transform, having a vertex selected means the face (and thus it's tessellated
@@ -630,16 +689,23 @@ BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float
/* Setup BVHTreeFromMesh */
memset(data, 0, sizeof(*data));
data->tree = tree;
+ data->em_evil = em;
if (data->tree) {
data->cached = TRUE;
- data->nearest_callback = mesh_faces_nearest_point;
- data->raycast_callback = mesh_faces_spherecast;
+ if (em) {
+ data->nearest_callback = editmesh_faces_nearest_point;
+ data->raycast_callback = editmesh_faces_spherecast;
+ }
+ else {
+ data->nearest_callback = mesh_faces_nearest_point;
+ data->raycast_callback = mesh_faces_spherecast;
- data->mesh = mesh;
- data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
- data->face = mesh->getTessFaceDataArray(mesh, CD_MFACE);
+ data->mesh = mesh;
+ data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
+ data->face = mesh->getTessFaceDataArray(mesh, CD_MFACE);
+ }
data->sphere_radius = epsilon;
}