A raytracer in Python for Cinema 4D

A raytracer in Python for Cinema 4D

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.

Preparations

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.


Go!

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:
    sys.path.insert(0, folder)

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())


The meat

Let’s take a look at the previously instantiated MyCommandData class.
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.

#END:

I hope this gave you a first glimpse at Python plugin development for Cinema 4D as this short introduction will end here.

The renderer itself is a nice piece of work keim_at_Si originally wrote for Actionscript 3 and JavaScript.
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…

Hint:
You can render a sequence of images to the picture viewer and save it as video using ShowBitmap().

Last but not least you can download the source here – have fun coding!

5 thoughts on “A raytracer in Python for Cinema 4D”

  1. Michael

    Great stuff. Curious, did you develop this entirely inside of c4d’s python editor? Or did you use an external editor such as TextMate or the like? If so, how can you get c4d to reload your plugin so you dont have to restart c4d every single time you want to test out a new addition to the code?

    Thanks!

  2. flashgordon Post Author

    Hi Michael,

    yes, I use the Pydev IDE with Eclipse and sometimes Notepadd++.

    I always save Cinema 4D’s actual state as startup layout and put an empty file “c4d_debug.txt” in it’s root.

    This ensures it will always open with my dev setup in place and working under Windows, I get the trace console window which is handy to quickly kill c4d (just by closing it).

  3. Michael

    Ah, excellent. Have you gotten code completion to work in eclipse? If so, what forced builtins and libraries do you have to add. And is there anything else you need to configure to get cc working?

    Btw, I had never seen your site before. You’re flash stuff is really great.

    Thanks.

  4. flashgordon Post Author

    Oh I am very sorry, I saw your last comment just now.

    I have a standard Python 2.6.4 Installation and told Pydev to use it’s interpreter – code completion, refactoring etc. works fine.

    Glad you like the flash stuff :)

    Cheers

  5. Pingback: Smart-Page.net » Blog Archive » Advanced Python Plugin Coding For Cinema 4D

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" line="">