Example #1
0
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')
Example #2
0
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')
Example #3
0
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')