[AddOn]Locked of Camera Placer (possibly usable with pans)

This script takes user inputed data and placer a camera exactly the same 3D location and rotation as was used on set. When shooting, find a base line in the shot and measure the length . Then measure the distance from either end to the camera. Also measure the following: the camera hight (relative to the base line), the dutch and tilt and how far the centre of the shot is along the base line.


# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
 
import bpy, math
class CameraPanel(bpy.types.Panel):     
    bl_label = "Camera Setup"    
    bl_space_type = "PROPERTIES"    
    bl_region_type = "WINDOW"    
    bl_context = "render"      
    def draw(self, context):         
        layout = self.layout           
        scn = bpy.context.scene         
        row = layout.row()         
        col = row.column()    
        col.label(text="Camera Placement Data:")     
        col.prop( scn, "base_line" )
        col.prop( scn, "camera_centre" )
        col.prop( scn, "camera_left" )
        col.prop( scn, "camera_right" )
        col.prop( scn, "camera_height" )
        col.prop( scn, "camera_dutch" )
        col.prop( scn, "camera_tilt" )
        row = layout.row()         
        col.operator( "camera.placer_op" ) 
        col.label(text="General Camera Data:")
        col.prop( scn, "focal_length" )
        col.prop( scn, "focus_distance" )
        col.prop( scn, "f_stop" )
        col.operator( "camera.general_settings" )
 
class CameraPlacer(bpy.types.Operator):
    bl_idname = "camera.placer_op"
    bl_label = "Place Camera"
 
    def execute(self, context):
 
        #Convert user inputs to float (not string)
        Base_line = bpy.context.scene.base_line
        Base_line = float(Base_line)
        Camera_centre = bpy.context.scene.camera_centre
        Camera_centre = float(Camera_centre)
 
        Camera_left = bpy.context.scene.camera_left
        Camera_left = float(Camera_left)
 
        Camera_right = bpy.context.scene.camera_right
        Camera_right = float(Camera_right)
 
        Camera_height = bpy.context.scene.camera_height
        Camera_height = float(Camera_height)
 
        Camera_dutch = bpy.context.scene.camera_dutch
        Camera_dutch = float(Camera_dutch)
 
        Camera_tilt = bpy.context.scene.camera_tilt
        Camera_tilt = float(Camera_tilt) 
        #Work out left angle
        Angle_left = (Base_line**2 + Camera_left**2 - Camera_right**2) / (2 * Base_line * Camera_left)
        Angle_left = math.acos(Angle_left)
        #Find cordinates
        Stantion_point_x = (Camera_left) * math.cos(Angle_left)
 
        Stantion_point_y = (Camera_left) * math.sin(Angle_left)
 
        #Work out tilt and dutch
        Final_tilt = 90 + Camera_tilt
        Final_tilt = math.radians(Final_tilt)
 
        Final_dutch = math.radians(Camera_dutch)
 
        # Work out Z rotation
        #calculate CC to SP
        Angle_left = (Base_line**2 + Camera_left**2 - Camera_right**2) / (2 * Base_line * Camera_left)
        d = (Camera_centre**2 + Camera_left**2 - 2 * Camera_centre * Camera_left * Angle_left)        
        CC_to_SP = math.sqrt(d)
 
        #Stantion_point_x-CC
        x = Stantion_point_x-Camera_centre
 
        #Z_rotation
        Z_rotation = math.acos((Stantion_point_y**2 + CC_to_SP**2 - x**2) / (2 * Stantion_point_y * CC_to_SP))
        if Camera_centre > (Base_line / 2):
            Z_rotation = 180 - (math.degrees(Z_rotation))
            Z_rotation = -(math.radians(Z_rotation))
        else:
            Z_rotation = 180 - (math.degrees(Z_rotation))
            Z_rotation = math.radians(Z_rotation)          
 
        bpy.ops.object.add(type='EMPTY', location=(Base_line, 0, 0))
        bpy.data.objects['Empty'].name = "Base_left"
        bpy.ops.object.add(type='EMPTY', location=(Camera_centre, 0, 0))
        bpy.data.objects['Empty'].name = "Camera_centre"
        bpy.ops.object.add(type='CAMERA', location=(Stantion_point_x, Stantion_point_y, Camera_height), rotation=(Final_tilt, Final_dutch, Z_rotation))
        bpy.ops.object.add(type='EMPTY', location=(0, 0, 0))
        bpy.data.objects['Empty'].name = "Base_right"
 
        #Parent to Camera_right
        bpy.ops.object.select_all(action='TOGGLE')
        bpy.data.objects['Camera'].select = True
        bpy.data.objects['Base_left'].select = True 
        bpy.data.objects['Camera_centre'].select = True
        bpy.data.objects['Base_right'].select = True
        bpy.ops.object.parent_set(type='OBJECT')
        bpy.ops.object.select_all(action='TOGGLE')
 
        return {'FINISHED'}
 
