private List <STGenericObject> CreateGenericObjects(string Name, library_geometries Geometries) { List <STGenericObject> objects = new List <STGenericObject>(); foreach (var geom in Geometries.geometry) { var daeMesh = geom.Item as mesh; if (daeMesh == null) { continue; } STGenericObject mesh = new STGenericObject(); mesh.ObjectName = Name; foreach (var source in daeMesh.source) { var float_array = source.Item as float_array; if (float_array == null) { continue; } } objects.Add(mesh); } return(objects); }
public STGenericObject CreateGenericObject(Node parentNode, Mesh msh, int Index, Matrix4 transform) { STGenericObject obj = new STGenericObject(); obj.BoneIndex = 0; if (msh.MaterialIndex != -1) { obj.MaterialIndex = msh.MaterialIndex; } else { scene.Materials.Add(new Material() { Name = msh.Name }); } if (scene.Materials[msh.MaterialIndex].Name == "") { scene.Materials[msh.MaterialIndex].Name = msh.Name; } obj.HasPos = msh.HasVertices; obj.HasNrm = msh.HasNormals; obj.HasUv0 = msh.HasTextureCoords(0); obj.HasUv1 = msh.HasTextureCoords(1); obj.HasUv2 = msh.HasTextureCoords(2); obj.HasIndices = msh.HasBones; if (msh.HasBones && msh.BoneCount > 1) { obj.HasWeights = msh.Bones[0].HasVertexWeights; } obj.HasTans = msh.HasTangentBasis; obj.HasBitans = msh.HasTangentBasis; obj.HasVertColors = msh.HasVertexColors(0); obj.HasVertColors2 = msh.HasVertexColors(1); obj.ObjectName = msh.Name; if (parentNode != null && msh.Name == string.Empty) { obj.ObjectName = parentNode.Name; } obj.boneList = GetBoneList(msh); obj.VertexSkinCount = (byte)GetVertexSkinCount(msh); STGenericObject.LOD_Mesh lod = new STGenericObject.LOD_Mesh(); lod.faces = GetFaces(msh); lod.IndexFormat = STIndexFormat.UInt16; lod.PrimativeType = STPrimitiveType.Triangles; lod.GenerateSubMesh(); obj.lodMeshes.Add(lod); obj.vertices = GetVertices(msh, transform, obj); obj.VertexBufferIndex = Index; return(obj); }
private static void SaveMesh(StringBuilder writer, STGenericObject mesh, STGenericMaterial mat, int VertexCount) { writer.AppendLine($"o {mesh.Text}"); writer.AppendLine($"g {mesh.Text}"); foreach (var v in mesh.vertices) { writer.AppendLine($"v {v.pos.X} {v.pos.Y} {v.pos.Z}"); writer.AppendLine($"vn {v.nrm.X} {v.nrm.Y} {v.nrm.Z}"); writer.AppendLine($"vt {v.uv0.X} {v.uv0.Y}"); } if (mat != null) { writer.AppendLine($"usemtl {mat.Text}"); } for (int i = 0; i < mesh.faces.Count; i++) { int[] indices = new int[3] { mesh.faces[i++], mesh.faces[i++], mesh.faces[i] }; writer.AppendLine($"f {indices[0] + VertexCount}/{indices[0] + VertexCount}/{indices[0] + VertexCount}" + $" {indices[1] + VertexCount}/{indices[1] + VertexCount}/{indices[1] + VertexCount}" + $" {indices[2] + VertexCount}/{indices[2] + VertexCount}/{indices[2] + VertexCount}"); } VertexCount += mesh.vertices.Count; }
public static void Export(string FileName, ExportSettings settings, STGenericObject mesh) { Export(FileName, settings, new List <STGenericObject>() { mesh }, new List <STGenericMaterial>(), new List <STGenericTexture>()); }
public static void ExportMesh(string FileName, STGenericObject genericMesh) { string fileNoExt = Path.GetFileNameWithoutExtension(FileName); string fileMtlPath = FileName.Replace("obj", "mtl"); //Write mesh StringBuilder writer = new StringBuilder(); SaveMesh(writer, genericMesh, null, 0); File.WriteAllText(FileName, writer.ToString()); }
private static SELib.SEModelMesh SaveMesh(STGenericObject mesh) { var seMesh = new SELib.SEModelMesh(); var MeshLevel = mesh.lodMeshes[mesh.DisplayLODIndex]; for (int i = 0; i < MeshLevel.faces.Count; i++) { seMesh.AddFace((uint)MeshLevel.faces[i], (uint)MeshLevel.faces[i++], (uint)MeshLevel.faces[i++]); } return(seMesh); }
public void SaveFromObject(STGenericObject genericObject, string FileName) { Scene scene = new Scene(); scene.RootNode = new Node("Root"); var mesh = SaveMesh(genericObject, scene, 0, null, null); mesh.MaterialIndex = 0; scene.Meshes.Add(mesh); Material material = new Material(); material.Name = "NewMaterial"; scene.Materials.Add(material); SaveScene(FileName, scene, new List <STGenericObject>() { genericObject }); }
private Mesh SaveMesh(STGenericObject genericObj, Scene scene, int index, STSkeleton skeleton, List <int> NodeArray) { //Assimp is weird so use mesh_# for the name. We'll change it back after save Mesh mesh = new Mesh($"mesh_{ index }", PrimitiveType.Triangle); if (genericObj.MaterialIndex < scene.MaterialCount && genericObj.MaterialIndex > 0) { mesh.MaterialIndex = genericObj.MaterialIndex; } else { mesh.MaterialIndex = 0; } List <Vector3D> textureCoords0 = new List <Vector3D>(); List <Vector3D> textureCoords1 = new List <Vector3D>(); List <Vector3D> textureCoords2 = new List <Vector3D>(); List <Color4D> vertexColors = new List <Color4D>(); int vertexID = 0; foreach (Vertex v in genericObj.vertices) { mesh.Vertices.Add(new Vector3D(v.pos.X, v.pos.Y, v.pos.Z)); mesh.Normals.Add(new Vector3D(v.nrm.X, v.nrm.Y, v.nrm.Z)); textureCoords0.Add(new Vector3D(v.uv0.X, v.uv0.Y, 0)); textureCoords1.Add(new Vector3D(v.uv1.X, v.uv1.Y, 0)); textureCoords2.Add(new Vector3D(v.uv2.X, v.uv2.Y, 0)); vertexColors.Add(new Color4D(v.col.X, v.col.Y, v.col.Z, v.col.W)); if (skeleton != null) { for (int j = 0; j < v.boneIds.Count; j++) { if (j < genericObj.VertexSkinCount) { STBone STbone = null; if (NodeArray != null) { //Get the bone via the node array and bone index from the vertex STbone = skeleton.bones[NodeArray[v.boneIds[j]]]; } else { STbone = skeleton.bones[v.boneIds[j]]; } //Find the index of a bone. If it doesn't exist then we add it int boneInd = mesh.Bones.FindIndex(x => x.Name == STbone.Text); if (boneInd == -1) { var matrices = Toolbox.Library.IO.MatrixExenstion.CalculateInverseMatrix(STbone); //Set the inverse matrix Matrix4x4 transform = matrices.inverse.FromNumerics(); //Create a new assimp bone Bone bone = new Bone(); bone.Name = STbone.Text; bone.OffsetMatrix = STbone.invert.ToMatrix4x4(); mesh.Bones.Add(bone); BoneNames.Add(bone.Name); boneInd = mesh.Bones.IndexOf(bone); //Set the index of the bone for the vertex weight } int MinWeightAmount = 0; //Check if the max amount of weights is higher than the current bone id if (v.boneWeights.Count > j && v.boneWeights[j] > MinWeightAmount) { if (v.boneWeights[j] <= 1) { mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, v.boneWeights[j])); } else { mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, 1)); } } else if (v.boneWeights.Count == 0 || v.boneWeights[j] > MinWeightAmount) { mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, 1)); } } } } vertexID++; } if (genericObj.lodMeshes.Count != 0) { List <int> faces = genericObj.lodMeshes[genericObj.DisplayLODIndex].faces; for (int f = 0; f < faces.Count; f++) { mesh.Faces.Add(new Face(new int[] { faces[f++], faces[f++], faces[f] })); } } if (genericObj.PolygonGroups.Count != 0) { for (int p = 0; p < genericObj.PolygonGroups.Count; p++) { var polygonGroup = genericObj.PolygonGroups[p]; for (int f = 0; f < polygonGroup.faces.Count; f++) { if (f < polygonGroup.faces.Count - 2) { mesh.Faces.Add(new Face(new int[] { polygonGroup.faces[f++], polygonGroup.faces[f++], polygonGroup.faces[f] })); } } } } mesh.TextureCoordinateChannels.SetValue(textureCoords0, 0); mesh.TextureCoordinateChannels.SetValue(textureCoords1, 1); mesh.TextureCoordinateChannels.SetValue(textureCoords2, 2); mesh.VertexColorChannels.SetValue(vertexColors, 0); return(mesh); }
public static void Export(string FileName, ExportSettings settings, List <STGenericObject> Meshes, List <STGenericMaterial> Materials, List <STGenericTexture> Textures, STSkeleton skeleton = null, List <int> NodeArray = null) { if (Materials == null) { Materials = new List <STGenericMaterial>(); } if (skeleton != null && skeleton.BoneIndices != null) { NodeArray = skeleton.BoneIndices.ToList(); } List <string> failedTextureExport = new List <string>(); STProgressBar progressBar = new STProgressBar(); progressBar.Task = "Exporting Model..."; progressBar.Value = 0; progressBar.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; progressBar.Show(); progressBar.Refresh(); if (settings.UseOldExporter) { AssimpSaver saver = new AssimpSaver(); STGenericModel model = new STGenericModel(); model.Objects = Meshes; model.Materials = Materials; saver.SaveFromModel(model, FileName, Textures, skeleton, NodeArray); return; } string TexturePath = System.IO.Path.GetDirectoryName(FileName); Dictionary <string, STGenericMaterial> MaterialRemapper = new Dictionary <string, STGenericMaterial>(); using (ColladaWriter writer = new ColladaWriter(FileName, settings)) { writer.WriteAsset(); if (Materials.Count > 0) { List <string> textureNames = new List <string>(); for (int i = 0; i < Textures?.Count; i++) { if (!textureNames.Contains(Textures[i].Text)) { textureNames.Add(Textures[i].Text); } if (settings.ExportTextures) { progressBar.Task = $"Exporting Texture {Textures[i].Text}"; progressBar.Value = ((i * 100) / Textures.Count); progressBar.Refresh(); try { var bitmap = Textures[i].GetBitmap(); if (bitmap != null) { if (settings.UseTextureChannelComponents) { bitmap = Textures[i].GetComponentBitmap(bitmap); } string textureName = Textures[i].Text; if (textureName.RemoveIllegaleFileNameCharacters() != textureName) { string properName = textureName.RemoveIllegaleFileNameCharacters(); for (int m = 0; m < Materials?.Count; m++) { foreach (var tex in Materials[m].TextureMaps) { if (tex.Name == textureName) { tex.Name = properName; } } } textureName = properName; } bitmap.Save($"{TexturePath}/{textureName}.png"); bitmap.Dispose(); GC.Collect(); } } catch (Exception ex) { failedTextureExport.Add(Textures[i].Text); } } } List <Material> materials = new List <Material>(); foreach (var mat in Materials) { Material material = new Material(); material.Name = mat.Text; if (!MaterialRemapper.ContainsKey(mat.Text)) { MaterialRemapper.Add(mat.Text, mat); } else { string name = Utils.RenameDuplicateString(MaterialRemapper.Keys.ToList(), mat.Text); MaterialRemapper.Add(name, mat); material.Name = name; } materials.Add(material); foreach (var tex in mat.TextureMaps) { TextureMap texMap = new TextureMap(); texMap.Name = tex.Name; if (tex.Type == STGenericMatTexture.TextureType.Diffuse) { texMap.Type = PhongTextureType.diffuse; } else if (tex.Type == STGenericMatTexture.TextureType.Normal) { texMap.Type = PhongTextureType.bump; } else if (tex.Type == STGenericMatTexture.TextureType.Specular) { texMap.Type = PhongTextureType.specular; } else if (tex.Type == STGenericMatTexture.TextureType.Emission) { texMap.Type = PhongTextureType.emission; } else { continue; //Skip adding unknown types } if (tex.WrapModeS == STTextureWrapMode.Repeat) { texMap.WrapModeS = SamplerWrapMode.WRAP; } else if (tex.WrapModeS == STTextureWrapMode.Mirror) { texMap.WrapModeS = SamplerWrapMode.MIRROR; } else if (tex.WrapModeS == STTextureWrapMode.Clamp) { texMap.WrapModeS = SamplerWrapMode.CLAMP; } if (tex.WrapModeT == STTextureWrapMode.Repeat) { texMap.WrapModeT = SamplerWrapMode.WRAP; } else if (tex.WrapModeT == STTextureWrapMode.Mirror) { texMap.WrapModeT = SamplerWrapMode.MIRROR; } else if (tex.WrapModeT == STTextureWrapMode.Clamp) { texMap.WrapModeT = SamplerWrapMode.CLAMP; } //If no textures are saved, still keep images references //So the user can still dump textures after if (Textures?.Count == 0 && !textureNames.Contains(texMap.Name)) { textureNames.Add($"{texMap.Name}"); } material.Textures.Add(texMap); } } writer.WriteLibraryImages(textureNames.ToArray()); writer.WriteLibraryMaterials(materials); writer.WriteLibraryEffects(materials); } else { writer.WriteLibraryImages(); } if (skeleton != null) { //Search for bones with rigging first List <string> riggedBones = new List <string>(); if (settings.OnlyExportRiggedBones) { for (int i = 0; i < Meshes.Count; i++) { for (int v = 0; v < Meshes[i].vertices.Count; v++) { var vertex = Meshes[i].vertices[v]; for (int j = 0; j < vertex.boneIds.Count; j++) { int id = -1; if (NodeArray != null && NodeArray.Count > vertex.boneIds[j]) { id = NodeArray[vertex.boneIds[j]]; } else { id = vertex.boneIds[j]; } if (id < skeleton.bones.Count && id != -1) { riggedBones.Add(skeleton.bones[id].Text); } } } } } foreach (var bone in skeleton.bones) { if (settings.OnlyExportRiggedBones && !riggedBones.Contains(bone.Text)) { Console.WriteLine("Skipping " + bone.Text); continue; } //Set the inverse matrix var inverse = skeleton.GetBoneTransform(bone).Inverted(); var transform = bone.GetTransform(); float[] Transform = new float[] { transform.M11, transform.M21, transform.M31, transform.M41, transform.M12, transform.M22, transform.M32, transform.M42, transform.M13, transform.M23, transform.M33, transform.M43, transform.M14, transform.M24, transform.M34, transform.M44 }; float[] InvTransform = new float[] { inverse.M11, inverse.M21, inverse.M31, inverse.M41, inverse.M12, inverse.M22, inverse.M32, inverse.M42, inverse.M13, inverse.M23, inverse.M33, inverse.M43, inverse.M14, inverse.M24, inverse.M34, inverse.M44 }; writer.AddJoint(bone.Text, bone.parentIndex == -1 ? "" : skeleton.bones[bone.parentIndex].Text, Transform, InvTransform, new float[3] { bone.Position.X, bone.Position.Y, bone.Position.Z }, new float[3] { bone.EulerRotation.X *Rad2Deg, bone.EulerRotation.Y *Rad2Deg, bone.EulerRotation.Z *Rad2Deg }, new float[3] { bone.Scale.X, bone.Scale.Y, bone.Scale.Z }); } } int meshIndex = 0; writer.StartLibraryGeometries(); foreach (var mesh in Meshes) { progressBar.Task = $"Exporting Mesh {mesh.Text}"; progressBar.Value = ((meshIndex++ *100) / Meshes.Count); progressBar.Refresh(); int[] IndexTable = null; if (NodeArray != null) { IndexTable = NodeArray.ToArray(); } writer.StartGeometry(mesh.Text); if (mesh.MaterialIndex != -1 && Materials.Count > mesh.MaterialIndex) { writer.CurrentMaterial = Materials[mesh.MaterialIndex].Text; Console.WriteLine($"MaterialIndex {mesh.MaterialIndex } {Materials[mesh.MaterialIndex].Text}"); } if (settings.TransformColorUVs) { List <Vertex> transformedVertices = new List <Vertex>(); foreach (var poly in mesh.PolygonGroups) { var mat = poly.Material; if (mat == null) { continue; } var faces = poly.GetDisplayFace(); for (int v = 0; v < poly.displayFaceSize; v += 3) { if (faces.Count < v + 2) { break; } var diffuse = mat.TextureMaps.FirstOrDefault(x => x.Type == STGenericMatTexture.TextureType.Diffuse); STTextureTransform transform = new STTextureTransform(); if (diffuse != null) { transform = diffuse.Transform; } var vertexA = mesh.vertices[faces[v]]; var vertexB = mesh.vertices[faces[v + 1]]; var vertexC = mesh.vertices[faces[v + 2]]; if (!transformedVertices.Contains(vertexA)) { vertexA.uv0 = (vertexA.uv0 * transform.Scale) + transform.Translate; transformedVertices.Add(vertexA); } if (!transformedVertices.Contains(vertexB)) { vertexB.uv0 = (vertexB.uv0 * transform.Scale) + transform.Translate; transformedVertices.Add(vertexB); } if (!transformedVertices.Contains(vertexC)) { vertexC.uv0 = (vertexC.uv0 * transform.Scale) + transform.Translate; transformedVertices.Add(vertexC); } } } } // collect sources List <float> Position = new List <float>(); List <float> Normal = new List <float>(); List <float> UV0 = new List <float>(); List <float> UV1 = new List <float>(); List <float> UV2 = new List <float>(); List <float> UV3 = new List <float>(); List <float> Color = new List <float>(); List <float> Color2 = new List <float>(); List <int[]> BoneIndices = new List <int[]>(); List <float[]> BoneWeights = new List <float[]>(); bool HasNormals = false; bool HasColors = false; bool HasColors2 = false; bool HasUV0 = false; bool HasUV1 = false; bool HasUV2 = false; bool HasBoneIds = false; foreach (var vertex in mesh.vertices) { if (vertex.nrm != Vector3.Zero) { HasNormals = true; } if (vertex.col != Vector4.One && settings.UseVertexColors) { HasColors = true; } if (vertex.col2 != Vector4.One && settings.UseVertexColors) { HasColors2 = true; } if (vertex.uv0 != Vector2.Zero) { HasUV0 = true; } if (vertex.uv1 != Vector2.Zero) { HasUV1 = true; } if (vertex.uv2 != Vector2.Zero) { HasUV2 = true; } if (vertex.boneIds.Count > 0) { HasBoneIds = true; } Position.Add(vertex.pos.X); Position.Add(vertex.pos.Y); Position.Add(vertex.pos.Z); Normal.Add(vertex.nrm.X); Normal.Add(vertex.nrm.Y); Normal.Add(vertex.nrm.Z); if (settings.FlipTexCoordsVertical) { UV0.Add(vertex.uv0.X); UV0.Add(1 - vertex.uv0.Y); UV1.Add(vertex.uv1.X); UV1.Add(1 - vertex.uv1.Y); UV2.Add(vertex.uv2.X); UV2.Add(1 - vertex.uv2.Y); } else { UV0.Add(vertex.uv0.X); UV0.Add(vertex.uv0.Y); UV1.Add(vertex.uv1.X); UV1.Add(vertex.uv1.Y); UV2.Add(vertex.uv2.X); UV2.Add(vertex.uv2.Y); } Color.AddRange(new float[] { vertex.col.X, vertex.col.Y, vertex.col.Z, vertex.col.W }); Color2.AddRange(new float[] { vertex.col2.X, vertex.col2.Y, vertex.col2.Z, vertex.col2.W }); List <int> bIndices = new List <int>(); List <float> bWeights = new List <float>(); for (int b = 0; b < vertex.boneIds.Count; b++) { if (b > mesh.VertexSkinCount - 1) { continue; } //Skip 0 weights if (vertex.boneWeights.Count > b) { if (vertex.boneWeights[b] == 0) { continue; } } int index = -1; if (IndexTable != null) { index = (int)IndexTable[vertex.boneIds[b]]; } else { index = (int)vertex.boneIds[b]; } //Only map for valid weights/indices bool hasValidIndex = index != -1 && index < skeleton?.bones.Count; bool hasValidWeight = vertex.boneWeights.Count > b; if (hasValidIndex) { bIndices.Add(index); } if (hasValidWeight && hasValidIndex) { bWeights.Add(vertex.boneWeights[b]); } } //Rigid bodies with no direct bone indices if (bIndices.Count == 0 && mesh.BoneIndex != -1) { HasBoneIds = true; bIndices.Add(mesh.BoneIndex); bWeights.Add(1); } //Bone indices with no weights directly mapped if (bWeights.Count == 0 && bIndices.Count > 0) { bWeights.Add(1.0f); } BoneIndices.Add(bIndices.ToArray()); BoneWeights.Add(bWeights.ToArray()); } List <TriangleList> triangleLists = new List <TriangleList>(); if (mesh.lodMeshes.Count > 0) { TriangleList triangleList = new TriangleList(); triangleLists.Add(triangleList); var lodMesh = mesh.lodMeshes[mesh.DisplayLODIndex]; List <int> faces = new List <int>(); if (lodMesh.PrimativeType == STPrimitiveType.TrangleStrips) { faces = STGenericObject.ConvertTriangleStripsToTriangles(lodMesh.faces); } else { faces = lodMesh.faces; } for (int i = 0; i < faces.Count; i++) { triangleList.Indices.Add((uint)faces[i]); } } if (mesh.PolygonGroups.Count > 0) { foreach (var group in mesh.PolygonGroups) { TriangleList triangleList = new TriangleList(); triangleLists.Add(triangleList); STGenericMaterial material = new STGenericMaterial(); if (group.MaterialIndex != -1 && Materials.Count > group.MaterialIndex) { material = Materials[group.MaterialIndex]; } if (group.Material != null) { material = group.Material; } if (MaterialRemapper.Values.Any(x => x == material)) { var key = MaterialRemapper.FirstOrDefault(x => x.Value == material).Key; triangleList.Material = key; } else if (material.Text != string.Empty) { triangleList.Material = material.Text; } List <int> faces = new List <int>(); if (group.PrimativeType == STPrimitiveType.TrangleStrips) { faces = STGenericObject.ConvertTriangleStripsToTriangles(group.faces); } else { faces = group.faces; } for (int i = 0; i < faces.Count; i++) { triangleList.Indices.Add((uint)faces[i]); } } } // write sources writer.WriteGeometrySource(mesh.Text, SemanticType.POSITION, Position.ToArray(), triangleLists.ToArray()); if (HasNormals) { writer.WriteGeometrySource(mesh.Text, SemanticType.NORMAL, Normal.ToArray(), triangleLists.ToArray()); } if (HasColors) { writer.WriteGeometrySource(mesh.Text, SemanticType.COLOR, Color.ToArray(), triangleLists.ToArray(), 0); } if (HasColors2) { writer.WriteGeometrySource(mesh.Text, SemanticType.COLOR, Color2.ToArray(), triangleLists.ToArray(), 1); } if (HasUV0) { writer.WriteGeometrySource(mesh.Text, SemanticType.TEXCOORD, UV0.ToArray(), triangleLists.ToArray(), 0); } if (HasUV1) { writer.WriteGeometrySource(mesh.Text, SemanticType.TEXCOORD, UV1.ToArray(), triangleLists.ToArray(), 1); } if (HasUV2) { writer.WriteGeometrySource(mesh.Text, SemanticType.TEXCOORD, UV2.ToArray(), triangleLists.ToArray(), 2); } if (HasBoneIds) { writer.AttachGeometryController(BoneIndices, BoneWeights); } writer.EndGeometryMesh(); } writer.EndGeometrySection(); } progressBar?.Close(); if (!settings.SuppressConfirmDialog) { System.Windows.Forms.MessageBox.Show($"Exported {FileName} Successfuly!"); } }
public List <Vertex> GetVertices(Mesh msh, Matrix4 transform, STGenericObject STobj) { Matrix4 NormalsTransform = Matrix4.CreateFromQuaternion(transform.ExtractRotation()); List <Vertex> vertices = new List <Vertex>(); for (int v = 0; v < msh.VertexCount; v++) { Vertex vert = new Vertex(); if (msh.HasVertices) { vert.pos = Vector3.TransformPosition(AssimpHelper.FromVector(msh.Vertices[v]), transform); } if (msh.HasNormals) { vert.nrm = Vector3.TransformNormal(AssimpHelper.FromVector(msh.Normals[v]), NormalsTransform); } if (msh.HasTextureCoords(0)) { vert.uv0 = new Vector2(msh.TextureCoordinateChannels[0][v].X, msh.TextureCoordinateChannels[0][v].Y); } if (msh.HasTextureCoords(1)) { vert.uv1 = new Vector2(msh.TextureCoordinateChannels[1][v].X, msh.TextureCoordinateChannels[1][v].Y); } if (msh.HasTextureCoords(2)) { vert.uv2 = new Vector2(msh.TextureCoordinateChannels[2][v].X, msh.TextureCoordinateChannels[2][v].Y); } if (msh.HasTangentBasis) { vert.tan = new Vector4(msh.Tangents[v].X, msh.Tangents[v].Y, msh.Tangents[v].Z, 1); } if (msh.HasVertexColors(0) && !isDae) { vert.col = new Vector4(msh.VertexColorChannels[0][v].R, msh.VertexColorChannels[0][v].G, msh.VertexColorChannels[0][v].B, msh.VertexColorChannels[0][v].A); } if (msh.HasVertexColors(1) && !isDae) { vert.col2 = new Vector4(msh.VertexColorChannels[1][v].R, msh.VertexColorChannels[1][v].G, msh.VertexColorChannels[1][v].B, msh.VertexColorChannels[1][v].A); } if (msh.HasTangentBasis) { vert.bitan = new Vector4(msh.BiTangents[v].X, msh.BiTangents[v].Y, msh.BiTangents[v].Z, 1); } vertices.Add(vert); Console.WriteLine($"{msh.Name} COLOR { vert.col}"); } if (msh.HasBones && msh.BoneCount > 1) { for (int i = 0; i < msh.BoneCount; i++) { Bone bn = msh.Bones[i]; if (bn.HasVertexWeights) { foreach (VertexWeight w in bn.VertexWeights) { if (DaeHelper.IDMapToName.ContainsKey(bn.Name)) { bn.Name = DaeHelper.IDMapToName[bn.Name]; } vertices[w.VertexID].boneWeights.Add(w.Weight); vertices[w.VertexID].boneNames.Add(bn.Name); if (!BoneNames.Contains(bn.Name)) { BoneNames.Add(bn.Name); } } } } } return(vertices); }
public STGenericObject CreateGenericObject(SELib.SEModel seModel, SELib.SEModelMesh seMesh) { int Index = seModel.Meshes.IndexOf(seMesh); STGenericObject mesh = new STGenericObject(); mesh.ObjectName = $"Mesh_{Index}"; if (seMesh.MaterialReferenceIndicies.Count > 0) { mesh.MaterialIndex = seMesh.MaterialReferenceIndicies[0]; } mesh.HasPos = true; for (int v = 0; v < seMesh.VertexCount; v++) { if (seMesh.Verticies[v].UVSets.Count > 0) { mesh.HasUv0 = true; } if (seMesh.Verticies[v].Weights.Count > 0) { mesh.HasIndices = true; for (int w = 0; w < seMesh.Verticies[v].WeightCount; w++) { if (seMesh.Verticies[v].Weights[w].BoneWeight != 0) { mesh.HasWeights = true; } } } if (seMesh.Verticies[v].VertexColor != SELib.Utilities.Color.White) { mesh.HasVertColors = true; } if (seMesh.Verticies[v].VertexNormal != SELib.Utilities.Vector3.Zero) { mesh.HasNrm = true; } Vertex vertex = new Vertex(); mesh.vertices.Add(vertex); vertex.pos = ToTKVector3(seMesh.Verticies[v].Position); vertex.nrm = ToTKVector3(seMesh.Verticies[v].VertexNormal); vertex.col = ToTKVector4(seMesh.Verticies[v].VertexColor); for (int u = 0; u < seMesh.Verticies[v].UVSetCount; u++) { if (u == 0) { vertex.uv0 = ToTKVector2(seMesh.Verticies[v].UVSets[u]); } if (u == 1) { vertex.uv1 = ToTKVector2(seMesh.Verticies[v].UVSets[u]); } if (u == 2) { vertex.uv2 = ToTKVector2(seMesh.Verticies[v].UVSets[u]); } } for (int w = 0; w < seMesh.Verticies[v].WeightCount; w++) { //Get the bone name from the index. Indices for formats get set after the importer string BoneName = seModel.Bones[(int)seMesh.Verticies[v].Weights[w].BoneIndex].BoneName; float BoneWeight = seMesh.Verticies[v].Weights[w].BoneWeight; vertex.boneNames.Add(BoneName); vertex.boneWeights.Add(BoneWeight); } } mesh.lodMeshes = new List <STGenericObject.LOD_Mesh>(); var lodMesh = new STGenericObject.LOD_Mesh(); lodMesh.PrimativeType = STPrimitiveType.Triangles; mesh.lodMeshes.Add(lodMesh); for (int f = 0; f < seMesh.FaceCount; f++) { lodMesh.faces.Add((int)seMesh.Faces[f].FaceIndex1); lodMesh.faces.Add((int)seMesh.Faces[f].FaceIndex2); lodMesh.faces.Add((int)seMesh.Faces[f].FaceIndex3); } return(mesh); }
public static void Export(string FileName, ExportSettings settings, List <STGenericObject> Meshes, List <STGenericMaterial> Materials, List <STGenericTexture> Textures, STSkeleton skeleton = null, List <int> NodeArray = null) { if (Materials == null) { Materials = new List <STGenericMaterial>(); } List <string> failedTextureExport = new List <string>(); STProgressBar progressBar = new STProgressBar(); progressBar.Task = "Exporting Model..."; progressBar.Value = 0; progressBar.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; progressBar.Show(); progressBar.Refresh(); if (settings.UseOldExporter) { AssimpSaver saver = new AssimpSaver(); STGenericModel model = new STGenericModel(); model.Objects = Meshes; model.Materials = Materials; saver.SaveFromModel(model, FileName, Textures, skeleton, NodeArray); return; } string TexturePath = System.IO.Path.GetDirectoryName(FileName); using (ColladaWriter writer = new ColladaWriter(FileName, settings)) { writer.WriteAsset(); if (Materials.Count > 0) { List <string> textureNames = new List <string>(); for (int i = 0; i < Textures?.Count; i++) { textureNames.Add(Textures[i].Text); if (settings.ExportTextures) { progressBar.Task = $"Exporting Texture {Textures[i].Text}"; progressBar.Value = ((i * 100) / Textures.Count); progressBar.Refresh(); try { var bitmap = Textures[i].GetBitmap(); if (bitmap != null) { string textureName = Textures[i].Text; if (textureName.RemoveIllegaleFileNameCharacters() != textureName) { string properName = textureName.RemoveIllegaleFileNameCharacters(); for (int m = 0; m < Materials?.Count; m++) { foreach (var tex in Materials[m].TextureMaps) { if (tex.Name == textureName) { tex.Name = properName; } } } textureName = properName; } bitmap.Save($"{TexturePath}/{textureName}.png"); bitmap.Dispose(); GC.Collect(); } } catch (Exception ex) { failedTextureExport.Add(Textures[i].Text); } } } List <Material> materials = new List <Material>(); foreach (var mat in Materials) { Material material = new Material(); material.Name = mat.Text; materials.Add(material); foreach (var tex in mat.TextureMaps) { TextureMap texMap = new TextureMap(); texMap.Name = tex.Name; if (tex.Type == STGenericMatTexture.TextureType.Diffuse) { texMap.Type = PhongTextureType.diffuse; } else if (tex.Type == STGenericMatTexture.TextureType.Normal) { texMap.Type = PhongTextureType.bump; } else if (tex.Type == STGenericMatTexture.TextureType.Specular) { texMap.Type = PhongTextureType.specular; } else if (tex.Type == STGenericMatTexture.TextureType.Emission) { texMap.Type = PhongTextureType.emission; } else { continue; //Skip adding unknown types } if (tex.WrapModeS == STTextureWrapMode.Repeat) { texMap.WrapModeS = SamplerWrapMode.WRAP; } else if (tex.WrapModeS == STTextureWrapMode.Mirror) { texMap.WrapModeS = SamplerWrapMode.MIRROR; } else if (tex.WrapModeS == STTextureWrapMode.Clamp) { texMap.WrapModeS = SamplerWrapMode.CLAMP; } if (tex.WrapModeT == STTextureWrapMode.Repeat) { texMap.WrapModeT = SamplerWrapMode.WRAP; } else if (tex.WrapModeT == STTextureWrapMode.Mirror) { texMap.WrapModeT = SamplerWrapMode.MIRROR; } else if (tex.WrapModeT == STTextureWrapMode.Clamp) { texMap.WrapModeT = SamplerWrapMode.CLAMP; } //If no textures are saved, still keep images references //So the user can still dump textures after if (Textures?.Count == 0) { textureNames.Add($"{texMap.Name}"); } material.Textures.Add(texMap); } } writer.WriteLibraryImages(textureNames.ToArray()); writer.WriteLibraryMaterials(materials); writer.WriteLibraryEffects(materials); } else { writer.WriteLibraryImages(); } if (skeleton != null) { foreach (var bone in skeleton.bones) { //Set the inverse matrix var inverse = skeleton.GetBoneTransform(bone).Inverted(); var transform = bone.GetTransform(); float[] Transform = new float[] { transform.M11, transform.M21, transform.M31, transform.M41, transform.M12, transform.M22, transform.M32, transform.M42, transform.M13, transform.M23, transform.M33, transform.M43, transform.M14, transform.M24, transform.M34, transform.M44 }; float[] InvTransform = new float[] { inverse.M11, inverse.M21, inverse.M31, inverse.M41, inverse.M12, inverse.M22, inverse.M32, inverse.M42, inverse.M13, inverse.M23, inverse.M33, inverse.M43, inverse.M14, inverse.M24, inverse.M34, inverse.M44 }; writer.AddJoint(bone.Text, bone.parentIndex == -1 ? "" : skeleton.bones[bone.parentIndex].Text, Transform, InvTransform); } } int meshIndex = 0; writer.StartLibraryGeometries(); foreach (var mesh in Meshes) { progressBar.Task = $"Exporting Mesh {mesh.Text}"; progressBar.Value = ((meshIndex++ *100) / Meshes.Count); progressBar.Refresh(); int[] IndexTable = null; if (NodeArray != null) { IndexTable = NodeArray.ToArray(); } writer.StartGeometry(mesh.Text); if (mesh.MaterialIndex != -1 && Materials.Count > mesh.MaterialIndex) { writer.CurrentMaterial = Materials[mesh.MaterialIndex].Text; } // collect sources List <float> Position = new List <float>(); List <float> Normal = new List <float>(); List <float> UV0 = new List <float>(); List <float> UV1 = new List <float>(); List <float> UV2 = new List <float>(); List <float> UV3 = new List <float>(); List <float> Color = new List <float>(); List <int[]> BoneIndices = new List <int[]>(); List <float[]> BoneWeights = new List <float[]>(); bool HasNormals = false; bool HasColors = false; bool HasUV0 = false; bool HasUV1 = false; bool HasUV2 = false; bool HasBoneIds = false; foreach (var vertex in mesh.vertices) { //Remove zero weights if (settings.OptmizeZeroWeights) { float MaxWeight = 1; for (int i = 0; i < 4; i++) { if (vertex.boneWeights.Count <= i) { continue; } if (vertex.boneIds.Count < i + 1) { vertex.boneWeights[i] = 0; MaxWeight = 0; } else { float weight = vertex.boneWeights[i]; if (vertex.boneWeights.Count == i + 1) { weight = MaxWeight; } if (weight >= MaxWeight) { weight = MaxWeight; MaxWeight = 0; } else { MaxWeight -= weight; } vertex.boneWeights[i] = weight; } } } if (vertex.nrm != Vector3.Zero) { HasNormals = true; } if (vertex.col != Vector4.One && settings.UseVertexColors) { HasColors = true; } if (vertex.uv0 != Vector2.Zero) { HasUV0 = true; } if (vertex.uv1 != Vector2.Zero) { HasUV1 = true; } if (vertex.uv2 != Vector2.Zero) { HasUV2 = true; } if (vertex.boneIds.Count > 0) { HasBoneIds = true; } Position.Add(vertex.pos.X); Position.Add(vertex.pos.Y); Position.Add(vertex.pos.Z); Normal.Add(vertex.nrm.X); Normal.Add(vertex.nrm.Y); Normal.Add(vertex.nrm.Z); if (settings.FlipTexCoordsVertical) { UV0.Add(vertex.uv0.X); UV0.Add(1 - vertex.uv0.Y); UV1.Add(vertex.uv1.X); UV1.Add(1 - vertex.uv1.Y); UV2.Add(vertex.uv2.X); UV2.Add(1 - vertex.uv2.Y); } else { UV0.Add(vertex.uv0.X); UV0.Add(vertex.uv0.Y); UV1.Add(vertex.uv1.X); UV1.Add(vertex.uv1.Y); UV2.Add(vertex.uv2.X); UV2.Add(vertex.uv2.Y); } Color.AddRange(new float[] { vertex.col.X, vertex.col.Y, vertex.col.Z, vertex.col.W }); List <int> bIndices = new List <int>(); List <float> bWeights = new List <float>(); for (int b = 0; b < vertex.boneIds.Count; b++) { if (b > mesh.VertexSkinCount - 1) { continue; } if (vertex.boneWeights.Count > b) { if (vertex.boneWeights[b] == 0) { continue; } } int index = -1; if (IndexTable != null) { index = (int)IndexTable[vertex.boneIds[b]]; } else { index = (int)vertex.boneIds[b]; } if (index != -1 && index < skeleton?.bones.Count) { bIndices.Add(index); } //Some models may only use indices (single bind, rigid skin) if (vertex.boneWeights.Count > b) { bWeights.Add(vertex.boneWeights[b]); } else { bWeights.Add(1); } } if (bIndices.Count == 0 && mesh.BoneIndex != -1) { HasBoneIds = true; bIndices.Add(mesh.BoneIndex); bWeights.Add(1); } BoneIndices.Add(bIndices.ToArray()); BoneWeights.Add(bWeights.ToArray()); } List <TriangleList> triangleLists = new List <TriangleList>(); if (mesh.lodMeshes.Count > 0) { TriangleList triangleList = new TriangleList(); triangleLists.Add(triangleList); var lodMesh = mesh.lodMeshes[mesh.DisplayLODIndex]; List <int> faces = new List <int>(); if (lodMesh.PrimativeType == STPrimitiveType.TrangleStrips) { faces = STGenericObject.ConvertTriangleStripsToTriangles(lodMesh.faces); } else { faces = lodMesh.faces; } for (int i = 0; i < faces.Count; i++) { triangleList.Indices.Add((uint)faces[i]); } } if (mesh.PolygonGroups.Count > 0) { foreach (var group in mesh.PolygonGroups) { TriangleList triangleList = new TriangleList(); triangleLists.Add(triangleList); if (group.MaterialIndex != -1 && Materials.Count > group.MaterialIndex) { triangleList.Material = Materials[group.MaterialIndex].Text; } List <int> faces = new List <int>(); if (group.PrimativeType == STPrimitiveType.TrangleStrips) { faces = STGenericObject.ConvertTriangleStripsToTriangles(group.faces); } else { faces = group.faces; } for (int i = 0; i < faces.Count; i++) { triangleList.Indices.Add((uint)faces[i]); } } } // write sources writer.WriteGeometrySource(mesh.Text, SemanticType.POSITION, Position.ToArray(), triangleLists.ToArray()); if (HasNormals) { writer.WriteGeometrySource(mesh.Text, SemanticType.NORMAL, Normal.ToArray(), triangleLists.ToArray()); } if (HasColors) { writer.WriteGeometrySource(mesh.Text, SemanticType.COLOR, Color.ToArray(), triangleLists.ToArray()); } if (HasUV0) { writer.WriteGeometrySource(mesh.Text, SemanticType.TEXCOORD, UV0.ToArray(), triangleLists.ToArray(), 0); } if (HasUV1) { writer.WriteGeometrySource(mesh.Text, SemanticType.TEXCOORD, UV1.ToArray(), triangleLists.ToArray(), 1); } if (HasUV2) { writer.WriteGeometrySource(mesh.Text, SemanticType.TEXCOORD, UV2.ToArray(), triangleLists.ToArray(), 2); } if (HasBoneIds) { writer.AttachGeometryController(BoneIndices, BoneWeights); } writer.EndGeometryMesh(); } writer.EndGeometrySection(); } progressBar?.Close(); if (!settings.SuppressConfirmDialog) { System.Windows.Forms.MessageBox.Show($"Exported {FileName} Successfuly!"); } }