private static MashTrigle GetMashTrigle(string fname) { MashTrigle result = new MashTrigle(); using (FileStream fs = new FileStream(fname, FileMode.Open)) { using (BinaryReader reader = new BinaryReader(fs)) { long flen = fs.Length; if (flen % 108 != 0) { throw new Exception("不是正确的文件"); } int facecount = (int)(flen / 108); TrigleFace[] trigles = new TrigleFace[facecount]; for (int i = 0; i < facecount; i++) { Vector3f v0, v1, v2, vt0, vt1, vt2, vn0, vn1, vn2; v0 = ReadAVector(reader); vt0 = ReadAVector(reader); vn0 = ReadAVector(reader); v1 = ReadAVector(reader); vt1 = ReadAVector(reader); vn1 = ReadAVector(reader); v2 = ReadAVector(reader); vt2 = ReadAVector(reader); vn2 = ReadAVector(reader); TrigleFace face = new TrigleFace(v0, v1, v2) { sp0 = new Vector2f(vt0.X, vt0.Y), sp1 = new Vector2f(vt1.X, vt1.Y), sp2 = new Vector2f(vt2.X, vt2.Y), n0 = vn0, n1 = vn1, n2 = vn2 }; trigles[i] = face; } result.SetTrigles(trigles); } } return(result); }
static TrigleFace[] Smooth(List <PW_Trigle> faces, List <Vector3f> v, List <Vector2f> vt, Dictionary <int, List <PW_Trigle> > faceList) { if (faces == null || faces.Count == 0) { return(null); } Dictionary <int, Vector3f> pointNormal = new Dictionary <int, Vector3f>(); TrigleFace[] re = new TrigleFace[faces.Count]; foreach (KeyValuePair <int, List <PW_Trigle> > kv in faceList) { Vector3f n = new Vector3f(); foreach (PW_Trigle trigle in kv.Value) { n += trigle.Normal; } n = Vector3f.Normalize(n); pointNormal[kv.Key] = n; } int idx = 0; foreach (PW_Trigle trigle in faces) { TrigleFace t = new TrigleFace(v[trigle.v0], v[trigle.v1], v[trigle.v2]); t.sp0 = vt[trigle.vt0]; t.sp1 = vt[trigle.vt1]; t.sp2 = vt[trigle.vt2]; t.n0 = pointNormal[trigle.v0]; t.n1 = pointNormal[trigle.v1]; t.n2 = pointNormal[trigle.v2]; re[idx] = t; idx++; } return(re); }
public static MashTrigle[] LoadModel(string filePath, bool negativeZ = false) { string[] lines = File.ReadAllLines(filePath); List <MashTrigle> mashes = new List <MashTrigle>(); List <Vector3f> v = new List <Vector3f>() { new Vector3f() }; List <Vector2f> vt = new List <Vector2f>() { new Vector2f() }; List <Vector3f> vn = new List <Vector3f>() { new Vector3f() }; MashTrigle nobj = null; List <TrigleFace> trigles = new List <TrigleFace>(); for (int linecount = 0; linecount < lines.Length; linecount++) { string line = lines[linecount]; if (string.IsNullOrWhiteSpace(line) || line.StartsWith('#')) { continue; } float p0 = 0.0f, p1 = 0.0f, p2 = 0.0f; string[] parts = line.Split(LineSplitChars, StringSplitOptions.RemoveEmptyEntries); switch (parts[0].ToLower()) { case "v": #region v if (parts.Length != 4) { throw new Exception($"line {linecount} : 缺少参数的行,请求3个,实际为{parts.Length - 1}个"); } if (!Float.TryParse(parts[1], out p0)) { throw new Exception($"line {linecount} : 不能转换的数据 {parts[1]}"); } if (!Float.TryParse(parts[2], out p1)) { throw new Exception($"line {linecount} : 不能转换的数据 {parts[2]}"); } if (!Float.TryParse(parts[3], out p2)) { throw new Exception($"line {linecount} : 不能转换的数据 {parts[3]}"); } if (negativeZ) { v.Add(new Vector3f(p0, p1, -p2)); } else { v.Add(new Vector3f(p0, p1, p2)); } #endregion break; case "vt": #region vt if (parts.Length != 3 && parts.Length != 4) { throw new Exception($"line {linecount} : 缺少参数的行,请求2或3个,实际为{parts.Length - 1}个"); } if (!Float.TryParse(parts[1], out p0)) { throw new Exception($"line {linecount} : 不能转换的数据 {parts[1]}"); } if (!Float.TryParse(parts[2], out p1)) { throw new Exception($"line {linecount} : 不能转换的数据 {parts[2]}"); } vt.Add(new Vector2f(p0, p1)); #endregion break; case "vn": #region vn if (parts.Length != 4) { throw new Exception($"line {linecount} : 缺少参数的行,请求3个,实际为{parts.Length - 1}个"); } if (!Float.TryParse(parts[1], out p0)) { throw new Exception($"line {linecount} : 不能转换的数据 {parts[1]}"); } if (!Float.TryParse(parts[2], out p1)) { throw new Exception($"line {linecount} : 不能转换的数据 {parts[2]}"); } if (!Float.TryParse(parts[3], out p2)) { throw new Exception($"line {linecount} : 不能转换的数据 {parts[3]}"); } if (negativeZ) { vn.Add(Vector3f.Normalize(new Vector3f(p0, p1, -p2))); } else { vn.Add(Vector3f.Normalize(new Vector3f(p0, p1, p2))); } #endregion break; case "vp": break; case "g": #region g if (trigles != null && trigles.Count > 0) { if (nobj == null) { nobj = new MashTrigle(); } nobj.SetTrigles(trigles.ToArray()); mashes.Add(nobj); } nobj = new MashTrigle(); trigles = new List <TrigleFace>(); #endregion break; case "f": #region f if (parts.Length < 4) { throw new Exception($"line {linecount} : 缺少参数的行,请求至少为3个,实际为{parts.Length - 1}个"); } int pointcount = parts.Length - 1; int[] vidx = new int[pointcount], vtidx = new int[pointcount], vnidx = new int[pointcount]; // 分割顶点信息 for (int i = 0; i < pointcount; i++) { string pinfo = parts[i + 1]; string[] infos = pinfo.Split(PInfoSplitChars); vidx[i] = int.Parse(infos[0]); int tmp; if (infos.Length > 1 && int.TryParse(infos[1], out tmp)) { vtidx[i] = tmp; } else { vtidx[i] = -1; } if (infos.Length > 2 && int.TryParse(infos[1], out tmp)) { vnidx[i] = tmp; } else { vnidx[i] = -1; } } // 生成三角形面 for (int i = 2; i < pointcount; i++) { TrigleFace face = new TrigleFace(v[vidx[0]], v[vidx[i - 1]], v[vidx[i]]); { //normal Vector3f facenormal = new Vector3f(); if (vnidx[0] == -1 || vnidx[i - 1] == -1 || vnidx[i] == -1) { facenormal = Vector3f.Normalize(Vector3f.Cross(face.e1, face.e2)); } if (vnidx[0] == -1) { face.n0 = facenormal; } else { face.n0 = vn[vnidx[0]]; } if (vnidx[i - 1] == -1) { face.n1 = facenormal; } else { face.n1 = vn[vnidx[i - 1]]; } if (vnidx[i] == -1) { face.n2 = facenormal; } else { face.n2 = vn[vnidx[i]]; } } { //sp if (vtidx[0] != -1) { face.sp0 = vt[vtidx[0]]; } if (vtidx[i - 1] != -1) { face.sp1 = vt[vtidx[i - 1]]; } if (vtidx[i] != -1) { face.sp2 = vt[vtidx[i]]; } } trigles.Add(face); } #endregion break; } } if (trigles != null && trigles.Count > 0) { if (nobj == null) { nobj = new MashTrigle(); } nobj.SetTrigles(trigles.ToArray()); mashes.Add(nobj); } return(mashes.ToArray()); }