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); }
/// <summary> /// Reads a SEAnim from a stream /// </summary> /// <param name="Stream">The stream to read from</param> /// <returns>A SEAnim if successful, otherwise throws an error and returns null</returns> public static SEModel Read(Stream Stream) { // Create a new model var model = new SEModel(); // Setup a new reader using (ExtendedBinaryReader readFile = new ExtendedBinaryReader(Stream)) { // Magic var Magic = readFile.ReadChars(7); // Version var Version = readFile.ReadInt16(); // Header size var HeaderSize = readFile.ReadInt16(); // Check magic if (!Magic.SequenceEqual(new char[] { 'S', 'E', 'M', 'o', 'd', 'e', 'l' })) { // Bad file throw new Exception("Bad SEModel file, magic was invalid"); } // Data present flags var DataPresentFlags = readFile.ReadByte(); // Bone data present flags var BoneDataPresentFlags = readFile.ReadByte(); // Mesh data present flags var MeshDataPresentFlags = readFile.ReadByte(); // Read counts var BoneCount = readFile.ReadInt32(); var MeshCount = readFile.ReadInt32(); var MatCount = readFile.ReadInt32(); // Skip 3 reserved bytes readFile.BaseStream.Position += 3; // Read bone tag names List <string> BoneNames = new List <string>(); // Loop for (int i = 0; i < BoneCount; i++) { BoneNames.Add(readFile.ReadNullTermString()); } // Loop and read bones for (int i = 0; i < BoneCount; i++) { // Read bone flags (unused) var BoneFlags = readFile.ReadByte(); // Read bone index var ParentIndex = readFile.ReadInt32(); // Check for global matricies Vector3 GlobalPosition = Vector3.Zero; Quaternion GlobalRotation = Quaternion.Identity; // Check if (Convert.ToBoolean(BoneDataPresentFlags & (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_GLOBAL_MATRIX)) { GlobalPosition = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); GlobalRotation = new Quaternion(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); } // Check for local matricies Vector3 LocalPosition = Vector3.Zero; Quaternion LocalRotation = Quaternion.Identity; // Check if (Convert.ToBoolean(BoneDataPresentFlags & (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_LOCAL_MATRIX)) { LocalPosition = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); LocalRotation = new Quaternion(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); } // Check for scales Vector3 Scale = Vector3.One; // Check if (Convert.ToBoolean(BoneDataPresentFlags & (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_SCALES)) { Scale = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); } // Add the bone model.AddBone(BoneNames[i], ParentIndex, GlobalPosition, GlobalRotation, LocalPosition, LocalRotation, Scale); } // Loop and read meshes for (int i = 0; i < MeshCount; i++) { // Make a new submesh var mesh = new SEModelMesh(); // Read mesh flags (unused) var MeshFlags = readFile.ReadByte(); // Read counts var MatIndiciesCount = readFile.ReadByte(); var MaxSkinInfluenceCount = readFile.ReadByte(); var VertexCount = readFile.ReadInt32(); var FaceCount = readFile.ReadInt32(); // Loop and read positions for (int v = 0; v < VertexCount; v++) { mesh.AddVertex(new SEModelVertex() { Position = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()) }); } // Read uvlayers if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_UVSET)) { for (int v = 0; v < VertexCount; v++) { for (int l = 0; l < MatIndiciesCount; l++) { mesh.Verticies[v].UVSets.Add(new Vector2(readFile.ReadSingle(), readFile.ReadSingle())); } } } // Read normals if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_NORMALS)) { // Loop and read vertex normals for (int v = 0; v < VertexCount; v++) { mesh.Verticies[v].VertexNormal = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); } } // Read colors if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_COLOR)) { // Loop and read colors for (int v = 0; v < VertexCount; v++) { mesh.Verticies[v].VertexColor = new Color(readFile.ReadByte(), readFile.ReadByte(), readFile.ReadByte(), readFile.ReadByte()); } } // Read weights if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_WEIGHTS)) { for (int v = 0; v < VertexCount; v++) { // Read IDs and Values for (int l = 0; l < MaxSkinInfluenceCount; l++) { if (BoneCount <= 0xFF) { mesh.Verticies[v].Weights.Add(new SEModelWeight() { BoneIndex = readFile.ReadByte(), BoneWeight = readFile.ReadSingle() }); } else if (BoneCount <= 0xFFFF) { mesh.Verticies[v].Weights.Add(new SEModelWeight() { BoneIndex = readFile.ReadUInt16(), BoneWeight = readFile.ReadSingle() }); } else { mesh.Verticies[v].Weights.Add(new SEModelWeight() { BoneIndex = readFile.ReadUInt32(), BoneWeight = readFile.ReadSingle() }); } } } } // Loop and read faces for (int f = 0; f < FaceCount; f++) { if (VertexCount <= 0xFF) { mesh.AddFace(readFile.ReadByte(), readFile.ReadByte(), readFile.ReadByte()); } else if (VertexCount <= 0xFFFF) { mesh.AddFace(readFile.ReadUInt16(), readFile.ReadUInt16(), readFile.ReadUInt16()); } else { mesh.AddFace(readFile.ReadUInt32(), readFile.ReadUInt32(), readFile.ReadUInt32()); } } // Read material reference indicies for (int f = 0; f < MatIndiciesCount; f++) { mesh.AddMaterialIndex(readFile.ReadInt32()); } // Add the mesh model.AddMesh(mesh); } // Loop and read materials for (int m = 0; m < MatCount; m++) { var mat = new SEModelMaterial(); // Read the name mat.Name = readFile.ReadNullTermString(); // Read IsSimpleMaterial var IsSimpleMaterial = readFile.ReadBoolean(); // Read the material if (IsSimpleMaterial) { mat.MaterialData = new SEModelSimpleMaterial() { DiffuseMap = readFile.ReadNullTermString(), NormalMap = readFile.ReadNullTermString(), SpecularMap = readFile.ReadNullTermString() }; } // Add the material model.AddMaterial(mat); } } // Return result return(model); }
/// <summary> /// Adds the given mesh to the model /// </summary> /// <param name="Mesh">The mesh to add</param> public void AddMesh(SEModelMesh Mesh) { // Add it Meshes.Add(Mesh); }
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); }