Maxon has just released the R12 version of Cinema 4D, which includes Python – so let’s dig into Python plugin development!
We are going to build a ray tracer… with Python! Watch a rendered video.
Update: All Python scripts in this blog have been updated to work with the R12.
Ok, I’m sorry – I should have come up with something more useful, but hey – it’s fun and it serves the purpose.
Also this is not really about raytracing basics, but coding Python plugins for Cinema 4D – the cake is a lie!
And while I am apologizing… I don’t do tutorial style posts that often, so please bear with me.
This is meant for coders coming from a C++ or Coffee background, so if you are already familiar with Python you might want to skip a few lines.
Please note that this is supposed to be a template for a rather complex Python plugin, so don’t feel discouraged if you had something simpler in mind – no problem – you can just write a full-fledged plugin using only one *.pyp file.
It’s a good idea to start by deciding which plugin type is best suited – in this case I want to write a
CommandData plugin that will be callable from the Python plugin menu and open a dialog to display the rendered output.
So first I create a folder
'SmartPray4D' within the
'plugins' directory of my Cinema 4D installation.
(SmartPray4D because “Smart Python based Ray tracer for Cinema 4D” was exactly one letter too long for my taste ).
Within that folder I then make two other directory’s: ‘res’ – which will hold all resource files the plugin will load, such as *.res-, *.str files and the plugin’s icon.
The other one is called ‘smartpray4dpackage’ and as the name suggest I am going to create a package here.
A package is really just a collection of Python modules – or better ‘sub modules’.
It’s mandatory to place an empty file named ‘__init__.py’ within a package folder. This tells Python to look for sub modules within that directory.
Now let’s get started – within the plugin directory I make a *.pyp file – the entry point which will register the plugin with Cinema 4D.
First I want to append my plugins directory to Python’s search path, so it may find the
'__init__.py' within the ‘smartpray4dpackage’ folder and treat it as package.
folder = os.path.dirname(__file__)
if folder not in sys.path:
As you can see from that statement, Python doesn’t use curly braces but indentation (4 spaces) to define code blocks and logical operators are spelled out.
Now I have access to my package and import a config file that will hold some constants and the
MyCommandData class that I will register in the next step.
from smartpray4dpackage.config import PLUGIN_ID
from smartpray4dpackage.mycommanddata import MyCommandData
The registration itself is done within the
__main__ block and is pretty straight forward.
Note how I load an TIF icon from the ‘res’ folder and the
PLUGIN_ID which was imported from the config class – you need to apply for a unique plugin ID from Maxon so your plugin won’t interfere with others.
if __name__ == "__main__":
icon = c4d.bitmaps.BaseBitmap()
icon.InitWith(os.path.join(os.path.dirname(__file__), "res", "smartpray4d.tif"))
c4d.plugins.RegisterCommandPlugin(PLUGIN_ID, "Smart Pray4D", 0, icon, "A crazy Python benchmark", MyCommandData())
Let’s take a look at the previously instantiated
There is a private object
__dialog which will hold the dialog that is created once the
CommandData plugin gets executed by the user.
It’s created within the overridden method
Execute which Cinema 4D calls once the plugin gets selected.
ReloadLayout also has to be defined so Cinema knows what to do when the dialog gets restored.
In this case it’s a simple matter of checking if there already is a dialog or if it needs to be created.
Now this is where the fun begins – lets head over to the ‘mydialog.py’.
This module has the familiar
__init__ constructor in which three objects
__userarea, __scene and
__renderer get instantiated. Note the self-parameter – it is similar to the C++ pointer or the
this reference in ECMA/Java and has to be the first parameter in every class method.
The mydialog module then overwrites the
CreateLayout which… does exactly that, and creates a timer that will call the renderer, providing him with the scene to render and the userarea as target for its output.
I hope this gave you a first glimpse at Python plugin development for Cinema 4D as this short introduction will end here.
I did some small changes, but really just ported it to Python and tried my best to abstract it a little.
Now where to go from here? It’s really up to you Checkout the sources and have a look at the Python SDK documentation – endless possibilities…
You can render a sequence of images to the picture viewer and save it as video using
Last but not least you can download the source here – have fun coding!