Added bvh nearest neighbour for nearest surface shrinkwrap

This commit is contained in:
Andre Susano Pinto
2008-05-27 18:32:23 +00:00
parent 4383743ace
commit 2a0a999a71
3 changed files with 44 additions and 16 deletions

View File

@@ -86,6 +86,7 @@
typedef void ( *Shrinkwrap_ForeachVertexCallback) (DerivedMesh *target, float *co, float *normal);
static float nearest_point_in_tri_surface(const float *point, const float *v0, const float *v1, const float *v2, float *nearest);
static void normal_short2float(const short *ns, float *nf)
{
@@ -145,18 +146,19 @@ static BVHTree* bvhtree_from_mesh_tri(DerivedMesh *mesh)
{
for(i = 0; i < numFaces; i++)
{
float co[4][3];
float co[3][3];
VECCOPY(co[0], vert[ face[i].v1 ].co);
VECCOPY(co[1], vert[ face[i].v2 ].co);
VECCOPY(co[2], vert[ face[i].v3 ].co);
if(face[i].v4)
VECCOPY(co[3], vert[ face[i].v4 ].co);
BLI_bvhtree_insert(tree, 2*i, co[0], 3);
if(face[i].v4)
BLI_bvhtree_insert(tree, 2*i+1, co[1], 3);
{
/* second face is v1,v3,v4 */
VECCOPY(co[1], vert[ face[i].v3 ].co);
VECCOPY(co[2], vert[ face[i].v4 ].co);
BLI_bvhtree_insert(tree, 2*i+1, co[0], 3);
}
}
BLI_bvhtree_balance(tree);
@@ -165,7 +167,17 @@ static BVHTree* bvhtree_from_mesh_tri(DerivedMesh *mesh)
return tree;
}
static float mesh_tri_nearest_point(void *userdata, int index, const float *co, float *nearest)
{
DerivedMesh *mesh = (DerivedMesh*)(userdata);
MVert *vert = (MVert*)mesh->getVertDataArray(mesh, CD_MVERT);
MFace *face = (MFace*)mesh->getFaceDataArray(mesh, CD_MFACE) + index/2;
if(index & 1)
return nearest_point_in_tri_surface(co, vert[ face->v1 ].co, vert[ face->v3 ].co, vert[ face->v4 ].co, nearest);
else
return nearest_point_in_tri_surface(co, vert[ face->v1 ].co, vert[ face->v2 ].co, vert[ face->v3 ].co, nearest);
}
/*
* Raytree from mesh
@@ -482,7 +494,7 @@ static float nearest_point_in_tri_surface(const float *point, const float *v0, c
nearest[2] = du[2]*nearest_2d[0] + dv[2] * nearest_2d[1] + dw[2] * plane_offset;
}
return sasqrt(plane_sdist + normal_dist*normal_dist);
return plane_sdist + normal_dist*normal_dist;
}
@@ -808,8 +820,8 @@ DerivedMesh *shrinkwrapModifier_do(ShrinkwrapModifierData *smd, Object *ob, Deri
switch(smd->shrinkType)
{
case MOD_SHRINKWRAP_NEAREST_SURFACE:
// BENCH(shrinkwrap_calc_nearest_surface_point(&calc));
BENCH(shrinkwrap_calc_foreach_vertex(&calc, bruteforce_shrinkwrap_calc_nearest_surface_point));
BENCH(shrinkwrap_calc_nearest_surface_point(&calc));
// BENCH(shrinkwrap_calc_foreach_vertex(&calc, bruteforce_shrinkwrap_calc_nearest_surface_point));
break;
case MOD_SHRINKWRAP_NORMAL:
@@ -888,7 +900,7 @@ void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
}
else nearest.dist = FLT_MAX;
index = BLI_bvhtree_find_nearest(tree, tmp_co, &nearest);
index = BLI_bvhtree_find_nearest(tree, tmp_co, &nearest, NULL, NULL);
if(index != -1)
{
@@ -1046,7 +1058,7 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
}
else nearest.dist = FLT_MAX;
index = BLI_bvhtree_find_nearest(tree, tmp_co, &nearest);
index = BLI_bvhtree_find_nearest(tree, tmp_co, &nearest, mesh_tri_nearest_point, calc->target);
if(index != -1)
{

View File

@@ -47,6 +47,10 @@ typedef struct BVHTreeNearest
float dist; /* squared distance to search arround */
} BVHTreeNearest;
/* returns square of the minimum distance from given co to the node, nearest point is stored on nearest */
typedef float (*BVHTree_NearestPointCallback) (void *userdata, int index, const float *co, float *nearest);
BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis);
void BLI_bvhtree_free(BVHTree *tree);
@@ -64,7 +68,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result)
float BLI_bvhtree_getepsilon(BVHTree *tree);
/* find nearest node to the given coordinates (if nearest is given it will only search nodes where square distance is smaller than nearest->dist) */
int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest);
int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata);
#endif // BLI_KDOPBVH_H

View File

@@ -117,6 +117,8 @@ typedef struct BVHNearestData
{
BVHTree *tree;
float *co;
BVHTree_NearestPointCallback callback;
void *userdata;
float proj[13]; //coordinates projection over axis
BVHTreeNearest nearest;
} BVHNearestData;
@@ -919,25 +921,32 @@ static void dfs_find_nearest(BVHNearestData *data, BVHNode *node)
float nearest[3], sdist;
sdist = calc_nearest_point(data, node, nearest);
if(sdist >= data->nearest.dist) return;
if(node->totnode == 0)
{
if(data->callback)
sdist = data->callback(data->userdata , node->index, data->co, nearest);
if(sdist >= data->nearest.dist) return;
data->nearest.index = node->index;
VECCOPY(data->nearest.nearest, nearest);
data->nearest.dist = sdist;
}
else
{
for(i=0; i != node->totnode; i++)
if(sdist < data->nearest.dist)
{
dfs_find_nearest(data, node->children[i]);
for(i=0; i != node->totnode; i++)
{
dfs_find_nearest(data, node->children[i]);
}
}
}
}
int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest)
int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
{
int i;
@@ -947,6 +956,9 @@ int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest)
data.tree = tree;
data.co = co;
data.callback = callback;
data.userdata = userdata;
for(i = data.tree->start_axis; i != data.tree->stop_axis; i++)
{
data.proj[i] = INPR(data.co, KDOP_AXES[i]);