public static void Run()
        {
            string filePath    = Constants.SAMPLE_DOCX_10_PAGES;
            string filePathOut = Path.Combine(Constants.GetOutputDirectoryPath(), "document_{0}.{1}");

            SplitOptions splitOptions = new SplitOptions(filePathOut, 3, 7);

            /* This options set should produce:
             *
             * Document name   |  Page numbers
             * document_0     |     3
             * document_1     |     4
             * document_2     |     5
             * document_3     |     6
             * document_4     |     7
             */

            using (Merger merger = new Merger(filePath))
            {
                merger.Split(splitOptions);
            }

            Console.WriteLine("Source document was splitted successfully.");
            Console.WriteLine($"Check output {filePathOut}.");
        }
Beispiel #2
0
        public static string[] Split(string input,
                                     string[] delimiters,
                                     RegexOptions regexOptions = RegexOptions.None,
                                     SplitOptions splitOptions = SplitOptions.None)
        {
            if (delimiters == null || delimiters.Length == 0)
            {
                throw new ArgumentException("Delimiters can't be empty", "delimiters");
            }

            var pattern = new StringBuilder(String.Join("|", delimiters.Select(d => Regex.Escape(d))));

            // pattern building order matters: IncludeDelimiters must occur first if selected
            if (splitOptions.HasFlag(SplitOptions.IncludeDelimiters))
            {
                PrefixSuffix(pattern, "(", ")");
            }
            if (splitOptions.HasFlag(SplitOptions.MatchWholeWords))
            {
                PrefixSuffix(pattern, @"\b");
            }
            if (splitOptions.HasFlag(SplitOptions.TrimWhitespace))
            {
                PrefixSuffix(pattern, @"\s*");
            }

            string[] result = Regex.Split(input, pattern.ToString(), regexOptions);
            if (splitOptions.HasFlag(SplitOptions.RemoveEmptyEntries))
            {
                result = RemoveEmptyEntries(result);
            }
            return(result);
        }
    /// <summary>
    /// The current save file format version. This number has nothing to do with the Application.version.
    /// It should be the first line of every savefile prepended by a v so that it can be immediately identified how to interpret
    /// the rest of the file.
    /// The first savefiles do not contain a version number (1), but instead immediately start with the simulation objective as an int,
    /// which is how they can be differentiated from the rest (They don't start with a v).
    /// </summary>
    // private static int version = 2;


    public static SimulationData ParseSimulationData(string filename, string contents)
    {
        var lineEndings  = contents.Contains("\r\n") ? "\r\n" : "\n";
        var splitOptions = new SplitOptions(lineEndings);

        var components = contents.Split(splitOptions.SPLIT_ARRAY, System.StringSplitOptions.None);

        // extract the save data from the file contents.
        // determine the version of the save file.
        // if the first line doesn't start with a v the version is 1

        if (components[0].ToUpper()[0] != 'V')
        {
            // V1
            return(SimulationParserV1.ParseSimulationData(filename, contents, splitOptions));
        }

        var version = int.Parse(components[0].Split(' ')[1]);

        switch (version)
        {
        case 2:
            return(SimulationParserV2.ParseSimulationData(filename, contents, splitOptions));

        default: throw new System.Exception("Unknown Save file format!");
        }
    }
Beispiel #4
0
        public static void Run()
        {
            var configuration = new Configuration(Common.MyAppSid, Common.MyAppKey);
            var apiInstance   = new DocumentApi(configuration);

            try
            {
                var fileInfo = new FileInfo
                {
                    FilePath = "WordProcessing/sample-10-pages.docx"
                };

                var options = new SplitOptions
                {
                    FileInfo        = fileInfo,
                    OutputPath      = "Output/split-by-start-end-numbers",
                    StartPageNumber = 3,
                    EndPageNumber   = 7,
                    Mode            = SplitOptions.ModeEnum.Pages
                };

                var request  = new SplitRequest(options);
                var response = apiInstance.Split(request);

                foreach (var document in response.Documents)
                {
                    Console.WriteLine("Output file path: " + document.Path);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception while calling api: " + e.Message);
            }
        }
Beispiel #5
0
        public static void Run()
        {
            var configuration = new Configuration(Common.MyAppSid, Common.MyAppKey);
            var apiInstance   = new DocumentApi(configuration);

            try
            {
                var fileInfo = new FileInfo
                {
                    FilePath = "WordProcessing/sample-10-pages.docx"
                };

                var options = new SplitOptions
                {
                    FileInfo   = fileInfo,
                    OutputPath = "Output/split-to-multipage-document",
                    Pages      = new List <int?> {
                        3, 6, 8
                    },
                    Mode = SplitOptions.ModeEnum.Intervals
                };

                var request  = new SplitRequest(options);
                var response = apiInstance.Split(request);

                foreach (var document in response.Documents)
                {
                    Console.WriteLine("Output file path: " + document.Path);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception while calling api: " + e.Message);
            }
        }
Beispiel #6
0
        public static string[] Split(string input,
            string[] delimiters,
            RegexOptions regexOptions = RegexOptions.None,
            SplitOptions splitOptions = SplitOptions.None)
        {
            if (delimiters == null || delimiters.Length == 0)
            {
                throw new ArgumentException("Delimiters can't be empty", "delimiters");
            }

            var pattern = new StringBuilder(String.Join("|", delimiters.Select(d => Regex.Escape(d))));

            // pattern building order matters: IncludeDelimiters must occur first if selected
            if (splitOptions.HasFlag(SplitOptions.IncludeDelimiters))
            {
                PrefixSuffix(pattern, "(", ")");
            }
            if (splitOptions.HasFlag(SplitOptions.MatchWholeWords))
            {
                PrefixSuffix(pattern, @"\b");
            }
            if (splitOptions.HasFlag(SplitOptions.TrimWhitespace))
            {
                PrefixSuffix(pattern, @"\s*");
            }

            string[] result = Regex.Split(input, pattern.ToString(), regexOptions);
            if (splitOptions.HasFlag(SplitOptions.RemoveEmptyEntries))
            {
                result = RemoveEmptyEntries(result);
            }
            return result;
        }
Beispiel #7
0
 public static void RestoreOptions()
 {
     isMerge         = false;
     splitInFiles    = new Dictionary <string, bool>();
     splitOpts       = new SplitOptions();
     splitOutPath    = segmentIDs = mergeOrigFile =
         mergeInPath = mergeInfoFile = string.Empty;
 }
Beispiel #8
0
    public static void LoadSimulationFromSaveFile(string filename, CreatureBuilder creatureBuilder, Evolution evolution)
    {
        if (!filename.EndsWith(".txt"))
        {
            filename += ".txt";
        }

        // check if the file exists
        var path = RESOURCE_PATH;         //Path.Combine(RESOURCE_PATH, SAVE_FOLDER);

        path = Path.Combine(path, filename);

        var reader   = new StreamReader(path);
        var contents = reader.ReadToEnd();

        reader.Close();

        var splitOptions = new SplitOptions();

        // Determine the line endings
        if (contents.Contains("\r\n"))
        {
            // Windows style endings
            splitOptions = new SplitOptions("\r\n");
        }
        else
        {
            splitOptions = new SplitOptions("\n");
        }

        var components = contents.Split(splitOptions.SPLIT_ARRAY, System.StringSplitOptions.None);

        // extract the save data from the file contents.
        // determine the version of the save file.
        // if the first line doesn't start with a v the version is 1

        if (components[0].ToUpper()[0] == 'V')
        {
            var version = int.Parse(components[0].Split(' ')[1]);

            if (version == 2)
            {
                LoadSimulationFromSaveFileV2(filename, contents, splitOptions, creatureBuilder, evolution);
            }
            else
            {
                throw new System.Exception("Unknown Save file format!");
            }
        }
        else
        {
            // V1
            LoadSimulationFromSaveFileV1(filename, contents, splitOptions, creatureBuilder, evolution);
        }
    }
Beispiel #9
0
        private void addSplitOptionControl(string labelText)
        {
            var ctrl = new SplitOptions();
            var vm   = new SplitOptionsViewModel();

            ctrl.DataContext = vm;
            vm.ParentVM      = this;
            vm.LabelText     = labelText;

            SplitOptionControls.Add(ctrl);
        }
Beispiel #10
0
        public static IEnumerable<string> EnumerateValues(Regex regex, string input, int count, int startAt, SplitOptions options)
        {
            if (regex == null)
                throw new ArgumentNullException(nameof(regex));

            if (input == null)
                throw new ArgumentNullException(nameof(input));

            if (count < 0)
                throw new ArgumentOutOfRangeException(nameof(count));

            if (startAt < 0 || startAt > input.Length)
                throw new ArgumentOutOfRangeException(nameof(startAt));

            if (count == 1)
            {
                yield return input;
                yield break;
            }

            Match firstMatch = regex.Match(input, startAt);

            if (!firstMatch.Success)
            {
                yield return input;
                yield break;
            }

            bool omitGroupValues = (options & SplitOptions.OmitGroupValues) != 0;
            bool omitEmptyValues = (options & SplitOptions.OmitEmptyValues) != 0;
            int prevIndex = 0;

            count--;

            foreach (Match match in (regex.RightToLeft) ? EnumerateMatchesRightToLeft(firstMatch, count) : EnumerateMatches(firstMatch, count))
            {
                if (!omitEmptyValues || ((match.Index - prevIndex) > 0))
                    yield return input.Substring(prevIndex, match.Index - prevIndex);

                prevIndex = match.Index + match.Length;

                if (!omitGroupValues)
                {
                    foreach (Group group in (regex.RightToLeft) ? EnumerateGroupsRightToLeft(match) : EnumerateGroups(match))
                    {
                        if (group.Success && (!omitEmptyValues || group.Length > 0))
                            yield return group.Value;
                    }
                }
            }

            yield return input.Substring(prevIndex, input.Length - prevIndex);
        }
Beispiel #11
0
 public static async Task InitAsync(SplitInteropHelper interopHelper, string id, string[] elements,
                                    SplitOptions options, SplitInitOptions initOptions)
 {
     await JSRuntime.Current.InvokeAsync <object>(
         "blazorSplit.init",
         new DotNetObjectRef(interopHelper),
         id,
         elements,
         options,
         initOptions
         );
 }
Beispiel #12
0
        private static object SplitOperatorImpl(System.Management.Automation.ExecutionContext context, IScriptExtent errorPosition, object lval, object rval, SplitImplOptions implOptions, bool ignoreCase)
        {
            IEnumerable <string> content   = enumerateContent(context, errorPosition, implOptions, lval);
            ScriptBlock          predicate = null;
            string       separatorPattern  = null;
            int          limit             = 0;
            SplitOptions options           = 0;

            object[] objArray = unfoldTuple(context, errorPosition, rval);
            if (objArray.Length < 1)
            {
                throw InterpreterError.NewInterpreterException(rval, typeof(RuntimeException), errorPosition, "BadOperatorArgument", ParserStrings.BadOperatorArgument, new object[] { "-split", rval });
            }
            object obj1 = objArray[0];

            predicate = objArray[0] as ScriptBlock;
            if (predicate == null)
            {
                separatorPattern = PSObject.ToStringParser(context, objArray[0]);
            }
            if (objArray.Length >= 2)
            {
                limit = FixNum(objArray[1], errorPosition);
            }
            if ((objArray.Length >= 3) && (objArray[2] != null))
            {
                string str2 = objArray[2] as string;
                if ((str2 == null) || !string.IsNullOrEmpty(str2))
                {
                    options = ConvertTo <SplitOptions>(objArray[2], errorPosition);
                    if (predicate != null)
                    {
                        throw InterpreterError.NewInterpreterException(null, typeof(ParseException), errorPosition, "InvalidSplitOptionWithPredicate", ParserStrings.InvalidSplitOptionWithPredicate, new object[0]);
                    }
                    if (ignoreCase && ((options & SplitOptions.IgnoreCase) == 0))
                    {
                        options |= SplitOptions.IgnoreCase;
                    }
                }
            }
            else if (ignoreCase)
            {
                options |= SplitOptions.IgnoreCase;
            }
            if (predicate != null)
            {
                return(SplitWithPredicate(context, errorPosition, content, predicate, limit));
            }
            return(SplitWithPattern(context, errorPosition, content, separatorPattern, limit, options));
        }
Beispiel #13
0
        private static RegexOptions parseRegexOptions(SplitOptions options)
        {
            int[][]      numArray = new int[][] { new int[] { 4, 0x200 }, new int[] { 8, 0x20 }, new int[] { 0x10, 2 }, new int[] { 0x20, 0x10 }, new int[] { 0x40, 1 }, new int[] { 0x80, 4 } };
            RegexOptions none     = RegexOptions.None;

            foreach (int[] numArray2 in numArray)
            {
                if ((options & (SplitOptions)numArray2[0]) != 0)
                {
                    none |= (RegexOptions)numArray2[1];
                }
            }
            return(none);
        }
        public static void ConfigureContainer(this ContainerBuilder builder)
        {
            _configuration = LoadConfiguration();

            builder.RegisterType <DummyRepository.DummyRepository>().As <ICustomerScopeRepository>();
            builder.RegisterType <SplitRepository>().As <ICustomerScopeRepository>();

            builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(SplitService)))
            .AsImplementedInterfaces();

            var splitioOptions = new SplitOptions();

            _configuration.GetSection("Splitio").Bind(splitioOptions);
            builder.Register(x => new SplitFactory(splitioOptions.ApiKey)).As <ISplitFactory>().SingleInstance();
        }
Beispiel #15
0
        public IEnumerable <Property> Split(SplitOptions options = SplitOptions.Recursive)
        {
            if (!IsShorthand)
            {
                throw new InvalidOperationException("Only short hand property can be splitted.");
            }

            if (options == SplitOptions.NonRecursive)
            {
                return(NonRecursiveSplit());
            }
            else
            {
                return(RecursiveSplit());
            }
        }
        private string CodeFolderName(SplitOptions Split, DateTime date)
        {
            if (Split == SplitOptions.Yearly)
            {
                return(date.Year + "");
            }
            else if (Split == SplitOptions.Monthly)
            {
                return(date.Year + "-" + date.Month);
            }
            else if (Split == SplitOptions.Daily)
            {
                return(date.Year + "-" + date.Month + "-" + date.Day);
            }
            else if (Split == SplitOptions.AllTimes)
            {
                return("AllTimesData");
            }

            return(null);
        }
