public async void SimplifyObj(string sourcePath, string destPath, float quality) { simplifyTask = new Task(() => { quality = MathHelper.Clamp01(quality); ObjMesh sourceObjMesh = new ObjMesh(); sourceObjMesh.ReadFile(sourcePath); var sourceVertices = sourceObjMesh.Vertices; var sourceNormals = sourceObjMesh.Normals; var sourceTexCoords2D = sourceObjMesh.TexCoords2D; var sourceTexCoords3D = sourceObjMesh.TexCoords3D; var sourceSubMeshIndices = sourceObjMesh.SubMeshIndices; var sourceMesh = new MeshDecimator.Mesh(sourceVertices, sourceSubMeshIndices); sourceMesh.Normals = sourceNormals; if (sourceTexCoords2D != null) { sourceMesh.SetUVs(0, sourceTexCoords2D); } else if (sourceTexCoords3D != null) { sourceMesh.SetUVs(0, sourceTexCoords3D); } int currentTriangleCount = 0; for (int i = 0; i < sourceSubMeshIndices.Length; i++) { currentTriangleCount += (sourceSubMeshIndices[i].Length / 3); } int targetTriangleCount = (int)Math.Ceiling(currentTriangleCount * quality); string info_1 = string.Format("Input: {0} vertices, {1} triangles (target {2}) \n", sourceVertices.Length, currentTriangleCount, targetTriangleCount); // Console.WriteLine(info_1); simplifyInfo.Invoke(info_1); var stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Reset(); stopwatch.Start(); var algorithm = MeshDecimation.CreateAlgorithm(Algorithm.Default); algorithm.Verbose = true; MeshDecimator.Mesh destMesh = MeshDecimation.DecimateMesh(algorithm, sourceMesh, targetTriangleCount); stopwatch.Stop(); var destVertices = destMesh.Vertices; var destNormals = destMesh.Normals; var destIndices = destMesh.GetSubMeshIndices(); ObjMesh destObjMesh = new ObjMesh(destVertices, destIndices); destObjMesh.Normals = destNormals; destObjMesh.MaterialLibraries = sourceObjMesh.MaterialLibraries; destObjMesh.SubMeshMaterials = sourceObjMesh.SubMeshMaterials; if (sourceTexCoords2D != null) { var destUVs = destMesh.GetUVs2D(0); destObjMesh.TexCoords2D = destUVs; } else if (sourceTexCoords3D != null) { var destUVs = destMesh.GetUVs3D(0); destObjMesh.TexCoords3D = destUVs; } destObjMesh.WriteFile(destPath); int outputTriangleCount = 0; for (int i = 0; i < destIndices.Length; i++) { outputTriangleCount += (destIndices[i].Length / 3); } float reduction = (float)outputTriangleCount / (float)currentTriangleCount; float timeTaken = (float)stopwatch.Elapsed.TotalSeconds; string info_2 = string.Format("Output: {0} vertices, {1} triangles ({2} reduction; {3:0.0000} sec) \n", destVertices.Length, outputTriangleCount, reduction, timeTaken); // Console.WriteLine(info_2); simplifyInfo.Invoke(info_2); simplifyInfo.Invoke("finish"); DisposeTask(); }); simplifyTask.Start(); }
public static Godot.Collections.Array generateMeshFromSurface(float quality, MeshInstance origMeshInst, int surface = 0) { var arr = origMeshInst.Mesh.SurfaceGetArrays(surface); var sourceNormals = (Godot.Vector3[])arr[(int)ArrayMesh.ArrayType.Normal]; var sourceVertices = (Godot.Vector3[])arr[(int)ArrayMesh.ArrayType.Vertex]; var sourceTxUv = (Godot.Vector2[])arr[(int)ArrayMesh.ArrayType.TexUv]; var sourceTxUv2 = (Godot.Vector2[])arr[(int)ArrayMesh.ArrayType.TexUv2]; var indexed_arr = (int[])arr[(int)ArrayMesh.ArrayType.Index]; var sourceTangets = (float[])arr[(int)ArrayMesh.ArrayType.Tangent]; // chunck to 4 var sourceBones = (int[])arr[(int)ArrayMesh.ArrayType.Bones]; //chunck to 4 var sourceBonesWeights = (float[])arr[(int)ArrayMesh.ArrayType.Weights]; //chunck to 4 var tangentList = new List <Vector4>(); var weights = new List <Vector4>(); var boneWeights = new List <BoneWeight>(); var sourceMesh = new Mesh(sourceVertices.Select(d => new Vector3d(d.x, d.y, d.z)).ToArray(), indexed_arr); if (sourceTangets != null) { foreach (var c in sourceTangets.Split(4)) { var l = c.ToArray(); var vec = new Vector4(l[0], l[1], l[2], l[3]); tangentList.Add(vec); } } if (sourceBonesWeights != null && sourceBones != null) { foreach (var c in sourceBonesWeights.Split(4)) { var l = c.ToArray(); var vec = new Vector4(l[0], l[1], l[2], l[3]); weights.Add(vec); } int i = 0; foreach (var c in sourceBones.Split(4)) { var l = c.ToArray(); var bvc = weights[i]; var vec = new BoneWeight(l[0], l[1], l[2], l[3], bvc[0], bvc[1], bvc[2], bvc[3]); boneWeights.Add(vec); i++; } if (boneWeights.Count() > 0) { sourceMesh.BoneWeights = boneWeights.ToArray(); } } sourceMesh.Normals = sourceNormals.Select(d => new MeshDecimator.Math.Vector3(d.x, d.y, d.z)).ToArray(); sourceMesh.Tangents = tangentList.ToArray(); if (sourceTxUv != null) { sourceMesh.UV1 = sourceTxUv.Select(d => new MeshDecimator.Math.Vector2(d.x, d.y)).ToArray(); } if (sourceTxUv2 != null) { sourceMesh.UV2 = sourceTxUv2.Select(d => new MeshDecimator.Math.Vector2(d.x, d.y)).ToArray(); } int currentTriangleCount = 0; var subMeshIndicies = sourceMesh.GetSubMeshIndices(); for (int i = 0; i < sourceMesh.GetSubMeshIndices().Length; i++) { currentTriangleCount += (subMeshIndicies[i].Length / 3); } //new triangle amount int targetTriangleCount = (int)Godot.Mathf.Ceil(currentTriangleCount * quality); GD.Print("Input: " + sourceVertices.Length + " vertices, " + currentTriangleCount + " triangles => " + targetTriangleCount); var algorithm = MeshDecimation.CreateAlgorithm(Algorithm.Default); var destMesh = MeshDecimation.DecimateMesh(algorithm, sourceMesh, targetTriangleCount); //create new mesh from arrays var arrays = new Godot.Collections.Array(); arrays.Resize((int)ArrayMesh.ArrayType.Max); if (destMesh.Vertices != null) { arrays[(int)ArrayMesh.ArrayType.Vertex] = destMesh.Vertices.Select(tf => new Godot.Vector3((float)tf.x, (float)tf.y, (float)tf.z)).ToArray(); } if (destMesh.Normals != null) { arrays[(int)ArrayMesh.ArrayType.Normal] = destMesh.Normals.Select(tf => new Godot.Vector3((float)tf.x, (float)tf.y, (float)tf.z)).ToArray(); } if (destMesh.Indices != null) { arrays[(int)ArrayMesh.ArrayType.Index] = destMesh.Indices.ToArray(); } if (destMesh.Tangents != null) { List <float> tangArr = new List <float>(); foreach (var x in destMesh.Tangents) { tangArr.Add(x.x); tangArr.Add(x.y); tangArr.Add(x.z); tangArr.Add(x.w); } arrays[(int)ArrayMesh.ArrayType.Tangent] = tangArr.ToArray(); } if (destMesh.BoneWeights != null) { List <float> newBoneWeights = new List <float>(); List <int> newBoneIndexes = new List <int>(); foreach (var x in destMesh.BoneWeights) { newBoneIndexes.Add(x.boneIndex0); newBoneIndexes.Add(x.boneIndex1); newBoneIndexes.Add(x.boneIndex2); newBoneIndexes.Add(x.boneIndex3); newBoneWeights.Add(x.boneWeight0); newBoneWeights.Add(x.boneWeight1); newBoneWeights.Add(x.boneWeight2); newBoneWeights.Add(x.boneWeight3); } arrays[(int)ArrayMesh.ArrayType.Bones] = newBoneIndexes.ToArray(); arrays[(int)ArrayMesh.ArrayType.Weights] = newBoneWeights.ToArray(); } if (destMesh.UV1 != null) { arrays[(int)ArrayMesh.ArrayType.TexUv] = destMesh.UV1.Select(tf => new Godot.Vector2(tf.x, tf.y)).ToArray(); } if (destMesh.UV2 != null) { arrays[(int)ArrayMesh.ArrayType.TexUv2] = destMesh.UV2.Select(tf => new Godot.Vector2(tf.x, tf.y)).ToArray(); } return(arrays); }