Paste Code
Paste Blends
Paste Images
bl_info={"name": "Create Camera Image Plane", "author": "Torbjörn Westerlund", "category":"Object" }

import bpy
from bpy_extras.image_utils import load_image
from mathutils import Vector, Euler
import math

class CreateCameraImagePlane(bpy.types.Operator):
"""Create image plane for camera"""
bl_idname= "object.createcameraimageplane"
bl_label="Camera Image Plane"
bl_options={'REGISTER', 'UNDO'}
def SetupDriverVariables(self, driver, imageplane):
camAngle = driver.variables.new()
camAngle.name = 'camAngle'
camAngle.type = 'SINGLE_PROP'
camAngle.targets[0].id = imageplane.parent
camAngle.targets[0].data_path="data.angle"

depth = driver.variables.new()
depth.name = 'depth'
depth.type = 'TRANSFORMS'
depth.targets[0].id = imageplane
depth.targets[0].data_path = 'location'
depth.targets[0].transform_type = 'LOC_Z'
depth.targets[0].transform_space = 'LOCAL_SPACE'

#unfortunately not possible to add driver on scene object
# resolution_x = driver.variables.new()
# resolution_x.name = 'resolution_x'
# resolution_x.type = 'SINGLE_PROP'
# resolution_x.targets[0].id =bpy.context.scene
# resolution_x.targets[0].data_path = 'render.resolution_x'
# resolution_y = driver.variables.new()
# resolution_y.name = 'resolution_y'
# resolution_y.type = 'SINGLE_PROP'
# resolution_y.targets[0].id =bpy.context.scene
# resolution_y.targets[0].data_path = 'render.resolution_y'
# pixel_x = driver.variables.new()
# pixel_x.name = 'pixel_x'
# pixel_x.type = 'SINGLE_PROP'
# pixel_x.targets[0].id =bpy.context.scene
# pixel_x.targets[0].data_path = 'render.pixel_aspect_x'
# pixel_y = driver.variables.new()
# pixel_y.name = 'pixel_y'
# pixel_y.type = 'SINGLE_PROP'
# pixel_y.targets[0].id =bpy.context.scene
# pixel_y.targets[0].data_path = 'render.pixel_aspect_y'


def SetupDriversForImagePlane(self, imageplane):
driver = imageplane.driver_add('scale',1).driver
driver.type = 'SCRIPTED'
self.SetupDriverVariables( driver, imageplane)
#driver.expression ="-depth*math.tan(camAngle/2)*resolution_y*pixel_y/(resolution_x*pixel_x)"
driver.expression ="-depth*tan(camAngle/2)*bpy.context.scene.render.resolution_y * bpy.context.scene.render.pixel_aspect_y/(bpy.context.scene.render.resolution_x * bpy.context.scene.render.pixel_aspect_x)"
driver = imageplane.driver_add('scale',0).driver
driver.type= 'SCRIPTED'
self.SetupDriverVariables( driver, imageplane)
driver.expression ="-depth*tan(camAngle/2)"

# get selected camera (might traverse children of selected object until a camera is found?)
# for now just pick the active object
def createImagePlaneForCamera(self, camera):
imageplane = None
try:
depth = 10


#create imageplane
bpy.ops.mesh.primitive_plane_add()#radius = 0.5)
imageplane = bpy.context.active_object
imageplane.name = "imageplane"
bpy.ops.object.parent_set(type='OBJECT', keep_transform=False)
bpy.ops.object.editmode_toggle()
bpy.ops.mesh.select_all(action='TOGGLE')
bpy.ops.transform.resize( value=(0.5,0.5,0.5))
bpy.ops.uv.smart_project(angle_limit=66,island_margin=0, user_area_weight=0)
bpy.ops.uv.select_all(action='TOGGLE')
bpy.ops.transform.rotate(value=1.5708, axis=(0,0,1) )
bpy.ops.object.editmode_toggle()


imageplane.location = (0,0,-depth)
imageplane.parent = camera


#calculate scale
#REPLACED WITH CREATING EXPRESSIONS
self.SetupDriversForImagePlane(imageplane)

#setup material
if( len( imageplane.material_slots) == 0 ):
bpy.ops.object.material_slot_add()
#imageplane.material_slots.
bpy.ops.material.new()
mat_index = len(bpy.data.materials)-1
imageplane.material_slots[0].material = bpy.data.materials[mat_index]
material = imageplane.material_slots[0].material
# if not returned by new use imgeplane.material_slots[0].material
material.name = 'mat_imageplane_'+camera.name
material.use_nodes = True
nodes = material.node_tree.nodes
links = material.node_tree.links