class CameraSettings(bpy.types.Operator):
    bl_idname = "camera.general_settings"
    bl_label = "Update Settings"
 
    def execute(self, context):
         bpy.data.cameras['Camera'].lens = bpy.context.scene.focal_length
         bpy.data.cameras['Camera'].dof_distance = bpy.context.scene.focus_distance
         bpy.data.cameras['Camera'].show_limits = True
 
         return {'FINISHED'}
 
def register():         
    bpy.utils.register_class( CameraPanel )
    bpy.utils.register_class( CameraPlacer ) 
    bpy.utils.register_class( CameraSettings ) 
 
def unregister():        
    bpy.utils.register_class( CameraPanel )
    bpy.utils.register_class( CameraPlacer )
    bpy.utils.register_class( CameraSettings ) 
 
if __name__ == '__main__':     
    bpy.types.Scene.base_line = bpy.props.FloatProperty( name = "Base Line", default = 0, min = 0, precision = 5, description = "Length of Base line") 
    bpy.types.Scene.camera_centre = bpy.props.FloatProperty( name = "Camera Centre", default = 0, min = 0, precision = 5, description = "Distance from base line right to centre of the camera")
    bpy.types.Scene.camera_left = bpy.props.FloatProperty(  name="Camera Left", default = 0, min = 0, precision = 5, description = "Length of camera left side")
    bpy.types.Scene.camera_right = bpy.props.FloatProperty(  name="Camera Right", default = 0, min = 0, precision = 5, description = "Length of camera right side")
    bpy.types.Scene.camera_height = bpy.props.FloatProperty(  name="Camera Height", default = 0, precision = 5, description = "Height of camera oabove the base line")
    bpy.types.Scene.camera_dutch = bpy.props.FloatProperty(  name="Camera Dutch", default = 0, precision = 5, description = "Camera Dutch. Positive=right, negative=left")
    bpy.types.Scene.camera_tilt = bpy.props.FloatProperty(  name="Camera Tilt", default = 0, precision = 5, description = "Camera Tilt. Positive=lens up, negative=lens down")
    bpy.types.Scene.focal_length = bpy.props.FloatProperty( name="Focal Length", default = 35, precision = 3, description = "Perspective Camera lens value in Millimetres" )
    bpy.types.Scene.focus_distance = bpy.props.FloatProperty( name="Focus Distance", default = 0, precision = 3, description = "Distance to object in Focus" )
    bpy.types.Scene.f_stop = bpy.props.FloatProperty( name="F. Stop", default = 5.6, precision = 3, description = "F. Stop value of the camera" )
 
    register() 

This script should be useful for matching locked of shots and possibly pans (with some work) to CGI. Sorry if that’s a bad explination, if you have any questions I’ll try to explain it better. It is based on the method used in the VES Handbook.

Thanks
Tom

Here’s a quick update:


# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
bl_info = {
    'name': 'VFX Camera',
    'author': 'Thomas Wilshaw',
    "blender": (2, 6, 1),
    'location': 'Properties > Render > Camera Setup',
    'description': 'Allows camera setup and placement',
    'warning': '', # used for warning icon and text in addons panel
    'category': '3D View '}
 
import bpy, math
class CameraPanel(bpy.types.Panel):     
    bl_label = "VFX Camera Setup"    
    bl_space_type = "PROPERTIES"    
    bl_region_type = "WINDOW"    
    bl_context = "render"      
    def draw(self, context):         
        layout = self.layout           
        scn = bpy.context.scene         
        row = layout.row()         
        col = row.column()
        col.label(text="General Camera Data:")
        col.prop( scn, "camera_name" )
        col.prop( scn, "focal_length" )
        col.prop( scn, "focus_distance" )
        col.prop( scn, "f_stop" )
        col.operator( "camera.general_settings" )    
        col.label(text="Camera Placement Data:")     
        col.prop( scn, "base_line" )
        col.prop( scn, "camera_centre" )
        col.prop( scn, "camera_left" )
        col.prop( scn, "camera_right" )
        col.prop( scn, "camera_height" )
        col.prop( scn, "camera_dutch" )
        col.prop( scn, "camera_tilt" )
        row = layout.row()         
        col.operator( "camera.placer_op" ) 
 
 
