bool AssemblyLeafVisitor::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_index = node.get_item_index(); 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[assembly_instance_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. ShadingPoint local_shading_point; transform_ray_to_assembly_instance_space( assembly_instance, assembly_instance_transform, m_parent_shading_point, ray, local_shading_point.m_ray); local_shading_point.m_ray.m_tmin = ray.m_tmin; local_shading_point.m_ray.m_tmax = ray.m_tmax; local_shading_point.m_ray.m_time = m_shading_point.m_ray.m_time; local_shading_point.m_ray.m_flags = m_shading_point.m_ray.m_flags; const RayInfo3d local_ray_info(local_shading_point.m_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. RegionLeafVisitor visitor( local_shading_point, m_triangle_tree_cache #ifdef FOUNDATION_BVH_ENABLE_TRAVERSAL_STATS , m_triangle_tree_stats #endif ); RegionLeafIntersector intersector; intersector.intersect( region_tree, local_shading_point.m_ray, local_ray_info, visitor); } else { // Retrieve the triangle tree of this assembly. 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. TriangleTreeIntersector intersector; TriangleLeafVisitor visitor(*triangle_tree, local_shading_point); intersector.intersect( *triangle_tree, local_shading_point.m_ray, local_ray_info, local_shading_point.m_ray.m_time, visitor #ifdef FOUNDATION_BVH_ENABLE_TRAVERSAL_STATS , m_triangle_tree_stats #endif ); visitor.read_hit_triangle_data(); } } // Keep track of the closest hit. if (local_shading_point.m_hit && local_shading_point.m_ray.m_tmax < m_shading_point.m_ray.m_tmax) { m_shading_point.m_ray.m_tmax = local_shading_point.m_ray.m_tmax; m_shading_point.m_hit = true; m_shading_point.m_bary = local_shading_point.m_bary; m_shading_point.m_assembly_instance = assembly_instance; m_shading_point.m_assembly_instance_transform = assembly_instance_transform; m_shading_point.m_object_instance_index = local_shading_point.m_object_instance_index; m_shading_point.m_region_index = local_shading_point.m_region_index; m_shading_point.m_triangle_index = local_shading_point.m_triangle_index; m_shading_point.m_triangle_support_plane = local_shading_point.m_triangle_support_plane; } } // Continue traversal. distance = m_shading_point.m_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; }