nodes.clear()
emissive = nodes.new('ShaderNodeEmission')
emissive.location = 0, 0
transparent = nodes.new('ShaderNodeBsdfTransparent')
transparent.location = 0,100
mix = nodes.new('ShaderNodeMixShader')
mix.location = 400,0
links.new( emissive.outputs[0], mix.inputs[2] )
links.new( transparent.outputs[0], mix.inputs[1] )
outnode = nodes.new('ShaderNodeOutputMaterial')
outnode.location = 800,0
links.new( mix.outputs[0], outnode.inputs[0] )
texture = nodes.new('ShaderNodeTexImage')
texture.location = -400,0
links.new( texture.outputs[0], emissive.inputs[0] )
links.new( texture.outputs[1], mix.inputs[0] )
#texture.image = bpy.ops.image.open(filepath="c:\\nova\\keyed\\1\\1_5_1\\1_5_1.00000.png")


except Exception as e:
imageplane.select=False
camera.select = True
raise e
return {'FINISHED'}

def execute(self, context):
camera = bpy.context.active_object #bpy.data.objects['Camera']
return self.createImagePlaneForCamera(camera)


# main
print("========================")
print(" SCRIPT STARTING")
print("========================")

#camera = bpy.context.active_object #bpy.data.objects['Camera']
#createImagePlaneForCamera(camera)


#def register():
# bpy.utils.register_class(CreateCameraImagePlane)
#def unregister():
# bpy.utils.unregister_class(CreateCameraImagePlane)

def menu_func(self, context):
self.layout.operator(CreateCameraImagePlane.bl_idname, icon='FILE_IMAGE')

def register():
bpy.utils.register_class(CreateCameraImagePlane)
bpy.types.INFO_MT_mesh_add.append(menu_func)

def unregister():
bpy.utils.unregister_class(CreateCameraImagePlane)
bpy.types.INFO_MT_mesh_add.remove(menu_func)



