Unity has a Clockwise winding order?

I’ve been beating my head over this, and I can’t find it anywhere in the documentation or forums. :frowning:

Can someone please confirm for me that Unity uses a CLOCKWISE winding order for determining front-facing polygons? I’ve been trying to figure it all out, and the only thing that’s working to see my mesh is to use a clockwise winding order.

Or amy I just doing it WAY wrong?

vertices[0] = new Vector3 (left, bottom, depth);
vertices[1] = new Vector3 (right, bottom, depth);
vertices[2] = new Vector3 (right, top, depth);
vertices[3] = new Vector3 (left, top, depth);

uvs = new Vector2[4];
uvs[0] = new Vector2 (0, 0);
uvs[1] = new Vector2 (1, 0);
uvs[2] = new Vector2 (1, 1);
uvs[3] = new Vector2 (0, 1);

triangles = new int[6];
triangles[0] = 0;
triangles[1] = 2;
triangles[2] = 1;
triangles[3] = 2;
triangles[4] = 0;
triangles[5] = 3;

Right?

And doesn’t most everyone else use a CCW winding order, or is that just OpenGL (by default)?

Unity uses a clockwise winding order for determining front-facing polygons.

No.

–Eric

2 Likes

Unity uses a counter-clockwise winding order. See this code where I set the indices counter-clockwise. I originally set it clockwise based on what Eric5h5 claimed, and the mesh was upside down.

static public Mesh CreateTesselatedPlane(float width, float height, int segmentsWide, int segmentsHeight, Color defaultVertexColor)
    {
        Mesh mesh = new Mesh();
        int numVerticesWide = segmentsWide + 1;
        int numVerticesHeight = segmentsHeight + 1;
        Color[] colors = new Color[numVerticesWide * numVerticesHeight];
        Vector3[] normals = new Vector3[numVerticesWide * numVerticesHeight];
        Vector3[] vertices = new Vector3[numVerticesWide * numVerticesHeight];
        Vector2[] uvs = new Vector2[numVerticesWide * numVerticesHeight];
        for (int h = 0; h < numVerticesHeight; h++)
        {
            for (int w = 0; w < numVerticesWide; w++)
            {
                vertices[numVerticesWide * h + w] = new Vector3(
                    -width / 2.0f + width * (float) w / (float) segmentsWide,
                    0.0f,
                    -height / 2.0f + height * (float) h / (float) segmentsHeight);

                normals[numVerticesWide * h + w] = Vector3.up;
                colors[numVerticesWide * h + w] = defaultVertexColor;
                uvs[numVerticesWide * h + w] = new Vector2(Mathf.Min(1.0f, (float) w / (float) segmentsWide), Mathf.Min(1.0f, (float) h / (float) segmentsHeight));
            }
        }

        int[] indices = new int[6 * segmentsHeight * segmentsWide];
        for (int h = 0; h < segmentsHeight; h++)
        {
            for (int w = 0; w < segmentsWide; w++)
            {
                int upperLeftVertex = w + h * numVerticesWide;
                int upperRightVertex = w + h * numVerticesWide + 1;
                int lowerLeftVertex = w + (h+1) * numVerticesWide;
                int lowerRightVertex = w + (h+1) * numVerticesWide + 1;

                indices[6 * (segmentsWide * h + w) + 0] = upperRightVertex;
                indices[6 * (segmentsWide * h + w) + 1] = upperLeftVertex;
                indices[6 * (segmentsWide * h + w) + 2] = lowerLeftVertex;
                indices[6 * (segmentsWide * h + w) + 3] = lowerLeftVertex;
                indices[6 * (segmentsWide * h + w) + 4] = lowerRightVertex;
                indices[6 * (segmentsWide * h + w) + 5] = upperRightVertex;
            }
        }

        mesh.vertices = vertices;
        mesh.normals = normals;
        mesh.colors = colors;
        mesh.uv = uvs;
        mesh.SetIndices(indices, MeshTopology.Triangles, 0);

        return mesh;
    }

Nope.

var m = new Mesh();
GetComponent<MeshFilter>().mesh = m;
var verts = new Vector3[] {new Vector3(5, 5, 0), new Vector3(5, 0, 0), Vector3.zero};
var tris = new int[] {0, 1, 2};
m.vertices = verts;
m.triangles = tris;

Results in:

3198466--244462--mesh1.png

Note the clockwise winding order. Reversing the triangle order to 2, 1, 0 results in:

3198466--244463--mesh2.png

Counter-clockwise is invisible from this side (rotate the view to the other side and it’s visible).

–Eric

6 Likes

The code on top turns a quad into two tris. But if you’re using SetIndices (instead of the older triangles=indices; method) you may as well use MeshTopology.Quads.

As far as winding order, I’d guess upperRightVertex is in fact not really the upper right (or something similar.)

The ordering is counter-clockwise if you are making triangles. I just did some procedural mesh generation and the faces were backwards unless I did them in counter-clockwise order.

It might be easier to think of it as the left-hand rule (similar to Unity’s left-handed rule for axises). Wrap your left-hand fingers around the verts in order, and your thumb points out the front face.

It is not. It’s clockwise. Look at the post I made above a couple of years ago; there’s pictures, code, and everything. Should not be hard to understand.

–Eric

1 Like

Ran into issues where Raknets assumptions seem somewhat valid… found that it is best to start at the highest Y vector in the triangle (in unity) and work clockwise. If you start at the lowest and work clockwise it gives you issues on occasion. Also consider if you cant get the highest to work clockwise, get the furthest to the right and work clockwise.

The best thing to do is just get the triangle, visualize the vectors inside of a clock and if its not possible to work from top → right → down → left… (priority) well… maybe try lines xD. Works well with Clockwise in mind. (also if you want to flip a triangle replace triangle item 1 with item 3 and vice versa).

ex (to flip)
Original Triangle = 3 4 5
New Triangle Flipped is 5 4 3 (where 3rd item is moved into first position, and 1st item is moved into the third position). Easy to just flip it if you are making procedural stuff or want to design your code to be able to flip the triangles.

It’s clockwise.
Link from Unity Manual
Quote:
The ordering is important because you must order the corners clockwise