private void Start() { _originalMeshes = new List <Mesh>(); _meshes = new List <Mesh>(); _slider = GetComponent <Slider>(); _slider.onValueChanged.AddListener(OnValueChanged); Renderer[] renderers = original.GetComponentsInChildren <Renderer>(); HashSet <Mesh> uniqueMeshes = new HashSet <Mesh>(); foreach (Renderer renderer in renderers) { if (renderer is MeshRenderer meshRenderer) { var meshFilter = renderer.gameObject.GetComponent <MeshFilter>(); if (!meshFilter) { continue; } var mesh = meshFilter.sharedMesh; _polycount += mesh.triangles.Length; if (!uniqueMeshes.Add(mesh)) { continue; } _originalMeshes.Add(mesh); // Clone mesh mesh = meshFilter.sharedMesh = UnityConverter.ToSharedMesh(mesh).ToUnityMesh(); _meshes.Add(mesh); } else if (renderer is SkinnedMeshRenderer skinnedMeshRenderer) { var mesh = skinnedMeshRenderer.sharedMesh; _polycount += mesh.triangles.Length; if (!uniqueMeshes.Add(mesh)) { continue; } _originalMeshes.Add(mesh); // Clone mesh mesh = skinnedMeshRenderer.sharedMesh = mesh.ToSharedMesh().ToUnityMesh(); _meshes.Add(mesh); } } OnValueChanged(1); }
private void SetDecimation(float value, Dictionary <string, float> variables) { ConnectedMesh[] connectedMeshes = _originalMeshes.Select(x => UnityConverter.ToSharedMesh(x).ToConnectedMesh()).ToArray(); foreach (ConnectedMesh connectedMesh in connectedMeshes) { for (int i = 0; i < connectedMesh.attributeDefinitions.Length; i++) { switch (connectedMesh.attributeDefinitions[i].type) { case AttributeType.Normals: connectedMesh.attributeDefinitions[i].weight = variables["NormalWeight"]; break; case AttributeType.UVs: connectedMesh.attributeDefinitions[i].weight = variables["UVsWeight"]; break; } } } foreach (ConnectedMesh connectedMesh in connectedMeshes) { // Important step : // We merge positions to increase chances of having correct topology information // We merge attributes in order to make interpolation properly operate on every face connectedMesh.MergePositions(0.0001f /*variables["MergeThreshold"]*/); connectedMesh.MergeAttributes(); connectedMesh.Compact(); } DecimateModifier.MergeNormalsThresholdDegrees = variables["MergeNormalsThreshold"]; //DecimateModifier.UpdateFarNeighbors = variables["UpdateFarNeighbors"] > 0.5; //DecimateModifier.UpdateMinsOnCollapse = variables["UpdateMinsOnCollapse"] > 0.5; //DecimateModifier.UseEdgeLength = variables["UseEdgeLength"] > 0.5; DecimateModifier.CollapseToMidpointPenalty = variables["CollapseToMidpointPenalty"]; ConnectedMesh.EdgeBorderPenalty = variables["EdgeBorderPenalty"]; SceneDecimator sceneDecimator = new SceneDecimator(); sceneDecimator.Initialize(connectedMeshes); sceneDecimator.DecimateToRatio(value); for (int i = 0; i < connectedMeshes.Length; i++) { _meshes[i].Clear(); connectedMeshes[i].ToSharedMesh().ToUnityMesh(_meshes[i]); _meshes[i].bindposes = _originalMeshes[i].bindposes; } }
private void OnValueChanged(float value) { polycountLabel.text = $"{Math.Round(100 * value)}% ({Math.Round(value * _polycount)}/{_polycount} triangles)"; Profiling.Start("Convert"); var connectedMeshes = _originalMeshes.Select(x => UnityConverter.ToSharedMesh(x).ToConnectedMesh()).ToArray(); Debug.Log(Profiling.End("Convert")); Profiling.Start("Clean"); foreach (var connectedMesh in connectedMeshes) { // Important step : // We merge positions to increase chances of having correct topology information // We merge attributes in order to make interpolation properly operate on every face connectedMesh.MergePositions(0.0001f); connectedMesh.MergeAttributes(); connectedMesh.Compact(); } Debug.Log(Profiling.End("Clean")); Profiling.Start("Decimate"); SceneDecimator sceneDecimator = new SceneDecimator(); sceneDecimator.Initialize(connectedMeshes); sceneDecimator.DecimateToRatio(value); Debug.Log(Profiling.End("Decimate")); Profiling.Start("Convert back"); for (int i = 0; i < connectedMeshes.Length; i++) { _meshes[i].Clear(); connectedMeshes[i].ToSharedMesh().ToUnityMesh(_meshes[i]); _meshes[i].bindposes = _originalMeshes[i].bindposes; } Debug.Log(Profiling.End("Convert back")); }
private void Start() { _originalMeshes = new List <Mesh>(); _meshes = new List <Mesh>(); Renderer[] renderers = gameObject.GetComponentsInChildren <Renderer>(); HashSet <Mesh> uniqueMeshes = new HashSet <Mesh>(); foreach (Renderer renderer in renderers) { if (renderer is MeshRenderer meshRenderer) { MeshFilter meshFilter = renderer.gameObject.GetComponent <MeshFilter>(); if (!meshFilter) { continue; } Mesh mesh = meshFilter.sharedMesh; if (!uniqueMeshes.Add(mesh)) { continue; } _originalMeshes.Add(mesh); // Clone mesh mesh = meshFilter.sharedMesh = UnityConverter.ToSharedMesh(mesh).ToUnityMesh(); _meshes.Add(mesh); } else if (renderer is SkinnedMeshRenderer skinnedMeshRenderer) { Mesh mesh = skinnedMeshRenderer.sharedMesh; if (!uniqueMeshes.Add(mesh)) { continue; } _originalMeshes.Add(mesh); // Clone mesh mesh = skinnedMeshRenderer.sharedMesh = mesh.ToSharedMesh().ToUnityMesh(); _meshes.Add(mesh); } } Camera camera = Camera.main; Texture2D textureOriginal = CalibrationUtils.CaptureScreenshot(camera, 1000, 1000); File.WriteAllBytes(@"C:\Users\oginiaux\Downloads\trace\original.jpg", textureOriginal.EncodeToJPG()); Digest originalDigest = ImagePhash.ComputeDigest(CalibrationUtils.ToLuminanceImage(textureOriginal)); List <Dictionary <string, float> > results = new List <Dictionary <string, float> >(); float highestCorrelation = float.MinValue; for (int i = 0; i < iterations; i++) { Dictionary <string, float> values = new Dictionary <string, float>(); values["NormalWeight"] = Random.Range(0f, 100f); values["MergeThreshold"] = Random.Range(0.00001f, 0.1f); values["MergeNormalsThreshold"] = MathF.Cos(Random.Range(5f, 140f) * MathF.PI / 180f); values["UseEdgeLength"] = Random.Range(0f, 1f); values["UpdateFarNeighbors"] = Random.Range(0f, 0.75f); values["UpdateMinsOnCollapse"] = Random.Range(0.25f, 1f); values["EdgeBorderPenalty"] = Random.Range(0f, 1000f); values["Case"] = i; System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); SetDecimation(0.5f, values); sw.Stop(); values["Time"] = (float)sw.Elapsed.TotalMilliseconds; Texture2D textureDecimated = CalibrationUtils.CaptureScreenshot(camera, 1000, 1000); Digest modified = ImagePhash.ComputeDigest(CalibrationUtils.ToLuminanceImage(textureDecimated)); values["Correlation"] = ImagePhash.GetCrossCorrelation(originalDigest, modified); if (highestCorrelation < values["Correlation"]) { highestCorrelation = values["Correlation"]; File.WriteAllBytes($@"C:\Users\oginiaux\Downloads\trace\case_{i}.jpg", textureDecimated.EncodeToJPG()); } results.Add(values); } foreach (Dictionary <string, float> result in results.OrderByDescending(x => x["Correlation"]).Take(3)) { StringBuilder strbldr = new StringBuilder(); foreach (KeyValuePair <string, float> pair in result.OrderBy(x => x.Key)) { strbldr.Append($"{pair.Key} = {pair.Value}\n"); } Debug.Log(strbldr); } }
private void Start() { _originalMeshes = new List <Mesh>(); _meshes = new List <Mesh>(); Renderer[] renderers = gameObject.GetComponentsInChildren <Renderer>(); HashSet <Mesh> uniqueMeshes = new HashSet <Mesh>(); foreach (Renderer renderer in renderers) { if (renderer is MeshRenderer meshRenderer) { MeshFilter meshFilter = renderer.gameObject.GetComponent <MeshFilter>(); if (!meshFilter) { continue; } Mesh mesh = meshFilter.sharedMesh; if (!uniqueMeshes.Add(mesh)) { continue; } _originalMeshes.Add(mesh); // Clone mesh mesh = meshFilter.sharedMesh = UnityConverter.ToSharedMesh(mesh).ToUnityMesh(); _meshes.Add(mesh); } else if (renderer is SkinnedMeshRenderer skinnedMeshRenderer) { Mesh mesh = skinnedMeshRenderer.sharedMesh; if (!uniqueMeshes.Add(mesh)) { continue; } _originalMeshes.Add(mesh); // Clone mesh mesh = skinnedMeshRenderer.sharedMesh = mesh.ToSharedMesh().ToUnityMesh(); _meshes.Add(mesh); } } _camera = Camera.main; Texture2D textureOriginal = CalibrationUtils.CaptureScreenshot(_camera, 1000, 1000); _originalDigest = ImagePhash.ComputeDigest(CalibrationUtils.ToLuminanceImage(textureOriginal)); switch (metaHeuristicAlgo) { case MetaHeuristicAlgo.GeneticAlgorithm: _metaheuristicAlgorithm = new GeneticAlgorithm <Dictionary <string, float> >(Crossover); break; case MetaHeuristicAlgo.HillClimbing: _metaheuristicAlgorithm = new HillClimb <Dictionary <string, float> >(); break; } var config = new Configuration <Dictionary <string, float> >(); config.initializeSolutionFunction = GetInitialState; config.cloneFunction = Clone; config.mutationFunction = Mutate; config.movement = Search.Direction.Optimization; config.selectionFunction = Selection.RankBased; config.objectiveFunction = GetFitness; config.populationSize = populationSize; config.noOfIterations = iterations; config.writeToConsole = false; config.enforceHardObjective = false; _metaheuristicAlgorithm.Create(config); StartCoroutine(Run()); }