@@ -1352,6 +1352,7 @@ def load_prim(filepath, lod_mask):
13521352 continue
13531353 mesh = load_prim_mesh (prim , prim_name , mesh_index )
13541354 obj = bpy .data .objects .new (mesh .name , mesh )
1355+ bpy .context .scene .collection .objects .link (obj )
13551356 objects .append (obj )
13561357
13571358 return objects
@@ -2252,6 +2253,90 @@ def get_bounding_sphere_data(obj, ws_mat, lsbbox_center = None):
22522253 radius = max ((mathutils .Vector (ws_mat @ mathutils .Vector (ls_corner )) - wsbbox_center ).xy for ls_corner in obj .bound_box )
22532254 return wsbbox_center , radius .length
22542255
2256+ def create_volume (name , col_name , pos , rot , scale , shape = 'CUBE' ):
2257+ o = bpy .data .objects .new (name , None )
2258+ bpy .data .collections .get (col_name ).objects .link ( o )
2259+ o .empty_display_type = shape
2260+ o .empty_display_size = 0.5
2261+ o .location = pos
2262+ o .rotation_mode = "QUATERNION"
2263+ o .rotation_quaternion = rot
2264+ o .scale = scale
2265+ o .show_name = True #Good idea to show names? Or makes viewport too busy?
2266+
2267+ def load_volume_boxes (json_data , volume_types ):
2268+ volume_boxes_coll = bpy .data .collections .new ("Volume boxes" )
2269+ bpy .context .scene .collection .children .link (volume_boxes_coll )
2270+ for volt in volume_types :
2271+ if volt not in json_data :
2272+ continue
2273+ if volt == "gates" :
2274+ if volt not in bpy .data .collections :
2275+ gates_coll = bpy .data .collections .new (volt )
2276+ volume_boxes_coll .children .link (gates_coll )
2277+ else :
2278+ gates_coll = bpy .data .collections .get (volt )
2279+ for vol in json_data [volt ]:
2280+ coords = ["w" ,"x" ,"y" ,"z" ]
2281+ pos , rot , scale , center = [
2282+ mathutils .Vector ([vol ["position" ][coord ] for coord in coords [1 :]]),
2283+ mathutils .Quaternion ([vol ["rotation" ][coord ] for coord in coords ]),
2284+ mathutils .Vector ([vol ["bboxHalfSize" ][coord ] for coord in coords [1 :]]) * 2 ,
2285+ mathutils .Vector ([vol ["bboxCenter" ][coord ] for coord in coords [1 :]])
2286+ ]
2287+ pos += center
2288+ create_volume (vol ["name" ], gates_coll .name , pos , rot , scale )
2289+ elif volt == "rooms" :
2290+ if volt not in bpy .data .collections :
2291+ rooms_coll = bpy .data .collections .new (volt )
2292+ volume_boxes_coll .children .link (rooms_coll )
2293+ else :
2294+ rooms_coll = bpy .data .collections .get (volt )
2295+ for vol in json_data [volt ]:
2296+ coords = ["w" ,"x" ,"y" ,"z" ]
2297+ pos , rot = [
2298+ mathutils .Vector ([vol ["position" ][coord ] for coord in coords [1 :]]),
2299+ mathutils .Quaternion ([vol ["rotation" ][coord ] for coord in coords ]),
2300+ ]
2301+ scale = mathutils .Vector ([vol ["roomExtentMax" ]["data" ][coord ] for coord in coords [1 :]]) - mathutils .Vector ([vol ["roomExtentMin" ]["data" ][coord ] for coord in coords [1 :]])
2302+ center = (mathutils .Vector ([vol ["roomExtentMax" ]["data" ][coord ] for coord in coords [1 :]]) + mathutils .Vector ([vol ["roomExtentMin" ]["data" ][coord ] for coord in coords [1 :]]))/ 2
2303+ pos += center
2304+ create_volume (vol ["name" ], rooms_coll .name , pos , rot , scale )
2305+ elif volt == "aiArea" :
2306+ for ai_area_world in json_data ["aiAreaWorld" ]:
2307+ area_world_coll = bpy .data .collections .new (ai_area_world ["name" ])
2308+ volume_boxes_coll .children .link (area_world_coll )
2309+ #Go through the volumes and prepare the hashmap
2310+ id_to_trigger_volume = {}
2311+ for trig_vol in json_data ["volumeBoxes" ]:
2312+ id_to_trigger_volume [trig_vol ["id" ]] = trig_vol
2313+ for trig_vol in json_data ["volumeSpheres" ]:
2314+ id_to_trigger_volume [trig_vol ["id" ]] = trig_vol
2315+ for ai_area in json_data [volt ]:
2316+ area_coll = bpy .data .collections .new (ai_area ["name" ])
2317+ prev_coll = area_coll
2318+ for parent_coll_name in ai_area ["logicalParent" ]:
2319+ parent_coll_name = parent_coll_name .split ("(" )[0 ][:- 1 ]
2320+ parent_coll = bpy .data .collections .get (parent_coll_name )
2321+ if parent_coll is None :
2322+ parent_coll = bpy .data .collections .new (parent_coll_name )
2323+ if prev_coll .name not in parent_coll .children :
2324+ parent_coll .children .link (prev_coll )
2325+ prev_coll = parent_coll
2326+ for vol_name in ai_area ['areaVolumeNames' ]:
2327+ id = vol_name .split ("(" )[1 ].split (")" )[0 ] # name ex: VolumeBox_AIArea_02 (729b0d862bef84a2)
2328+ trig_vol = id_to_trigger_volume [id ]
2329+ coords = ["w" ,"x" ,"y" ,"z" ]
2330+ pos , rot = [
2331+ mathutils .Vector ([trig_vol ["position" ][coord ] for coord in coords [1 :]]),
2332+ mathutils .Quaternion ([trig_vol ["rotation" ][coord ] for coord in coords ])
2333+ ]
2334+ if "radius" in trig_vol : #sphere volume
2335+ scale = mathutils .Vector ([trig_vol ["radius" ]["data" ] for _ in range (3 )])
2336+ create_volume (vol_name , area_coll .name , pos , rot , scale , 'SPHERE' )
2337+ else : #box volume
2338+ scale = mathutils .Vector ([trig_vol ["scale" ]["data" ][coord ] for coord in coords [1 :]])
2339+ create_volume (vol_name , area_coll .name , pos , rot , scale )
22552340
22562341def load_scenario (path_to_nav_json , path_to_output_obj_file , mesh_type , lod_mask , build_type , filter_to_include_box ):
22572342 start = timer ()
@@ -2265,6 +2350,8 @@ def load_scenario(path_to_nav_json, path_to_output_obj_file, mesh_type, lod_mask
22652350 room_color_index = 0
22662351 room_folder_color_index = 0
22672352
2353+ load_volume_boxes (data , ["gates" , "rooms" , "aiArea" ])
2354+
22682355 #Get the "pathfinding include" box
22692356 pf_include_box_info = None
22702357 pf_box_bounding_sphere_center = None
@@ -2309,7 +2396,7 @@ def load_scenario(path_to_nav_json, path_to_output_obj_file, mesh_type, lod_mask
23092396 else :
23102397 mesh_hash = hash_and_entity ['primHash' ]
23112398
2312- room_folder_name = hash_and_entity ["roomFolderName" ][:63 ]
2399+ room_folder_name = hash_and_entity ["roomFolderName" ][:63 ] if hash_and_entity [ "roomFolderName" ] else "Default"
23132400 if room_folder_name not in bpy .data .collections :
23142401 coll = bpy .data .collections .new (room_folder_name )
23152402 bpy .context .scene .collection .children .link (coll )
@@ -2319,7 +2406,7 @@ def load_scenario(path_to_nav_json, path_to_output_obj_file, mesh_type, lod_mask
23192406
23202407 room_folder_coll = bpy .data .collections .get (room_folder_name )
23212408
2322- room_name = hash_and_entity ["roomName" ][:63 ]
2409+ room_name = hash_and_entity ["roomName" ][:63 ] if hash_and_entity [ "roomName" ] else "Default"
23232410 if room_name not in bpy .data .collections :
23242411 coll = bpy .data .collections .new (room_name )
23252412 room_folder_coll .children .link (coll )
@@ -2481,18 +2568,21 @@ def load_scenario(path_to_nav_json, path_to_output_obj_file, mesh_type, lod_mask
24812568 positions .append ([aloc_positions [u ] for u in range (t_size ) if u not in culled_indices ])
24822569 rotations .append ([aloc_rotations [u ] for u in range (t_size ) if u not in culled_indices ])
24832570 scales .append ([aloc_scales [u ] for u in range (t_size ) if u not in culled_indices ])
2571+ unlinked = [False for _ in range (o_size )]
24842572 for i in range (t_size ):
24852573 room_name = room_names [mesh_hash ][i ]
24862574 mesh_id = transforms [mesh_hash ][i ]["id" ]
24872575 log ("INFO" , "Transforming " + mesh_type + " [" + str (current_mesh_in_scene_index ) + "/" + str (meshes_in_scenario_count ) + "]: " + mesh_hash + " #" + str (i ) + " Mesh: [" + str (mesh_i + 1 ) + "/" + str (mesh_count ) + "] Room name: " + room_name , "load_scenario" )
24882576 mesh_i += 1
24892577 for o_i in range (o_size ):
2578+ obj = objects [o_i ]
2579+ if not unlinked [o_i ]:
2580+ bpy .context .scene .collection .objects .unlink (obj )
2581+ unlinked [o_i ] = True
24902582 if i >= len (positions [o_i ]):
24912583 continue
2492- obj = objects [o_i ]
24932584 if cur is None :
24942585 cur = obj
2495- bpy .context .scene .collection .objects .unlink (obj )
24962586 else :
24972587 cur = obj .copy ()
24982588 bpy .data .collections .get (room_name ).objects .link (cur )
0 commit comments