public static void Write(Model model, string name, ParsingFlags ps = ParsingFlags.WriteAll) { int mi = 0, ei = 0; foreach (ModelMesh mesh in model.Meshes) { // Get All The Distinct Meshes foreach (ModelMeshPart mp in mesh.MeshParts.Distinct(new MMComp())) { string nfObj = name + "." + mi + ".obj"; StreamWriter fObj = new StreamWriter(new BufferedStream(File.Create(nfObj))); WriteObj(new MeshPart(mp), fObj, ps); fObj.Flush(); fObj.Close(); mi++; } // Get All The Distinct Effects foreach (EffectMaterial e in mesh.Effects) { string nfEff = name + "." + ei + ".fxc"; StreamWriter fEff = new StreamWriter(new BufferedStream(File.Create(nfEff))); WriteEffect(e, fEff); fEff.Flush(); fEff.Close(); ei++; } } }
private void LoadBulletModel(RTSRenderer renderer, Stream s, ParsingFlags pf = ParsingFlags.ConversionOpenGL) { VertexPositionNormalTexture[] v; int[] inds; ObjParser.TryParse(s, out v, out inds, pf); VertexPositionTexture[] verts = new VertexPositionTexture[v.Length]; for (int i = 0; i < verts.Length; i++) { verts[i].Position = v[i].Position; verts[i].TextureCoordinate = v[i].TextureCoordinate; } plBullets.VBuffer = renderer.CreateVertexBuffer(VertexPositionTexture.VertexDeclaration, verts.Length, BufferUsage.WriteOnly); plBullets.VBuffer.SetData(verts); plBullets.IBuffer = renderer.CreateIndexBuffer(IndexElementSize.ThirtyTwoBits, inds.Length, BufferUsage.WriteOnly); plBullets.IBuffer.SetData(inds); }
public static bool TryParse(Stream s, out ObjTriangle[] tris, ParsingFlags ps = ParsingFlags.None) { VertexPositionNormalTexture[] verts; int[] inds; if (TryParse(s, out verts, out inds, ps)) { tris = new ObjTriangle[inds.Length / 3]; for (int ti = 0, i = 0; ti < tris.Length; ti++) { tris[ti] = new ObjTriangle( verts[inds[i]], verts[inds[i + 1]], verts[inds[i + 2]] ); i += 3; } return(true); } tris = null; return(false); }
public static void WriteObj(MeshPart mp, StreamWriter writer, ParsingFlags ps = ParsingFlags.WriteAll) { ParsingFlags capable = ParsingFlags.None; // Loop Through All Vertex Elements VertexElement[] elements = mp.VBuffer.VertexDeclaration.GetVertexElements(); foreach (VertexElement ve in elements) { // Choose Formatting Functions By Type switch (ve.VertexElementFormat) { case VertexElementFormat.Vector2: WriteElement <Vector2>(writer, ve, mp, Format, ref capable); break; case VertexElementFormat.Vector3: WriteElement <Vector3>(writer, ve, mp, Format, ref capable); break; case VertexElementFormat.Vector4: WriteElement <Vector4>(writer, ve, mp, Format, ref capable); break; case VertexElementFormat.Single: WriteElement <float>(writer, ve, mp, Format, ref capable); break; case VertexElementFormat.Color: WriteElement <Color>(writer, ve, mp, Format, ref capable); break; case VertexElementFormat.Byte4: WriteElement <Color>(writer, ve, mp, Format, ref capable); break; default: // Those Are The Basic Types break; } } // Only Write What Is Capable ps &= capable; // Write Indices switch (mp.IBuffer.IndexElementSize) { case IndexElementSize.SixteenBits: WriteIndices <short>(writer, mp, Format, ps); break; case IndexElementSize.ThirtyTwoBits: WriteIndices <int>(writer, mp, Format, ps); break; } }
static void WriteIndices <T>(StreamWriter writer, MeshPart mp, Func <T, int> formatter, ParsingFlags ps) where T : struct { IndexBuffer iBuffer = mp.IBuffer; T[] data = new T[mp.NumIndices]; int iSize = mp.IBuffer.IndexElementSize == IndexElementSize.SixteenBits ? 2 : 4; mp.IBuffer.GetData(mp.StartIndex * iSize, data, 0, data.Length); int i = 0; while (i < data.Length) { writer.Write("f"); for (int vi = 0; vi < 3 && i < data.Length; vi++) { int vert; if (ps.HasFlag(ParsingFlags.FlipTriangleOrder)) { vert = formatter(data[i + (2 - vi)]) + 1; } else { vert = formatter(data[i + vi]) + 1; } writer.Write(" " + vert); writer.Write("/"); if (ps.HasFlag(ParsingFlags.WriteUV)) { writer.Write(vert); } writer.Write("/"); if (ps.HasFlag(ParsingFlags.WriteNorms)) { writer.Write(vert); } } i += 3; writer.WriteLine(""); } }
static void WriteElementByUsage <T>(StreamWriter writer, T[] data, VertexElement ve, Func <T, string> formatter, ref ParsingFlags ps) { switch (ve.VertexElementUsage) { case VertexElementUsage.Position: if (ve.UsageIndex == 0) { WriteAllElements(writer, data, "v", formatter); } else { WriteAllElements(writer, data, "v" + ve.UsageIndex, formatter); } break; case VertexElementUsage.Normal: ps |= ParsingFlags.WriteNorms; if (ve.UsageIndex == 0) { WriteAllElements(writer, data, "vn", formatter); } else { WriteAllElements(writer, data, "vn" + ve.UsageIndex, formatter); } break; case VertexElementUsage.TextureCoordinate: ps |= ParsingFlags.WriteUV; if (ps.HasFlag(ParsingFlags.FlipTexCoordV)) { Vector2[] vt = data as Vector2[]; if (vt != null) { for (int i = 0; i < vt.Length; i++) { vt[i].Y = 1 - vt[i].Y; } data = vt as T[]; } } if (ve.UsageIndex == 0) { WriteAllElements(writer, data, "vt", formatter); } else { WriteAllElements(writer, data, "vt" + ve.UsageIndex, formatter); } break; case VertexElementUsage.Color: ps |= ParsingFlags.WriteColor; if (ve.UsageIndex == 0) { WriteAllElements(writer, data, "vc", formatter); } else { WriteAllElements(writer, data, "vc" + ve.UsageIndex, formatter); } break; } }
static void WriteElement <T>(StreamWriter writer, VertexElement ve, MeshPart mp, Func <T, string> formatter, ref ParsingFlags ps) where T : struct { T[] data = new T[mp.NumVertices]; mp.VBuffer.GetData(ve.Offset + mp.VertexOffset * mp.VertexStride, data, 0, data.Length, mp.VertexStride); WriteElementByUsage(writer, data, ve, formatter, ref ps); }
public static bool TryParse(Stream s, GraphicsDevice g, out VertexBuffer vb, out IndexBuffer ib, ParsingFlags ps = ParsingFlags.None) { VertexPositionNormalTexture[] verts; int[] inds; if (!TryParse(s, out verts, out inds, ps)) { vb = null; ib = null; return(false); } vb = new VertexBuffer(g, VertexPositionNormalTexture.VertexDeclaration, verts.Length, BufferUsage.WriteOnly); vb.SetData(verts); ib = new IndexBuffer(g, IndexElementSize.ThirtyTwoBits, inds.Length, BufferUsage.WriteOnly); ib.SetData(inds); return(true); }
public static bool TryParse(Stream s, GraphicsDevice g, ContentManager c, out Effect fx, ref List <object> refs, ParsingFlags ps = ParsingFlags.None) { fx = null; StreamReader f = new StreamReader(new BufferedStream(s)); // Get The Arguments From The Material File List <string[]> args = new List <string[]>(); while (!f.EndOfStream) { string line = f.ReadLine(); if (string.IsNullOrWhiteSpace(line)) { continue; } string[] split = line.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries); if (split.Length < 1) { continue; } split[0] = split[0].Trim().ToLower(); switch (split[0]) { case "fx": if (split.Length >= 2) { args.Add(split); } break; case "fxpt": if (split.Length >= 3) { args.Add(split); } break; case "fxptc": if (split.Length >= 3) { args.Add(split); } break; case "fxpf": if (split.Length >= 4) { args.Add(split); } break; } } // Get The Effect For This Material Predicate <string[]> fxMatch = (a) => { return(a[0].Equals("fx")); }; string[] fxArg = args.Find(fxMatch); if (fxArg == null) { return(false); } args.RemoveAll(fxMatch); // Try To Create The Effect if (ps.HasFlag(ParsingFlags.LoadEffectByteCode)) { try { byte[] code = null; using (FileStream fxs = File.OpenRead(fxArg[1].Trim())) { code = new byte[fxs.Length]; fxs.Read(code, 0, code.Length); } fx = new Effect(g, code); } catch (Exception) { fx = null; return(false); } } else { try { fx = c.Load <Effect>(fxArg[1].Trim()); } catch (Exception) { fx = null; return(false); } } // Will Attempt To Set As Many Uniforms As Possible Without Raising Errors foreach (string[] arg in args) { switch (arg[0]) { case "fxpt": EffectParameter fxpt = fx.Parameters[arg[1].Trim()]; if (fxpt == null) { continue; } try { Texture2D t = null; if (ps.HasFlag(ParsingFlags.LoadTextureStream)) { using (FileStream ts = File.OpenRead(arg[2].Trim())) { t = Texture2D.FromStream(g, ts); } } else { t = c.Load <Texture2D>(arg[2].Trim()); } if (t != null) { refs.Add(t); fxpt.SetValue(t); } } catch (Exception) { continue; } break; case "fxptc": // Texture Cube Parameter EffectParameter fxptc = fx.Parameters[arg[1].Trim()]; if (fxptc == null) { continue; } try { TextureCube tc = c.Load <TextureCube>(arg[2].Trim()); if (tc != null) { refs.Add(tc); fxptc.SetValue(tc); } } catch (Exception) { continue; } break; case "fxpf": // Vector Parameter EffectParameter fxptv = fx.Parameters[arg[1].Trim()]; int comps; if (fxptv == null || !int.TryParse(arg[2], out comps)) { continue; } string[] sc = arg[3].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (sc.Length != comps) { continue; } switch (comps) { case 1: float v1; if (float.TryParse(sc[0], out v1)) { fxptv.SetValue(v1); } break; case 2: Vector2 v2 = Vector2.Zero; if (float.TryParse(sc[0], out v2.X) && float.TryParse(sc[1], out v2.Y) ) { fxptv.SetValue(v2); } break; case 3: Vector3 v3 = Vector3.Zero; if (float.TryParse(sc[0], out v3.X) && float.TryParse(sc[1], out v3.Y) && float.TryParse(sc[2], out v3.Z) ) { fxptv.SetValue(v3); } break; case 4: Vector4 v4 = Vector4.Zero; if (float.TryParse(sc[0], out v4.X) && float.TryParse(sc[1], out v4.Y) && float.TryParse(sc[2], out v4.Z) && float.TryParse(sc[3], out v4.W) ) { fxptv.SetValue(v4); } break; default: if (comps > 4) { float[] vn = new float[comps]; bool vnc = true; for (int i = 0; i < sc.Length && i < vn.Length && vnc; i++) { if (!float.TryParse(sc[i], out vn[i])) { vnc = false; } } if (vnc) { fxptv.SetValue(vn); } } break; } break; } } return(true); }
public static bool TryParse(Stream s, out VertexPositionNormalTexture[] verts, out int[] inds, ParsingFlags ps = ParsingFlags.None) { // Default Values verts = null; inds = null; // Encapsulate Stream To A Buffered Stream Reader BufferedStream bs = new BufferedStream(s); StreamReader f = new StreamReader(bs); // List Of Components List <Vector3> pos = new List <Vector3>(100); List <Vector2> uv = new List <Vector2>(100); List <Vector3> norms = new List <Vector3>(100); List <Tri> tris = new List <Tri>(200); // Buffer Vectors Vector3 v3 = Vector3.Zero; Vector2 v2 = Vector2.Zero; // Get All The Information From The Stream string line; string[] spl; while (!f.EndOfStream) { line = f.ReadLine(); spl = Regex.Split(line, @"\s+", RegexOptions.IgnorePatternWhitespace); switch (spl[0].ToLower()) { case "v": // Vertex Position if (spl.Length != 4) { return(false); } if (!float.TryParse(spl[1], out v3.X)) { return(false); } if (!float.TryParse(spl[2], out v3.Y)) { return(false); } if (!float.TryParse(spl[3], out v3.Z)) { return(false); } pos.Add(v3); break; case "vt": // Vertex Texture Coordinate if (spl.Length != 3) { return(false); } if (!float.TryParse(spl[1], out v2.X)) { return(false); } if (!float.TryParse(spl[2], out v2.Y)) { return(false); } // Possibly Flip Tex Coords if (ps.HasFlag(ParsingFlags.FlipTexCoordV)) { v2.Y = 1 - v2.Y; } uv.Add(v2); break; case "vn": // Vertex Normal if (spl.Length != 4) { return(false); } if (!float.TryParse(spl[1], out v3.X)) { return(false); } if (!float.TryParse(spl[2], out v3.Y)) { return(false); } if (!float.TryParse(spl[3], out v3.Z)) { return(false); } norms.Add(v3); break; case "f": // Mesh Triangle if (spl.Length != 4) { return(false); } try { // Add In Correct Triangle Ordering if (ps.HasFlag(ParsingFlags.FlipTriangleOrder)) { tris.Add(new Tri(spl[1], spl[3], spl[2])); } else { tris.Add(new Tri(spl[1], spl[2], spl[3])); } } catch (Exception) { return(false); } break; } } // Create Indices VertDict vd = new VertDict(); inds = new int[tris.Count * 3]; int ii = 0; foreach (Tri tri in tris) { inds[ii++] = vd.Get(tri.V1); inds[ii++] = vd.Get(tri.V2); inds[ii++] = vd.Get(tri.V3); } // Create Vertices verts = new VertexPositionNormalTexture[vd.Count]; foreach (VertDict.Key v in vd) { verts[v.Index].Position = pos[v.Vertex.PosInd]; if (v.Vertex.UVInd < 0) { verts[v.Index].TextureCoordinate = Vector2.Zero; } else { verts[v.Index].TextureCoordinate = uv[v.Vertex.UVInd]; } if (v.Vertex.NormInd < 0) { verts[v.Index].Normal = Vector3.Zero; } else { verts[v.Index].Normal = norms[v.Vertex.NormInd]; } } return(true); }
private void LoadBulletModel(RTSRenderer renderer, Stream s, ParsingFlags pf = ParsingFlags.ConversionOpenGL) { VertexPositionNormalTexture[] v; int[] inds; ObjParser.TryParse(s, out v, out inds, pf); VertexPositionTexture[] verts = new VertexPositionTexture[v.Length]; for(int i = 0; i < verts.Length; i++) { verts[i].Position = v[i].Position; verts[i].TextureCoordinate = v[i].TextureCoordinate; } plBullets.VBuffer = renderer.CreateVertexBuffer(VertexPositionTexture.VertexDeclaration, verts.Length, BufferUsage.WriteOnly); plBullets.VBuffer.SetData(verts); plBullets.IBuffer = renderer.CreateIndexBuffer(IndexElementSize.ThirtyTwoBits, inds.Length, BufferUsage.WriteOnly); plBullets.IBuffer.SetData(inds); }