bool Manipulator::canManipulate(Ray3f ray,Box3f box,Mat4f* T) { //nothing to do if (!box.isValid()) return false; Vec3f size=box.size(); Mat4f Direct=(*T) * getTransformationToBox(box); Mat4f Inverse=Direct.invert(); // the ray is in world coordinate Vec3f P1=Inverse * (ray.origin ); Vec3f P2=Inverse * (ray.origin+ray.dir); // should be the unit bounding ball not the bounding box, but seems good enough (probably better) // is objects does not overlap too much! float epsilon=1e-4f; Box3f unit_box( Vec3f( size[0]?-1:-epsilon, size[1]?-1:-epsilon, size[2]?-1:-epsilon), Vec3f( size[0]?+1:+epsilon, size[1]?+1:+epsilon, size[2]?+1:+epsilon)); float tmin,tmax; return (Ray3f(P1,P2-P1).intersectBox(tmin,tmax,unit_box) && tmin>0); }
void test_cast_against_tree(const array<kd_tree_dynamic*>& treelist) // Shoot a ton of random rays against the kdtrees. { assert(treelist.size() > 0); static const int RAY_COUNT = 100000; printf("building kd_tree_packed...\n"); uint64 start_build_ticks = tu_timer::get_profile_ticks(); // Make a list of packed trees, and get an overall bound. array<kd_tree_packed*> kds; axial_box bound(axial_box::INVALID, vec3::flt_max, vec3::minus_flt_max); for (int i = 0; i < treelist.size(); i++) { kd_tree_packed* kd = kd_tree_packed::build(treelist[i]); kds.push_back(kd); bound.set_enclosing(kd->get_bound()); } uint64 end_build_ticks = tu_timer::get_profile_ticks(); printf("built %d trees in %3.3f seconds\n", kds.size(), tu_timer::profile_ticks_to_seconds(end_build_ticks - start_build_ticks)); printf("starting to cast...\n"); uint64 start_cast_ticks = tu_timer::get_profile_ticks(); int hit_count = 0; axial_box unit_box(vec3(-0.5f, -0.5f, -0.5f), vec3(0.5f, 0.5f, 0.5f)); for (int i = 0; i < RAY_COUNT; i++) { #define RANDOM_RAY #ifdef RANDOM_RAY // Ray between two random points within the volume. vec3 start = bound.get_random_point(); vec3 end = bound.get_random_point(); // Avoid near-zero-length ray tests. while ((start - end).sqrmag() < 1e-3f) { end = bound.get_random_point(); } #else // SHORT_RAY // Short rays at some random point within the volume. vec3 start = bound.get_random_point(); vec3 disp = unit_box.get_random_point() * 100.f; while (disp.sqrmag() < 1e-6f) { disp = unit_box.get_random_point() * 100.f; } vec3 end = start + disp; #endif ray_query ray(ray_query::start_end, start, end); bool result = false; for (int ti = 0, tn = kds.size(); ti < tn; ti++) { result = kds[ti]->ray_test(ray); if (result) { hit_count++; break; // early out on hit } } } uint64 end_ticks = tu_timer::get_profile_ticks(); print_ray_stats(start_cast_ticks, end_ticks, RAY_COUNT, hit_count); }