Blender V2.61 - r43446

bvhutils.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Andr Pinto.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00032 #include <stdio.h>
00033 #include <string.h>
00034 #include <math.h>
00035 #include <assert.h>
00036 
00037 #include "DNA_meshdata_types.h"
00038 
00039 #include "BLI_editVert.h"
00040 #include "BLI_utildefines.h"
00041 #include "BLI_linklist.h"
00042 
00043 #include "BKE_DerivedMesh.h"
00044 
00045 
00046 #include "BLI_math.h"
00047 #include "MEM_guardedalloc.h"
00048 
00049 /* Math stuff for ray casting on mesh faces and for nearest surface */
00050 
00051 float bvhtree_ray_tri_intersection(const BVHTreeRay *ray, const float UNUSED(m_dist), const float v0[3], const float v1[3], const float v2[3])
00052 {
00053     float dist;
00054 
00055     if(isect_ray_tri_epsilon_v3(ray->origin, ray->direction, v0, v1, v2, &dist, NULL, FLT_EPSILON))
00056         return dist;
00057 
00058     return FLT_MAX;
00059 }
00060 
00061 static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, const float m_dist, const float v0[3], const float v1[3], const float v2[3])
00062 {
00063     
00064     float idist;
00065     float p1[3];
00066     float plane_normal[3], hit_point[3];
00067 
00068     normal_tri_v3(plane_normal, v0, v1, v2);
00069 
00070     madd_v3_v3v3fl(p1, ray->origin, ray->direction, m_dist);
00071     if(isect_sweeping_sphere_tri_v3(ray->origin, p1, radius, v0, v1, v2, &idist, hit_point))
00072     {
00073         return idist * m_dist;
00074     }
00075 
00076     return FLT_MAX;
00077 }
00078 
00079 
00080 /*
00081  * Function adapted from David Eberly's distance tools (LGPL)
00082  * http://www.geometrictools.com/LibFoundation/Distance/Distance.html
00083  */
00084 float nearest_point_in_tri_surface(const float v0[3], const float v1[3], const float v2[3], const float p[3], int *v, int *e, float nearest[3])
00085 {
00086     float diff[3];
00087     float e0[3];
00088     float e1[3];
00089     float A00;
00090     float A01;
00091     float A11;
00092     float B0;
00093     float B1;
00094     float C;
00095     float Det;
00096     float S;
00097     float T;
00098     float sqrDist;
00099     int lv = -1, le = -1;
00100     
00101     sub_v3_v3v3(diff, v0, p);
00102     sub_v3_v3v3(e0, v1, v0);
00103     sub_v3_v3v3(e1, v2, v0);
00104     
00105     A00 = dot_v3v3(e0, e0);
00106     A01 = dot_v3v3(e0, e1 );
00107     A11 = dot_v3v3(e1, e1 );
00108     B0 = dot_v3v3(diff, e0 );
00109     B1 = dot_v3v3(diff, e1 );
00110     C = dot_v3v3(diff, diff );
00111     Det = fabs( A00 * A11 - A01 * A01 );
00112     S = A01 * B1 - A11 * B0;
00113     T = A01 * B0 - A00 * B1;
00114 
00115     if ( S + T <= Det )
00116     {
00117         if ( S < 0.0f )
00118         {
00119             if ( T < 0.0f )  // Region 4
00120             {
00121                 if ( B0 < 0.0f )
00122                 {
00123                     T = 0.0f;
00124                     if ( -B0 >= A00 )
00125                     {
00126                         S = 1.0f;
00127                         sqrDist = A00 + 2.0f * B0 + C;
00128                         lv = 1;
00129                     }
00130                     else
00131                     {
00132                         if(fabsf(A00) > FLT_EPSILON)
00133                             S = -B0/A00;
00134                         else
00135                             S = 0.0f;
00136                         sqrDist = B0 * S + C;
00137                         le = 0;
00138                     }
00139                 }
00140                 else
00141                 {
00142                     S = 0.0f;
00143                     if ( B1 >= 0.0f )
00144                     {
00145                         T = 0.0f;
00146                         sqrDist = C;
00147                         lv = 0;
00148                     }
00149                     else if ( -B1 >= A11 )
00150                     {
00151                         T = 1.0f;
00152                         sqrDist = A11 + 2.0f * B1 + C;
00153                         lv = 2;
00154                     }
00155                     else
00156                     {
00157                         if(fabsf(A11) > FLT_EPSILON)
00158                             T = -B1 / A11;
00159                         else
00160                             T = 0.0f;
00161                         sqrDist = B1 * T + C;
00162                         le = 1;
00163                     }
00164                 }
00165             }
00166             else  // Region 3
00167             {
00168                 S = 0.0f;
00169                 if ( B1 >= 0.0f )
00170                 {
00171                     T = 0.0f;
00172                     sqrDist = C;
00173                     lv = 0;
00174                 }
00175                 else if ( -B1 >= A11 )
00176                 {
00177                     T = 1.0f;
00178                     sqrDist = A11 + 2.0f * B1 + C;
00179                     lv = 2;
00180                 }
00181                 else
00182                 {
00183                     if(fabsf(A11) > FLT_EPSILON)
00184                         T = -B1 / A11;
00185                     else
00186                         T = 0.0;
00187                     sqrDist = B1 * T + C;
00188                     le = 1;
00189                 }
00190             }
00191         }
00192         else if ( T < 0.0f )  // Region 5
00193         {
00194             T = 0.0f;
00195             if ( B0 >= 0.0f )
00196             {
00197                 S = 0.0f;
00198                 sqrDist = C;
00199                 lv = 0;
00200             }
00201             else if ( -B0 >= A00 )
00202             {
00203                 S = 1.0f;
00204                 sqrDist = A00 + 2.0f * B0 + C;
00205                 lv = 1;
00206             }
00207             else
00208             {
00209                 if(fabsf(A00) > FLT_EPSILON)
00210                     S = -B0 / A00;
00211                 else
00212                     S = 0.0f;
00213                 sqrDist = B0 * S + C;
00214                 le = 0;
00215             }
00216         }
00217         else  // Region 0
00218         {
00219             // Minimum at interior lv
00220             float invDet;
00221             if(fabsf(Det) > FLT_EPSILON)
00222                 invDet = 1.0f / Det;
00223             else
00224                 invDet = 0.0f;
00225             S *= invDet;
00226             T *= invDet;
00227             sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0) +
00228                     T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
00229         }
00230     }
00231     else
00232     {
00233         float tmp0, tmp1, numer, denom;
00234 
00235         if ( S < 0.0f )  // Region 2
00236         {
00237             tmp0 = A01 + B0;
00238             tmp1 = A11 + B1;
00239             if ( tmp1 > tmp0 )
00240             {
00241                 numer = tmp1 - tmp0;
00242                 denom = A00 - 2.0f * A01 + A11;
00243                 if ( numer >= denom )
00244                 {
00245                     S = 1.0f;
00246                     T = 0.0f;
00247                     sqrDist = A00 + 2.0f * B0 + C;
00248                     lv = 1;
00249                 }
00250                 else
00251                 {
00252                     if(fabsf(denom) > FLT_EPSILON)
00253                         S = numer / denom;
00254                     else
00255                         S = 0.0f;
00256                     T = 1.0f - S;
00257                     sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) +
00258                             T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
00259                     le = 2;
00260                 }
00261             }
00262             else
00263             {
00264                 S = 0.0f;
00265                 if ( tmp1 <= 0.0f )
00266                 {
00267                     T = 1.0f;
00268                     sqrDist = A11 + 2.0f * B1 + C;
00269                     lv = 2;
00270                 }
00271                 else if ( B1 >= 0.0f )
00272                 {
00273                     T = 0.0f;
00274                     sqrDist = C;
00275                     lv = 0;
00276                 }
00277                 else
00278                 {
00279                     if(fabsf(A11) > FLT_EPSILON)
00280                         T = -B1 / A11;
00281                     else
00282                         T = 0.0f;
00283                     sqrDist = B1 * T + C;
00284                     le = 1;
00285                 }
00286             }
00287         }
00288         else if ( T < 0.0f )  // Region 6
00289         {
00290             tmp0 = A01 + B1;
00291             tmp1 = A00 + B0;
00292             if ( tmp1 > tmp0 )
00293             {
00294                 numer = tmp1 - tmp0;
00295                 denom = A00 - 2.0f * A01 + A11;
00296                 if ( numer >= denom )
00297                 {
00298                     T = 1.0f;
00299                     S = 0.0f;
00300                     sqrDist = A11 + 2.0f * B1 + C;
00301                     lv = 2;
00302                 }
00303                 else
00304                 {
00305                     if(fabsf(denom) > FLT_EPSILON)
00306                         T = numer / denom;
00307                     else
00308                         T = 0.0f;
00309                     S = 1.0f - T;
00310                     sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) +
00311                             T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
00312                     le = 2;
00313                 }
00314             }
00315             else
00316             {
00317                 T = 0.0f;
00318                 if ( tmp1 <= 0.0f )
00319                 {
00320                     S = 1.0f;
00321                     sqrDist = A00 + 2.0f * B0 + C;
00322                     lv = 1;
00323                 }
00324                 else if ( B0 >= 0.0f )
00325                 {
00326                     S = 0.0f;
00327                     sqrDist = C;
00328                     lv = 0;
00329                 }
00330                 else
00331                 {
00332                     if(fabsf(A00) > FLT_EPSILON)
00333                         S = -B0 / A00;
00334                     else
00335                         S = 0.0f;
00336                     sqrDist = B0 * S + C;
00337                     le = 0;
00338                 }
00339             }
00340         }
00341         else  // Region 1
00342         {
00343             numer = A11 + B1 - A01 - B0;
00344             if ( numer <= 0.0f )
00345             {
00346                 S = 0.0f;
00347                 T = 1.0f;
00348                 sqrDist = A11 + 2.0f * B1 + C;
00349                 lv = 2;
00350             }
00351             else
00352             {
00353                 denom = A00 - 2.0f * A01 + A11;
00354                 if ( numer >= denom )
00355                 {
00356                     S = 1.0f;
00357                     T = 0.0f;
00358                     sqrDist = A00 + 2.0f * B0 + C;
00359                     lv = 1;
00360                 }
00361                 else
00362                 {
00363                     if(fabsf(denom) > FLT_EPSILON)
00364                         S = numer / denom;
00365                     else
00366                         S = 0.0f;
00367                     T = 1.0f - S;
00368                     sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) +
00369                             T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
00370                     le = 2;
00371                 }
00372             }
00373         }
00374     }
00375 
00376     // Account for numerical round-off error
00377     if ( sqrDist < FLT_EPSILON )
00378         sqrDist = 0.0f;
00379     
00380     {
00381         float w[3], x[3], y[3], z[3];
00382         copy_v3_v3(w, v0);
00383         copy_v3_v3(x, e0);
00384         mul_v3_fl(x, S);
00385         copy_v3_v3(y, e1);
00386         mul_v3_fl(y, T);
00387         add_v3_v3v3(z, w, x);
00388         add_v3_v3v3(z, z, y);
00389         //sub_v3_v3v3(d, p, z);
00390         copy_v3_v3(nearest, z);
00391         // d = p - ( v0 + S * e0 + T * e1 );
00392     }
00393     *v = lv;
00394     *e = le;
00395 
00396     return sqrDist;
00397 }
00398 
00399 
00400 /*
00401  * BVH from meshs callbacks
00402  */
00403 
00404 // Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces.
00405 // userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
00406 static void mesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
00407 {
00408     const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata;
00409     MVert *vert = data->vert;
00410     MFace *face = data->face + index;
00411 
00412     float *t0, *t1, *t2, *t3;
00413     t0 = vert[ face->v1 ].co;
00414     t1 = vert[ face->v2 ].co;
00415     t2 = vert[ face->v3 ].co;
00416     t3 = face->v4 ? vert[ face->v4].co : NULL;
00417 
00418     
00419     do
00420     {   
00421         float nearest_tmp[3], dist;
00422         int vertex, edge;
00423         
00424         dist = nearest_point_in_tri_surface(t0, t1, t2, co, &vertex, &edge, nearest_tmp);
00425         if(dist < nearest->dist)
00426         {
00427             nearest->index = index;
00428             nearest->dist = dist;
00429             copy_v3_v3(nearest->co, nearest_tmp);
00430             normal_tri_v3( nearest->no,t0, t1, t2);
00431         }
00432 
00433         t1 = t2;
00434         t2 = t3;
00435         t3 = NULL;
00436 
00437     } while(t2);
00438 }
00439 
00440 // Callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_faces.
00441 // userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
00442 static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
00443 {
00444     const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata;
00445     MVert *vert = data->vert;
00446     MFace *face = data->face + index;
00447 
00448     float *t0, *t1, *t2, *t3;
00449     t0 = vert[ face->v1 ].co;
00450     t1 = vert[ face->v2 ].co;
00451     t2 = vert[ face->v3 ].co;
00452     t3 = face->v4 ? vert[ face->v4].co : NULL;
00453 
00454     
00455     do
00456     {   
00457         float dist;
00458         if(data->sphere_radius == 0.0f)
00459             dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
00460         else
00461             dist = sphereray_tri_intersection(ray, data->sphere_radius, hit->dist, t0, t1, t2);
00462 
00463         if(dist >= 0 && dist < hit->dist)
00464         {
00465             hit->index = index;
00466             hit->dist = dist;
00467             madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
00468 
00469             normal_tri_v3( hit->no,t0, t1, t2);
00470         }
00471 
00472         t1 = t2;
00473         t2 = t3;
00474         t3 = NULL;
00475 
00476     } while(t2);
00477 }
00478 
00479 // Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_edges.
00480 // userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
00481 static void mesh_edges_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
00482 {
00483     const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata;
00484     MVert *vert = data->vert;
00485     MEdge *edge = data->edge + index;
00486     float nearest_tmp[3], dist;
00487 
00488     float *t0, *t1;
00489     t0 = vert[ edge->v1 ].co;
00490     t1 = vert[ edge->v2 ].co;
00491 
00492     closest_to_line_segment_v3(nearest_tmp, co, t0, t1);
00493     dist = len_squared_v3v3(nearest_tmp, co);
00494     
00495     if(dist < nearest->dist)
00496     {
00497         nearest->index = index;
00498         nearest->dist = dist;
00499         copy_v3_v3(nearest->co, nearest_tmp);
00500         sub_v3_v3v3(nearest->no, t0, t1);
00501         normalize_v3(nearest->no);
00502     }
00503 }
00504 
00505 /*
00506  * BVH builders
00507  */
00508 // Builds a bvh tree.. where nodes are the vertexs of the given mesh
00509 BVHTree* bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
00510 {
00511     BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_VERTICES);
00512 
00513     //Not in cache
00514     if(tree == NULL)
00515     {
00516         int i;
00517         int numVerts= mesh->getNumVerts(mesh);
00518         MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT);
00519 
00520         if(vert != NULL)
00521         {
00522             tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis);
00523 
00524             if(tree != NULL)
00525             {
00526                 for(i = 0; i < numVerts; i++)
00527                     BLI_bvhtree_insert(tree, i, vert[i].co, 1);
00528 
00529                 BLI_bvhtree_balance(tree);
00530 
00531                 //Save on cache for later use
00532 //              printf("BVHTree built and saved on cache\n");
00533                 bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_VERTICES);
00534             }
00535         }
00536     }
00537     else
00538     {
00539 //      printf("BVHTree is already build, using cached tree\n");
00540     }
00541 
00542 
00543     //Setup BVHTreeFromMesh
00544     memset(data, 0, sizeof(*data));
00545     data->tree = tree;
00546 
00547     if(data->tree)
00548     {
00549         data->cached = TRUE;
00550 
00551         //a NULL nearest callback works fine
00552         //remeber the min distance to point is the same as the min distance to BV of point
00553         data->nearest_callback = NULL;
00554         data->raycast_callback = NULL;
00555 
00556         data->mesh = mesh;
00557         data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
00558         data->face = mesh->getFaceDataArray(mesh, CD_MFACE);
00559 
00560         data->sphere_radius = epsilon;
00561     }
00562 
00563     return data->tree;
00564 }
00565 
00566 // Builds a bvh tree.. where nodes are the faces of the given mesh.
00567 BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
00568 {
00569     BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_FACES);
00570 
00571     //Not in cache
00572     if(tree == NULL)
00573     {
00574         int i;
00575         int numFaces= mesh->getNumFaces(mesh);
00576         MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT);
00577         MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE);
00578 
00579         if(vert != NULL && face != NULL)
00580         {
00581             /* Create a bvh-tree of the given target */
00582             tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis);
00583             if(tree != NULL)
00584             {
00585                 /* XXX, for snap only, em & dm are assumed to be aligned, since dm is the em's cage */
00586                 EditMesh *em= data->em_evil;
00587                 if(em) {
00588                     EditFace *efa= em->faces.first;
00589                     for(i = 0; i < numFaces; i++, efa= efa->next) {
00590                         if(!(efa->f & 1) && efa->h==0 && !((efa->v1->f&1)+(efa->v2->f&1)+(efa->v3->f&1)+(efa->v4?efa->v4->f&1:0))) {
00591                             float co[4][3];
00592                             copy_v3_v3(co[0], vert[ face[i].v1 ].co);
00593                             copy_v3_v3(co[1], vert[ face[i].v2 ].co);
00594                             copy_v3_v3(co[2], vert[ face[i].v3 ].co);
00595                             if(face[i].v4)
00596                                 copy_v3_v3(co[3], vert[ face[i].v4 ].co);
00597                     
00598                             BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
00599                         }
00600                     }
00601                 }
00602                 else {
00603                     for(i = 0; i < numFaces; i++) {
00604                         float co[4][3];
00605                         copy_v3_v3(co[0], vert[ face[i].v1 ].co);
00606                         copy_v3_v3(co[1], vert[ face[i].v2 ].co);
00607                         copy_v3_v3(co[2], vert[ face[i].v3 ].co);
00608                         if(face[i].v4)
00609                             copy_v3_v3(co[3], vert[ face[i].v4 ].co);
00610                 
00611                         BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
00612                     }
00613                 }
00614                 BLI_bvhtree_balance(tree);
00615 
00616                 //Save on cache for later use
00617 //              printf("BVHTree built and saved on cache\n");
00618                 bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_FACES);
00619             }
00620         }
00621     }
00622     else
00623     {
00624 //      printf("BVHTree is already build, using cached tree\n");
00625     }
00626 
00627 
00628     //Setup BVHTreeFromMesh
00629     memset(data, 0, sizeof(*data));
00630     data->tree = tree;
00631 
00632     if(data->tree)
00633     {
00634         data->cached = TRUE;
00635 
00636         data->nearest_callback = mesh_faces_nearest_point;
00637         data->raycast_callback = mesh_faces_spherecast;
00638 
00639         data->mesh = mesh;
00640         data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
00641         data->face = mesh->getFaceDataArray(mesh, CD_MFACE);
00642 
00643         data->sphere_radius = epsilon;
00644     }
00645     return data->tree;
00646 
00647 }
00648 
00649 // Builds a bvh tree.. where nodes are the faces of the given mesh.
00650 BVHTree* bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
00651 {
00652     BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_EDGES);
00653 
00654     //Not in cache
00655     if(tree == NULL)
00656     {
00657         int i;
00658         int numEdges= mesh->getNumEdges(mesh);
00659         MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT);
00660         MEdge *edge = mesh->getEdgeDataArray(mesh, CD_MEDGE);
00661 
00662         if(vert != NULL && edge != NULL)
00663         {
00664             /* Create a bvh-tree of the given target */
00665             tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis);
00666             if(tree != NULL)
00667             {
00668                 for(i = 0; i < numEdges; i++)
00669                 {
00670                     float co[4][3];
00671                     copy_v3_v3(co[0], vert[ edge[i].v1 ].co);
00672                     copy_v3_v3(co[1], vert[ edge[i].v2 ].co);
00673             
00674                     BLI_bvhtree_insert(tree, i, co[0], 2);
00675                 }
00676                 BLI_bvhtree_balance(tree);
00677 
00678                 //Save on cache for later use
00679 //              printf("BVHTree built and saved on cache\n");
00680                 bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_EDGES);
00681             }
00682         }
00683     }
00684     else
00685     {
00686 //      printf("BVHTree is already build, using cached tree\n");
00687     }
00688 
00689 
00690     //Setup BVHTreeFromMesh
00691     memset(data, 0, sizeof(*data));
00692     data->tree = tree;
00693 
00694     if(data->tree)
00695     {
00696         data->cached = TRUE;
00697 
00698         data->nearest_callback = mesh_edges_nearest_point;
00699         data->raycast_callback = NULL;
00700 
00701         data->mesh = mesh;
00702         data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
00703         data->edge = mesh->getEdgeDataArray(mesh, CD_MEDGE);
00704 
00705         data->sphere_radius = epsilon;
00706     }
00707     return data->tree;
00708 
00709 }
00710 
00711 // Frees data allocated by a call to bvhtree_from_mesh_*.
00712 void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
00713 {
00714     if(data->tree)
00715     {
00716         if(!data->cached)
00717             BLI_bvhtree_free(data->tree);
00718 
00719         memset( data, 0, sizeof(*data) );
00720     }
00721 }
00722 
00723 
00724 /* BVHCache */
00725 typedef struct BVHCacheItem
00726 {
00727     int type;
00728     BVHTree *tree;
00729 
00730 } BVHCacheItem;
00731 
00732 static void bvhcacheitem_set_if_match(void *_cached, void *_search)
00733 {
00734     BVHCacheItem * cached = (BVHCacheItem *)_cached;
00735     BVHCacheItem * search = (BVHCacheItem *)_search;
00736 
00737     if(search->type == cached->type)
00738     {
00739         search->tree = cached->tree;        
00740     }
00741 } 
00742 
00743 BVHTree *bvhcache_find(BVHCache *cache, int type)
00744 {
00745     BVHCacheItem item;
00746     item.type = type;
00747     item.tree = NULL;
00748 
00749     BLI_linklist_apply(*cache, bvhcacheitem_set_if_match, &item);
00750     return item.tree;
00751 }
00752 
00753 void bvhcache_insert(BVHCache *cache, BVHTree *tree, int type)
00754 {
00755     BVHCacheItem *item = NULL;
00756 
00757     assert( tree != NULL );
00758     assert( bvhcache_find(cache, type) == NULL );
00759 
00760     item = MEM_mallocN(sizeof(BVHCacheItem), "BVHCacheItem");
00761     assert( item != NULL );
00762 
00763     item->type = type;
00764     item->tree = tree;
00765 
00766     BLI_linklist_prepend( cache, item );
00767 }
00768 
00769 
00770 void bvhcache_init(BVHCache *cache)
00771 {
00772     *cache = NULL;
00773 }
00774 
00775 static void bvhcacheitem_free(void *_item)
00776 {
00777     BVHCacheItem *item = (BVHCacheItem *)_item;
00778 
00779     BLI_bvhtree_free(item->tree);
00780     MEM_freeN(item);
00781 }
00782 
00783 
00784 void bvhcache_free(BVHCache *cache)
00785 {
00786     BLI_linklist_free(*cache, (LinkNodeFreeFP)bvhcacheitem_free);
00787     *cache = NULL;
00788 }
00789 
00790