Beispiel #17
0
        public static IEnumerable <IEnumerable <T> > Split <T>(this IEnumerable <T> source,
                                                               Relation <T, T, T> relation,
                                                               SplitOptions options = SplitOptions.None)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (relation == null)
            {
                throw new ArgumentNullException(nameof(relation));
            }

            if (options.HasFlag(SplitOptions.IncludeBorders))
            {
                return(SplitWithBordersIterator(source, relation));
            }
            else
            {
                return(SplitIterator(source, relation));
            }
        }
Beispiel #18
0
        public static void Run()
        {
            string filePath    = Constants.SAMPLE_DOCX_10_PAGES;
            string filePathOut = Path.Combine(Constants.GetOutputDirectoryPath(), "document_{0}.{1}");

            SplitOptions splitOptions = new SplitOptions(filePathOut, new int[] { 3, 6, 8 }, SplitMode.Interval);

            /* This options set should produce
             * Document name   |  Page numbers
             * document_0     |     1, 2
             * document_1     |     3, 4, 5
             * document_2     |     6, 7
             * document_3     |     8, 9, 10
             */

            using (Merger merger = new Merger(filePath))
            {
                merger.Split(splitOptions);
            }

            Console.WriteLine("Source document was splitted successfully.");
            Console.WriteLine($"Check output {filePathOut}.");
        }
Beispiel #19
0
        static void Main(string[] args)
        {
            var invokedVerb         = string.Empty;
            var invokedVerbInstance = new object();

            var options = new SplitOptions();

            if (!CommandLine.Parser.Default.ParseArguments(args, options, (verb, subOptions) =>
            {
                invokedVerb = verb;
                invokedVerbInstance = subOptions;
            }))
            {
                Environment.Exit(CommandLine.Parser.DefaultExitCodeFail);
            }

            switch (invokedVerb)
            {
            case "split":
                var splitOptions = (SplitOptions)invokedVerbInstance;
                Splitter.SplitFiles(options);
                break;
            }
        }
