private static CollisionMeshData CreateDataOptionallyReduce(Mesh mesh,
                                                                    CollisionMeshOptions options,
                                                                    Utils.MeshMerger merger)
        {
            var reductionEnabled = options != null && options.ReductionEnabled;
            var orgNumVertices   = merger.Vertices.Count;

            if (reductionEnabled)
            {
                merger.Reduce(options.ReductionRatio, options.ReductionAggressiveness);
            }

            if (merger.Vertices.Count == 0)
            {
                if (reductionEnabled && orgNumVertices > 0)
                {
                    UnityEngine.Debug.LogWarning($"Vertex Reduction reduced a collision mesh from {orgNumVertices} vertices to zero. " +
                                                 "Ignoring collision mesh.", mesh);
                }
                else
                {
                    UnityEngine.Debug.LogWarning($"Mesh \"{mesh.name}\" doesn't contain any vertices for the collision mesh. " +
                                                 "Ignoring collision mesh.", mesh);
                }
                return(null);
            }

            var meshData = new CollisionMeshData();

            meshData.Apply(merger.Vertices, merger.Indices);

            return(meshData);
        }
        private Task <Result[]> Create(Mesh[] meshes, CollisionMeshOptions[] meshOptions)
        {
            var mergers        = meshes.Select(mesh => Utils.MeshMerger.Merge(null, mesh.SourceObjects)).ToArray();
            var totNumVertices = mergers.Sum(merger => merger.Vertices.Count);

            Progress = 0.0f;
            var numProcessedVertices = 0;

            return(Task.Run(() =>
            {
                var results = new Result[meshes.Length];

                NativeHandler.Instance.RegisterCurrentThread();

                for (int i = 0; i < meshes.Length; ++i)
                {
                    var mesh = meshes[i];
                    var options = meshOptions[i];

                    var merger = mergers[i];
                    numProcessedVertices += merger.Vertices.Count;
                    if (options == null || options.Mode == CollisionMeshOptions.MeshMode.Trimesh)
                    {
                        var collisionMesh = CreateDataOptionallyReduce(mesh,
                                                                       options,
                                                                       merger);
                        var result = new Result()
                        {
                            Mesh = mesh,
                            Options = options,
                            CollisionMeshes = collisionMesh != null ?
                                              new CollisionMeshData[] { collisionMesh } :
                            null
                        };
                        results[i] = result;
                    }
                    else if (options.Mode == CollisionMeshOptions.MeshMode.Convex)
                    {
                        CollisionMeshData collisionMesh = null;
                        using (var tmpConvex = agxUtil.agxUtilSWIG.createConvexRef(merger.Vertices))
                            collisionMesh = CreateDataOptionallyReduce(mesh,
                                                                       options,
                                                                       merger,
                                                                       tmpConvex.get());

                        var result = new Result()
                        {
                            Mesh = mesh,
                            Options = options,
                            CollisionMeshes = collisionMesh != null ?
                                              new CollisionMeshData[] { collisionMesh } :
                            null
                        };
                        results[i] = result;
                    }
                    else if (options.Mode == CollisionMeshOptions.MeshMode.ConvexDecomposition)
                    {
                        var result = new Result()
                        {
                            Mesh = mesh,
                            Options = options,
                            CollisionMeshes = null
                        };

                        var convexes = new agxCollide.ConvexVector();
                        var elementsPerAxis = options.ElementResolutionPerAxis;
                        agxUtil.agxUtilSWIG.createVHACDConvexDecomposition(merger.Vertices,
                                                                           merger.Indices,
                                                                           convexes,
                                                                           (uint)elementsPerAxis);
                        if (convexes.Count == 0)
                        {
                            UnityEngine.Debug.LogWarning($"Convex Decomposition of {mesh} resulted in zero convex shapes.", mesh);
                        }

                        var collisionMeshes = (from convexRef in convexes
                                               let collisionMesh = CreateDataOptionallyReduce(mesh,
                                                                                              options,
                                                                                              merger,
                                                                                              convexRef.get())
                                                                   where collisionMesh != null
                                                                   select collisionMesh).ToArray();
                        if (collisionMeshes.Length > 0)
                        {
                            result.CollisionMeshes = collisionMeshes;
                        }

                        results[i] = result;
                    }

                    Progress = (float)numProcessedVertices / totNumVertices;
                }

                NativeHandler.Instance.UnregisterCurrentThread();

                return results;
            }));
        }