I am looking for a scripted way to export the 2D coordinates of an object to be used in Adobe After Effects. My Python knowledge is basically zero, so I could use some help.
# use this script to export the resulting screen coordinates
# of the currently active object in 3D space. Coords get
# output to the console -h
import bpy
from bpy_extras.object_utils import world_to_camera_view
scene = bpy.context.scene
# needed to rescale 2d coordinates
render = scene.render
res_x = render.resolution_x
res_y = render.resolution_y
rnd = lambda i: round(i,1)
print("====================")
for j in range(1845,1902): # frame range you're interested in
scene.frame_set(j)
obj = bpy.context.active_object
coords_2d = world_to_camera_view(scene, cam, (obj.matrix_world * obj.location))
print("\t{}\t{}\t{}\t".format(j, rnd(res_x*coords_2d.x), rnd(res_y*(1-coords_2d.y))))
The first error was NameError: name 'cam' is not defined, so I’ve added
cam = bpy.context.scene.camera
To the variables, which at least fixed that one. Still, execution of the script threw another error:
TypeError: Element-wise multiplication: not supported between 'Matrix' and 'Vector' types
which happens in the penultimate line. How could I fix that?
Ideally I’d like to have a few more features in this, especially using the currently set frame range (instead having to change it in the script all the time) and the ability to copy the generated coordinates to the clipboard automatically on execution, so that I can just paste them into a 2D layer in After Effects. I’d prefer the clipboard way over outputting a file, because this would require extra steps which I’d like to avoid. Is this at all possible inside of Blender?
The script you found was written for an older version of blender than you are currently using. I believe it was Blender 2.80 that changed the matrix math. Use @ instead of * in the line:
I’ve optimized this thing a bit, now writing into a text file, for the time being (until I find out, how to copy the output to the clipboard instead). Also I’m now reading all the data, like frame ranges, from the scene, so nothing needs to be defined in the script.
I also had to throw out the obj.matrix_world part of the calculation, as it produced wrong coordinates. Now it seems to be working fine!
So, the big question is, how can I get this output to the clipboard when running the script? It wouldn’t mind if the text-file is created as an intermediate step.
Thanks, but there are so many “solutions” in that thread, I feel a bit lost. At a quick glance it looks like they are just copying a defined string to the clipboard. I am creating more than just one string with my script, so how would I copy the whole output to the clipboard in one go? Or can I load my saved text-file as a single string?
Unfortunately that still doesn’t work. Nothing gets into the clipboard, instead the first line (and only the first line) of the text file is printed in the console.
yeah the default Python clipboard functionality is super buggy. It’s hard to say what precisely is going wrong. Try the second option, the one with pyperclip
I’ve tried pyperclip before, installed it via pip install pyperclip, which worked (version 1.8.2), but as soon as I try to import pyperclip in Blender, it just states ModuleNotFoundError: No module named 'pyperclip'
You have to install Pyperclip in Blender using Blender’s pip. Blender runs on its own Python installation, so pip installs aren’t loaded in Blender. That code I wrote with pyperclip is specifically written for Blender, it will install pyperclip into Blender’s python installation
import subprocess
TextFile='C:\\tmp\\coordinates.txt'
with open(TextFile) as f:
s = "".join(f.readlines())
subprocess.run("clip", universal_newlines=True, input=s)
Thanks a lot! That last command finally worked. So, here’s my final script, which copies the 2D-coordinates of the selected object to the clipboard (using the active camera, render size, frame rate, and frame range) to be pasted as keyframes into a position property in Adobe After Effects: