 Okay, welcome everyone. So I'm going to talk about K3D, free 3D modeling and animation package. Starting with a small overview of my presentation, I'll first introduce what K3D is about. Next I'll show how to use a standard plugin in K3D. The main chapter of this presentation is actually to show you how to write your own plugin. And finally we will see how to use this new plugin and then I will end with a conclusion, which is of course that K3D is amazing. So what is K3D? It's a free 3D modeling and animation package, which was written by Tim Shad. He started the project around 1992. K3D does modeling and animation for the actual rendering. It relies on external rendering engines, such as XS, which implements the Pixar-Renderman interface. Renderman engines are supported out of the box and we also have some plugins for some non-renderman engines. It has a very modular design, which means basically everything is a plugin, including user interface. Different plugins interact with each other through a fairly unique visual programming system, which allows you to make a sort of a tree, which interconnects different nodes. So how do we use a standard plugin? We start from the create menu, which is basically a big menu containing all the plugins available. In this case we will import an alias wavefront object, so we go to the mesh reader category and choose the alias wavefront loader plugin. Once we have chosen this plugin, we get to see the properties panel, which actually shows all the inputs and parameters for the plugin chosen. Most importantly here, of course, the file name. Once we go on to set the file name, the object gets loaded and is shown in the viewport. Now we're going to apply an additional modifier, which is done by right-clicking the model. We get again all the plugins that can be used as a modifier, and in this case we apply the subdivision surface modifier, which creates an interactive, smoothed version of the object we imported. So next onto the important part, which is actually how to create new plugins. I'll start off with a small overview of what the basic components of a plugin are. So you basically just start off in a new directory, which can be external to the K3D source tree. The first thing you have to define is a CMake file. So the CMake file simply contains two calls to pre-defined CMake macros and basically define the name of the plugin until the build system where to find our new plugin. Next is a module.cpp file, which will contain the actual code of our new plugin. It can contain one or more classes, which for a plugin in the document should all inherit from the K3D iNode interface. In this class we can define different so-called properties, which will actually store the data for the plugin and which will also allow inputs, and parameters to be set. Finally, we also need to define a factory class, which will be used to instantiate new instances of our plugin. As an example, I will show you how to create a simple mirror tool, which will mirror points along one or more components. So the first thing we have to do is to declare our interface we will be using. Since we will be deforming mesh points, we will be flipping components of each point in the mesh. I chose to use mesh deformation modifier here, which permits to easily do this action on the mesh. So we declare a class, which inherits from our base class, which is part of the SDK, and type the base class for convenience. Next, we have to define some parameters to our new plugin. In this case, I will define three Boolean parameters, which specify if the points should be mirrored along the x, y, and z I have only shown the x component here because the others are exactly the same. In order to declare a property, we call the K3DDataMacro, which actually is a shortcut to an otherwise complicated template declaration of a series of nested template arguments, which in fact define different policy classes. So the first argument is a type of the property, Boolean in this case. Next, the policy about the property name. The name is important because it will be used in scripting and for serialization to file. In this case, we choose that the name should not be possible to change. In case our Boolean value changes, we want to emit a change signal. So we specify the change signal policy. When modified, we want to be able to undo our changes. So we simply specify with undo, so it will be taken into account in the standard undo redo system in K3D. Local storage means that the Boolean value is actually stored inside the property. It's not referred to by a pointer or anything like that. No constraint means we don't constrain a property value in case of a Boolean that would not be very useful. But in case of a double or integer value, it is useful to be able to define constraints so we can limit the values to a certain range. Property is going to be writable, obviously, otherwise, we won't be able to change it. With serialization means that the property will automatically get saved into the K3D document file if we specify with serialization. Okay, so this is the basic declaration of our new class for the plugin. Next, we have to implement the constructor for our class, which always takes two arguments, one for the factory to create the plugin and one for the document it will be part of. We simply pass those on to our base class. Next, we have to initialize our three properties. Again, I'm only showing one of them. The owner is the container of the property. Obviously, in this case, this will be our new plugin itself, so we use this pointer. Next, we initialize the name and for the X component, I use mirror underscore X. This can be referred to in the Python scripting later on and will also be saved into the file. The label is what will be shown in the user interface. It's mirror X, a little prettier than the name. Next, we initiate the description, which is shown in the tooltip once it shows up in user interface and we give an initial value of true. Constructor body, then, has to take into account that we have to update the mesh if the property changes, so we simply connect to the 6C++ change signal that is emitted by our new property. Next, the important part, in fact, the real code of our plugin. Since we inherited from the mesh deformation modifier, we get to implement the on deform mesh modifier, which has as arguments all the inputs for the mesh, including the list of input points and the list of output points we have to store to. So in this case, of course, the met is extremely simple. We simply loop over all the points and if the corresponding property is set, we flip the component and we store the points in the output area. The important part of this code is the pipeline value here. So our mirror X here is a property, which means that it can have an internal value, but it can also be connected through the user interface to another input. Specifying pipeline value here means that we want the final result of all the connections that are made to establish the value of our property, which is a very powerful tool, obviously. So the last thing we have to do is to take care of plug-in registration. In order to do this, we define a factory. This contains an interface list, which is used to keep track of what capabilities each plug-in has. In this case, it's both a mesh source and a mesh sync, because it can take mesh data as inputs and outputs new mesh data. We also have to give it a unique ID. There's a small tool based on LibQUID that generates a 64-bit unique ID for each plug-in, which is used to recover the plug-ins from documents. We give it a name, a description that will again be the tooltip, a category, and we mark it as experimental if we're not entirely sure that it already works completely in the way it's supposed to. Finally, we call the registration macro, which actually sets an entry point to the module, since it will be compiled as a shared object. We have to give an entry point for DLOpen to load the module into K3D. Okay, so now how can we use a new plug-in? Again, we go to the create menu. After we have rebuilt K3D, our external plug-in will be shown in the deformation category, which we entered on the previous slides. See here the deformation category and the different names. They immediately and automatically show up in the user interface. It's marked as experimental, as requested. Again, after creation, the properties panel shows up, and we find our three properties, as we declared, also automatically taken into the user interface, with the first one set default true, the other is default false. Now, nothing is happening yet. We still have our previously loaded mesh, but it's unaltered, because we haven't set the input yet. In order to do that, as you can see, there's no possibility to enter a value or anything. We have to click the connect button. So, if we click the connect button next to the property, we can connect to our original mesh, and once this is done, the mesh gets updated, and we get our two twins immediately integrated into the pipeline. So, if we modify part of the original mesh on the left, the mesh on the right changes along with it interactively. So, as you can see, the modular design of K3D makes it very easy to get started writing your own code. You don't have to worry too much about the framework and everything. It's very easy to dive right in and to write a plugin that does what you want to do. There's plenty of opportunity there. We are not at all feature complete yet, so currently most tools are based on modeling. There's still a lot of work to do. For instance, in the texturing department, NURBS modeling and so on is not fully supported yet. All the basic components are there in the SDK, just waiting for someone to write plugins on top of them. For instance, to allow modifying NURBS objects, UV parameters, physics integration, deformation bones, those are all things you will find in competing open source packages, such as Blender, but which are not yet integrated into K3D. The framework is there, and for the moment we are working hard on finalizing our modeling system, and then we will move on to the animation functionality, but there's plenty of opportunity for improvements. If you want more information, you can visit our website or subscribe to our mailing list. We will also likely hopefully take part again in the summer of code this year, so if you're a student and you're interested in participating, we should have some more news on that pretty soon. Okay, thank you for your attention. I'll be down there for questions if you have any. Thank you.