Beispiel #20
0
            public static SpaceTreeNode BuildSpaceTree(MeshData meshDataIn, int nSubdivisionLevels, FracturedObject fracturedComponent, ProgressDelegate progress = null)
            {
                if (nSubdivisionLevels < 1)
                {
                    return(null);
                }

                SplitOptions splitOptions = new SplitOptions();

                splitOptions.bForceNoIslandGeneration     = true;
                splitOptions.bForceNoChunkConnectionInfo  = true;
                splitOptions.bForceNoIslandConnectionInfo = true;
                splitOptions.bForceNoCap       = false;
                splitOptions.bVerticesAreLocal = true;

                SpaceTreeNode nodeRoot = new SpaceTreeNode();

                nodeRoot.listMeshDatasSpace = new List <MeshData>();
                nodeRoot.listMeshDatasSpace.Add(meshDataIn);
                nodeRoot.nLevel   = 0;
                nodeRoot.nSplitsX = 0;
                nodeRoot.nSplitsY = 0;
                nodeRoot.nSplitsZ = 0;
                nodeRoot.v3Min    = meshDataIn.v3Min;
                nodeRoot.v3Max    = meshDataIn.v3Max;

                Queue <SpaceTreeNode> queueNodes = new Queue <SpaceTreeNode>();

                queueNodes.Enqueue(nodeRoot);

                int nTotalSubdivisions   = 0;
                int nCurrentSubdivisions = 0;
                int nSplitsX             = 0;
                int nSplitsY             = 0;
                int nSplitsZ             = 0;

                for (int i = 0; i < nSubdivisionLevels; i++)
                {
                    nTotalSubdivisions += Mathf.RoundToInt(Mathf.Pow(2, i));
                }

                while (queueNodes.Count > 0)
                {
                    SpaceTreeNode nodeCurrent = queueNodes.Dequeue();

                    List <MeshData> listMeshDataPos;
                    List <MeshData> listMeshDataNeg;

                    if (nodeCurrent.nLevel < nSubdivisionLevels)
                    {
                        if (progress != null)
                        {
                            progress("Fracturing", string.Format("Pre computing space volume (split {0}/{1}, Depth {2})", nCurrentSubdivisions + 1, nTotalSubdivisions, nodeCurrent.nLevel + 1), Mathf.Clamp01((float)nCurrentSubdivisions / (float)nTotalSubdivisions));
                        }

                        if (Fracturer.IsFracturingCancelled())
                        {
                            return(null);
                        }

                        Vector3 v3Normal = Vector3.up;
                        Vector3 v3Right  = Vector3.right;
                        Vector3 v3Pos    = (nodeCurrent.v3Min + nodeCurrent.v3Max) * 0.5f;

                        float fSizeX = nodeCurrent.v3Max.x - nodeCurrent.v3Min.x;
                        float fSizeY = nodeCurrent.v3Max.y - nodeCurrent.v3Min.y;
                        float fSizeZ = nodeCurrent.v3Max.z - nodeCurrent.v3Min.z;

                        Vector3 v3MinNeg = nodeCurrent.v3Min;
                        Vector3 v3MaxNeg = nodeCurrent.v3Max;
                        Vector3 v3MinPos = nodeCurrent.v3Min;
                        Vector3 v3MaxPos = nodeCurrent.v3Max;

                        if (fSizeX >= fSizeY && fSizeX >= fSizeZ)
                        {
                            v3Normal = Vector3.right;
                            v3Right  = Vector3.forward;

                            v3MaxNeg.x = v3Pos.x;
                            v3MinPos.x = v3Pos.x;

                            nSplitsX++;
                        }
                        else if (fSizeY >= fSizeX && fSizeY >= fSizeZ)
                        {
                            v3Normal = Vector3.up;
                            v3Right  = Vector3.right;

                            v3MaxNeg.y = v3Pos.y;
                            v3MinPos.y = v3Pos.y;

                            nSplitsY++;
                        }
                        else
                        {
                            v3Normal = Vector3.forward;
                            v3Right  = Vector3.right;

                            v3MaxNeg.z = v3Pos.z;
                            v3MinPos.z = v3Pos.z;

                            nSplitsZ++;
                        }

                        foreach (MeshData meshData in nodeCurrent.listMeshDatasSpace)
                        {
                            if (SplitMeshUsingPlane(meshData, fracturedComponent, splitOptions, v3Normal, v3Right, v3Pos, out listMeshDataPos, out listMeshDataNeg, progress) == true)
                            {
                                nodeCurrent.nodeOneSide = new SpaceTreeNode();
                                nodeCurrent.nodeOneSide.listMeshDatasSpace = listMeshDataNeg;
                                nodeCurrent.nodeOneSide.v3Min    = v3MinNeg;
                                nodeCurrent.nodeOneSide.v3Max    = v3MaxNeg;
                                nodeCurrent.nodeOneSide.nLevel   = nodeCurrent.nLevel + 1;
                                nodeCurrent.nodeOneSide.nSplitsX = nSplitsX;
                                nodeCurrent.nodeOneSide.nSplitsY = nSplitsY;
                                nodeCurrent.nodeOneSide.nSplitsZ = nSplitsZ;

                                queueNodes.Enqueue(nodeCurrent.nodeOneSide);

                                nodeCurrent.nodeOtherSide = new SpaceTreeNode();
                                nodeCurrent.nodeOtherSide.listMeshDatasSpace = listMeshDataPos;
                                nodeCurrent.nodeOtherSide.v3Min    = v3MinPos;
                                nodeCurrent.nodeOtherSide.v3Max    = v3MaxPos;
                                nodeCurrent.nodeOtherSide.nLevel   = nodeCurrent.nLevel + 1;
                                nodeCurrent.nodeOtherSide.nSplitsX = nSplitsX;
                                nodeCurrent.nodeOtherSide.nSplitsY = nSplitsY;
                                nodeCurrent.nodeOtherSide.nSplitsZ = nSplitsZ;

                                queueNodes.Enqueue(nodeCurrent.nodeOtherSide);
                            }
                        }

                        nCurrentSubdivisions++;
                    }
                }

                return(nodeRoot);
            }
        public static bool SplitMeshUsingPlane(GameObject gameObjectIn, FracturedObject fracturedComponent, SplitOptions splitOptions, Transform transformPlaneSplit, out List<GameObject> listGameObjectsPosOut, out List<GameObject> listGameObjectsNegOut, ProgressDelegate progress = null)
        {
            listGameObjectsPosOut = new List<GameObject>();
            listGameObjectsNegOut = new List<GameObject>();

            MeshFilter meshfIn = gameObjectIn.GetComponent<MeshFilter>();

            if(meshfIn == null)
            {
                return false;
            }

            foreach(FracturedChunk chunk in fracturedComponent.ListFracturedChunks)
            {
                if(chunk != null)
                {
                    UnityEngine.Object.DestroyImmediate(chunk.gameObject);
                }
            }

            fracturedComponent.ListFracturedChunks.Clear();
            fracturedComponent.DecomposeRadius = (meshfIn.sharedMesh.bounds.max - meshfIn.sharedMesh.bounds.min).magnitude;
            Random.seed = fracturedComponent.RandomSeed;

//            Debug.Log("In: " + gameObjectIn.name + ": " + meshfIn.sharedMesh.subMeshCount + " submeshes, " + ": " + (meshfIn.sharedMesh.triangles.Length / 3) + " triangles, " + meshfIn.sharedMesh.vertexCount + " vertices, " + (meshfIn.sharedMesh.uv != null ? meshfIn.sharedMesh.uv.Length : 0) + " uv1, " + (meshfIn.sharedMesh.uv2 != null ? meshfIn.sharedMesh.uv2.Length : 0) + " uv2");

            // Check if the input object already has been split, to get its split closing submesh

            FracturedChunk fracturedChunk = gameObjectIn.GetComponent<FracturedChunk>();

            int nSplitCloseSubMesh = fracturedChunk != null ? fracturedChunk.SplitSubMeshIndex : -1;

            if(nSplitCloseSubMesh == -1 && gameObjectIn.GetComponent<Renderer>())
            {
                // Check if its material is the same as the split material

                if(gameObjectIn.GetComponent<Renderer>().sharedMaterial == fracturedComponent.SplitMaterial)
                {
                    nSplitCloseSubMesh = 0;
                }
            }

            List<MeshData> listMeshDatasPos;
            List<MeshData> listMeshDatasNeg;

            Material[] aMaterials = fracturedComponent.gameObject.GetComponent<Renderer>() ? fracturedComponent.gameObject.GetComponent<Renderer>().sharedMaterials : null;

            MeshData meshDataIn = new MeshData(meshfIn.transform, meshfIn.sharedMesh, aMaterials, meshfIn.transform.localToWorldMatrix, !splitOptions.bVerticesAreLocal, nSplitCloseSubMesh, true);

            if(SplitMeshUsingPlane(meshDataIn, fracturedComponent, splitOptions, transformPlaneSplit.up, transformPlaneSplit.right, transformPlaneSplit.position, out listMeshDatasPos, out listMeshDatasNeg, progress) == false)
            {
                return false;
            }

            // Set the mesh properties and add objects to list

            if(listMeshDatasPos.Count > 0)
            {
                for(int nMeshCount = 0; nMeshCount < listMeshDatasPos.Count; nMeshCount++)
                {
                    GameObject goPos = CreateNewSplitGameObject(gameObjectIn, fracturedComponent, gameObjectIn.name + "0" + (listMeshDatasPos.Count > 1 ? ("(" + nMeshCount + ")") : ""), !splitOptions.bVerticesAreLocal, listMeshDatasPos[nMeshCount]);
                    listGameObjectsPosOut.Add(goPos);
                }
            }

            if(listMeshDatasNeg.Count > 0)
            {
                for(int nMeshCount = 0; nMeshCount < listMeshDatasNeg.Count; nMeshCount++)
                {
                    GameObject goNeg = CreateNewSplitGameObject(gameObjectIn, fracturedComponent, gameObjectIn.name + "1" + (listMeshDatasNeg.Count > 1 ? ("(" + nMeshCount + ")") : ""), !splitOptions.bVerticesAreLocal, listMeshDatasNeg[nMeshCount]);
                    listGameObjectsNegOut.Add(goNeg);
                }
            }

            return true;
        }
        private static bool SplitMeshUsingPlane(MeshData meshDataIn, FracturedObject fracturedComponent, SplitOptions splitOptions, Vector3 v3PlaneNormal, Vector3 v3PlaneRight, Vector3 v3PlanePoint, out List<MeshData> listMeshDatasPosOut, out List<MeshData> listMeshDatasNegOut, ProgressDelegate progress = null)
        {
            Plane planeSplit = new Plane(v3PlaneNormal, v3PlanePoint);

            listMeshDatasPosOut = new List<MeshData>();
            listMeshDatasNegOut = new List<MeshData>();

            // Check if the input object already has been split, to get its split closing submesh

            bool bNeedsNewSplitSubMesh = meshDataIn.nSplitCloseSubMesh == -1;
            int  nSplitCloseSubMesh    = meshDataIn.nSplitCloseSubMesh;

            // Here we are going to store our output vertex/index data

            int nCurrentVertexHash = meshDataIn.nCurrentVertexHash; // We will use this to identify vertices with same coordinates but different vertex data. They will share the same vertex hash

            List<VertexData>     listVertexDataPos   = new List<VertexData>();
            List<VertexData>     listVertexDataNeg   = new List<VertexData>();
            List<int>[]          alistIndicesPos     = new List<int>[meshDataIn.nSubMeshCount + (meshDataIn.nSplitCloseSubMesh == -1 ? 1 : 0)];
            List<int>[]          alistIndicesNeg     = new List<int>[meshDataIn.nSubMeshCount + (meshDataIn.nSplitCloseSubMesh == -1 ? 1 : 0)];
            MeshFaceConnectivity faceConnectivityPos = new MeshFaceConnectivity();
            MeshFaceConnectivity faceConnectivityNeg = new MeshFaceConnectivity();
            MeshDataConnectivity meshConnectivityPos = new MeshDataConnectivity();
            MeshDataConnectivity meshConnectivityNeg = new MeshDataConnectivity();

            listVertexDataPos.Capacity = meshDataIn.aVertexData.Length / 2;
            listVertexDataNeg.Capacity = meshDataIn.aVertexData.Length / 2;

            if(bNeedsNewSplitSubMesh)
            {
                // Make room for the split closing submesh

                nSplitCloseSubMesh = meshDataIn.nSubMeshCount;

                alistIndicesPos[nSplitCloseSubMesh] = new List<int>();
                alistIndicesNeg[nSplitCloseSubMesh] = new List<int>();
            }

            // Our vertices that form the clipped cap

            Dictionary<EdgeKeyByHash, int>     dicClipVerticesHash = new Dictionary<EdgeKeyByHash, int>    (new EdgeKeyByHash.EqualityComparer());
            Dictionary<EdgeKeyByHash, CapEdge> dicCapEdges         = new Dictionary<EdgeKeyByHash, CapEdge>(new EdgeKeyByHash.EqualityComparer());

            // A hash table with our clipped edges, to reuse clipped vertices

            Dictionary<EdgeKeyByIndex, ClippedEdge> dicClippedEdgesPos = new Dictionary<EdgeKeyByIndex, ClippedEdge>(new EdgeKeyByIndex.EqualityComparer());
            Dictionary<EdgeKeyByIndex, ClippedEdge> dicClippedEdgesNeg = new Dictionary<EdgeKeyByIndex, ClippedEdge>(new EdgeKeyByIndex.EqualityComparer());

            int nClippedCacheHits   = 0;
            int nClippedCacheMisses = 0;

            // A hash table with the remapped indices, to reuse non-clipped vertices

            Dictionary<int, int> dicRemappedIndicesPos = new Dictionary<int, int>();
            Dictionary<int, int> dicRemappedIndicesNeg = new Dictionary<int, int>();

            for(int nSubMesh = 0; nSubMesh < meshDataIn.nSubMeshCount; nSubMesh++)
            {
                // Index list

                alistIndicesPos[nSubMesh] = new List<int>();
                alistIndicesNeg[nSubMesh] = new List<int>();
                List<int> listIndicesPos = alistIndicesPos[nSubMesh];
                List<int> listIndicesNeg = alistIndicesNeg[nSubMesh];

                alistIndicesPos[nSubMesh].Capacity = meshDataIn.aaIndices[nSubMesh].Length / 2;
                alistIndicesNeg[nSubMesh].Capacity = meshDataIn.aaIndices[nSubMesh].Length / 2;

                // A reference to the output arrays/lists (it will be switching between positive/negative side along the algorithm)

                List<VertexData>     plistVertexData    = listVertexDataPos;
                List<int>            plistObjectIndices = listIndicesPos;
                MeshFaceConnectivity pFaceConnectivity  = faceConnectivityPos;
                MeshDataConnectivity pMeshConnectivity  = meshConnectivityPos;

                Dictionary<EdgeKeyByIndex, ClippedEdge> pdicClippedEdges    = dicClippedEdgesPos;
                Dictionary<int, int>                    pdicRemappedIndices = dicRemappedIndicesPos;

                // Iterate through all submesh faces:

                for(int i = 0; i < meshDataIn.aaIndices[nSubMesh].Length / 3; i++)
	            {
                    plistVertexData     = listVertexDataPos;
                    plistObjectIndices  = listIndicesPos;
                    pFaceConnectivity   = faceConnectivityPos;
                    pMeshConnectivity   = meshConnectivityPos;
                    pdicClippedEdges    = dicClippedEdgesPos;
                    pdicRemappedIndices = dicRemappedIndicesPos;

		            int nIndex1 = meshDataIn.aaIndices[nSubMesh][i * 3 + 0];
		            int nIndex2 = meshDataIn.aaIndices[nSubMesh][i * 3 + 1];
		            int nIndex3 = meshDataIn.aaIndices[nSubMesh][i * 3 + 2];

                    int nHashV1 = meshDataIn.aVertexData[nIndex1].nVertexHash;
                    int nHashV2 = meshDataIn.aVertexData[nIndex2].nVertexHash;
                    int nHashV3 = meshDataIn.aVertexData[nIndex3].nVertexHash;

		            Vector3 v1 = meshDataIn.aVertexData[nIndex1].v3Vertex;
		            Vector3 v2 = meshDataIn.aVertexData[nIndex2].v3Vertex;
		            Vector3 v3 = meshDataIn.aVertexData[nIndex3].v3Vertex;

                    // Classify vertices depending on the side of the plane they lay on, then clip if necessary.

		            float fSide1 = v1.x * planeSplit.normal.x + v1.y * planeSplit.normal.y + v1.z * planeSplit.normal.z + planeSplit.distance;
		            float fSide2 = v2.x * planeSplit.normal.x + v2.y * planeSplit.normal.y + v2.z * planeSplit.normal.z + planeSplit.distance;
		            float fSide3 = v3.x * planeSplit.normal.x + v3.y * planeSplit.normal.y + v3.z * planeSplit.normal.z + planeSplit.distance;

                    bool  bForceSameSide  = false;
                    int   nAlmostInPlane  = 0;
                    bool  bAlmostInPlane1 = false;
                    bool  bAlmostInPlane2 = false;
                    bool  bAlmostInPlane3 = false;
                    float fFurthest       = 0.0f;

                    if(Mathf.Abs(fSide1) < UltimateFracturing.Parameters.EPSILONDISTANCEPLANE) { bAlmostInPlane1 = true; nAlmostInPlane++; }
                    if(Mathf.Abs(fSide2) < UltimateFracturing.Parameters.EPSILONDISTANCEPLANE) { bAlmostInPlane2 = true; nAlmostInPlane++; }
                    if(Mathf.Abs(fSide3) < UltimateFracturing.Parameters.EPSILONDISTANCEPLANE) { bAlmostInPlane3 = true; nAlmostInPlane++; }

                    if(Mathf.Abs(fSide1) > Mathf.Abs(fFurthest)) fFurthest = fSide1;
                    if(Mathf.Abs(fSide2) > Mathf.Abs(fFurthest)) fFurthest = fSide2;
                    if(Mathf.Abs(fSide3) > Mathf.Abs(fFurthest)) fFurthest = fSide3;

                    if(nAlmostInPlane == 1)
                    {
                        // Look if the other two vertices are on the same side. If so, we'll skip the clipping too.
                        if(bAlmostInPlane1 && (fSide2 * fSide3 > 0.0f)) bForceSameSide = true;
                        if(bAlmostInPlane2 && (fSide1 * fSide3 > 0.0f)) bForceSameSide = true;
                        if(bAlmostInPlane3 && (fSide1 * fSide2 > 0.0f)) bForceSameSide = true;
                    }
                    else if(nAlmostInPlane > 1)
                    {
                        bForceSameSide = true;

                        if(nAlmostInPlane == 3)
                        {
                            // Coplanar
                            continue;
                        }
                    }

		            if((fSide1 * fSide2 > 0.0f && fSide2 * fSide3 > 0.0f) || bForceSameSide)
		            {
			            // All on the same side, no clipping needed

			            if(fFurthest < 0.0f)
			            {
				            plistVertexData     = listVertexDataNeg;
				            plistObjectIndices  = listIndicesNeg;
                            pFaceConnectivity   = faceConnectivityNeg;
                            pMeshConnectivity   = meshConnectivityNeg;
                            pdicClippedEdges    = dicClippedEdgesNeg;
                            pdicRemappedIndices = dicRemappedIndicesNeg;
			            }

                        int nNewIndex1 = -1;
                        int nNewIndex2 = -1;
                        int nNewIndex3 = -1;

                        // Find vertices in remapped indices list and add vertex data if not present

                        if(pdicRemappedIndices.ContainsKey(nIndex1))
                        {
                            nNewIndex1 = pdicRemappedIndices[nIndex1];
                        }
                        if(nNewIndex1 == -1)
                        {
                            nNewIndex1 = plistVertexData.Count;
                            plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                            pdicRemappedIndices[nIndex1] = nNewIndex1;
                        }

                        if(pdicRemappedIndices.ContainsKey(nIndex2))
                        {
                            nNewIndex2 = pdicRemappedIndices[nIndex2];
                        }
                        if(nNewIndex2 == -1)
                        {
                            nNewIndex2 = plistVertexData.Count;
                            plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                            pdicRemappedIndices[nIndex2] = nNewIndex2;
                        }

                        if(pdicRemappedIndices.ContainsKey(nIndex3))
                        {
                            nNewIndex3 = pdicRemappedIndices[nIndex3];
                        }
                        if(nNewIndex3 == -1)
                        {
                            nNewIndex3 = plistVertexData.Count;
                            plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                            pdicRemappedIndices[nIndex3] = nNewIndex3;
                        }

                        // Add triangle indices

                        if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                        {
                            pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                        }

                        plistObjectIndices.Add(nNewIndex1);
                        plistObjectIndices.Add(nNewIndex2);
                        plistObjectIndices.Add(nNewIndex3);

                        if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                        {
                            pFaceConnectivity.AddEdge(nSubMesh, v1, v2, nHashV1, nHashV2, nNewIndex1, nNewIndex2);
                            pFaceConnectivity.AddEdge(nSubMesh, v2, v3, nHashV2, nHashV3, nNewIndex2, nNewIndex3);
                            pFaceConnectivity.AddEdge(nSubMesh, v3, v1, nHashV3, nHashV1, nNewIndex3, nNewIndex1);
                        }

                        // Add cap edges only if an edge is lying on the plane

                        if(nAlmostInPlane == 2)
                        {
                            if(fFurthest > 0.0f)
                            {
                                if(bAlmostInPlane1 && bAlmostInPlane2 && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV1, nHashV2, v1, v2);
                                if(bAlmostInPlane2 && bAlmostInPlane3 && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV2, nHashV3, v2, v3);
                                if(bAlmostInPlane3 && bAlmostInPlane1 && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV3, nHashV1, v3, v1);
                            }
                            else
                            {
                                if(bAlmostInPlane1 && bAlmostInPlane2 && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV2, nHashV1, v2, v1);
                                if(bAlmostInPlane2 && bAlmostInPlane3 && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV3, nHashV2, v3, v2);
                                if(bAlmostInPlane3 && bAlmostInPlane1 && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV1, nHashV3, v1, v3);
                            }
                        }
		            }
                    else if(nAlmostInPlane == 1)
                    {
                        // Special treatment clipping for one vertex laying on the clipping plane and the other 2 on different sides

                        int  nNewIndex1 = -1;
                        int  nNewIndex2 = -1;
                        int  nNewIndex3 = -1;
                        int  nNewIndex4 = -1;
                        int  nHashV4    = -1;
                        bool bEdge      = false;

                        EdgeKeyByIndex clippedEdgeKey;

                        if(bAlmostInPlane1)
                        {
                            // v1 almost on the clipping plane

					        if(fSide2 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
						        plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }

                            clippedEdgeKey = new EdgeKeyByIndex(nIndex2, nIndex3);

                            if(pdicClippedEdges.ContainsKey(clippedEdgeKey))
                            {
                                nClippedCacheHits++;
                                bEdge = true;
                                nNewIndex2 = pdicClippedEdges[clippedEdgeKey].GetFirstIndex(nIndex2);
                                nNewIndex4 = pdicClippedEdges[clippedEdgeKey].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex2)) nNewIndex2 = pdicRemappedIndices[nIndex2];
                            }

                            // Clip if not present in clipped edge list

                            EdgeKeyByHash clippedEdgeKeyHash = new EdgeKeyByHash(nHashV2, nHashV3);

                            if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                            {
                                nHashV4 = dicClipVerticesHash[clippedEdgeKeyHash];
                            }
                            else
                            {
                                nHashV4 = nCurrentVertexHash++;
                                dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV4);
                            }

                            VertexData vd4 = new VertexData(nHashV4);

                            if(bEdge == false)
                            {
                                if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex2, nIndex3, v2, v3, planeSplit, ref vd4) == false)
                                {
                                    return false;
                                }
                            }

                            // Add geometry of one side

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex1 == -1)
                            {
                                if(pdicRemappedIndices.ContainsKey(nIndex1))
                                {
                                    nNewIndex1 = pdicRemappedIndices[nIndex1];
                                }
                            }
                            if(nNewIndex1 == -1)
                            {
                                nNewIndex1 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                                pdicRemappedIndices[nIndex1] = nNewIndex1;
                            }

                            if(nNewIndex2 == -1)
                            {
                                nNewIndex2 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                                pdicRemappedIndices[nIndex2] = nNewIndex2;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex1);
                            plistObjectIndices.Add(nNewIndex2);
                            plistObjectIndices.Add(nNewIndex4);

                            Vector3 v4 = plistVertexData[nNewIndex4].v3Vertex;

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v1, v2, nHashV1, nHashV2, nNewIndex1, nNewIndex2);
                                pFaceConnectivity.AddEdge(nSubMesh, v2, v4, nHashV2, nHashV4, nNewIndex2, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v1, nHashV4, nHashV1, nNewIndex4, nNewIndex1);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV4, nHashV1, plistVertexData[nNewIndex4].v3Vertex, plistVertexData[nNewIndex1].v3Vertex);

                            if(bEdge == false) pdicClippedEdges.Add(clippedEdgeKey, new ClippedEdge(nIndex2, nIndex3, nNewIndex2, nNewIndex3, nNewIndex4));

                            // Add geometry of other side

					        if(fSide3 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
                                plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }
					        else
					        {
						        plistVertexData     = listVertexDataPos;
						        plistObjectIndices  = listIndicesPos;
                                pFaceConnectivity   = faceConnectivityPos;
                                pMeshConnectivity   = meshConnectivityPos;
                                pdicClippedEdges    = dicClippedEdgesPos;
                                pdicRemappedIndices = dicRemappedIndicesPos;
					        }

                            nNewIndex1 = -1;
                            nNewIndex2 = -1;
                            nNewIndex3 = -1;
                            nNewIndex4 = -1;
                            bEdge      = false;

                            // Find edges in cache

                            if(pdicClippedEdges.ContainsKey(clippedEdgeKey))
                            {
                                nClippedCacheHits++;
                                bEdge      = true;
                                nNewIndex3 = pdicClippedEdges[clippedEdgeKey].GetSecondIndex(nIndex3);
                                nNewIndex4 = pdicClippedEdges[clippedEdgeKey].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex3)) nNewIndex3 = pdicRemappedIndices[nIndex3];
                            }

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex1 == -1)
                            {
                                if(pdicRemappedIndices.ContainsKey(nIndex1))
                                {
                                    nNewIndex1 = pdicRemappedIndices[nIndex1];
                                }
                            }
                            if(nNewIndex1 == -1)
                            {
                                nNewIndex1 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                                pdicRemappedIndices[nIndex1] = nNewIndex1;
                            }

                            if(nNewIndex3 == -1)
                            {
                                nNewIndex3 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                                pdicRemappedIndices[nIndex3] = nNewIndex3;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex1);
                            plistObjectIndices.Add(nNewIndex4);
                            plistObjectIndices.Add(nNewIndex3);

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v1, v4, nHashV1, nHashV4, nNewIndex1, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v3, nHashV4, nHashV3, nNewIndex4, nNewIndex3);
                                pFaceConnectivity.AddEdge(nSubMesh, v3, v1, nHashV3, nHashV1, nNewIndex3, nNewIndex1);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV1, nHashV4, plistVertexData[nNewIndex1].v3Vertex, plistVertexData[nNewIndex4].v3Vertex);

                            if(bEdge == false) pdicClippedEdges.Add(clippedEdgeKey, new ClippedEdge(nIndex2, nIndex3, nNewIndex2, nNewIndex3, nNewIndex4));
                        }
                        else if(bAlmostInPlane2)
                        {
                            // v2 almost on the clipping plane

					        if(fSide3 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
						        plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }

                            clippedEdgeKey = new EdgeKeyByIndex(nIndex3, nIndex1);

                            if(pdicClippedEdges.ContainsKey(clippedEdgeKey))
                            {
                                nClippedCacheHits++;
                                bEdge      = true;
                                nNewIndex3 = pdicClippedEdges[clippedEdgeKey].GetFirstIndex(nIndex3);
                                nNewIndex4 = pdicClippedEdges[clippedEdgeKey].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex3)) nNewIndex3 = pdicRemappedIndices[nIndex3];
                            }

                            // Clip if not present in clipped edge list

                            EdgeKeyByHash clippedEdgeKeyHash = new EdgeKeyByHash(nHashV3, nHashV1);

                            if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                            {
                                nHashV4 = dicClipVerticesHash[clippedEdgeKeyHash];
                            }
                            else
                            {
                                nHashV4 = nCurrentVertexHash++;
                                dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV4);
                            }

                            VertexData vd4 = new VertexData(nHashV4);

                            if(bEdge == false)
                            {
                                if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex3, nIndex1, v3, v1, planeSplit, ref vd4) == false)
                                {
                                    return false;
                                }
                            }

                            // Add geometry of one side

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex2 == -1)
                            {
                                if(pdicRemappedIndices.ContainsKey(nIndex2))
                                {
                                    nNewIndex2 = pdicRemappedIndices[nIndex2];
                                }
                            }
                            if(nNewIndex2 == -1)
                            {
                                nNewIndex2 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                                pdicRemappedIndices[nIndex2] = nNewIndex2;
                            }

                            if(nNewIndex3 == -1)
                            {
                                nNewIndex3 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                                pdicRemappedIndices[nIndex3] = nNewIndex3;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex2);
                            plistObjectIndices.Add(nNewIndex3);
                            plistObjectIndices.Add(nNewIndex4);

                            Vector3 v4 = plistVertexData[nNewIndex4].v3Vertex;

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v2, v3, nHashV2, nHashV3, nNewIndex2, nNewIndex3);
                                pFaceConnectivity.AddEdge(nSubMesh, v3, v4, nHashV3, nHashV4, nNewIndex3, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v2, nHashV4, nHashV2, nNewIndex4, nNewIndex2);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV4, nHashV2, plistVertexData[nNewIndex4].v3Vertex, plistVertexData[nNewIndex2].v3Vertex);

                            if(bEdge == false) pdicClippedEdges.Add(clippedEdgeKey, new ClippedEdge(nIndex3, nIndex1, nNewIndex3, nNewIndex1, nNewIndex4));

                            // Add geometry of other side

					        if(fSide1 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
                                plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }
					        else
					        {
						        plistVertexData     = listVertexDataPos;
						        plistObjectIndices  = listIndicesPos;
                                pFaceConnectivity   = faceConnectivityPos;
                                pMeshConnectivity   = meshConnectivityPos;
                                pdicClippedEdges    = dicClippedEdgesPos;
                                pdicRemappedIndices = dicRemappedIndicesPos;
					        }

                            nNewIndex1 = -1;
                            nNewIndex2 = -1;
                            nNewIndex4 = -1;
                            bEdge      = false;

                            // Find edges in cache

                            if(pdicClippedEdges.ContainsKey(clippedEdgeKey))
                            {
                                nClippedCacheHits++;
                                bEdge      = true;
                                nNewIndex1 = pdicClippedEdges[clippedEdgeKey].GetSecondIndex(nIndex1);
                                nNewIndex4 = pdicClippedEdges[clippedEdgeKey].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex1)) nNewIndex1 = pdicRemappedIndices[nIndex1];
                            }

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex1 == -1)
                            {
                                nNewIndex1 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                                pdicRemappedIndices[nIndex1] = nNewIndex1;
                            }

                            if(nNewIndex2 == -1)
                            {
                                if(pdicRemappedIndices.ContainsKey(nIndex2))
                                {
                                    nNewIndex2 = pdicRemappedIndices[nIndex2];
                                }
                            }
                            if(nNewIndex2 == -1)
                            {
                                nNewIndex2 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                                pdicRemappedIndices[nIndex2] = nNewIndex2;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex2);
                            plistObjectIndices.Add(nNewIndex4);
                            plistObjectIndices.Add(nNewIndex1);

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v2, v4, nHashV2, nHashV4, nNewIndex2, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v1, nHashV4, nHashV1, nNewIndex4, nNewIndex1);
                                pFaceConnectivity.AddEdge(nSubMesh, v1, v2, nHashV1, nHashV2, nNewIndex1, nNewIndex2);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV2, nHashV4, plistVertexData[nNewIndex2].v3Vertex, plistVertexData[nNewIndex4].v3Vertex);

                            if(bEdge == false) pdicClippedEdges.Add(clippedEdgeKey, new ClippedEdge(nIndex3, nIndex1, nNewIndex3, nNewIndex1, nNewIndex4));
                        }
                        else if(bAlmostInPlane3)
                        {
                            // v3 almost on the clipping plane

					        if(fSide1 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
						        plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }

                            clippedEdgeKey = new EdgeKeyByIndex(nIndex1, nIndex2);

                            if(pdicClippedEdges.ContainsKey(clippedEdgeKey))
                            {
                                nClippedCacheHits++;
                                bEdge      = true;
                                nNewIndex1 = pdicClippedEdges[clippedEdgeKey].GetFirstIndex(nIndex1);
                                nNewIndex4 = pdicClippedEdges[clippedEdgeKey].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex1)) nNewIndex1 = pdicRemappedIndices[nIndex1];
                            }

                            // Clip if not present in clipped edge list

                            EdgeKeyByHash clippedEdgeKeyHash = new EdgeKeyByHash(nHashV1, nHashV2);

                            if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                            {
                                nHashV4 = dicClipVerticesHash[clippedEdgeKeyHash];
                            }
                            else
                            {
                                nHashV4 = nCurrentVertexHash++;
                                dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV4);
                            }

                            VertexData vd4 = new VertexData(nHashV4);

                            if(bEdge == false)
                            {
                                if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex1, nIndex2, v1, v2, planeSplit, ref vd4) == false)
                                {
                                    return false;
                                }
                            }

                            // Add geometry of one side

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex1 == -1)
                            {
                                nNewIndex1 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                                pdicRemappedIndices[nIndex1] = nNewIndex1;
                            }

                            if(nNewIndex3 == -1)
                            {
                                if(pdicRemappedIndices.ContainsKey(nIndex3))
                                {
                                    nNewIndex3 = pdicRemappedIndices[nIndex3];
                                }
                            }
                            if(nNewIndex3 == -1)
                            {
                                nNewIndex3 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                                pdicRemappedIndices[nIndex3] = nNewIndex3;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex1);
                            plistObjectIndices.Add(nNewIndex4);
                            plistObjectIndices.Add(nNewIndex3);

                            Vector3 v4 = plistVertexData[nNewIndex4].v3Vertex;

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v1, v4, nHashV1, nHashV4, nNewIndex1, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v3, nHashV4, nHashV3, nNewIndex4, nNewIndex3);
                                pFaceConnectivity.AddEdge(nSubMesh, v3, v1, nHashV3, nHashV1, nNewIndex3, nNewIndex1);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV4, nHashV3, plistVertexData[nNewIndex4].v3Vertex, plistVertexData[nNewIndex3].v3Vertex);

                            if(bEdge == false) pdicClippedEdges.Add(clippedEdgeKey, new ClippedEdge(nIndex1, nIndex2, nNewIndex1, nNewIndex2, nNewIndex4));

                            // Add geometry of other side

					        if(fSide2 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
                                plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }
					        else
					        {
						        plistVertexData     = listVertexDataPos;
						        plistObjectIndices  = listIndicesPos;
                                pFaceConnectivity   = faceConnectivityPos;
                                pMeshConnectivity   = meshConnectivityPos;
                                pdicClippedEdges    = dicClippedEdgesPos;
                                pdicRemappedIndices = dicRemappedIndicesPos;
					        }

                            nNewIndex2 = -1;
                            nNewIndex3 = -1;
                            nNewIndex4 = -1;
                            bEdge      = false;

                            // Find edges in cache

                            if(pdicClippedEdges.ContainsKey(clippedEdgeKey))
                            {
                                nClippedCacheHits++;
                                bEdge      = true;
                                nNewIndex2 = pdicClippedEdges[clippedEdgeKey].GetSecondIndex(nIndex2);
                                nNewIndex4 = pdicClippedEdges[clippedEdgeKey].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex2)) nNewIndex2 = pdicRemappedIndices[nIndex2];
                            }

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex2 == -1)
                            {
                                nNewIndex2 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                                pdicRemappedIndices[nIndex2] = nNewIndex2;
                            }

                            if(nNewIndex3 == -1)
                            {
                                if(pdicRemappedIndices.ContainsKey(nIndex3))
                                {
                                    nNewIndex3 = pdicRemappedIndices[nIndex3];
                                }
                            }
                            if(nNewIndex3 == -1)
                            {
                                nNewIndex3 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                                pdicRemappedIndices[nIndex3] = nNewIndex3;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex2);
                            plistObjectIndices.Add(nNewIndex3);
                            plistObjectIndices.Add(nNewIndex4);

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v2, v3, nHashV2, nHashV3, nNewIndex2, nNewIndex3);
                                pFaceConnectivity.AddEdge(nSubMesh, v3, v4, nHashV3, nHashV4, nNewIndex3, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v2, nHashV4, nHashV2, nNewIndex4, nNewIndex2);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV3, nHashV4, plistVertexData[nNewIndex3].v3Vertex, plistVertexData[nNewIndex4].v3Vertex);

                            if(bEdge == false) pdicClippedEdges.Add(clippedEdgeKey, new ClippedEdge(nIndex1, nIndex2, nNewIndex1, nNewIndex2, nNewIndex4));
                        }
                    }
		            else
		            {
			            if(fSide1 * fSide2 < 0.0f)
			            {
				            // v1 and v2 on different sides

				            if(fSide2 * fSide3 < 0.0f)
				            {
					            // ... and v3 on same side as v1

					            if(fSide1 < 0.0f)
					            {
						            plistVertexData     = listVertexDataNeg;
						            plistObjectIndices  = listIndicesNeg;
                                    pFaceConnectivity   = faceConnectivityNeg;
                                    pMeshConnectivity   = meshConnectivityNeg;
                                    pdicClippedEdges    = dicClippedEdgesNeg;
                                    pdicRemappedIndices = dicRemappedIndicesNeg;
					            }

                                int  nNewIndex1 = -1;
                                int  nNewIndex2 = -1;
                                int  nNewIndex3 = -1;
                                int  nNewIndex4 = -1;
                                int  nNewIndex5 = -1;
                                int  nHashV4    = -1;
                                int  nHashV5    = -1;
                                bool bEdgeKey1  = false;
                                bool bEdgeKey2  = false;

                                EdgeKeyByIndex edgeKey1 = new EdgeKeyByIndex(nIndex1, nIndex2);
                                EdgeKeyByIndex edgeKey2 = new EdgeKeyByIndex(nIndex2, nIndex3);

                                // Find edges in cache

                                if(pdicClippedEdges.ContainsKey(edgeKey1))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey1  = true;
                                    nNewIndex1 = pdicClippedEdges[edgeKey1].GetFirstIndex(nIndex1);
                                    nNewIndex4 = pdicClippedEdges[edgeKey1].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex1)) nNewIndex1 = pdicRemappedIndices[nIndex1];
                                }

                                if(pdicClippedEdges.ContainsKey(edgeKey2))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey2  = true;
                                    nNewIndex3 = pdicClippedEdges[edgeKey2].GetSecondIndex(nIndex3);
                                    nNewIndex5 = pdicClippedEdges[edgeKey2].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex3)) nNewIndex3 = pdicRemappedIndices[nIndex3];
                                }

                                // Clip if not present in clipped edge list

                                EdgeKeyByHash clippedEdgeKeyHash = new EdgeKeyByHash(nHashV1, nHashV2);

                                if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                                {
                                    nHashV4 = dicClipVerticesHash[clippedEdgeKeyHash];
                                }
                                else
                                {
                                    nHashV4 = nCurrentVertexHash++;
                                    dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV4);
                                }

                                clippedEdgeKeyHash = new EdgeKeyByHash(nHashV2, nHashV3);

                                if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                                {
                                    nHashV5 = dicClipVerticesHash[clippedEdgeKeyHash];
                                }
                                else
                                {
                                    nHashV5 = nCurrentVertexHash++;
                                    dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV5);
                                }

                                VertexData vd4 = new VertexData(nHashV4), vd5 = new VertexData(nHashV5);

                                if(bEdgeKey1 == false)
                                {
                                    if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex1, nIndex2, v1, v2, planeSplit, ref vd4) == false)
                                    {
                                        return false;
                                    }
                                }

                                if(bEdgeKey2 == false)
                                {
                                    if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex2, nIndex3, v2, v3, planeSplit, ref vd5) == false)
                                    {
                                        return false;
                                    }
                                }

					            // Add geometry of one side

                                // Add vertex data for all data not present in remapped list

                                if(nNewIndex1 == -1)
                                {
                                    nNewIndex1 = plistVertexData.Count;
                                    plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                                    pdicRemappedIndices[nIndex1] = nNewIndex1;
                                }

                                if(nNewIndex3 == -1)
                                {
                                    nNewIndex3 = plistVertexData.Count;
                                    plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                                    pdicRemappedIndices[nIndex3] = nNewIndex3;
                                }

                                if(nNewIndex4 == -1)
                                {
                                    nNewIndex4 = plistVertexData.Count;
                                    plistVertexData.Add(vd4);
                                }

                                if(nNewIndex5 == -1)
                                {
                                    nNewIndex5 = plistVertexData.Count;
                                    plistVertexData.Add(vd5);
                                }

                                if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                                {
                                    pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                                }

                                plistObjectIndices.Add(nNewIndex1);
                                plistObjectIndices.Add(nNewIndex4);
                                plistObjectIndices.Add(nNewIndex5);

                                if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                                {
                                    pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                                }

                                plistObjectIndices.Add(nNewIndex1);
                                plistObjectIndices.Add(nNewIndex5);
                                plistObjectIndices.Add(nNewIndex3);

                                Vector3 v4 = plistVertexData[nNewIndex4].v3Vertex;
                                Vector3 v5 = plistVertexData[nNewIndex5].v3Vertex;

                                if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                                {
                                    pFaceConnectivity.AddEdge(nSubMesh, v1, v4, nHashV1, nHashV4, nNewIndex1, nNewIndex4);
                                    pFaceConnectivity.AddEdge(nSubMesh, v4, v5, nHashV4, nHashV5, nNewIndex4, nNewIndex5);
                                    pFaceConnectivity.AddEdge(nSubMesh, v5, v1, nHashV5, nHashV1, nNewIndex5, nNewIndex1);
                                    pFaceConnectivity.AddEdge(nSubMesh, v1, v5, nHashV1, nHashV5, nNewIndex1, nNewIndex5);
                                    pFaceConnectivity.AddEdge(nSubMesh, v5, v3, nHashV5, nHashV3, nNewIndex5, nNewIndex3);
                                    pFaceConnectivity.AddEdge(nSubMesh, v3, v1, nHashV3, nHashV1, nNewIndex3, nNewIndex1);
                                }

                                // Update cap edges and cache

                                if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV4, nHashV5, plistVertexData[nNewIndex4].v3Vertex, plistVertexData[nNewIndex5].v3Vertex);

                                if(pdicClippedEdges.ContainsKey(edgeKey1) == false) pdicClippedEdges.Add(edgeKey1, new ClippedEdge(nIndex1, nIndex2, nNewIndex1, nNewIndex2, nNewIndex4));
                                if(pdicClippedEdges.ContainsKey(edgeKey2) == false) pdicClippedEdges.Add(edgeKey2, new ClippedEdge(nIndex2, nIndex3, nNewIndex2, nNewIndex3, nNewIndex5));

                                // Add geometry of other side

					            if(fSide2 < 0.0f)
					            {
						            plistVertexData     = listVertexDataNeg;
                                    plistObjectIndices  = listIndicesNeg;
                                    pFaceConnectivity   = faceConnectivityNeg;
                                    pMeshConnectivity   = meshConnectivityNeg;
                                    pdicClippedEdges    = dicClippedEdgesNeg;
                                    pdicRemappedIndices = dicRemappedIndicesNeg;
					            }
					            else
					            {
						            plistVertexData     = listVertexDataPos;
						            plistObjectIndices  = listIndicesPos;
                                    pFaceConnectivity   = faceConnectivityPos;
                                    pMeshConnectivity   = meshConnectivityPos;
                                    pdicClippedEdges    = dicClippedEdgesPos;
                                    pdicRemappedIndices = dicRemappedIndicesPos;
					            }

                                nNewIndex1 = -1;
                                nNewIndex2 = -1;
                                nNewIndex3 = -1;
                                nNewIndex4 = -1;
                                nNewIndex5 = -1;
                                bEdgeKey1  = false;
                                bEdgeKey2  = false;

                                // Find edges in cache

                                if(pdicClippedEdges.ContainsKey(edgeKey1))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey1  = true;
                                    nNewIndex2 = pdicClippedEdges[edgeKey1].GetSecondIndex(nIndex2);
                                    nNewIndex4 = pdicClippedEdges[edgeKey1].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex2)) nNewIndex2 = pdicRemappedIndices[nIndex2];
                                }

                                if(pdicClippedEdges.ContainsKey(edgeKey2))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey2  = true;
                                    nNewIndex2 = pdicClippedEdges[edgeKey2].GetFirstIndex(nIndex2);
                                    nNewIndex5 = pdicClippedEdges[edgeKey2].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex2)) nNewIndex2 = pdicRemappedIndices[nIndex2];
                                }

                                // Add vertex data for all data not present in remapped list

                                if(nNewIndex2 == -1)
                                {
                                    nNewIndex2 = plistVertexData.Count;
                                    plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                                    pdicRemappedIndices[nIndex2] = nNewIndex2;
                                }

                                if(nNewIndex4 == -1)
                                {
                                    nNewIndex4 = plistVertexData.Count;
                                    plistVertexData.Add(vd4);
                                }

                                if(nNewIndex5 == -1)
                                {
                                    nNewIndex5 = plistVertexData.Count;
                                    plistVertexData.Add(vd5);
                                }

                                if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                                {
                                    pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                                }

                                plistObjectIndices.Add(nNewIndex4);
                                plistObjectIndices.Add(nNewIndex2);
                                plistObjectIndices.Add(nNewIndex5);

                                if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                                {
                                    pFaceConnectivity.AddEdge(nSubMesh, v4, v2, nHashV4, nHashV2, nNewIndex4, nNewIndex2);
                                    pFaceConnectivity.AddEdge(nSubMesh, v2, v5, nHashV2, nHashV5, nNewIndex2, nNewIndex5);
                                    pFaceConnectivity.AddEdge(nSubMesh, v5, v4, nHashV5, nHashV4, nNewIndex5, nNewIndex4);
                                }

                                // Update cap edges and cache

                                if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV5, nHashV4, plistVertexData[nNewIndex5].v3Vertex, plistVertexData[nNewIndex4].v3Vertex);

                                if(pdicClippedEdges.ContainsKey(edgeKey1) == false) pdicClippedEdges.Add(edgeKey1, new ClippedEdge(nIndex1, nIndex2, nNewIndex1, nNewIndex2, nNewIndex4));
                                if(pdicClippedEdges.ContainsKey(edgeKey2) == false) pdicClippedEdges.Add(edgeKey2, new ClippedEdge(nIndex2, nIndex3, nNewIndex2, nNewIndex3, nNewIndex5));
				            }
				            else
				            {
					            // ... and v3 on same side as v2

					            if(fSide1 < 0.0f)
					            {
						            plistVertexData     = listVertexDataNeg;
						            plistObjectIndices  = listIndicesNeg;
                                    pFaceConnectivity   = faceConnectivityNeg;
                                    pMeshConnectivity   = meshConnectivityNeg;
                                    pdicClippedEdges    = dicClippedEdgesNeg;
                                    pdicRemappedIndices = dicRemappedIndicesNeg;
					            }

                                int  nNewIndex1 = -1;
                                int  nNewIndex2 = -1;
                                int  nNewIndex3 = -1;
                                int  nNewIndex4 = -1;
                                int  nNewIndex5 = -1;
                                int  nHashV4    = -1;
                                int  nHashV5    = -1;
                                bool bEdgeKey1  = false;
                                bool bEdgeKey3  = false;

                                EdgeKeyByIndex edgeKey1 = new EdgeKeyByIndex(nIndex1, nIndex2);
                                EdgeKeyByIndex edgeKey3 = new EdgeKeyByIndex(nIndex1, nIndex3);

                                // Find edges in cache

                                if(pdicClippedEdges.ContainsKey(edgeKey1))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey1  = true;
                                    nNewIndex1 = pdicClippedEdges[edgeKey1].GetFirstIndex(nIndex1);
                                    nNewIndex4 = pdicClippedEdges[edgeKey1].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex1)) nNewIndex1 = pdicRemappedIndices[nIndex1];
                                }

                                if(pdicClippedEdges.ContainsKey(edgeKey3))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey3  = true;
                                    nNewIndex1 = pdicClippedEdges[edgeKey3].GetFirstIndex(nIndex1);
                                    nNewIndex5 = pdicClippedEdges[edgeKey3].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex1)) nNewIndex1 = pdicRemappedIndices[nIndex1];
                                }

                                // Clip if not present in clipped edge list

                                EdgeKeyByHash clippedEdgeKeyHash = new EdgeKeyByHash(nHashV1, nHashV2);

                                if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                                {
                                    nHashV4 = dicClipVerticesHash[clippedEdgeKeyHash];
                                }
                                else
                                {
                                    nHashV4 = nCurrentVertexHash++;
                                    dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV4);
                                }

                                clippedEdgeKeyHash = new EdgeKeyByHash(nHashV1, nHashV3);

                                if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                                {
                                    nHashV5 = dicClipVerticesHash[clippedEdgeKeyHash];
                                }
                                else
                                {
                                    nHashV5 = nCurrentVertexHash++;
                                    dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV5);
                                }

                                VertexData vd4 = new VertexData(nHashV4), vd5 = new VertexData(nHashV5);

                                if(bEdgeKey1 == false)
                                {
                                    if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex1, nIndex2, v1, v2, planeSplit, ref vd4) == false)
                                    {
                                        return false;
                                    }
                                }

                                if(bEdgeKey3 == false)
                                {
                                    if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex1, nIndex3, v1, v3, planeSplit, ref vd5) == false)
                                    {
                                        return false;
                                    }
                                }

					            // Add geometry of one side

                                // Add vertex data for all data not present in remapped list

                                if(nNewIndex1 == -1)
                                {
                                    nNewIndex1 = plistVertexData.Count;
                                    plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                                    pdicRemappedIndices[nIndex1] = nNewIndex1;
                                }

                                if(nNewIndex4 == -1)
                                {
                                    nNewIndex4 = plistVertexData.Count;
                                    plistVertexData.Add(vd4);
                                }

                                if(nNewIndex5 == -1)
                                {
                                    nNewIndex5 = plistVertexData.Count;
                                    plistVertexData.Add(vd5);
                                }

                                if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                                {
                                    pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                                }

                                plistObjectIndices.Add(nNewIndex1);
                                plistObjectIndices.Add(nNewIndex4);
                                plistObjectIndices.Add(nNewIndex5);

                                Vector3 v4 = plistVertexData[nNewIndex4].v3Vertex;
                                Vector3 v5 = plistVertexData[nNewIndex5].v3Vertex;

                                if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                                {
                                    pFaceConnectivity.AddEdge(nSubMesh, v1, v4, nHashV1, nHashV4, nNewIndex1, nNewIndex4);
                                    pFaceConnectivity.AddEdge(nSubMesh, v4, v5, nHashV4, nHashV5, nNewIndex4, nNewIndex5);
                                    pFaceConnectivity.AddEdge(nSubMesh, v5, v1, nHashV5, nHashV1, nNewIndex5, nNewIndex1);
                                }

                                // Update cap edges and cache

                                if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV4, nHashV5, plistVertexData[nNewIndex4].v3Vertex, plistVertexData[nNewIndex5].v3Vertex);

                                if(pdicClippedEdges.ContainsKey(edgeKey1) == false) pdicClippedEdges.Add(edgeKey1, new ClippedEdge(nIndex1, nIndex2, nNewIndex1, nNewIndex2, nNewIndex4));
                                if(pdicClippedEdges.ContainsKey(edgeKey3) == false) pdicClippedEdges.Add(edgeKey3, new ClippedEdge(nIndex1, nIndex3, nNewIndex1, nNewIndex3, nNewIndex5));

                                // Add geometry of other side

					            if(fSide2 < 0.0f)
					            {
						            plistVertexData     = listVertexDataNeg;
                                    plistObjectIndices  = listIndicesNeg;
                                    pFaceConnectivity   = faceConnectivityNeg;
                                    pMeshConnectivity   = meshConnectivityNeg;
                                    pdicClippedEdges    = dicClippedEdgesNeg;
                                    pdicRemappedIndices = dicRemappedIndicesNeg;
					            }
					            else
					            {
						            plistVertexData     = listVertexDataPos;
						            plistObjectIndices  = listIndicesPos;
                                    pFaceConnectivity   = faceConnectivityPos;
                                    pMeshConnectivity   = meshConnectivityPos;
                                    pdicClippedEdges    = dicClippedEdgesPos;
                                    pdicRemappedIndices = dicRemappedIndicesPos;
					            }

                                nNewIndex1 = -1;
                                nNewIndex2 = -1;
                                nNewIndex3 = -1;
                                nNewIndex4 = -1;
                                nNewIndex5 = -1;
                                bEdgeKey1  = false;
                                bEdgeKey3  = false;

                                // Find edges in cache

                                if(pdicClippedEdges.ContainsKey(edgeKey1))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey1  = true;
                                    nNewIndex2 = pdicClippedEdges[edgeKey1].GetSecondIndex(nIndex2);
                                    nNewIndex4 = pdicClippedEdges[edgeKey1].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex2)) nNewIndex2 = pdicRemappedIndices[nIndex2];
                                }

                                if(pdicClippedEdges.ContainsKey(edgeKey3))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey3  = true;
                                    nNewIndex3 = pdicClippedEdges[edgeKey3].GetSecondIndex(nIndex3);
                                    nNewIndex5 = pdicClippedEdges[edgeKey3].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex3)) nNewIndex3 = pdicRemappedIndices[nIndex3];
                                }

                                // Add vertex data for all data not present in remapped list

                                if(nNewIndex2 == -1)
                                {
                                    nNewIndex2 = plistVertexData.Count;
                                    plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                                    pdicRemappedIndices[nIndex2] = nNewIndex2;
                                }

                                if(nNewIndex3 == -1)
                                {
                                    nNewIndex3 = plistVertexData.Count;
                                    plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                                    pdicRemappedIndices[nIndex3] = nNewIndex3;
                                }

                                if(nNewIndex4 == -1)
                                {
                                    nNewIndex4 = plistVertexData.Count;
                                    plistVertexData.Add(vd4);
                                }

                                if(nNewIndex5 == -1)
                                {
                                    nNewIndex5 = plistVertexData.Count;
                                    plistVertexData.Add(vd5);
                                }

                                if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                                {
                                    pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                                }

                                plistObjectIndices.Add(nNewIndex4);
                                plistObjectIndices.Add(nNewIndex2);
                                plistObjectIndices.Add(nNewIndex3);

                                if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                                {
                                    pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                                }

                                plistObjectIndices.Add(nNewIndex4);
                                plistObjectIndices.Add(nNewIndex3);
                                plistObjectIndices.Add(nNewIndex5);

                                if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                                {
                                    pFaceConnectivity.AddEdge(nSubMesh, v4, v2, nHashV4, nHashV2, nNewIndex4, nNewIndex2);
                                    pFaceConnectivity.AddEdge(nSubMesh, v2, v3, nHashV2, nHashV3, nNewIndex2, nNewIndex3);
                                    pFaceConnectivity.AddEdge(nSubMesh, v3, v4, nHashV3, nHashV4, nNewIndex3, nNewIndex4);
                                    pFaceConnectivity.AddEdge(nSubMesh, v4, v3, nHashV4, nHashV3, nNewIndex4, nNewIndex3);
                                    pFaceConnectivity.AddEdge(nSubMesh, v3, v5, nHashV3, nHashV5, nNewIndex3, nNewIndex5);
                                    pFaceConnectivity.AddEdge(nSubMesh, v5, v4, nHashV5, nHashV4, nNewIndex5, nNewIndex4);
                                }

                                // Update cap edges and cache

                                if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV5, nHashV4, plistVertexData[nNewIndex5].v3Vertex, plistVertexData[nNewIndex4].v3Vertex);

                                if(pdicClippedEdges.ContainsKey(edgeKey1) == false) pdicClippedEdges.Add(edgeKey1, new ClippedEdge(nIndex1, nIndex2, nNewIndex1, nNewIndex2, nNewIndex4));
                                if(pdicClippedEdges.ContainsKey(edgeKey3) == false) pdicClippedEdges.Add(edgeKey3, new ClippedEdge(nIndex1, nIndex3, nNewIndex1, nNewIndex3, nNewIndex5));
				            }
			            }
			            else if(fSide2 * fSide3 < 0.0f)
			            {
				            // v1 and v2 on same side, and v3 on different side

					        if(fSide1 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
						        plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }

                            int  nNewIndex1 = -1;
                            int  nNewIndex2 = -1;
                            int  nNewIndex3 = -1;
                            int  nNewIndex4 = -1;
                            int  nNewIndex5 = -1;
                            int  nHashV4    = -1;
                            int  nHashV5    = -1;
                            bool bEdgeKey2  = false;
                            bool bEdgeKey3  = false;

                            EdgeKeyByIndex edgeKey2 = new EdgeKeyByIndex(nIndex2, nIndex3);
                            EdgeKeyByIndex edgeKey3 = new EdgeKeyByIndex(nIndex1, nIndex3);

                            // Find edges in cache

                            if(pdicClippedEdges.ContainsKey(edgeKey2))
                            {
                                nClippedCacheHits++;
                                bEdgeKey2  = true;
                                nNewIndex2 = pdicClippedEdges[edgeKey2].GetFirstIndex(nIndex2);
                                nNewIndex5 = pdicClippedEdges[edgeKey2].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex2)) nNewIndex2 = pdicRemappedIndices[nIndex2];
                            }

                            if(pdicClippedEdges.ContainsKey(edgeKey3))
                            {
                                nClippedCacheHits++;
                                bEdgeKey3  = true;
                                nNewIndex1 = pdicClippedEdges[edgeKey3].GetFirstIndex(nIndex1);
                                nNewIndex4 = pdicClippedEdges[edgeKey3].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex1)) nNewIndex1 = pdicRemappedIndices[nIndex1];
                            }

                            // Clip if not present in clipped edge list

                            EdgeKeyByHash clippedEdgeKeyHash = new EdgeKeyByHash(nHashV1, nHashV3);

                            if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                            {
                                nHashV4 = dicClipVerticesHash[clippedEdgeKeyHash];
                            }
                            else
                            {
                                nHashV4 = nCurrentVertexHash++;
                                dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV4);
                            }

                            clippedEdgeKeyHash = new EdgeKeyByHash(nHashV2, nHashV3);

                            if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                            {
                                nHashV5 = dicClipVerticesHash[clippedEdgeKeyHash];
                            }
                            else
                            {
                                nHashV5 = nCurrentVertexHash++;
                                dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV5);
                            }

                            VertexData vd4 = new VertexData(nHashV4), vd5 = new VertexData(nHashV5);

                            if(bEdgeKey2 == false)
                            {
                                if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex2, nIndex3, v2, v3, planeSplit, ref vd5) == false)
                                {
                                    return false;
                                }
                            }

                            if(bEdgeKey3 == false)
                            {
                                if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex1, nIndex3, v1, v3, planeSplit, ref vd4) == false)
                                {
                                    return false;
                                }
                            }

					        // Add geometry of one side

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex1 == -1)
                            {
                                nNewIndex1 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                                pdicRemappedIndices[nIndex1] = nNewIndex1;
                            }

                            if(nNewIndex2 == -1)
                            {
                                nNewIndex2 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                                pdicRemappedIndices[nIndex2] = nNewIndex2;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(nNewIndex5 == -1)
                            {
                                nNewIndex5 = plistVertexData.Count;
                                plistVertexData.Add(vd5);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex2);
                            plistObjectIndices.Add(nNewIndex5);
                            plistObjectIndices.Add(nNewIndex4);

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex2);
                            plistObjectIndices.Add(nNewIndex4);
                            plistObjectIndices.Add(nNewIndex1);

                            Vector3 v4 = plistVertexData[nNewIndex4].v3Vertex;
                            Vector3 v5 = plistVertexData[nNewIndex5].v3Vertex;

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v2, v5, nHashV2, nHashV5, nNewIndex2, nNewIndex5);
                                pFaceConnectivity.AddEdge(nSubMesh, v5, v4, nHashV5, nHashV4, nNewIndex5, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v2, nHashV4, nHashV2, nNewIndex4, nNewIndex2);
                                pFaceConnectivity.AddEdge(nSubMesh, v2, v4, nHashV2, nHashV4, nNewIndex2, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v1, nHashV4, nHashV1, nNewIndex4, nNewIndex1);
                                pFaceConnectivity.AddEdge(nSubMesh, v1, v2, nHashV1, nHashV2, nNewIndex1, nNewIndex2);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV5, nHashV4, plistVertexData[nNewIndex5].v3Vertex, plistVertexData[nNewIndex4].v3Vertex);

                            if(pdicClippedEdges.ContainsKey(edgeKey2) == false) pdicClippedEdges.Add(edgeKey2, new ClippedEdge(nIndex2, nIndex3, nNewIndex2, nNewIndex3, nNewIndex5));
                            if(pdicClippedEdges.ContainsKey(edgeKey3) == false) pdicClippedEdges.Add(edgeKey3, new ClippedEdge(nIndex1, nIndex3, nNewIndex1, nNewIndex3, nNewIndex4));

                            // Add geometry of other side

					        if(fSide3 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
                                plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }
					        else
					        {
						        plistVertexData     = listVertexDataPos;
						        plistObjectIndices  = listIndicesPos;
                                pFaceConnectivity   = faceConnectivityPos;
                                pMeshConnectivity   = meshConnectivityPos;
                                pdicClippedEdges    = dicClippedEdgesPos;
                                pdicRemappedIndices = dicRemappedIndicesPos;
					        }

                            nNewIndex1 = -1;
                            nNewIndex2 = -1;
                            nNewIndex3 = -1;
                            nNewIndex4 = -1;
                            nNewIndex5 = -1;
                            bEdgeKey2  = false;
                            bEdgeKey3  = false;

                            // Find edges in cache

                            if(pdicClippedEdges.ContainsKey(edgeKey2))
                            {
                                nClippedCacheHits++;
                                bEdgeKey2  = true;
                                nNewIndex3 = pdicClippedEdges[edgeKey2].GetSecondIndex(nIndex3);
                                nNewIndex5 = pdicClippedEdges[edgeKey2].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex3)) nNewIndex3 = pdicRemappedIndices[nIndex3];
                            }

                            if(pdicClippedEdges.ContainsKey(edgeKey3))
                            {
                                nClippedCacheHits++;
                                bEdgeKey3  = true;
                                nNewIndex3 = pdicClippedEdges[edgeKey3].GetSecondIndex(nIndex3);
                                nNewIndex4 = pdicClippedEdges[edgeKey3].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex3)) nNewIndex3 = pdicRemappedIndices[nIndex3];
                            }

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex3 == -1)
                            {
                                nNewIndex3 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                                pdicRemappedIndices[nIndex3] = nNewIndex3;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(nNewIndex5 == -1)
                            {
                                nNewIndex5 = plistVertexData.Count;
                                plistVertexData.Add(vd5);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex5);
                            plistObjectIndices.Add(nNewIndex3);
                            plistObjectIndices.Add(nNewIndex4);

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v5, v3, nHashV5, nHashV3, nNewIndex5, nNewIndex3);
                                pFaceConnectivity.AddEdge(nSubMesh, v3, v4, nHashV3, nHashV4, nNewIndex3, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v5, nHashV4, nHashV5, nNewIndex4, nNewIndex5);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV4, nHashV5, plistVertexData[nNewIndex4].v3Vertex, plistVertexData[nNewIndex5].v3Vertex);

                            if(pdicClippedEdges.ContainsKey(edgeKey2) == false) pdicClippedEdges.Add(edgeKey2, new ClippedEdge(nIndex2, nIndex3, nNewIndex2, nNewIndex3, nNewIndex5));
                            if(pdicClippedEdges.ContainsKey(edgeKey3) == false) pdicClippedEdges.Add(edgeKey3, new ClippedEdge(nIndex1, nIndex3, nNewIndex1, nNewIndex3, nNewIndex4));
			            }
		            }
	            }
            }