class CameraPlacer(bpy.types.Operator):
    bl_idname = "camera.placer_op"
    bl_label = "Place Camera"
 
    def execute(self, context):
 
        #Convert user inputs to float (not string)
        Base_line = bpy.context.scene.base_line
        Base_line = float(Base_line)
        Camera_centre = bpy.context.scene.camera_centre
        Camera_centre = float(Camera_centre)
 
        Camera_left = bpy.context.scene.camera_left
        Camera_left = float(Camera_left)
 
        Camera_right = bpy.context.scene.camera_right
        Camera_right = float(Camera_right)
 
        Camera_height = bpy.context.scene.camera_height
        Camera_height = float(Camera_height)
 
        Camera_dutch = bpy.context.scene.camera_dutch
        Camera_dutch = float(Camera_dutch)
 
        Camera_tilt = bpy.context.scene.camera_tilt
        Camera_tilt = float(Camera_tilt) 
        #Work out left angle
        Angle_left = (Base_line**2 + Camera_left**2 - Camera_right**2) / (2 * Base_line * Camera_left)
        Angle_left = math.acos(Angle_left)
        #Find cordinates
        Stantion_point_x = (Camera_left) * math.cos(Angle_left)
 
        Stantion_point_y = (Camera_left) * math.sin(Angle_left)
 
        #Work out tilt and dutch
        Final_tilt = 90 + Camera_tilt
        Final_tilt = math.radians(Final_tilt)
 
        Final_dutch = math.radians(Camera_dutch)
 
        # Work out Z rotation
        #calculate CC to SP
        Angle_left = (Base_line**2 + Camera_left**2 - Camera_right**2) / (2 * Base_line * Camera_left)
        d = (Camera_centre**2 + Camera_left**2 - 2 * Camera_centre * Camera_left * Angle_left)        
        CC_to_SP = math.sqrt(d)
 
        #Stantion_point_x-CC
        x = Stantion_point_x-Camera_centre
 
        #Z_rotation
        Z_rotation = math.acos((Stantion_point_y**2 + CC_to_SP**2 - x**2) / (2 * Stantion_point_y * CC_to_SP))
        if Camera_centre > (Base_line / 2):
            Z_rotation = 180 - (math.degrees(Z_rotation))
            Z_rotation = -(math.radians(Z_rotation))
        else:
            Z_rotation = 180 - (math.degrees(Z_rotation))
            Z_rotation = math.radians(Z_rotation)          
 
        #Place Camera
        camera_name = bpy.context.scene.camera_name
        bpy.ops.object.add(type='EMPTY', location=(Base_line, 0, 0))
        bpy.data.objects['Empty'].name = "Base_left"
        bpy.ops.object.add(type='EMPTY', location=(Camera_centre, 0, 0))
        bpy.data.objects['Empty'].name = "Camera_centre"
        bpy.data.objects[camera_name].rotation_euler[0] = Final_tilt
        bpy.data.objects[camera_name].rotation_euler[1] = Final_dutch
        bpy.data.objects[camera_name].rotation_euler[2] = Z_rotation
        bpy.data.objects[camera_name].location[0] = Stantion_point_x
        bpy.data.objects[camera_name].location[1] = Stantion_point_y
        bpy.data.objects[camera_name].location[2] = Camera_height
        bpy.ops.object.add(type='EMPTY', location=(0, 0, 0))
        bpy.data.objects['Empty'].name = "Base_right"
 
        #Parent to Camera_right
        bpy.ops.object.select_all(action='TOGGLE')
        bpy.data.objects[camera_name].select = True
        bpy.data.objects['Base_left'].select = True 
        bpy.data.objects['Camera_centre'].select = True
        bpy.data.objects['Base_right'].select = True
        bpy.ops.object.parent_set(type='OBJECT')
        bpy.ops.object.select_all(action='TOGGLE')
 
        return {'FINISHED'}
 
