/* * This function raycast a single vertex and updates the hit if the "hit" is considered valid. * Returns TRUE if "hit" was updated. * Opts control whether an hit is valid or not * Supported options are: * MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE (front faces hits are ignored) * MOD_SHRINKWRAP_CULL_TARGET_BACKFACE (back faces hits are ignored) */ int normal_projection_project_vertex(char options, const float *vert, const float *dir, const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) { float tmp_co[3], tmp_no[3]; const float *co, *no; BVHTreeRayHit hit_tmp; //Copy from hit (we need to convert hit rays from one space coordinates to the other memcpy(&hit_tmp, hit, sizeof(hit_tmp)); //Apply space transform (TODO readjust dist) if (transf) { copy_v3_v3(tmp_co, vert); space_transform_apply(transf, tmp_co); co = tmp_co; copy_v3_v3(tmp_no, dir); space_transform_apply_normal(transf, tmp_no); no = tmp_no; hit_tmp.dist *= mat4_to_scale(((SpaceTransform*)transf)->local2target); } else { co = vert; no = dir; } hit_tmp.index = -1; BLI_bvhtree_ray_cast(tree, co, no, 0.0f, &hit_tmp, callback, userdata); if (hit_tmp.index != -1) { /* invert the normal first so face culling works on rotated objects */ if (transf) { space_transform_invert_normal(transf, hit_tmp.no); } if (options & (MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE|MOD_SHRINKWRAP_CULL_TARGET_BACKFACE)) { /* apply backface */ const float dot= dot_v3v3(dir, hit_tmp.no); if ( ((options & MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE) && dot <= 0.0f) || ((options & MOD_SHRINKWRAP_CULL_TARGET_BACKFACE) && dot >= 0.0f) ) { return FALSE; /* Ignore hit */ } } if (transf) { /* Inverting space transform (TODO make coeherent with the initial dist readjust) */ space_transform_invert(transf, hit_tmp.co); hit_tmp.dist = len_v3v3((float *)vert, hit_tmp.co); } memcpy(hit, &hit_tmp, sizeof(hit_tmp)); return TRUE; } return FALSE; }
/* * This function raycast a single vertex and updates the hit if the "hit" is considered valid. * Returns true if "hit" was updated. * Opts control whether an hit is valid or not * Supported options are: * MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE (front faces hits are ignored) * MOD_SHRINKWRAP_CULL_TARGET_BACKFACE (back faces hits are ignored) */ bool BKE_shrinkwrap_project_normal( char options, const float vert[3], const float dir[3], const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) { /* don't use this because this dist value could be incompatible * this value used by the callback for comparing prev/new dist values. * also, at the moment there is no need to have a corrected 'dist' value */ // #define USE_DIST_CORRECT float tmp_co[3], tmp_no[3]; const float *co, *no; BVHTreeRayHit hit_tmp; /* Copy from hit (we need to convert hit rays from one space coordinates to the other */ memcpy(&hit_tmp, hit, sizeof(hit_tmp)); /* Apply space transform (TODO readjust dist) */ if (transf) { copy_v3_v3(tmp_co, vert); space_transform_apply(transf, tmp_co); co = tmp_co; copy_v3_v3(tmp_no, dir); space_transform_apply_normal(transf, tmp_no); no = tmp_no; #ifdef USE_DIST_CORRECT hit_tmp.dist *= mat4_to_scale(((SpaceTransform *)transf)->local2target); #endif } else { co = vert; no = dir; } hit_tmp.index = -1; BLI_bvhtree_ray_cast(tree, co, no, 0.0f, &hit_tmp, callback, userdata); if (hit_tmp.index != -1) { /* invert the normal first so face culling works on rotated objects */ if (transf) { space_transform_invert_normal(transf, hit_tmp.no); } if (options & (MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE | MOD_SHRINKWRAP_CULL_TARGET_BACKFACE)) { /* apply backface */ const float dot = dot_v3v3(dir, hit_tmp.no); if (((options & MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE) && dot <= 0.0f) || ((options & MOD_SHRINKWRAP_CULL_TARGET_BACKFACE) && dot >= 0.0f)) { return false; /* Ignore hit */ } } if (transf) { /* Inverting space transform (TODO make coeherent with the initial dist readjust) */ space_transform_invert(transf, hit_tmp.co); #ifdef USE_DIST_CORRECT hit_tmp.dist = len_v3v3(vert, hit_tmp.co); #endif } BLI_assert(hit_tmp.dist <= hit->dist); memcpy(hit, &hit_tmp, sizeof(hit_tmp)); return true; } return false; }