static void ProcessCNT(CNT cnt, Model model, int ParentBoneIndex = 0) { int boneIndex; SceneManager.Current.UpdateProgress(string.Format("Processing {0}", cnt.Name)); if (cnt.Section == CNT.NodeType.MODL || cnt.Section == CNT.NodeType.SKIN) { var m = SceneManager.Current.Content.Load<Model, MDLImporter>(cnt.Model, rootPath); boneIndex = model.AddMesh(m.Meshes[0], ParentBoneIndex); } else { boneIndex = model.AddMesh(null, ParentBoneIndex); switch (cnt.Section) { case CNT.NodeType.LITg: model.Bones[boneIndex].Type = BoneType.Light; if (cnt.EmbeddedLight) { model.Bones[boneIndex].Attachment = cnt.Light; } else { model.Bones[boneIndex].Attachment = SceneManager.Current.Content.Load<Model, LIGHTImporter>(cnt.LightName, rootPath).Bones[0].Attachment; model.Bones[boneIndex].AttachmentFile = cnt.LightName; } break; case CNT.NodeType.VFXI: model.Bones[boneIndex].Type = BoneType.VFX; model.Bones[boneIndex].AttachmentFile = cnt.VFXFile; break; } } model.SetName(cnt.Name, boneIndex); model.SetTransform( new Matrix4 ( cnt.Transform.M11, cnt.Transform.M12, cnt.Transform.M13, 0, cnt.Transform.M21, cnt.Transform.M22, cnt.Transform.M23, 0, cnt.Transform.M31, cnt.Transform.M32, cnt.Transform.M33, 0, cnt.Transform.M41, cnt.Transform.M42, cnt.Transform.M43, 1 ), boneIndex); foreach (CNT subcnt in cnt.Children) { ProcessCNT(subcnt, model, boneIndex); } }
static void ProcessCNT(CNT cnt, Model model, int ParentBoneIndex = 0) { int boneIndex; SceneManager.Current.UpdateProgress(string.Format("Processing {0}", cnt.Name)); if (cnt.Section == CNT.NodeType.MODL || cnt.Section == CNT.NodeType.SKIN) { var m = SceneManager.Current.Content.Load <Model, MDLImporter>(cnt.Model, rootPath); boneIndex = model.AddMesh(m.Meshes[0], ParentBoneIndex); } else { boneIndex = model.AddMesh(null, ParentBoneIndex); switch (cnt.Section) { case CNT.NodeType.LITg: model.Bones[boneIndex].Type = BoneType.Light; if (cnt.EmbeddedLight) { model.Bones[boneIndex].Attachment = cnt.Light; } else { model.Bones[boneIndex].Attachment = SceneManager.Current.Content.Load <Model, LIGHTImporter>(cnt.LightName, rootPath).Bones[0].Attachment; model.Bones[boneIndex].AttachmentFile = cnt.LightName; } break; case CNT.NodeType.VFXI: model.Bones[boneIndex].Type = BoneType.VFX; model.Bones[boneIndex].AttachmentFile = cnt.VFXFile; break; } } model.SetName(cnt.Name, boneIndex); model.SetTransform( new Matrix4( cnt.Transform.M11, cnt.Transform.M12, cnt.Transform.M13, 0, cnt.Transform.M21, cnt.Transform.M22, cnt.Transform.M23, 0, cnt.Transform.M31, cnt.Transform.M32, cnt.Transform.M33, 0, cnt.Transform.M41, cnt.Transform.M42, cnt.Transform.M43, 1 ), boneIndex); foreach (CNT subcnt in cnt.Children) { ProcessCNT(subcnt, model, boneIndex); } }
public override Asset Import(string path) { HIE hie = HIE.Load(path); Model model = new Model(); Model mshses = new Model(); foreach (string mesh in hie.Meshes) { Model mshs = SceneManager.Current.Content.Load <Model, MSHSImporter>(Path.GetFileNameWithoutExtension(mesh), Path.GetDirectoryName(path)); foreach (ModelMesh part in mshs.Meshes) { mshses.AddMesh(part); } } foreach (string texture in hie.Textures) { SceneManager.Current.Content.Load <Material, TXImporter>(texture, Path.GetDirectoryName(path), true); } processNode(hie.Root, model, mshses, hie); ModelManipulator.FlipAxis(model, Axis.X, true); return(model); }
static void processNode(TDRNode node, Model model, Model mshses, HIE hie, int parentBoneIndex = 0) { int boneIndex = parentBoneIndex; switch (node.Type) { case TDRNode.NodeType.Matrix: boneIndex = model.AddMesh(null, boneIndex); model.SetName(node.Name, boneIndex); model.SetTransform(node.Transform, boneIndex); break; case TDRNode.NodeType.Mesh: int index = node.Index; mshses.Meshes[index].MeshParts[0].Material = material; if (model.Bones[parentBoneIndex].Mesh == null) { model.SetMesh(mshses.Meshes[index], boneIndex); } else { boneIndex = model.AddMesh(mshses.Meshes[index], parentBoneIndex); model.SetName(mshses.Meshes[index].Name, boneIndex); } break; case TDRNode.NodeType.Texture: if (node.Index > -1) { material = SceneManager.Current.Content.Load <Material, TXImporter>(hie.Textures[node.Index]); } else { material = null; } break; } foreach (TDRNode child in node.Children) { processNode(child, model, mshses, hie, boneIndex); } }
public override Asset Import(string path) { MSHS mshs = MSHS.Load(path); Model model = new Model(); string name = Path.GetFileNameWithoutExtension(path); int meshnum = 0; foreach (var tdrmesh in mshs.Meshes) { ModelMesh mesh = new ModelMesh(); mesh.Name = name + meshnum++.ToString("0000"); ModelMeshPart meshpart = new ModelMeshPart(); meshpart.PrimitiveType = OpenTK.Graphics.OpenGL.PrimitiveType.Triangles; SceneManager.Current.UpdateProgress(string.Format("Processing {0}", mesh.Name)); for (int i = 0; i < tdrmesh.Faces.Count; i++) { var face = tdrmesh.Faces[i]; var v1 = tdrmesh.Vertexes[face.V1]; var v2 = tdrmesh.Vertexes[face.V2]; var v3 = tdrmesh.Vertexes[face.V3]; meshpart.AddFace( new OpenTK.Vector3[] { new OpenTK.Vector3(v1.Position.X, v1.Position.Y, v1.Position.Z), new OpenTK.Vector3(v2.Position.X, v2.Position.Y, v2.Position.Z), new OpenTK.Vector3(v3.Position.X, v3.Position.Y, v3.Position.Z) }, new OpenTK.Vector3[] { new OpenTK.Vector3(v1.Normal.X, v1.Normal.Y, v1.Normal.Z), new OpenTK.Vector3(v2.Normal.X, v2.Normal.Y, v2.Normal.Z), new OpenTK.Vector3(v3.Normal.X, v3.Normal.Y, v3.Normal.Z) }, new OpenTK.Vector2[] { new OpenTK.Vector2(v1.UV.X, v1.UV.Y), new OpenTK.Vector2(v2.UV.X, v2.UV.Y), new OpenTK.Vector2(v3.UV.X, v3.UV.Y) } ); } mesh.AddModelMeshPart(meshpart); model.SetName(mesh.Name, model.AddMesh(mesh)); } return model; }
public override Asset Import(string path) { MSHS mshs = MSHS.Load(path); Model model = new Model(); string name = Path.GetFileNameWithoutExtension(path); int meshnum = 0; foreach (var tdrmesh in mshs.Meshes) { ModelMesh mesh = new ModelMesh(); mesh.Name = name + meshnum++.ToString("0000"); ModelMeshPart meshpart = new ModelMeshPart(); meshpart.PrimitiveType = OpenTK.Graphics.OpenGL.PrimitiveType.Triangles; SceneManager.Current.UpdateProgress(string.Format("Processing {0}", mesh.Name)); for (int i = 0; i < tdrmesh.Faces.Count; i++) { var face = tdrmesh.Faces[i]; var v1 = tdrmesh.Vertexes[face.V1]; var v2 = tdrmesh.Vertexes[face.V2]; var v3 = tdrmesh.Vertexes[face.V3]; meshpart.AddFace( new OpenTK.Vector3[] { new OpenTK.Vector3(v1.Position.X, v1.Position.Y, v1.Position.Z), new OpenTK.Vector3(v2.Position.X, v2.Position.Y, v2.Position.Z), new OpenTK.Vector3(v3.Position.X, v3.Position.Y, v3.Position.Z) }, new OpenTK.Vector3[] { new OpenTK.Vector3(v1.Normal.X, v1.Normal.Y, v1.Normal.Z), new OpenTK.Vector3(v2.Normal.X, v2.Normal.Y, v2.Normal.Z), new OpenTK.Vector3(v3.Normal.X, v3.Normal.Y, v3.Normal.Z) }, new OpenTK.Vector2[] { new OpenTK.Vector2(v1.UV.X, v1.UV.Y), new OpenTK.Vector2(v2.UV.X, v2.UV.Y), new OpenTK.Vector2(v3.UV.X, v3.UV.Y) } ); } mesh.AddModelMeshPart(meshpart); model.SetName(mesh.Name, model.AddMesh(mesh)); } return(model); }
public override Asset Import(string path) { LIGHT light = LIGHT.Load(path); Model model = new Model(); SceneManager.Current.UpdateProgress(string.Format("Processing {0}", Path.GetFileName(path))); int boneIndex = model.AddMesh(null, 0); model.SetName(Path.GetFileNameWithoutExtension(path), boneIndex); model.Bones[boneIndex].Type = BoneType.Light; model.Bones[boneIndex].Attachment = light; SceneManager.Current.UpdateProgress(string.Format("Loaded {0}", Path.GetFileName(path))); return model; }
public override Asset Import(string path) { LIGHT light = LIGHT.Load(path); Model model = new Model(); SceneManager.Current.UpdateProgress(string.Format("Processing {0}", Path.GetFileName(path))); int boneIndex = model.AddMesh(null, 0); model.SetName(Path.GetFileNameWithoutExtension(path), boneIndex); model.Bones[boneIndex].Type = BoneType.Light; model.Bones[boneIndex].Attachment = light; SceneManager.Current.UpdateProgress(string.Format("Loaded {0}", Path.GetFileName(path))); return(model); }
private void btnOK_Click(object sender, EventArgs e) { if (lstWheels.SelectedItem != null) { Wheel = new Model(); Wheel wp = wheels[lstWheels.SelectedIndex]; CNTImporter cntImporter = new CNTImporter(); Model rim = (Model)cntImporter.Import(Path.Combine(wp.Archive, wp.Path, "rim.cnt")); foreach (ModelMesh mesh in rim.Meshes) { Wheel.SetName(mesh.Name, Wheel.AddMesh(mesh, 0)); } } Close(); }
public void Draw() { if (model == null) { model = new Model(); Sphere sphere = new Sphere(0.025f, 7, 7); ModelManipulator.SetVertexColour(sphere, 0, 255, 0, 255); model.AddMesh(sphere); model.SetRenderStyle(RenderStyle.Wireframe); } Matrix4D parentTransform = LinkedBone.CombinedTransform; Transform = Matrix4D.Identity; Vector3 v = parentTransform.ExtractTranslation(); parentTransform.Normalise(); parentTransform.M41 = v.X; parentTransform.M42 = v.Y; parentTransform.M43 = v.Z; Transform *= Matrix4D.CreateFromQuaternion(parentTransform.ExtractRotation()); Transform *= Matrix4D.CreateTranslation(parentTransform.ExtractTranslation()); Matrix4D mS = SceneManager.Current.Transform; Matrix4D mT = Transform; SceneManager.Current.Renderer.PushMatrix(); SceneManager.Current.Renderer.MultMatrix(ref mS); SceneManager.Current.Renderer.MultMatrix(ref mT); model.Draw(); SceneManager.Current.Renderer.PopMatrix(); }
/// <summary> /// Generates a cube model. /// </summary> /// <returns>The cube model.</returns> public Model GenerateCube() { Model m = new Model("cube") { Engine = this, Skinned = true, ModelMin = new BEPUutilities.Vector3(-1, -1, -1), ModelMax = new BEPUutilities.Vector3(1, 1, 1) }; ModelMesh mm = new ModelMesh("cube"); Renderable.ListBuilder builder = new Renderable.ListBuilder(); builder.Prepare(); TextureCoordinates tc = new TextureCoordinates(); builder.AddSide(Location.UnitX, tc, offs: true); builder.AddSide(Location.UnitY, tc, offs: true); builder.AddSide(Location.UnitZ, tc, offs: true); builder.AddSide(-Location.UnitX, tc, offs: true); builder.AddSide(-Location.UnitY, tc, offs: true); builder.AddSide(-Location.UnitZ, tc, offs: true); m.Original = new Model3D(); Model3DMesh m3m = new Model3DMesh() { Name = "cube" }; m3m.Indices = builder.Indices.ToArray(); m3m.Vertices = builder.Vertices.ConvertAll((o) => o.ToLocation().ToBVector()).ToArray(); m3m.TexCoords = builder.TexCoords.ConvertAll((o) => new BEPUutilities.Vector2(o.X, o.Y)).ToArray(); m3m.Normals = builder.Normals.ConvertAll((o) => o.ToLocation().ToBVector()).ToArray(); m.Original.Meshes = new Model3DMesh[] { m3m }; mm.BaseRenderable.GenerateVBO(builder); m.AddMesh(mm); return(m); }
public override Asset Import(string path) { ACT act = ACT.Load(path); Model model = new Model(); int boneIndex = 0; string fileName = path.Substring(path.LastIndexOf("\\") + 1); path = path.Replace(fileName, ""); Model dat = SceneManager.Current.Content.Load<Model, DATImporter>(fileName.Replace(".act", ".dat", StringComparison.OrdinalIgnoreCase), path); Material material = null; foreach (var section in act.Sections) { switch (section.Section) { case Section.Name: boneIndex = model.AddMesh(null, boneIndex); model.SetName(section.Identifier, boneIndex); material = null; break; case Section.Material: material = (Material)SceneManager.Current.Materials.Entries.Find(m => m.Name == section.Material); if (material == null) { material = new Material() { Name = section.Material }; SceneManager.Current.Add(material); } break; case Section.Model: model.SetMesh(new ModelMesh(dat.FindMesh((section.Model.Contains(".") ? section.Model.Substring(0, section.Model.IndexOf(".")) : section.Model))), boneIndex); if (material != null) { foreach (var modelmesh in model.Meshes) { foreach (var meshpart in modelmesh.MeshParts) { if (meshpart.Material == null) { meshpart.Material = material; } } } } break; case Section.Matrix: model.SetTransform( new Matrix4( section.Transform.M11, section.Transform.M12, section.Transform.M13, 0, section.Transform.M21, section.Transform.M22, section.Transform.M23, 0, section.Transform.M31, section.Transform.M32, section.Transform.M33, 0, section.Transform.M41, section.Transform.M42, section.Transform.M43, 1 ), boneIndex ); break; case Section.SubLevelBegin: break; case Section.SubLevelEnd: boneIndex = model.Bones[boneIndex].Parent.Index; break; } } SceneManager.Current.UpdateProgress(string.Format("Loaded {0}", fileName)); return model; }
public override Asset Import(string path) { FBX fbx = FBX.Load(path); Model model = new Model(); Dictionary <long, object> components = new Dictionary <long, object>(); Dictionary <long, Matrix4D> transforms = new Dictionary <long, Matrix4D>(); Dictionary <long, string> triangulationErrors = new Dictionary <long, string>(); string name = Path.GetFileNameWithoutExtension(path); if (fbx == null) { SceneManager.Current.RaiseError($"File \"{name}\" could not be opened. Please ensure this is a binary FBX file."); return(null); } FBXElem objects = fbx.Elements.Find(e => e.ID == "Objects"); Matrix4D worldMatrix = createTransformFor(fbx.Elements.Find(e => e.ID == "GlobalSettings").Children[1], out Quaternion.RotationOrder order); foreach (FBXElem material in objects.Children.Where(e => e.ID == "Material")) { string matName = material.Properties[1].Value.ToString(); matName = matName.Substring(0, matName.IndexOf("::")); Material m = new Material { Name = matName }; components.Add((long)material.Properties[0].Value, m); Console.WriteLine($"Added material \"{matName}\" ({material.Properties[0].Value})"); } foreach (FBXElem video in objects.Children.Where(e => e.ID == "Video")) { FBXElem content = video.Children.Find(e => e.ID == "Content"); if (content.Properties[0].Size > 4) { components.Add((long)video.Properties[0].Value, (byte[])content.Properties[0].Value); } } IEnumerable <FBXElem> textures = objects.Children.Where(e => e.ID == "Texture"); foreach (FBXElem texture in textures) { string fullFile = texture.Children.Find(e => e.ID == "FileName").Properties[0].Value.ToString(); if (fullFile.IndexOf('.') == -1) { continue; } string file = Path.GetFileName(fullFile); Texture t = new Texture(); long videoKey = (long)fbx.Elements.Find(e => e.ID == "Connections").Children.Where(c => (long)c.Properties[2].Value == (long)texture.Properties[0].Value).First().Properties[1].Value; if (components.ContainsKey(videoKey)) { using (FileStream fs = new FileStream(Path.Combine(Path.GetDirectoryName(path), file), FileMode.Create)) using (BinaryWriter bw = new BinaryWriter(fs)) { bw.Write((byte[])components[videoKey]); } } t = SceneManager.Current.Content.Load(Path.GetFileName(file)); switch (fbx.Elements.Find(e => e.ID == "Connections").Children.Where(c => (long)c.Properties[1].Value == (long)texture.Properties[0].Value).First().Properties.Last().Value.ToString()) { case "NormalMap": t.Type = Texture.TextureType.Normal; break; case "SpecularColor": t.Type = Texture.TextureType.Specular; break; } if (!components.ContainsKey((long)texture.Properties[0].Value)) { components.Add((long)texture.Properties[0].Value, t); Console.WriteLine($"Added texture \"{file}\" ({texture.Properties[0].Value})"); } } foreach (FBXElem element in objects.Children.Where(e => e.ID == "Model")) { string modelName = element.Properties[1].Value.ToString(); modelName = modelName.Substring(0, modelName.IndexOf("::")); components.Add((long)element.Properties[0].Value, new ModelMesh { Name = modelName, Tag = (long)element.Properties[0].Value }); Console.WriteLine("Added model \"{0}\" ({1})", modelName, element.Properties[0].Value); FBXElem properties = element.Children.Find(c => c.ID == "Properties70"); Matrix4D m = Matrix4D.Identity; bool bRotationActive = false; Vector3 lclTranslation = Vector3.Zero; Quaternion lclRotation = Quaternion.Identity; Quaternion preRotation = Quaternion.Identity; Quaternion postRotation = Quaternion.Identity; Vector3 rotationPivot = Vector3.Zero; Vector3 rotationOffset = Vector3.Zero; Vector3 lclScaling = Vector3.One; Vector3 scalingPivot = Vector3.Zero; Vector3 scalingOffset = Vector3.Zero; Vector3 geoPosition = Vector3.Zero; Quaternion geoRotation = Quaternion.Identity; Vector3 geoScale = Vector3.One; FBXElem property; property = properties.Children.GetProperty("RotationActive"); if (property != null) { bRotationActive = ((int)property.Properties[4].Value == 1); } property = properties.Children.GetProperty("ScalingPivot"); if (property != null) { scalingPivot = new Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("Lcl Scaling"); if (property != null) { lclScaling = new Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("ScalingOffset"); if (property != null) { scalingOffset = new Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("RotationPivot"); if (property != null) { rotationPivot = new Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("PostRotation"); if (property != null) { postRotation = MakeQuaternion( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value), order ); } property = properties.Children.GetProperty("Lcl Rotation"); if (property != null) { lclRotation = MakeQuaternion( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value), order ); } property = properties.Children.GetProperty("PreRotation"); if (property != null) { preRotation = MakeQuaternion( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value), order ); } property = properties.Children.GetProperty("RotationOffset"); if (property != null) { rotationOffset = new Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("Lcl Translation"); if (property != null) { lclTranslation = new Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("GeometricTranslation"); if (property != null) { geoPosition = new Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("GeometricRotation"); if (property != null) { geoRotation = MakeQuaternion( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value), order ); } property = properties.Children.GetProperty("GeometricScaling"); if (property != null) { geoScale = new Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } m = Matrix4D.CreateTranslation(scalingPivot).Inverted() * Matrix4D.CreateScale(lclScaling) * Matrix4D.CreateTranslation(scalingPivot) * Matrix4D.CreateTranslation(scalingOffset) * Matrix4D.CreateTranslation(rotationPivot).Inverted() * Matrix4D.CreateFromQuaternion(postRotation) * Matrix4D.CreateFromQuaternion(lclRotation) * Matrix4D.CreateFromQuaternion(preRotation) * Matrix4D.CreateTranslation(rotationPivot) * Matrix4D.CreateTranslation(rotationOffset) * Matrix4D.CreateTranslation(lclTranslation); if (m != Matrix4D.Identity) { transforms.Add((long)element.Properties[0].Value, m); } } foreach (FBXElem element in objects.Children.Where(e => e.ID == "Geometry")) { bool bUVs = true; bool bNorms = true; bool bColours = true; bool bUseIndexNorm = false; bool bNeedsTriangulating = false; string geometryName = element.Properties[1].Value.ToString(); geometryName = geometryName.Substring(0, geometryName.IndexOf("::")); List <Vector3> verts = new List <Vector3>(); List <Vector3> norms = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <Colour> colours = new List <Colour>(); double[] vertParts = (double[])element.Children.Find(e => e.ID == "Vertices").Properties[0].Value; for (int i = 0; i < vertParts.Length; i += 3) { verts.Add(new Vector3((float)vertParts[i + 0], (float)vertParts[i + 1], (float)vertParts[i + 2])); } SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->Vertices"); FBXElem normElem = element.Children.Find(e => e.ID == "LayerElementNormal"); if (normElem != null) { double[] normParts = (double[])normElem.Children.Find(e => e.ID == "Normals").Properties[0].Value; for (int i = 0; i < normParts.Length; i += 3) { norms.Add(new Vector3((float)normParts[i + 0], (float)normParts[i + 1], (float)normParts[i + 2])); } bUseIndexNorm = (normElem.Children.Find(e => e.ID == "MappingInformationType").Properties[0].Value.ToString() == "ByVertice"); SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->Normals"); } else { bNorms = false; } FBXElem colourElem = element.Children.Find(e => e.ID == "LayerElementColor"); if (colourElem != null) { double[] colourParts = (double[])colourElem.Children.Find(e => e.ID == "Colors").Properties[0].Value; FBXElem colourReferenceType = colourElem.Children.Find(e => e.ID == "ReferenceInformationType"); switch (colourReferenceType.Properties[0].Value.ToString()) { case "IndexToDirect": int[] colourIndicies = (int[])colourElem.Children.Find(e => e.ID == "ColorIndex").Properties[0].Value; for (int i = 0; i < colourIndicies.Length; i++) { int offset = colourIndicies[i] * 4; colours.Add(new Colour( (float)colourParts[offset + 0], (float)colourParts[offset + 1], (float)colourParts[offset + 2], (float)colourParts[offset + 3]) ); } break; case "Direct": bColours = false; break; default: throw new NotImplementedException($"Unsupported Colour Reference Type: {colourReferenceType.Properties[0].Value}"); } SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->Colours"); } else { bColours = false; } FBXElem uvElem = element.Children.Find(e => e.ID == "LayerElementUV"); if (uvElem != null) { double[] uvParts = (double[])uvElem.Children.Find(e => e.ID == "UV").Properties[0].Value; FBXElem uvReferenceType = uvElem.Children.Find(e => e.ID == "ReferenceInformationType"); if (uvReferenceType.Properties[0].Value.ToString() == "IndexToDirect") { List <Vector2> luvs = new List <Vector2>(); for (int i = 0; i < uvParts.Length; i += 2) { luvs.Add(new Vector2((float)uvParts[i + 0], 1 - (float)uvParts[i + 1])); } int[] uvindicies = (int[])uvElem.Children.Find(e => e.ID == "UVIndex").Properties[0].Value; for (int i = 0; i < uvindicies.Length; i++) { if (uvindicies[i] == -1) { uvs.Add(Vector2.Zero); } else { uvs.Add(luvs[uvindicies[i]]); } } } else { for (int i = 0; i < uvParts.Length; i += 2) { uvs.Add(new Vector2((float)uvParts[i + 0], (float)uvParts[i + 1])); } } SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->UVs"); } else { bUVs = false; } int[] indicies = (int[])element.Children.Find(e => e.ID == "PolygonVertexIndex").Properties[0].Value; List <FBXFace> faces = new List <FBXFace>(); FBXFace face = new FBXFace(); int j = 0; for (int i = 0; i < indicies.Length; i++) { bool bFace = false; int index = indicies[i]; if (index < 0) { bFace = true; index = (index * -1) - 1; } j++; face.AddVertex(verts[index], bNorms ? norms[bUseIndexNorm ? index : i] : Vector3.Zero, bUVs ? uvs[i] : Vector2.Zero, bColours ? colours[i] : Colour.White); if (bFace) { if (j > 3) { triangulationErrors.Add((long)element.Properties[0].Value, geometryName); bNeedsTriangulating = true; break; } faces.Add(face); face = new FBXFace(); j = 0; } } List <ModelMeshPart> parts = new List <ModelMeshPart>(); if (!bNeedsTriangulating) { SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->Faces"); FBXElem elemMaterial = element.Children.Find(e => e.ID == "LayerElementMaterial"); if (elemMaterial != null) { int[] faceMaterials = (int[])elemMaterial.Children.Find(e => e.ID == "Materials").Properties[0].Value; for (int i = 0; i < faceMaterials.Length; i++) { faces[i].MaterialID = faceMaterials[i]; } SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->Materials"); } IEnumerable <IGrouping <int, FBXFace> > materialGroups = faces.GroupBy(f => f.MaterialID); int processedFaceCount = 0, processedGroupCount = 0; foreach (IGrouping <int, FBXFace> materialGroup in materialGroups) { IEnumerable <IGrouping <int, FBXFace> > smoothingGroups = materialGroup.GroupBy(f => f.SmoothingGroup); foreach (IGrouping <int, FBXFace> smoothingGroup in smoothingGroups) { ModelMeshPart meshpart = new ModelMeshPart { PrimitiveType = Flummery.Core.PrimitiveType.Triangles }; processedFaceCount = 0; foreach (FBXFace groupface in smoothingGroup) { foreach (Vertex vert in groupface.Vertices) { meshpart.AddVertex(vert.Position, vert.Normal, vert.UV, vert.Colour); } processedFaceCount++; if (processedFaceCount % 250 == 0) { SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->MeshPart[{processedGroupCount}]->Face[{processedFaceCount}]"); } } meshpart.Key = materialGroup.Key; parts.Add(meshpart); SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->MeshPart"); processedGroupCount++; } } } components.Add((long)element.Properties[0].Value, parts); SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}"); } Dictionary <long, BoneType> nodeAttributes = new Dictionary <long, BoneType>(); Dictionary <long, object> nodeAttachments = new Dictionary <long, object>(); foreach (FBXElem nodeAttribute in objects.Children.Where(e => e.ID == "NodeAttribute")) { FBXElem typeFlags = nodeAttribute.Children.Find(e => e.ID == "TypeFlags"); if (typeFlags != null) { switch (typeFlags.Properties[0].Value.ToString().ToLower()) { case "light": LIGHT light = new LIGHT(); FBXElem lightType = nodeAttribute.Children.Find(c => c.ID == "Properties70").Children.GetProperty("LightType"); light.Type = (LIGHT.LightType)(lightType == null ? 0 : lightType.Properties[4].Value); nodeAttributes.Add((long)nodeAttribute.Properties[0].Value, BoneType.Light); nodeAttachments.Add((long)nodeAttribute.Properties[0].Value, light); break; default: // null node break; } } } string[] connectionOrder = new string[] { "System.Collections.Generic.List`1[Flummery.Core.ModelMeshPart]", "Flummery.Core.Texture", "Flummery.Core.Material", "Flummery.Core.ModelMesh" }; FBXElem connections = fbx.Elements.Find(e => e.ID == "Connections"); HashSet <long> loaded = new HashSet <long>(); foreach (string connectionType in connectionOrder) { IEnumerable <FBXElem> connectionsOfType = connections.Children.Where(c => components.ContainsKey((long)c.Properties[1].Value) && components[(long)c.Properties[1].Value].GetType().ToString() == connectionType); foreach (FBXElem connection in connectionsOfType) { long keyA = (long)connection.Properties[1].Value; long keyB = (long)connection.Properties[2].Value; Console.WriteLine("{0} is connected to {1} :: {2}", keyA, keyB, connectionType); switch (connectionType) { case "Flummery.Core.ModelMesh": int boneID; if (keyB == 0) { boneID = model.AddMesh((ModelMesh)components[keyA]); model.SetName(((ModelMesh)components[keyA]).Name, boneID); if (transforms.ContainsKey(keyA)) { model.SetTransform(transforms[keyA], boneID); } FBXElem attribute = connections.Children.FirstOrDefault(c => nodeAttributes.ContainsKey((long)c.Properties[1].Value) && (long)c.Properties[2].Value == keyA); if (attribute != null) { keyA = (long)attribute.Properties[1].Value; if (nodeAttributes.ContainsKey(keyA)) { model.Bones[boneID].Type = nodeAttributes[keyA]; } if (nodeAttachments.ContainsKey(keyA)) { model.Bones[boneID].Attachment = nodeAttachments[keyA]; } } } else { ModelMesh parent = model.FindMesh(keyB); if (parent != null) { boneID = model.AddMesh((ModelMesh)components[keyA], parent.Parent.Index); model.SetName(((ModelMesh)components[keyA]).Name, boneID); if (transforms.ContainsKey(keyA)) { model.SetTransform(transforms[keyA], boneID); } } else { if (!components.ContainsKey(keyB)) { Console.WriteLine("Components doesn't contain {0}", keyB); } else { Console.WriteLine("Couldn't find {0}", ((ModelMesh)components[keyB]).Name); } } } break; case "Flummery.Core.Texture": if (components.ContainsKey(keyB) && components[keyB].GetType().ToString() == "Flummery.Core.Material") { if (loaded.Add(keyA)) { ((Material)components[keyB]).Texture = (Texture)components[keyA]; //SceneManager.Current.Add((Material)components[keyB]); } } else { Console.WriteLine("{0} is of unknown type {1}", keyA, components[keyA].GetType().ToString()); Console.WriteLine("{0} is of unknown type {1}", keyB, components[keyB].GetType().ToString()); } break; case "System.Collections.Generic.List`1[Flummery.Core.ModelMeshPart]": if (components.ContainsKey(keyB) && components[keyB].GetType().ToString() == "Flummery.Core.ModelMesh") { if (triangulationErrors.ContainsKey(keyA)) { triangulationErrors[keyA] += " (geometry of " + ((ModelMesh)components[keyB]).Name + ")"; } foreach (ModelMeshPart part in (List <ModelMeshPart>)components[keyA]) { ((ModelMesh)components[keyB]).AddModelMeshPart(part); } } break; case "Flummery.Core.Material": if (components.ContainsKey(keyB) && components[keyB].GetType().ToString() == "Flummery.Core.ModelMesh") { List <FBXElem> materialLookup = connections.Children.Where(c => (long)c.Properties[2].Value == keyB).ToList(); for (int i = materialLookup.Count - 1; i > -1; i--) { if (!connectionsOfType.Any(c => (long)c.Properties[1].Value == (long)materialLookup[i].Properties[1].Value)) { materialLookup.RemoveAt(i); } } foreach (ModelMeshPart part in ((ModelMesh)components[keyB]).MeshParts) { if ((long)materialLookup[(int)part.Key].Properties[1].Value == keyA) { part.Material = (Material)components[keyA]; SceneManager.Current.Add(part.Material); } } } break; default: Console.WriteLine("{0} is of unknown type {1}", keyA, components[keyA].GetType().ToString()); if (components.ContainsKey(keyB)) { Console.WriteLine("{0} is of unknown type {1}", keyB, components[keyB].GetType().ToString()); } Console.WriteLine("==="); break; } } } if (triangulationErrors.Count > 0) { SceneManager.Current.UpdateProgress($"Failed to load {name}"); string error = $"File \"{name}\" has part{(triangulationErrors.Count > 1 ? "s" : "")} that need been triangulating! Please triangulate the following:"; foreach (KeyValuePair <long, string> kvp in triangulationErrors) { error += $"\r\n{kvp.Value}"; } SceneManager.Current.RaiseError(error); return(null); } else { SceneManager.Current.UpdateProgress($"Loaded {name}"); model.Santise(); //if (worldMatrix != Matrix4D.Identity) { ModelManipulator.Freeze(model, worldMatrix); } ModelManipulator.FlipAxis(model, Axis.Z, true); return(model); } }
public override Asset Import(string path) { FBX fbx = FBX.Load(path); Model model = new Model(); Dictionary <long, object> components = new Dictionary <long, object>(); Dictionary <long, Matrix4> transforms = new Dictionary <long, Matrix4>(); Dictionary <long, string> triangulationErrors = new Dictionary <long, string>(); string name = Path.GetFileNameWithoutExtension(path); if (fbx == null) { SceneManager.Current.RaiseError(string.Format("File \"{0}\" could not be opened. Please ensure this is a binary FBX file.", name)); return(null); } var objects = fbx.Elements.Find(e => e.ID == "Objects"); RotationOrder order; var worldMatrix = createTransformFor(fbx.Elements.Find(e => e.ID == "GlobalSettings").Children[1], out order); foreach (var material in objects.Children.Where(e => e.ID == "Material")) { string matName = material.Properties[1].Value.ToString(); matName = matName.Substring(0, matName.IndexOf("::")); var m = new Material { Name = matName }; components.Add((long)material.Properties[0].Value, m); Console.WriteLine("Added material \"{0}\" ({1})", matName, material.Properties[0].Value); } var textures = objects.Children.Where(e => e.ID == "Texture"); foreach (var texture in textures) { Texture t = null; string fullFile = texture.Children.Find(e => e.ID == "FileName").Properties[0].Value.ToString(); if (fullFile.IndexOf('.') == -1) { continue; } string file = Path.GetFileName(fullFile); switch (Path.GetExtension(file)) { case ".bmp": t = SceneManager.Current.Content.Load <Texture, BMPImporter>(Path.GetFileNameWithoutExtension(file)); break; case ".png": t = SceneManager.Current.Content.Load <Texture, PNGImporter>(Path.GetFileNameWithoutExtension(file)); break; case ".tif": t = SceneManager.Current.Content.Load <Texture, TIFImporter>(Path.GetFileNameWithoutExtension(file)); break; case ".tga": t = SceneManager.Current.Content.Load <Texture, TGAImporter>(Path.GetFileNameWithoutExtension(file)); break; default: t = new Texture(); break; } if (!components.ContainsKey((long)texture.Properties[0].Value)) { components.Add((long)texture.Properties[0].Value, t); Console.WriteLine("Added texture \"{0}\" ({1})", file, texture.Properties[0].Value); } } foreach (var element in objects.Children.Where(e => e.ID == "Model")) { string modelName = element.Properties[1].Value.ToString(); modelName = modelName.Substring(0, modelName.IndexOf("::")); components.Add((long)element.Properties[0].Value, new ModelMesh { Name = modelName, Tag = (long)element.Properties[0].Value }); Console.WriteLine("Added model \"{0}\" ({1})", modelName, element.Properties[0].Value); var properties = element.Children.Find(c => c.ID == "Properties70"); var m = Matrix4.Identity; bool bRotationActive = false; var lclTranslation = OpenTK.Vector3.Zero; var lclRotation = Quaternion.Identity; var preRotation = Quaternion.Identity; var postRotation = Quaternion.Identity; var rotationPivot = OpenTK.Vector3.Zero; var rotationOffset = OpenTK.Vector3.Zero; var lclScaling = OpenTK.Vector3.One; var scalingPivot = OpenTK.Vector3.Zero; var scalingOffset = OpenTK.Vector3.Zero; var geoPosition = OpenTK.Vector3.Zero; var geoRotation = Quaternion.Identity; var geoScale = OpenTK.Vector3.One; FBXElem property; property = properties.Children.GetProperty("RotationActive"); if (property != null) { bRotationActive = ((int)property.Properties[4].Value == 1); } property = properties.Children.GetProperty("ScalingPivot"); if (property != null) { scalingPivot = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("Lcl Scaling"); if (property != null) { lclScaling = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("ScalingOffset"); if (property != null) { scalingOffset = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("RotationPivot"); if (property != null) { rotationPivot = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("PostRotation"); if (property != null) { postRotation = MakeQuaternion( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value), order ); } property = properties.Children.GetProperty("Lcl Rotation"); if (property != null) { lclRotation = MakeQuaternion( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value), order ); } property = properties.Children.GetProperty("PreRotation"); if (property != null) { preRotation = MakeQuaternion( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value), order ); } property = properties.Children.GetProperty("RotationOffset"); if (property != null) { rotationOffset = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("Lcl Translation"); if (property != null) { lclTranslation = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("GeometricTranslation"); if (property != null) { geoPosition = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("GeometricRotation"); if (property != null) { geoRotation = MakeQuaternion( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value), order ); } property = properties.Children.GetProperty("GeometricScaling"); if (property != null) { geoScale = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } m = Matrix4.CreateTranslation(scalingPivot).Inverted() * Matrix4.CreateScale(lclScaling) * Matrix4.CreateTranslation(scalingPivot) * Matrix4.CreateTranslation(scalingOffset) * Matrix4.CreateTranslation(rotationPivot).Inverted() * Matrix4.CreateFromQuaternion(postRotation) * Matrix4.CreateFromQuaternion(lclRotation) * Matrix4.CreateFromQuaternion(preRotation) * Matrix4.CreateTranslation(rotationPivot) * Matrix4.CreateTranslation(rotationOffset) * Matrix4.CreateTranslation(lclTranslation); if (m != Matrix4.Identity) { transforms.Add((long)element.Properties[0].Value, m); } } foreach (var element in objects.Children.Where(e => e.ID == "Geometry")) { bool bUVs = true; bool bNorms = true; bool bColours = true; bool bUseIndexNorm = false; bool bNeedsTriangulating = false; string geometryName = element.Properties[1].Value.ToString(); geometryName = geometryName.Substring(0, geometryName.IndexOf("::")); var verts = new List <OpenTK.Vector3>(); var norms = new List <OpenTK.Vector3>(); var uvs = new List <OpenTK.Vector2>(); var colours = new List <OpenTK.Graphics.Color4>(); var vertParts = (double[])element.Children.Find(e => e.ID == "Vertices").Properties[0].Value; for (int i = 0; i < vertParts.Length; i += 3) { verts.Add(new OpenTK.Vector3((float)vertParts[i + 0], (float)vertParts[i + 1], (float)vertParts[i + 2])); } SceneManager.Current.UpdateProgress(string.Format("Processed {0}->Vertices", element.Properties[1].Value)); var normElem = element.Children.Find(e => e.ID == "LayerElementNormal"); if (normElem != null) { var normParts = (double[])normElem.Children.Find(e => e.ID == "Normals").Properties[0].Value; for (int i = 0; i < normParts.Length; i += 3) { norms.Add(new OpenTK.Vector3((float)normParts[i + 0], (float)normParts[i + 1], (float)normParts[i + 2])); } bUseIndexNorm = (normElem.Children.Find(e => e.ID == "MappingInformationType").Properties[0].Value.ToString() == "ByVertice"); SceneManager.Current.UpdateProgress(string.Format("Processed {0}->Normals", element.Properties[1].Value)); } else { bNorms = false; } var colourElem = element.Children.Find(e => e.ID == "LayerElementColor"); if (colourElem != null) { var colourParts = (double[])colourElem.Children.Find(e => e.ID == "Colors").Properties[0].Value; var colourReferenceType = colourElem.Children.Find(e => e.ID == "ReferenceInformationType"); switch (colourReferenceType.Properties[0].Value.ToString()) { case "IndexToDirect": var colourIndicies = (int[])colourElem.Children.Find(e => e.ID == "ColorIndex").Properties[0].Value; for (int i = 0; i < colourIndicies.Length; i++) { int offset = colourIndicies[i] * 4; colours.Add(new OpenTK.Graphics.Color4((float)colourParts[offset + 0], (float)colourParts[offset + 1], (float)colourParts[offset + 2], (float)colourParts[offset + 3])); } break; case "Direct": bColours = false; break; default: throw new NotImplementedException("Unsupported Colour Reference Type: " + colourReferenceType.Properties[0].Value.ToString()); } SceneManager.Current.UpdateProgress(string.Format("Processed {0}->Colours", element.Properties[1].Value)); } else { bColours = false; } var uvElem = element.Children.Find(e => e.ID == "LayerElementUV"); if (uvElem != null) { var uvParts = (double[])uvElem.Children.Find(e => e.ID == "UV").Properties[0].Value; var uvReferenceType = uvElem.Children.Find(e => e.ID == "ReferenceInformationType"); if (uvReferenceType.Properties[0].Value.ToString() == "IndexToDirect") { var luvs = new List <OpenTK.Vector2>(); for (int i = 0; i < uvParts.Length; i += 2) { luvs.Add(new OpenTK.Vector2((float)uvParts[i + 0], 1 - (float)uvParts[i + 1])); } var uvindicies = (int[])uvElem.Children.Find(e => e.ID == "UVIndex").Properties[0].Value; for (int i = 0; i < uvindicies.Length; i++) { if (uvindicies[i] == -1) { uvs.Add(OpenTK.Vector2.Zero); } else { uvs.Add(luvs[uvindicies[i]]); } } } else { for (int i = 0; i < uvParts.Length; i += 2) { uvs.Add(new OpenTK.Vector2((float)uvParts[i + 0], (float)uvParts[i + 1])); } } SceneManager.Current.UpdateProgress(string.Format("Processed {0}->UVs", element.Properties[1].Value)); } else { bUVs = false; } var indicies = (int[])element.Children.Find(e => e.ID == "PolygonVertexIndex").Properties[0].Value; var faces = new List <FBXFace>(); var face = new FBXFace(); var j = 0; for (int i = 0; i < indicies.Length; i++) { bool bFace = false; int index = indicies[i]; if (index < 0) { bFace = true; index = (index * -1) - 1; } j++; face.AddVertex(verts[index], (bNorms ? norms[(bUseIndexNorm ? index : i)] : OpenTK.Vector3.Zero), (bUVs ? uvs[i] : OpenTK.Vector2.Zero), (bColours ? colours[i] : OpenTK.Graphics.Color4.White)); if (bFace) { if (j > 3) { triangulationErrors.Add((long)element.Properties[0].Value, geometryName); bNeedsTriangulating = true; break; } faces.Add(face); face = new FBXFace(); j = 0; } } var parts = new List <ModelMeshPart>(); if (!bNeedsTriangulating) { SceneManager.Current.UpdateProgress(string.Format("Processed {0}->Faces", element.Properties[1].Value)); var elemMaterial = element.Children.Find(e => e.ID == "LayerElementMaterial"); if (elemMaterial != null) { var faceMaterials = (int[])elemMaterial.Children.Find(e => e.ID == "Materials").Properties[0].Value; for (int i = 0; i < faceMaterials.Length; i++) { faces[i].MaterialID = faceMaterials[i]; } SceneManager.Current.UpdateProgress(string.Format("Processed {0}->Materials", element.Properties[1].Value)); } var materialGroups = faces.GroupBy(f => f.MaterialID); int processedFaceCount = 0, processedGroupCount = 0; foreach (var materialGroup in materialGroups) { var smoothingGroups = materialGroup.GroupBy(f => f.SmoothingGroup); foreach (var smoothingGroup in smoothingGroups) { var meshpart = new ModelMeshPart { PrimitiveType = OpenTK.Graphics.OpenGL.PrimitiveType.Triangles }; processedFaceCount = 0; foreach (var groupface in smoothingGroup) { foreach (var vert in groupface.Vertices) { meshpart.AddVertex(vert.Position, vert.Normal, vert.UV, vert.Colour); } processedFaceCount++; if (processedFaceCount % 250 == 0) { SceneManager.Current.UpdateProgress(string.Format("Processed {0}->MeshPart[{1}]->Face[{2}]", element.Properties[1].Value, processedGroupCount, processedFaceCount)); } } meshpart.Key = materialGroup.Key; parts.Add(meshpart); SceneManager.Current.UpdateProgress(string.Format("Processed {0}->MeshPart", element.Properties[1].Value)); processedGroupCount++; } } } components.Add((long)element.Properties[0].Value, parts); SceneManager.Current.UpdateProgress(string.Format("Processed {0}", element.Properties[1].Value)); } string[] connectionOrder = new string[] { "System.Collections.Generic.List`1[Flummery.ModelMeshPart]", "Flummery.Texture", "Flummery.Material", "Flummery.ModelMesh" }; var connections = fbx.Elements.Find(e => e.ID == "Connections"); HashSet <long> loaded = new HashSet <long>(); foreach (var connectionType in connectionOrder) { var connectionsOfType = connections.Children.Where(c => components.ContainsKey((long)c.Properties[1].Value) && components[(long)c.Properties[1].Value].GetType().ToString() == connectionType); foreach (var connection in connectionsOfType) { long keyA = (long)connection.Properties[1].Value; long keyB = (long)connection.Properties[2].Value; Console.WriteLine("{0} is connected to {1} :: {2}", keyA, keyB, connectionType); switch (connectionType) { case "Flummery.ModelMesh": int boneID; if (keyB == 0) { boneID = model.AddMesh((ModelMesh)components[keyA]); model.SetName(((ModelMesh)components[keyA]).Name, boneID); if (transforms.ContainsKey(keyA)) { model.SetTransform(transforms[keyA], boneID); } } else { var parent = model.FindMesh(keyB); if (parent != null) { boneID = model.AddMesh((ModelMesh)components[keyA], parent.Parent.Index); model.SetName(((ModelMesh)components[keyA]).Name, boneID); if (transforms.ContainsKey(keyA)) { model.SetTransform(transforms[keyA], boneID); } } else { if (!components.ContainsKey(keyB)) { Console.WriteLine("Components doesn't contain {0}", keyB); } else { Console.WriteLine("Couldn't find {0}", ((ModelMesh)components[keyB]).Name); } } } break; case "Flummery.Texture": if (components.ContainsKey(keyB) && components[keyB].GetType().ToString() == "Flummery.Material") { if (loaded.Add(keyB)) { ((Material)components[keyB]).Texture = (Texture)components[keyA]; SceneManager.Current.Add((Material)components[keyB]); } } else { Console.WriteLine("{0} is of unknown type {1}", keyA, components[keyA].GetType().ToString()); Console.WriteLine("{0} is of unknown type {1}", keyB, components[keyB].GetType().ToString()); } break; case "System.Collections.Generic.List`1[Flummery.ModelMeshPart]": if (components.ContainsKey(keyB) && components[keyB].GetType().ToString() == "Flummery.ModelMesh") { if (triangulationErrors.ContainsKey(keyA)) { triangulationErrors[keyA] += " (geometry of " + ((ModelMesh)components[keyB]).Name + ")"; } foreach (var part in (List <ModelMeshPart>)components[keyA]) { ((ModelMesh)components[keyB]).AddModelMeshPart(part); } } break; case "Flummery.Material": if (components.ContainsKey(keyB) && components[keyB].GetType().ToString() == "Flummery.ModelMesh") { var materialLookup = connections.Children.Where(c => (long)c.Properties[2].Value == keyB).ToList(); for (int i = materialLookup.Count - 1; i > -1; i--) { if (!connectionsOfType.Any(c => (long)c.Properties[1].Value == (long)materialLookup[i].Properties[1].Value)) { materialLookup.RemoveAt(i); } } foreach (var part in ((ModelMesh)components[keyB]).MeshParts) { if ((long)materialLookup[(int)part.Key].Properties[1].Value == keyA) { part.Material = (Material)components[keyA]; //SceneManager.Current.Add(part.Material); } } } break; default: Console.WriteLine("{0} is of unknown type {1}", keyA, components[keyA].GetType().ToString()); if (components.ContainsKey(keyB)) { Console.WriteLine("{0} is of unknown type {1}", keyB, components[keyB].GetType().ToString()); } Console.WriteLine("==="); break; } } } if (triangulationErrors.Count > 0) { SceneManager.Current.UpdateProgress(string.Format("Failed to load {0}", name)); string error = string.Format("File \"{0}\" has part{1} that need been triangulating! Please triangulate the following:", name, (triangulationErrors.Count > 1 ? "s" : "")); foreach (var kvp in triangulationErrors) { error += "\r\n" + kvp.Value; } SceneManager.Current.RaiseError(error); return(null); } else { SceneManager.Current.UpdateProgress(string.Format("Loaded {0}", name)); model.Santise(); if (worldMatrix != Matrix4.Identity) { ModelManipulator.Freeze(model, worldMatrix); } ModelManipulator.FlipAxis(model.Root.Mesh, Axis.X, true); return(model); } }
public override Asset Import(string path) { MSHS mshs = MSHS.Load(path); Model model = new Model(); string name = Path.GetFileNameWithoutExtension(path); int meshnum = 0; foreach (TDRMesh tdrmesh in mshs.Meshes) { ModelMesh mesh = new ModelMesh { Name = $"{name}{meshnum++:0000}" }; ModelMeshPart meshpart = new ModelMeshPart { PrimitiveType = PrimitiveType.Triangles }; SceneManager.Current.UpdateProgress($"Processing {mesh.Name}"); TDRVertex v1 = null, v2 = null, v3 = null; switch (tdrmesh.Mode) { case TDRMesh.MSHMode.NGon: for (int i = 0; i < tdrmesh.Faces.Count; i++) { TDRFace face = tdrmesh.Faces[i]; for (int j = 2; j < face.VertexCount; j++) { int flip = j % 2; v1 = face.Vertices[j - (2 + flip)]; v2 = face.Vertices[j - 1]; v3 = face.Vertices[j - 0]; meshpart.AddFace( new Vector3[] { v1.Position, v2.Position, v3.Position }, new Vector3[] { v1.Normal, v2.Normal, v3.Normal }, new Vector2[] { v1.UV, v2.UV, v3.UV } ); } } break; case TDRMesh.MSHMode.TriIndexedPosition: for (int i = 0; i < tdrmesh.Faces.Count; i++) { TDRFace face = tdrmesh.Faces[i]; v1 = face.Vertices[0]; v2 = face.Vertices[1]; v3 = face.Vertices[2]; meshpart.AddFace( new Vector3[] { tdrmesh.Positions[v1.PositionIndex], tdrmesh.Positions[v2.PositionIndex], tdrmesh.Positions[v3.PositionIndex] }, new Vector3[] { v1.Normal, v2.Normal, v3.Normal }, new Vector2[] { v1.UV, v2.UV, v3.UV } ); } break; case TDRMesh.MSHMode.Tri: for (int i = 0; i < tdrmesh.Faces.Count; i++) { TDRFace face = tdrmesh.Faces[i]; v1 = tdrmesh.Vertices[face.V1]; v2 = tdrmesh.Vertices[face.V2]; v3 = tdrmesh.Vertices[face.V3]; meshpart.AddFace( new Vector3[] { v1.Position, v2.Position, v3.Position }, new Vector3[] { v1.Normal, v2.Normal, v3.Normal }, new Vector2[] { v1.UV, v2.UV, v3.UV } ); } break; } mesh.AddModelMeshPart(meshpart); model.SetName(mesh.Name, model.AddMesh(mesh)); } return(model); }
public override Asset Import(string path) { MDL mdl = MDL.Load(path); Model model = new Model(); ModelMesh mesh = new ModelMesh(); // 2015-07-12 : Commenting out SupportingDocuments["Source"] to see if anything breaks // model.SupportingDocuments["Source"] = mdl; bool bUsePrepData = true; for (int i = 0; i < mdl.Meshes.Count; i++) { Dictionary<int, int> newIndex = new Dictionary<int, int>(); ModelMeshPart meshpart = new ModelMeshPart(); var mdlmesh = mdl.GetMesh(i); meshpart.Material = SceneManager.Current.Content.Load<Material, MaterialImporter>(mdlmesh.Name, Path.GetDirectoryName(path), true); if (bUsePrepData) { foreach (var f in mdl.Faces.Where(f => f.MaterialID == i)) { for (int j = 0; j < 3; j++) { if (!newIndex.ContainsKey(f.Verts[j])) { var v = mdl.Vertices[f.Verts[j]]; int index = meshpart.AddVertex(new Vector3(v.Position.X, v.Position.Y, v.Position.Z), new Vector3(v.Normal.X, v.Normal.Y, v.Normal.Z), new Vector2(v.UV.X, v.UV.Y), new Vector2(v.UV2.X, v.UV2.Y), v.Colour, false); newIndex.Add(f.Verts[j], index); } } meshpart.AddFace( newIndex[f.Verts[0]], newIndex[f.Verts[1]], newIndex[f.Verts[2]] ); } } else { int[] verts = new int[3]; for (int j = 0; j < mdlmesh.StripList.Count - 2; j++) { if (mdlmesh.StripList[j + 2].Degenerate) { continue; } verts[0] = mdlmesh.StripList[j + 0].Index; if (j % 2 == 0) { verts[1] = mdlmesh.StripList[j + 1].Index; verts[2] = mdlmesh.StripList[j + 2].Index; } else { verts[1] = mdlmesh.StripList[j + 2].Index; verts[2] = mdlmesh.StripList[j + 1].Index; } for (int k = 0; k < 3; k++) { if (!newIndex.ContainsKey(verts[k])) { var v = mdl.Vertices[verts[k]]; int index = meshpart.AddVertex(new Vector3(v.Position.X, v.Position.Y, v.Position.Z), new Vector3(v.Normal.X, v.Normal.Y, v.Normal.Z), new Vector2(v.UV.X, v.UV.Y), new Vector2(v.UV2.X, v.UV2.Y), v.Colour, false); newIndex.Add(verts[k], index); } } meshpart.AddFace( newIndex[verts[0]], newIndex[verts[1]], newIndex[verts[2]] ); } // Process patch list for (int j = 0; j < mdlmesh.TriList.Count; j += 3) { verts[0] = mdlmesh.TriList[j + 0].Index; verts[1] = mdlmesh.TriList[j + 1].Index; verts[2] = mdlmesh.TriList[j + 2].Index; for (int k = 0; k < 3; k++) { if (!newIndex.ContainsKey(verts[k])) { var v = mdl.Vertices[verts[k]]; int index = meshpart.AddVertex(new Vector3(v.Position.X, v.Position.Y, v.Position.Z), new Vector3(v.Normal.X, v.Normal.Y, v.Normal.Z), new Vector2(v.UV.X, v.UV.Y), new Vector2(v.UV2.X, v.UV2.Y), v.Colour, false); newIndex.Add(verts[k], index); } } meshpart.AddFace( newIndex[verts[0]], newIndex[verts[1]], newIndex[verts[2]] ); } } mesh.AddModelMeshPart(meshpart); Console.WriteLine(meshpart.VertexCount / 3); } mesh.Name = mdl.Name; model.SetName(mdl.Name, model.AddMesh(mesh)); return model; }
static void ProcessNode(TDRNode node, Model model, Model mshses, HIE hie, int ParentBoneIndex = 0) { int boneIndex = ParentBoneIndex; if (exit) { return; } switch (node.Type) { case TDRNode.NodeType.Matrix: boneIndex = model.AddMesh(null, boneIndex); model.SetName(node.Name, boneIndex); model.SetTransform( new Matrix4( node.Transform.M11, node.Transform.M12, node.Transform.M13, 0, node.Transform.M21, node.Transform.M22, node.Transform.M23, 0, node.Transform.M31, node.Transform.M32, node.Transform.M33, 0, node.Transform.M41, node.Transform.M42, node.Transform.M43, 1 ), boneIndex); break; case TDRNode.NodeType.Mesh: int index = node.Index; mshses.Meshes[index].MeshParts[0].Material = material; if (model.Bones[ParentBoneIndex].Mesh == null) { model.SetMesh(mshses.Meshes[index], boneIndex); //exit = true; //Console.WriteLine("Adding mesh #{0} \"{1}\" to bone #{2} \"{3}\"", index, mshses.Meshes[index].Name, boneIndex, model.Bones[boneIndex].Name); } else { boneIndex = model.AddMesh(mshses.Meshes[index], ParentBoneIndex); model.SetName(mshses.Meshes[index].Name, boneIndex); //model.SetName(mshses.Meshes[index].Name, model.AddMesh(mshses.Meshes[index], ParentBoneIndex)); //Console.WriteLine("Adding mesh #{0} \"{1}\" to brand new bone", index, mshses.Meshes[index].Name); } break; case TDRNode.NodeType.Texture: if (node.Index > -1) { material = SceneManager.Current.Content.Load <Material, TXImporter>(hie.Textures[node.Index]); } else { material = null; } break; } foreach (var child in node.Children) { ProcessNode(child, model, mshses, hie, boneIndex); } }
public override Asset Import(string path) { DAT dat = DAT.Load(path); SceneManager.Current.Content.LoadMany <MaterialList, MaterialImporter>(Path.GetFileName(path).Replace(".dat", ".mat", StringComparison.OrdinalIgnoreCase), Path.GetDirectoryName(path) + "\\", true); Model model = new Model(); foreach (var datmesh in dat.DatMeshes) { Console.WriteLine(datmesh.Name); datmesh.Mesh.GenerateNormals(); ModelMesh mesh = new ModelMesh(); mesh.Name = (datmesh.Name.Contains(".") ? datmesh.Name.Substring(0, datmesh.Name.IndexOf(".")) : datmesh.Name); SceneManager.Current.UpdateProgress(string.Format("Processing {0}", mesh.Name)); for (int i = -1; i < datmesh.Mesh.Materials.Count; i++) { var meshpart = new ModelMeshPart(); if (i > -1) { var material = SceneManager.Current.Materials.Entries.Find(m => m.Name == datmesh.Mesh.Materials[i]); if (material == null) { material = new Material { Name = datmesh.Mesh.Materials[i] }; SceneManager.Current.Add(material); } meshpart.Material = (Material)material; } foreach (var face in datmesh.Mesh.Faces.Where(f => f.MaterialID == i)) { int smoothingGroup = (face.SmoothingGroup << 8); meshpart.AddFace( new OpenTK.Vector3[] { new OpenTK.Vector3(datmesh.Mesh.Verts[face.V1].X, datmesh.Mesh.Verts[face.V1].Y, datmesh.Mesh.Verts[face.V1].Z), new OpenTK.Vector3(datmesh.Mesh.Verts[face.V2].X, datmesh.Mesh.Verts[face.V2].Y, datmesh.Mesh.Verts[face.V2].Z), new OpenTK.Vector3(datmesh.Mesh.Verts[face.V3].X, datmesh.Mesh.Verts[face.V3].Y, datmesh.Mesh.Verts[face.V3].Z) }, new OpenTK.Vector3[] { new OpenTK.Vector3(datmesh.Mesh.Normals[smoothingGroup + face.V1].X, datmesh.Mesh.Normals[smoothingGroup + face.V1].Y, datmesh.Mesh.Normals[smoothingGroup + face.V1].Z), new OpenTK.Vector3(datmesh.Mesh.Normals[smoothingGroup + face.V2].X, datmesh.Mesh.Normals[smoothingGroup + face.V2].Y, datmesh.Mesh.Normals[smoothingGroup + face.V2].Z), new OpenTK.Vector3(datmesh.Mesh.Normals[smoothingGroup + face.V3].X, datmesh.Mesh.Normals[smoothingGroup + face.V3].Y, datmesh.Mesh.Normals[smoothingGroup + face.V3].Z) }, new OpenTK.Vector2[] { (datmesh.Mesh.HasUVs ? new OpenTK.Vector2(datmesh.Mesh.UVs[face.UV1].X, datmesh.Mesh.UVs[face.UV1].Y) : OpenTK.Vector2.Zero), (datmesh.Mesh.HasUVs ? new OpenTK.Vector2(datmesh.Mesh.UVs[face.UV2].X, datmesh.Mesh.UVs[face.UV2].Y) : OpenTK.Vector2.Zero), (datmesh.Mesh.HasUVs ? new OpenTK.Vector2(datmesh.Mesh.UVs[face.UV3].X, datmesh.Mesh.UVs[face.UV3].Y) : OpenTK.Vector2.Zero) } ); } mesh.AddModelMeshPart(meshpart, false); } for (int i = mesh.MeshParts.Count - 1; i >= 0; i--) { if (mesh.MeshParts[i].VertexCount == 0) { mesh.MeshParts.RemoveAt(i); } else { mesh.MeshParts[i].Finalise(); } } model.SetName(mesh.Name, model.AddMesh(mesh)); } return(model); }
public override Asset Import(string path) { DAT dat = DAT.Load(path); SceneManager.Current.Content.LoadMany<MaterialList, MaterialImporter>(Path.GetFileName(path).Replace(".dat", ".mat", StringComparison.OrdinalIgnoreCase), Path.GetDirectoryName(path) + "\\", true); Model model = new Model(); foreach (var datmesh in dat.DatMeshes) { Console.WriteLine(datmesh.Name); datmesh.Mesh.GenerateNormals(); ModelMesh mesh = new ModelMesh(); mesh.Name = (datmesh.Name.Contains(".") ? datmesh.Name.Substring(0, datmesh.Name.IndexOf(".")) : datmesh.Name); SceneManager.Current.UpdateProgress(string.Format("Processing {0}", mesh.Name)); for (int i = -1; i < datmesh.Mesh.Materials.Count; i++) { var meshpart = new ModelMeshPart(); if (i > -1) { var material = SceneManager.Current.Materials.Entries.Find(m => m.Name == datmesh.Mesh.Materials[i]); if (material == null) { material = new Material { Name = datmesh.Mesh.Materials[i] }; SceneManager.Current.Add(material); } meshpart.Material = (Material)material; } foreach (var face in datmesh.Mesh.Faces.Where(f => f.MaterialID == i)) { int smoothingGroup = (face.SmoothingGroup << 8); meshpart.AddFace( new OpenTK.Vector3[] { new OpenTK.Vector3(datmesh.Mesh.Verts[face.V1].X, datmesh.Mesh.Verts[face.V1].Y, datmesh.Mesh.Verts[face.V1].Z), new OpenTK.Vector3(datmesh.Mesh.Verts[face.V2].X, datmesh.Mesh.Verts[face.V2].Y, datmesh.Mesh.Verts[face.V2].Z), new OpenTK.Vector3(datmesh.Mesh.Verts[face.V3].X, datmesh.Mesh.Verts[face.V3].Y, datmesh.Mesh.Verts[face.V3].Z) }, new OpenTK.Vector3[] { new OpenTK.Vector3(datmesh.Mesh.Normals[smoothingGroup + face.V1].X, datmesh.Mesh.Normals[smoothingGroup + face.V1].Y, datmesh.Mesh.Normals[smoothingGroup + face.V1].Z), new OpenTK.Vector3(datmesh.Mesh.Normals[smoothingGroup + face.V2].X, datmesh.Mesh.Normals[smoothingGroup + face.V2].Y, datmesh.Mesh.Normals[smoothingGroup + face.V2].Z), new OpenTK.Vector3(datmesh.Mesh.Normals[smoothingGroup + face.V3].X, datmesh.Mesh.Normals[smoothingGroup + face.V3].Y, datmesh.Mesh.Normals[smoothingGroup + face.V3].Z) }, new OpenTK.Vector2[] { (datmesh.Mesh.HasUVs ? new OpenTK.Vector2(datmesh.Mesh.UVs[face.UV1].X, datmesh.Mesh.UVs[face.UV1].Y) : OpenTK.Vector2.Zero), (datmesh.Mesh.HasUVs ? new OpenTK.Vector2(datmesh.Mesh.UVs[face.UV2].X, datmesh.Mesh.UVs[face.UV2].Y) : OpenTK.Vector2.Zero), (datmesh.Mesh.HasUVs ? new OpenTK.Vector2(datmesh.Mesh.UVs[face.UV3].X, datmesh.Mesh.UVs[face.UV3].Y) : OpenTK.Vector2.Zero) } ); } mesh.AddModelMeshPart(meshpart, false); } for (int i = mesh.MeshParts.Count - 1; i >= 0; i--) { if (mesh.MeshParts[i].VertexCount == 0) { mesh.MeshParts.RemoveAt(i); } else { mesh.MeshParts[i].Finalise(); } } model.SetName(mesh.Name, model.AddMesh(mesh)); } return model; }
static void ProcessNode(TDRNode node, Model model, Model mshses, HIE hie, int ParentBoneIndex = 0) { int boneIndex = ParentBoneIndex; if (exit) { return; } switch (node.Type) { case TDRNode.NodeType.Matrix: boneIndex = model.AddMesh(null, boneIndex); model.SetName(node.Name, boneIndex); model.SetTransform( new Matrix4 ( node.Transform.M11, node.Transform.M12, node.Transform.M13, 0, node.Transform.M21, node.Transform.M22, node.Transform.M23, 0, node.Transform.M31, node.Transform.M32, node.Transform.M33, 0, node.Transform.M41, node.Transform.M42, node.Transform.M43, 1 ), boneIndex); break; case TDRNode.NodeType.Mesh: int index = node.Index; mshses.Meshes[index].MeshParts[0].Material = material; if (model.Bones[ParentBoneIndex].Mesh == null) { model.SetMesh(mshses.Meshes[index], boneIndex); //exit = true; //Console.WriteLine("Adding mesh #{0} \"{1}\" to bone #{2} \"{3}\"", index, mshses.Meshes[index].Name, boneIndex, model.Bones[boneIndex].Name); } else { boneIndex = model.AddMesh(mshses.Meshes[index], ParentBoneIndex); model.SetName(mshses.Meshes[index].Name, boneIndex); //model.SetName(mshses.Meshes[index].Name, model.AddMesh(mshses.Meshes[index], ParentBoneIndex)); //Console.WriteLine("Adding mesh #{0} \"{1}\" to brand new bone", index, mshses.Meshes[index].Name); } break; case TDRNode.NodeType.Texture: if (node.Index > -1) { material = SceneManager.Current.Content.Load<Material, TXImporter>(hie.Textures[node.Index]); } else { material = null; } break; } foreach (var child in node.Children) { ProcessNode(child, model, mshses, hie, boneIndex); } }
public override Asset Import(string path) { HIE hie = HIE.Load(path); Model model = new Model(); Model mshses = new Model(); foreach (string mesh in hie.Meshes) { var mshs = SceneManager.Current.Content.Load<Model, MSHSImporter>(Path.GetFileNameWithoutExtension(mesh), Path.GetDirectoryName(path) + "\\"); foreach (var part in mshs.Meshes) { mshses.AddMesh(part); } } foreach (string texture in hie.Textures) { SceneManager.Current.Content.Load<Material, TXImporter>(texture, Path.GetDirectoryName(path) + "\\", true); } ProcessNode(hie.Root, model, mshses, hie); //ModelMesh mesh = new ModelMesh(); //mesh.Name = "DEFAULT"; //foreach (var tdrmesh in mshs.Meshes) //{ // ModelMeshPart meshpart = new ModelMeshPart(); // meshpart.PrimitiveType = OpenTK.Graphics.OpenGL.PrimitiveType.Triangles; // SceneManager.Current.UpdateProgress(string.Format("Processing {0}", mesh.Name)); // for (int i = 0; i < tdrmesh.Faces.Count; i++) // { // var face = tdrmesh.Faces[i]; // var v1 = tdrmesh.Vertexes[face.V1]; // var v2 = tdrmesh.Vertexes[face.V2]; // var v3 = tdrmesh.Vertexes[face.V3]; // meshpart.AddFace( // new OpenTK.Vector3[] { // new OpenTK.Vector3(v1.Position.X, v1.Position.Y, v1.Position.Z), // new OpenTK.Vector3(v2.Position.X, v2.Position.Y, v2.Position.Z), // new OpenTK.Vector3(v3.Position.X, v3.Position.Y, v3.Position.Z) // }, // new OpenTK.Vector3[] { // new OpenTK.Vector3(v1.Normal.X, v1.Normal.Y, v1.Normal.Z), // new OpenTK.Vector3(v2.Normal.X, v2.Normal.Y, v2.Normal.Z), // new OpenTK.Vector3(v3.Normal.X, v3.Normal.Y, v3.Normal.Z) // }, // new OpenTK.Vector2[] { // new OpenTK.Vector2(v1.UV.X, v1.UV.Y), // new OpenTK.Vector2(v2.UV.X, v2.UV.Y), // new OpenTK.Vector2(v3.UV.X, v3.UV.Y) // } // ); // } // mesh.AddModelMeshPart(meshpart); //} //model.SetName(mesh.Name, model.AddMesh(mesh)); return model; }
public void Draw() { if (asset == null) { ModelMeshPart sprite = new ModelMeshPart(); sprite.AddVertex(new Vector3(-0.25f, -0.25f, 0.0f), Vector3.UnitY, new Vector2(0, 1)); sprite.AddVertex(new Vector3(-0.25f, 0.25f, 0.0f), Vector3.UnitY, new Vector2(0, 0)); sprite.AddVertex(new Vector3(0.25f, 0.25f, 0.0f), Vector3.UnitY, new Vector2(1, 0)); sprite.AddVertex(new Vector3(0.25f, -0.25f, 0.0f), Vector3.UnitY, new Vector2(1, 1)); sprite.AddVertex(new Vector3(0.25f, -0.25f, 0.0f), Vector3.UnitY, new Vector2(0, 1)); sprite.AddVertex(new Vector3(0.25f, 0.25f, 0.0f), Vector3.UnitY, new Vector2(0, 0)); sprite.AddVertex(new Vector3(-0.25f, 0.25f, 0.0f), Vector3.UnitY, new Vector2(1, 0)); sprite.AddVertex(new Vector3(-0.25f, -0.25f, 0.0f), Vector3.UnitY, new Vector2(1, 1)); sprite.IndexBuffer.Initialise(); sprite.VertexBuffer.Initialise(); sprite.Material = new Material { Name = "Entity.Asset", Texture = SceneManager.Current.Content.Load <Texture, PNGImporter>(IconFilename) }; sprite.PrimitiveType = PrimitiveType.Quads; ModelMesh spritemesh = new ModelMesh(); spritemesh.AddModelMeshPart(sprite); Model spritemodel = new Model(); spritemodel.AddMesh(spritemesh); asset = spritemodel; } if (Linked) { Matrix4D parentTransform = ((ModelBone)Link).CombinedTransform; if (LinkType == LinkType.All) { Transform = parentTransform; } else { Transform = Matrix4D.Identity; Vector3 v = parentTransform.ExtractTranslation(); parentTransform.Normalise(); parentTransform.M41 = v.X; parentTransform.M42 = v.Y; parentTransform.M43 = v.Z; if (LinkType.HasFlag(LinkType.Rotation)) { Transform *= Matrix4D.CreateFromQuaternion(parentTransform.ExtractRotation()); } if (LinkType.HasFlag(LinkType.Scale)) { Transform *= Matrix4D.CreateScale(parentTransform.ExtractScale()); } if (LinkType.HasFlag(LinkType.Position)) { Transform *= Matrix4D.CreateTranslation(parentTransform.ExtractTranslation()); } } } Matrix4D mS = SceneManager.Current.Transform; Matrix4D mT = Transform; SceneManager.Current.Renderer.PushMatrix(); Matrix4D position = Matrix4D.CreateTranslation(mT.ExtractTranslation()); SceneManager.Current.Renderer.MultMatrix(ref mS); SceneManager.Current.Renderer.MultMatrix(ref position); if (Lollipop) { Matrix4D rotation = ViewportManager.Current.Active.Camera.Rotation; Matrix4D scale = Matrix4D.CreateScale(0.1f); SceneManager.Current.Renderer.MultMatrix(ref rotation); SceneManager.Current.Renderer.MultMatrix(ref scale); } SceneManager.Current.Renderer.Enable("Blend"); SceneManager.Current.Renderer.BlendFunc("SrcAlpha", "OneMinusSrcAlpha"); ((Model)asset).Draw(); SceneManager.Current.Renderer.Disable("Blend"); SceneManager.Current.Renderer.PopMatrix(); }
public override Asset Import(string path) { BOM bom = BOM.Load(path); Model model = new Model(); model.SupportingDocuments["Source"] = bom; for (int i = 0; i < bom.Meshes.Count; i++) { var bommesh = bom.Meshes[i]; ModelMesh mesh = new ModelMesh(); ModelMeshPart meshpart = new ModelMeshPart(); if (i < 4) { for (int j = 0; j < bommesh.IndexBuffer.Count; j += 3) { int p0 = bommesh.IndexBuffer[j + 0]; int p1 = bommesh.IndexBuffer[j + 1]; int p2 = bommesh.IndexBuffer[j + 2]; meshpart.AddFace( new Vector3[] { new Vector3(bom.Verts[p0].Position.X, bom.Verts[p0].Position.Y, bom.Verts[p0].Position.Z), new Vector3(bom.Verts[p1].Position.X, bom.Verts[p1].Position.Y, bom.Verts[p1].Position.Z), new Vector3(bom.Verts[p2].Position.X, bom.Verts[p2].Position.Y, bom.Verts[p2].Position.Z), }, new Vector3[] { new Vector3(bom.Verts[p0].Normal.X, bom.Verts[p0].Normal.Y, bom.Verts[p0].Normal.Z), new Vector3(bom.Verts[p1].Normal.X, bom.Verts[p1].Normal.Y, bom.Verts[p1].Normal.Z), new Vector3(bom.Verts[p2].Normal.X, bom.Verts[p2].Normal.Y, bom.Verts[p2].Normal.Z), }, new Vector2[] { Vector2.Zero, Vector2.Zero, Vector2.Zero } ); } } else { // Process triangle strip for (int j = 0; j < bommesh.IndexBuffer.Count - 2; j++) { BOMVertex v0, v1, v2; v0 = bom.Verts[bommesh.IndexBuffer[j + 0]]; if (j % 2 != 0) { v1 = bom.Verts[bommesh.IndexBuffer[j + 1]]; v2 = bom.Verts[bommesh.IndexBuffer[j + 2]]; } else { v1 = bom.Verts[bommesh.IndexBuffer[j + 2]]; v2 = bom.Verts[bommesh.IndexBuffer[j + 1]]; } meshpart.AddFace( new Vector3[] { new Vector3(v0.Position.X, v0.Position.Y, v0.Position.Z), new Vector3(v1.Position.X, v1.Position.Y, v1.Position.Z), new Vector3(v2.Position.X, v2.Position.Y, v2.Position.Z) }, new Vector3[] { new Vector3(v0.Normal.X, v0.Normal.Y, v0.Normal.Z), new Vector3(v1.Normal.X, v1.Normal.Y, v1.Normal.Z), new Vector3(v2.Normal.X, v2.Normal.Y, v2.Normal.Z) }, new Vector2[] { Vector2.Zero, Vector2.Zero, Vector2.Zero } ); } } mesh.AddModelMeshPart(meshpart); mesh.Name = bom.Name + "_" + i; model.SetName(bom.Name, model.AddMesh(mesh)); } return(model); }
public override Asset Import(string path) { ACT act = ACT.Load(path); Model model = new Model(); int boneIndex = 0; string fileName = Path.GetFileName(path); path = Path.GetDirectoryName(path); Model dat = SceneManager.Current.Content.Load <Model, DATImporter>($"{Path.GetFileNameWithoutExtension(fileName)}.dat", path); if (dat.SupportingDocuments.ContainsKey("Source")) { model.SupportingDocuments.Add("Source", dat.GetSupportingDocument <DAT>("Source")); } Material material = null; foreach (ACTNode section in act.Sections) { switch (section.Section) { case Section.Name: boneIndex = model.AddMesh(null, boneIndex); model.SetName(section.Identifier, boneIndex); material = null; break; case Section.Material: material = (Material)SceneManager.Current.Materials.Entries.Find(m => m != null && m.Name == section.Material); if (material == null) { material = new Material() { Name = section.Material }; SceneManager.Current.Add(material); } break; case Section.Model: ModelMesh mesh = dat.FindMesh(section.Model); if (mesh != null) { model.SetMesh(new ModelMesh(mesh), boneIndex); if (material != null) { foreach (ModelMesh modelmesh in model.Meshes) { foreach (ModelMeshPart meshpart in modelmesh.MeshParts) { if (meshpart.Material == null) { meshpart.Material = material; } } } } } break; case Section.Matrix: model.SetTransform( new Matrix4D( section.Transform.M11, section.Transform.M12, section.Transform.M13, 0, section.Transform.M21, section.Transform.M22, section.Transform.M23, 0, section.Transform.M31, section.Transform.M32, section.Transform.M33, 0, section.Transform.M41, section.Transform.M42, section.Transform.M43, 1 ), boneIndex ); break; case Section.SubLevelBegin: break; case Section.SubLevelEnd: boneIndex = model.Bones[boneIndex].Parent.Index; break; } } SceneManager.Current.UpdateProgress(string.Format("Loaded {0}", fileName)); return(model); }
//public override string GetHints(string currentPath) //{ // string hints = string.Empty; // while (Directory.Exists(Directory.GetParent(currentPath).FullName)) // { // if (Directory.Exists(Path.Combine(Directory.GetParent(currentPath).FullName, "Models"))) // { // } // } // if (currentPath != null && Directory.Exists(Directory.GetParent(currentPath).FullName)) // { // hints = $"{currentPath};"; // if (Directory.Exists(Path.Combine(Directory.GetParent(currentPath).FullName, "PIXELMAP"))) // { // hints += $"{Path.Combine(Directory.GetParent(currentPath).FullName, "PIXELMAP")};"; // } // } // return hints; //} public override Asset Import(string path) { MDL mdl = MDL.Load(path); Model model = new Model(); ModelMesh mesh = new ModelMesh(); // 2015-07-12 : Commenting out SupportingDocuments["Source"] to see if anything breaks // model.SupportingDocuments["Source"] = mdl; bool bUsePrepData = true; for (int i = 0; i < mdl.Meshes.Count; i++) { Dictionary <int, int> newIndex = new Dictionary <int, int>(); ModelMeshPart meshpart = new ModelMeshPart(); MDLMaterialGroup mdlmesh = mdl.GetMesh(i); meshpart.Material = SceneManager.Current.Content.Load <Material, MaterialImporter>(mdlmesh.Name, Path.GetDirectoryName(path), true); if (bUsePrepData) { foreach (MDLFace f in mdl.Faces.Where(f => f.MaterialID == i)) { for (int j = 0; j < 3; j++) { if (!newIndex.ContainsKey(f.Verts[j])) { MDLVertex v = mdl.Vertices[f.Verts[j]]; int index = meshpart.AddVertex(new Vector3(v.Position.X, v.Position.Y, v.Position.Z), new Vector3(v.Normal.X, v.Normal.Y, v.Normal.Z), new Vector2(v.UV.X, v.UV.Y), new Vector2(v.UV2.X, v.UV2.Y), v.Colour, false); newIndex.Add(f.Verts[j], index); } } meshpart.AddFace( newIndex[f.Verts[0]], newIndex[f.Verts[1]], newIndex[f.Verts[2]] ); } } else { int[] verts = new int[3]; for (int j = 0; j < mdlmesh.StripList.Count - 2; j++) { if (mdlmesh.StripList[j + 2].Degenerate) { continue; } verts[0] = mdlmesh.StripList[j + 0].Index; if (j % 2 == 0) { verts[1] = mdlmesh.StripList[j + 1].Index; verts[2] = mdlmesh.StripList[j + 2].Index; } else { verts[1] = mdlmesh.StripList[j + 2].Index; verts[2] = mdlmesh.StripList[j + 1].Index; } for (int k = 0; k < 3; k++) { if (!newIndex.ContainsKey(verts[k])) { MDLVertex v = mdl.Vertices[verts[k]]; int index = meshpart.AddVertex(new Vector3(v.Position.X, v.Position.Y, v.Position.Z), new Vector3(v.Normal.X, v.Normal.Y, v.Normal.Z), new Vector2(v.UV.X, v.UV.Y), new Vector2(v.UV2.X, v.UV2.Y), v.Colour, false); newIndex.Add(verts[k], index); } } meshpart.AddFace( newIndex[verts[0]], newIndex[verts[1]], newIndex[verts[2]] ); } // Process patch list for (int j = 0; j < mdlmesh.TriList.Count; j += 3) { verts[0] = mdlmesh.TriList[j + 0].Index; verts[1] = mdlmesh.TriList[j + 1].Index; verts[2] = mdlmesh.TriList[j + 2].Index; for (int k = 0; k < 3; k++) { if (!newIndex.ContainsKey(verts[k])) { MDLVertex v = mdl.Vertices[verts[k]]; int index = meshpart.AddVertex(new Vector3(v.Position.X, v.Position.Y, v.Position.Z), new Vector3(v.Normal.X, v.Normal.Y, v.Normal.Z), new Vector2(v.UV.X, v.UV.Y), new Vector2(v.UV2.X, v.UV2.Y), v.Colour, false); newIndex.Add(verts[k], index); } } meshpart.AddFace( newIndex[verts[0]], newIndex[verts[1]], newIndex[verts[2]] ); } } mesh.AddModelMeshPart(meshpart); Console.WriteLine(meshpart.VertexCount / 3); } mesh.Name = mdl.Name; model.SetName(mdl.Name, model.AddMesh(mesh)); return(model); }
public override WriteableBitmap Initialize(Device device) { const int width = 600; const int height = 400; // Create device and swap chain. var swapChainPresenter = new WpfSwapChainPresenter(); _swapChain = device.CreateSwapChain(width, height, swapChainPresenter); _deviceContext = device.ImmediateContext; // Create RenderTargetView from the backbuffer. var backBuffer = Texture2D.FromSwapChain(_swapChain, 0); _renderTargetView = device.CreateRenderTargetView(backBuffer); // Compile Vertex and Pixel shaders var vertexShaderByteCode = ShaderCompiler.CompileFromFile("Modules/SampleBrowser/Samples/BasicTriangle/MiniTri.fx", "VS", "vs_4_0"); var vertexShader = device.CreateVertexShader(vertexShaderByteCode); var pixelShaderByteCode = ShaderCompiler.CompileFromFile("Modules/SampleBrowser/Samples/BasicTriangle/MiniTri.fx", "PS", "ps_4_0"); var pixelShader = device.CreatePixelShader(pixelShaderByteCode); // Layout from VertexShader input signature var layout = device.CreateInputLayout( new[] { new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0), new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 0) }, vertexShaderByteCode); // Instantiate Vertex buffer from vertex data var vertices = device.CreateBuffer(new BufferDescription(BindFlags.VertexBuffer), new[] { new Vector4(0.0f, 0.5f, 0.5f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), new Vector4(0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f) }); _model = new Model(); _model.AddMesh(new ModelMesh { IndexBuffer = device.CreateBuffer(new BufferDescription { BindFlags = BindFlags.IndexBuffer }, new uint[] { 0, 1, 2 }), IndexCount = 3, InputLayout = layout, PrimitiveCount = 1, PrimitiveTopology = PrimitiveTopology.TriangleList, VertexBuffer = vertices, VertexCount = 3, VertexSize = 32 }); // Prepare all the stages _deviceContext.VertexShader.Shader = vertexShader; _deviceContext.Rasterizer.SetViewports(new Viewport(0, 0, width, height, 0.0f, 1.0f)); _deviceContext.PixelShader.Shader = pixelShader; _deviceContext.OutputMerger.SetTargets(null, _renderTargetView); return(swapChainPresenter.Bitmap); }
public override Asset Import(string path) { FBX fbx = FBX.Load(path); Model model = new Model(); Dictionary<long, object> components = new Dictionary<long, object>(); Dictionary<long, Matrix4> transforms = new Dictionary<long, Matrix4>(); Dictionary<long, string> triangulationErrors = new Dictionary<long, string>(); string name = Path.GetFileNameWithoutExtension(path); if (fbx == null) { SceneManager.Current.RaiseError(string.Format("File \"{0}\" could not be opened. Please ensure this is a binary FBX file.", name)); return null; } var objects = fbx.Elements.Find(e => e.ID == "Objects"); RotationOrder order; var worldMatrix = createTransformFor(fbx.Elements.Find(e => e.ID == "GlobalSettings").Children[1], out order); foreach (var material in objects.Children.Where(e => e.ID == "Material")) { string matName = material.Properties[1].Value.ToString(); matName = matName.Substring(0, matName.IndexOf("::")); var m = new Material { Name = matName }; components.Add((long)material.Properties[0].Value, m); Console.WriteLine("Added material \"{0}\" ({1})", matName, material.Properties[0].Value); } var textures = objects.Children.Where(e => e.ID == "Texture"); foreach (var texture in textures) { Texture t = null; string fullFile = texture.Children.Find(e => e.ID == "FileName").Properties[0].Value.ToString(); if (fullFile.IndexOf('.') == -1) { continue; } string file = Path.GetFileName(fullFile); switch (Path.GetExtension(file)) { case ".bmp": t = SceneManager.Current.Content.Load<Texture, BMPImporter>(Path.GetFileNameWithoutExtension(file)); break; case ".png": t = SceneManager.Current.Content.Load<Texture, PNGImporter>(Path.GetFileNameWithoutExtension(file)); break; case ".tif": t = SceneManager.Current.Content.Load<Texture, TIFImporter>(Path.GetFileNameWithoutExtension(file)); break; case ".tga": t = SceneManager.Current.Content.Load<Texture, TGAImporter>(Path.GetFileNameWithoutExtension(file)); break; default: t = new Texture(); break; } if (!components.ContainsKey((long)texture.Properties[0].Value)) { components.Add((long)texture.Properties[0].Value, t); Console.WriteLine("Added texture \"{0}\" ({1})", file, texture.Properties[0].Value); } } foreach (var element in objects.Children.Where(e => e.ID == "Model")) { string modelName = element.Properties[1].Value.ToString(); modelName = modelName.Substring(0, modelName.IndexOf("::")); components.Add((long)element.Properties[0].Value, new ModelMesh { Name = modelName, Tag = (long)element.Properties[0].Value }); Console.WriteLine("Added model \"{0}\" ({1})", modelName, element.Properties[0].Value); var properties = element.Children.Find(c => c.ID == "Properties70"); var m = Matrix4.Identity; bool bRotationActive = false; var lclTranslation = OpenTK.Vector3.Zero; var lclRotation = Quaternion.Identity; var preRotation = Quaternion.Identity; var postRotation = Quaternion.Identity; var rotationPivot = OpenTK.Vector3.Zero; var rotationOffset = OpenTK.Vector3.Zero; var lclScaling = OpenTK.Vector3.One; var scalingPivot = OpenTK.Vector3.Zero; var scalingOffset = OpenTK.Vector3.Zero; var geoPosition = OpenTK.Vector3.Zero; var geoRotation = Quaternion.Identity; var geoScale = OpenTK.Vector3.One; FBXElem property; property = properties.Children.GetProperty("RotationActive"); if (property != null) { bRotationActive = ((int)property.Properties[4].Value == 1); } property = properties.Children.GetProperty("ScalingPivot"); if (property != null) { scalingPivot = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("Lcl Scaling"); if (property != null) { lclScaling = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("ScalingOffset"); if (property != null) { scalingOffset = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("RotationPivot"); if (property != null) { rotationPivot = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("PostRotation"); if (property != null) { postRotation = MakeQuaternion( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value), order ); } property = properties.Children.GetProperty("Lcl Rotation"); if (property != null) { lclRotation = MakeQuaternion( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value), order ); } property = properties.Children.GetProperty("PreRotation"); if (property != null) { preRotation = MakeQuaternion( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value), order ); } property = properties.Children.GetProperty("RotationOffset"); if (property != null) { rotationOffset = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("Lcl Translation"); if (property != null) { lclTranslation = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("GeometricTranslation"); if (property != null) { geoPosition = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } property = properties.Children.GetProperty("GeometricRotation"); if (property != null) { geoRotation = MakeQuaternion( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value), order ); } property = properties.Children.GetProperty("GeometricScaling"); if (property != null) { geoScale = new OpenTK.Vector3( Convert.ToSingle(property.Properties[4].Value), Convert.ToSingle(property.Properties[5].Value), Convert.ToSingle(property.Properties[6].Value) ); } m = Matrix4.CreateTranslation(scalingPivot).Inverted() * Matrix4.CreateScale(lclScaling) * Matrix4.CreateTranslation(scalingPivot) * Matrix4.CreateTranslation(scalingOffset) * Matrix4.CreateTranslation(rotationPivot).Inverted() * Matrix4.CreateFromQuaternion(postRotation) * Matrix4.CreateFromQuaternion(lclRotation) * Matrix4.CreateFromQuaternion(preRotation) * Matrix4.CreateTranslation(rotationPivot) * Matrix4.CreateTranslation(rotationOffset) * Matrix4.CreateTranslation(lclTranslation); if (m != Matrix4.Identity) { transforms.Add((long)element.Properties[0].Value, m); } } foreach (var element in objects.Children.Where(e => e.ID == "Geometry")) { bool bUVs = true; bool bNorms = true; bool bColours = true; bool bUseIndexNorm = false; bool bNeedsTriangulating = false; string geometryName = element.Properties[1].Value.ToString(); geometryName = geometryName.Substring(0, geometryName.IndexOf("::")); var verts = new List<OpenTK.Vector3>(); var norms = new List<OpenTK.Vector3>(); var uvs = new List<OpenTK.Vector2>(); var colours = new List<OpenTK.Graphics.Color4>(); var vertParts = (double[])element.Children.Find(e => e.ID == "Vertices").Properties[0].Value; for (int i = 0; i < vertParts.Length; i += 3) { verts.Add(new OpenTK.Vector3((float)vertParts[i + 0], (float)vertParts[i + 1], (float)vertParts[i + 2])); } SceneManager.Current.UpdateProgress(string.Format("Processed {0}->Vertices", element.Properties[1].Value)); var normElem = element.Children.Find(e => e.ID == "LayerElementNormal"); if (normElem != null) { var normParts = (double[])normElem.Children.Find(e => e.ID == "Normals").Properties[0].Value; for (int i = 0; i < normParts.Length; i += 3) { norms.Add(new OpenTK.Vector3((float)normParts[i + 0], (float)normParts[i + 1], (float)normParts[i + 2])); } bUseIndexNorm = (normElem.Children.Find(e => e.ID == "MappingInformationType").Properties[0].Value.ToString() == "ByVertice"); SceneManager.Current.UpdateProgress(string.Format("Processed {0}->Normals", element.Properties[1].Value)); } else { bNorms = false; } var colourElem = element.Children.Find(e => e.ID == "LayerElementColor"); if (colourElem != null) { var colourParts = (double[])colourElem.Children.Find(e => e.ID == "Colors").Properties[0].Value; var colourReferenceType = colourElem.Children.Find(e => e.ID == "ReferenceInformationType"); switch (colourReferenceType.Properties[0].Value.ToString()) { case "IndexToDirect": var colourIndicies = (int[])colourElem.Children.Find(e => e.ID == "ColorIndex").Properties[0].Value; for (int i = 0; i < colourIndicies.Length; i++) { int offset = colourIndicies[i] * 4; colours.Add(new OpenTK.Graphics.Color4((float)colourParts[offset + 0], (float)colourParts[offset + 1], (float)colourParts[offset + 2], (float)colourParts[offset + 3])); } break; case "Direct": bColours = false; break; default: throw new NotImplementedException("Unsupported Colour Reference Type: " + colourReferenceType.Properties[0].Value.ToString()); } SceneManager.Current.UpdateProgress(string.Format("Processed {0}->Colours", element.Properties[1].Value)); } else { bColours = false; } var uvElem = element.Children.Find(e => e.ID == "LayerElementUV"); if (uvElem != null) { var uvParts = (double[])uvElem.Children.Find(e => e.ID == "UV").Properties[0].Value; var uvReferenceType = uvElem.Children.Find(e => e.ID == "ReferenceInformationType"); if (uvReferenceType.Properties[0].Value.ToString() == "IndexToDirect") { var luvs = new List<OpenTK.Vector2>(); for (int i = 0; i < uvParts.Length; i += 2) { luvs.Add(new OpenTK.Vector2((float)uvParts[i + 0], 1 - (float)uvParts[i + 1])); } var uvindicies = (int[])uvElem.Children.Find(e => e.ID == "UVIndex").Properties[0].Value; for (int i = 0; i < uvindicies.Length; i++) { if (uvindicies[i] == -1) { uvs.Add(OpenTK.Vector2.Zero); } else { uvs.Add(luvs[uvindicies[i]]); } } } else { for (int i = 0; i < uvParts.Length; i += 2) { uvs.Add(new OpenTK.Vector2((float)uvParts[i + 0], (float)uvParts[i + 1])); } } SceneManager.Current.UpdateProgress(string.Format("Processed {0}->UVs", element.Properties[1].Value)); } else { bUVs = false; } var indicies = (int[])element.Children.Find(e => e.ID == "PolygonVertexIndex").Properties[0].Value; var faces = new List<FBXFace>(); var face = new FBXFace(); var j = 0; for (int i = 0; i < indicies.Length; i++) { bool bFace = false; int index = indicies[i]; if (index < 0) { bFace = true; index = (index * -1) - 1; } j++; face.AddVertex(verts[index], (bNorms ? norms[(bUseIndexNorm ? index : i)] : OpenTK.Vector3.Zero), (bUVs ? uvs[i] : OpenTK.Vector2.Zero), (bColours ? colours[i] : OpenTK.Graphics.Color4.White)); if (bFace) { if (j > 3) { triangulationErrors.Add((long)element.Properties[0].Value, geometryName); bNeedsTriangulating = true; break; } faces.Add(face); face = new FBXFace(); j = 0; } } var parts = new List<ModelMeshPart>(); if (!bNeedsTriangulating) { SceneManager.Current.UpdateProgress(string.Format("Processed {0}->Faces", element.Properties[1].Value)); var elemMaterial = element.Children.Find(e => e.ID == "LayerElementMaterial"); if (elemMaterial != null) { var faceMaterials = (int[])elemMaterial.Children.Find(e => e.ID == "Materials").Properties[0].Value; for (int i = 0; i < faceMaterials.Length; i++) { faces[i].MaterialID = faceMaterials[i]; } SceneManager.Current.UpdateProgress(string.Format("Processed {0}->Materials", element.Properties[1].Value)); } var materialGroups = faces.GroupBy(f => f.MaterialID); int processedFaceCount = 0, processedGroupCount = 0; foreach (var materialGroup in materialGroups) { var smoothingGroups = materialGroup.GroupBy(f => f.SmoothingGroup); foreach (var smoothingGroup in smoothingGroups) { var meshpart = new ModelMeshPart { PrimitiveType = OpenTK.Graphics.OpenGL.PrimitiveType.Triangles }; processedFaceCount = 0; foreach (var groupface in smoothingGroup) { foreach (var vert in groupface.Vertices) { meshpart.AddVertex(vert.Position, vert.Normal, vert.UV, vert.Colour); } processedFaceCount++; if (processedFaceCount % 250 == 0) { SceneManager.Current.UpdateProgress(string.Format("Processed {0}->MeshPart[{1}]->Face[{2}]", element.Properties[1].Value, processedGroupCount, processedFaceCount)); } } meshpart.Key = materialGroup.Key; parts.Add(meshpart); SceneManager.Current.UpdateProgress(string.Format("Processed {0}->MeshPart", element.Properties[1].Value)); processedGroupCount++; } } } components.Add((long)element.Properties[0].Value, parts); SceneManager.Current.UpdateProgress(string.Format("Processed {0}", element.Properties[1].Value)); } string[] connectionOrder = new string[] { "System.Collections.Generic.List`1[Flummery.ModelMeshPart]", "Flummery.Texture", "Flummery.Material", "Flummery.ModelMesh" }; var connections = fbx.Elements.Find(e => e.ID == "Connections"); HashSet<long> loaded = new HashSet<long>(); foreach (var connectionType in connectionOrder) { var connectionsOfType = connections.Children.Where(c => components.ContainsKey((long)c.Properties[1].Value) && components[(long)c.Properties[1].Value].GetType().ToString() == connectionType); foreach (var connection in connectionsOfType) { long keyA = (long)connection.Properties[1].Value; long keyB = (long)connection.Properties[2].Value; Console.WriteLine("{0} is connected to {1} :: {2}", keyA, keyB, connectionType); switch (connectionType) { case "Flummery.ModelMesh": int boneID; if (keyB == 0) { boneID = model.AddMesh((ModelMesh)components[keyA]); model.SetName(((ModelMesh)components[keyA]).Name, boneID); if (transforms.ContainsKey(keyA)) { model.SetTransform(transforms[keyA], boneID); } } else { var parent = model.FindMesh(keyB); if (parent != null) { boneID = model.AddMesh((ModelMesh)components[keyA], parent.Parent.Index); model.SetName(((ModelMesh)components[keyA]).Name, boneID); if (transforms.ContainsKey(keyA)) { model.SetTransform(transforms[keyA], boneID); } } else { if (!components.ContainsKey(keyB)) { Console.WriteLine("Components doesn't contain {0}", keyB); } else { Console.WriteLine("Couldn't find {0}", ((ModelMesh)components[keyB]).Name); } } } break; case "Flummery.Texture": if (components.ContainsKey(keyB) && components[keyB].GetType().ToString() == "Flummery.Material") { if (loaded.Add(keyB)) { ((Material)components[keyB]).Texture = (Texture)components[keyA]; SceneManager.Current.Add((Material)components[keyB]); } } else { Console.WriteLine("{0} is of unknown type {1}", keyA, components[keyA].GetType().ToString()); Console.WriteLine("{0} is of unknown type {1}", keyB, components[keyB].GetType().ToString()); } break; case "System.Collections.Generic.List`1[Flummery.ModelMeshPart]": if (components.ContainsKey(keyB) && components[keyB].GetType().ToString() == "Flummery.ModelMesh") { if (triangulationErrors.ContainsKey(keyA)) { triangulationErrors[keyA] += " (geometry of " + ((ModelMesh)components[keyB]).Name + ")"; } foreach (var part in (List<ModelMeshPart>)components[keyA]) { ((ModelMesh)components[keyB]).AddModelMeshPart(part); } } break; case "Flummery.Material": if (components.ContainsKey(keyB) && components[keyB].GetType().ToString() == "Flummery.ModelMesh") { var materialLookup = connections.Children.Where(c => (long)c.Properties[2].Value == keyB).ToList(); for (int i = materialLookup.Count - 1; i > -1; i--) { if (!connectionsOfType.Any(c => (long)c.Properties[1].Value == (long)materialLookup[i].Properties[1].Value)) { materialLookup.RemoveAt(i); } } foreach (var part in ((ModelMesh)components[keyB]).MeshParts) { if ((long)materialLookup[(int)part.Key].Properties[1].Value == keyA) { part.Material = (Material)components[keyA]; //SceneManager.Current.Add(part.Material); } } } break; default: Console.WriteLine("{0} is of unknown type {1}", keyA, components[keyA].GetType().ToString()); if (components.ContainsKey(keyB)) { Console.WriteLine("{0} is of unknown type {1}", keyB, components[keyB].GetType().ToString()); } Console.WriteLine("==="); break; } } } if (triangulationErrors.Count > 0) { SceneManager.Current.UpdateProgress(string.Format("Failed to load {0}", name)); string error = string.Format("File \"{0}\" has part{1} that need been triangulating! Please triangulate the following:", name, (triangulationErrors.Count > 1 ? "s" : "")); foreach (var kvp in triangulationErrors) { error += "\r\n" + kvp.Value; } SceneManager.Current.RaiseError(error); return null; } else { SceneManager.Current.UpdateProgress(string.Format("Loaded {0}", name)); model.Santise(); if (worldMatrix != Matrix4.Identity) { ModelManipulator.Freeze(model, worldMatrix); } ModelManipulator.FlipAxis(model.Root.Mesh, Axis.X, true); return model; } }
//Create meshes and add vertex and index buffers private void AddVertexData(Model model, Scene scene, Node node, Device device, ref Matrix transform) { Matrix previousTransform = transform; transform = Matrix.Multiply(previousTransform, FromMatrix(node.Transform)); //also calculate inverse transpose matrix for normal/tangent/bitagent transformation Matrix invTranspose = transform; invTranspose.Invert(); invTranspose.Transpose(); if (node.HasMeshes) { foreach (int index in node.MeshIndices) { //get a mesh from the scene Assimp.Mesh mesh = scene.Meshes[index]; //create new mesh to add to model ModelMesh modelMesh = new ModelMesh(); model.AddMesh(ref modelMesh); //determine the elements in the vertex bool hasTexCoords = mesh.HasTextureCoords(0); bool hasColors = mesh.HasVertexColors(0); bool hasNormals = mesh.HasNormals; bool hasTangents = mesh.Tangents != null; bool hasBitangents = mesh.BiTangents != null; //create vertex element list InputElement[] vertexElements = new InputElement[GetNoofInputElements(mesh)]; uint elementIndex = 0; vertexElements[elementIndex++] = new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0); short vertexSize = (short)Utilities.SizeOf <Vector3>(); if (hasColors) { vertexElements[elementIndex++] = new InputElement("COLOR", 0, Format.R8G8B8A8_UInt, vertexSize, 0); vertexSize += (short)Utilities.SizeOf <Color>(); } if (hasNormals) { vertexElements[elementIndex++] = new InputElement("NORMAL", 0, Format.R32G32B32_Float, vertexSize, 0); vertexSize += (short)Utilities.SizeOf <Vector3>(); } if (hasTangents) { vertexElements[elementIndex++] = new InputElement("TANGENT", 0, Format.R32G32B32_Float, vertexSize, 0); vertexSize += (short)Utilities.SizeOf <Vector3>(); } if (hasBitangents) { vertexElements[elementIndex++] = new InputElement("BITANGENT", 0, Format.R32G32B32_Float, vertexSize, 0); vertexSize += (short)Utilities.SizeOf <Vector3>(); } if (hasTexCoords) { vertexElements[elementIndex++] = new InputElement("TEXCOORD", 0, Format.R32G32_Float, vertexSize, 0); vertexSize += (short)Utilities.SizeOf <Vector2>(); } //set the vertex elements and size modelMesh.InputElements = vertexElements; modelMesh.VertexSize = vertexSize; //get pointers to vertex data Vector3D[] positions = mesh.Vertices; Vector3D[] texCoords = mesh.GetTextureCoords(0); Vector3D[] normals = mesh.Normals; Vector3D[] tangents = mesh.Tangents; Vector3D[] biTangents = mesh.BiTangents; Color4D[] colours = mesh.GetVertexColors(0); //also determine primitive type switch (mesh.PrimitiveType) { case Assimp.PrimitiveType.Point: modelMesh.PrimitiveTopology = PrimitiveTopology.PointList; break; case Assimp.PrimitiveType.Line: modelMesh.PrimitiveTopology = PrimitiveTopology.LineList; break; case Assimp.PrimitiveType.Triangle: modelMesh.PrimitiveTopology = PrimitiveTopology.TriangleList; break; default: throw new Exception("ModelLoader::AddVertexData(): Unknown primitive type"); } //create data stream for vertices DataStream vertexStream = new DataStream(mesh.VertexCount * vertexSize, true, true); for (int i = 0; i < mesh.VertexCount; i++) { //add position, after transforming it with accumulated node transform { Vector4 result; Vector3 pos = FromVector(positions[i]); Vector3.Transform(ref pos, ref transform, out result); vertexStream.Write <Vector3>(new Vector3(result.X, result.Y, result.Z)); } if (hasColors) { Color vertColor = FromColor(mesh.GetVertexColors(0)[i]); vertexStream.Write <Color>(vertColor); } if (hasNormals) { Vector4 result; Vector3 normal = FromVector(normals[i]); Vector3.Transform(ref normal, ref invTranspose, out result); vertexStream.Write <Vector3>(new Vector3(result.X, result.Y, result.Z)); } if (hasTangents) { Vector4 result; Vector3 tangent = FromVector(tangents[i]); Vector3.Transform(ref tangent, ref invTranspose, out result); vertexStream.Write <Vector3>(new Vector3(result.X, result.Y, result.Z)); } if (hasBitangents) { Vector4 result; Vector3 biTangent = FromVector(biTangents[i]); Vector3.Transform(ref biTangent, ref invTranspose, out result); vertexStream.Write <Vector3>(new Vector3(result.X, result.Y, result.Z)); } if (hasTexCoords) { vertexStream.Write <Vector2>(new Vector2(texCoords[i].X, 1 - texCoords[i].Y)); } } vertexStream.Position = 0; //create new vertex buffer var vertexBuffer = new Buffer(device, vertexStream, new BufferDescription() { BindFlags = BindFlags.VertexBuffer, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None, SizeInBytes = mesh.VertexCount * vertexSize, Usage = ResourceUsage.Default } ); //add it to the mesh modelMesh.VertexBuffer = vertexBuffer; modelMesh.VertexCount = mesh.VertexCount; modelMesh.PrimitiveCount = mesh.FaceCount; //get pointer to indices data uint[] indices = mesh.GetIndices(); //create data stream for indices DataStream indexStream = new DataStream(indices.GetLength(0) * sizeof(uint), true, true); for (int i = 0; i < indices.GetLength(0); i++) { indexStream.Write <uint>(indices[i]); } indexStream.Position = 0; //create new index buffer var indexBuffer = new Buffer(device, indexStream, new BufferDescription() { BindFlags = BindFlags.IndexBuffer, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None, SizeInBytes = indices.GetLength(0) * sizeof(uint), Usage = ResourceUsage.Default } ); //add it to the mesh modelMesh.IndexBuffer = indexBuffer; modelMesh.IndexCount = indices.GetLength(0); } } //if node has more children process them as well for (int i = 0; i < node.ChildCount; i++) { AddVertexData(model, scene, node.Children[i], device, ref transform); } transform = previousTransform; }
public override Asset Import(string path) { HIE hie = HIE.Load(path); Model model = new Model(); Model mshses = new Model(); foreach (string mesh in hie.Meshes) { var mshs = SceneManager.Current.Content.Load <Model, MSHSImporter>(Path.GetFileNameWithoutExtension(mesh), Path.GetDirectoryName(path) + "\\"); foreach (var part in mshs.Meshes) { mshses.AddMesh(part); } } foreach (string texture in hie.Textures) { SceneManager.Current.Content.Load <Material, TXImporter>(texture, Path.GetDirectoryName(path) + "\\", true); } ProcessNode(hie.Root, model, mshses, hie); //ModelMesh mesh = new ModelMesh(); //mesh.Name = "DEFAULT"; //foreach (var tdrmesh in mshs.Meshes) //{ // ModelMeshPart meshpart = new ModelMeshPart(); // meshpart.PrimitiveType = OpenTK.Graphics.OpenGL.PrimitiveType.Triangles; // SceneManager.Current.UpdateProgress(string.Format("Processing {0}", mesh.Name)); // for (int i = 0; i < tdrmesh.Faces.Count; i++) // { // var face = tdrmesh.Faces[i]; // var v1 = tdrmesh.Vertexes[face.V1]; // var v2 = tdrmesh.Vertexes[face.V2]; // var v3 = tdrmesh.Vertexes[face.V3]; // meshpart.AddFace( // new OpenTK.Vector3[] { // new OpenTK.Vector3(v1.Position.X, v1.Position.Y, v1.Position.Z), // new OpenTK.Vector3(v2.Position.X, v2.Position.Y, v2.Position.Z), // new OpenTK.Vector3(v3.Position.X, v3.Position.Y, v3.Position.Z) // }, // new OpenTK.Vector3[] { // new OpenTK.Vector3(v1.Normal.X, v1.Normal.Y, v1.Normal.Z), // new OpenTK.Vector3(v2.Normal.X, v2.Normal.Y, v2.Normal.Z), // new OpenTK.Vector3(v3.Normal.X, v3.Normal.Y, v3.Normal.Z) // }, // new OpenTK.Vector2[] { // new OpenTK.Vector2(v1.UV.X, v1.UV.Y), // new OpenTK.Vector2(v2.UV.X, v2.UV.Y), // new OpenTK.Vector2(v3.UV.X, v3.UV.Y) // } // ); // } // mesh.AddModelMeshPart(meshpart); //} //model.SetName(mesh.Name, model.AddMesh(mesh)); return(model); }
public static void ProcessCarForCarmageddonMaxDamage() { if (SceneManager.Current.Models.Count == 0) { return; } Model model = SceneManager.Current.Models[0]; ModelBoneCollection bones = SceneManager.Current.Models[0].Bones[0].AllChildren(); SceneManager.Current.UpdateProgress("Applying Carmageddon Reincarnation scale"); ModelManipulator.Scale(bones, Matrix4D.CreateScale(6.9f, 6.9f, -6.9f), true); ModelManipulator.FlipFaces(bones, true); SceneManager.Current.UpdateProgress("Fixing material names"); foreach (Material material in SceneManager.Current.Materials) { if (material.Name.Contains(".")) { material.Name = material.Name.Substring(0, material.Name.IndexOf(".")); } material.Name = material.Name.Replace("\\", ""); } SceneManager.Current.UpdateProgress("Munging parts and fixing wheels"); float scale; for (int i = 0; i < bones.Count; i++) { ModelBone bone = bones[i]; if (i == 0) { bone.Name = "c_Body"; bone.Mesh.Name = "c_Body"; } else { bone.Name = Path.GetFileNameWithoutExtension(bone.Name); } switch (bone.Name.ToUpper()) { case "C_BODY": break; case "FLPIVOT": case "FRPIVOT": bone.Name = "Hub_" + bone.Name.ToUpper().Substring(0, 2); if (bone.Transform.ExtractTranslation() == Vector3.Zero) { ModelManipulator.MungeMeshWithBone(bone.Children[0].Mesh, false); Matrix4D m = bone.Transform; m.M31 = bone.Children[0].Transform.M31; m.M32 = bone.Children[0].Transform.M32; m.M33 = bone.Children[0].Transform.M33; bone.Transform = m; model.SetTransform(Matrix4D.Identity, bone.Children[0].Index); } break; case "FLWHEEL": scale = bone.CombinedTransform.ExtractTranslation().Y / 0.35f; bone.Name = "Wheel_FL"; model.ClearMesh(bone.Index); model.SetTransform(Matrix4D.CreateScale(scale) * Matrix4D.CreateRotationY(Maths.DegreesToRadians(180)), bone.Index); break; case "FRWHEEL": scale = bone.CombinedTransform.ExtractTranslation().Y / 0.35f; bone.Name = "Wheel_FR"; model.ClearMesh(bone.Index); model.SetTransform(Matrix4D.CreateScale(scale), bone.Index); break; case "RLWHEEL": case "RRWHEEL": string suffix = bone.Name.ToUpper().Substring(0, 2); bone.Name = "Hub_" + suffix; if (bone.Transform.ExtractTranslation() == Vector3.Zero) { ModelManipulator.MungeMeshWithBone(bone.Mesh, false); } model.ClearMesh(bone.Index); scale = bone.CombinedTransform.ExtractTranslation().Y / 0.35f; int newBone = model.AddMesh(null, bone.Index); model.SetName("Wheel_" + suffix, newBone); model.SetTransform(Matrix4D.CreateScale(scale) * (suffix == "RL" ? Matrix4D.CreateRotationY(Maths.DegreesToRadians(180)) : Matrix4D.Identity), newBone); break; case "DRIVER": bone.Name = "Dryver"; goto default; default: if (bone.Type == BoneType.Mesh) { ModelManipulator.MungeMeshWithBone(bone.Mesh, false); } break; } } SceneManager.Current.UpdateProgress("Processing complete!"); SceneManager.Current.SetCoordinateSystem(CoordinateSystem.LeftHanded); SceneManager.Current.Change(ChangeType.Munge, ChangeContext.Model, -1); SceneManager.Current.SetContext("Carmageddon Max Damage", ContextMode.Car); }
public override Asset Import(string path) { BOM bom = BOM.Load(path); Model model = new Model(); model.SupportingDocuments["Source"] = bom; for (int i = 0; i < bom.Meshes.Count; i++) { var bommesh = bom.Meshes[i]; ModelMesh mesh = new ModelMesh(); ModelMeshPart meshpart = new ModelMeshPart(); if (i < 4) { for (int j = 0; j < bommesh.IndexBuffer.Count; j += 3) { int p0 = bommesh.IndexBuffer[j + 0]; int p1 = bommesh.IndexBuffer[j + 1]; int p2 = bommesh.IndexBuffer[j + 2]; meshpart.AddFace( new Vector3[] { new Vector3(bom.Verts[p0].Position.X, bom.Verts[p0].Position.Y, bom.Verts[p0].Position.Z), new Vector3(bom.Verts[p1].Position.X, bom.Verts[p1].Position.Y, bom.Verts[p1].Position.Z), new Vector3(bom.Verts[p2].Position.X, bom.Verts[p2].Position.Y, bom.Verts[p2].Position.Z), }, new Vector3[] { new Vector3(bom.Verts[p0].Normal.X, bom.Verts[p0].Normal.Y, bom.Verts[p0].Normal.Z), new Vector3(bom.Verts[p1].Normal.X, bom.Verts[p1].Normal.Y, bom.Verts[p1].Normal.Z), new Vector3(bom.Verts[p2].Normal.X, bom.Verts[p2].Normal.Y, bom.Verts[p2].Normal.Z), }, new Vector2[] { Vector2.Zero, Vector2.Zero, Vector2.Zero } ); } } else { // Process triangle strip for (int j = 0; j < bommesh.IndexBuffer.Count - 2; j++) { BOMVertex v0, v1, v2; v0 = bom.Verts[bommesh.IndexBuffer[j + 0]]; if (j % 2 != 0) { v1 = bom.Verts[bommesh.IndexBuffer[j + 1]]; v2 = bom.Verts[bommesh.IndexBuffer[j + 2]]; } else { v1 = bom.Verts[bommesh.IndexBuffer[j + 2]]; v2 = bom.Verts[bommesh.IndexBuffer[j + 1]]; } meshpart.AddFace( new Vector3[] { new Vector3(v0.Position.X, v0.Position.Y, v0.Position.Z), new Vector3(v1.Position.X, v1.Position.Y, v1.Position.Z), new Vector3(v2.Position.X, v2.Position.Y, v2.Position.Z) }, new Vector3[] { new Vector3(v0.Normal.X, v0.Normal.Y, v0.Normal.Z), new Vector3(v1.Normal.X, v1.Normal.Y, v1.Normal.Z), new Vector3(v2.Normal.X, v2.Normal.Y, v2.Normal.Z) }, new Vector2[] { Vector2.Zero, Vector2.Zero, Vector2.Zero } ); } } mesh.AddModelMeshPart(meshpart); mesh.Name = bom.Name + "_" + i; model.SetName(bom.Name, model.AddMesh(mesh)); } return model; }
public override Asset Import(string path) { DAT dat = DAT.Load(path); SceneManager.Current.Content.LoadMany <MaterialList, MATImporter>($"{Path.GetFileNameWithoutExtension(path)}.mat", Path.GetDirectoryName(path), true); Model model = new Model(); model.SupportingDocuments.Add("Source", dat); foreach (DatMesh datmesh in dat.DatMeshes) { Console.WriteLine(datmesh.Name); datmesh.Mesh.GenerateNormals(); ModelMesh mesh = new ModelMesh { Name = datmesh.Name }; SceneManager.Current.UpdateProgress($"Processing {mesh.Name}"); for (int i = -1; i < datmesh.Mesh.Materials.Count; i++) { ModelMeshPart meshpart = new ModelMeshPart(); if (i > -1) { Asset material = SceneManager.Current.Materials.Entries.Find(m => m != null && m.Name == datmesh.Mesh.Materials[i]); if (material == null) { material = new Material { Name = datmesh.Mesh.Materials[i] }; SceneManager.Current.Add(material); } meshpart.Material = (Material)material; } foreach (ToxicRagers.Carmageddon2.Helpers.C2Face face in datmesh.Mesh.Faces.Where(f => f.MaterialID == i)) { int smoothingGroup = (face.SmoothingGroup << 8); meshpart.AddFace( new Vector3[] { new Vector3(datmesh.Mesh.Verts[face.V1].X, datmesh.Mesh.Verts[face.V1].Y, datmesh.Mesh.Verts[face.V1].Z), new Vector3(datmesh.Mesh.Verts[face.V2].X, datmesh.Mesh.Verts[face.V2].Y, datmesh.Mesh.Verts[face.V2].Z), new Vector3(datmesh.Mesh.Verts[face.V3].X, datmesh.Mesh.Verts[face.V3].Y, datmesh.Mesh.Verts[face.V3].Z) }, new Vector3[] { new Vector3(datmesh.Mesh.Normals[smoothingGroup + face.V1].X, datmesh.Mesh.Normals[smoothingGroup + face.V1].Y, datmesh.Mesh.Normals[smoothingGroup + face.V1].Z), new Vector3(datmesh.Mesh.Normals[smoothingGroup + face.V2].X, datmesh.Mesh.Normals[smoothingGroup + face.V2].Y, datmesh.Mesh.Normals[smoothingGroup + face.V2].Z), new Vector3(datmesh.Mesh.Normals[smoothingGroup + face.V3].X, datmesh.Mesh.Normals[smoothingGroup + face.V3].Y, datmesh.Mesh.Normals[smoothingGroup + face.V3].Z) }, new Vector2[] { (datmesh.Mesh.HasUVs ? new Vector2(datmesh.Mesh.UVs[face.UV1].X, datmesh.Mesh.UVs[face.UV1].Y) : Vector2.Zero), (datmesh.Mesh.HasUVs ? new Vector2(datmesh.Mesh.UVs[face.UV2].X, datmesh.Mesh.UVs[face.UV2].Y) : Vector2.Zero), (datmesh.Mesh.HasUVs ? new Vector2(datmesh.Mesh.UVs[face.UV3].X, datmesh.Mesh.UVs[face.UV3].Y) : Vector2.Zero) } ); } mesh.AddModelMeshPart(meshpart, false); } for (int i = mesh.MeshParts.Count - 1; i >= 0; i--) { if (mesh.MeshParts[i].VertexCount == 0) { mesh.MeshParts.RemoveAt(i); } else { mesh.MeshParts[i].Finalise(); } } model.SetName(mesh.Name, model.AddMesh(mesh)); } return(model); }