public VertexStore(int numberOfNodes) { NumberOfNodes = numberOfNodes; Vertices = new Model.Vertex[constInitialNumberOfVertices]; for (int i = 0; i < constInitialNumberOfVertices; ++i) { Vertices[i] = new Vertex(); } NextFreeItemIndex = 0; }
Point PerspectiveProjection(Model.Vertex converted) { return(converted.Y > 0.01 ? new Point(Screen.Width / 2 + (int)(converted.X / converted.Y * Focus), Screen.Height / 2 + (int)(-converted.Z / converted.Y * Focus)) : new Point(-1, -1)); }
Point OrthogonalProjectection(Model.Vertex converted) { return(new Point(Screen.Width / 2 + (int)(converted.X * 500 * OrthogonalScale), Screen.Height / 2 + (int)(-converted.Z * 500 * OrthogonalScale))); }
private double GetDistance(Model.Vertex vertex) { return(Math.Sqrt(Math.Pow(vertex.X, 2) + Math.Pow(vertex.Y, 2) + Math.Pow(vertex.Z, 2))); }
private static Model LoadSEModel(string filePath) { var model = new Model(Path.GetFileNameWithoutExtension(filePath)); var input = SEModel.Read(filePath); Printer.WriteLine("LOADER", string.Format("Loading {0}", model.Name)); foreach (var bone in input.Bones) { model.Bones.Add(new Model.Bone( bone.BoneName, bone.BoneParent, new Vector3( (float)bone.LocalPosition.X, (float)bone.LocalPosition.Y, (float)bone.LocalPosition.Z), new Quaternion( (float)bone.LocalRotation.X, (float)bone.LocalRotation.Y, (float)bone.LocalRotation.Z, (float)bone.LocalRotation.W), new Vector3( (float)bone.GlobalPosition.X, (float)bone.GlobalPosition.Y, (float)bone.GlobalPosition.Z), new Quaternion( (float)bone.GlobalRotation.X, (float)bone.GlobalRotation.Y, (float)bone.GlobalRotation.Z, (float)bone.GlobalRotation.W))); } foreach (var semesh in input.Meshes) { var mesh = new Model.Mesh((int)semesh.VertexCount, (int)semesh.FaceCount); foreach (var mtl in semesh.MaterialReferenceIndicies) { mesh.MaterialIndices.Add(mtl); } foreach (var severtex in semesh.Verticies) { var vertex = new Model.Vertex( new Vector3((float)severtex.Position.X, (float)severtex.Position.Y, (float)severtex.Position.Z), new Vector3((float)severtex.VertexNormal.X, (float)severtex.VertexNormal.Y, (float)severtex.VertexNormal.Z)); foreach (var uv in severtex.UVSets) { vertex.UVs.Add(new Vector2((float)uv.X, (float)uv.Y)); } foreach (var weight in severtex.Weights) { vertex.Weights.Add(new Model.Vertex.Weight() { BoneIndex = (int)weight.BoneIndex, Influence = weight.BoneWeight }); } vertex.Color = new Vector4( severtex.VertexColor.R / 255.0f, severtex.VertexColor.G / 255.0f, severtex.VertexColor.B / 255.0f, severtex.VertexColor.A / 255.0f); mesh.Vertices.Add(vertex); } foreach (var face in semesh.Faces) { mesh.Faces.Add(new Model.Face((int)face.FaceIndex1, (int)face.FaceIndex2, (int)face.FaceIndex3)); } model.Meshes.Add(mesh); } foreach (var material in input.Materials) { model.Materials.Add(new Model.Material(material.Name)); } Printer.WriteLine("LOADER", string.Format("Loaded {0}", model.Name)); return(model); }
static void Main(string[] args) { Printer.WriteLine("INIT", "---------------------------"); Printer.WriteLine("INIT", "ModelMerger by Scobalula"); Printer.WriteLine("INIT", "Merges SEModels into 1"); Printer.WriteLine("INIT", string.Format("Version {0}", Assembly.GetExecutingAssembly().GetName().Version)); Printer.WriteLine("INIT", "---------------------------"); try { var models = LoadModels(args); if (models.Count == 0) { Printer.WriteLine("USAGE", "Simply drag and drop supported model files onto the exe"); } else { var rootModel = GetRootModel(models); if (rootModel == null) { throw new Exception("Failed to obtain root model"); } Printer.WriteLine("MERGER", string.Format("Using {0} as root model", rootModel.Name)); var merged = new List <Model>(models.Count) { rootModel }; var outputFolder = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Merged Models"); // Keep looping until we've resolved all models // We do this because some models connect to other // so we need to wait until we've processed that model while (merged.Count < models.Count) { foreach (var model in models) { // Check if we've processed, also considers root as it's added to merged if (merged.Contains(model)) { continue; } // If we have a model that doesn't exist, and can be connected, we must wait // for it's parent model to be connected if (!rootModel.HasBone(model.Bones[0].Name) && CanBeConnected(model, models)) { continue; } // Add to the group merged.Add(model); Printer.WriteLine("MERGER", string.Format("Merging {0}", model.Name)); foreach (var bone in model.Bones) { if (!rootModel.HasBone(bone.Name)) { var nBone = new Model.Bone(bone.Name, bone.ParentIndex, bone.LocalPosition, bone.LocalRotation); if (bone.ParentIndex > -1) { nBone.ParentIndex = rootModel.Bones.FindIndex(x => x.Name == model.Bones[nBone.ParentIndex].Name); } rootModel.Bones.Add(nBone); } } // Compute global positions (we need them for offsetting) rootModel.GenerateGlobalBoneData(); model.GenerateGlobalBoneData(); // Get root and the new root, to compute offsets var root = model.Bones[0]; var nRoot = rootModel.Bones.Find(x => x.Name == root.Name); // TODO: compute this for each bone and utilize weights // but as an option, as it may cause severe deformations // if bones have moved var translation = nRoot.GlobalPosition - root.GlobalPosition; var rotation = (nRoot.GlobalRotation * root.GlobalRotation.Inverse()).ToMatrix(); foreach (var material in model.Materials) { if (rootModel.Materials.Find(x => x.Name == material.Name) == null) { rootModel.Materials.Add(material); } } foreach (var mesh in model.Meshes) { var nMesh = new Model.Mesh(mesh.Vertices.Count, 0) { Faces = new List <Model.Face>(mesh.Faces) }; foreach (var material in mesh.MaterialIndices) { nMesh.MaterialIndices.Add(rootModel.Materials.FindIndex(x => x.Name == model.Materials[material].Name)); } foreach (var vertex in mesh.Vertices) { var nVertex = new Model.Vertex(vertex.Position, vertex.Normal, vertex.Tangent) { Color = vertex.Color, Weights = new List <Model.Vertex.Weight>(vertex.Weights.Count), UVs = new List <Vector2>(vertex.UVs) }; foreach (var weight in vertex.Weights) { nVertex.Weights.Add(new Model.Vertex.Weight() { Influence = weight.Influence, BoneIndex = rootModel.Bones.FindIndex(x => x.Name == model.Bones[weight.BoneIndex].Name), }); } // Now move it to the new position nVertex.Position = rotation.TransformVector(vertex.Position); nVertex.Normal = rotation.TransformVector(vertex.Normal); nVertex.Position += translation; nMesh.Vertices.Add(nVertex); } rootModel.Meshes.Add(nMesh); } Printer.WriteLine("MERGER", string.Format("Merged {0}", model.Name)); } } Printer.WriteLine("MERGER", string.Format("Saving {0}", rootModel.Name)); Directory.CreateDirectory(outputFolder); rootModel.Save(Path.Combine(outputFolder, rootModel.Name + ".semodel")); Printer.WriteLine("MERGER", string.Format("Saved {0}", rootModel.Name)); } } catch (Exception e) { Printer.WriteLine("ERROR", "An unhandled exception has occured:", ConsoleColor.DarkRed); Console.WriteLine(e); } Printer.WriteLine("DONE", "Execution complete, press Enter to exit"); Console.ReadLine(); }
/// <summary> /// Loads Meshes from a Resident Evil 7 Mesh File /// </summary> private static List <List <Model> > ConvertRE7(BinaryReader reader) { var results = new List <List <Model> >(3); var header = reader.ReadStruct <MeshHeaderRE7>(); var boneDataHeader = new BoneDataHeaderRE7(); var geometryHeader = new GeometryHeaderRE7(); if (header.BoneDataHeaderPointer > 0) { boneDataHeader = reader.ReadStruct <BoneDataHeaderRE7>(header.BoneDataHeaderPointer); } if (header.GeometryPointer > 0) { geometryHeader = reader.ReadStruct <GeometryHeaderRE7>(header.GeometryPointer); } // Parse all strings for bones, materials, etc. into lists to make it easier to pass around, etc. var strings = new List <string>(header.StringCount); foreach (var offset in reader.ReadArray <long>(header.StringTablePointer, header.StringCount)) { strings.Add(reader.ReadNullTerminatedString(offset)); } var boneNames = new List <string>(boneDataHeader.BoneCount); foreach (var boneNameIndex in reader.ReadArray <ushort>(header.BoneNamesPointer, boneDataHeader.BoneCount)) { boneNames.Add(strings[boneNameIndex]); } var bones = new List <Model.Bone>(boneDataHeader.BoneCount); if (header.BoneDataHeaderPointer > 0) { var boneDatas = reader.ReadArray <BoneDataRE7>(boneDataHeader.BoneTablePointer, boneDataHeader.BoneCount); var boneMatrices = reader.ReadArray <Matrix4x4>(boneDataHeader.MatricesPointer, boneDataHeader.BoneCount); for (ushort i = 0; i < boneDataHeader.BoneCount; i++) { var bone = new Model.Bone(boneNames[i], boneDatas[i].ParentIndex, new Vector3( boneMatrices[i].W.X, boneMatrices[i].W.Y, boneMatrices[i].W.Z), boneMatrices[i].ToQuaternion()); bones.Add(bone); } } bool firstMdlProcessed = false; for (int mdl = 0; mdl < 3; mdl++) { if (header.ModelPointers[mdl] == 0) { continue; } if (firstMdlProcessed) { break; } var lods = new List <Model>(); var modelHeader = reader.ReadStruct <ModelHeaderRE7>(header.ModelPointers[mdl]); var vertexSize = 20 + (modelHeader.UVCount * 4) + (boneDataHeader.BoneCount > 0 ? 16 : 0); reader.BaseStream.Position = header.ModelPointers[mdl] + (firstMdlProcessed ? 16 : 64); var materialIndices = reader.ReadArray <short>(header.MaterialNamesPointer, modelHeader.MaterialCount); firstMdlProcessed = true; var lodPointers = reader.ReadArray <long>(reader.ReadInt64(), modelHeader.LODCount); foreach (var lodPointer in lodPointers) { var model = new Model() { Bones = bones }; var uniqueMaterials = new List <string>(modelHeader.MaterialCount); var lodHeader = reader.ReadStruct <LODHeaderRE7>(lodPointer); var boneIndices = reader.ReadArray <short>(lodPointer + 16, lodHeader.BoneCount); var meshPointers = reader.ReadArray <long>(lodHeader.MeshesPointer, lodHeader.MeshCount); foreach (var meshPointer in meshPointers) { var mesh = reader.ReadStruct <LODMeshRE7>(meshPointer); var subMeshes = reader.ReadArray <LODSubMeshRE7>(meshPointer + 16, mesh.SubMeshCount); int verticesRead = 0; for (int i = 0; i < subMeshes.Length; i++) { var materialName = strings[materialIndices[subMeshes[i].MaterialIndex]]; if (!uniqueMaterials.Contains(materialName)) { uniqueMaterials.Add(materialName); } var subMesh = new Model.Mesh(); subMesh.MaterialIndices.Add(uniqueMaterials.IndexOf(materialName)); int subMeshVertexCount = 0; int subMeshFaceCount = subMeshes[i].FaceCount; // Since the counts aren't stored in each, we can use this to determine the counts if (i != subMeshes.Length - 1) { subMeshVertexCount = subMeshes[i + 1].VertexIndex - subMeshes[i].VertexIndex; } else { subMeshVertexCount = mesh.VertexCount - verticesRead; } verticesRead += subMeshVertexCount; reader.BaseStream.Position = header.GeometryPointer + 48 + (vertexSize * subMeshes[i].VertexIndex); for (int v = 0; v < subMeshVertexCount; v++) { // Base vertex data var vertex = new Model.Vertex( reader.ReadStruct <Vector3>(), reader.ReadStruct <PackedVector3>().Unpack(), reader.ReadStruct <PackedVector3>().Unpack()); vertex.UVs.Add(new Vector2(reader.ReadStruct <Half>(), reader.ReadStruct <Half>())); // Skip unnsupported UV layers reader.BaseStream.Position += 4 * (modelHeader.UVCount - 1); // Check if we have bones if (lodHeader.BoneCount > 0) { var localBoneIndices = reader.ReadBytes(8); var weights = reader.ReadBytes(8); var weightSum = 0.0f; for (int w = 0; w < 8 && weights[w] != 0; w++) { vertex.Weights.Add(new Model.Vertex.Weight() { BoneIndex = boneIndices[localBoneIndices[w]], Influence = weights[w] / 255.0f }); weightSum += vertex.Weights[w].Influence; } var multiplier = 1.0f / weightSum; foreach (var weight in vertex.Weights) { weight.Influence *= multiplier; } } subMesh.Vertices.Add(vertex); } switch (lodHeader.Flags) { case 0: reader.BaseStream.Position = geometryHeader.FaceBufferOffset + (2 * subMeshes[i].FaceIndex); for (int f = 0; f < subMeshes[i].FaceCount / 3; f++) { var v1 = reader.ReadUInt16(); var v2 = reader.ReadUInt16(); var v3 = reader.ReadUInt16(); if (v1 != v2 && v2 != v3 && v3 != v1) { subMesh.Faces.Add(new Model.Face(v1, v2, v3)); } } break; case 1: reader.BaseStream.Position = geometryHeader.FaceBufferOffset + (4 * subMeshes[i].FaceIndex); for (int f = 0; f < subMeshes[i].FaceCount / 3; f++) { var v1 = reader.ReadInt32(); var v2 = reader.ReadInt32(); var v3 = reader.ReadInt32(); if (v1 != v2 && v2 != v3 && v3 != v1) { subMesh.Faces.Add(new Model.Face(v1, v2, v3)); } } break; } model.Meshes.Add(subMesh); } } foreach (var materialName in uniqueMaterials) { model.Materials.Add(new Model.Material(materialName)); } lods.Add(model); } results.Add(lods); } return(results); }