public TexturedMeshBinder(Autodesk.Dynamo.MeshToolkit.Mesh mesh, Color color, string textureFileName, Vector2Collection textureCoordinates) { StartingPositions = mesh.Vertices().ToTriples().ToArray(); Color = color; try { diffuseMap = new BitmapImage(new Uri(textureFileName)); } catch (FileNotFoundException) { throw new Exception("Could not locate the texture file"); } this.textureCoordinates = textureCoordinates; faceIndices = mesh.VertexIndicesByTri(); int faceCount = faceIndices.Count / 3; faces = new IndexGroup[faceCount]; for (int i = 0; i < faceCount; i++) { faces[i] = IndexGroup.ByIndices( (uint)faceIndices[i * 3], (uint)faceIndices[i * 3 + 1], (uint)faceIndices[i * 3 + 2]); } meshFaceIndices = new IntCollection(); foreach (IndexGroup face in faces) { meshFaceIndices.Add((int)face.A); meshFaceIndices.Add((int)face.B); meshFaceIndices.Add((int)face.C); } }
/// <summary> /// Create a Mesh, with found props /// </summary> /// <param name="positions"></param> /// <param name="textureCoordinates"></param> /// <param name="triangleIndices"></param> /// <param name="normals"></param> /// <param name="tangents"></param> /// <param name="bitangents"></param> /// <param name="material"></param> /// <param name="transforms"></param> private void CreateMesh(Vector3Collection positions, Vector2Collection textureCoordinates, IntCollection triangleIndices, List <Matrix> transforms, out Vector3Collection normals, out Vector3Collection tangents, out Vector3Collection bitangents, MaterialCore material) { ComputeNormals(positions, triangleIndices, out normals); if (textureCoordinates == null) { textureCoordinates = new Vector2Collection(); foreach (var pos in positions) { textureCoordinates.Add(Vector2.One); } } MeshBuilder.ComputeTangents(positions, normals, textureCoordinates, triangleIndices, out tangents, out bitangents); MeshGeometry3D mesh = new MeshGeometry3D() { Positions = positions, Normals = normals, TextureCoordinates = textureCoordinates, Indices = triangleIndices, Tangents = tangents, BiTangents = bitangents }; Object3D ob3d = new Object3D(); ob3d.Geometry = mesh; ob3d.Material = material; ob3d.Transform = transforms; ob3d.Name = "Default"; this.obGroup.Add(ob3d); }
protected BillboardSingleImage3D() { Positions = new Vector3Collection(6); Colors = new Color4Collection(6); TextureCoordinates = new Vector2Collection(6); MaskColor = Color.Transparent; }
public BillboardText3D() { Positions = new Vector3Collection(); Colors = new Color4Collection(); TextureCoordinates = new Vector2Collection(); this.TextInfo = new List<TextInfo>(); var assembly = Assembly.GetExecutingAssembly(); //Read the texture description using(var texDescriptionStream = assembly.GetManifestResourceStream("HelixToolkit.Wpf.SharpDX.Textures.arial.fnt")) { bmpFont = new BitmapFont(); bmpFont.Load(texDescriptionStream); } //Read the texture using(var texImageStream = assembly.GetManifestResourceStream("HelixToolkit.Wpf.SharpDX.Textures.arial.png")) { var image = new BitmapImage(); image.BeginInit(); image.StreamSource = texImageStream; image.EndInit(); Texture = image; } }
private static List <MeshGeometryModel3D> GenerateMeshGeometryModels(MGEOFile mgeo) { List <MeshGeometryModel3D> models = new List <MeshGeometryModel3D>(mgeo.Objects.Count); foreach (MGEOObject mgeoModel in mgeo.Objects) { IntCollection indices = new IntCollection(mgeoModel.Indices.Select(x => (int)x).AsEnumerable()); Vector3Collection vertices = new Vector3Collection(mgeoModel.Vertices.Count); Vector2Collection uvs = new Vector2Collection(mgeoModel.Vertices.Count); foreach (MGEOVertex vertex in mgeoModel.Vertices) { vertices.Add(new dxVector3(vertex.Position.X, vertex.Position.Y, vertex.Position.Z)); uvs.Add(new dxVector2(vertex.DiffuseUV.X, vertex.DiffuseUV.Y)); } MeshGeometry3D meshGeometry = new MeshGeometry3D() { Indices = indices, Positions = vertices, TextureCoordinates = uvs }; MeshGeometryModel3D model = new MeshGeometryModel3D() { Geometry = meshGeometry, Material = DiffuseMaterials.Pearl, Name = mgeoModel.Name }; models.Add(model); } return(models); }
public BillboardSingleText3D() { Positions = new Vector3Collection(); Colors = new Color4Collection(); TextureCoordinates = new Vector2Collection(); TextInfo = new TextInfo(); }
public MeshModel(Vector3Collection positions, Vector3Collection normals, IntCollection triangleIndices, Vector2Collection textureCoordinates) { Positions = positions; Normals = normals; TriangleIndices = triangleIndices; TextureCoordinates = textureCoordinates; }
/// <summary> /// Creates a new mesh where no vertices are shared. /// </summary> /// <param name="input"> /// The input mesh. /// </param> /// <returns> /// A new mesh. /// </returns> public static MeshGeometry3D NoSharedVertices(this MeshGeometry3D input) { var p = new Point3DCollection(); var ti = new Int32Collection(); Vector3DCollection n = null; if (input.Normals != null) { n = new Vector3DCollection(); } PointCollection tc = null; if (input.TextureCoordinates != null) { tc = new PointCollection(); } for (var i = 0; i < input.TriangleIndices.Count; i += 3) { var i0 = i; var i1 = i + 1; var i2 = i + 2; var index0 = input.TriangleIndices[i0]; var index1 = input.TriangleIndices[i1]; var index2 = input.TriangleIndices[i2]; var p0 = input.Positions[index0]; var p1 = input.Positions[index1]; var p2 = input.Positions[index2]; p.Add(p0); p.Add(p1); p.Add(p2); ti.Add(i0); ti.Add(i1); ti.Add(i2); if (n != null && input.Normals.Count > 0) { n.Add(input.Normals[index0]); n.Add(input.Normals[index1]); n.Add(input.Normals[index2]); } if (tc != null) { tc.Add(input.TextureCoordinates[index0]); tc.Add(input.TextureCoordinates[index1]); tc.Add(input.TextureCoordinates[index2]); } } #if SHARPDX return(new MeshGeometry3D { Positions = p, TriangleIndices = new IntCollection(ti), Normals = n, TextureCoordinates = tc }); #else return(new MeshGeometry3D { Positions = p, TriangleIndices = ti, Normals = n, TextureCoordinates = tc }); #endif }
public BillboardText3D() { Positions = new Vector3Collection(); Colors = new Color4Collection(); TextureCoordinates = new Vector2Collection(); TextInfo = new List <TextInfo>(); }
public BillboardText3D() { Positions = new Vector3Collection(); Colors = new Color4Collection(); TextureCoordinates = new Vector2Collection(); this.TextInfo = new List <TextInfo>(); var assembly = Assembly.GetExecutingAssembly(); //Read the texture description using (var texDescriptionStream = assembly.GetManifestResourceStream("HelixToolkit.Wpf.SharpDX.Textures.arial.fnt")) { bmpFont = new BitmapFont(); bmpFont.Load(texDescriptionStream); } //Read the texture using (var texImageStream = assembly.GetManifestResourceStream("HelixToolkit.Wpf.SharpDX.Textures.arial.png")) { var image = new BitmapImage(); image.BeginInit(); image.StreamSource = texImageStream; image.EndInit(); Texture = image; } }
public static MeshGeometry3D Merge(params MeshGeometry3D[] meshes) { var positions = new Vector3Collection(); var indices = new IntCollection(); var normals = meshes.All(x => x.Normals != null) ? new Vector3Collection() : null; var colors = meshes.All(x => x.Colors != null) ? new Color4Collection() : null; var textureCoods = meshes.All(x => x.TextureCoordinates != null) ? new Vector2Collection() : null; var tangents = meshes.All(x => x.Tangents != null) ? new Vector3Collection() : null; var bitangents = meshes.All(x => x.BiTangents != null) ? new Vector3Collection() : null; int index = 0; foreach (var part in meshes) { positions.AddRange(part.Positions); indices.AddRange(part.Indices.Select(x => x + index)); index += part.Positions.Count; } if (normals != null) { normals = new Vector3Collection(meshes.SelectMany(x => x.Normals)); } if (colors != null) { colors = new Color4Collection(meshes.SelectMany(x => x.Colors)); } if (textureCoods != null) { textureCoods = new Vector2Collection(meshes.SelectMany(x => x.TextureCoordinates)); } if (tangents != null) { tangents = new Vector3Collection(meshes.SelectMany(x => x.Tangents)); } if (bitangents != null) { bitangents = new Vector3Collection(meshes.SelectMany(x => x.BiTangents)); } var mesh = new MeshGeometry3D() { Positions = positions, Indices = indices, }; mesh.Normals = normals; mesh.Colors = colors; mesh.TextureCoordinates = textureCoods; mesh.Tangents = tangents; mesh.BiTangents = bitangents; return(mesh); }
public static void AssertContains(this Vector2Collection collection, params double[][] points) { Assert.AreEqual(points.Length, collection.Count, "Expected to find {0} points in collection", points.Length); foreach (var point in points) { Assert.IsTrue(collection.Contains(point), "Expected collection to contain point [{0},{1}]", point[0], point[1]); } }
public static IEnumerable <double> ToEnumerable(this Vector2Collection collection) { foreach (var v in collection) { yield return(v.X); yield return(v.Y); } }
public BillboardText3D() { Positions = new Vector3Collection(); Colors = new Color4Collection(); TextureCoordinates = new Vector2Collection(); TextInfo = new List<TextInfo>(); Initialize(); }
public BillboardSingleText3D(float width, float height) { Positions = new Vector3Collection(12); Colors = new Color4Collection(12); TextureCoordinates = new Vector2Collection(12); TextInfo = new TextInfo(); Width = width; Height = height; predefinedSize = true; }
private Vector2Collection ReadTexCoords(BinaryReader reader) { int size = reader.ReadUInt16(); var pts = new Vector2Collection(); for (int i = 0; i < size; i++) { float x = reader.ReadSingle(); float y = reader.ReadSingle(); pts.Add(new Vector2(x, 1 - y)); } return(pts); }
private void CreatePerlinNoise() { float[] noise; MathHelper.GenerateNoiseMap(Width, Height, 8, out noise); Vector2Collection collection = new Vector2Collection(Width * Height); for (int i = 0; i < Width; ++i) { for (int j = 0; j < Height; ++j) { collection.Add(new Vector2(Math.Abs(noise[Width * i + j]), 0)); } } Model.TextureCoordinates = collection; }
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { if (value == null) { throw GetConvertFromException(value); } var source = value as string; if (source != null) { return(Vector2Collection.Parse(source)); } return(base.ConvertFrom(context, culture, value)); }
public static MeshGeometry3D GetRect(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) { var positions = new Vector3Collection(); var triangleIndices = new HelixToolkit.Wpf.SharpDX.Core.IntCollection(); var normals = new Vector3Collection(); //private Vector3Collection tangents; //private Vector3Collection bitangents; var textureCoordinates = new Vector2Collection(); var widthOrientation = new Vector3(0, 0, 1); var heightOrientation = new Vector3(0, 1, 0); positions.Add(p0); positions.Add(p1); positions.Add(p2); positions.Add(p3); normals.Add(new Vector3(1, 0, 0)); normals.Add(new Vector3(1, 0, 0)); normals.Add(new Vector3(1, 0, 0)); normals.Add(new Vector3(1, 0, 0)); textureCoordinates.Add(new Vector2(0, 0)); textureCoordinates.Add(new Vector2(1, 0)); textureCoordinates.Add(new Vector2(1, 1)); textureCoordinates.Add(new Vector2(0, 1)); triangleIndices.Add(2); triangleIndices.Add(1); triangleIndices.Add(0); triangleIndices.Add(0); triangleIndices.Add(3); triangleIndices.Add(2); return(new MeshGeometry3D() { Positions = positions, Indices = triangleIndices, Normals = normals, TextureCoordinates = textureCoordinates }); }
public static IEnumerable <GroupNode> LoadMapMGEO(MGEOFile mgeo, MapData mapData, string mapPath) { foreach (MGEOObject mgeoModel in mgeo.Objects) { IntCollection indices = new IntCollection(mgeoModel.Indices.Select(x => (int)x).AsEnumerable()); Vector3Collection vertices = new Vector3Collection(mgeoModel.Vertices.Count); Vector2Collection uvs = new Vector2Collection(mgeoModel.Vertices.Count); foreach (MGEOVertex vertex in mgeoModel.Vertices) { vertices.Add(new dxVector3(vertex.Position.X, vertex.Position.Y, vertex.Position.Z)); uvs.Add(new dxVector2(vertex.DiffuseUV.X, vertex.DiffuseUV.Y)); } foreach (MGEOSubmesh submesh in mgeoModel.Submeshes) { GroupNode groupNode = new GroupNode() { Name = mgeoModel.Name }; MeshGeometry3D submeshGeometry3D = new MeshGeometry3D() { Indices = indices.GetRange((int)submesh.StartIndex, (int)submesh.IndexCount) as IntCollection, Positions = vertices, TextureCoordinates = uvs }; DiffuseMaterial diffuseMaterial = new DiffuseMaterial() { Name = submesh.Material, DiffuseMap = CreateMaterial(submesh.Material, mapData, mapPath), EnableUnLit = true }; groupNode.AddChildNode(new MeshNode() { Name = mgeoModel.Name + "|" + submesh.Material, Geometry = submeshGeometry3D, Material = diffuseMaterial }); yield return(groupNode); } } }
public static Vector2Collection Parse(string source) { IFormatProvider formatProvider = CultureInfo.InvariantCulture; var th = new TokenizerHelper(source, formatProvider); var resource = new Vector2Collection(); Vector2 value; while (th.NextToken()) { value = new Vector2( Convert.ToSingle(th.GetCurrentToken(), formatProvider), Convert.ToSingle(th.NextTokenRequired(), formatProvider)); resource.Add(value); } return(resource); }
public static MeshGeometry3D GetRect(Vector3 center, float width, float height, Vector3 widthOrientation, Vector3 heightOrientation) { var positions = new Vector3Collection(); var triangleIndices = new HelixToolkit.Wpf.SharpDX.Core.IntCollection(); var normals = new Vector3Collection(); //private Vector3Collection tangents; //private Vector3Collection bitangents; var textureCoordinates = new Vector2Collection(); positions.Add(center - widthOrientation * width / 2 - heightOrientation * height / 2); positions.Add(center + widthOrientation * width / 2 - heightOrientation * height / 2); positions.Add(center + widthOrientation * width / 2 + heightOrientation * height / 2); positions.Add(center - widthOrientation * width / 2 + heightOrientation * height / 2); normals.Add(new Vector3(1, 0, 0)); normals.Add(new Vector3(1, 0, 0)); normals.Add(new Vector3(1, 0, 0)); normals.Add(new Vector3(1, 0, 0)); textureCoordinates.Add(new Vector2(1, 1)); textureCoordinates.Add(new Vector2(0, 1)); textureCoordinates.Add(new Vector2(0, 0)); textureCoordinates.Add(new Vector2(1, 0)); triangleIndices.Add(2); triangleIndices.Add(1); triangleIndices.Add(0); triangleIndices.Add(0); triangleIndices.Add(3); triangleIndices.Add(2); return(new MeshGeometry3D() { Positions = positions, Indices = triangleIndices, Normals = normals, TextureCoordinates = textureCoordinates }); }
public BillboardText3D() { Positions = new Vector3Collection(); Colors = new Color4Collection(); TextureCoordinates = new Vector2Collection(); this.TextInfo = new List <TextInfo>(); var assembly = Assembly.GetExecutingAssembly(); var texDescriptionFilePath = Path.GetTempFileName(); var texImageFilePath = Path.GetTempFileName(); //Read the texture description var texDescriptionStream = assembly.GetManifestResourceStream("HelixToolkit.Wpf.SharpDX.Textures.arial.fnt"); using (var fileStream = File.Create(texDescriptionFilePath)) { texDescriptionStream.CopyTo(fileStream); } bmpFont = BitmapFontLoader.LoadFontFromFile(texDescriptionFilePath); //Read the texture var texImageStream = assembly.GetManifestResourceStream("HelixToolkit.Wpf.SharpDX.Textures.arial.png"); using (var fileStream = File.Create(texImageFilePath)) { texImageStream.CopyTo(fileStream); } Texture = new BitmapImage(new Uri(texImageFilePath)); //Cleanup the temp files if (File.Exists(texDescriptionFilePath)) { File.Delete(texDescriptionFilePath); } }
public static MeshGeometry3D GetCube(Vector3 minimum, Vector3 maximum) { var positions = new Vector3Collection(); var triangleIndices = new HelixToolkit.Wpf.SharpDX.Core.IntCollection(); var normals = new Vector3Collection(); var textureCoordinates = new Vector2Collection(); positions.Add(new Vector3(minimum.X, minimum.Y, minimum.Z)); //0 positions.Add(new Vector3(maximum.X, minimum.Y, minimum.Z)); //1 positions.Add(new Vector3(minimum.X, maximum.Y, minimum.Z)); //2 positions.Add(new Vector3(minimum.X, minimum.Y, maximum.Z)); //3 positions.Add(new Vector3(maximum.X, maximum.Y, minimum.Z)); //4 positions.Add(new Vector3(maximum.X, minimum.Y, maximum.Z)); //5 positions.Add(new Vector3(minimum.X, maximum.Y, maximum.Z)); //6 positions.Add(new Vector3(maximum.X, maximum.Y, maximum.Z)); //7 triangleIndices.AddRange(new[] { 0, 5, 3, 0, 1, 5 }); triangleIndices.AddRange(new[] { 1, 7, 5, 1, 4, 7 }); triangleIndices.AddRange(new[] { 4, 7, 2, 7, 6, 2 }); triangleIndices.AddRange(new[] { 6, 3, 0, 6, 0, 2 }); triangleIndices.AddRange(new[] { 6, 3, 5, 5, 7, 6 }); triangleIndices.AddRange(new[] { 0, 1, 2, 2, 1, 4 }); for (int i = 0; i < positions.Count; i++) { normals.Add(new Vector3(1, 0, 0)); textureCoordinates.Add(new Vector2(0, 0)); } return(new MeshGeometry3D() { Positions = positions, Indices = triangleIndices, Normals = normals, TextureCoordinates = textureCoordinates }); }
public BillboardText3D() { Positions = new Vector3Collection(); Colors = new Color4Collection(); TextureCoordinates = new Vector2Collection(); this.TextInfo = new List<TextInfo>(); var assembly = Assembly.GetExecutingAssembly(); var texDescriptionFilePath = Path.GetTempFileName(); var texImageFilePath = Path.GetTempFileName(); //Read the texture description var texDescriptionStream = assembly.GetManifestResourceStream("HelixToolkit.Wpf.SharpDX.Textures.arial.fnt"); using (var fileStream = File.Create(texDescriptionFilePath)) { texDescriptionStream.CopyTo(fileStream); } bmpFont = BitmapFontLoader.LoadFontFromFile(texDescriptionFilePath); //Read the texture var texImageStream = assembly.GetManifestResourceStream("HelixToolkit.Wpf.SharpDX.Textures.arial.png"); using (var fileStream = File.Create(texImageFilePath)) { texImageStream.CopyTo(fileStream); } Texture = new BitmapImage(new Uri(texImageFilePath)); //Cleanup the temp files if (File.Exists(texDescriptionFilePath)) { File.Delete(texDescriptionFilePath); } }
protected void CalculateTextureCoordinates() { var uvCollection = new Vector2[Positions.Count]; for (var i = 0; i < TriangleIndices.Count; i += 3) { var a = Positions[TriangleIndices[i]]; var b = Positions[TriangleIndices[i + 1]]; var c = Positions[TriangleIndices[i + 2]]; var side1 = b - a; var side2 = c - a; var n = Vector3.Cross(side1, side2); n = new Vector3(Math.Abs(n.X), Math.Abs(n.Normalized().Y), Math.Abs(n.Normalized().Z)); if (n.X > n.Y && n.X > n.Z) { uvCollection[TriangleIndices[i]] = new Vector2(Positions[TriangleIndices[i]].Z, Positions[TriangleIndices[i]].Y); uvCollection[TriangleIndices[i + 1]] = new Vector2(Positions[TriangleIndices[i + 1]].Z, Positions[TriangleIndices[i + 1]].Y); uvCollection[TriangleIndices[i + 2]] = new Vector2(Positions[TriangleIndices[i + 2]].Z, Positions[TriangleIndices[i + 2]].Y); } else if (n.Y > n.X && n.Y > n.Z) { uvCollection[TriangleIndices[i]] = new Vector2(Positions[TriangleIndices[i]].X, Positions[TriangleIndices[i]].Z); uvCollection[TriangleIndices[i + 1]] = new Vector2(Positions[TriangleIndices[i + 1]].X, Positions[TriangleIndices[i + 1]].Z); uvCollection[TriangleIndices[i + 2]] = new Vector2(Positions[TriangleIndices[i + 2]].X, Positions[TriangleIndices[i + 2]].Z); } else if (n.Z > n.X && n.Z > n.Y) { uvCollection[TriangleIndices[i]] = new Vector2(Positions[TriangleIndices[i]].X, Positions[TriangleIndices[i]].Y); uvCollection[TriangleIndices[i + 1]] = new Vector2(Positions[TriangleIndices[i + 1]].X, Positions[TriangleIndices[i + 1]].Y); uvCollection[TriangleIndices[i + 2]] = new Vector2(Positions[TriangleIndices[i + 2]].X, Positions[TriangleIndices[i + 2]].Y); } } TextureCoordinates = new Vector2Collection(uvCollection); }
/// <summary> /// Parses the MDL file to obtain model information /// </summary> /// <param name="selectedItem">The currently selected item</param> /// <param name="selectedRace">The currently selected race</param> /// <param name="selectedBody">The currently selected body</param> /// <param name="selectedPart">The currently selected part</param> /// <param name="selectedCategory">The items category </param> public MDL(ItemData selectedItem, string selectedCategory, string selectedRace, string selectedBody, string selectedPart) { string itemType = Helper.GetCategoryType(selectedCategory); string MDLFolder = ""; if (itemType.Equals("weapon") || itemType.Equals("food")) { if (selectedPart.Equals("Secondary")) { MDLFolder = string.Format(Strings.WeapMDLFolder, selectedItem.SecondaryModelID, selectedItem.SecondaryModelBody); MDLFile = string.Format(Strings.WeapMDLFile, selectedItem.SecondaryModelID, selectedItem.SecondaryModelBody); } else { MDLFolder = string.Format(Strings.WeapMDLFolder, selectedItem.PrimaryModelID, selectedItem.PrimaryModelBody); MDLFile = string.Format(Strings.WeapMDLFile, selectedItem.PrimaryModelID, selectedItem.PrimaryModelBody); } } else if (itemType.Equals("accessory")) { MDLFolder = string.Format(Strings.AccMDLFolder, selectedItem.PrimaryModelID); MDLFile = string.Format(Strings.AccMDLFile, selectedRace, selectedItem.PrimaryModelID, Info.slotAbr[selectedCategory]); } else if (itemType.Equals("character")) { if (selectedItem.ItemName.Equals(Strings.Body)) { MDLFolder = string.Format(Strings.BodyMDLFolder, selectedRace, selectedBody.PadLeft(4, '0')); MDLFile = string.Format(Strings.BodyMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart); } else if (selectedItem.ItemName.Equals(Strings.Face)) { MDLFolder = string.Format(Strings.FaceMDLFolder, selectedRace, selectedBody.PadLeft(4, '0')); MDLFile = string.Format(Strings.FaceMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart); } else if (selectedItem.ItemName.Equals(Strings.Hair)) { MDLFolder = string.Format(Strings.HairMDLFolder, selectedRace, selectedBody.PadLeft(4, '0')); MDLFile = string.Format(Strings.HairMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart); } else if (selectedItem.ItemName.Equals(Strings.Tail)) { MDLFolder = string.Format(Strings.TailMDLFolder, selectedRace, selectedBody.PadLeft(4, '0')); MDLFile = string.Format(Strings.TailMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart); } } else if (itemType.Equals("monster")) { bool isDemiHuman = false; if (selectedItem.PrimaryMTRLFolder != null) { isDemiHuman = selectedItem.PrimaryMTRLFolder.Contains("demihuman"); } string ID = ""; string body = ""; if (selectedCategory.Equals(Strings.Pets)) { int part = 1; if (selectedItem.ItemName.Equals(Strings.Selene) || selectedItem.ItemName.Equals(Strings.Bishop_Autoturret)) { part = 2; } ID = Info.petID[selectedItem.ItemName]; body = part.ToString().PadLeft(4, '0'); } else { ID = selectedItem.PrimaryModelID.PadLeft(4, '0'); body = selectedItem.PrimaryModelBody; } if (isDemiHuman) { MDLFolder = string.Format(Strings.DemiMDLFolder, ID, body); MDLFile = string.Format(Strings.DemiMDLFile, ID, body, selectedPart); } else { MDLFolder = string.Format(Strings.MonsterMDLFolder, ID, body); MDLFile = string.Format(Strings.MonsterMDLFile, ID, body); } } else { MDLFolder = string.Format(Strings.EquipMDLFolder, selectedItem.PrimaryModelID); if (selectedPart.Equals("-")) { MDLFile = string.Format(Strings.EquipMDLFile, selectedRace, selectedItem.PrimaryModelID, Info.slotAbr[selectedCategory]); } else { MDLFile = string.Format(Strings.EquipMDLFile, selectedRace, selectedItem.PrimaryModelID, selectedPart); } } fullPath = MDLFolder + "/" + MDLFile; int offset = Helper.GetDataOffset(FFCRC.GetHash(MDLFolder), FFCRC.GetHash(MDLFile), Strings.ItemsDat); if (offset == 0) { if (itemType.Equals("weapon")) { if (selectedPart.Equals("Secondary")) { MDLFolder = string.Format(Strings.EquipMDLFolder, selectedItem.SecondaryModelID); MDLFile = string.Format(Strings.EquipMDLFile, "0101", selectedItem.SecondaryModelID, Info.slotAbr[Strings.Hands]); offset = Helper.GetDataOffset(FFCRC.GetHash(MDLFolder), FFCRC.GetHash(MDLFile), Strings.ItemsDat); } } } int datNum = ((offset / 8) & 0x000f) / 2; var MDLDatData = Helper.GetType3DecompressedData(offset, datNum, Strings.ItemsDat); using (BinaryReader br = new BinaryReader(new MemoryStream(MDLDatData.Item1))) { // The size of the header + (size of the mesh information block (136 bytes) * the number of meshes) + padding br.BaseStream.Seek(64 + 136 * MDLDatData.Item2 + 4, SeekOrigin.Begin); var modelStringCount = br.ReadInt32(); var stringBlockSize = br.ReadInt32(); var stringBlock = br.ReadBytes(stringBlockSize); var unknown = br.ReadBytes(4); var totalMeshCount = br.ReadInt16(); var attributeStringCount = br.ReadInt16(); var meshPartsCount = br.ReadInt16(); var materialStringCount = br.ReadInt16(); var boneStringCount = br.ReadInt16(); var boneListCount = br.ReadInt16(); var unknown1 = br.ReadInt16(); var unknown2 = br.ReadInt16(); var unknown3 = br.ReadInt16(); var unknown4 = br.ReadInt16(); var unknown5 = br.ReadInt16(); var unknown6 = br.ReadInt16(); br.ReadBytes(10); var unknown7 = br.ReadInt16(); br.ReadBytes(16); using (BinaryReader br1 = new BinaryReader(new MemoryStream(stringBlock))) { br1.BaseStream.Seek(0, SeekOrigin.Begin); for (int i = 0; i < attributeStringCount; i++) { while (br1.ReadByte() != 0) { //extract each atribute string here } } for (int i = 0; i < boneStringCount; i++) { byte b; List <byte> boneName = new List <byte>(); while ((b = br1.ReadByte()) != 0) { boneName.Add(b); } string bone = Encoding.ASCII.GetString(boneName.ToArray()); bone = bone.Replace("\0", ""); boneStrings.Add(bone); } for (int i = 0; i < materialStringCount; i++) { byte b; List <byte> name = new List <byte>(); while ((b = br1.ReadByte()) != 0) { name.Add(b); } string material = Encoding.ASCII.GetString(name.ToArray()); material = material.Replace("\0", ""); materialStrings.Add(material); } } br.ReadBytes(32 * unknown5); for (int i = 0; i < 3; i++) { LevelOfDetail LoD = new LevelOfDetail(); LoD.MeshOffset = br.ReadInt16(); LoD.MeshCount = br.ReadInt16(); br.ReadBytes(40); LoD.VertexDataSize = br.ReadInt32(); LoD.IndexDataSize = br.ReadInt32(); LoD.VertexOffset = br.ReadInt32(); LoD.IndexOffset = br.ReadInt32(); modelData.LoD.Add(LoD); } var savePos = br.BaseStream.Position; for (int i = 0; i < modelData.LoD.Count; i++) { List <MeshDataInfo> meshInfoList = new List <MeshDataInfo>(); for (int j = 0; j < modelData.LoD[i].MeshCount; j++) { modelData.LoD[i].MeshList.Add(new Mesh()); meshInfoList.Clear(); br.BaseStream.Seek((i * 136) + 68, SeekOrigin.Begin); var dataBlockNum = br.ReadByte(); while (dataBlockNum != 255) { MeshDataInfo meshInfo = new MeshDataInfo() { VertexDataBlock = dataBlockNum, Offset = br.ReadByte(), DataType = br.ReadByte(), UseType = br.ReadByte() }; meshInfoList.Add(meshInfo); br.ReadBytes(4); dataBlockNum = br.ReadByte(); } modelData.LoD[i].MeshList[j].MeshDataInfoList = meshInfoList.ToArray(); } } br.BaseStream.Seek(savePos, SeekOrigin.Begin); for (int x = 0; x < modelData.LoD.Count; x++) { for (int i = 0; i < modelData.LoD[x].MeshCount; i++) { MeshInfo meshInfo = new MeshInfo() { VertexCount = br.ReadInt32(), IndexCount = br.ReadInt32(), MaterialNum = br.ReadInt16(), MeshPartOffset = br.ReadInt16(), MeshPartCount = br.ReadInt16(), BoneListIndex = br.ReadInt16(), IndexDataOffset = br.ReadInt32() }; for (int j = 0; j < 3; j++) { meshInfo.VertexDataOffsets.Add(br.ReadInt32()); } for (int k = 0; k < 3; k++) { meshInfo.VertexSizes.Add(br.ReadByte()); } meshInfo.VertexDataBlockCount = br.ReadByte(); modelData.LoD[x].MeshList[i].MeshInfo = meshInfo; } } br.ReadBytes(attributeStringCount * 4); br.ReadBytes(unknown6 * 20); for (int i = 0; i < modelData.LoD.Count; i++) { foreach (var mesh in modelData.LoD[i].MeshList) { for (int j = 0; j < mesh.MeshInfo.MeshPartCount; j++) { MeshPart meshPart = new MeshPart() { IndexOffset = br.ReadInt32(), IndexCount = br.ReadInt32(), Attributes = br.ReadInt32(), BoneOffset = br.ReadInt16(), BoneCount = br.ReadInt16() }; mesh.MeshPartList.Add(meshPart); } } } br.ReadBytes(unknown7 * 12); br.ReadBytes(materialStringCount * 4); br.ReadBytes(boneStringCount * 4); for (int i = 0; i < boneListCount; i++) { Bones bones = new Bones(); for (int j = 0; j < 64; j++) { bones.BoneData.Add(br.ReadInt16()); } bones.BoneCount = br.ReadInt32(); modelData.BoneSet.Add(bones); } //br.ReadBytes(unknown1 * 16); Dictionary <int, int> indexMin = new Dictionary <int, int>(); Dictionary <int, List <int> > extraIndices = new Dictionary <int, List <int> >(); List <ExtraIndex> indexCounts = new List <ExtraIndex>(); var pCount = 0; var pCount1 = 0; var pCount2 = 0; if (unknown1 > 0) { for (int i = 0; i < unknown1; i++) { //not sure br.ReadBytes(4); //LoD[0] Extra Data Index var p1 = br.ReadUInt16(); //LoD[1] Extra Data Index var p2 = br.ReadUInt16(); //LoD[2] Extra Data Index var p3 = br.ReadUInt16(); //LoD[0] Extra Data Part Count var p1n = br.ReadUInt16(); pCount += p1n; //LoD[1] Extra Data Part Count var p2n = br.ReadUInt16(); pCount1 += p2n; //LoD[2] Extra Data Part Count var p3n = br.ReadUInt16(); pCount2 += p3n; } } Dictionary <int, int> indexLoc = new Dictionary <int, int>(); if (unknown1 > 0) { for (int i = 0; i < modelData.LoD[0].MeshCount; i++) { var ido = modelData.LoD[0].MeshList[i].MeshInfo.IndexDataOffset; indexLoc.Add(ido, i); } } List <int> maskCounts = new List <int>(); Dictionary <int, int> totalExtraCounts = new Dictionary <int, int>(); if (unknown2 > 0) { for (int i = 0; i < pCount; i++) { //Index Offset Start var m1 = br.ReadInt32(); var iLoc = 0; if (indexLoc.ContainsKey(m1)) { iLoc = indexLoc[m1]; } //index count var mCount = br.ReadInt32(); //index offset in unk3 var mOffset = br.ReadInt32(); indexCounts.Add(new ExtraIndex() { IndexLocation = iLoc, IndexCount = mCount }); maskCounts.Add(mCount); } br.ReadBytes((pCount1 + pCount2) * 12); } int totalLoD0MaskCount = 0; if (unknown2 > 0) { for (int i = 0; i < pCount; i++) { totalLoD0MaskCount += maskCounts[i]; } } if (unknown3 > 0) { var unk3Remainder = (unknown3 * 4) - (totalLoD0MaskCount * 4); foreach (var ic in indexCounts) { HashSet <int> mIndexList = new HashSet <int>(); for (int i = 0; i < ic.IndexCount; i++) { //index its replacing? attatched to? br.ReadBytes(2); //extra index following last equipment index var mIndex = br.ReadInt16(); mIndexList.Add(mIndex); if (extraIndices.ContainsKey(ic.IndexLocation)) { extraIndices[ic.IndexLocation].Add(mIndex); } else { extraIndices.Add(ic.IndexLocation, new List <int>() { mIndex }); } } if (totalExtraCounts.ContainsKey(ic.IndexLocation)) { totalExtraCounts[ic.IndexLocation] += mIndexList.Count; } else { totalExtraCounts.Add(ic.IndexLocation, mIndexList.Count); } } //the rest of unk3 br.ReadBytes(unk3Remainder); } if (unknown3 > 0) { foreach (var ei in extraIndices) { indexMin.Add(ei.Key, ei.Value.Min()); } extraIndexData.indexCounts = indexCounts; extraIndexData.indexMin = indexMin; extraIndexData.totalExtraCounts = totalExtraCounts; extraIndexData.extraIndices = extraIndices; modelData.ExtraData = extraIndexData; } //br.ReadBytes(unknown3 * 4); var boneIndexSize = br.ReadInt32(); for (int i = 0; i < boneIndexSize / 2; i++) { modelData.BoneIndicies.Add(br.ReadInt16()); } int padding = br.ReadByte(); br.ReadBytes(padding); for (int i = 0; i < 4; i++) { ModelMaterial.BoundingBox boundingBox = new ModelMaterial.BoundingBox(); for (int j = 0; j < 4; j++) { boundingBox.PointA.Add(br.ReadSingle()); } for (int k = 0; k < 4; k++) { boundingBox.PointB.Add(br.ReadSingle()); } modelData.BoundingBoxes.Add(boundingBox); } //float4x4 for (int i = 0; i < boneStringCount; i++) { boneTransforms.Add(br.ReadSingle()); boneTransforms.Add(br.ReadSingle()); boneTransforms.Add(br.ReadSingle()); boneTransforms.Add(br.ReadSingle()); boneTransforms.Add(br.ReadSingle()); boneTransforms.Add(br.ReadSingle()); boneTransforms.Add(br.ReadSingle()); boneTransforms.Add(br.ReadSingle()); } for (int i = 0; i < 3; i++) { for (int j = 0; j < modelData.LoD[i].MeshCount; j++) { Mesh mesh = modelData.LoD[i].MeshList[j]; for (int k = 0; k < mesh.MeshInfo.VertexDataBlockCount; k++) { br.BaseStream.Seek(modelData.LoD[i].VertexOffset + mesh.MeshInfo.VertexDataOffsets[k], SeekOrigin.Begin); mesh.MeshVertexData.Add(br.ReadBytes(mesh.MeshInfo.VertexSizes[k] * mesh.MeshInfo.VertexCount)); } br.BaseStream.Seek(modelData.LoD[i].IndexOffset + (mesh.MeshInfo.IndexDataOffset * 2), SeekOrigin.Begin); mesh.IndexData = br.ReadBytes(2 * mesh.MeshInfo.IndexCount); } } int vertex = 0, coordinates = 0, normals = 0, tangents = 0, colors = 0, blendWeights = 0, blendIndices = 0; for (int i = 0; i < modelData.LoD[0].MeshCount; i++) { objBytes.Clear(); var vertexList = new Vector3Collection(); var texCoordList = new Vector2Collection(); var texCoordList2 = new Vector2Collection(); var normalList = new Vector3Collection(); var tangentList = new Vector3Collection(); var colorsList = new Color4Collection(); var indexList = new IntCollection(); var blendWeightList = new List <float>(); var blendWeightList2 = new List <float[]>(); var blendIndicesList = new List <int>(); var blendIndicesList2 = new List <int[]>(); var weightCounts = new List <int>(); Mesh mesh = modelData.LoD[0].MeshList[i]; MeshDataInfo[] meshDataInfoList = mesh.MeshDataInfoList; int c = 0; foreach (var meshDataInfo in meshDataInfoList) { if (meshDataInfo.UseType == 0) { vertex = c; } else if (meshDataInfo.UseType == 1) { blendWeights = c; } else if (meshDataInfo.UseType == 2) { blendIndices = c; } else if (meshDataInfo.UseType == 3) { normals = c; } else if (meshDataInfo.UseType == 4) { coordinates = c; } else if (meshDataInfo.UseType == 6) { tangents = c; } else if (meshDataInfo.UseType == 7) { colors = c; } c++; } /* * ----------------- * Vertex * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[vertex].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[vertex].VertexDataBlock] + meshDataInfoList[vertex].Offset, SeekOrigin.Begin); Vector3 vVector = new Vector3(); if (meshDataInfoList[vertex].DataType == 13 || meshDataInfoList[vertex].DataType == 14) { System.Half h1 = System.Half.ToHalf((ushort)br1.ReadInt16()); System.Half h2 = System.Half.ToHalf((ushort)br1.ReadInt16()); System.Half h3 = System.Half.ToHalf((ushort)br1.ReadInt16()); float x = HalfHelper.HalfToSingle(h1); float y = HalfHelper.HalfToSingle(h2); float z = HalfHelper.HalfToSingle(h3); vVector = new Vector3(x, y, z); objBytes.Add("v " + x.ToString("N5") + " " + y.ToString("N5") + " " + z.ToString("N5") + " "); } else if (meshDataInfoList[vertex].DataType == 2) { var x = BitConverter.ToSingle(br1.ReadBytes(4), 0); var y = BitConverter.ToSingle(br1.ReadBytes(4), 0); var z = BitConverter.ToSingle(br1.ReadBytes(4), 0); vVector = new Vector3(x, y, z); objBytes.Add("v " + x.ToString("N5") + " " + y.ToString("N5") + " " + z.ToString("N5") + " "); } vertexList.Add(vVector); } } /* * ----------------- * Blend Weight * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[blendWeights].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[blendWeights].VertexDataBlock] + meshDataInfoList[blendWeights].Offset, SeekOrigin.Begin); float x = br1.ReadByte() / 255.0f; float y = br1.ReadByte() / 255.0f; float z = br1.ReadByte() / 255.0f; float w = br1.ReadByte() / 255.0f; int count = 0; if (x != 0) { blendWeightList.Add(x); count++; if (y != 0) { blendWeightList.Add(y); count++; if (z != 0) { blendWeightList.Add(z); count++; if (w != 0) { blendWeightList.Add(w); count++; } } } } if (count == 1) { blendWeightList2.Add(new float[] { x }); } else if (count == 2) { blendWeightList2.Add(new float[] { x, y }); } else if (count == 3) { blendWeightList2.Add(new float[] { x, y, z }); } else if (count == 4) { blendWeightList2.Add(new float[] { x, y, z, w }); } weightCounts.Add(count); } } /* * ----------------- * Blend Index * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[blendIndices].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[blendIndices].VertexDataBlock] + meshDataInfoList[blendIndices].Offset, SeekOrigin.Begin); int x = br1.ReadByte(); int y = br1.ReadByte(); int z = br1.ReadByte(); int w = br1.ReadByte(); if (weightCounts[j] == 1) { blendIndicesList.Add(x); blendIndicesList2.Add(new int[] { x }); } else if (weightCounts[j] == 2) { blendIndicesList.Add(x); blendIndicesList.Add(y); blendIndicesList2.Add(new int[] { x, y }); } else if (weightCounts[j] == 3) { blendIndicesList.Add(x); blendIndicesList.Add(y); blendIndicesList.Add(z); blendIndicesList2.Add(new int[] { x, y, z }); } else if (weightCounts[j] == 4) { blendIndicesList.Add(x); blendIndicesList.Add(y); blendIndicesList.Add(z); blendIndicesList.Add(w); blendIndicesList2.Add(new int[] { x, y, z, w }); } } } /* * ----------------- * Texture Coordinates * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[coordinates].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[coordinates].VertexDataBlock] + meshDataInfoList[coordinates].Offset, SeekOrigin.Begin); float x = 0; float y = 0; float z = 0; float w = 0; if (meshDataInfoList[coordinates].DataType == 13 || meshDataInfoList[coordinates].DataType == 14) { var sx = (ushort)br1.ReadInt16(); var sy = (ushort)br1.ReadInt16(); var sz = (ushort)br1.ReadInt16(); var sw = (ushort)br1.ReadInt16(); var h1 = new SharpDX.Half(sx); var h2 = new SharpDX.Half(sy); var h3 = new SharpDX.Half(sz); var h4 = new SharpDX.Half(sw); x = h1; y = h2; z = h3; w = h4; } else if (meshDataInfoList[coordinates].DataType == 1) { x = br1.ReadSingle(); y = br1.ReadSingle(); } else { x = br1.ReadSingle(); y = br1.ReadSingle(); z = br1.ReadSingle(); w = br1.ReadSingle(); } var ox = x - Math.Truncate(x); var oy = y - Math.Truncate(y); objBytes.Add("vt " + ox.ToString("N5") + " " + (1 - y).ToString("N5") + " "); texCoordList.Add(new Vector2(x, y)); texCoordList2.Add(new Vector2(z, w)); } } /* * ----------------- * Normals * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[normals].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[normals].VertexDataBlock] + meshDataInfoList[normals].Offset, SeekOrigin.Begin); float x = 0; float y = 0; float z = 0; float w = 0; if (meshDataInfoList[normals].DataType == 13 || meshDataInfoList[normals].DataType == 14) { System.Half h1 = System.Half.ToHalf((ushort)br1.ReadInt16()); System.Half h2 = System.Half.ToHalf((ushort)br1.ReadInt16()); System.Half h3 = System.Half.ToHalf((ushort)br1.ReadInt16()); System.Half h4 = System.Half.ToHalf((ushort)br1.ReadInt16()); x = HalfHelper.HalfToSingle(h1); y = HalfHelper.HalfToSingle(h2); z = HalfHelper.HalfToSingle(h3); w = HalfHelper.HalfToSingle(h4); } else { x = br1.ReadSingle(); y = br1.ReadSingle(); z = br1.ReadSingle(); } var nv = new Vector3(x, y, z); objBytes.Add("vn " + x.ToString("N5") + " " + y.ToString("N5") + " " + z.ToString("N5") + " "); normalList.Add(nv); } } /* * ----------------- * Tangents * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[tangents].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[tangents].VertexDataBlock] + meshDataInfoList[tangents].Offset, SeekOrigin.Begin); int x = br1.ReadByte(); int y = br1.ReadByte(); int z = br1.ReadByte(); int w = br1.ReadByte(); var x1 = x * 2 / 255f - 1f; var y1 = y * 2 / 255f - 1f; var z1 = z * 2 / 255f - 1f; var w1 = w * 2 / 255f - 1f; var nv = new Vector3(x1, y1, z1); tangentList.Add(nv); } } /* * ----------------- * Vertex Color * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[colors].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[colors].VertexDataBlock] + meshDataInfoList[colors].Offset, SeekOrigin.Begin); int a = br1.ReadByte(); int r = br1.ReadByte(); int g = br1.ReadByte(); int b = br1.ReadByte(); colorsList.Add(new Color4(r, g, b, a)); } } /* * ----------------- * Index * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.IndexData))) { for (int j = 0; j < mesh.MeshInfo.IndexCount; j += 3) { int i1 = br1.ReadInt16(); int i2 = br1.ReadInt16(); int i3 = br1.ReadInt16(); objBytes.Add("f " + (i1 + 1) + "/" + (i1 + 1) + "/" + (i1 + 1) + " " + (i2 + 1) + "/" + (i2 + 1) + "/" + (i2 + 1) + " " + (i3 + 1) + "/" + (i3 + 1) + "/" + (i3 + 1) + " "); indexList.Add(i1); indexList.Add(i2); indexList.Add(i3); } } ModelMeshData modelMeshData = new ModelMeshData() { Vertices = vertexList, Normals = normalList, TextureCoordinates = texCoordList, TextureCoordinates2 = texCoordList2, BiTangents = tangentList, Indices = indexList, VertexColors = colorsList, OBJFileData = objBytes.ToArray(), BoneStrings = boneStrings, BoneIndices = modelData.BoneIndicies, BoneTransforms = boneTransforms, BlendWeights = blendWeightList, BlendIndices = blendIndicesList, WeightCounts = weightCounts, MeshPartList = mesh.MeshPartList, BlendIndicesArrayList = blendIndicesList2, BlendWeightsArrayList = blendWeightList2, MaterialNum = mesh.MeshInfo.MaterialNum, MeshPartCount = mesh.MeshInfo.MeshPartCount, MeshPartOffset = mesh.MeshInfo.MeshPartOffset }; meshList.Add(modelMeshData); } } }
///////////////////////////////////////////////////////////////////////////////////////////// //// below all functions taken from "Helix 3D Toolkit" MeshBuilder ///////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Gets a circle section (cached). /// </summary> /// <param name="thetaDiv"> /// The number of division. /// </param> /// <param name="closed"> /// Is the circle closed? /// If true, the last point will not be at the same position than the first one. /// </param> /// <returns> /// A circle. /// </returns> public static IList<Vector2> GetCircle(int thetaDiv, bool closed = false) { IList<Vector2> circle = null; // If the circle can't be found in one of the two caches if ((!closed && !CircleCache.TryGetValue(thetaDiv, out circle)) || (closed && !ClosedCircleCache.TryGetValue(thetaDiv, out circle))) { circle = new Vector2Collection(); // Add to the cache if (!closed) { CircleCache.TryAdd(thetaDiv, circle); } else { ClosedCircleCache.TryAdd(thetaDiv, circle); } // Determine the angle steps var num = closed ? thetaDiv : thetaDiv - 1; for (int i = 0; i < thetaDiv; i++) { double theta = Math.PI * 2 * ((double)i / num); circle.Add(new Vector2((float)Math.Cos(theta), (float)-Math.Sin(theta))); } } // Since Vector2Collection is not Freezable, // return new IList<Vector> to avoid manipulation of the Cached Values IList<Vector2> result = new List<Vector2>(); foreach (var point in circle) { result.Add(new Vector2(point.X, point.Y)); } return result; }
/// <summary> /// Initializes a new instance of the <see cref="MeshBuilder"/> class. /// </summary> /// <remarks> /// Normal and texture coordinate generation are included. /// </remarks> public MeshBuilder(bool generateNormals = true, bool generateTexCoords = true, bool tangentSpace = false) { this.positions = new Vector3Collection(); this.triangleIndices = new IntCollection(); if (generateNormals) { this.normals = new Vector3Collection(); } if (generateTexCoords) { this.textureCoordinates = new Vector2Collection(); } if (tangentSpace) { this.tangents = new Vector3Collection(); this.bitangents = new Vector3Collection(); } }
private void Timer_Tick() { ++counter; counter %= 128; if (DynamicTexture) { Vector2Collection texture = null; if (!AnimateUVOffset) { texture = new Vector2Collection(Model.TextureCoordinates); var t0 = texture[0]; for (int i = 1; i < texture.Count; ++i) { texture[i - 1] = texture[i]; } texture[texture.Count - 1] = t0; } context.Send((o) => { if (!AnimateUVOffset) { Model.TextureCoordinates = texture; if (ReverseInnerRotation) { var texture1 = new Vector2Collection(texture); texture1.Reverse(); InnerModel.TextureCoordinates = texture1; } else { InnerModel.TextureCoordinates = texture; } } else { ModelMaterial.UVTransform = new UVTransform(0, Vector2.One, ModelMaterial.UVTransform.Translation + new Vector2(0.005f, -0.01f)); InnerModelMaterial.UVTransform = new UVTransform(0, Vector2.One, InnerModelMaterial.UVTransform.Translation + new Vector2(-0.01f, 0.005f)); } }, null); } if (DynamicVertices) { var positions = new Vector3Collection(initialPosition); for (int i = 0; i < positions.Count; ++i) { var off = (float)Math.Sin(Math.PI * (float)(counter + i) / 64); var p = positions[i]; p *= 0.8f + off * 0.2f; positions[i] = p; } var linePositions = new Vector3Collection(positions); linePositions.Add(Vector3.Zero); //var normals = MeshGeometryHelper.CalculateNormals(positions, initialIndicies); //var innerNormals = new Vector3Collection(normals.Select(x => { return x * -1; })); context.Send((o) => { //Model.Normals = normals; //InnerModel.Normals = innerNormals; //Model.Positions = positions; //InnerModel.Positions = positions; PointModel.Positions = positions; LineModel.Positions = linePositions; }, null); } if (DynamicTriangles) { var indices = new IntCollection(initialIndicies); if (isRemoving) { removedIndex += 3 * 8; if (removedIndex >= initialIndicies.Count) { removedIndex = initialIndicies.Count; isRemoving = false; } } else { removedIndex -= 3 * 8; if (removedIndex <= 0) { isRemoving = true; removedIndex = 0; } } indices.RemoveRange(0, removedIndex); context.Send((o) => { Model.Indices = indices; InnerModel.Indices = indices; }, null); } if (DynamicTexture) { var colors = new Color4Collection(PointModel.Colors); for (int k = 0; k < 10; ++k) { var c = colors[colors.Count - 1]; for (int i = colors.Count - 1; i > 0; --i) { colors[i] = colors[i - 1]; } colors[0] = c; } var lineColors = new Color4Collection(LineModel.Colors); for (int k = 0; k < 10; ++k) { var c = lineColors[colors.Count - 2]; for (int i = lineColors.Count - 2; i > 0; --i) { lineColors[i] = lineColors[i - 1]; } lineColors[0] = c; } context.Send((o) => { PointModel.Colors = colors; LineModel.Colors = lineColors; }, null); } }
private void Timer_Tick(object sender, EventArgs e) { if (DynamicTexture) { var texture = new Vector2Collection(Model.TextureCoordinates); for (int i = 1; i < Model.TextureCoordinates.Count; ++i) { texture[i - 1] = Model.TextureCoordinates[i]; } texture[texture.Count - 1] = Model.TextureCoordinates[0]; Model.TextureCoordinates = texture; if (ReverseInnerRotation) { var texture1 = new Vector2Collection(texture); texture1.Reverse(); InnerModel.TextureCoordinates = texture1; } else { InnerModel.TextureCoordinates = texture; } } if (DynamicVertices) { var positions = new Vector3Collection(initialPosition); for (int i = 0; i < positions.Count; ++i) { positions[i] = positions[i] * (float)rnd.Next(95, 105) / 100; } Model.Normals = MeshGeometryHelper.CalculateNormals(positions, Model.Indices); InnerModel.Normals = new Vector3Collection(Model.Normals.Select(x => { return(x * -1); })); Model.Positions = positions; InnerModel.Positions = positions; //Alternative implementation //Floor.DisablePropertyChangedEvent = true; //Floor.Positions = positions; //Floor.CalculateNormals(); //Floor.DisablePropertyChangedEvent = false; //Floor.UpdateVertex(); } if (DynamicTriangles) { var indices = new IntCollection(initialIndicies); if (isRemoving) { removedIndex += 3 * 8; if (removedIndex >= initialIndicies.Count) { removedIndex = initialIndicies.Count; isRemoving = false; } } else { removedIndex -= 3 * 8; if (removedIndex <= 0) { isRemoving = true; removedIndex = 0; } } indices.RemoveRange(0, removedIndex); Model.Indices = indices; InnerModel.Indices = indices; } }
/// <summary> /// Reads a triangular mesh. /// </summary> /// <param name="reader"> /// The reader. /// </param> /// <param name="chunkSize"> /// The chunk size. /// </param> private void ReadTriangularMesh(BinaryReader reader, int chunkSize) { MeshBuilder builder = new MeshBuilder(); int bytesRead = 6; Vector3Collection positions = null; IntCollection faces = null; Vector2Collection textureCoordinates = null; List <FaceSet> facesets = null; IntCollection triangleIndices = null; Vector3Collection normals = null; //Matrix matrix = Matrix.Identity; Vector3Collection tangents = null; Vector3Collection bitangents = null; List <Matrix> transforms = new List <Matrix>(); while (bytesRead < chunkSize) { ChunkID id = this.ReadChunkId(reader); int size = this.ReadChunkSize(reader); bytesRead += size; switch (id) { case ChunkID.TRI_VERTEXL: positions = this.ReadVertexList(reader); break; case ChunkID.TRI_FACEL1: faces = ReadFaceList(reader); size -= (faces.Count / 3 * 8) + 2; facesets = this.ReadFaceSets(reader, size - 6); break; case ChunkID.TRI_TEXCOORD: textureCoordinates = ReadTexCoords(reader); break; case ChunkID.TRI_LOCAL: transforms.Add(this.ReadTransformation(reader)); break; default: this.ReadData(reader, size - 6); break; } } if (faces == null) { //no faces defined?? return... return; } if (facesets == null || facesets.Count == 0) { triangleIndices = faces; CreateMesh(positions, textureCoordinates, triangleIndices, transforms, out normals, out tangents, out bitangents, new PhongMaterial() { Name = "Gray", AmbientColor = new Color4(0.1f, 0.1f, 0.1f, 1.0f), DiffuseColor = new Color4(0.254902f, 0.254902f, 0.254902f, 1.0f), SpecularColor = new Color4(0.0225f, 0.0225f, 0.0225f, 1.0f), EmissiveColor = new Color4(0.0f, 0.0f, 0.0f, 1.0f), SpecularShininess = 12.8f, }); //Add default get and setter } else { foreach (var fm in facesets) { triangleIndices = ConvertFaceIndices(fm.Faces, faces); MaterialCore mat = null; if (this.materials.ContainsKey(fm.Name)) { mat = this.materials[fm.Name]; } CreateMesh(positions, textureCoordinates, triangleIndices, transforms, out normals, out tangents, out bitangents, mat); } } }
///////////////////////////////////////////////////////////////////////////////////////////// //// below all functions taken from "Helix 3D Toolkit" MeshBuilder ///////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Gets a circle section (cached). /// </summary> /// <param name="thetaDiv"> /// The number of division. /// </param> /// <returns> /// A circle. /// </returns> public static IList<Vector2> GetCircle(int thetaDiv) { IList<Vector2> circle; if (!CircleCache.TryGetValue(thetaDiv, out circle)) { circle = new Vector2Collection(); CircleCache.Add(thetaDiv, circle); for (int i = 0; i < thetaDiv; i++) { double theta = Math.PI * 2 * ((double)i / (thetaDiv - 1)); circle.Add(new Vector2((float)Math.Cos(theta), -(float)Math.Sin(theta))); } } return circle; }
/// <summary> /// Adds an arrow to the mesh. /// </summary> /// <param name="point1"> /// The start point. /// </param> /// <param name="point2"> /// The end point. /// </param> /// <param name="diameter"> /// The diameter of the arrow cylinder. /// </param> /// <param name="headLength"> /// Length of the head (relative to diameter). /// </param> /// <param name="thetaDiv"> /// The number of divisions around the arrow. /// </param> public void AddArrow(Vector3 point1, Vector3 point2, double diameter, double headLength = 3, int thetaDiv = 18) { var dir = point2 - point1; var length = dir.Length(); var r = (float)diameter / 2; var pc = new Vector2Collection { new Vector2(0, 0), new Vector2(0, r), new Vector2(length - (float)(diameter * headLength), r), new Vector2(length - (float)(diameter * headLength), r * 2), new Vector2(length, 0) }; this.AddRevolvedGeometry(pc, point1, dir, thetaDiv); }
private static void AppendSphere(Vector3 center, double radius, int thetaSteps, int phiSteps, out Vector3Collection positions, out Vector3Collection normals, out Vector2Collection textureCoordinates, out IntCollection triangleIndices) { positions = new Vector3Collection(); normals = new Vector3Collection(); textureCoordinates = new Vector2Collection(); triangleIndices = new IntCollection(); double dt = DegToRad(360.0) / thetaSteps; double dp = DegToRad(180.0) / phiSteps; for (int pi = 0; pi <= phiSteps; pi++) { double phi = pi * dp; for (int ti = 0; ti <= thetaSteps; ti++) { // we want to start the mesh on the x axis double theta = ti * dt; positions.Add(GetPosition(theta, phi, radius) + center); normals.Add(GetNormal(theta, phi)); textureCoordinates.Add(GetTextureCoordinate(theta, phi)); } } for (int pi = 0; pi < phiSteps; pi++) { for (int ti = 0; ti < thetaSteps; ti++) { int x0 = ti; int x1 = ti + 1; int y0 = pi * (thetaSteps + 1); int y1 = (pi + 1) * (thetaSteps + 1); triangleIndices.Add(x0 + y0); triangleIndices.Add(x0 + y1); triangleIndices.Add(x1 + y0); triangleIndices.Add(x1 + y0); triangleIndices.Add(x0 + y1); triangleIndices.Add(x1 + y1); } } }
/// <summary> /// Makes sure no triangles share the same vertex. /// </summary> private void NoSharedVertices() { var p = new Vector3Collection(); var ti = new IntCollection(); Vector3Collection n = null; if (this.normals != null) { n = new Vector3Collection(); } Vector2Collection tc = null; if (this.textureCoordinates != null) { tc = new Vector2Collection(); } for (int i = 0; i < this.triangleIndices.Count; i += 3) { int i0 = i; int i1 = i + 1; int i2 = i + 2; int index0 = this.triangleIndices[i0]; int index1 = this.triangleIndices[i1]; int index2 = this.triangleIndices[i2]; var p0 = this.positions[index0]; var p1 = this.positions[index1]; var p2 = this.positions[index2]; p.Add(p0); p.Add(p1); p.Add(p2); ti.Add(i0); ti.Add(i1); ti.Add(i2); if (n != null) { n.Add(this.normals[index0]); n.Add(this.normals[index1]); n.Add(this.normals[index2]); } if (tc != null) { tc.Add(this.textureCoordinates[index0]); tc.Add(this.textureCoordinates[index1]); tc.Add(this.textureCoordinates[index2]); } } this.positions = p; this.triangleIndices = ti; this.normals = n; this.textureCoordinates = tc; }
/// <summary> /// Chamfers the specified corner (experimental code). /// </summary> /// <param name="p"> /// The corner point. /// </param> /// <param name="d"> /// The chamfer distance. /// </param> /// <param name="eps"> /// The corner search limit distance. /// </param> /// <param name="chamferPoints"> /// If this parameter is provided, the collection will be filled with the generated chamfer points. /// </param> public void ChamferCorner(Vector3 p, double d, double eps = 1e-6, IList<Vector3> chamferPoints = null) { this.NoSharedVertices(); this.normals = null; this.textureCoordinates = null; var cornerNormal = this.FindCornerNormal(p, eps); var newCornerPoint = p - (cornerNormal * (float)d); int index0 = this.positions.Count; this.positions.Add(newCornerPoint); var plane = new Plane3D(newCornerPoint, cornerNormal); int ntri = this.triangleIndices.Count; for (int i = 0; i < ntri; i += 3) { int i0 = i; int i1 = i + 1; int i2 = i + 2; var p0 = this.positions[this.triangleIndices[i0]]; var p1 = this.positions[this.triangleIndices[i1]]; var p2 = this.positions[this.triangleIndices[i2]]; var d0 = (p - p0).LengthSquared(); var d1 = (p - p1).LengthSquared(); var d2 = (p - p2).LengthSquared(); var mind = Math.Min(d0, Math.Min(d1, d2)); if (mind > eps) { continue; } if (d1 < eps) { i0 = i + 1; i1 = i + 2; i2 = i; } if (d2 < eps) { i0 = i + 2; i1 = i; i2 = i + 1; } p0 = this.positions[this.triangleIndices[i0]]; p1 = this.positions[this.triangleIndices[i1]]; p2 = this.positions[this.triangleIndices[i2]]; // p0 is the corner vertex (at index i0) // find the intersections between the chamfer plane and the two edges connected to the corner var line1 = new Ray(p0, p1 - p0); var line2 = new Ray(p0, p2 - p0); Vector3 p01, p02; if (!plane.Intersects(ref line1, out p01)) { continue; } if (!plane.Intersects(ref line2, out p02)) { continue; } if (chamferPoints != null) { // add the chamfered points if (!chamferPoints.Contains(p01)) { chamferPoints.Add(p01); } if (!chamferPoints.Contains(p02)) { chamferPoints.Add(p02); } } int i01 = i0; // change the original triangle to use the first chamfer point this.positions[this.triangleIndices[i01]] = p01; int i02 = this.positions.Count; this.positions.Add(p02); // add a new triangle for the other chamfer point this.triangleIndices.Add(i01); this.triangleIndices.Add(i2); this.triangleIndices.Add(i02); // add a triangle connecting the chamfer points and the new corner point this.triangleIndices.Add(index0); this.triangleIndices.Add(i01); this.triangleIndices.Add(i02); } this.NoSharedVertices(); }
private Vector2Collection ReadTexCoords(BinaryReader reader) { int size = reader.ReadUInt16(); var pts = new Vector2Collection(); for(int i=0;i< size; i++) { float x = reader.ReadSingle(); float y = reader.ReadSingle(); pts.Add(new Vector2(x, y)); } return pts; }
/// <summary> /// Adds a (possibly truncated) cone. /// </summary> /// <param name="origin"> /// The origin. /// </param> /// <param name="direction"> /// The direction (normalization not required). /// </param> /// <param name="baseRadius"> /// The base radius. /// </param> /// <param name="topRadius"> /// The top radius. /// </param> /// <param name="height"> /// The height. /// </param> /// <param name="baseCap"> /// Include a base cap if set to <c>true</c> . /// </param> /// <param name="topCap"> /// Include the top cap if set to <c>true</c> . /// </param> /// <param name="thetaDiv"> /// The number of divisions around the cone. /// </param> /// <remarks> /// See http://en.wikipedia.org/wiki/Cone_(geometry). /// </remarks> public void AddCone( Vector3 origin, Vector3 direction, double baseRadius, double topRadius, double height, bool baseCap, bool topCap, int thetaDiv) { var pc = new Vector2Collection(); if (baseCap) { pc.Add(new Vector2(0, 0)); } pc.Add(new Vector2(0, (float)baseRadius)); pc.Add(new Vector2((float)height, (float)topRadius)); if (topCap) { pc.Add(new Vector2((float)height, 0)); } this.AddRevolvedGeometry(pc, origin, direction, thetaDiv); }
private IList <Object3D> Load(BinaryReader reader) { var name = reader.ReadCMO_wchar(); int numMaterials = (int)reader.ReadUInt32(); var materials = new List <Tuple <PhongMaterial, IList <string> > >(numMaterials); for (int i = 0; i < numMaterials; ++i) { var material = new PhongMaterial { Name = reader.ReadCMO_wchar(), AmbientColor = reader.ReadStructure <Color4>(), DiffuseColor = reader.ReadStructure <Color4>(), SpecularColor = reader.ReadStructure <Color4>(), SpecularShininess = reader.ReadSingle(), EmissiveColor = reader.ReadStructure <Color4>() }; var uvTransform = reader.ReadStructure <Matrix>(); if (uvTransform == Matrix.Zero) { uvTransform = Matrix.Identity; } uvTransform.Decompose(out var s, out var r, out var tra); material.UVTransform = new UVTransform(r.Angle, new Vector2(s.X, s.Y), new Vector2(tra.X, tra.Y)); var pixelShaderName = reader.ReadCMO_wchar();//Not used var textures = new List <string>(); for (int t = 0; t < MaxTextures; ++t) { textures.Add(reader.ReadCMO_wchar()); } materials.Add(new Tuple <PhongMaterial, IList <string> >(material, textures)); } // BYTE - 1 if there is skeletal animation data present // is there skeletal animation data present? bool isAnimationData = reader.ReadByte() == 1; // UINT - SubMesh count // { [SubMesh count] // SubMesh structure // } // load sub meshes if any var mesh = new MeshGeometry3D(); int subMeshCount = (int)reader.ReadUInt32(); var subMesh = new List <SubMesh>(subMeshCount); for (int i = 0; i < subMeshCount; i++) { subMesh.Add(reader.ReadStructure <SubMesh>()); } // UINT - IB Count // { [IB Count] // UINT - Number of USHORTs in IB // USHORT[] - Array of indices // } // load triangle indices int indexBufferCount = (int)reader.ReadUInt32(); var indices = new List <ushort[]>(indexBufferCount); for (var i = 0; i < indexBufferCount; i++) { indices.Add(reader.ReadUInt16((int)reader.ReadUInt32())); } // UINT - VB Count // { [VB Count] // UINT - Number of verts in VB // Vertex[] - Array of vertices // } // load vertex positions int vertexBufferCount = (int)reader.ReadUInt32(); var vertexBuffers = new List <Vertex[]>(vertexBufferCount); for (var i = 0; i < vertexBufferCount; i++) { vertexBuffers.Add(reader.ReadStructure <Vertex>((int)reader.ReadUInt32())); } // UINT - Skinning VB Count // { [Skinning VB Count] // UINT - Number of verts in Skinning VB // SkinningVertex[] - Array of skinning verts // } // load vertex skinning parameters int skinningVertexBufferCount = (int)reader.ReadUInt32(); var skinningVertexBuffers = new List <SkinningVertex[]>(skinningVertexBufferCount); for (var i = 0; i < skinningVertexBufferCount; i++) { skinningVertexBuffers.Add(reader.ReadStructure <SkinningVertex>((int)reader.ReadUInt32())); } // load mesh extent var extent = reader.ReadStructure <MeshExtent>(); var animationHierarchy = new AnimationHierarchy(); IList <string> boneNames = null; if (isAnimationData) { // UINT - Bone count // { [Bone count] // UINT - Length of bone name // wchar_t[] - Bone name (if length > 0) // Bone structure // } int boneCount = (int)reader.ReadUInt32(); boneNames = new string[boneCount]; for (var i = 0; i < boneCount; i++) { boneNames[i] = reader.ReadCMO_wchar(); animationHierarchy.Bones.Add(reader.ReadStructure <BoneStruct>()); } // UINT - Animation clip count // { [Animation clip count] // UINT - Length of clip name // wchar_t[] - Clip name (if length > 0) // float - Start time // float - End time // UINT - Keyframe count // { [Keyframe count] // Keyframe structure // } // } int animationCount = (int)reader.ReadUInt32(); for (var i = 0; i < animationCount; i++) { Animation animation = new Animation(AnimationType.Keyframe); string animationName = reader.ReadCMO_wchar(); animation.StartTime = reader.ReadSingle(); animation.EndTime = reader.ReadSingle(); animation.Name = animationName; int keyframeCount = (int)reader.ReadUInt32(); for (var j = 0; j < keyframeCount; j++) { var keyframe = reader.ReadStructure <KeyframeCMO>(); keyframe.Transform.Decompose(out var s, out var q, out var t); animation.Keyframes.Add(new Keyframe() { Translation = t, Rotation = q, Scale = s, Time = keyframe.Time }); } animationHierarchy.Animations.Add(animation.Name, animation); if (!UniqueAnimations.ContainsKey(animation.Name)) { UniqueAnimations.Add(animation.Name, new List <Guid>()); } UniqueAnimations[animation.Name].Add(animation.GUID); } } var obj3Ds = new List <Object3D>(subMeshCount); for (int i = 0; i < subMesh.Count; ++i) { var sub = subMesh[i]; var material = materials.Count == 0 ? new PhongMaterial() : materials[(int)sub.MaterialIndex].Item1; var vertexCollection = new Vector3Collection(vertexBuffers[(int)sub.VertexDataIndex].Select(x => x.Position)); var normal = new Vector3Collection(vertexBuffers[(int)sub.VertexDataIndex].Select(x => x.Normal)); var tex = new Vector2Collection(vertexBuffers[(int)sub.VertexDataIndex].Select(x => x.UV)); var tangent = new Vector3Collection(vertexBuffers[(int)sub.VertexDataIndex].Select(x => x.Tangent.ToVector3())); var biTangent = new Vector3Collection(normal.Zip(tangent, (x, y) => { return(Vector3.Cross(x, y)); })); var indexCollection = new IntCollection(indices[(int)sub.IndexDataIndex].Select(x => (int)x)); var meshGeo = new MeshGeometry3D() { Positions = vertexCollection, Indices = indexCollection, Normals = normal, Tangents = tangent, BiTangents = biTangent, TextureCoordinates = tex }; if (isAnimationData) { var boneskinmesh = new BoneSkinnedMeshGeometry3D(meshGeo); boneskinmesh.VertexBoneIds = new List <BoneIds>(skinningVertexBuffers[(int)sub.VertexDataIndex] .Select(x => new BoneIds() { Bone1 = (int)x.BoneIndex0, Bone2 = (int)x.BoneIndex1, Bone3 = (int)x.BoneIndex2, Bone4 = (int)x.BoneIndex3, Weights = new Vector4(x.BoneWeight0, x.BoneWeight1, x.BoneWeight2, x.BoneWeight3), })); meshGeo = boneskinmesh; } //Todo Load textures obj3Ds.Add(new Object3D() { Geometry = meshGeo, Material = material, Name = name }); animationHierarchy.Meshes.Add(obj3Ds.Last()); } AnimationHierarchy.Add(animationHierarchy); return(obj3Ds); }
/// <summary> /// Gets a circle segment section. /// </summary> /// <param name="thetaDiv">The number of division.</param> /// <param name="totalAngle">The angle of the circle segment.</param> /// <param name="angleOffset">The angle-offset to use.</param> /// <returns> /// A circle segment. /// </returns> public static IList<Vector2> GetCircleSegment(int thetaDiv, float totalAngle = 2 * (float)Math.PI, float angleOffset = 0) { IList <Vector2> circleSegment; circleSegment = new Vector2Collection(); for (int i = 0; i < thetaDiv; i++) { double theta = totalAngle * ((double)i / (thetaDiv - 1)) + angleOffset; circleSegment.Add(new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta))); } return circleSegment; }
public static MeshGeometry3D Merge(params MeshGeometry3D[] meshes) { var positions = new Vector3Collection(); var indices = new IntCollection(); var normals = meshes.All(x => x.Normals != null) ? new Vector3Collection() : null; var colors = meshes.All(x => x.Colors != null) ? new Color4Collection() : null; var textureCoods = meshes.All(x => x.TextureCoordinates != null) ? new Vector2Collection() : null; var tangents = meshes.All(x => x.Tangents != null) ? new Vector3Collection() : null; var bitangents = meshes.All(x => x.BiTangents != null) ? new Vector3Collection() : null; int index = 0; foreach (var part in meshes) { for (int i = 0; i < part.Positions.Count; i++) { positions.Add(part.Positions[i]); } for (int i = 0; i < part.Indices.Count; i++) { indices.Add(index + part.Indices[i]); } index += part.Indices.Count; } if (normals != null) { normals = new Vector3Collection(meshes.SelectMany(x => x.Normals)); } if (colors != null) { colors = new Color4Collection(meshes.SelectMany(x => x.Colors)); } if (textureCoods != null) { textureCoods = new Vector2Collection(meshes.SelectMany(x => x.TextureCoordinates)); } if (tangents != null) { tangents = new Vector3Collection(meshes.SelectMany(x => x.Tangents)); } if (bitangents != null) { bitangents = new Vector3Collection(meshes.SelectMany(x => x.BiTangents)); } var mesh = new MeshGeometry3D() { Positions = positions, Indices = indices, }; mesh.Normals = normals; mesh.Colors = colors; mesh.TextureCoordinates = textureCoods; mesh.Tangents = tangents; mesh.BiTangents = bitangents; return mesh; }
/// <summary> /// Adds a (possibly hollow) pipe. /// </summary> /// <param name="point1"> /// The start point. /// </param> /// <param name="point2"> /// The end point. /// </param> /// <param name="innerDiameter"> /// The inner diameter. /// </param> /// <param name="diameter"> /// The outer diameter. /// </param> /// <param name="thetaDiv"> /// The number of divisions around the pipe. /// </param> public void AddPipe(Vector3 point1, Vector3 point2, double innerDiameter, double diameter, int thetaDiv) { var dir = point2 - point1; double height = dir.Length(); dir.Normalize(); var pc = new Vector2Collection { new Vector2(0, (float)innerDiameter / 2), new Vector2(0, (float)diameter / 2), new Vector2((float)height, (float)diameter / 2), new Vector2((float)height, (float)innerDiameter / 2) }; if (innerDiameter > 0) { // Add the inner surface pc.Add(new Vector2(0, (float)innerDiameter / 2)); } this.AddRevolvedGeometry(pc, point1, dir, thetaDiv); }
public static bool Contains(this Vector2Collection vectors, double[] expectedVector) { return(vectors.Any(vector => Math.Abs((float)expectedVector[0] - vector.X) < float.Epsilon && Math.Abs((float)expectedVector[1] - vector.Y) < float.Epsilon)); }
public TexturedMeshBinder(Autodesk.Dynamo.MeshToolkit.Mesh mesh, string textureFileName, Vector2Collection textureCoordinates) : this(mesh, DynaShapeDisplay.DefaultMeshFaceColor, textureFileName, textureCoordinates) { }
/// <summary> /// Create a Mesh, with found props /// </summary> /// <param name="positions"></param> /// <param name="textureCoordinates"></param> /// <param name="triangleIndices"></param> /// <param name="normals"></param> /// <param name="tangents"></param> /// <param name="bitangents"></param> /// <param name="material"></param> private void CreateMesh(Vector3Collection positions, Vector2Collection textureCoordinates, IntCollection triangleIndices, out Vector3Collection normals, out Vector3Collection tangents, out Vector3Collection bitangents,Material material) { ComputeNormals(positions, triangleIndices, out normals); if (textureCoordinates == null) { textureCoordinates = new Vector2Collection(); foreach(var pos in positions) { textureCoordinates.Add(Vector2.One); } } MeshBuilder.ComputeTangents(positions, normals, textureCoordinates, triangleIndices, out tangents, out bitangents); MeshGeometry3D mesh = new MeshGeometry3D() { Positions = positions, Normals = normals, TextureCoordinates = textureCoordinates, Indices = triangleIndices, Tangents = tangents, BiTangents = bitangents }; Object3D ob3d = new Object3D(); ob3d.Geometry = mesh; ob3d.Material = material; ob3d.Transform = Matrix.Identity; ob3d.Name = "Default"; this.obGroup.Add(ob3d); }