Create a curve from camera to empty

I made this script in Maya a long time ago. It creates a curve (actually a straight line) that will go from the current camera to the selected locator (empty). I need the same thing in Blender but I have no idea on how to do this in Blender as the Blender commands are not the same as in Maya, obviously.

The steps are:

  1. get the location of the empty (A)
  2. get the location of the camera (B)
  3. create a curve from A to B
  4. set the origin at B
  5. scale the curve by 1000
  6. select the empty

Here’s the original code in Maya:

# Fires a curve from the camera to the selected object. By Robert Rioux. Inspired by NavKit by Laurent Taillefer. :-)

import maya.cmds as cmds
target = cmds.ls(sl=True)


class rayProject(object):
   def __init__(self,*args):
       self.rayProjectWin = 'rayProject'
       if cmds.window(self.rayProjectWin, exists=True):
           cmds.deleteUI(self.rayProjectWin)

       self.buildWin()

   def buildWin(self,*args):
       self.rayProject = cmds.window(self.rayProjectWin, t="Ray Project", tlb = True, w=100, h=30, bgc= [0.4,0.4,0.4])
       theRowLayout = cmds.rowColumnLayout(nc=1,columnWidth=(30,1), h=30)
       cmds.button(label="Fire!",  width = 80, command = self.fire)       
       cmds.setParent( theRowLayout )
       cmds.showWindow(self.rayProjectWin)   



# Project the curve


   def fire(*args):

       target = cmds.ls(sl=True)

       if not target:
           cmds.error("Please select a locator")

       else:    
           transform = maya.cmds.xform( target, q=True, ws=True, t=True )

           pan = cmds.getPanel(wf=True)
           cam = cmds.modelPanel(pan, q=True, camera=True)

           transformCam = maya.cmds.xform( cam, q=True, ws=True, t=True )

           cmds.curve (p=[(transformCam[0],transformCam[1],transformCam[2]),(transform[0],transform[1],transform[2])], d=1) 

           newCurve =  cmds.ls(sl=True)
           cmds.xform (r=True, piv=(transformCam[0],transformCam[1],transformCam[2]))
           cmds.xform (s=(10,10,10))
           cmds.select (target)

rayProject()

Can anybody help me? Thanks.

Hi @BlenderBob ,
this should do what you want. I added step 4 and 5 as comments, didnt get the sense. So have a look at that.

import bpy
from mathutils import Vector

maincam = bpy.data.objects["Camera"]

sel_objs=  bpy.context.selected_objects

first_sel_empty = None
for obj in  sel_objs:
    if obj.type == 'EMPTY':
        first_sel_empty = obj        
        break
    
if first_sel_empty != None:
    new_curve = bpy.data.curves.new('path_curve', type='CURVE')
    new_curve.dimensions = '3D'
    path = new_curve.splines.new('POLY')

    path.points.add(2)
    path.points[0].co = Vector((first_sel_empty.location.x,first_sel_empty.location.y,first_sel_empty.location.z,1))
    path.points[1].co = Vector((maincam.location.x,maincam.location.y,maincam.location.z,1))
    
    curve_obj = bpy.data.objects.new('CamToEmptyCurve', new_curve)
    #curve_obj.location = maincam.location
    #curve_obj.scale = (1000,1000,1000)
    scene = bpy.context.scene
    scene.collection.objects.link(curve_obj)
    scene.objects.active = first_sel_empty

You need to have an empty selected in the outliner and the camera is identified by its name

Cool! I gave to a shot. I actually creates a line that goes from the 3d cursor to the camera to the empty. Also, can we scale the line using the camera location as origin by 1000? Thank you so much!

Oh yeah, I see that what you commented was actually the origin ans scale. it makes sense for me as I need the curve to extend beyond the empty.

I think what needs to be changed in the first commented lines is the origin needs to be at the cam location, not the curve itself

Ok got it.

Like that?

import bpy
from mathutils import Vector

maincam = bpy.data.objects["Camera"]

sel_objs=  bpy.context.selected_objects

first_sel_empty = None
for obj in  sel_objs:
    if obj.type == 'EMPTY':
        first_sel_empty = obj        
        break
    
if first_sel_empty != None:
    new_curve = bpy.data.curves.new('path_curve', type='CURVE')
    new_curve.dimensions = '3D'
    path = new_curve.splines.new('POLY')

    path.points.add(2)
    path.points[0].co = Vector((0,0,0,1))
    vec_e=  Vector((first_sel_empty.location.x,first_sel_empty.location.y,first_sel_empty.location.z,1))
    vec_c=  Vector((maincam.location.x,maincam.location.y,maincam.location.z,1))
    path.points[1].co = (vec_e-vec_c) * 1000
    
    curve_obj = bpy.data.objects.new('CamToEmptyCurve', new_curve)
    curve_obj.location = maincam.location
    #curve_obj.scale = (1000,1000,1000)
    scene = bpy.context.scene
    scene.collection.objects.link(curve_obj)


1 Like

YES YES YES YES YES!!! Thank you so much! This is super useful if you have a good camera track but you don’t have a tracking point where you need it. The idea is that you move your empty on the place you want it, you rune the script, you move on the time line. You will see that curve but the empty will not be exactly on the location you wanted it but you can move it along the curve (snap) until you reach the wanted location and this way you will have a prefect location for the empty. (If it doesn’t make sense I can send you screen shots). It’s hard to explain. :slight_smile:

1 Like

Not sure if I got you right. Do you have some screenshots ready?

Here you go!

2 Likes

Oh ok i got it, you want to fix a wrong trackpoint location that was caused by a wrong distance/deptth along the first camview and eliminate its last degree of freedom by moving it along this former camray from another view. Yeah thats neat indeed. :+1:

We modified the script. Now it will find the active camera instead of the hard coded “Camera”. We also created an edge instead of a curve because the snapping wouldn’t work on a curve.The pervious line will be deleted if another one is created and we made it an addon. There’s a “Fire” button that appears in the Tool tab. I’d like to distribute it for free to the community. I assume that’s ok with you since you posted it here. I’d like to give you the credit for the first version. Do you want me to use Debuk or something else?

1 Like