Skip to content

Commit be39fd8

Browse files
Joschukadbierek
andauthored
ZGateEntity, ZRoomEntity, ZAIAreaEntity support (#78)
Co-authored-by: Danny Bierek <dannybierek@gmail.com>
1 parent 54a2096 commit be39fd8

1 file changed

Lines changed: 94 additions & 4 deletions

File tree

src/resource/glacier2obj.py

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

22562341
def 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

Comments
 (0)