Example #1
0
    public static void SoftNormalsInTangents(Mesh mesh)
    {
        var mVerts    = mesh.vertices;
        var mTangents = new Vector4[mVerts.Length];
        var mTris     = mesh.triangles;

        Dictionary <Vector3, SoftNormal> vertDict = new Dictionary <Vector3, SoftNormal>();

        for (int i = 0; i < mTris.Length; i += 3)
        {
            int i0 = mTris[i];
            int i1 = mTris[i + 1];
            int i2 = mTris[i + 2];

            var v0 = mVerts[i0];
            var v1 = mVerts[i1];
            var v2 = mVerts[i2];

            Vector3 dir = v1 - v0;
            Vector3 tan = v2 - v0;

            if (dir == Vector3.zero)
            {
                continue;
            }
            if (tan == Vector3.zero)
            {
                continue;
            }

            var normal = Vector3.Cross(tan, dir).normalized;

            float dirLength = dir.magnitude;

            float height = Vector3.Dot(tan, Vector3.Cross(dir / dirLength, normal));

            float area = (dirLength * height) / 2f;

            normal *= area;

            Vector4 tangent = new Vector4(normal.x, normal.y, normal.z, 0);

            for (int j = 0; j < 3; j++)
            {
                SoftNormal softNormal;
                int        vertIndex = mTris[i + j];
                Vector3    vert      = mVerts[vertIndex];
                if (!vertDict.TryGetValue(mVerts[mTris[i + j]], out softNormal))
                {
                    softNormal = new SoftNormal();
                    vertDict.Add(vert, softNormal);
                }
                if (!softNormal.indexs.Contains(vertIndex))
                {
                    softNormal.indexs.Add(vertIndex);
                }
                softNormal.normal += tangent;
            }
        }

        var softNormals = vertDict.Values;

        foreach (var softNormal in softNormals)
        {
            for (int i = 0; i < softNormal.indexs.Count; i++)
            {
                mTangents[softNormal.indexs[i]] += softNormal.normal;
            }
        }

        for (int i = 0; i < mTangents.Length; i++)
        {
            mTangents[i] = -mTangents[i].normalized;
        }
        mesh.tangents = mTangents;
    }
Example #2
0
    /// Credit to:
    /// · https://stackoverflow.com/questions/45477806/general-method-for-calculating-smooth-vertex-normals-with-100-smoothness
    /// · Oskar Stålberg (@OskSta)
    public static void SoftNormalsAsColors(this Mesh mesh)
    {
        var tris  = mesh.triangles;
        var verts = mesh.vertices;
        var tans  = new Vector4[verts.Length];

        var dicVerts = new Dictionary <Vector3, SoftNormal> ();

        for (var v = 0; v < tris.Length; v += 3)
        {
            int i1 = tris[v + 0];
            int i2 = tris[v + 1];
            int i3 = tris[v + 2];

            // p1, p2 and p3 are the points in the face
            var p1 = verts[i1];
            var p2 = verts[i2];
            var p3 = verts[i3];

            // Calculate normal of the surface using edges
            var edge1 = p2 - p1;
            var edge2 = p3 - p1;

            if (edge1 == Vector3.zero)
            {
                continue;
            }
            if (edge2 == Vector3.zero)
            {
                continue;
            }
            var n = Vector3.Cross(edge1, edge2).normalized;

            // Get the angle between the two other points for each point
            var angles = new float[3];
            angles[0] = Vector3.Angle(p2 - p1, p3 - p1);               // p1 is the 'base' here
            angles[1] = Vector3.Angle(p3 - p2, p1 - p2);               // p2 is the 'base' here
            angles[2] = Vector3.Angle(p1 - p3, p2 - p3);               // p3 is the 'base' here

            // Store the weighted normal in an structured array
            var tangent = new Vector4(n.x, n.y, n.z, 0f);
            for (var i = 0; i != 3; i++)
            {
                SoftNormal softNormal;
                int        vertIndex = tris[v + i];
                var        vert      = verts[vertIndex];

                if (!dicVerts.TryGetValue(vert, out softNormal))
                {
                    softNormal = new SoftNormal();
                    dicVerts.Add(vert, softNormal);
                }
                if (!softNormal.indexs.Contains(vertIndex))
                {
                    softNormal.indexs.Add(vertIndex);
                }

                softNormal.normal += tangent * angles[i];
            }
        }

        //okay
        foreach (var softNormal in dicVerts.Values)
        {
            foreach (var index in softNormal.indexs)
            {
                tans[index] += softNormal.normal;
            }
        }

        var colors = new Color32[tans.Length];

        // Normalize sum
        for (int i = 0; i != tans.Length; i++)
        {
            tans[i] = tans[i].normalized;
            // Get corresponding color
            var color =
                new Color32
                (
                    // Tranform to range [0,1] and then [0,255]
                    (byte)(((tans[i].x + 1) / 2) * 255),
                    (byte)(((tans[i].y + 1) / 2) * 255),
                    (byte)(((tans[i].z + 1) / 2) * 255),
                    1);
            colors[i] = color;
        }
        // Save to mesh
        mesh.colors32 = colors;
    }