talpa/main.cpp
/// Ray cast into the scene, return index of the closest primitive of the type specified
///
Ray cast into the scene, return index of the closest primitive of the type specified
Ray cast into the scene return index of the closest primitive of the type specified
unsigned int ray_cast(const DynamicSurface& surface,
                          const Vec3f& ray_origin, 
                          const Vec3f& ray_direction, 
                          unsigned int primitive_type, 
                          size_t& hit_index )
    {
        const double RAY_CAST_HIT_DISTANCE = 2e-2;
        Vec3d rorigin( ray_origin[0], ray_origin[1], ray_origin[2] );
        Vec3d rhead = rorigin + 100.0 * Vec3d( ray_direction[0], ray_direction[1], ray_direction[2] );
        Vec3d aabb_low, aabb_high;
        minmax( rorigin, rhead, aabb_low, aabb_high );
        if ( primitive_type == 0)
        {
            if ( surface.m_verbose ) { std::cout << "looking for vertices..." << std::endl; }
            double vertex_min_parameter = BIG_DOUBLE;
            size_t vertex_min_index = (size_t)~0;
            std::vector<size_t> overlapping_vertices;
            surface.m_broad_phase->get_potential_vertex_collisions( aabb_low, aabb_high, true, true, overlapping_vertices );
            if ( surface.m_verbose ) { std::cout << "potential vertices: " << overlapping_vertices.size() << std::endl; }
            for ( size_t i = 0; i < overlapping_vertices.size(); ++i )
            {
                const Vec3d& v = surface.get_position( overlapping_vertices[i] );
                double distance = UNINITIALIZED_DOUBLE;       
                double ray_parameter = UNINITIALIZED_DOUBLE;
                Vec3d normal(UNINITIALIZED_DOUBLE, UNINITIALIZED_DOUBLE, UNINITIALIZED_DOUBLE);
                double normal_multiplier = UNINITIALIZED_DOUBLE;
                check_point_edge_proximity( false, v, rhead, rorigin, distance, ray_parameter, normal, normal_multiplier );
                if ( distance < RAY_CAST_HIT_DISTANCE )
                {
                    if ( ray_parameter < vertex_min_parameter )
                    {
                        vertex_min_parameter = ray_parameter - RAY_CAST_HIT_DISTANCE;
                        vertex_min_index = overlapping_vertices[i];
                    }
                }
            }
            if ( vertex_min_parameter < BIG_DOUBLE )
            {
                hit_index = vertex_min_index;
                return RAY_HIT_VERTEX;
            }
            else
            {
                return RAY_HIT_NOTHING;
            }
        }
        else if ( primitive_type == 1)
        {
            double edge_min_distance = BIG_DOUBLE;
            size_t edge_min_index = (size_t)~0;
            std::vector<size_t> overlapping_edges;
            surface.m_broad_phase->get_potential_edge_collisions( aabb_low, aabb_high, true, true, overlapping_edges );
            for ( size_t i = 0; i < overlapping_edges.size(); ++i )
            {
                const Vec2st& e = surface.m_mesh.m_edges[ overlapping_edges[i] ];
                const Vec3d& v0 = surface.get_position( e[0] );
                const Vec3d& v1 = surface.get_position( e[1] );
                double distance;
                double ray_parameter, edge_parameter;
                Vec3d normal;
                check_edge_edge_proximity( rhead,  
                                          rorigin,
                                          v0,
                                          v1,
                                          distance, ray_parameter, edge_parameter, normal );
                if ( distance < RAY_CAST_HIT_DISTANCE && edge_parameter > 0.0 && edge_parameter < 1.0 )
                {
                    if ( distance < edge_min_distance )
                    {
                        edge_min_distance = distance; 
                        edge_min_index = overlapping_edges[i];
                    }
                }         
            }
            if ( edge_min_distance < BIG_DOUBLE )
            {
                hit_index = edge_min_index;
                return RAY_HIT_EDGE;
            }
            else
            {
                return RAY_HIT_NOTHING;
            }
        }
        else
        {
            double triangle_min_parameter = BIG_DOUBLE;
            size_t triangle_min_index = (size_t)~0;
            std::vector<size_t> overlapping_triangles;
            surface.m_broad_phase->get_potential_triangle_collisions( aabb_low, aabb_high, true, true, overlapping_triangles );
            for ( size_t i = 0; i < overlapping_triangles.size(); ++i )
            {
                const Vec3st& tri = surface.m_mesh.get_triangle( overlapping_triangles[i] );
                Vec3st t = sort_triangle( tri );
                assert( t[0] < t[1] && t[0] < t[2] && t[1] < t[2] );
                const Vec3d& v0 = surface.get_position( t[0] );
                const Vec3d& v1 = surface.get_position( t[1] );
                const Vec3d& v2 = surface.get_position( t[2] );      
                double origin_parameter, ray_parameter, s0, s1, s2;
                Vec3d normal;
                size_t dummy_index = surface.get_num_vertices();
                bool ray_hit = segment_triangle_intersection( rorigin, dummy_index,
                                                             rhead, dummy_index + 1,                                                      
                                                             v0, t[0],
                                                             v1, t[1],
                                                             v2, t[2],   
                                                             origin_parameter, ray_parameter, s0, s1, s2,
                                                             false );
                if ( ray_hit )
                {
                    if ( ray_parameter < triangle_min_parameter )
                    {
                        triangle_min_parameter = ray_parameter;
                        triangle_min_index = overlapping_triangles[i];
                    }
                }         
            }
            if ( triangle_min_parameter < BIG_DOUBLE )
            {
                hit_index = triangle_min_index;
                return RAY_HIT_TRIANGLE;
            }
            else
            {
                return RAY_HIT_NOTHING;
            }
        }
    }
