Everyday 3D

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

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 64×64 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 64×64 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 64×64 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.

Unity3D tutorial in .NET magazine

Recently I had the privilege to write an article for .NET magazine. It’s an introductory tutorial to Unity3D in which you’ll see how to build a car simulation in a simple desert scenery.

Those of you who had attended my sessions at FITC Amsterdam and at the March LFPUG meeting have already seen me building it live. The nice thing about Unity3D IDE and its drag & drop abilities is that you can actually create a car simulation in 10 minutes. But don’t be fooled, because tweaking it afterward takes ages – as with everything else. Anyway, now you can see and try it yourself. I hope you’ll like it!

The tutorial will lead you through different features of Unity3D like the terrain editor, 3D assets import, built-in scripts, projected shadows and particle system. It is available in the UK and elsewhere in Europe from March 30th (issue 201). It will be published in the US and Canada too, but a month later (also please note that .NET Magazine is called Practical Web Design on the other side of the Atlantic).

To make the tutorial as enjoyable as possible I put in all my modeling skills to create a nice car – a classic U.S. Army Jeep Willys. I also added a few simple scenery models like a hut and a dried tree trunk that can be used as obstacles. You can see a demo based on those models here.

A cinematic video player

Here’s a little piece I made after the image decomposer. This time I wanted to load videos instead of images. I had the idea to project them on a big screen so that the user can actually feel like he is in a movie theater. I started to play with it, I modeled a cinema interior, setup the lightning and I thought it’s pretty neat.

You can walk around the theater with cursor keys and space to jump over the seats. If you go into the corridor in the back the movie will pause (wouldn’t it be nice if that happened in real life too?). Use the left mouse button to toggle a flashlight.

Unity3D currently supports videos in Ogg Theora format only. Although it’s free, it is not very popular on the net. It’s mainly used by Wikipedia and Archive.org for the video content.

The demo works the same way as the image decomposer, which means you can append a URL to any valid Ogg video on the web and you should be able to watch it. To start, here are a few interesting movies I found:

Sita Sings The Blues, an animated film produced and directed by Nina Paley. More info…

Big Bucks Bunny, a short computer animated film by the Blender Institute. More info…

The Blob trailer, 1958 movie with Steve McQueen. Back then it was scary, today it’s funny.

The Adventures of Flash Gordon, 1955. Probably a very bad movie.

Dynamic loading of videos in Unity is easy and it’s well documented. The code is almost exactly that same as with images. I won’t publish the sources this time because there is very little code in it, on the other hand there are over 50MB of textures in a pretty big mess.

If you find (or create) an Ogg encoded video worth watching post a link in the comments.
Have fun!

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.

Loading and manipulating images in Unity3D

As I promised here's the first article exploring Unity as a 3D web application tool.

Every web application nowadays is data driven, therefore the ability to dynamically load assets is crucial. Unity3D can load plain text, images, video and sound. Since loading plain text is not so interesting, I thought I'd see how it works with an image.

Here's a little experiment I called "Image Decomposer". It loads an image passed as parameter in the URL and creates a wall of little cubes which colors are based on the pixels of the image. When you rollover the cubes they fall down slowly decomposing it, hence the name.

The code is pretty simple, you can get the source here. Below are a few things I found out while making it.

URL parameters

A very useful way to pass parameters to your swf files is to attach them as a query string in the embedding HTML, like this: flash.swf?paramA=valueA&paramB=valueB. It's a Flash classic!

The good news is that is also works in Unity. Take a look a the HTML source of the demo to see how the image URL is passed to the unity3d file. Inside Unity3D it's very easy to get access to it through a static property called Application.srcValue. It returns the whole path, including the file name and you need to parse the query string yourself. Here's a sample code in C#:

C#:
  1. string su = Application.srcValue;    
  2. string qs = su.Substring(su.IndexOf("?") + 1);
  3. char[] deli = "=".ToCharArray();
  4. string[] ps = qs.Split(deli);

The 'ps' array now contains pairs of key/values from the query string.

Loading freedom

Unity3D supports JPG and PNG format. Sadly GIFs are not supported, even animated... ;) The really nice thing is that there aren't any security restrictions when loading files from other domains. This is something that drove me crazy so many times with Flash! In Unity3D pass a valid URL and it will load the asset, it's so simple. If you don't believe me - just paste any link pointing to an image in the demo ("image" parameter in the URL) and see it for yourself.

I wouldn't expect things to be like that forever though, so use it while you can people!

Coroutines and C#

To deal with asynchronous events, like loading an external asset, Unity3D uses coroutines. They are a bit different from events in AS3, but not very much. If you are a fan of C# and want to use coroutines you may find the official documentation a bit unclear. So, first, read the official documentation here and here, and continue reading this post afterward.

What caught my attention is that to use the yield statement, the enclosing method must return IEnumerator. But all of the inherited methods in MonoBehavior, like Start(), Update() and the event handling ones return void.

