Пример #1
0
        private void RecalculateNormals(Mesh mesh, float angle, int[] triangles, Vector3[] vertices, bool instant = false)
        {
            if (triangles == null)
            {
                if (meshInfoCache == null)
                {
                    meshInfoCache = new Dictionary <Mesh, KeyValuePair <int[], Vector3[]> >();
                }
                if (meshInfoCache.ContainsKey(mesh))
                {
                    triangles = meshInfoCache[mesh].Key;
                    vertices  = meshInfoCache[mesh].Value;
                }
                else
                {
                    triangles = mesh.GetTriangles(0);
                    vertices  = mesh.vertices;
                    meshInfoCache.Add(mesh, new KeyValuePair <int[], Vector3[]>(triangles, vertices));
                }
            }
            var triNormals = AllocatedArray <Vector3> .Get(triangles.Length / 3);

            var normals = AllocatedArray <Vector3> .Get(vertices.Length);

            angle = angle * Mathf.Deg2Rad;

            var dictionary = PooledDictionary <Vector3, VertexEntry> .Get(vertices.Length, VectorComparer);

            //Goes through all the triangles and gathers up data to be used later
            for (var i = 0; i < triangles.Length; i += 3)
            {
                int i1 = triangles[i];
                int i2 = triangles[i + 1];
                int i3 = triangles[i + 2];

                //Calculate the normal of the triangle
                Vector3 p1       = vertices[i2] - vertices[i1];
                Vector3 p2       = vertices[i3] - vertices[i1];
                Vector3 normal   = Vector3.Cross(p1, p2).normalized;
                int     triIndex = i / 3;
                triNormals[triIndex] = normal;

                VertexEntry entry;
                //VertexKey key;

                //For each of the three points of the triangle
                //  > Add this triangle as part of the triangles they're connected to.

                if (!dictionary.TryGetValue(vertices[i1], out entry))
                {
                    entry = GenericObjectPool <VertexEntry> .Get();

                    entry.PopulateArrays();
                    dictionary.Add(vertices[i1], entry);
                }
                entry.Add(i1, triIndex);

                if (!dictionary.TryGetValue(vertices[i2], out entry))
                {
                    entry = GenericObjectPool <VertexEntry> .Get();

                    entry.PopulateArrays();
                    dictionary.Add(vertices[i2], entry);
                }
                entry.Add(i2, triIndex);

                if (!dictionary.TryGetValue(vertices[i3], out entry))
                {
                    entry = GenericObjectPool <VertexEntry> .Get();

                    entry.PopulateArrays();
                    dictionary.Add(vertices[i3], entry);
                }
                entry.Add(i3, triIndex);
            }

            foreach (var kvp in dictionary)
            {
                var value = kvp.Value;
                for (var i = 0; i < value.Count; ++i)
                {
                    var sum = new Vector3();
                    for (var j = 0; j < value.Count; ++j)
                    {
                        if (value.VertexIndex[i] == value.VertexIndex[j])
                        {
                            sum += triNormals[value.TriangleIndex[j]];
                        }
                        else
                        {
                            float dot = Vector3.Dot(
                                triNormals[value.TriangleIndex[i]],
                                triNormals[value.TriangleIndex[j]]);
                            dot = Mathf.Clamp(dot, -0.99999f, 0.99999f);
                            float acos = Mathf.Acos(dot);
                            if (acos <= angle)
                            {
                                sum += triNormals[value.TriangleIndex[j]];
                            }
                        }
                    }
                    normals[value.VertexIndex[i]] = sum.normalized;
                }
                value.Clear();
                GenericObjectPool <VertexEntry> .Return(value);
            }
            dictionary.ReturnToPool();
            if (instant == false)
            {
                if (mainThreadActions == null)
                {
                    mainThreadActions = new Queue <System.Action>();
                }
                mainThreadActions.Enqueue(() =>
                {
                    if (mesh)
                    {
                        mesh.normals = normals;
                    }
                    AllocatedArray <Vector3> .Return(normals, false);
                });
            }
            else
            {
                mesh.normals = normals;
                AllocatedArray <Vector3> .Return(normals, false);
            }
        }