public SegaSaturnPolygonData GetPolygonData(List <Texture> textures, Option option) { bool hasTexture = this.MeshSources.Any(item => item.MeshSourceKind == MeshSource.MeshSourceKindEnum.Texcoord); string name = this.Name ?? this.Id ?? this.GetHashCode().ToString(); name = Regex.Replace(name, "[^A-Za-z0-9]", ""); if (this.GeometryIndex > 1) { name += this.GeometryIndex.ToString(); } SegaSaturnPolygonData toReturn = new SegaSaturnPolygonData { Points = this.GetPoints(), Name = name }; if (this.PolygonCount > 10000) { MessageBox.Show(String.Format("{0} polygons({1}) ? Seriously !? It's a Sega Saturn not a PS4 :)", this.PolygonCount, toReturn.Name), Editor.Instance.Text, MessageBoxButtons.OK, MessageBoxIcon.Error); throw new InvalidOperationException("Too many polygons"); } List <SegaSaturnVertices> vertices = this.GetVertices(); List <SegaSaturnNormal> normals = this.GetNormals(); retry: toReturn.Textures = new List <SegaSaturnTexture>(); toReturn.Polygons = new List <SegaSaturnPolygon>(); toReturn.Attributes = new List <SegaSaturnAttribute>(); for (int i = 0; i < this.PolygonCount; ++i) { toReturn.Polygons.Add(new SegaSaturnPolygon { Normal = normals[i], Vertices = vertices[i] }); toReturn.Attributes.Add(new SegaSaturnAttribute { FrontBackPlane = SegaSaturnAttribute.FrontBackPlaneEnum.Dual, ZSortSpecification = SegaSaturnAttribute.ZSortSpecificationEnum.Cen, Color = new SegaSaturnColor(Collada.DefaultColors[(this.GeometryIndex - 1) % Collada.DefaultColors.Count]), UseLight = option.UseLight, UseScreenDoors = option.UseScreenDoors }); } if (hasTexture) { toReturn.Textures = this.GetTextures(textures, toReturn.Attributes, 64); } else { toReturn.Textures = new List <SegaSaturnTexture>(); } if (toReturn.Textures.Count > 64) { if (MessageBox.Show(String.Format("{0} textured polygons({1}) is too much for the Sega Saturn but would you like to export the mesh without textures ?", this.PolygonCount, toReturn.Name), Editor.Instance.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No) { throw new InvalidOperationException("Too many polygons"); } hasTexture = false; goto retry; } return(toReturn); }
public List <SegaSaturnPolygonData> Parse(string path, Option option) { List <SegaSaturnPolygonData> toReturn = new List <SegaSaturnPolygonData>(); Dictionary <string, Material> material = new Dictionary <string, Material>(); Dictionary <string, SegaSaturnTexture> dict = new Dictionary <string, SegaSaturnTexture>(); List <SegaSaturnNormal> normals = new List <SegaSaturnNormal>(); List <SegaSaturnTextureCoordinates> textureCoordinates = new List <SegaSaturnTextureCoordinates>(); SegaSaturnPolygonData currentPolygonData = new SegaSaturnPolygonData(); Material currentMaterial = new Material(); bool newMesh = false; using (StreamReader reader = new StreamReader(path)) { string line; while ((line = reader.ReadLine()) != null) { string[] data = line.Split(new[] { " ", "\t" }, StringSplitOptions.RemoveEmptyEntries); if (data.Length <= 0) { continue; } switch (data[0].ToLower()) { case "usemtl": if (material.ContainsKey(data[1])) { currentMaterial = material[data[1]]; } else { currentMaterial = new Material(); } break; case "mtllib": material = this.ParseMaterial(data[1], option.WorkingDir, 128); break; case "g": if (String.IsNullOrWhiteSpace(currentPolygonData.Name)) { currentPolygonData.Name = data[1]; } break; case "v": if (newMesh) { dict.Clear(); newMesh = false; if (currentPolygonData != null) { if (String.IsNullOrWhiteSpace(currentPolygonData.Name)) { currentPolygonData.Name = String.Format("Unnamed{0}", toReturn.Count + 1); } toReturn.Add(currentPolygonData); } //normals = new List<SegaSaturnNormal>(); //textureCoordinates = new List<SegaSaturnTextureCoordinates>(); currentMaterial = new Material(); currentPolygonData = new SegaSaturnPolygonData(); } float x = float.Parse(data[1], CultureInfo.InvariantCulture) * (float)option.ZoomFactor; float y = float.Parse(data[2], CultureInfo.InvariantCulture) * (float)option.ZoomFactor; float z = float.Parse(data[3], CultureInfo.InvariantCulture) * (float)option.ZoomFactor; currentPolygonData.Points.Add(new SegaSaturnPoint(x, y, z)); break; case "vn": normals.Add(new SegaSaturnNormal(float.Parse(data[1], CultureInfo.InvariantCulture), float.Parse(data[2], CultureInfo.InvariantCulture), float.Parse(data[3], CultureInfo.InvariantCulture))); break; case "vt": textureCoordinates.Add(new SegaSaturnTextureCoordinates(float.Parse(data[1], CultureInfo.InvariantCulture), float.Parse(data[2], CultureInfo.InvariantCulture))); break; case "f": newMesh = true; if (data.Length > 5) { throw new NotSupportedException("Ngons are not supported"); } string v; string vt; string vn; this.ParseFace(data[1], out v, out vt, out vn); bool hasTexture = option.UseTexture && !String.IsNullOrEmpty(vt) && currentMaterial.Texture != null; bool hasNormal = !String.IsNullOrEmpty(vn); SegaSaturnAttribute attributes = new SegaSaturnAttribute { Color = hasTexture ? null : new SegaSaturnColor(Obj.DefaultColors[toReturn.Count % Obj.DefaultColors.Count]), ZSortSpecification = SegaSaturnAttribute.ZSortSpecificationEnum.Cen, FrontBackPlane = option.DualPlane ? SegaSaturnAttribute.FrontBackPlaneEnum.Dual : SegaSaturnAttribute.FrontBackPlaneEnum.Single, UseScreenDoors = option.UseScreenDoors, UseLight = option.UseLight }; currentPolygonData.Attributes.Add(attributes); SegaSaturnPolygon polygon = new SegaSaturnPolygon(); SegaSaturnTextureVerticesIndexes textureVertices = new SegaSaturnTextureVerticesIndexes(); if (hasNormal) { polygon.Normal = normals[int.Parse(vn, CultureInfo.InvariantCulture) - 1]; } polygon.Vertices = new SegaSaturnVertices(); //vertice #1 polygon.Vertices.Vertice1 = int.Parse(v, CultureInfo.InvariantCulture) - 1; textureVertices.Vertice1 = !String.IsNullOrWhiteSpace(vt) ? int.Parse(vt, CultureInfo.InvariantCulture) - 1 : 0; //vertice #2 this.ParseFace(data[2], out v, out vt, out vn); polygon.Vertices.Vertice2 = int.Parse(v, CultureInfo.InvariantCulture) - 1; textureVertices.Vertice2 = !String.IsNullOrWhiteSpace(vt) ? int.Parse(vt, CultureInfo.InvariantCulture) - 1 : 0; //vertice #3 this.ParseFace(data[3], out v, out vt, out vn); polygon.Vertices.Vertice3 = int.Parse(v, CultureInfo.InvariantCulture) - 1; textureVertices.Vertice3 = !String.IsNullOrWhiteSpace(vt) ? int.Parse(vt, CultureInfo.InvariantCulture) - 1 : 0; //vertice #4 if (data.Length <= 4) { polygon.Vertices.Vertice4 = polygon.Vertices.Vertice3; textureVertices.Vertice4 = textureVertices.Vertice3; } else { this.ParseFace(data[4], out v, out vt, out vn); polygon.Vertices.Vertice4 = int.Parse(v, CultureInfo.InvariantCulture) - 1; textureVertices.Vertice4 = !String.IsNullOrWhiteSpace(vt) ? int.Parse(vt, CultureInfo.InvariantCulture) - 1 : 0; } // Textures if (hasTexture) { SegaSaturnTextureCoordinates p1 = textureCoordinates[textureVertices.Vertice1]; p1.ComputeTextureCoordinates(currentMaterial.Texture.Width, currentMaterial.Texture.Height); SegaSaturnTextureCoordinates p2 = textureCoordinates[textureVertices.Vertice2]; p2.ComputeTextureCoordinates(currentMaterial.Texture.Width, currentMaterial.Texture.Height); SegaSaturnTextureCoordinates p3 = textureCoordinates[textureVertices.Vertice3]; p3.ComputeTextureCoordinates(currentMaterial.Texture.Width, currentMaterial.Texture.Height); SegaSaturnTextureCoordinates p4 = textureCoordinates[textureVertices.Vertice4]; p4.ComputeTextureCoordinates(currentMaterial.Texture.Width, currentMaterial.Texture.Height); if (p1.Hash != p2.Hash || p2.Hash != p3.Hash) { SegaSaturnTexture texture = SegaSaturnTexture.ConvertFrom(currentMaterial.Texture, currentMaterial.Name ?? Path.GetFileNameWithoutExtension(currentMaterial.TexturePath), p1, p2, p3, p4, textureVertices.IsTriangleMapping); if (!dict.ContainsKey(texture.Hash)) { texture.Name += currentPolygonData.Textures.Count.ToString(); dict.Add(texture.Hash, texture); currentPolygonData.Textures.Add(texture); } attributes.SpriteIndex = currentPolygonData.Textures.FindIndex(item => item.Hash == texture.Hash); attributes.Color = null; } } currentPolygonData.Polygons.Add(polygon); break; default: break; } } } if (currentPolygonData != null) { if (String.IsNullOrWhiteSpace(currentPolygonData.Name)) { currentPolygonData.Name = String.Format("Unnamed{0}", toReturn.Count + 1); } toReturn.Add(currentPolygonData); } return(toReturn); }