public string ToJson() { // I did think of using a JSON serialiser, // either one of these two provided by the // .NET framework or one of the other libraries: // System.Runtime.Serialization.Json.DataContractJsonSerializer // System.Web.Script.Serialization.JavaScriptSerializer // However, reading this comparison and alternative // implementation, I decided to just write the couple // of lines myself. // http://procbits.com/2011/08/11/fridaythe13th-the-best-json-parser-for-silverlight-and-net string s = string.Format ("\n \"FacetCount\":{0}," + "\n \"VertexCount\":{1}," + "\n \"VertexCoords\":[{2}]," + "\n \"VertexIndices\":[{3}]," + "\n \"Normals\":[{4}]," + "\n \"NormalIndices\":[{5}]," + "\n \"Center\":[{6}]," + "\n \"Color\":[{7}]," + "\n \"Id\":\"{8}\"", FacetCount, VertexCount, string.Join(",", VertexCoords.Select <int, string>(i => (_export_factor * i).ToString("0.#")).ToArray()), string.Join(",", VertexIndices.Select <int, string>(i => i.ToString()).ToArray()), string.Join(",", Normals.Select <double, string>(a => a.ToString("0.####")).ToArray()), string.Join(",", NormalIndices.Select <int, string>(i => i.ToString())), string.Join(",", Center.Select <int, string>(i => (_export_factor * i).ToString("0.#"))), Color, Id); return("\n{" + s + "\n}"); }
public VertexIndices(VertexIndices previous, int finalIndex) { Vertex = previous.Vertex; TexCoord = previous.TexCoord; Normal = previous.Normal; FinalIndex = finalIndex; }
private static VertexIndices ParseVertexIndices(string element) { int count = element.Count(ch => ch == '/'); VertexIndices result = new VertexIndices(); if (element.Contains("//")) { // Vertex, normal string[] vertexNormal = element.Split(new [] { "//" }, StringSplitOptions.None); result.Vertex = int.Parse(vertexNormal[0]); result.Normal = int.Parse(vertexNormal[1]); } else if (count == 1) { // Vertex, texcoord string[] vertexTCoord = element.Split('/'); result.Vertex = int.Parse(vertexTCoord[0]); result.TexCoord = int.Parse(vertexTCoord[1]); } else if (count == 2) { // Vertex, texcoord, normal string[] vertexTCoordNormal = element.Split('/'); result.Vertex = int.Parse(vertexTCoordNormal[0]); result.TexCoord = int.Parse(vertexTCoordNormal[1]); result.Normal = int.Parse(vertexTCoordNormal[2]); } else { throw new AssetLoadException("model", "texture face element declaration incorrect, count was " + count.ToString() + " @ line " + currentLine.ToString()); } return(result); }
public virtual void Dispose() { VertexOffsets.Dispose(); VertexIndices.Dispose(); EdgeFlags.Dispose(); Triangles.Dispose(); }
protected override void PopulateSerializedValues(IList <string> serializedValues) { SerializeToFloat(serializedValues, VertexIndices.Count()); foreach (var index in VertexIndices) { SerializeToFloat(serializedValues, index); } if (Normal != null) { SerializeToFloat(serializedValues, Normal.X); SerializeToFloat(serializedValues, Normal.Y); SerializeToFloat(serializedValues, Normal.Z); } if (Color.HasValue) { Serialize(serializedValues, Color.Value.R); Serialize(serializedValues, Color.Value.G); Serialize(serializedValues, Color.Value.B); Serialize(serializedValues, Color.Value.A); } if (BackColor.HasValue) { Serialize(serializedValues, Color.Value.R); Serialize(serializedValues, Color.Value.G); Serialize(serializedValues, Color.Value.B); Serialize(serializedValues, Color.Value.A); } }
public VertexSet(PrimitiveType mode, IAttributedVertexBuffer buffer, VertexIndices indices, ISet <int> enabledAttribs = null, int depth = 0) { DrawMode = mode; VBuffer = buffer; EnabledAttributes = enabledAttribs; this.indices = indices; DrawDepth = depth; }
protected void GenerateVertices() { var Count = VertexIndices.Count; VertexIndices.Clear(); List <ObjMeshSection> SortedMeshSectionList = new List <ObjMeshSection>(); foreach (var sectionlist in MeshSectionList.GroupBy(x => x.SectionName)) { var sectionName = sectionlist.First().SectionName; var sectionCount = sectionlist.Count(); UInt32 StartIndex = (UInt32)VertexIndices.Count; foreach (var section in sectionlist) { for (int i = (int)section.StartIndex; i < section.EndIndex; ++i) { var V1 = new PNTT_VertexAttribute(); V1.VertexPosition = TempVertexList[(int)VertexIndexList[i]]; if (HasTexCoordinate) { V1.TexCoord = TempTexCoordList[(int)TexCoordIndexList[i]]; V1.Tangent = TempTangentList[(int)VertexIndexList[i]]; } if (HasNormal) { V1.VertexNormal = TempNormalList[(int)NormalIndexList[i]]; } uint index = 0; if (GetSimilarVertexIndex(ref V1, out index)) { VertexIndices.Add(index); } else { Vertices.Add(V1); uint newIndex = (uint)Vertices.Count - 1; VertexCacheMap.Add(V1, newIndex); VertexIndices.Add(newIndex); } } } UInt32 EndIndex = (UInt32)VertexIndices.Count; SortedMeshSectionList.Add(new ObjMeshSection(sectionName, StartIndex, EndIndex)); } MeshSectionList = SortedMeshSectionList; Debug.Assert(Count == VertexIndices.Count); }
public Sprite(Texture tex, IBindableVertexBuffer buffer, int bufferInd, int depth = 0) : base( tex, PrimitiveType.Quads, new AttributedVertexBuffer(buffer, VertexAttributeSet.FromType <TexturedVertex2>()), VertexIndices.FromRange(bufferInd, 4), null, depth) { index = bufferInd; }
private static int GetFirstFinalIndexOfDuplicate(List <VertexIndices> vIndices, int currentIndex, bool optimize) { if (optimize) { VertexIndices vertex = vIndices[currentIndex]; for (int i = 0; i < currentIndex; ++i) { VertexIndices other = vIndices[i]; if (vertex == other) { return(other.FinalIndex); } } } return(-1); }
private static void SortOutVIndices( List <Vector4> verticesIn, out List <Vector4> verticesOut, List <Vector3> normalsIn, out List <Vector3> normalsOut, List <Vector2> tCoordsIn, out List <Vector2> tCoordsOut, out List <int> indicesOut, List <VertexIndices> vIndices, bool optimize) { verticesOut = new List <Vector4>(verticesIn.Count); normalsOut = new List <Vector3>(normalsIn.Count); tCoordsOut = new List <Vector2>(tCoordsIn.Count); indicesOut = new List <int>(verticesIn.Count); for (int i = 0; i < vIndices.Count; ++i) { int firstFinalIndex = GetFirstFinalIndexOfDuplicate(vIndices, i, optimize); if (firstFinalIndex == -1) { VertexIndices vertex = vIndices[i]; vIndices[i] = new VertexIndices(vertex, verticesOut.Count); indicesOut.Add(verticesOut.Count); verticesOut.Add(verticesIn[vertex.Vertex - 1]); if (vertex.TexCoord.HasValue) { tCoordsOut.Add(tCoordsIn[vertex.TexCoord.Value - 1]); } if (vertex.Normal.HasValue) { normalsOut.Add(normalsIn[vertex.Normal.Value - 1]); } } else { indicesOut.Add(firstFinalIndex); } } }
private static StringBuilder CreateObjGeometry(List <Dictionary <string, List <WorldVertex[]> > > geometryByTexture, ref WavefrontExportSettings data) { StringBuilder obj = new StringBuilder(); Vector2D offset; const string vertexFormatter = "{0} {2} {1}\n"; Dictionary <Vector3D, int> uniqueVerts = new Dictionary <Vector3D, int>(); Dictionary <Vector3D, int> uniqueNormals = new Dictionary <Vector3D, int>(); Dictionary <PointF, int> uniqueUVs = new Dictionary <PointF, int>(); var vertexDataByTexture = new Dictionary <string, Dictionary <WorldVertex, VertexIndices> >(StringComparer.Ordinal); int pc = 0; int nc = 0; int uvc = 0; Vector3D tl = new Vector3D(double.MaxValue, double.MinValue, double.MinValue); Vector3D br = new Vector3D(double.MinValue, double.MaxValue, double.MaxValue); //optimize geometry foreach (Dictionary <string, List <WorldVertex[]> > dictionary in geometryByTexture) { foreach (KeyValuePair <string, List <WorldVertex[]> > group in dictionary) { Dictionary <WorldVertex, VertexIndices> vertsData = new Dictionary <WorldVertex, VertexIndices>(); foreach (WorldVertex[] verts in group.Value) { //vertex normals. biwa not sure why I need to invert the normal, but it seems to be necessary Vector3D n = new Vector3D(verts[0].nx, verts[0].ny, verts[0].nz).GetNormal() * -1; int ni; if (uniqueNormals.ContainsKey(n)) { ni = uniqueNormals[n]; } else { uniqueNormals.Add(n, ++nc); ni = nc; } foreach (WorldVertex v in verts) { if (vertsData.ContainsKey(v)) { continue; } VertexIndices indices = new VertexIndices(); indices.NormalIndex = ni; //vertex coords Vector3D vc = new Vector3D(v.x, v.y, v.z); if (uniqueVerts.ContainsKey(vc)) { indices.PositionIndex = uniqueVerts[vc]; } else { uniqueVerts.Add(vc, ++pc); indices.PositionIndex = pc; } //uv PointF uv = new PointF(v.u, v.v); if (uniqueUVs.ContainsKey(uv)) { indices.UVIndex = uniqueUVs[uv]; } else { uniqueUVs.Add(uv, ++uvc); indices.UVIndex = uvc; } vertsData.Add(v, indices); } } if (vertsData.Count > 0) { if (vertexDataByTexture.ContainsKey(group.Key)) { foreach (KeyValuePair <WorldVertex, VertexIndices> g in vertsData) { vertexDataByTexture[group.Key].Add(g.Key, g.Value); } } else { vertexDataByTexture.Add(group.Key, vertsData); } } } } // Get the dimensions of the model foreach (Dictionary <WorldVertex, VertexIndices> vdata in vertexDataByTexture.Values) { foreach (WorldVertex wv in vdata.Keys) { if (wv.x < tl.x) { tl.x = wv.x; } if (wv.x > br.x) { br.x = wv.x; } if (wv.y > tl.y) { tl.y = wv.y; } if (wv.y < br.y) { br.y = wv.y; } if (wv.z > tl.z) { tl.z = wv.z; } if (wv.z < br.z) { br.z = wv.z; } } } data.Radius = br.x - tl.x > tl.y - br.y ? (int)(tl.y - br.y) / 2 : (int)(br.x - tl.x) / 2; data.Height = (int)(tl.z - br.z); if (data.CenterModel) { offset = new Vector2D(tl.x + (br.x - tl.x) / 2.0, tl.y + (br.y - tl.y) / 2.0); } else { offset = new Vector2D(0.0, 0.0); } //write geometry //write vertices if (data.ExportForGZDoom) { foreach (KeyValuePair <Vector3D, int> group in uniqueVerts) { double z = (group.Key.z - (data.NormalizeLowestVertex ? br.z : 0)) * data.Scale * 1.2f; obj.Append(string.Format(CultureInfo.InvariantCulture, "v " + vertexFormatter, (group.Key.x - offset.x) * data.Scale, -(group.Key.y - offset.y) * data.Scale, z)); } } else { // biwa. Not sure why the x-axis is flipped here, since it will result in wrong normals when using the model directly in GZDoom. For this reason // I disabled the flipping above foreach (KeyValuePair <Vector3D, int> group in uniqueVerts) { double z = (group.Key.z - (data.NormalizeLowestVertex ? br.z : 0)) * data.Scale; obj.Append(string.Format(CultureInfo.InvariantCulture, "v " + vertexFormatter, -(group.Key.x - offset.x) * data.Scale, (group.Key.y - offset.y) * data.Scale, z)); } } //write normals foreach (KeyValuePair <Vector3D, int> group in uniqueNormals) { obj.Append(string.Format(CultureInfo.InvariantCulture, "vn " + vertexFormatter, group.Key.x, group.Key.y, group.Key.z)); } //write UV coords foreach (KeyValuePair <PointF, int> group in uniqueUVs) { obj.Append(string.Format(CultureInfo.InvariantCulture, "vt {0} {1}\n", group.Key.X, -group.Key.Y)); } // GZDoom ignores the material lib, so don't add it if the model is for GZDoom if (!data.ExportForGZDoom) { obj.Append("mtllib ").Append(data.ObjName + ".mtl").Append("\n"); } //write materials and surface indices foreach (Dictionary <string, List <WorldVertex[]> > dictionary in geometryByTexture) { foreach (KeyValuePair <string, List <WorldVertex[]> > group in dictionary) { //material obj.Append("usemtl ").Append(group.Key).Append("\n"); foreach (WorldVertex[] verts in group.Value) { //surface indices obj.Append("f"); foreach (WorldVertex v in verts) { VertexIndices vi = vertexDataByTexture[group.Key][v]; obj.Append(" " + vi.PositionIndex + "/" + vi.UVIndex + "/" + vi.NormalIndex); } obj.Append("\n"); } } } return(obj); }
private static StringBuilder CreateObjGeometry(List <Dictionary <string, List <WorldVertex[]> > > geometryByTexture, WavefrontExportSettings data) { StringBuilder obj = new StringBuilder(); const string vertexFormatter = "{0} {2} {1}\n"; Dictionary <Vector3D, int> uniqueVerts = new Dictionary <Vector3D, int>(); Dictionary <Vector3D, int> uniqueNormals = new Dictionary <Vector3D, int>(); Dictionary <PointF, int> uniqueUVs = new Dictionary <PointF, int>(); var vertexDataByTexture = new Dictionary <string, Dictionary <WorldVertex, VertexIndices> >(StringComparer.Ordinal); int pc = 0; int nc = 0; int uvc = 0; //optimize geometry foreach (Dictionary <string, List <WorldVertex[]> > dictionary in geometryByTexture) { foreach (KeyValuePair <string, List <WorldVertex[]> > group in dictionary) { Dictionary <WorldVertex, VertexIndices> vertsData = new Dictionary <WorldVertex, VertexIndices>(); foreach (WorldVertex[] verts in group.Value) { //vertex normals Vector3D n = new Vector3D(verts[0].nx, verts[0].ny, verts[0].nz).GetNormal(); int ni; if (uniqueNormals.ContainsKey(n)) { ni = uniqueNormals[n]; } else { uniqueNormals.Add(n, ++nc); ni = nc; } foreach (WorldVertex v in verts) { if (vertsData.ContainsKey(v)) { continue; } VertexIndices indices = new VertexIndices(); indices.NormalIndex = ni; //vertex coords Vector3D vc = new Vector3D(v.x, v.y, v.z); if (uniqueVerts.ContainsKey(vc)) { indices.PositionIndex = uniqueVerts[vc]; } else { uniqueVerts.Add(vc, ++pc); indices.PositionIndex = pc; } //uv PointF uv = new PointF(v.u, v.v); if (uniqueUVs.ContainsKey(uv)) { indices.UVIndex = uniqueUVs[uv]; } else { uniqueUVs.Add(uv, ++uvc); indices.UVIndex = uvc; } vertsData.Add(v, indices); } } if (vertsData.Count > 0) { if (vertexDataByTexture.ContainsKey(group.Key)) { foreach (KeyValuePair <WorldVertex, VertexIndices> g in vertsData) { vertexDataByTexture[group.Key].Add(g.Key, g.Value); } } else { vertexDataByTexture.Add(group.Key, vertsData); } } } } //write geometry //write vertices if (data.FixScale) { foreach (KeyValuePair <Vector3D, int> group in uniqueVerts) { obj.Append(string.Format(CultureInfo.InvariantCulture, "v " + vertexFormatter, -group.Key.x * data.Scale, group.Key.y * data.Scale, group.Key.z * data.Scale * 1.2f)); } } else { foreach (KeyValuePair <Vector3D, int> group in uniqueVerts) { obj.Append(string.Format(CultureInfo.InvariantCulture, "v " + vertexFormatter, -group.Key.x * data.Scale, group.Key.y * data.Scale, group.Key.z * data.Scale)); } } //write normals foreach (KeyValuePair <Vector3D, int> group in uniqueNormals) { obj.Append(string.Format(CultureInfo.InvariantCulture, "vn " + vertexFormatter, group.Key.x, group.Key.y, group.Key.z)); } //write UV coords foreach (KeyValuePair <PointF, int> group in uniqueUVs) { obj.Append(string.Format(CultureInfo.InvariantCulture, "vt {0} {1}\n", group.Key.X, -group.Key.Y)); } //write material library obj.Append("mtllib ").Append(data.ObjName + ".mtl").Append("\n"); //write materials and surface indices foreach (Dictionary <string, List <WorldVertex[]> > dictionary in geometryByTexture) { foreach (KeyValuePair <string, List <WorldVertex[]> > group in dictionary) { //material obj.Append("usemtl ").Append(group.Key).Append("\n"); foreach (WorldVertex[] verts in group.Value) { //surface indices obj.Append("f"); foreach (WorldVertex v in verts) { VertexIndices vi = vertexDataByTexture[group.Key][v]; obj.Append(" " + vi.PositionIndex + "/" + vi.UVIndex + "/" + vi.NormalIndex); } obj.Append("\n"); } } } return(obj); }
public TexturedVertexSet(Texture tex, PrimitiveType mode, IAttributedVertexBuffer buffer, VertexIndices indices, ISet <int> enabledAttribs = null, int depth = 0) : base(mode, buffer, indices, enabledAttribs, depth) { Texture = tex; }
public void AddVertexSet(PrimitiveType mode, V[] vertices, ISet <int> enabledAttribs = null) { AddState(new VertexSet(mode, VBuffer, VertexIndices.FromRange(currentIndex, vertices.Length), enabledAttribs)); AddVertices(vertices); }
public void Import(string FilePath, string MtlPath) { if (File.Exists(MtlPath)) { ParseMtlFile(MtlPath); } if (File.Exists(FilePath)) { var Lines = File.ReadAllLines(FilePath); foreach (var line in Lines) { var Trimmedline = line.TrimStart(new char[] { ' ', '\t' }); if (Trimmedline.StartsWith("vn")) { var tokens = Trimmedline.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); HasNormal = true; if (tokens.Count() >= 4) { Vector3 VN = new Vector3(); VN.X = Convert.ToSingle(tokens[1]); VN.Y = Convert.ToSingle(tokens[2]); VN.Z = Convert.ToSingle(tokens[3]); TempNormalList.Add(VN); } } else if (Trimmedline.StartsWith("v ")) { var tokens = Trimmedline.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (tokens.Count() == 4) { Vector3 V = new Vector3(); V.X = Convert.ToSingle(tokens[1]); V.Y = Convert.ToSingle(tokens[2]); V.Z = Convert.ToSingle(tokens[3]); UpdateMinMaxVertex(ref V); TempVertexList.Add(V); } } else if (Trimmedline.StartsWith("vt")) { HasTexCoordinate = true; var tokens = Trimmedline.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (tokens.Count() >= 3) { Vector2 V = new Vector2(); V.X = Convert.ToSingle(tokens[1]); V.Y = Convert.ToSingle(tokens[2]); TempTexCoordList.Add(V); } } else if (Trimmedline.StartsWith("f ")) { var tokens = Trimmedline.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (tokens.Count() == 4) { var Token1 = tokens[1].Split('/'); var Token2 = tokens[2].Split('/'); var Token3 = tokens[3].Split('/'); uint Index1 = Convert.ToUInt32(Token1[0]); uint Index2 = Convert.ToUInt32(Token2[0]); uint Index3 = Convert.ToUInt32(Token3[0]); VertexIndexList.Add(Index1 - 1); VertexIndexList.Add(Index2 - 1); VertexIndexList.Add(Index3 - 1); if (HasTexCoordinate) { uint TexIndex1 = Convert.ToUInt32(Token1[1]); uint TexIndex2 = Convert.ToUInt32(Token2[1]); uint TexIndex3 = Convert.ToUInt32(Token3[1]); TexCoordIndexList.Add(TexIndex1 - 1); TexCoordIndexList.Add(TexIndex2 - 1); TexCoordIndexList.Add(TexIndex3 - 1); } if (HasNormal) { uint NormIndex1 = Convert.ToUInt32(Token1[2]); uint NormIndex2 = Convert.ToUInt32(Token2[2]); uint NormIndex3 = Convert.ToUInt32(Token3[2]); NormalIndexList.Add(NormIndex1 - 1); NormalIndexList.Add(NormIndex2 - 1); NormalIndexList.Add(NormIndex3 - 1); } VertexIndices.Add((uint)VertexIndices.Count); VertexIndices.Add((uint)VertexIndices.Count); VertexIndices.Add((uint)VertexIndices.Count); } } else if (Trimmedline.StartsWith("usemtl")) { var MtlLine = Trimmedline.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (MtlLine.Count() == 2) { if (MeshSectionList.Count() == 0) { ObjMeshSection NewSection = new ObjMeshSection(); NewSection.StartIndex = 0; NewSection.SectionName = MtlLine[1]; MeshSectionList.Add(NewSection); } else { MeshSectionList.Last().EndIndex = (UInt32)VertexIndices.Count; ObjMeshSection NewSection = new ObjMeshSection(); NewSection.SectionName = MtlLine[1]; NewSection.StartIndex = (UInt32)VertexIndices.Count; MeshSectionList.Add(NewSection); } } } } if (MeshSectionList.Count > 0) { MeshSectionList.Last().EndIndex = (UInt32)VertexIndices.Count; } } // update min,max,center MinVertex = new Vector3(MinX, MinY, MinZ); MaxVertex = new Vector3(MaxX, MaxY, MaxZ); CenterVertex = (MinVertex + MaxVertex) / 2; if (HasTexCoordinate) { GenerateTangents(); } GenerateVertices(); Clear(); }