def add_cameras(op, cameras, path_to_images=None, add_image_planes=False, convert_camera_coordinate_system=True, cameras_parent='Cameras', camera_collection_name='Camera Collection', image_planes_parent='Image Planes', image_plane_collection_name='Image Plane Collection', camera_scale=1.0): """ ======== The images are currently only shown in BLENDER RENDER ======== ======== Make sure to enable TEXTURE SHADING in the 3D view to make the images visible ======== :param cameras: :param path_to_images: :param add_image_planes: :param convert_camera_coordinate_system: :param cameras_parent: :param camera_collection_name: :param image_plane_collection_name: :return: """ op.report({'INFO'}, 'Adding Cameras: ...') stop_watch = StopWatch() cameras_parent = add_empty(cameras_parent) cameras_parent.hide_viewport = True cameras_parent.hide_render = True camera_collection = bpy.data.collections.new(camera_collection_name) if add_image_planes: op.report({'INFO'}, 'Adding image planes: True') image_planes_parent = add_empty(image_planes_parent) image_planes_collection = bpy.data.collections.new( image_plane_collection_name) else: op.report({'INFO'}, 'Adding image planes: False') # Adding cameras and image planes: for index, camera in enumerate(cameras): start_time = stop_watch.get_elapsed_time() # camera_name = "Camera %d" % index # original code # Replace the camera name so it matches the image name (without extension) image_file_name_stem = os.path.splitext( os.path.basename(camera.file_name))[0] camera_name = image_file_name_stem + '_cam' bcamera = add_single_camera(op, camera_name, camera) camera_object = add_obj(bcamera, camera_name) matrix_world = compute_camera_matrix_world(camera) camera_object.matrix_world = matrix_world camera_object.scale *= camera_scale set_object_parent(camera_object, cameras_parent, keep_transform=True) camera_collection.objects.link(camera_object) if add_image_planes: path_to_image = os.path.join(path_to_images, os.path.basename(camera.file_name)) if os.path.isfile(path_to_image): op.report({'INFO'}, 'Adding image plane for: ' + str(path_to_image)) # Group image plane and camera: camera_image_plane_pair = bpy.data.collections.new( "Camera Image Plane Pair Collection %s" % image_file_name_stem) camera_image_plane_pair.objects.link(camera_object) image_plane_name = image_file_name_stem + '_image_plane' px, py = camera.get_principal_point() # do not add image planes by default, this is slow ! image_plane_obj = add_camera_image_plane( matrix_world, path_to_image, camera.width, camera.height, camera.get_focal_length(), px=px, py=py, name=image_plane_name, op=op) camera_image_plane_pair.objects.link(image_plane_obj) set_object_parent(image_plane_obj, image_planes_parent, keep_transform=True) image_planes_collection.objects.link(image_plane_obj) end_time = stop_watch.get_elapsed_time() op.report({'INFO'}, 'Duration: ' + str(stop_watch.get_elapsed_time())) op.report({'INFO'}, 'Adding Cameras: Done')
def add_points_as_mesh(op, points, add_points_as_particle_system, mesh_type, point_extent): op.report({'INFO'}, 'Adding Points: ...') stop_watch = StopWatch() name = "Point_Cloud" mesh = bpy.data.meshes.new(name) mesh.update() mesh.validate() point_world_coordinates = [tuple(point.coord) for point in points] mesh.from_pydata(point_world_coordinates, [], []) meshobj = add_obj(mesh, name) if add_points_as_particle_system or add_meshes_at_vertex_positions: op.report({'INFO'}, 'Representing Points in the Point Cloud with Meshes: True') op.report({'INFO'}, 'Mesh Type: ' + str(mesh_type)) # The default size of elements added with # primitive_cube_add, primitive_uv_sphere_add, etc. is (2,2,2) point_scale = point_extent * 0.5 bpy.ops.object.select_all(action='DESELECT') if mesh_type == "PLANE": bpy.ops.mesh.primitive_plane_add(size=point_scale) elif mesh_type == "CUBE": bpy.ops.mesh.primitive_cube_add(size=point_scale) elif mesh_type == "SPHERE": bpy.ops.mesh.primitive_uv_sphere_add(radius=point_scale) else: bpy.ops.mesh.primitive_uv_sphere_add(radius=point_scale) viz_mesh = bpy.context.object if add_points_as_particle_system: material_name = "PointCloudMaterial" material = bpy.data.materials.new(name=material_name) viz_mesh.data.materials.append(material) # enable cycles, otherwise the material has no nodes bpy.context.scene.render.engine = 'CYCLES' material.use_nodes = True node_tree = material.node_tree if 'Material Output' in node_tree.nodes: # is created by default material_output_node = node_tree.nodes['Material Output'] else: material_output_node = node_tree.nodes.new( 'ShaderNodeOutputMaterial') if 'Diffuse BSDF' in node_tree.nodes: # is created by default diffuse_node = node_tree.nodes['Diffuse BSDF'] else: diffuse_node = node_tree.nodes.new("ShaderNodeBsdfDiffuse") node_tree.links.new(diffuse_node.outputs['BSDF'], material_output_node.inputs['Surface']) if 'Image Texture' in node_tree.nodes: image_texture_node = node_tree.nodes['Image Texture'] else: image_texture_node = node_tree.nodes.new("ShaderNodeTexImage") node_tree.links.new(image_texture_node.outputs['Color'], diffuse_node.inputs['Color']) vis_image_height = 1 # To view the texture we set the height of the texture to vis_image_height image = bpy.data.images.new('ParticleColor', len(point_world_coordinates), vis_image_height) # working on a copy of the pixels results in a MASSIVE performance speed local_pixels = list(image.pixels[:]) num_points = len(points) for j in range(vis_image_height): for point_index, point in enumerate(points): column_offset = point_index * 4 # (R,G,B,A) row_offset = j * 4 * num_points color = point.color # Order is R,G,B, opacity local_pixels[row_offset + column_offset] = color[0] / 255.0 local_pixels[row_offset + column_offset + 1] = color[1] / 255.0 local_pixels[row_offset + column_offset + 2] = color[2] / 255.0 # opacity (0 = transparent, 1 = opaque) #local_pixels[row_offset + column_offset + 3] = 1.0 # already set by default image.pixels = local_pixels[:] # Pack the image, otherwise saving and loading will result in a black texture image.pack(as_png=True) image_texture_node.image = image particle_info_node = node_tree.nodes.new('ShaderNodeParticleInfo') divide_node = node_tree.nodes.new('ShaderNodeMath') divide_node.operation = 'DIVIDE' node_tree.links.new(particle_info_node.outputs['Index'], divide_node.inputs[0]) divide_node.inputs[1].default_value = num_points shader_node_combine = node_tree.nodes.new('ShaderNodeCombineXYZ') node_tree.links.new(divide_node.outputs['Value'], shader_node_combine.inputs['X']) node_tree.links.new(shader_node_combine.outputs['Vector'], image_texture_node.inputs['Vector']) if len(meshobj.particle_systems) == 0: meshobj.modifiers.new("particle sys", type='PARTICLE_SYSTEM') particle_sys = meshobj.particle_systems[0] settings = particle_sys.settings settings.type = 'HAIR' settings.use_advanced_hair = True settings.emit_from = 'VERT' settings.count = len(point_world_coordinates) # The final object extent is hair_length * obj.scale settings.hair_length = 100 # This must not be 0 settings.use_emit_random = False settings.render_type = 'OBJECT' settings.instance_object = viz_mesh bpy.context.scene.update else: op.report({'INFO'}, 'Representing Points in the Point Cloud with Meshes: False') op.report({'INFO'}, 'Duration: ' + str(stop_watch.get_elapsed_time())) op.report({'INFO'}, 'Adding Points: Done')
def add_cameras(op, cameras, parent_collection, path_to_images=None, add_background_images=False, add_image_planes=False, convert_camera_coordinate_system=True, camera_collection_name='Cameras', image_plane_collection_name='Image Planes', camera_scale=1.0, image_plane_transparency=0.5, add_image_plane_emission=True): """ ======== The images are currently only shown in BLENDER RENDER ======== ======== Make sure to enable TEXTURE SHADING in the 3D view to make the images visible ======== :param cameras: :param path_to_images: :param add_image_planes: :param convert_camera_coordinate_system: :param camera_collection_name: :param image_plane_collection_name: :return: """ op.report({'INFO'}, 'Adding Cameras: ...') stop_watch = StopWatch() camera_collection = add_collection(camera_collection_name, parent_collection) if add_image_planes: op.report({'INFO'}, 'Adding image planes: True') image_planes_collection = add_collection(image_plane_collection_name, parent_collection) camera_image_plane_pair_collection = add_collection( "Camera Image Plane Pair Collection", parent_collection) else: op.report({'INFO'}, 'Adding image planes: False') # Adding cameras and image planes: for index, camera in enumerate(cameras): # camera_name = "Camera %d" % index # original code # Replace the camera name so it matches the image name (without extension) image_file_name_stem = os.path.splitext( os.path.basename(camera.file_name))[0] camera_name = image_file_name_stem + '_cam' bcamera = add_single_camera(op, camera_name, camera) camera_object = add_obj(bcamera, camera_name, camera_collection) matrix_world = compute_camera_matrix_world(camera) camera_object.matrix_world = matrix_world camera_object.scale *= camera_scale if not add_image_planes and not add_background_images: continue path_to_image = os.path.join(path_to_images, os.path.basename(camera.file_name)) if not os.path.isfile(path_to_image): continue blender_image = bpy.data.images.load(path_to_image) if add_background_images: # op.report({'INFO'}, 'Adding background image for: ' + camera_name) camera_data = bpy.data.objects[camera_name].data camera_data.show_background_images = True background_image = camera_data.background_images.new() background_image.image = blender_image if add_image_planes and not camera.is_panoramic(): # op.report({'INFO'}, 'Adding image plane for: ' + camera_name) # Group image plane and camera: camera_image_plane_pair_collection_current = add_collection( "Camera Image Plane Pair Collection %s" % image_file_name_stem, camera_image_plane_pair_collection) image_plane_name = image_file_name_stem + '_image_plane' px, py = camera.get_principal_point() # do not add image planes by default, this is slow ! image_plane_obj = add_camera_image_plane( matrix_world, blender_image, camera.width, camera.height, camera.get_focal_length(), px=px, py=py, name=image_plane_name, transparency=image_plane_transparency, add_image_plane_emission=add_image_plane_emission, image_planes_collection=image_planes_collection, op=op) camera_image_plane_pair_collection_current.objects.link( camera_object) camera_image_plane_pair_collection_current.objects.link( image_plane_obj) op.report({'INFO'}, 'Duration: ' + str(stop_watch.get_elapsed_time())) op.report({'INFO'}, 'Adding Cameras: Done')