import bpy import json import math import os object_name = 'Cube' object_to_delete = bpy.data.objects.get(object_name) # Check if the object exists before trying to delete it if object_to_delete is not None: bpy.data.objects.remove(object_to_delete, do_unlink=True) def import_glb(file_path, object_name): bpy.ops.import_scene.gltf(filepath=file_path) imported_object = bpy.context.view_layer.objects.active if imported_object is not None: imported_object.name = object_name def import_fbx(file_path, object_name): bpy.ops.import_scene.fbx(filepath=file_path) for obj in bpy.context.selected_objects: obj.name = object_name def create_room(width, depth, height): # Create floor bpy.ops.mesh.primitive_plane_add(size=1, enter_editmode=False, align='WORLD', location=(0, 0, 0)) # Extrude to create walls bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value":(0, 0, height)}) bpy.ops.object.mode_set(mode='OBJECT') # Scale the walls to the desired dimensions bpy.ops.transform.resize(value=(width, depth, 1)) bpy.context.active_object.location.x += width / 2 bpy.context.active_object.location.y += depth / 2 def find_files(directory, extensions): files = {} for root, dirs, filenames in os.walk(directory): for filename in filenames: if filename.endswith(extensions): key = filename.split(".")[0] if key not in files: files[key] = os.path.join(root, filename) return files def get_highest_parent_objects(): highest_parent_objects = [] for obj in bpy.data.objects: # Check if the object has no parent if obj.parent is None: highest_parent_objects.append(obj) return highest_parent_objects def delete_empty_objects(): # Iterate through all objects in the scene for obj in bpy.context.scene.objects: # Check if the object is empty (has no geometry) print(obj.name, obj.type) if obj.type == 'EMPTY': bpy.context.view_layer.objects.active = obj bpy.data.objects.remove(obj) def select_meshes_under_empty(empty_object_name): # Get the empty object empty_object = bpy.data.objects.get(empty_object_name) print(empty_object is not None) if empty_object is not None and empty_object.type == 'EMPTY': # Iterate through the children of the empty object for child in empty_object.children: # Check if the child is a mesh if child.type == 'MESH': # Select the mesh child.select_set(True) bpy.context.view_layer.objects.active = child else: select_meshes_under_empty(child.name) def rescale_object(obj, scale): # Ensure the object has a mesh data if obj.type == 'MESH': bbox_dimensions = obj.dimensions scale_factors = ( scale["length"] / bbox_dimensions.x, scale["width"] / bbox_dimensions.y, scale["height"] / bbox_dimensions.z ) obj.scale = scale_factors objects_in_room = {} file_path = "scene_graph.json" with open(file_path, 'r') as file: data = json.load(file) for item in data: if item["new_object_id"] not in ["south_wall", "north_wall", "east_wall", "west_wall", "middle of the room", "ceiling"]: objects_in_room[item["new_object_id"]] = item directory_path = os.path.join(os.getcwd(), "Assets") fbx_files = find_files(directory_path, ".fbx") glb_files = find_files(directory_path, ".glb") for item_id, object_in_room in objects_in_room.items(): if item_id in fbx_files: fbx_file_path = fbx_files[item_id] import_fbx(fbx_file_path, item_id) for item_id, object_in_room in objects_in_room.items(): if item_id in glb_files: glb_file_path = glb_files[item_id] import_glb(glb_file_path, item_id) parents = get_highest_parent_objects() empty_parents = [parent for parent in parents if parent.type == "EMPTY"] print(empty_parents) for empty_parent in empty_parents: bpy.ops.object.select_all(action='DESELECT') select_meshes_under_empty(empty_parent.name) bpy.ops.object.join() bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='BOUNDS') joined_object = bpy.context.view_layer.objects.active if joined_object is not None: joined_object.name = empty_parent.name + "-joined" bpy.context.view_layer.objects.active = None MSH_OBJS = [m for m in bpy.context.scene.objects if m.type == 'MESH'] for OBJS in MSH_OBJS: bpy.context.view_layer.objects.active = OBJS bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM') OBJS.location = (0.0, 0.0, 0.0) bpy.context.view_layer.objects.active = OBJS OBJS.select_set(True) bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='BOUNDS') MSH_OBJS = [m for m in bpy.context.scene.objects if m.type == 'MESH'] for OBJS in MSH_OBJS: item = objects_in_room[OBJS.name.split("-")[0]] object_position = (item["position"]["x"], item["position"]["y"], item["position"]["z"]) # X, Y, and Z coordinates object_rotation_z = (item["rotation"]["z_angle"] / 180.0) * math.pi + math.pi # Rotation angles in radians around the X, Y, and Z axes bpy.ops.object.select_all(action='DESELECT') OBJS.select_set(True) OBJS.location = object_position bpy.ops.transform.rotate(value=object_rotation_z, orient_axis='Z') rescale_object(OBJS, item["size_in_meters"]) bpy.ops.object.select_all(action='DESELECT') delete_empty_objects() # TODO: Generate the room with the room dimensions create_room(4.0, 4.0, 2.5)