By Roland van der Linden, Marnix Kraus and Bart Bollen
1. Initial project description
The initial project description, the way we found it ourselves: Initial Description.
2. Our own interpretation
The meaning of this project is creating a system that can define/form procedural filters. These procedural filters can then be applied to virtual (game) worlds.
A procedural filter can be divided in two sections:
A filter is an effect thrown over a ‘basic’ environment or object. After the filter, the blueprint of this environment or object will still be the same, but the appearence will be different.
The ‘procedural’ term in procedural filter comes from the fact that how the appearence changed, will be automatically calculated in some random way. So applying a procedural filter twice on the same object, will result in two different looking objects.
Take for example a wooden chair. If we create a procedural filter that applies lichen to an object, we can change the appearence of the chair by simply applying the filter to it. So after applying the filter, the chair will look like a wooden chair, covered with lichen. Even better is: If we have 20 wooden chairs, we can apply the procedural lichen filter to it, and now all chairs are covered in lichen, but no chair looks the same! Taking this even further, if we have a classroom full of tables, chairs, closets, etc. We can simply apply the lichen filter to the ‘environment’ classroom, and all objects will be covered in lichen.
Ofcourse, a lichen filter is just one example. It is very likely that users will want to apply multiple filters to an environment. Therefor the system will be able to combine multiple procedural filters, in any order. This adds the complexity that subsequent filters will effect eachother.
From the example we can conclude that procedural filters are useful because it lowers the amount of work needed to create a world with different looking same-type objects. In theory, all kind of real-world phenomena can be turned into procedural filters. Therefor our goal is not to create a specific amount of different filters, but create a system that can define procedural filters. The system needs to be easy to use and understandable, since artists will be using it. Then again, it needs to support a lot of possible operations.
The ultimate goal of the project is that the procedural filters created by our system can be used within the procedural world generator currently develloped for TNO: Sketchaworld.
3. Procedural Filter Examples
For 9 weeks, we worked on a system in which anyone can create, apply, and view procedural filters. Without further ado, we will show you the results we got from the filters we created ourselves.
In this image, you can see we had a basic office, and turned it into an office in which a party has taken place. So we applied a ‘partyfilter’ on the office. This added paperchains, and all sorts of party stuff (like balloons, empty bottles etc) to the tables and floor.
This image shows an image of the exact same filter as the one mentioned above, however it is from a different camera perspective.
In this image, you can see we had a basic factory, and turned it into a filthy old factory with a filth-filter. You can see rust, dust, garbage, rotated boxes and erosion. Note that we could not alter the walls and floors, or those would also have looked way filthier.
4. Side Note
The examples shown here, are maybe not that impressive. The focus of the project was mostly on the Editor, in which filter can be created. This editor needs to be used by artists, who have nothing to do with coding. Therefor, most of our time was spend on the visual representation, an userfriendly-environment, and clearness of creating the procedural filters. If one uses worlds that look amazing, then the procedural filters will work just as well, and the results will be way more impressive.
The big plus of a procedural filter is that it will work on all sorts of worlds. The filth-filter can be applied to an object, the factory, or some landscape-world. If the user creates the filter correctly (in other words: it works generic), the filter will make any given world ‘filthy’.
5. The Procedural Filter Editor
For us, this is the most important part of the project, the program with which anyone (with some general background knowledge) can create procedural filters. We were asked to create an easy scripting language, however we decided to go with another visual representation which works well for other equal programs. This added complexity to the creation of the system, but we think the effort will pay off for the end-user.
As you can see, operations are represented by nodes. With a modular structure of operations, every operation can be reused and chained to form the filter. We created 30 operations or so, but the user will want more. Therefore new operations can be added easily (this does in fact require a programmer’s hand). Every created filter can be used within another filter. Other than operations, the filter has nodes for values, unknown values (parameters that can be entered at runtime), subfilters, and results. All those nodes have their own color, which is why you can see 4 different types of nodes (the fifth is not visible in this image).
6. Video’s of the editor
For the final presentation, we created some video’s to explain the possibilities of the editor. The explanation (in words) is not in the video’s, but if you want to see the editor at work, try the video’s below.
- In this first video, you will not see the editor at work, but it will give you an introduction of the program in which filters can be used on an environment. This ‘viewer’, as we call it, will be used to show a demo of what our created filters can do. Since there is no additional explanation in the video, you can find extra information on what happens right under the following link. Please save the file to your computer before playing it if the Media Player Extension does not work.
We show what the program looks like. It has 3 lists, and a screen in which an environment can be placed. The first thing we do is open such an environment. Notice that the first list now holds all references to the objects in the environment. The second list contains filters which can be added. The third list is the selection of objects to add a filter to. So we first add a filter to the second list, we add an object to the ‘selected objects’, and then add a filter to the ‘selected objects’. The filter will add objects of a certain type to the environment, in this case it are coat racks. We enter the parameter for how many coat racks we want, and press the button that executes the filters on the selected objects. Note that the selected object is the whole environment, so the result is an environment with extra coat racks.
- In the second video, we show the creation steps of a simple filter, and also what happens when we use it (also: if something happens at all!). Try to look at the filter creation only, since we will cover the rest of the program in the last video. Since there is no additional explanation in the video, you can find extra information on what happens right under the following link. Please save the file to your computer before playing it if the Media Player Extension does not work.
We decide to create a filter that can rotate all kinds of cupboards. Therefor, we need the operation ‘rotate’, and we need the get all the cupboards from the environment, operation ‘SelectThingsOfClass‘. We need the environment itself, which will be given at runtime, because of which it will be a parameter (inputNode). Also, we need the type of objects to rotate (called a class), and the new rotation as a parameter (inputNode). Finally, we need to return the resulting environment through a ‘resultNode’.
After dragging all these nodes on the canvas (your working area), we start connecting them. Nodes work with a basic input-output system, (inputs on the left, outputs on the right). The first thing that needs to happen is: select things of class ‘cupboard’ from the environment. The result of this operation (a list containing all the cupboards) has to be passed on the the next operation. This is the rotation-operation, and it will rotate every object in the list with the given new rotation.
We save our first filter, and head over to the viewer. Here we open the filter, and add it to the total environment. We can now enter the new rotation, so we just make something up. After using the filter, we note that all cupboards have rotated! This may not have been the wanted rotation (since they’re half through the walls etc), but that just needs a new rotation value which can be done very easily.
- In the third and last video, we show the depth of the program. It will cover creating a (sub-)filter, how it can be reused in other filters, and what happens when the subfilter itself changes. Other than that, many minor userfriendly features will be shown. Since there is no additional explanation in the video, you can find extra information on what happens right under the following link.
We decide to create a filter that adds a number of items to tables. We already have the filter that puts stuff on the tables, and we need to create an filter that calculates how many things need to be added. This is not a logical calculation process, but we will just use some random multiplications and a sum to show you the use of the subfilter. The first thing we do is get some nodes on the canvas. Note that we can also search for an operation name in the searchbar, so you can get nodes by their name (which works way faster if there are a lot of operations). We drag two multiplications, a sum, two inputs and an output on the canvas, and start connecting them. Note that there is a list with the current filter-errors underneath the canvas. If an error remains, the filter will never execute correctly (kind of like a TODO-list). Every input and output location has some types next to them. These allowed-types will change when we connect nodes with eachother. They also make sure that you can NOT connect two nodes with eachother if the types don’t match, so the user can’t create filters with wrong connections in them. If you do try to connect two nodes with types that dont match, a message will be shown in the status bar (there are way more messages than just this one).
After connecting everything, we note there is still one error, but we save the filter as ‘FilterA’, and open up a new one in another tab. Here we drag in a filterNode, a node containing a filter. We tell it to contain ‘FilterA’, and there we have it. It now represents the filter we created, and it will change if the saved filter changes. We show that you can add your own descriptions and they will appear in tooltips, so you can recognize what things come from the subfilter. We drag some other nodes on the canvas (the AddThingsToTables filterNode as mentioned earlier and some other ones so the filter will actually work) and connect it to the FilterA node. We save this filter as ‘FilterB’.
Now we go back to our filterA by double-clicking the filterNode. We needed to do this, because our FilterB had an error that said ‘FilterNode with FilterA still has errors’. It opens up in a new tab, and we indeed see we left one error when we saved it. Therefor we need to change FilterA. So we change filterA, and we notice that FilterB only changes when we SAVE the changes to filterA (the filterNode holds a reference to the saved file, not the current version of the filter in the editor). So we show you that it’s annoying that you need to reconnect the nodes to filterA everytime something changes on it’s inputs or outputs. Therefor we made sure that you do not have to reconnect manually if nothing changes on the inputs and outputs. So you can change the operations of filterA, and nothing will happen inside filterB. As an example we added the operation ‘show a message box’, save it, and we notice that in filterB everything remained connected. You’ll want to remember we added the ‘show a message box’ operation.
We are done with the filter, so we show you the unknown AddThingsToTables filterNode very fast, and see there is also a subfilter inside the subfilter (which works recursively).
Now we go the viewer, to use our filter. We open FilterB, and add it to the total environment. We apply all filters, we get the messagebox with the number of things we’re going to add (this is shown because of the ‘show a message box’ operation!), and now we indeed have alot of new items on the tables.
7. More Information
If the subject or results got your attention, you can find way more information by following the links below:
Project Report. This contains all technical details on our project, as well as the subsystems and the way we covered the encountered problems. In the report, you will find all sub-reports including RAD, SDD etc. Note that the document is written entirely in Dutch.
Project Presentation. These are the slides we used for the final presentation. You will not be able to view the video’s in it, but you can find them on this page.
Contact. Here you can find the personal page of the one you can contact to get more information.