//          Debug.Log("Clipped cache hits " + nClippedCacheHits + " clipped cache misses " + nClippedCacheMisses);

            // Compute transforms

            Vector3 v3CenterPos = Vector3.zero;

            if(listVertexDataPos.Count > 0)
            {
                Vector3 v3Min = Vector3.zero, v3Max = Vector3.zero;
                MeshData.ComputeMinMax(listVertexDataPos, ref v3Min, ref v3Max);
                v3CenterPos = (v3Min + v3Max) * 0.5f;
            }

            Matrix4x4 mtxToLocalPos = Matrix4x4.TRS(v3CenterPos, meshDataIn.qRotation, meshDataIn.v3Scale).inverse;

            if(splitOptions.bVerticesAreLocal)
            {
                mtxToLocalPos = Matrix4x4.TRS(v3CenterPos, Quaternion.identity, Vector3.one).inverse;
            }

            Vector3 v3CenterNeg = Vector3.zero;

            if(listVertexDataNeg.Count > 0)
            {
                Vector3 v3Min = Vector3.zero, v3Max = Vector3.zero;
                MeshData.ComputeMinMax(listVertexDataNeg, ref v3Min, ref v3Max);
                v3CenterNeg = (v3Min + v3Max) * 0.5f;
            }

            Matrix4x4 mtxToLocalNeg = Matrix4x4.TRS(v3CenterNeg, meshDataIn.qRotation, meshDataIn.v3Scale).inverse;

            if(splitOptions.bVerticesAreLocal)
            {
                mtxToLocalNeg = Matrix4x4.TRS(v3CenterNeg, Quaternion.identity, Vector3.one).inverse;
            }

            // Resolve cap outline and add its geometry

            List<List<Vector3>> listlistResolvedCapVertices   = new List<List<Vector3>>();
            List<List<int>>     listlistResolvedCapHashValues = new List<List<int>>();

            bool bNeedsConnectivityPostprocess = false;

            Matrix4x4 mtxPlane = Matrix4x4.TRS(v3PlanePoint, Quaternion.LookRotation(Vector3.Cross(v3PlaneNormal, v3PlaneRight), v3PlaneNormal), Vector3.one);

            if(dicCapEdges.Count > 0 && splitOptions.bForceNoCap == false)
            {
                if(ResolveCap(dicCapEdges, listlistResolvedCapVertices, listlistResolvedCapHashValues, fracturedComponent))
	            {
                    if(listlistResolvedCapVertices.Count > 1)
                    {
                        // There's more than one closed cap. We need to postprocess the mesh because there may be more than one object on a side of the plane as a result of the clipping.
                        bNeedsConnectivityPostprocess = (fracturedComponent.GenerateIslands && (splitOptions.bForceNoIslandGeneration == false)) ? true : false;
                    }

                    TriangulateConstrainedDelaunay( listlistResolvedCapVertices, listlistResolvedCapHashValues, splitOptions.bForceCapVertexSoup, fracturedComponent, bNeedsConnectivityPostprocess, faceConnectivityPos, faceConnectivityNeg,
                                                    meshConnectivityPos, meshConnectivityNeg, splitOptions.nForceMeshConnectivityHash, nSplitCloseSubMesh,
                                                    mtxPlane, mtxToLocalPos, mtxToLocalNeg, v3CenterPos, v3CenterNeg,
                                                    alistIndicesPos, listVertexDataPos, alistIndicesNeg, listVertexDataNeg);
                }
                else
                {
                    if(fracturedComponent.Verbose) Debug.LogWarning("Error resolving cap");
                }
            }

            // Postprocess if necessary
            if(bNeedsConnectivityPostprocess)
            {
                // Search for multiple objects inside each meshes

                List<MeshData> listIslandsPos = MeshData.PostProcessConnectivity(meshDataIn, faceConnectivityPos, meshConnectivityPos, alistIndicesPos, listVertexDataPos, nSplitCloseSubMesh, nCurrentVertexHash, false);
                List<MeshData> listIslandsNeg = new List<MeshData>();

                if(splitOptions.bIgnoreNegativeSide == false)
                {
                    listIslandsNeg = MeshData.PostProcessConnectivity(meshDataIn, faceConnectivityNeg, meshConnectivityNeg, alistIndicesNeg, listVertexDataNeg, nSplitCloseSubMesh, nCurrentVertexHash, false);
                }

                // Sometimes we are feed a mesh with multiple islands as input. If this is the case, compute connectivity between islands at this point.

                List<MeshData> listTotalIslands = new List<MeshData>();
                listTotalIslands.AddRange(listIslandsPos);
                listTotalIslands.AddRange(listIslandsNeg);

                if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoIslandConnectionInfo == false)
                {
                    for(int i = 0; i < listTotalIslands.Count; i++)
                    {
                        if(progress != null && listTotalIslands.Count > 10 && splitOptions.bForceNoProgressInfo == false)
                        {
                            progress("Fracturing", "Processing island connectivity...", i / (float)listTotalIslands.Count);
                            if(Fracturer.IsFracturingCancelled()) return false;
                        }

                        for(int j = 0; j < listTotalIslands.Count; j++)
                        {
                            if(i != j)
                            {
                                ComputeIslandsMeshDataConnectivity(fracturedComponent, splitOptions.bVerticesAreLocal, listTotalIslands[i], listTotalIslands[j]);
                            }
                        }
                    }
                }

                listMeshDatasPosOut.AddRange(listIslandsPos);
                listMeshDatasNegOut.AddRange(listIslandsNeg);
            }
            else
            {
                // Create new MeshDatas

                if(listVertexDataPos.Count > 0 && alistIndicesPos.Length > 0)
                {
                    MeshData newMeshData = new MeshData(meshDataIn.aMaterials, alistIndicesPos, listVertexDataPos, nSplitCloseSubMesh, v3CenterPos, meshDataIn.qRotation, meshDataIn.v3Scale, mtxToLocalPos, false, false);
                    newMeshData.meshDataConnectivity = meshConnectivityPos;
                    newMeshData.nCurrentVertexHash   = nCurrentVertexHash;
                    listMeshDatasPosOut.Add(newMeshData);
                }

                if(listVertexDataNeg.Count > 0 && alistIndicesNeg.Length > 0 && splitOptions.bIgnoreNegativeSide == false)
                {
                    MeshData newMeshData = new MeshData(meshDataIn.aMaterials, alistIndicesNeg, listVertexDataNeg, nSplitCloseSubMesh, v3CenterNeg, meshDataIn.qRotation, meshDataIn.v3Scale, mtxToLocalNeg, false, false);
                    newMeshData.meshDataConnectivity = meshConnectivityNeg;
                    newMeshData.nCurrentVertexHash   = nCurrentVertexHash;
                    listMeshDatasNegOut.Add(newMeshData);
                }
            }

            return true;
        }
Beispiel #23
0
    /// <summary>
    /// Saves the given information about an evolution simulation of a creature in a file, so that
    /// it can be loaded and continued at the same generation again.
    /// The filename cannot contain dots (.)
    /// Throws: IllegalFilenameException
    ///
    /// Returns: The filename of the saved file.
    /// </summary>
    //public static string WriteSaveFile(string creatureName, Evolution.Task task, int timePerGen, int generationNumber, string creatureSaveData, List<ChromosomeInfo> bestChromosomes, List<string> currentChromosomes) {
    public static string WriteSaveFile(string creatureName, EvolutionSettings settings, NeuralNetworkSettings networkSettings, int generationNumber, string creatureSaveData, List <ChromosomeStats> bestChromosomes, List <string> currentChromosomes)
    {
        var splitOptions = new SplitOptions();

        var date = System.DateTime.Now.ToString("yyyy-MM-dd");
        //var taskName = Evolution.TaskToString(task);

        var filename = string.Format("{0} - {1} - {2} - Gen({3}).txt", creatureName, settings.task, date, generationNumber);            // MAYBE IMPORTANT FOR THE FUTURE: Changed from Gen:i to Gen(i)

        var stringBuilder = new StringBuilder();

        // Add the task type
        //stringBuilder.AppendLine(((int)task).ToString());

        // Add the version number
        stringBuilder.AppendLine(string.Format("v {0}", version.ToString()));
        stringBuilder.Append(splitOptions.COMPONENT_SEPARATOR);

        // Add the time per generation
        //stringBuilder.AppendLine(settings.simulationTime.ToString());
        //stringBuilder.Append(COMPONENT_SEPARATOR);

        // Add the encoded evolution settings
        stringBuilder.AppendLine(settings.Encode());
        stringBuilder.Append(splitOptions.COMPONENT_SEPARATOR);

        // Add the encoded neural network settings
        stringBuilder.AppendLine(networkSettings.Encode());
        stringBuilder.Append(splitOptions.COMPONENT_SEPARATOR);

        // Add the creature save data
        stringBuilder.AppendLine(creatureSaveData);
        stringBuilder.Append(splitOptions.COMPONENT_SEPARATOR);

        // Add the list of best chromosomes
        foreach (var chromosome in bestChromosomes)
        {
            stringBuilder.AppendLine(chromosome.ToString());
        }
        stringBuilder.Append(splitOptions.COMPONENT_SEPARATOR);

        // Add the list of current chromosomes
        foreach (var chromosome in currentChromosomes)
        {
            stringBuilder.AppendLine(chromosome);
        }
        stringBuilder.Append(splitOptions.COMPONENT_SEPARATOR);

        var path = RESOURCE_PATH;         //Path.Combine(RESOURCE_PATH, SAVE_FOLDER);

        path = Path.Combine(path, filename);

        int counter = 2;

        while (System.IO.File.Exists(path))
        {
            //var pattern = new Regex(@"( \d+)?.txt");
            var pattern = @"( \d+)?.txt";

            filename = Regex.Replace(filename, pattern, string.Format(" {0}.txt", counter));
            path     = Path.Combine(RESOURCE_PATH, filename);
            //path = path.Replace(".txt", string.Format(" ({0}).txt", counter));
            //filename = filename.Replace(".txt", string.Format(" ({0}).txt", counter));
            counter++;
        }

        CreateSaveFolder();
        File.WriteAllText(path, stringBuilder.ToString());

        return(filename);
    }
Beispiel #24
0
    /// <summary>
    /// Loads the simulation from save file of format version 1.
    /// </summary>
    /// <param name="filename">The Filename has to end on .txt .</param>
    /// <param name="content">The Content of the save file.</param>
    private static void LoadSimulationFromSaveFileV1(string filename, string content, SplitOptions splitOptions, CreatureBuilder creatureBuilder, Evolution evolution)
    {
        var creatureName = filename.Split('-')[0].Replace(" ", "");

        var components = content.Split(splitOptions.SPLIT_ARRAY, System.StringSplitOptions.None);

        // extract the save data from the file contents.
        var taskType = EvolutionTaskUtil.TaskForNumber(int.Parse(components[0].Replace(Environment.NewLine, "")));

        var timePerGen = int.Parse(components[1].Replace(Environment.NewLine, ""));

        var creatureData = components[2];

        CreatureSaver.LoadCreatureFromContents(creatureData, creatureBuilder);

        var bestChromosomesData = new List <string>(components[3].Split(splitOptions.NEWLINE_SPLIT, StringSplitOptions.None));
        var bestChromosomes     = new List <ChromosomeStats>();

        foreach (var chromosomeData in bestChromosomesData)
        {
            if (chromosomeData != "")
            {
                var chromosomeInfo  = ChromosomeInfo.FromString(chromosomeData);
                var chromosomeStats = new ChromosomeStats(chromosomeInfo.chromosome, new CreatureStats());
                chromosomeStats.stats.fitness = chromosomeInfo.fitness;

                bestChromosomes.Add(chromosomeStats);
            }
        }

        var chromosomeComponents = components[4].Split(splitOptions.NEWLINE_SPLIT, StringSplitOptions.None);
        var currentChromosomes   = new List <string>();

        foreach (var chromosome in chromosomeComponents)
        {
            if (chromosome != "")
            {
                currentChromosomes.Add(chromosome);
            }
        }

        var currentGeneration = bestChromosomes.Count + 1;

        var settings = new EvolutionSettings();

        settings.task           = taskType;
        settings.simulationTime = timePerGen;
        settings.populationSize = currentChromosomes.Count;

        var networkSettings = new NeuralNetworkSettings();

        evolution.Settings = settings;

        creatureBuilder.ContinueEvolution(evolution, () => {
            CreatureSaver.SaveCurrentCreatureName(creatureName);
            evolution.ContinueEvolution(currentGeneration, settings, networkSettings, bestChromosomes, currentChromosomes);
        });
    }
Beispiel #25
0
            public static SpaceTreeNode BuildSpaceTree(MeshData meshDataIn, int nSubdivisionLevels, FracturedObject fracturedComponent, ProgressDelegate progress = null)
            {
                if(nSubdivisionLevels < 1)
                {
                    return null;
                }

                SplitOptions splitOptions = new SplitOptions();

                splitOptions.bForceNoIslandGeneration     = true;
                splitOptions.bForceNoChunkConnectionInfo  = true;            
                splitOptions.bForceNoIslandConnectionInfo = true;
                splitOptions.bForceNoCap                  = false;
                splitOptions.bVerticesAreLocal            = true;

                SpaceTreeNode nodeRoot = new SpaceTreeNode();

                nodeRoot.listMeshDatasSpace = new List<MeshData>();
                nodeRoot.listMeshDatasSpace.Add(meshDataIn);
                nodeRoot.nLevel   = 0;
                nodeRoot.nSplitsX = 0;
                nodeRoot.nSplitsY = 0;
                nodeRoot.nSplitsZ = 0;
                nodeRoot.v3Min    = meshDataIn.v3Min;
                nodeRoot.v3Max    = meshDataIn.v3Max;

                Queue<SpaceTreeNode> queueNodes = new Queue<SpaceTreeNode>();
                queueNodes.Enqueue(nodeRoot);

                int nTotalSubdivisions   = 0;
                int nCurrentSubdivisions = 0;
                int nSplitsX             = 0;
                int nSplitsY             = 0;
                int nSplitsZ             = 0;
                
                for(int i = 0; i < nSubdivisionLevels; i++)
                {
                    nTotalSubdivisions += Mathf.RoundToInt(Mathf.Pow(2, i));
                }

                while(queueNodes.Count > 0)
                {
                    SpaceTreeNode nodeCurrent = queueNodes.Dequeue();

                    List<MeshData> listMeshDataPos;
                    List<MeshData> listMeshDataNeg;

                    if(nodeCurrent.nLevel < nSubdivisionLevels)
                    {
                        if(progress != null)
                        {
                            progress("Fracturing", string.Format("Pre computing space volume (split {0}/{1}, Depth {2})", nCurrentSubdivisions + 1, nTotalSubdivisions, nodeCurrent.nLevel + 1), Mathf.Clamp01((float)nCurrentSubdivisions / (float)nTotalSubdivisions));
                        }

                        if(Fracturer.IsFracturingCancelled())
                        {
                            return null;
                        }

                        Vector3 v3Normal = Vector3.up;
                        Vector3 v3Right  = Vector3.right;
                        Vector3 v3Pos    = (nodeCurrent.v3Min + nodeCurrent.v3Max) * 0.5f;

                        float fSizeX = nodeCurrent.v3Max.x - nodeCurrent.v3Min.x;
                        float fSizeY = nodeCurrent.v3Max.y - nodeCurrent.v3Min.y;
                        float fSizeZ = nodeCurrent.v3Max.z - nodeCurrent.v3Min.z;

                        Vector3 v3MinNeg = nodeCurrent.v3Min;
                        Vector3 v3MaxNeg = nodeCurrent.v3Max;
                        Vector3 v3MinPos = nodeCurrent.v3Min;
                        Vector3 v3MaxPos = nodeCurrent.v3Max;

                        if(fSizeX >= fSizeY && fSizeX >= fSizeZ)
                        {
                            v3Normal = Vector3.right;
                            v3Right  = Vector3.forward;

                            v3MaxNeg.x = v3Pos.x;
                            v3MinPos.x = v3Pos.x;

                            nSplitsX++;
                        }
                        else if(fSizeY >= fSizeX && fSizeY >= fSizeZ)
                        {
                            v3Normal = Vector3.up;
                            v3Right  = Vector3.right;

                            v3MaxNeg.y = v3Pos.y;
                            v3MinPos.y = v3Pos.y;

                            nSplitsY++;
                        }
                        else
                        {
                            v3Normal = Vector3.forward;
                            v3Right  = Vector3.right;

                            v3MaxNeg.z = v3Pos.z;
                            v3MinPos.z = v3Pos.z;

                            nSplitsZ++;
                        }

                        foreach(MeshData meshData in nodeCurrent.listMeshDatasSpace)
                        {
                            if(SplitMeshUsingPlane(meshData, fracturedComponent, splitOptions, v3Normal, v3Right, v3Pos, out listMeshDataPos, out listMeshDataNeg, progress) == true)
                            {
                                nodeCurrent.nodeOneSide = new SpaceTreeNode();
                                nodeCurrent.nodeOneSide.listMeshDatasSpace = listMeshDataNeg;
                                nodeCurrent.nodeOneSide.v3Min    = v3MinNeg;
                                nodeCurrent.nodeOneSide.v3Max    = v3MaxNeg;
                                nodeCurrent.nodeOneSide.nLevel   = nodeCurrent.nLevel + 1;
                                nodeCurrent.nodeOneSide.nSplitsX = nSplitsX;
                                nodeCurrent.nodeOneSide.nSplitsY = nSplitsY;
                                nodeCurrent.nodeOneSide.nSplitsZ = nSplitsZ;

                                queueNodes.Enqueue(nodeCurrent.nodeOneSide);

                                nodeCurrent.nodeOtherSide = new SpaceTreeNode();
                                nodeCurrent.nodeOtherSide.listMeshDatasSpace = listMeshDataPos;
                                nodeCurrent.nodeOtherSide.v3Min    = v3MinPos;
                                nodeCurrent.nodeOtherSide.v3Max    = v3MaxPos;
                                nodeCurrent.nodeOtherSide.nLevel   = nodeCurrent.nLevel + 1;
                                nodeCurrent.nodeOtherSide.nSplitsX = nSplitsX;
                                nodeCurrent.nodeOtherSide.nSplitsY = nSplitsY;
                                nodeCurrent.nodeOtherSide.nSplitsZ = nSplitsZ;

                                queueNodes.Enqueue(nodeCurrent.nodeOtherSide);
                            }
                        }

                        nCurrentSubdivisions++;
                    }
                }

                return nodeRoot;
            }
Beispiel #26
0
        public IEnumerable<Property> Split(SplitOptions options = SplitOptions.Recursive)
        {
            if (!IsShorthand)
                throw new InvalidOperationException("Only short hand property can be splitted.");

            if (options == SplitOptions.NonRecursive)
            {
                return NonRecursiveSplit();
            }
            else
            {
                return RecursiveSplit();
            }
        }
Beispiel #27
0
    /// <summary>
    /// Loads the simulation from save file with the format version 2
    /// </summary>
    /// <param name="filename">The Filename has to end on .txt .</param>
    /// <param name="content">The Content of the save file.</param>
    private static void LoadSimulationFromSaveFileV2(string filename, string content, SplitOptions splitOptions, CreatureBuilder creatureBuilder, Evolution evolution)
    {
        var creatureName = filename.Split('-')[0].Replace(" ", "");

        var components = content.Split(splitOptions.SPLIT_ARRAY, System.StringSplitOptions.None);

        var evolutionSettings = EvolutionSettings.Decode(components[1]);
        var networkSettings   = NeuralNetworkSettings.Decode(components[2]);

        var creatureData = components[3];

        CreatureSaver.LoadCreatureFromContents(creatureData, creatureBuilder);

        var bestChromosomesData = new List <string>(components[4].Split(splitOptions.NEWLINE_SPLIT, StringSplitOptions.None));
        var bestChromosomes     = new List <ChromosomeStats>();

        foreach (var chromosomeData in bestChromosomesData)
        {
            if (chromosomeData != "")
            {
                bestChromosomes.Add(ChromosomeStats.FromString(chromosomeData));
            }
        }

        var chromosomeComponents = components[5].Split(splitOptions.NEWLINE_SPLIT, StringSplitOptions.None);
        var currentChromosomes   = new List <string>();

        foreach (var chromosome in chromosomeComponents)
        {
            if (chromosome != "")
            {
                currentChromosomes.Add(chromosome);
            }
        }

        var currentGeneration = bestChromosomes.Count + 1;

        evolution.Settings = evolutionSettings;

        creatureBuilder.ContinueEvolution(evolution, () => {
            CreatureSaver.SaveCurrentCreatureName(creatureName);
            evolution.ContinueEvolution(currentGeneration, evolutionSettings, networkSettings, bestChromosomes, currentChromosomes);
        });
    }
	public HashSet<Construction> SetPhysicalConnection(HexMetrics.Direction relativeDirection, 
													PhysicalConnectionType newConnectionType, 
													SplitOptions splitOption)
	{
		ConnectionDescription connDesc = _connectedParts[(int)relativeDirection];
//		PhysicalConnectionType originalConnection = connDesc.connectionType;
		if (connDesc.connectedPart == null)
		{
			
			// disconnecting part
			connDesc.connectionType = PhysicalConnectionType.None;
			SetWeldSprite(relativeDirection, false);
			
			if (ParentConstruction != null)
			{
				if (splitOption == SplitOptions.SplitIfNecessary)
				{
					return ParentConstruction.CheckForSplitsOrJoins();
				}
				return new HashSet<Construction> { ParentConstruction };
			}
			
			return new HashSet<Construction> ();
		}
		
		HexMetrics.Direction oppositeDirection = ConnectedsOpposite(relativeDirection);
		ConnectionDescription otherConnDesc = connDesc.connectedPart._connectedParts[(int)oppositeDirection];
		
		bool weldableHere = Weldable(relativeDirection);
		bool weldableThere = connDesc.connectedPart.Weldable(oppositeDirection);
//		Debug.Log("Checking weldability: "+direction+"("+weldableHere+") <-> "+oppositeDirection+"("+weldabelThere+")");
		if (weldableHere && weldableThere)
		{
			connDesc.connectionType = newConnectionType;
			otherConnDesc.connectionType = newConnectionType;
		}
		else
		{
			connDesc.connectionType = PhysicalConnectionType.None;
			otherConnDesc.connectionType = PhysicalConnectionType.None;
		}
		
		// update the weld sprites
		SetWeldSprite(relativeDirection, connDesc.connectionType != PhysicalConnectionType.None);
		connDesc.connectedPart.SetWeldSprite(oppositeDirection, connDesc.connectionType != PhysicalConnectionType.None);
		
		
		//if we are disconnecting the side (None) or if it's not weldable, make sure that the parts are not connected
		if (connDesc.connectionType == PhysicalConnectionType.None)
		{
			otherConnDesc.connectedPart = null;
			connDesc.connectedPart = null;
			
			if (ParentConstruction == null)
			{
				Debug.LogWarning ("Parent is null!");
			}
			else
			{
				// check that by disconnecting a side, we have not split the construction up
				if (splitOption == SplitOptions.SplitIfNecessary)
				{
					return ParentConstruction.CheckForSplitsOrJoins();
				}
				return new HashSet<Construction> { ParentConstruction };
			}
		}
		if (ParentConstruction != null)
		{
			return new HashSet<Construction> { ParentConstruction };
		}
		return new HashSet<Construction>();
	}
Beispiel #29
0
 public static IEnumerable <string> EnumerateValues(Regex regex, string input, int count, SplitOptions options)
 {
     return(EnumerateValues(regex, input, count, (regex.RightToLeft) ? input.Length : 0, options));
 }
Beispiel #30
0
 /// <summary>
 /// Splits the specified input string a specified number of times at the positions defined by the regular expression into an enumerable collection of strings, using the specified split options.
 /// The search starts at a specified position in the input string.
 /// </summary>
 /// <param name="regex">The regular expression to be matched.</param>
 /// <param name="input">The string to split.</param>
 /// <param name="count">The maximum number of times the input can be split.</param>
 /// <param name="startAt">The position in the input string where the search starts.</param>
 /// <param name="splitOptions">A bitwise combination of the enumeration values that specify options.</param>
 /// <exception cref="ArgumentNullException"><paramref name="regex"/> or <paramref name="input"/> is <c>null</c>.</exception>
 /// <exception cref="ArgumentOutOfRangeException"><paramref name="count"/> is less than zero.
 /// <para><paramref name="startAt"/> is less than zero or greater than the length of <paramref name="input"/>.</para>
 /// </exception>
 public static IEnumerable <string> EnumerateSplit(this Regex regex, string input, int count, int startAt, SplitOptions splitOptions)
 {
     return(RegexSplit.EnumerateValues(regex, input, count, startAt, splitOptions));
 }
Beispiel #31
0
        private static object SplitWithPattern(System.Management.Automation.ExecutionContext context, IScriptExtent errorPosition, IEnumerable <string> content, string separatorPattern, int limit, SplitOptions options)
        {
            if (((options & SplitOptions.SimpleMatch) == 0) && ((options & SplitOptions.RegexMatch) == 0))
            {
                options |= SplitOptions.RegexMatch;
            }
            if (((options & SplitOptions.SimpleMatch) != 0) && ((options & ~(SplitOptions.IgnoreCase | SplitOptions.SimpleMatch)) != 0))
            {
                throw InterpreterError.NewInterpreterException(null, typeof(ParseException), errorPosition, "InvalidSplitOptionCombination", ParserStrings.InvalidSplitOptionCombination, new object[0]);
            }
            if ((options & (SplitOptions.Singleline | SplitOptions.Multiline)) == (SplitOptions.Singleline | SplitOptions.Multiline))
            {
                throw InterpreterError.NewInterpreterException(null, typeof(ParseException), errorPosition, "InvalidSplitOptionCombination", ParserStrings.InvalidSplitOptionCombination, new object[0]);
            }
            if ((options & SplitOptions.SimpleMatch) != 0)
            {
                separatorPattern = Regex.Escape(separatorPattern);
            }
            if (limit < 0)
            {
                limit = 0;
            }
            RegexOptions  options2 = parseRegexOptions(options);
            Regex         regex    = NewRegex(separatorPattern, options2);
            List <string> list     = new List <string>();

            foreach (string str in content)
            {
                string[] items = regex.Split(str, limit, 0);
                ExtendList <string>(list, items);
            }
            return(list.ToArray());
        }
Beispiel #32
0
 public static IEnumerable<string> EnumerateValues(Regex regex, string input, SplitOptions options)
 {
     return EnumerateValues(regex, input, 0, options);
 }
Beispiel #33
0
        public static string[] SplitAndKeep(this string strTargetString, char[] delims, SplitOptions splSplitOptions = SplitOptions.BEFORE_DELIMITER)
        {
            int start = 0;
            int index = 0;

            List <string> strSplitString = new List <string>();

            int iCrazyStop = 0;

            while ((index = strTargetString.IndexOfAny(delims, start)) != -1)
            {
                iCrazyStop++;

                if (iCrazyStop > 9000)
                {
                    Debug.LogError("infinite loop detected");
                    break;
                }



                if (splSplitOptions == SplitOptions.BEFORE_DELIMITER)
                {
                    //add string
                    strSplitString.Add(strTargetString.Substring(Mathf.Clamp((start - 1), 0, int.MaxValue), index - Mathf.Clamp((start - 1), 0, int.MaxValue)));
                    index++;
                }


                if (splSplitOptions == SplitOptions.AFTER_DELIMITER)
                {
                    index++;
                    //add string
                    strSplitString.Add(strTargetString.Substring(start, index - start));
                }

                int iHolder = start;
                start = index;

                index = iHolder;
            }


            //return the final string component
            if (splSplitOptions == SplitOptions.BEFORE_DELIMITER)
            {
                //add string
                strSplitString.Add(strTargetString.Substring(Mathf.Clamp((start - 1), 0, int.MaxValue)));
            }
            if (splSplitOptions == SplitOptions.AFTER_DELIMITER)
            {
                strSplitString.Add(strTargetString.Substring(start));
            }

            return(strSplitString.ToArray());

            //return new string[]{"Derp"};
        }
Beispiel #34
0
 public static IEnumerable<string> EnumerateValues(Regex regex, string input, int count, SplitOptions options)
 {
     return EnumerateValues(regex, input, count, regex.RightToLeft ? input.Length : 0, options);
 }
		// ----- Split() -----------------------------------------------------------------------------------------------------------------------------

		/// <summary>
		/// Returns a string collection that contains the substrings that are
		/// delimited by <paramref name="separator"/>.
		/// </summary>
		/// <param name="Value"></param>
		/// <param name="separator"></param>
		/// <param name="options"></param>
		/// <returns></returns>
		public static List<string> Split( this string Value, string separator, SplitOptions options )
		{
			List<string> result;
			string[] array;
			string temp;

			result = new List<string>();
			array = Value.Split(new string[] { separator },
					(options & SplitOptions.RemoveEmptyEntries) == SplitOptions.RemoveEmptyEntries ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None);

			foreach (string val in array) {
				if ((options & SplitOptions.TrimEachEntry) == SplitOptions.TrimEachEntry) {
					temp = val.Trim();
				} else {
					temp = val;
				}

				if ((options & SplitOptions.RemoveEmptyEntries) == SplitOptions.RemoveEmptyEntries) {
					if (temp.Length > 0) {
						result.Add(temp);
					}
				} else {
					result.Add(temp);
				}
			}

			return result;
		}
 protected override void SetOptions(SplitOptions options)
 {
     options.Direction = Direction.Vertical;
 }
Beispiel #37
0
 public static IEnumerable <string> EnumerateValues(Regex regex, string input, SplitOptions options)
 {
     return(EnumerateValues(regex, input, 0, options));
 }
 protected override void SetOptions(SplitOptions options)
 {
     options.Direction = Direction.Horizontal;
 }
Beispiel #39
0
        public static IEnumerable <string> EnumerateValues(Regex regex, string input, int count, int startAt, SplitOptions options)
        {
            if (regex == null)
            {
                throw new ArgumentNullException(nameof(regex));
            }

            if (input == null)
            {
                throw new ArgumentNullException(nameof(input));
            }

            if (count < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            if (startAt < 0 || startAt > input.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(startAt));
            }

            if (count == 1)
            {
                yield return(input);

                yield break;
            }

            Match firstMatch = regex.Match(input, startAt);

            if (!firstMatch.Success)
            {
                yield return(input);

                yield break;
            }

            bool omitGroupValues = (options & SplitOptions.OmitGroupValues) != 0;
            bool omitEmptyValues = (options & SplitOptions.OmitEmptyValues) != 0;
            int  prevIndex       = 0;

            count--;

            foreach (Match match in (regex.RightToLeft) ? EnumerateMatchesRightToLeft(firstMatch, count) : EnumerateMatches(firstMatch, count))
            {
                if (!omitEmptyValues || ((match.Index - prevIndex) > 0))
                {
                    yield return(input.Substring(prevIndex, match.Index - prevIndex));
                }

                prevIndex = match.Index + match.Length;

                if (!omitGroupValues)
                {
                    foreach (Group group in (regex.RightToLeft) ? EnumerateGroupsRightToLeft(match) : EnumerateGroups(match))
                    {
                        if (group.Success && (!omitEmptyValues || group.Length > 0))
                        {
                            yield return(group.Value);
                        }
                    }
                }
            }

            yield return(input.Substring(prevIndex, input.Length - prevIndex));
        }
Beispiel #40
0
        protected override void Execute(CodeActivityContext context)
        {
            try
            {
                SplitOptions  splitter = Splitter;
                List <string> temp     = new List <string>();
                String[]      stringsplitter;
                string        input;
                switch (splitter)
                {
                case SplitOptions.Comma:
                    input          = Input.Get(context);
                    stringsplitter = new String[] { "," };
                    var tmp = input.Split(stringsplitter, StringSplitOptions.RemoveEmptyEntries);
                    temp = tmp.ToList <string>();
                    break;

                case SplitOptions.Newline:
                    input          = Input.Get(context);
                    stringsplitter = new String[] { Environment.NewLine.ToString() };
                    tmp            = input.Split(stringsplitter, StringSplitOptions.RemoveEmptyEntries);
                    temp           = tmp.ToList <string>();
                    break;

                case SplitOptions.Pipe:
                    input          = Input.Get(context);
                    stringsplitter = new String[] { "|" };
                    tmp            = input.Split(stringsplitter, StringSplitOptions.RemoveEmptyEntries);
                    temp           = tmp.ToList <string>();
                    break;

                case SplitOptions.Custom:
                    input = Input.Get(context);
                    string[] customSplitter = CustomSplitter.Get(context);
                    if (customSplitter != null)
                    {
                        tmp  = input.Split(customSplitter, StringSplitOptions.RemoveEmptyEntries);
                        temp = tmp.ToList <string>();
                        break;
                    }
                    else
                    {
                        throw new NullReferenceException("Custom splitter cannot be null if Custom is selected");
                    }

                default:
                    Console.WriteLine("Invalid Splitter");
                    break;
                }

                Result.Set(context, temp.ToArray());
            }
            catch (NullReferenceException e)
            {
                Console.WriteLine(e.Message);
                throw;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                throw;
            }
        }