class CameraSettings(bpy.types.Operator):
    bl_idname = "camera.general_settings"
    bl_label = "Create Camera"
 
    def execute(self, context):
        camera_name = bpy.context.scene.camera_name
        bpy.ops.object.add(type='CAMERA')
        bpy.data.objects['Camera'].name = camera_name
        bpy.data.cameras['Camera'].name = camera_name
        bpy.data.cameras[camera_name].lens = bpy.context.scene.focal_length
        bpy.data.cameras[camera_name].dof_distance = bpy.context.scene.focus_distance
        bpy.data.cameras[camera_name].show_limits = True
 
        return {'FINISHED'}
 
def register():         
    bpy.utils.register_class( CameraPanel )
    bpy.utils.register_class( CameraPlacer ) 
    bpy.utils.register_class( CameraSettings ) 
 
def unregister():        
    bpy.utils.register_class( CameraPanel )
    bpy.utils.register_class( CameraPlacer )
    bpy.utils.register_class( CameraSettings ) 
 
if __name__ == '__main__':     
    bpy.types.Scene.base_line = bpy.props.FloatProperty( name = "Base Line", default = 0, min = 0, precision = 5, description = "Length of Base line") 
    bpy.types.Scene.camera_centre = bpy.props.FloatProperty( name = "Camera Centre", default = 0, min = 0, precision = 5, description = "Distance from base line right to centre of the camera")
    bpy.types.Scene.camera_left = bpy.props.FloatProperty(  name="Camera Left", default = 0, min = 0, precision = 5, description = "Length of camera left side")
    bpy.types.Scene.camera_right = bpy.props.FloatProperty(  name="Camera Right", default = 0, min = 0, precision = 5, description = "Length of camera right side")
    bpy.types.Scene.camera_height = bpy.props.FloatProperty(  name="Camera Height", default = 0, precision = 5, description = "Height of camera oabove the base line")
    bpy.types.Scene.camera_dutch = bpy.props.FloatProperty(  name="Camera Dutch", default = 0, precision = 5, description = "Camera Dutch. Positive=right, negative=left")
    bpy.types.Scene.camera_tilt = bpy.props.FloatProperty(  name="Camera Tilt", default = 0, precision = 5, description = "Camera Tilt. Positive=lens up, negative=lens down")
    bpy.types.Scene.focal_length = bpy.props.FloatProperty( name="Focal Length", default = 35, precision = 3, description = "Perspective Camera lens value in Millimetres" )
    bpy.types.Scene.focus_distance = bpy.props.FloatProperty( name="Focus Distance", default = 0, precision = 3, description = "Distance to object in Focus" )
    bpy.types.Scene.f_stop = bpy.props.FloatProperty( name="F. Stop", default = 5.6, precision = 3, description = "F. Stop value of the camera" )
    bpy.types.Scene.camera_name = bpy.props.StringProperty( name = "Camera Name", description = "Unique name for Camera")
 
    register() 

You now first create your camera with correct settings, and then place it. The camera name must be unique each time you add a new camera.

Here’s a very quick test I did, the measurements weren’t 100% accurate so it doesn’t quite fit, but it’s a good proof of concept. Also it gives a good starting point which you can tweak.



The monkey on the right should be behind the stool, I just forgot the stool was there when I shot it.

To do pans, I think you would set it up for a still and than animate the camera’s Z axis so that the base line matches, however I’ve not testeed this yet.

Thanks
Tom

Just another update, it now includes CCD size. Also a improved test image (i.e. a bit more compositing).

# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
bl_info = {
    'name': 'VFX Camera',
    'author': 'Thomas Wilshaw',
    "blender": (2, 6, 1),
    'location': 'Properties > Render > Camera Setup',
    'description': 'Allows camera setup and placement',
    'warning': '', # used for warning icon and text in addons panel
    'category': '3D View '}
 
import bpy, math
class CameraPanel(bpy.types.Panel):     
    bl_label = "VFX Camera Setup"    
    bl_space_type = "PROPERTIES"    
    bl_region_type = "WINDOW"    
    bl_context = "render"      
    def draw(self, context):         
        layout = self.layout           
        scn = bpy.context.scene         
        row = layout.row()         
        col = row.column()
        col.label(text="General Camera Data:")
        col.prop( scn, "camera_name" )
        col.prop( scn, "focal_length" )
        col.prop( scn, "focus_distance" )
        col.prop( scn, "f_stop" )
        col.prop( scn, "sensor_fit" )
        col.prop( scn, "sensor_width" )
        col.prop( scn, "sensor_height" )
        col.operator( "camera.general_settings" )    
        col.label(text="Camera Placement Data:")     
        col.prop( scn, "base_line" )
        col.prop( scn, "camera_centre" )
        col.prop( scn, "camera_left" )
        col.prop( scn, "camera_right" )
        col.prop( scn, "camera_height" )
        col.prop( scn, "camera_dutch" )
        col.prop( scn, "camera_tilt" )
        row = layout.row()         
        col.operator( "camera.placer_op" ) 
 
 
