public void Cleanup() { _parameters = null; progressDelegate = null; pdePerVertex = null; heapNodes = null; heap = null; mesh = null; }
// the mesh needs to have its edge list and creases calculated public void InitializeCollapsing(MeshEdges _mesh, SimplifyParameters parameters) { mesh = _mesh; _parameters = parameters; // Gain some time by avoiding unecessary calculations if (_mesh.hasBoneWeights == false) { parameters.boneWeightProtection = 0.0f; } if (_mesh.hasVertexColors == false) { parameters.vertexColorProtection = 0.0f; } _calculatePdePerVertex(); // construct heap int numEdges = mesh.edgeCount(); heapNodes = new HeapNode <CollapseInfo> [numEdges]; heap = new MinHeap <CollapseInfo>(); int progressCounter = kProgressGroups; float t = Time.realtimeSinceStartup; for (int i = 0; i < numEdges; ++i) { CollapseInfo pc = new CollapseInfo(); _calculateEdgeCost(i, pc); heapNodes[i] = heap.Insert(new HeapNode <CollapseInfo>(pc.cost, pc)); progressCounter--; if (progressCounter <= 0) { progressCounter = kProgressGroups; if (Time.realtimeSinceStartup - t > kProgressInterval && progressDelegate != null) { t = Time.realtimeSinceStartup; progressDelegate("Initialize Edge " + i + "/" + numEdges, 0.1f * ((float)i) / ((float)numEdges)); } } } // shortcut for fastest calc noPenalties = (parameters.checkTopology == false && parameters.maxEdgesPerVertex == 0 && parameters.preventNonManifoldEdges == false && parameters.boneWeightProtection <= 0.0f && parameters.vertexColorProtection <= 0.0f); //sharpnessLimitSqr = parameters.minTriangleShape*parameters.minTriangleShape; //if (parameters.minTriangleShape < 0.0f) sharpnessLimitSqr = 0.0f; }
override public void Calculate(ref KrablMesh.MeshEdges mesh, KMProcessorProgram parentProgram = null) { base.Calculate(ref mesh); KrablMesh.Simplify sim = new KrablMesh.Simplify(); KrablMesh.SimplifyParameters par = new KrablMesh.SimplifyParameters(); sim.progressDelegate = delegate(string text, float val) { ReportProgress(text, val); }; // par.maximumError = maximumError; par.targetFaceCount = targetTriangleCount; if (platformID != null) { for (int i = 0; i < ttcOverridePlatform.Length; ++i) { if (platformID.Equals(ttcOverridePlatform[i])) { par.targetFaceCount = ttcOverrideTargetTriangleCount[i]; break; } } } par.recalculateVertexPositions = allowVertexReposition; par.preventNonManifoldEdges = preventNonManifoldEdges; par.borderWeight = borders; par.creaseWeight = creases; par.uvSeamWeight = uvSeams; par.uv2SeamWeight = uv2Seams; par.materialSeamWeight = materialSeams; // par.minTriangleShape = minTriangleShape; par.boneWeightProtection = boneWeightProtection; par.vertexColorProtection = vertexColorProtection; // par.vertexNormalProtection = vertexNormalProtection; sim.Execute(ref mesh, par); }
/// <summary> /// Simplify a mesh by collapsing edges until the target face count is reached. /// </summary> /// <param name='unityMesh'> /// The mesh to simplify. /// </param> /// <param name='targetFaceCount'> /// The number of triangles to reduce the mesh to. If this is higher than the initial /// number of triangles, no processing will occur. /// </param> /// <param name='highQuality'> /// Use slower, but more precise calculations. /// </param> public static void SimplifyMesh(Mesh unityMesh, int targetFaceCount, bool highQuality = true) { KrablMesh.MeshEdges kmesh = new KrablMesh.MeshEdges(); KrablMesh.Simplify sim = new KrablMesh.Simplify(); KrablMesh.SimplifyParameters simpars = new KrablMesh.SimplifyParameters(); KrablMesh.ImportExport.UnityMeshToMeshEdges(unityMesh, kmesh); simpars.targetFaceCount = targetFaceCount; simpars.recalculateVertexPositions = highQuality; simpars.checkTopology = !highQuality; simpars.maxEdgesPerVertex = highQuality ? 18 : 0; if (highQuality == false) { simpars.preventNonManifoldEdges = false; simpars.boneWeightProtection = 0.0f; simpars.vertexColorProtection = 0.0f; } sim.Execute(ref kmesh, simpars); KrablMesh.ImportExport.MeshEdgesToUnityMesh(kmesh, unityMesh); }
/// <summary> /// Perform mesh simplification. /// </summary> /// <param name='mesh'> /// A mesh (KrablMesh.MeshEdges) to simplify. The mesh will be changed and might even be replaced by a new mesh structure. /// </param> /// <param name='parameters'> /// The parameters to use during the simplification. /// </param> public void Execute(ref MeshEdges mesh, SimplifyParameters parameters) { if (mesh.vertCount() == 0) { return; } if (mesh.topology != MeshTopology.Triangles) { Ops.TriangulateWithEdges(mesh); } if (progressDelegate != null) { progressDelegate("Initialize", 0.0f); } InitializeCollapsing(mesh, parameters); if (parameters.edgesToCollapse > 0) { Collapse(parameters.edgesToCollapse); } else if (parameters.targetFaceCount > 0) { int totalFacesToRemove = mesh.numValidFaces - parameters.targetFaceCount; int progressCounter = 0; float t = Time.realtimeSinceStartup + kProgressInterval; while (mesh.numValidFaces > parameters.targetFaceCount) { Collapse(1); progressCounter--; if (progressCounter <= 0) { progressCounter = kProgressGroups; if (Time.realtimeSinceStartup - t > kProgressInterval && progressDelegate != null) { t = Time.realtimeSinceStartup; int facesRemoved = totalFacesToRemove - (mesh.numValidFaces - parameters.targetFaceCount); progressDelegate("Mesh Faces " + mesh.numValidFaces + "->" + parameters.targetFaceCount, 0.1f + 0.9f * ((float)facesRemoved) / ((float)totalFacesToRemove)); } } } } else if (parameters.maximumError > 0) { // Determine size of mesh to scale errors meshSize = _determineMeshSize(mesh); int totalFacesToRemove = mesh.numValidFaces; float t = Time.realtimeSinceStartup + kProgressInterval; float costThreshold = meshSize * parameters.maximumError * 0.001f; costThreshold *= costThreshold; int progressCounter = 0; while (true) { int num = Collapse(1, costThreshold); if (num == 0) { break; } progressCounter--; if (progressCounter <= 0) { progressCounter = kProgressGroups; if (Time.realtimeSinceStartup - t > kProgressInterval && progressDelegate != null) { t = Time.realtimeSinceStartup; int facesRemoved = totalFacesToRemove - (mesh.numValidFaces - parameters.targetFaceCount); progressDelegate("Mesh Faces " + mesh.numValidFaces + "->" + parameters.targetFaceCount, 0.1f + 0.9f * ((float)facesRemoved) / ((float)totalFacesToRemove)); // TODO: do this better } } } } //Debugging.CheckMeshIntegrity(mesh); mesh.RebuildMesh(); /*float minShape = Debugging.CalculateMinTriangleShape(mesh); * Debug.LogError("MIN TRIANGLE SHAPE" + Mathf.Sqrt(minShape) + " param " + Mathf.Sqrt(sharpnessLimitSqr)); */ Cleanup(); }