|
|
import bpy |
|
|
import json |
|
|
import math |
|
|
import os |
|
|
|
|
|
object_name = 'Cube' |
|
|
object_to_delete = bpy.data.objects.get(object_name) |
|
|
|
|
|
|
|
|
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): |
|
|
|
|
|
bpy.ops.mesh.primitive_plane_add(size=1, enter_editmode=False, align='WORLD', location=(0, 0, 0)) |
|
|
|
|
|
|
|
|
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') |
|
|
|
|
|
|
|
|
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: |
|
|
|
|
|
if obj.parent is None: |
|
|
highest_parent_objects.append(obj) |
|
|
return highest_parent_objects |
|
|
|
|
|
def delete_empty_objects(): |
|
|
|
|
|
for obj in bpy.context.scene.objects: |
|
|
|
|
|
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): |
|
|
|
|
|
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': |
|
|
|
|
|
for child in empty_object.children: |
|
|
|
|
|
if child.type == 'MESH': |
|
|
|
|
|
child.select_set(True) |
|
|
bpy.context.view_layer.objects.active = child |
|
|
else: |
|
|
select_meshes_under_empty(child.name) |
|
|
|
|
|
def rescale_object(obj, scale): |
|
|
|
|
|
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"]) |
|
|
object_rotation_z = (item["rotation"]["z_angle"] / 180.0) * math.pi + math.pi |
|
|
|
|
|
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() |
|
|
|
|
|
|
|
|
create_room(4.0, 4.0, 2.5) |