class CameraPlacer(bpy.types.Operator):
    bl_idname = "camera.placer_op"
    bl_label = "Place Camera"
 
    def execute(self, context):
 
        #Convert user inputs to float (not string)
        Base_line = bpy.context.scene.base_line
        Base_line = float(Base_line)
        Camera_centre = bpy.context.scene.camera_centre
        Camera_centre = float(Camera_centre)
 
        Camera_left = bpy.context.scene.camera_left
        Camera_left = float(Camera_left)
 
        Camera_right = bpy.context.scene.camera_right
        Camera_right = float(Camera_right)
 
        Camera_height = bpy.context.scene.camera_height
        Camera_height = float(Camera_height)
 
        Camera_dutch = bpy.context.scene.camera_dutch
        Camera_dutch = float(Camera_dutch)
 
        Camera_tilt = bpy.context.scene.camera_tilt
        Camera_tilt = float(Camera_tilt) 
        #Work out left angle
        Angle_left = (Base_line**2 + Camera_left**2 - Camera_right**2) / (2 * Base_line * Camera_left)
        Angle_left = math.acos(Angle_left)
        #Find cordinates
        Stantion_point_x = (Camera_left) * math.cos(Angle_left)
 
        Stantion_point_y = (Camera_left) * math.sin(Angle_left)
 
        #Work out tilt and dutch
        Final_tilt = 90 + Camera_tilt
        Final_tilt = math.radians(Final_tilt)
 
        Final_dutch = math.radians(Camera_dutch)
 
        # Work out Z rotation
        #calculate CC to SP
        Angle_left = (Base_line**2 + Camera_left**2 - Camera_right**2) / (2 * Base_line * Camera_left)
        d = (Camera_centre**2 + Camera_left**2 - 2 * Camera_centre * Camera_left * Angle_left)        
        CC_to_SP = math.sqrt(d)
 
        #Stantion_point_x-CC
        x = Stantion_point_x-Camera_centre
 
        #Z_rotation
        Z_rotation = math.acos((Stantion_point_y**2 + CC_to_SP**2 - x**2) / (2 * Stantion_point_y * CC_to_SP))
        if Camera_centre > (Base_line / 2):
            Z_rotation = 180 - (math.degrees(Z_rotation))
            Z_rotation = -(math.radians(Z_rotation))
        else:
            Z_rotation = 180 - (math.degrees(Z_rotation))
            Z_rotation = math.radians(Z_rotation)          
 
        #Place Camera
        camera_name = bpy.context.scene.camera_name
        bpy.ops.object.add(type='EMPTY', location=(Base_line, 0, 0))
        bpy.data.objects['Empty'].name = "Base_left"
        bpy.ops.object.add(type='EMPTY', location=(Camera_centre, 0, 0))
        bpy.data.objects['Empty'].name = "Camera_centre"
        bpy.data.objects[camera_name].rotation_euler[0] = Final_tilt
        bpy.data.objects[camera_name].rotation_euler[1] = Final_dutch
        bpy.data.objects[camera_name].rotation_euler[2] = Z_rotation
        bpy.data.objects[camera_name].location[0] = Stantion_point_x
        bpy.data.objects[camera_name].location[1] = Stantion_point_y
        bpy.data.objects[camera_name].location[2] = Camera_height
        bpy.ops.object.add(type='EMPTY', location=(0, 0, 0))
        bpy.data.objects['Empty'].name = "Base_right"
 
        #Parent to Camera_right
        bpy.ops.object.select_all(action='TOGGLE')
        bpy.data.objects[camera_name].select = True
        bpy.data.objects['Base_left'].select = True 
        bpy.data.objects['Camera_centre'].select = True
        bpy.data.objects['Base_right'].select = True
        bpy.ops.object.parent_set(type='OBJECT')
        bpy.ops.object.select_all(action='TOGGLE')
 
        return {'FINISHED'}
 
