Posted by: Morten Nobel-Jørgensen | December 25, 2010

Procedural generated mesh in Unity


In this blog I’ll show how to create a mesh procedurally in Unity. This includes winding order, normals and how to expose your mesh factory to Unity using editor script.

One of the best features of Unity is how smooth the asset pipeline works where 3D models flows seamless from any 3D program into to the Unity scene editor. So why would you create meshes inside Unity? Actually there is a number of reasons:

  • Additional basic shapes can be used to mock-up a level. Unity already has some basic shapes (Cube, Sphere, Capsule, Cylinder and Plane), than can be used for creating a test-level without needing to open another tool. But why stop here? What about other often used shapes such as staircases, pyramids or cones.
  • Creating level design procedurally. Unity 3 already includes a tree editor, but you can easily create scripts that creates cities, characters and other game props procedurally.
  • The last reason for creating meshes procedurally is that it is fun. And by creating scripts that generates meshes, you’ll learn a lot about how Unity handles meshes internally.

Understanding the structure of a mesh

Tetrahedron

A polygon mesh in Unity is created of triangles. The most simple 3D shape is a Tetrahedron – a simple 4 sided shape.

The mesh consist of an array of vertices and indices:

The vertices are Vector3 positions and the triangle faces indices are integers (The illustration above uses one based index, but Unity uses zero based indices). The Tetradron is created by 4 triangles. The first triangle has the vertex indices 1-2-4 (the vertices P1, P2, P4). The triangle must be defined using clockwise polygon winding order – this is used for backface culling  (usually only the frontside of every triangle is draw).

By using shared vertices, with each vertex referenced multiple times, a mesh can be created very compact.

The source code for creating a simple Tetrahedron is:

MeshFilter meshFilter = GetComponent();
if (meshFilter==null){
	Debug.LogError("MeshFilter not found!");
	return;
}

Vector3 p0 = new Vector3(0,0,0);
Vector3 p1 = new Vector3(1,0,0);
Vector3 p2 = new Vector3(0.5f,0,Mathf.Sqrt(0.75f));
Vector3 p3 = new Vector3(0.5f,Mathf.Sqrt(0.75f),Mathf.Sqrt(0.75f)/3);

Mesh mesh = meshFilter.sharedMesh;
if (mesh == null){
	meshFilter.mesh = new Mesh();
	mesh = meshFilter.sharedMesh;
}
mesh.Clear();
mesh.vertices = new Vector3[]{p0,p1,p2,p3};
mesh.triangles = new int[]{
	0,1,2,
	0,2,3,
	2,1,3,
	0,3,1
};

mesh.RecalculateNormals();
mesh.RecalculateBounds();
mesh.Optimize();

Shared vertices

The code above creates the correct shape, but it has one serious problem. If you create a tethradron in Unity, you will notice that the shading is wrong (see screenshot ‘Shared vertices’). The problem is that the shading uses the vertex normals – and there is one vertex normal for each vertex (The normals are the red line segments – this is rendered using the MeshDisplay component). The normals are calculated using the face normals (using the method RecalculateNormals() ). In this case we want sharp edges and do not want to share vertex normals. This can be done by not sharing the vertices. If you are creating a mesh without sharp edges, you should use shared normals.

Unique vertices

The following shows the source code without shared vertices. This means that each corner of the shape has three vertices (one for each normal). This creates the hard edges we want for this shape. On the screen shoot to the right you can see the three normals at each corner.

Source code for unique vertices:

MeshFilter meshFilter = GetComponent();
if (meshFilter==null){
	Debug.LogError("MeshFilter not found!");
	return;
}

Vector3 p0 = new Vector3(0,0,0);
Vector3 p1 = new Vector3(1,0,0);
Vector3 p2 = new Vector3(0.5f,0,Mathf.Sqrt(0.75f));
Vector3 p3 = new Vector3(0.5f,Mathf.Sqrt(0.75f),Mathf.Sqrt(0.75f)/3);

Mesh mesh = meshFilter.sharedMesh;
mesh.Clear();

