bool AssemblyLeafProbeVisitor::visit( const vector<UniqueID>& items, const vector<GAABB3>& bboxes, const size_t begin, const size_t end, const ShadingRay::RayType& ray, const ShadingRay::RayInfoType& /*ray_info*/, const double tmin, const double tmax, double& distance) { assert(begin + 1 == end); // Retrieve the assembly instance. const AssemblyInstance* assembly_instance = m_tree.m_scene.assembly_instances().get_by_uid(items[begin]); assert(assembly_instance); ShadingRay::RayType local_ray; local_ray.m_tmin = tmin; local_ray.m_tmax = tmax; // Transform the ray to assembly instance space. transform_ray_to_assembly_instance_space( assembly_instance, m_parent_shading_point, ray, local_ray); const RayInfo3d local_ray_info(local_ray); if (assembly_instance->get_assembly().is_flushable()) { // Retrieve the region tree of this assembly. const RegionTree& region_tree = *m_region_tree_cache.access( assembly_instance->get_assembly_uid(), m_tree.m_region_trees); // Check the intersection between the ray and the region tree. RegionLeafProbeVisitor visitor( m_triangle_tree_cache #ifdef FOUNDATION_BSP_ENABLE_TRAVERSAL_STATS , m_triangle_bsp_stats #endif ); RegionLeafProbeIntersector intersector; #ifdef FOUNDATION_BSP_ENABLE_TRAVERSAL_STATS bsp::TraversalStatistics stats; intersector.intersect( region_tree, local_ray, local_ray_info, visitor, stats); #else intersector.intersect( region_tree, local_ray, local_ray_info, visitor); #endif // Terminate traversal if there was a hit. if (visitor.hit()) { m_hit = true; return false; } } else { // Retrieve the triangle tree of this leaf. const TriangleTree* triangle_tree = m_triangle_tree_cache.access( assembly_instance->get_assembly_uid(), m_tree.m_triangle_trees); if (triangle_tree) { // Check the intersection between the ray and the triangle tree. TriangleLeafProbeVisitor visitor; TriangleLeafProbeIntersector intersector; intersector.intersect( *triangle_tree, local_ray, local_ray_info, visitor #ifdef FOUNDATION_BSP_ENABLE_TRAVERSAL_STATS , m_triangle_bsp_stats #endif ); // Terminate traversal if there was a hit. if (visitor.hit()) { m_hit = true; return false; } } } // Continue traversal. distance = ray.m_tmax; return true; }
bool AssemblyLeafProbeVisitor::visit( const AssemblyTree::NodeType& node, const ShadingRay& ray, const ShadingRay::RayInfoType& ray_info, double& distance #ifdef FOUNDATION_BVH_ENABLE_TRAVERSAL_STATS , bvh::TraversalStatistics& stats #endif ) { // Retrieve the assembly instances for this leaf. const size_t assembly_instance_count = node.get_item_count(); const AssemblyInstance* const* assembly_instances = assembly_instance_count <= AssemblyTree::NodeType::MaxUserDataSize / sizeof(AssemblyInstance*) ? &node.get_user_data<const AssemblyInstance*>() // items are stored in the leaf node : &m_tree.m_assembly_instances[node.get_item_index()]; // items are stored in the tree for (size_t i = 0; i < assembly_instance_count; ++i) { // Retrieve the assembly instance. const AssemblyInstance* assembly_instance = assembly_instances[i]; // Evaluate the transformation of the assembly instance. const Transformd assembly_instance_transform = assembly_instance->transform_sequence().evaluate(ray.m_time); // Transform the ray to assembly instance space. ShadingRay local_ray; transform_ray_to_assembly_instance_space( assembly_instance, assembly_instance_transform, m_parent_shading_point, ray, local_ray); local_ray.m_tmin = ray.m_tmin; local_ray.m_tmax = ray.m_tmax; local_ray.m_time = ray.m_time; local_ray.m_flags = ray.m_flags; const RayInfo3d local_ray_info(local_ray); FOUNDATION_BVH_TRAVERSAL_STATS(stats.m_intersected_items.insert(1)); if (assembly_instance->get_assembly().is_flushable()) { // Retrieve the region tree of this assembly. const RegionTree& region_tree = *m_region_tree_cache.access( assembly_instance->get_assembly().get_uid(), m_tree.m_region_trees); // Check the intersection between the ray and the region tree. RegionLeafProbeVisitor visitor( m_triangle_tree_cache #ifdef FOUNDATION_BVH_ENABLE_TRAVERSAL_STATS , m_triangle_tree_stats #endif ); RegionLeafProbeIntersector intersector; intersector.intersect( region_tree, local_ray, local_ray_info, visitor); // Terminate traversal if there was a hit. if (visitor.hit()) { m_hit = true; return false; } } else { // Retrieve the triangle tree of this leaf. const TriangleTree* triangle_tree = m_triangle_tree_cache.access( assembly_instance->get_assembly().get_uid(), m_tree.m_triangle_trees); if (triangle_tree) { // Check the intersection between the ray and the triangle tree. TriangleTreeProbeIntersector intersector; TriangleLeafProbeVisitor visitor(*triangle_tree); intersector.intersect( *triangle_tree, local_ray, local_ray_info, local_ray.m_time, visitor #ifdef FOUNDATION_BVH_ENABLE_TRAVERSAL_STATS , m_triangle_tree_stats #endif ); // Terminate traversal if there was a hit. if (visitor.hit()) { m_hit = true; return false; } } } } // Continue traversal. distance = ray.m_tmax; return true; }
bool AssemblyLeafVisitor::visit( const vector<UniqueID>& items, const vector<GAABB3>& bboxes, const size_t begin, const size_t end, const ShadingRay::RayType& ray, const ShadingRay::RayInfoType& /*ray_info*/, const double tmin, const double tmax, double& distance) { assert(begin + 1 == end); // Retrieve the assembly instance. const AssemblyInstance* assembly_instance = m_tree.m_scene.assembly_instances().get_by_uid(items[begin]); assert(assembly_instance); ShadingPoint result; result.m_ray.m_tmin = tmin; result.m_ray.m_tmax = tmax; result.m_ray.m_time = m_shading_point.m_ray.m_time; result.m_ray.m_flags = m_shading_point.m_ray.m_flags; // Transform the ray to assembly instance space. transform_ray_to_assembly_instance_space( assembly_instance, m_parent_shading_point, ray, result.m_ray); const RayInfo3d ray_info(result.m_ray); if (assembly_instance->get_assembly().is_flushable()) { // Retrieve the region tree of this assembly. const RegionTree& region_tree = *m_region_tree_cache.access( assembly_instance->get_assembly_uid(), m_tree.m_region_trees); // Check the intersection between the ray and the region tree. RegionLeafVisitor visitor( result, m_triangle_tree_cache #ifdef FOUNDATION_BSP_ENABLE_TRAVERSAL_STATS , m_triangle_bsp_stats #endif ); RegionLeafIntersector intersector; #ifdef FOUNDATION_BSP_ENABLE_TRAVERSAL_STATS bsp::TraversalStatistics stats; intersector.intersect( region_tree, result.m_ray, ray_info, visitor, stats); #else intersector.intersect( region_tree, result.m_ray, ray_info, visitor); #endif } else { // Retrieve the triangle tree of this assembly. const TriangleTree* triangle_tree = m_triangle_tree_cache.access( assembly_instance->get_assembly_uid(), m_tree.m_triangle_trees); if (triangle_tree) { // Check the intersection between the ray and the triangle tree. TriangleLeafVisitor visitor(result); TriangleLeafIntersector intersector; intersector.intersect( *triangle_tree, result.m_ray, ray_info, visitor #ifdef FOUNDATION_BSP_ENABLE_TRAVERSAL_STATS , m_triangle_bsp_stats #endif ); visitor.read_hit_triangle_data(); } } // Keep track of the closest hit. if (result.m_hit && result.m_ray.m_tmax < m_shading_point.m_ray.m_tmax) { m_shading_point.m_ray.m_tmax = result.m_ray.m_tmax; m_shading_point.m_hit = true; m_shading_point.m_bary = result.m_bary; m_shading_point.m_asm_instance_uid = assembly_instance->get_uid(); m_shading_point.m_object_instance_index = result.m_object_instance_index; m_shading_point.m_region_index = result.m_region_index; m_shading_point.m_triangle_index = result.m_triangle_index; m_shading_point.m_triangle_support_plane = result.m_triangle_support_plane; } // Continue traversal. distance = m_shading_point.m_ray.m_tmax; return true; }