MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 #include "moab/Core.hpp" 00002 #include "moab/CartVect.hpp" 00003 #include "moab/OrientedBox.hpp" 00004 #include "moab/OrientedBoxTreeTool.hpp" 00005 #include <cstdlib> 00006 #include <iostream> 00007 #include <cmath> 00008 #include <ctime> 00009 #include <csignal> 00010 #include <cassert> 00011 00012 const int NUM_RAYS = 40000; 00013 const int NUM_XSCT = 20000; 00014 00015 using namespace moab; 00016 00017 static void usage() 00018 { 00019 std::cerr << "obb_time [-r <int>] [-i <int>] <filename>" << std::endl 00020 << " -r - Specify total rays to fire." << std::endl 00021 << " Zero implies unbounded. Default: " << NUM_RAYS << std::endl 00022 << " -i - Specify total intersecting rays to fire." << std::endl 00023 << " Zero implies unbounded. Default: " << NUM_XSCT << std::endl 00024 << " -s - Use set-based tree." << std::endl 00025 << " -p - Measure and report traversal performance statistics" << std::endl 00026 << " The input file should be generated using the '-s'" << std::endl 00027 << " option with 'obb_test'" << std::endl; 00028 exit( 1 ); 00029 } 00030 00031 void generate_ray( const CartVect& sphere_center, double sphere_radius, CartVect& point, CartVect& dir ) 00032 { 00033 const int H = RAND_MAX / 2; 00034 point[0] = (double)rand() / H - 1; 00035 point[1] = (double)rand() / H - 1; 00036 point[2] = (double)rand() / H - 1; 00037 point *= sphere_radius; 00038 00039 dir[0] = (double)rand() * -point[0]; 00040 dir[1] = (double)rand() * -point[1]; 00041 dir[2] = (double)rand() * -point[2]; 00042 dir.normalize(); 00043 00044 point += sphere_center; 00045 } 00046 00047 ErrorCode read_tree( Interface* instance, const char* filename, EntityHandle& tree_root_out ) 00048 { 00049 ErrorCode rval = instance->load_mesh( filename ); 00050 if( MB_SUCCESS != rval ) return rval; 00051 00052 Tag tag; 00053 rval = instance->tag_get_handle( "OBB_ROOT", 1, MB_TYPE_HANDLE, tag ); 00054 if( MB_SUCCESS != rval ) return rval; 00055 00056 const EntityHandle root = 0; 00057 return instance->tag_get_data( tag, &root, 1, &tree_root_out ); 00058 } 00059 00060 // global variables for CLI options 00061 int num_rays = NUM_RAYS; 00062 int num_xsct = NUM_XSCT; 00063 const char* filename = 0; 00064 bool do_sets = false; 00065 bool do_trv_stats = false; 00066 00067 // global to make accessable to signal handler 00068 int rays = 0, xsct = 0, gen = 0; 00069 clock_t ttimer; 00070 00071 extern "C" { 00072 void signal_handler( int ) 00073 { 00074 ttimer = clock() - ttimer; 00075 std::cout << filename << ":" << std::endl 00076 << rays << " of " << num_rays << " ray fires done" << std::endl 00077 << xsct << " of " << num_xsct << " intersecting fires" << std::endl 00078 << gen << " unique rays used" << std::endl 00079 << (double)ttimer / CLOCKS_PER_SEC << " seconds" << std::endl; 00080 exit( 1 ); 00081 } 00082 } 00083 00084 int main( int argc, char* argv[] ) 00085 { 00086 signal( SIGINT, &signal_handler ); 00087 00088 for( int i = 1; i < argc; ++i ) 00089 { 00090 if( !strcmp( argv[i], "-r" ) ) 00091 { 00092 ++i; 00093 if( i == argc || !argv[i][0] ) 00094 { 00095 std::cerr << "Expected value following '-r'" << std::endl; 00096 usage(); 00097 } 00098 char* end; 00099 long t1 = strtol( argv[i], &end, 0 ); 00100 num_rays = (int)t1; 00101 if( *end || t1 < 0 || num_rays != t1 ) 00102 { 00103 std::cerr << "Expected positive integer following '-r'" << std::endl; 00104 usage(); 00105 } 00106 } 00107 else if( !strcmp( argv[i], "-i" ) ) 00108 { 00109 ++i; 00110 if( i == argc || !argv[i][0] ) 00111 { 00112 std::cerr << "Expected value following '-i'" << std::endl; 00113 usage(); 00114 } 00115 char* end; 00116 long t1 = strtol( argv[i], &end, 0 ); 00117 num_xsct = (int)t1; 00118 if( *end || t1 < 0 || num_xsct != t1 ) 00119 { 00120 std::cerr << "Expected positive integer following '-i'" << std::endl; 00121 usage(); 00122 } 00123 } 00124 else if( !strcmp( argv[i], "-s" ) ) 00125 { 00126 do_sets = true; 00127 } 00128 else if( !strcmp( argv[i], "-p" ) ) 00129 { 00130 do_trv_stats = true; 00131 } 00132 else if( filename ) 00133 { 00134 std::cerr << "Invalid options or multiple file names specified." << std::endl; 00135 usage(); 00136 } 00137 else 00138 { 00139 filename = argv[i]; 00140 } 00141 } 00142 if( !filename ) 00143 { 00144 std::cerr << "No file name specified." << std::endl; 00145 usage(); 00146 } 00147 00148 Core instance; 00149 Interface* iface = &instance; 00150 EntityHandle root; 00151 ErrorCode rval = read_tree( iface, filename, root ); 00152 if( MB_SUCCESS != rval ) 00153 { 00154 std::cerr << "Failed to read \"" << filename << '"' << std::endl; 00155 return 2; 00156 } 00157 00158 OrientedBoxTreeTool tool( iface ); 00159 OrientedBox box; 00160 rval = tool.box( root, box ); 00161 if( MB_SUCCESS != rval ) 00162 { 00163 std::cerr << "Corrupt tree. Cannot get box for root node." << std::endl; 00164 return 3; 00165 } 00166 00167 OrientedBoxTreeTool::TrvStats* stats = NULL; 00168 if( do_trv_stats ) 00169 { 00170 stats = new OrientedBoxTreeTool::TrvStats; 00171 } 00172 00173 const unsigned cached = 1000; 00174 std::vector< double > intersections; 00175 std::vector< EntityHandle > sets, facets; 00176 CartVect point, dir; 00177 std::vector< CartVect > randrays; 00178 randrays.reserve( cached ); 00179 int cached_idx = 0; 00180 00181 ttimer = clock(); 00182 for( ;; ) 00183 { 00184 if( !num_rays ) 00185 { 00186 if( xsct >= num_xsct ) break; 00187 } 00188 else if( !num_xsct ) 00189 { 00190 if( rays >= num_rays ) break; 00191 } 00192 else if( rays >= num_rays && xsct >= num_xsct ) 00193 break; 00194 00195 ++rays; 00196 if( randrays.size() < cached ) 00197 { 00198 generate_ray( box.center, box.outer_radius(), point, dir ); 00199 ++gen; 00200 } 00201 else 00202 { 00203 point = randrays[cached_idx++]; 00204 dir = randrays[cached_idx++]; 00205 cached_idx = cached_idx % randrays.size(); 00206 } 00207 00208 intersections.clear(); 00209 if( do_sets ) 00210 { 00211 sets.clear(); 00212 facets.clear(); 00213 00214 OrientedBoxTreeTool::IntersectSearchWindow search_win; 00215 OrientedBoxTreeTool::IntRegCtxt int_reg_ctxt; 00216 rval = tool.ray_intersect_sets( intersections, sets, facets, root, 1e-6, point.array(), dir.array(), 00217 search_win, int_reg_ctxt, stats ); 00218 } 00219 else 00220 { 00221 rval = 00222 tool.ray_intersect_triangles( intersections, facets, root, 1e-6, point.array(), dir.array(), 0, stats ); 00223 } 00224 if( MB_SUCCESS != rval ) 00225 { 00226 std::cerr << "Rayfire #" << rays << " failed." << std::endl; 00227 return 4; 00228 } 00229 00230 if( !intersections.empty() ) 00231 { 00232 ++xsct; 00233 } 00234 00235 if( randrays.size() < cached && ( !intersections.empty() || !num_xsct || xsct >= num_xsct ) ) 00236 { 00237 randrays.push_back( point ); 00238 randrays.push_back( dir ); 00239 } 00240 } 00241 00242 ttimer = clock() - ttimer; 00243 std::cout << rays << " ray fires done" << std::endl 00244 << gen << " unique rays used" << std::endl 00245 << xsct << " intersecting fires" << std::endl 00246 << (double)ttimer / CLOCKS_PER_SEC << " seconds" << std::endl; 00247 00248 if( do_trv_stats ) 00249 { 00250 std::cout << "Traversal statistics: " << std::endl; 00251 stats->print( std::cout ); 00252 } 00253 00254 return 0; 00255 }