class CameraSettings(bpy.types.Operator):
    bl_idname = "camera.general_settings"
    bl_label = "Create Camera"
 
    def execute(self, context):
        camera_name = bpy.context.scene.camera_name
        bpy.ops.object.add(type='CAMERA')
        bpy.data.objects['Camera'].name = camera_name
        bpy.data.cameras['Camera'].name = camera_name
        bpy.data.cameras[camera_name].lens = bpy.context.scene.focal_length
        bpy.data.cameras[camera_name].dof_distance = bpy.context.scene.focus_distance
        bpy.data.cameras[camera_name].show_limits = True
        bpy.data.cameras[camera_name].sensor_fit = bpy.context.scene.sensor_fit
        bpy.data.cameras[camera_name].sensor_width = bpy.context.scene.sensor_width
        bpy.data.cameras[camera_name].sensor_height = bpy.context.scene.sensor_height
 
        return {'FINISHED'}
 
def register():         
    bpy.utils.register_class( CameraPanel )
    bpy.utils.register_class( CameraPlacer ) 
    bpy.utils.register_class( CameraSettings ) 
 
def unregister():        
    bpy.utils.register_class( CameraPanel )
    bpy.utils.register_class( CameraPlacer )
    bpy.utils.register_class( CameraSettings ) 
 
if __name__ == '__main__':     
    bpy.types.Scene.base_line = bpy.props.FloatProperty( name = "Base Line", default = 0, min = 0, precision = 5, description = "Length of Base line") 
    bpy.types.Scene.camera_centre = bpy.props.FloatProperty( name = "Camera Centre", default = 0, min = 0, precision = 5, description = "Distance from base line right to centre of the camera")
    bpy.types.Scene.camera_left = bpy.props.FloatProperty(  name="Camera Left", default = 0, min = 0, precision = 5, description = "Length of camera left side")
    bpy.types.Scene.camera_right = bpy.props.FloatProperty(  name="Camera Right", default = 0, min = 0, precision = 5, description = "Length of camera right side")
    bpy.types.Scene.camera_height = bpy.props.FloatProperty(  name="Camera Height", default = 0, precision = 5, description = "Height of camera oabove the base line")
    bpy.types.Scene.camera_dutch = bpy.props.FloatProperty(  name="Camera Dutch", default = 0, precision = 5, description = "Camera Dutch. Positive=right, negative=left")
    bpy.types.Scene.camera_tilt = bpy.props.FloatProperty(  name="Camera Tilt", default = 0, precision = 5, description = "Camera Tilt. Positive=lens up, negative=lens down")
    bpy.types.Scene.focal_length = bpy.props.FloatProperty( name="Focal Length", default = 35, precision = 3, description = "Perspective Camera lens value in Millimetres" )
    bpy.types.Scene.focus_distance = bpy.props.FloatProperty( name="Focus Distance", default = 0, precision = 3, description = "Distance to object in Focus" )
    bpy.types.Scene.f_stop = bpy.props.FloatProperty( name="F. Stop", default = 5.6, precision = 3, description = "F. Stop value of the camera" )
    bpy.types.Scene.camera_name = bpy.props.StringProperty( name = "Camera Name", description = "Unique name for Camera")
    EnumProperty = bpy.props.EnumProperty 
    fits = [  ( "AUTO", "Auto", "Fit the sensor width or height depending on image resolution" ),
              ( "HORIZONTAL", "Horizontal", "Fit the sensor width" ),
              ( "VERTICLE", "Vertical", "Fit the sensor height" )]
    bpy.types.Scene.sensor_fit = EnumProperty( name = "Sensor Fit", items = fits, description = "Method to fit image and field of view angle inside the sensor" )
    bpy.types.Scene.sensor_width =  bpy.props.FloatProperty( name="Sensor width", default = 35, precision = 3, description = "Sensor width" )
    bpy.types.Scene.sensor_height =  bpy.props.FloatProperty( name="Sensor height", default = 18, precision = 3, description = "Sensor width" )  
 
register() 


Thanks
Tom

Another quick update, it now actualy works as an addon if you save it in the addons folder.

# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
bl_info = {
    'name': 'VFX Camera',
    'author': 'Thomas Wilshaw',
    'version': (),
    "blender": (2, 6, 1),
    'location': 'Properties > Render > Camera Setup',
    'description': 'Allows camera setup and placement',
    'warning': '', # used for warning icon and text in addons panel
    "wiki_url": "",
    "tracker_url": "",
    'category': '3D View'}
 