unsigned int ray_cast ( const DynamicSurface & surface , const Vec3f & ray_origin , const Vec3f & ray_direction , unsigned int primitive_type , size_t & hit_index ) { const double RAY_CAST_HIT_DISTANCE = 2e-2 ; Vec3d rorigin ( ray_origin [ 0 ] , ray_origin [ 1 ] , ray_origin [ 2 ] ) ; Vec3d rhead = rorigin + 100.0 * Vec3d ( ray_direction [ 0 ] , ray_direction [ 1 ] , ray_direction [ 2 ] ) ; Vec3d aabb_low , aabb_high ; minmax ( rorigin , rhead , aabb_low , aabb_high ) ; if ( primitive_type == 0 ) { if ( surface . m_verbose ) { std :: cout << " " << std :: endl ; } double vertex_min_parameter = BIG_DOUBLE ; size_t vertex_min_index = ( size_t ) ~ 0 ; std :: vector < size_t > overlapping_vertices ; surface . m_broad_phase -> get_potential_vertex_collisions ( aabb_low , aabb_high , true , true , overlapping_vertices ) ; if ( surface . m_verbose ) { std :: cout << " " << overlapping_vertices . size ( ) << std :: endl ; } for ( size_t i = 0 ; i < overlapping_vertices . size ( ) ; ++ i ) { const Vec3d & v = surface . get_position ( overlapping_vertices [ i ] ) ; double distance = UNINITIALIZED_DOUBLE ; double ray_parameter = UNINITIALIZED_DOUBLE ; Vec3d normal ( UNINITIALIZED_DOUBLE , UNINITIALIZED_DOUBLE , UNINITIALIZED_DOUBLE ) ; double normal_multiplier = UNINITIALIZED_DOUBLE ; check_point_edge_proximity ( false , v , rhead , rorigin , distance , ray_parameter , normal , normal_multiplier ) ; if ( distance < RAY_CAST_HIT_DISTANCE ) { if ( ray_parameter < vertex_min_parameter ) { vertex_min_parameter = ray_parameter - RAY_CAST_HIT_DISTANCE ; vertex_min_index = overlapping_vertices [ i ] ; } } } if ( vertex_min_parameter < BIG_DOUBLE ) { hit_index = vertex_min_index ; return RAY_HIT_VERTEX ; } else { return RAY_HIT_NOTHING ; } } else if ( primitive_type == 1 ) { double edge_min_distance = BIG_DOUBLE ; size_t edge_min_index = ( size_t ) ~ 0 ; std :: vector < size_t > overlapping_edges ; surface . m_broad_phase -> get_potential_edge_collisions ( aabb_low , aabb_high , true , true , overlapping_edges ) ; for ( size_t i = 0 ; i < overlapping_edges . size ( ) ; ++ i ) { const Vec2st & e = surface . m_mesh . m_edges [ overlapping_edges [ i ] ] ; const Vec3d & v0 = surface . get_position ( e [ 0 ] ) ; const Vec3d & v1 = surface . get_position ( e [ 1 ] ) ; double distance ; double ray_parameter , edge_parameter ; Vec3d normal ; check_edge_edge_proximity ( rhead , rorigin , v0 , v1 , distance , ray_parameter , edge_parameter , normal ) ; if ( distance < RAY_CAST_HIT_DISTANCE && edge_parameter > 0.0 && edge_parameter < 1.0 ) { if ( distance < edge_min_distance ) { edge_min_distance = distance ; edge_min_index = overlapping_edges [ i ] ; } } } if ( edge_min_distance < BIG_DOUBLE ) { hit_index = edge_min_index ; return RAY_HIT_EDGE ; } else { return RAY_HIT_NOTHING ; } } else { double triangle_min_parameter = BIG_DOUBLE ; size_t triangle_min_index = ( size_t ) ~ 0 ; std :: vector < size_t > overlapping_triangles ; surface . m_broad_phase -> get_potential_triangle_collisions ( aabb_low , aabb_high , true , true , overlapping_triangles ) ; for ( size_t i = 0 ; i < overlapping_triangles . size ( ) ; ++ i ) { const Vec3st & tri = surface . m_mesh . get_triangle ( overlapping_triangles [ i ] ) ; Vec3st t = sort_triangle ( tri ) ; assert ( t [ 0 ] < t [ 1 ] && t [ 0 ] < t [ 2 ] && t [ 1 ] < t [ 2 ] ) ; const Vec3d & v0 = surface . get_position ( t [ 0 ] ) ; const Vec3d & v1 = surface . get_position ( t [ 1 ] ) ; const Vec3d & v2 = surface . get_position ( t [ 2 ] ) ; double origin_parameter , ray_parameter , s0 , s1 , s2 ; Vec3d normal ; size_t dummy_index = surface . get_num_vertices ( ) ; bool ray_hit = segment_triangle_intersection ( rorigin , dummy_index , rhead , dummy_index + 1 , v0 , t [ 0 ] , v1 , t [ 1 ] , v2 , t [ 2 ] , origin_parameter , ray_parameter , s0 , s1 , s2 , false ) ; if ( ray_hit ) { if ( ray_parameter < triangle_min_parameter ) { triangle_min_parameter = ray_parameter ; triangle_min_index = overlapping_triangles [ i ] ; } } } if ( triangle_min_parameter < BIG_DOUBLE ) { hit_index = triangle_min_index ; return RAY_HIT_TRIANGLE ; } else { return RAY_HIT_NOTHING ; } } }
Ray cast into the scene, return index of the closest primitive of the type specified
Ray cast into the scene return index of the closest primitive of the type specified
// ----------------------------------------------------------------- // Vertices // ----------------------------------------------------------------- // initialized to silence compiler warnings // ----------------------------------------------------------------- // Edges // ----------------------------------------------------------------- // - RAY_CAST_HIT_DISTANCE; // ----------------------------------------------------------------- // Triangles // -----------------------------------------------------------------