Everyday 3D

Creative use of technology // A blog about 3D Flash and Actionscript by Bartek Drozdz

Woodbots, an interactive installation

For the past 5 moths I have been working with North Kingdom on an interactive installation called Woodbot Pilots. I’m happy to announce that it had been launched last week!

It’s located at the Skellefteå Airport in Northern Sweden. If you happen to be in the area, make sure to check it out. However, as I imagine, it isn’t a location easily accessible to most of my readers, so I will be posting more pictures & videos as they appear.

UPDATE 28.01.2011 Here’s a video made by guys over at Interactive Institute in Umeå. The also published an article that you can read here.

Together with North Kingdom we are also working on a small website dedicated to the project. It will go live soon. In the meantime there’s a nice article from the opening ceremony in the local newspaper, Norran, where you can see Mr. Robert Lindberg, the director of Skellefteå Airport doing the first run.

Woodbot Pilots is a gestures controlled racing game. We display it on a huge 82″ HD touch screen (191 x 123 cm!) and a special 3D depth camera is used to read the gestures. The camera was developed by a company called Fotonic and is somehow similar to MS Kinect but has a bigger range (up to 7m) and is optimized for industrial environments.

The talented artists from Ars Thanea and North Kingdom created beautiful visuals and the sound engineers from Dinamhoe added a great soundtrack. The game itself was developed in the Unity3D engine. We connected the 3D camera using a C/C++ plugin developed by programmers over at Interactive Institute in Umeå who did a fantastic job – it runs very smoothly.

The game logic is implemented in C# – quite some code in there, even though the game concept is relatively simple. Thanks to a powerful graphic card (XFX Radeon HD 5870 1GB GDDR5) the thing runs at 60 FPS in full HD resolution which is quite amazing!

I will talk about the technical details in a future article. For the moment enjoy some pictures of the race track, and Happy Christmas everyone!

Also, make sure to check out this article on North Kingdom’s website – there are a lot of pictures of the installation itself.

C# events and Unity3d

Did you know that C# has a built-in event system? And a very good one! It can be quite useful with Unity3D. Here's an example.

In order to respond to events dispatched by a GameObject you typically would create a script that extends MonoBehaviour and implement the methods you need. So if you want to react to the user hovering the object with the mouse you would create the OnMouseOver method. It would typically look something like this:

C#:
  1. void OnMouseOver () {
  2. renderer.material.color = Color.red;
  3. }

That works fine. But what if you want another object to be notified about that event? One way would be to keep a reference to that other object in your script and call it from within your method:

C#:
  1. public MyScript myScript;
  2. void OnMouseOver () {
  3. myScript.NotifyMouseOver();
  4. }

This also works fine, but you always need to keep a reference to the object you notify. Also, you can only notify this object, unless you keep more references to other object. This can quickly get messy.

Messages

Another solution would be to use SendMessage or SendMessageUpwards methods. While they seem to be the right tool for the job, these methods have several major flaws, and in my opinion you should completely avoid using them.

Their syntax is awkward to start with, and you need to pass method names as string literals - which is very error prone! Also, those methods work only within the object's transform hierarchy. You can invoke methods on scripts that are either attached to the same GameObject or to one of it ancestors.

Events

Fortunately there is a better way to solve this problem, and this is with the C# built in event system. I can't explain how the event system works in detail, but if you are interested on learning more on this topic, go and check the tutorial on MSDN.

Now, let's see how to use events in Unity3D. Consider this script:

C#:
  1. using UnityEngine;
  2. public class EventDispatcher : MonoBehaviour {
  3. public delegate void EventHandler(GameObject e);
  4. public event EventHandler MouseOver;
  5. void OnMouseOver () {
  6.     if (MouseOver != null)
  7.         MouseOver (this.gameObject);
  8. }
  9. }

Don't worry if you don't know exactly what it does. What's important is that once you attach it to a GameObject you can go to another script (any script in your project!) and if you have a reference to that object you can write something like this:

C#:
  1. private GameObject s;
  2. [...]
  3. s.GetComponent<EventDispatcher>().MouseOver += Listener;
  4. [...]
  5. void Listener(GameObject g) {
  6.    // g is being hovered, do something...
  7. }

This approach is more flexible than using messages, because it works with any script not only with those that are in the same transform hierarchy. If you keep a Singleton object that manages the state of the application, you could listen to events coming from any GameObject in it. Of course not only a GameObject can send events - any object can.

One of the consequences of such setup is that the same listening function can be used to respond to events coming from different objects. By passing a reference as argument you always know which object dispatched the event - this is what I do in the example.

References, controllers and MVC

In the first scenario above you needed to keep a reference to the listener in the object that sends the event, and I said it's not a good idea. In the version which uses the built-in events, it needs to be the other way around - you need a reference to the object that sends the event in the object that listens to it. How is it better, you might ask?

First of all, here, the sender doesn't know who is listening to the events is sends - and even how many listeners there are. All it does is to send the event and forget. In the first scenario above, imagine how cumbersome it would be to tell the sender to stop notifying the listener!

With the event system, it's the listener that has the responsibility to decide what events it listens to, when to start, and when to stop listening to them. Such object usually manages the state of the application or executes some game logic. To borrow the term from the MVC design pattern - it's the controller. That is why it's perfectly logical to give him such responsibility. In that way, using events creates more solid code.

Finally, I love the overloaded += operator used to add a listener, it's so clean! As you might have guessed by now, when you are done listening to the event you can just say:

C#:
  1. s.GetComponent<EventDispatcher>().MouseOver -= Listener;

Of course you can create a generic EventDispatcher class that implements all events that a GameObject can send - here's a version that implements a few of them already. By looking at the code, I'm sure you can figure out how to add others. However, beware of implementing OnGUI that way! (if you want to know why, read this post).

Unity3D training

Hands-on Unity3d, 21-22 Oct 2010

I'm proud to announce, that I will be running a 2 day training in London later this month. I will be teaching Unity3D, showing how to use the editor and how to work with various assets. I will be also giving an introduction to scripting in C# and hopefully we will be able to cover some features of the latest release of the editor.

Unity3D version 3 has been released only a few days ago. The new version is packed a tremendous amount of new and cool features. Great games & other projects are created with Unity3D every day, so there has never been a better moment to start learning it!

You can read all the details about the training on the LFPUG page, who is also the organizer of the session. Unfortunately, the tickets have been sold out. However, if you would like to learn some Unity3D, please contact me (bartek [at] everyday3d.com) or Tink (training [at] lfpug.com). We are pretty excited about the interest people are showing for this topic, so currently we are planning to run another session in London in November and there are still a few places left on the list.

I got a couple of requests to run such a training in other places, so hopefully I will be bringing some Unity3D goodness to other cities in Europe as well. I'm working out the details, and I'll keep you posted. If you would be interested in hosting a Unity3D training session in your city, please let me know!

Loading 3d models at runtime in Unity3d

IMPORTANT UPDATE! With Unity 3 there were some changes in the API and code described below doesn't work. Here's a new version, that works with Unity 3: obj (v1.2). Now, instead of creating a new object, attach the OBJ script to a game object and add the path to the .obj file in the inspector.

This post is an addition to the last series I wrote about dynamic content loading in Unity3D.

When building a dynamic application, every now and then you might need to load some 3d models at runtime. Either because there's a database with models you want to use or just because you want someone to update the models without rebuilding the project. I actually had this situation a few weeks ago. Surprisingly, this option does not come with Unity out of the box.

Asset bundles and resource folders

But first thing first. I said there's no ready-to-use way to load 3d models at runtime, but it's not 100% true. In fact, there are two options: asset bundles and resource folders. These methods are discussed in depth here.

They can both be useful in some cases, but they both have one fundamental drawback: in order to create them, someone needs to open the project in Unity, import the 3d models, create the bundles or resource folders and then export the whole thing again. To create an AssetBundle you need to run a script in the editor, while the Resource Folders... honestly, I failed to even make them work!

In brief, it's all too complicated for what I was looking for.

A straightforward solution

What I needed and wanted was easy and simple: to load a 3d object (geometry + some materials and textures) at runtime, using just a URL as parameter. The only solution seemed to write my own importer.

Basically, I had the choice between Collada and Wavefornt OBJ. I would choose OBJ any time of the day because it's a simple, concise plain-text format, while Collada is bloated and is XML-based.

It's not that I hate XML (although I'm not a big fan either) but in order to parse XML you need to include a pretty weighty DLL in your *.unity3d file, around 850Kb, which in this case (and in many others) defeats the purpose. Still, it's good to know that it possible, and there are situations when it's ok to use it. If you want to learn more about Unity3D and XML there's a awesome article on this topic by Paul Tondeur.

It turned out that while it's not rocket science to write an OBJ importer, it's not exactly banal either. I spent a few days coding it so I thought I'll share this with everyone - maybe someone will make good use of it.

Here's a package with the source code (v1.1) (or a version that works in Unity 3 (v 1.2)), along with a simple scene demonstrating how it works. In fact it couldn't be simpler. All you have to do is to create an instance of the OBJ class and start a coroutine to load the contents, like this:

C#:
  1. string path = "http://www.everyday3d/unity3d/obj/monkey.obj";
  2. OBJ obj = new OBJ();
  3. StartCoroutine(obj.Load(path));