import bpy, math
class CameraPanel(bpy.types.Panel):     
    bl_label = "VFX Camera Setup"    
    bl_space_type = "PROPERTIES"    
    bl_region_type = "WINDOW"    
    bl_context = "render"      
    def draw(self, context):         
        layout = self.layout           
        scn = context.scene         
        row = layout.row()         
        col = row.column()
        col.label(text="General Camera Data:")
        col.prop( scn, "camera_name" )
        col.prop( scn, "focal_length" )
        col.prop( scn, "focus_distance" )
        col.prop( scn, "f_stop" )
        col.prop( scn, "sensor_fit" )
        col.prop( scn, "sensor_width" )
        col.prop( scn, "sensor_height" )
        col.operator( "camera.general_settings" )    
        col.label(text="Camera Placement Data:")     
        col.prop( scn, "base_line" )
        col.prop( scn, "camera_centre" )
        col.prop( scn, "camera_left" )
        col.prop( scn, "camera_right" )
        col.prop( scn, "camera_height" )
        col.prop( scn, "camera_dutch" )
        col.prop( scn, "camera_tilt" )
        row = layout.row()         
        col.operator( "camera.placer_op" ) 
 
 
class CameraPlacer(bpy.types.Operator):
    bl_idname = "camera.placer_op"
    bl_label = "Place Camera"
 
    def execute(self, context):
 
        #Convert user inputs to float (not string)
        Base_line = bpy.context.scene.base_line
        Base_line = float(Base_line)
        Camera_centre = bpy.context.scene.camera_centre
        Camera_centre = float(Camera_centre)
 
        Camera_left = bpy.context.scene.camera_left
        Camera_left = float(Camera_left)
 
        Camera_right = bpy.context.scene.camera_right
        Camera_right = float(Camera_right)
 
        Camera_height = bpy.context.scene.camera_height
        Camera_height = float(Camera_height)
 
        Camera_dutch = bpy.context.scene.camera_dutch
        Camera_dutch = float(Camera_dutch)
 
        Camera_tilt = bpy.context.scene.camera_tilt
        Camera_tilt = float(Camera_tilt) 
        #Work out left angle
        Angle_left = (Base_line**2 + Camera_left**2 - Camera_right**2) / (2 * Base_line * Camera_left)
        Angle_left = math.acos(Angle_left)
        #Find cordinates
        Stantion_point_x = (Camera_left) * math.cos(Angle_left)
 
        Stantion_point_y = (Camera_left) * math.sin(Angle_left)
 
        #Work out tilt and dutch
        Final_tilt = 90 + Camera_tilt
        Final_tilt = math.radians(Final_tilt)
 
        Final_dutch = math.radians(Camera_dutch)
 
        # Work out Z rotation
        #calculate CC to SP
        Angle_left = (Base_line**2 + Camera_left**2 - Camera_right**2) / (2 * Base_line * Camera_left)
        d = (Camera_centre**2 + Camera_left**2 - 2 * Camera_centre * Camera_left * Angle_left)        
        CC_to_SP = math.sqrt(d)
 
        #Stantion_point_x-CC
        x = Stantion_point_x-Camera_centre
 
        #Z_rotation
        Z_rotation = math.acos((Stantion_point_y**2 + CC_to_SP**2 - x**2) / (2 * Stantion_point_y * CC_to_SP))
        if Camera_centre > (Base_line / 2):
            Z_rotation = 180 - (math.degrees(Z_rotation))
            Z_rotation = -(math.radians(Z_rotation))
        else:
            Z_rotation = 180 - (math.degrees(Z_rotation))
            Z_rotation = math.radians(Z_rotation)          
 
        #Place Camera
        camera_name = bpy.context.scene.camera_name
        bpy.ops.object.add(type='EMPTY', location=(Base_line, 0, 0))
        bpy.data.objects['Empty'].name = "Base_left"
        bpy.ops.object.add(type='EMPTY', location=(Camera_centre, 0, 0))
        bpy.data.objects['Empty'].name = "Camera_centre"
        bpy.data.objects[camera_name].rotation_euler[0] = Final_tilt
        bpy.data.objects[camera_name].rotation_euler[1] = Final_dutch
        bpy.data.objects[camera_name].rotation_euler[2] = Z_rotation
        bpy.data.objects[camera_name].location[0] = Stantion_point_x
        bpy.data.objects[camera_name].location[1] = Stantion_point_y
        bpy.data.objects[camera_name].location[2] = Camera_height
        bpy.ops.object.add(type='EMPTY', location=(0, 0, 0))
        bpy.data.objects['Empty'].name = "Base_right"
 
        #Parent to Camera_right
        bpy.ops.object.select_all(action='TOGGLE')
        bpy.data.objects[camera_name].select = True
        bpy.data.objects['Base_left'].select = True 
        bpy.data.objects['Camera_centre'].select = True
        bpy.data.objects['Base_right'].select = True
        bpy.ops.object.parent_set(type='OBJECT')
        bpy.ops.object.select_all(action='TOGGLE')
 
        return {'FINISHED'}
 