Surprisingly, it turns out that you can just change the signature of any of those methods so that they return IEnumerator! If this isn't breaking OOP rules, I don't know what is. But, since it works, it's ok I guess. It's certainly not obvious. Otherwise it is possible to create a custom function that returns IEnumerator and use the StartCoroutine() method of MonoBehavior to run it.

Another thing is that with C# you need to write yield return... not just yield... The official docs being written in Javascript they tend to omit the new operator as well, and C# does not like that. So, if the docs say:

JAVASCRIPT:
  1. yield WaitForSeconds(2);

and you copy/paste this to a C# script, you need to edit this line and make it look like this:

C#:
  1. yield return new WaitForSeconds(2);

If you keep this in mind you will spare yourself some annoying compile errors.

Scaling images (or why you don't need to do this)

Once the image is loaded, it can be assigned to a Texture2D object, which is the type to store bitmaps in Unity3D. From now on it can be used as a texture for any material. For example, you can create a plane and assign it as the main texture of the plane's material or use GUI.Label to display the picture in 2D. But let's do something more interesting.

Texture2D has a few methods to extract information from the image, the most basic being GetPixel() and SetPixel(). They work exactly the same way as their equivalents in AS3 BitmapData class. The first allows to get the color of a pixel at a given coordinate, the other does the opposite.

When you start to play with these and you use images embedded in the project, make sure to select the "Is Readable" checkbox in the inspector. Images loaded dynamically are readable by default.

In the demo, no matter how big the loaded image is, the amount of cubes generated remains the same (it will adapt for different aspect ratios though). My first idea was to scale the image to something like 50x50 pixels, and then using getPixel() to fetch the color for each cube. But I found out that there isn't any function to resize an image in the API. Sure, I could write my own function, but this can get quite complex as you can see here. Fortunately there is a better way.

Texture2D has a method called GetPixelBilinear(). It uses bilinear filtering to evaluate the color of the image at a specific point defined by normalized coordinates (i.e. in 0-1 range). If the word "bilinear" sounds familiar to you it's because Photoshop also uses this algorithm to scale images. With this method the same code can be used to get pixel colors from images regardless of their size and aspect ratio:

C#:
  1. Color c1 = image.GetPixelBilinear(0,0); // always top-left color
  2. Color c2 = image.GetPixelBilinear(1,1); // always bottom-right

It's much more elegant (and faster) than scaling images!

As a side note: it would be also very easy to implement an actual resizing function using this method, in case you really need that. I'm sure that by now you can figure out how to do this :)

What's next?

The above example is simple but I hope it shows you how to get started with dynamic content. As far as images are concerned, much more is possible. By using custom shaders and render textures you can apply filter effects to images (and video). However, these features are available only in Unity3D Pro and besides, explaining it would make this post way too long. I'll do that in a separate article instead.

Unity3D: beyond games

I am not a game developer. For the last 10 years (with some short intervals) I've been working as a Flash designer and developer and I have been creating projects more or less related to advertising such as animations (including banners, that I actually enjoyed making), video sites, rich media interfaces, web applications, 3d simulations and, sometimes indeed, simple games.

I believe however, that Unity3D is much more that a game development platform, and all those kind of projects could be tackled with Unity3D as well. In some cases the result would be pretty awesome and way beyond anything we can currently dream of with Flash and Actionscript - and this kind of opportunity is what I am looking for. (In some other cases it could end up with a disaster, similar to what happens when sites that clearly require HTML are done with Flash. We will see those too, simply because errare humanum est).

Technology adoption is not as fast as we could wish. I'm sure that eventually Unity3D will become the standard for 3D applications on the web, but we're not there yet. So far it has been very successful with games for the iPhone and it starts to emerge as the tool of choice for online games. The advertising business will follow and adopt it as well. We can expect top interactive agencies and production companies to start releasing Unity3D productions soon. I hope this will happen within this or the next year. Chances are that such projects are already in the making.

The reason why this will happen is that Unity3D is versatile. It is marketed as a "game development tool", but it has numerous features that allow much more that that. It allows to integrate diversified content (2D, 3D, video, sound), has a great animation tool and a powerful scripting API to create any kind of complex logic.

As I got back from FITC Amsterdam loaded with new energy and inspiration, I decided to take a deeper look at Unity3D scripting and go at least a bit beyond the basics and beyond the "building a 3rd person shooter" scenario. As a long time Flash developer there are some problem/questions that are typical to Actionscript technology and I decided to check how similar problems can be solved with Unity3D. Here are the first few questions that came to my mind, pretty basic actually:

1. How to dynamically load an image into Unity3D and do something with it?
2. How to load a video?
3. How to draw lines, points and shapes at runtime?
4. How to generate content with code?

The questions order starts with those that have been easiest to answer. I have some more questions lined up, so this post might get updated. Anyway, in the coming days (or weeks rather) I'll be posting the solutions. I made some experiments, I have some code to share and some tips that I found on the way. See you soon!



  • FATC2011


  • FITC2011


  • FITC2010


  • FITC2010