mesh.vertices = new Vector3[]{
	p0,p1,p2,
	p0,p2,p3,
	p2,p1,p3,
	p0,p3,p1
};
mesh.triangles = new int[]{
	0,1,2,
	3,4,5,
	6,7,8,
	9,10,11
};

mesh.RecalculateNormals();
mesh.RecalculateBounds();
mesh.Optimize();

Tetrahedron GUI

To add the Tetrahedron object to the GameObject menu in Unity, create a script in the a folder called ‘Editor’ (every script in an Editor folder allows interaction with the Unity Editor).
In this script, create a static function with the annotation MenuItem. This will add the method as a menu item in Unity.

using UnityEngine;
using UnityEditor;

public class TetrahedronEditor : Editor {
	[MenuItem ("GameObject/Create Other/Tetrahedron")]
	static void Create(){
		GameObject gameObject = new GameObject("Tetrahedron");
		Tetrahedron s = gameObject.AddComponent();
		MeshFilter meshFilter = gameObject.GetComponent();
		meshFilter.mesh = new Mesh();
		s.Rebuild();
	}
}

The full source code for this project can be found at GitHub:
https://github.com/mortennobel/ProceduralMesh
This includes a simple UV mapping as well as a custom editor for the Tetrahedron component.

Part 2 of this article can be found here:
https://blog.nobel-joergensen.com/2011/04/05/procedural-generated-mesh-in-unity-part-2-with-uv-mapping/

Advertisement