# This allows you to run the script directly from blenders text editor
# to test the addon without having to install it.
if __name__ == "__main__":
register()
  1. bl_info={"name": "Create Camera Image Plane", "author": "Torbjörn Westerlund", "category":"Object" }
  2.  
  3. import bpy
  4. from bpy_extras.image_utils import load_image
  5. from mathutils import Vector, Euler
  6. import math
  7.  
  8. class CreateCameraImagePlane(bpy.types.Operator):
  9.     """Create image plane for camera"""
  10.     bl_idname= "object.createcameraimageplane"
  11.     bl_label="Camera Image Plane"
  12.     bl_options={'REGISTER', 'UNDO'}
  13.     def SetupDriverVariables(self, driver, imageplane):
  14.         camAngle = driver.variables.new()
  15.         camAngle.name = 'camAngle'
  16.         camAngle.type = 'SINGLE_PROP'
  17.         camAngle.targets[0].id = imageplane.parent
  18.         camAngle.targets[0].data_path="data.angle"
  19.        
  20.         depth = driver.variables.new()
  21.         depth.name = 'depth'
  22.         depth.type = 'TRANSFORMS'
  23.         depth.targets[0].id = imageplane    
  24.         depth.targets[0].data_path = 'location'
  25.         depth.targets[0].transform_type = 'LOC_Z'
  26.         depth.targets[0].transform_space = 'LOCAL_SPACE'
  27.    
  28.     #unfortunately not possible to add driver on scene object    
  29.     #    resolution_x = driver.variables.new()
  30.     #    resolution_x.name = 'resolution_x'
  31.     #    resolution_x.type = 'SINGLE_PROP'
  32.     #    resolution_x.targets[0].id =bpy.context.scene
  33.     #    resolution_x.targets[0].data_path = 'render.resolution_x'
  34.     #    resolution_y = driver.variables.new()
  35.     #    resolution_y.name = 'resolution_y'
  36.     #    resolution_y.type = 'SINGLE_PROP'
  37.     #    resolution_y.targets[0].id =bpy.context.scene
  38.     #    resolution_y.targets[0].data_path = 'render.resolution_y'
  39.     #    pixel_x = driver.variables.new()
  40.     #    pixel_x.name = 'pixel_x'
  41.     #    pixel_x.type = 'SINGLE_PROP'
  42.     #    pixel_x.targets[0].id =bpy.context.scene
  43.     #    pixel_x.targets[0].data_path = 'render.pixel_aspect_x'
  44.     #    pixel_y = driver.variables.new()
  45.     #    pixel_y.name = 'pixel_y'
  46.     #    pixel_y.type = 'SINGLE_PROP'
  47.     #    pixel_y.targets[0].id =bpy.context.scene
  48.     #    pixel_y.targets[0].data_path = 'render.pixel_aspect_y'
  49.                
  50.    
  51.     def SetupDriversForImagePlane(self, imageplane):
  52.         driver = imageplane.driver_add('scale',1).driver
  53.         driver.type = 'SCRIPTED'
  54.         self.SetupDriverVariables( driver, imageplane)
  55.         #driver.expression ="-depth*math.tan(camAngle/2)*resolution_y*pixel_y/(resolution_x*pixel_x)"
  56.         driver.expression ="-depth*tan(camAngle/2)*bpy.context.scene.render.resolution_y * bpy.context.scene.render.pixel_aspect_y/(bpy.context.scene.render.resolution_x * bpy.context.scene.render.pixel_aspect_x)"
  57.         driver = imageplane.driver_add('scale',0).driver
  58.         driver.type= 'SCRIPTED'
  59.         self.SetupDriverVariables( driver, imageplane)
  60.         driver.expression ="-depth*tan(camAngle/2)"
  61.    
  62.     # get selected camera (might traverse children of selected object until a camera is found?)
  63.     # for now just pick the active object
  64.     def createImagePlaneForCamera(self, camera):
  65.         imageplane = None
  66.         try:
  67.             depth = 10
  68.            
  69.            
  70.             #create imageplane
  71.             bpy.ops.mesh.primitive_plane_add()#radius = 0.5)
  72.             imageplane = bpy.context.active_object
  73.             imageplane.name = "imageplane"
  74.             bpy.ops.object.parent_set(type='OBJECT', keep_transform=False)
  75.             bpy.ops.object.editmode_toggle()
  76.             bpy.ops.mesh.select_all(action='TOGGLE')
  77.             bpy.ops.transform.resize( value=(0.5,0.5,0.5))
  78.             bpy.ops.uv.smart_project(angle_limit=66,island_margin=0, user_area_weight=0)
  79.             bpy.ops.uv.select_all(action='TOGGLE')
  80.             bpy.ops.transform.rotate(value=1.5708, axis=(0,0,1) )
  81.             bpy.ops.object.editmode_toggle()
  82.        
  83.            
  84.             imageplane.location = (0,0,-depth)
  85.             imageplane.parent = camera
  86.            
  87.            
  88.             #calculate scale
  89.             #REPLACED WITH CREATING EXPRESSIONS
  90.             self.SetupDriversForImagePlane(imageplane)
  91.    
  92.             #setup material
  93.             if( len( imageplane.material_slots) == 0 ):
  94.                 bpy.ops.object.material_slot_add()
  95.                 #imageplane.material_slots.
  96.             bpy.ops.material.new()
  97.             mat_index = len(bpy.data.materials)-1
  98.             imageplane.material_slots[0].material = bpy.data.materials[mat_index]
  99.             material =  imageplane.material_slots[0].material
  100.             # if not returned by new use imgeplane.material_slots[0].material
  101.             material.name = 'mat_imageplane_'+camera.name
  102.             material.use_nodes = True
  103.             nodes = material.node_tree.nodes
  104.             links = material.node_tree.links
  105.            
  106.             nodes.clear()
  107.             emissive = nodes.new('ShaderNodeEmission')
  108.             emissive.location = 0, 0
  109.             transparent = nodes.new('ShaderNodeBsdfTransparent')
  110.             transparent.location = 0,100
  111.             mix = nodes.new('ShaderNodeMixShader')
  112.             mix.location = 400,0
  113.             links.new( emissive.outputs[0], mix.inputs[2] )
  114.             links.new( transparent.outputs[0], mix.inputs[1] )
  115.             outnode = nodes.new('ShaderNodeOutputMaterial')
  116.             outnode.location = 800,0
  117.             links.new( mix.outputs[0], outnode.inputs[0] )
  118.             texture = nodes.new('ShaderNodeTexImage')
  119.             texture.location = -400,0
  120.             links.new( texture.outputs[0], emissive.inputs[0] )    
  121.             links.new( texture.outputs[1], mix.inputs[0] )
  122.             #texture.image = bpy.ops.image.open(filepath="c:\\nova\\keyed\\1\\1_5_1\\1_5_1.00000.png")
  123.    
  124.        
  125.         except Exception as e:
  126.             imageplane.select=False
  127.             camera.select = True
  128.             raise e    
  129.         return {'FINISHED'}
  130.    
  131.     def execute(self, context):
  132.         camera = bpy.context.active_object #bpy.data.objects['Camera']
  133.         return self.createImagePlaneForCamera(camera)
  134.  
  135.  
  136. # main
  137. print("========================")
  138. print("   SCRIPT STARTING")
  139. print("========================")
  140.  
  141. #camera = bpy.context.active_object #bpy.data.objects['Camera']
  142. #createImagePlaneForCamera(camera)
  143.  
  144.  
  145. #def register():
  146. #    bpy.utils.register_class(CreateCameraImagePlane)
  147. #def unregister():
  148. #    bpy.utils.unregister_class(CreateCameraImagePlane)
  149.  
  150. def menu_func(self, context):
  151.     self.layout.operator(CreateCameraImagePlane.bl_idname, icon='FILE_IMAGE')
  152.  
  153. def register():
  154.     bpy.utils.register_class(CreateCameraImagePlane)
  155.     bpy.types.INFO_MT_mesh_add.append(menu_func)
  156.  
  157. def unregister():
  158.     bpy.utils.unregister_class(CreateCameraImagePlane)
  159.     bpy.types.INFO_MT_mesh_add.remove(menu_func)       
  160.  
  161.  
  162.  
  163. # This allows you to run the script directly from blenders text editor
  164. # to test the addon without having to install it.
  165. if __name__ == "__main__":
  166.     register()
  167.  
go to heaven