Supported features

  • Vertex, normals and UV data
  • Multiple objects per file
  • Vertex groups and multiple materials per object
  • MTL files, diffuse and specular materials
  • Basic textures

And it's all at a cost of ~12Kb extra added to your final file!

Testing and the universality of OBJ format

In the 3D world the OBJ format is nearly universal - I think that every 3D editor in existence is able to export to this format. This also means that Wavefront files come in many different flavors.

I tested the code against models created with Blender and against common sense assumptions on how an OBJ file can be constructed. If it doesn't work with files exported from your editor send me the OBJ file, and if possible I'll update the code. It's released under the MIT license so feel free to use it in your projects, commercial or not.

That's it! I hope you'll find it useful!

Runtime objects in Unity3D

Unity3D can work with meshes created in external 3D editors, but geometry can also be created with code. And not only geometry, but materials and textures as well. To test all these options I created a simple cityscape. I got inspired by this set of awesome pictures and also by a project called Pixel City by Shamus Young.

Creating meshes

All information about the geometry of an object is stored in the Mesh object inside the MeshFilter component. A mesh is composed of an array of vertices grouped into triangles and with UV information added to it. It's a pretty common way to store information on 3d geometry, similar to what you can find in Actionscript - Graphics.drawTriangles expects arguments in the same data format. Many file formats out there store meshes that way too, ex. Wavefront OBJ (which makes writing importers/exporters relatively easy by the way).

Creating a mesh with code means populating the arrays of vertices, triangles and UVs. While it is pretty straightforward, even building a simple cube can be tricky and the code quickly becomes a unmanageable list of numbers. In the source code, the buildings are generated in the BuildingBuilder.cs file, so you can see it for yourselves.

Creating textures

We've already seen that any bitmap you import into a Unity3D project is represented by the class Texture2D. Of course, bitmaps don't have to be imported - they can be created from scratch. The constructor of the Texture2D class take a few arguments, including the width and height of the image.

Once a new texture is created all it's pixels are empty (i.e. black and transparent). Their values can be changed either on a pixel-per-pixel basis using the SetPixel method or by copying portions of other bitmaps using SetPixels.

In the above example I have 6 predefined textures with different types of windows, so I don't create those from scratch. However I use a procedural texture for the illumination maps. I generate a 64x64 bitmap where the value of each pixel determines the brightness of a single window (i.e. how much light it emits). It's pretty basic: after the Texture2D is created I just run through all it's pixels and assign a random value to it's alpha component.

Creating materials

There are 6 different textures representing a different type of window each and one illumination map. How to put these together? That's what materials are used for. As with any other element, materials are represented by the Material object in scripts, and they can be created with code. The constructor takes only one argument: a shader.

Shaders are one of the most crucial elements of Unity3D (and any other 3D rendering engine for that matter). They describe how a 3D geometry will be rendered, what colors and/or textures will be used and how it will interact with light. For the buildings I use a shader called Self-Illuminated Diffuse. It's one of Unity3D built-in shaders.

Shaders usually need some parameters to work with - like colors or textures. A material is essentially a shader and a number of objects that define it's parameters. Self-Illuminated shaders expect one texture for the color and the other that determines the amount of light emitted by this texture. It's great for creating objects that emit light like bulbs, neon signs or... windows in a night scenery (it's important to understand however that the object emits light but this light doesn't illuminate any other objects around it).

I use the window image as the color texture, and the procedural image with random alpha values as the illumination map texture. The trick is that I set the scale of the color texture to 64. This way the window is repeated 64x64 times on the material and each pixel of the procedural illumination map (scaled 1:1) corresponds to one single window. I also set the filtering mode of the illumination map texture to Point, so that it doesn't get blurred when seen form a bigger distance.

A word on optimization

The generated buildings have different width, height and depth. A natural solution to apply textures on all of them was to create a material that repeats the windows the appropriate amount of times for each building. Ex. a 4 story building with 3 windows in a row would have a material where the x-scale of the texture is set to 3 and y-scale to 4. The emission map scale needs to be divided by 64 in this case, giving values of 3/64 and 4/64 respectively.

While this seems quite ok, it poses an optimization problem. Unity3D is much more effective when there's a lower amount of meshes composed of large amount of vertices, rather that the other way around - lots of meshes with few vertices. One building has 20 vertices and I create 2500 separate meshes! It's far from optimal, and you can really feel the framerate going down because of that. Fortunately there is a built-in script called CombineChildren that automatically combines all the buildings into one huge mesh making everything work much faster and smoother. But (of course) there is a trick!

Unity3D will combine objects only if they share the same, exact material. The scale of a texture on a material is unique, so if there are two materials that are identical and the only difference is the scale of the texture, we still need 2 different materials. In the above scenario almost each building uses a different material, unless it has exactly the same number of stories and the same number of windows in a row. I had to come up with a way to use only one material, and to deal with texture coordinates in a different way.

The answer is to use UVs instead of the texture scaling. So I started by creating only one material, which contains 64x64 windows. If a building is ex. 20 stories high and has 6 windows in a row, this means that the wall of the building needs to be mapped to the texture with this coordinates [0, 0, 6/64, 20/64]. Remember that UV values are normalized, i.e have values between 0 and 1, 0 pointing to the left/top pixel of the texture, and 1 to the right/bottom.

This way I can reuse the same material on every building regardless of it's size. It works even on buildings that are higher that 64 stories, because UV values are repeated - ex. an UV value of 1.2 is the same as 0.2. Perfect!

One little problem still persist though. Since each building uses the same material it also has the same pattern of lit and unlit windows. It doesn't look nice. Fortunately there was an easy solution for this: to offset the UVs of each building by a random value multiplied by 1/64. That way each building is mapped to a different area of the of the material and things look more natural.

Effects

To make the cityscape more interesting I added a Glow image effect to the camera. It adds a subtle glow around lit areas of the scene - in this case the windows, giving it a slightly blurry look.

Source

You can grab the package with the source code here.

3 ways to draw 3D lines in Unity3D

Just as I was thinking about an interesting demo to play with drawing functions in Unity3D, Mrdoob published his Harmony drawing tool made with HTML5/Canvas. It looks really cool, so I though how about doing this in 3D? I only had to figure out how to draw lines.

I did some research and below I present 3 different solutions. You can grab the source of the examples discussed below here.

Drawing lines with Line Renderer [demo]

When it comes to lines, the first thing you'll bump into in the Unity3D API is the Line Renderer component. As the name suggests, it is used to draw lines so it seems the right tool for the job. Lines in this case are defined by 2 or more points (segments), a material and a width.

It has an important limitation: the line must be continuous. So if you need two lines, you need two renderers. The other problem is that the Line Renderer acts very strangely when new points are added dynamically. The width of the line does not seem to render correctly. It's either buggy or just wasn't designed for such use. Because of these limitations I had to create a separate Line Renderer for each tiny bit of line I'm drawing.

It was easy to implement, but not very fast since I end up spawning lots of GameObjects each with a LineRenderer attached. It seems to be the only option if you don't have Unity3D Pro though.

Drawing lines as a mesh using Graphics [demo]

The Graphics class allows to draw a mesh directly without the overhead of creating game objects and components to hold it. It runs much faster than Line Renderer, but you need to create the lines yourself. This is a bit more difficult but also gives you total control of the lines - their color, material, width and orientation.

Since meshes are composed of surfaces rather than lines or points, in 3D space a line is best rendered as a very thin quad. A quad is described with 4 vertices, and usually you'll only have the start and end points and a width. Based on this data you can compute a line like this:

C#:
  1. Vector3 normal = Vector3.Cross(start, end);
  2. Vector3 side = Vector3.Cross(normal, end-start);
  3. side.Normalize();
  4. Vector3 a = start + side * (lineWidth / 2);
  5. Vector3 b = start + side * (lineWidth / -2);
  6. Vector3 c = end + side * (lineWidth / 2);
  7. Vector3 d = end + side * (lineWidth / -2);

First, you get the normal of the plane on which both start and end vectors lie. This will be the plane on which the line-quad will located. The cross product of the normal and of the difference between end and start vectors gives you the side vector (the "thin" side of the quad). You need to normalize it to make it a unit vector. Finally calculate all 4 points of the rectangle by adding the side vector multiplied by half width to both start and end points in both directions. In the source code all this happens in MakeQuad and AddLine methods, so take a look in there.

It wasn't easy to implement, but once I was there it runs pretty fast.

Direct drawing with GL [demo]

No fast is fast enough! Instead of leaving this topic and live happily with the Graphics solution, I kept searching for something even better. And I found the GL class. GL is used to "issue rendering commands similar to OpenGL's immediate mode". This sounds like fast, doesn't it? It is!

Being much easier to implement that the Graphics solution it is a clear winner for me, the only drawback being that you don't have much control over the appearance of the lines. You can't set a width and perspective does not apply (i.e. lines that are far behind look exactly the same as those that are close to the camera).

Conclusion

For massive & dynamic line drawing LineRenderer is not the best solution, but it is the only one available in Unity free version. It can surely be useful to draw limited amounts of static lines and this is probably what it was made for. If you do have Unity3D Pro, the solution with Graphics is reasonable and very flexible but if it is performance you're after choose GL.



  • FATC2011


  • FITC2011


  • FITC2010


  • FITC2010