Responses

  1. This is really a piece of quality information! I love your blog!
    Solid work!
    Cheers,

  2. Excellent article, thank you for sharing all this info. I changed my plane generating methods to incorporate this method, very useful indeed. I like your articles because they are descriptive and concise. If you feel like it, I would be very interested in seeing articles describing the use of submeshes, bindposes, tangents and uv’s. Regarding uv’s, the code provided is useful but a description of their tricks and concepts (like the brilliant description of the shared vs unique normals) would be much appreciated. Thanks !

    • Thanks for the feedback. I’ll write some more blog posts about the topic soon 🙂

  3. Thanks for the tutorial! The triangle faces picture/table should, on the third line, read 324 instead of 314 though. 😉 had me mighty confused there.

  4. Nice article.

  5. Hi! For the triangles, since they have to be in counterclockwise, would it be 143 instead of 134 and 342 instead of 324

  6. Hmm actually Unity is a left-handed coord system, so I guess your tris are actually left-hand rule order?

  7. Doh, wish I found this article before I bashed my head trying to procedurally create planes. Still helped me figure out what was wrong with my triangle winding order – Thank you very much.

  8. Hi thanks very much for this. I am getting errors with the scripts on this page in unity 3.3.

    the first one gives me: “something poligon contains more than 255 something”

    Second one sais:
    Assets/ART mixed/tetrahedron2.cs(1,12): error CS0116: A namespace can only contain types and namespace declarations

    Third one, Editor sais:
    “Assets/Editor.cs(14,36): error CS0411: The type arguments for method `UnityEngine.GameObject.AddComponent()’ cannot be inferred from the usage. Try specifying the type arguments explicitly”

    The Tetrahedron.CS compiles ok but i cant see any tetrahedron when i drag the script to an empty gameobject.

    I feel like the very stupid on in the maths class that doesnt undestand anything :/

    • Your problems are unrelated to Unity 3.3. The first issue you have I cannot reproduce. Your second issue: You must have renamed a file, the github project does not contain any tetrahedron2.cs – Maybe that is the same issue for the third problem. There was a issue with dragging the script to a game object – I have updated the sourcecode in the github project and on this page.

      • Thanks Morten, I am very keen to do this!!!

        I have managed to add “Tetrahedron.cs” to an empty GameObject (it doesnt say i should but i presume yes?) and it’s fine except that the Tetrahedron is invisible.

        Also i tried to create a script called Editor, i tied to put it in a folder called Editor, and i tried also to put a script in C:/Unity/Editor but i couldnt figure which to do! the first option said

        “Namespace Tetrahedron couldnt be found”

        here is a picture of my attempt, if it amuses you!

        [IMG]http://i54.tinypic.com/1412x6r.jpg[/IMG]

      • The editor scripts should be located in the project in a folder in the $project$\Assets\Editor – not in the Unity installation. (Actually just download the full source code from git-hub and extract the directory structure in any Unity project folder (under Assets)). After this is done you can now rebuild the Tetrahedron using the new button below the script (see this image: http://i53.tinypic.com/i3b4w3.png )

      • Thanks!!! i found it ! i was making some procedural terrain for my cousins game engine and coming from an audio DSP field i know alot about how to randomise sines, multiply them in 3d graphs, make pointy, round, sine, canyon, crater derivatives of sines etc. so i hope i can make some good terrains in unity based on maths. i couldnt find any pics of all the variety of terrains i did for my cousin cos my dell is kaput. here is 2 pics.

        [IMG]http://i56.tinypic.com/2gslw7q.jpg[/IMG]
        i just am figuring a code framework to imput giant trigo based maps into tiles and add overhangs on them, caverns, it’s very technical thou. but if i get there one day 8))

        thansk!

  9. Morten, thanks for the amazing post – it is a great piece of writing. Just adding my thanks to your many fans!

  10. Note — this page is amazing. Just note there might be a small error relating to the winding:

    (1) It looks like some of the winding is the wrong way…all four should be the same.

    124 .. CCW
    134 .. CW
    324 .. CW
    132 .. CCW

    (2) The text reads “The triangle must be defined using counter clockwise polygon winding order ”

    In Unity3D, it must be CLOCKWISE, as seen from the OUTSIDE. For example un the Unity doco:

    http://unity3d.com/support/documentation/Manual/Using%20the%20Mesh%20Class.html

    “An important detail of the triangles is the ordering of the corner vertices. They should be arranged so that the corners go around clockwise as you look down on the visible outer surface of the triangle…”

    Hope it helps someone!

  11. Hi ! Thank you very much for this great tutorial ! It really helped us understand the basics of procedural meshes…
    Best Regards,
    Spigoule

  12. Thanks for the read!

    I have saved generated meshes into asset files before, but I am not sure how to save multiple sub-meshes into a single “.asset” file. I would like to be able to programmatically assign them to `MeshFilter` components. In the editor this is easy because they can simply be dragged in.

    I figure, there must be a way to do this within a script. Are you able to offer any pointers?

    i.e.

    // Somehow save multiple sub-meshes to an asset
    // …

    MeshFilter filter = go.GetComponent();
    filter.sharedMesh = myMeshAsset ??? GetSubMesh(1);

    Cheers!

  13. […] https://blog.nobel-joergensen.com/2010/12/25/procedural-generated-mesh-in-unity/ […]

  14. I’ve got a problem, not yet assimilated how to make the UVs of a cube here is the code can someone help me?

    using UnityEngine; using System.Collections;

    [RequireComponent (typeof (MeshCollider))] [RequireComponent (typeof (MeshFilter))] [RequireComponent (typeof (MeshRenderer))]

    public class Create_Cube : MonoBehaviour {

    public Color ColorBloc; public Texture2D Textura;

    // Use this for initialization void Start () {

    Mesh mesh = new Mesh ();
    mesh=GetComponent().mesh;
    Vector3 p0 = new Vector3(0,0,0); Vector3 p1 = new Vector3(1,0,0); Vector3 p2 = new Vector3(0,1,0); Vector3 p3 = new Vector3(0,0,1); Vector3 p4 = new Vector3(1,0,1); Vector3 p5 = new Vector3(1,1,0); Vector3 p6 = new Vector3(0,1,1); Vector3 p7 = new Vector3(1,1,1);

    mesh.vertices = new Vector3[]{p0,p1,p2,p3,p4,p5,p6,p7};
    mesh.triangles = new int[]{ 0,2,1, 1,2,5, //face 1 3,0,1, 1,4,3, //face 2 0,3,2, 2,3,6, //face 3 1,5,4, 5,7,4, //face 4 6,3,4, 6,4,7, //face 5 6,5,2, 7,5,6 //face 6 };

    //mesh.uv = new Vector2[]{new Vector2(0.0f,0.0f),new Vector2(1.0f,0.0f),new Vector2(0.0f,1.0f),new Vector2(0.0f,0.0f),new Vector2(1.0f,0.0f),new Vector2(1.0f,1.0f),new Vector2(0.0f,1.0f),new Vector2(1.0f,1.0f)};

    mesh.uv = new Vector2[]{
    new Vector2(0,0), new Vector2(0,1),

    new Vector2(1,0),new Vector2(0,1),

    new Vector2(1,1), new Vector2(0,0),

    new Vector2(0,0), new Vector2(1,0)
    };

    renderer.material = new Material(Shader.Find(“Diffuse”));
    renderer.material.mainTexture = Textura; renderer.material.color = ColorBloc;

    mesh.RecalculateNormals(); mesh.RecalculateBounds (); mesh.Optimize();

    } // Update is called once per frame void Update () {

    } }

  15. Nice info’s!
    So the barrier stopping us from making more complex and interesting shapes are finding algorithms to organise all the arrays of UV’s and vertices for advanced geometrical objects. for example, a great way to make geometrical objects is to to cut the object into hundreds of parralel slices, and drawing 2d triangles, hexagons, squares, sine based 2d outlines, metaball slices… and making and procedural mesh gen wrapper that takes the simple process of varying a 2d outline on a a sequence of planes, and applying vertices to approximate the outline and join each outline to the next, to make shapes that evolve in the 2d and 3rd dimention.
    It’s alot easier to code a long sequnce of varying 2d shapes and join them together than it is to make a 3d mesh from scratch. and it gives you massive power of control. then it should be eaiser to make tubes, trees, spirals, tunnels…
    i wish i know how to code well enough to make a wrapper that assigns a 3d mesh to an algorithm to a series of evolving outlines in 2 dimensions.
    😀 please god make a programmer that can do such a package!

    😀

    • I found that there is a mesh extrusion example in procedural mesh demo of unity, it’s a bunch of scripts you can download from the website, the extrusion is a bit basic, but she can take the square for example and smudge it into lots of vertices through space as it moves.

  16. hi! i’ve a problem with painting a shape. I didn’t get a 3d shape it looks like 2d. What it can be?

  17. i reckon a simple document with instructions how to use those *.cs file in unity will be most productive. As for me after creating a new blank project in unity i created a folder [mNobel] in the project panel and drag into it the Editor then created a subFolder named [cs] and drag the lot of *.cs file into it. what’s next ?
    cheers have a nice day 🙂

  18. Hello ,
    Nice post!
    Really helped me a lot for my project.
    I have one question though. I still dont understand the how the shading is wrong in the shared vertices and what unique vertices meshes are?
    Do you have any pointers on that

  19. Any way to get the mesh out of the tetrahedron procedural model? I have a Mesh array as a public variable in one of my scripts. In the inspector I can add the built in primitives as meshes to this array, but not the tetrahedron.

  20. Does anyone know how to create a hemisphere mesh? I am trying to mske a forcefield that shrinks and disappears, trying to make it look cool!!! 🙂

  21. Will it also work for collision? I.e. when I add collision shape and set it to mesh, will it collide properly?

    Also, how to add textures to such procedural meshes (i.e. for example I’d like to have eye on one of sides)?

  22. […] (英語)https://blog.nobel-joergensen.com/2010/12/25/procedural-generated-mesh-in-unity/ […]

  23. […] Hex system guideProcedural geometry in unity: Link […]

  24. […] for an alternative – I found an article in Morten Nobel’s Blog detailing how to create a tetrahedron in code (rather than importing a model) – I used the code pretty much as-is – only making […]

  25. To support collision, I added `GetComponent().sharedMesh = mesh;` just after `mesh.RecalculateBounds();` and checked on Convex. I also added a physics material, though I’m very new to unity so don’t know if this last step is absolutely necessary.

  26. That GetComponent call should be followed by MeshCollider in arrows but the blog’s sanitizer is stripping them out.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Categories

%d bloggers like this: