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}."); }
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!"); } }
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); } }
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); } }
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; }
public static void RestoreOptions() { isMerge = false; splitInFiles = new Dictionary <string, bool>(); splitOpts = new SplitOptions(); splitOutPath = segmentIDs = mergeOrigFile = mergeInPath = mergeInfoFile = string.Empty; }
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); } }
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); }
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); }
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 ); }
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)); }
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(); }
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); }
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)); } }
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}."); }
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; } }
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; }
/// <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); }
/// <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); }); }
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 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(); } }
/// <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>(); }
public static IEnumerable <string> EnumerateValues(Regex regex, string input, int count, SplitOptions options) { return(EnumerateValues(regex, input, count, (regex.RightToLeft) ? input.Length : 0, options)); }
/// <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)); }
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()); }
public static IEnumerable<string> EnumerateValues(Regex regex, string input, SplitOptions options) { return EnumerateValues(regex, input, 0, options); }
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"}; }
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; }
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; }
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)); }
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; } }