class CameraSettings(bpy.types.Operator):
    bl_idname = "camera.general_settings"
    bl_label = "Create Camera"
 
    def execute(self, context):
        camera_name = bpy.context.scene.camera_name
        bpy.ops.object.add(type='CAMERA')
        bpy.data.objects['Camera'].name = camera_name
        bpy.data.cameras['Camera'].name = camera_name
        bpy.data.cameras[camera_name].lens = bpy.context.scene.focal_length
        bpy.data.cameras[camera_name].dof_distance = bpy.context.scene.focus_distance
        bpy.data.cameras[camera_name].show_limits = True
        bpy.data.cameras[camera_name].sensor_fit = bpy.context.scene.sensor_fit
        bpy.data.cameras[camera_name].sensor_width = bpy.context.scene.sensor_width
        bpy.data.cameras[camera_name].sensor_height = bpy.context.scene.sensor_height
 
        return {'FINISHED'}
 
def register():         
    bpy.utils.register_module(__name__)
    bpy.types.Scene.camera_name = bpy.props.StringProperty( name = "Camera Name", description = "Unique name for Camera")
    bpy.types.Scene.focal_length = bpy.props.FloatProperty( name="Focal Length", default = 35, precision = 3, description = "Perspective Camera lens value in Millimetres" )
    bpy.types.Scene.focus_distance = bpy.props.FloatProperty( name="Focus Distance", default = 0, precision = 3, description = "Distance to object in Focus" )
    bpy.types.Scene.f_stop = bpy.props.FloatProperty( name="F. Stop", default = 5.6, precision = 3, description = "F. Stop value of the camera" )
    EnumProperty = bpy.props.EnumProperty 
    fits = [  ( "AUTO", "Auto", "Fit the sensor width or height depending on image resolution" ),
              ( "HORIZONTAL", "Horizontal", "Fit the sensor width" ),
              ( "VERTICLE", "Vertical", "Fit the sensor height" )]
    bpy.types.Scene.sensor_fit = EnumProperty( name = "Sensor Fit", items = fits, description = "Method to fit image and field of view angle inside the sensor" )
    bpy.types.Scene.sensor_width =  bpy.props.FloatProperty( name="Sensor width", default = 35, precision = 3, description = "Sensor width" )
    bpy.types.Scene.sensor_height =  bpy.props.FloatProperty( name="Sensor height", default = 18, precision = 3, description = "Sensor width" )  
    bpy.types.Scene.base_line = bpy.props.FloatProperty( name = "Base Line", default = 0, min = 0, precision = 5, description = "Length of Base line") 
    bpy.types.Scene.camera_centre = bpy.props.FloatProperty( name = "Camera Centre", default = 0, min = 0, precision = 5, description = "Distance from base line right to centre of the camera")
    bpy.types.Scene.camera_left = bpy.props.FloatProperty(  name="Camera Left", default = 0, min = 0, precision = 5, description = "Length of camera left side")
    bpy.types.Scene.camera_right = bpy.props.FloatProperty(  name="Camera Right", default = 0, min = 0, precision = 5, description = "Length of camera right side")
    bpy.types.Scene.camera_height = bpy.props.FloatProperty(  name="Camera Height", default = 0, precision = 5, description = "Height of camera oabove the base line")
    bpy.types.Scene.camera_dutch = bpy.props.FloatProperty(  name="Camera Dutch", default = 0, precision = 5, description = "Camera Dutch. Positive=right, negative=left")
    bpy.types.Scene.camera_tilt = bpy.props.FloatProperty(  name="Camera Tilt", default = 0, precision = 5, description = "Camera Tilt. Positive=lens up, negative=lens down")
 
    pass
 
def unregister():        
    bpy.utils.unregister_module(__name__)
    pass
 
if __name__ == '__main__':
    register()

If anyone has tested it, I’d appreciate any comments, whether bugs or just making it neater code.

Thanks
Tom

Just wonderd if anyone had tried this yet or had any feed back?

Thanks
Tom