static unsafe Object CreateObject(mqoIO.Object original, Material[] materials) { var vertexes = new List<Vertex>(); var faces = new List<Face>(); var obj = new Object(); obj.Name = original.Name; // 頂点一時コピー foreach (var vertex in original.Vertexes) { var v = new Vertex(); v.Position.X = vertex.X; v.Position.Y = vertex.Y; v.Position.Z = vertex.Z; vertexes.Add(v); } // 面一時コピー foreach (var face in original.Faces) { if (face.Indexes.Count() == 2) { } else if (face.Indexes.Count() == 3) { var f = new Face(); f.Indexes[0] = face.Indexes[0]; f.Indexes[1] = face.Indexes[1]; f.Indexes[2] = face.Indexes[2]; f.Colors[0] = face.Colors[0]; f.Colors[1] = face.Colors[1]; f.Colors[2] = face.Colors[2]; f.UV[0].X = face.UV[0 * 2 + 0]; f.UV[0].Y = face.UV[0 * 2 + 1]; f.UV[1].X = face.UV[1 * 2 + 0]; f.UV[1].Y = face.UV[1 * 2 + 1]; f.UV[2].X = face.UV[2 * 2 + 0]; f.UV[2].Y = face.UV[2 * 2 + 1]; f.Material = face.MaterialIndex; if (f.Material < 0) f.Material = materials.Length - 1; faces.Add(f); } if (face.Indexes.Count() == 4) { var f1 = new Face(); f1.Indexes[0] = face.Indexes[0]; f1.Indexes[1] = face.Indexes[1]; f1.Indexes[2] = face.Indexes[2]; f1.Colors[0] = face.Colors[0]; f1.Colors[1] = face.Colors[1]; f1.Colors[2] = face.Colors[2]; f1.UV[0].X = face.UV[0 * 2 + 0]; f1.UV[0].Y = face.UV[0 * 2 + 1]; f1.UV[1].X = face.UV[1 * 2 + 0]; f1.UV[1].Y = face.UV[1 * 2 + 1]; f1.UV[2].X = face.UV[2 * 2 + 0]; f1.UV[2].Y = face.UV[2 * 2 + 1]; f1.Material = face.MaterialIndex; if (f1.Material < 0) f1.Material = materials.Length - 1; faces.Add(f1); var f2 = new Face(); f2.Indexes[0] = face.Indexes[0]; f2.Indexes[1] = face.Indexes[2]; f2.Indexes[2] = face.Indexes[3]; f2.Colors[0] = face.Colors[0]; f2.Colors[1] = face.Colors[2]; f2.Colors[2] = face.Colors[3]; f2.UV[0].X = face.UV[0 * 2 + 0]; f2.UV[0].Y = face.UV[0 * 2 + 1]; f2.UV[1].X = face.UV[2 * 2 + 0]; f2.UV[1].Y = face.UV[2 * 2 + 1]; f2.UV[2].X = face.UV[3 * 2 + 0]; f2.UV[2].Y = face.UV[3 * 2 + 1]; f2.Material = face.MaterialIndex; if (f2.Material < 0) f2.Material = materials.Length - 1; faces.Add(f2); } } // 法線による分割 { var normals = new Vector3D[faces.Count]; var vertextoface = new Dictionary<int, List<int>>(); for (int i = 0; i < vertexes.Count; i++) { vertextoface.Add(i, new List<int>()); } // 法線を求める+所属頂点を設定 foreach (var fiv in faces.Select((v, i) => new { v, i })) { var fv = fiv.v; var v1 = vertexes[fv.Indexes[0]].Position - vertexes[fv.Indexes[1]].Position; var v2 = vertexes[fv.Indexes[2]].Position - vertexes[fv.Indexes[1]].Position; Vector3D n; Vector3D.Cross(out n, ref v1, ref v2); Vector3D.Normal(out n, ref n); normals[fiv.i] = n; vertextoface[fv.Indexes[0]].Add(fiv.i); vertextoface[fv.Indexes[1]].Add(fiv.i); vertextoface[fv.Indexes[2]].Add(fiv.i); } // 面の法線から頂点分離 foreach (var vf in vertextoface) { var fgroup = new List<List<int>>(); // 分別 foreach (var fi in vf.Value) { var setted = false; foreach (var fg in fgroup) { Vector3D cross; Vector3D.Cross(out cross, ref normals[fg[0]], ref normals[fi]); var s = cross.GetLength(); var c = Vector3D.Dot(ref normals[fg[0]], ref normals[fi]); if (Math.Atan2(s, c) < original.Facet / 180.0 * 3.14) { fg.Add(fi); setted = true; break; } } if (!setted) { fgroup.Add(new List<int>(new int[] { fi })); } } // 分離 if (fgroup.Count > 1) { for (int i = 1; i < fgroup.Count; i++) { // 新規頂点 vertexes.Add(new Vertex()); var oldV = vf.Key; var newV = vertexes.Count - 1; vertexes[newV] = vertexes[oldV].Clone(); foreach (var fi in fgroup[i]) { var f = faces[fi]; if (f.Indexes[0] == oldV) f.Indexes[0] = newV; if (f.Indexes[1] == oldV) f.Indexes[1] = newV; if (f.Indexes[2] == oldV) f.Indexes[2] = newV; faces[fi] = f; } } } } // クリア foreach (var bt in vertextoface) { bt.Value.Clear(); } // 所属頂点を設定 foreach (var fiv in faces.Select((v, i) => new { v, i })) { for (int loop = 0; loop < 3; loop++) { var fv = fiv.v; if (!vertextoface.ContainsKey(fv.Indexes[loop])) { vertextoface.Add(fv.Indexes[loop], new List<int>()); } vertextoface[fv.Indexes[loop]].Add(fiv.i); } } // 法線を設定 foreach (var vf in vertextoface) { var v = vertexes[vf.Key]; Vector3D normal = new Vector3D(); foreach (var f in vf.Value) { normal.X += normals[f].X; normal.Y += normals[f].Y; normal.Z += normals[f].Z; } normal.X /= (float)vf.Value.Count(); normal.Y /= (float)vf.Value.Count(); normal.Z /= (float)vf.Value.Count(); v.Normal = normal; vertexes[vf.Key] = v; } { } // UV,Color設定 { // 元の頂点とそこから派生した頂点インデックスへのDictoinary var originalToVertex = new Dictionary<int, List<int>>(); foreach (var v in vertexes.Select((v, i) => new { v, i })) { originalToVertex.Add(v.i, new List<int>()); } // 面の値を元に頂点を差し替え foreach (var f in faces.Select((v, i) => new { v, i })) { var face = faces[f.i]; for (int v = 0; v < 3; v++) { var vert = vertexes[face.Indexes[v]]; var o2v = originalToVertex[face.Indexes[v]]; if (o2v.Count == 0) { // 新規 vert.UV = face.UV[v]; vert.Color = face.Colors[v]; o2v.Add(face.Indexes[v]); } else { // 探索 bool found = false; foreach (var vind in o2v) { if (vertexes[vind].UV == face.UV[v] && vertexes[vind].Color == face.Colors[v]) { face.Indexes[v] = vind; found = true; break; } } if (found) continue; // 追加 var newVert = new Vertex(); newVert.Position = vert.Position; newVert.Normal = vert.Normal; newVert.UV = face.UV[v]; newVert.Color = face.Colors[v]; o2v.Add(vertexes.Count); face.Indexes[v] = vertexes.Count; vertexes.Add(newVert); } } } } } // 面材質によるソート { faces = faces.OrderBy(f => f.Material).ToList(); } obj.Vertexes = vertexes.ToArray(); obj.Faces = faces.ToArray(); AppendTangentAndBinormal(obj); return obj; }
static unsafe Object CreateObject(mqoIO.Object original, Material[] materials) { var vertexes = new List <Vertex>(); var faces = new List <Face>(); var obj = new Object(); obj.Name = original.Name; // 頂点一時コピー foreach (var vertex in original.Vertexes) { var v = new Vertex(); v.Position.X = vertex.X; v.Position.Y = vertex.Y; v.Position.Z = vertex.Z; vertexes.Add(v); } // 面一時コピー foreach (var face in original.Faces) { if (face.Indexes.Count() == 2) { } else if (face.Indexes.Count() == 3) { var f = new Face(); f.Indexes[0] = face.Indexes[0]; f.Indexes[1] = face.Indexes[1]; f.Indexes[2] = face.Indexes[2]; f.Colors[0] = face.Colors[0]; f.Colors[1] = face.Colors[1]; f.Colors[2] = face.Colors[2]; f.UV[0].X = face.UV[0 * 2 + 0]; f.UV[0].Y = face.UV[0 * 2 + 1]; f.UV[1].X = face.UV[1 * 2 + 0]; f.UV[1].Y = face.UV[1 * 2 + 1]; f.UV[2].X = face.UV[2 * 2 + 0]; f.UV[2].Y = face.UV[2 * 2 + 1]; f.Material = face.MaterialIndex; if (f.Material < 0) { f.Material = materials.Length - 1; } faces.Add(f); } if (face.Indexes.Count() == 4) { var f1 = new Face(); f1.Indexes[0] = face.Indexes[0]; f1.Indexes[1] = face.Indexes[1]; f1.Indexes[2] = face.Indexes[2]; f1.Colors[0] = face.Colors[0]; f1.Colors[1] = face.Colors[1]; f1.Colors[2] = face.Colors[2]; f1.UV[0].X = face.UV[0 * 2 + 0]; f1.UV[0].Y = face.UV[0 * 2 + 1]; f1.UV[1].X = face.UV[1 * 2 + 0]; f1.UV[1].Y = face.UV[1 * 2 + 1]; f1.UV[2].X = face.UV[2 * 2 + 0]; f1.UV[2].Y = face.UV[2 * 2 + 1]; f1.Material = face.MaterialIndex; if (f1.Material < 0) { f1.Material = materials.Length - 1; } faces.Add(f1); var f2 = new Face(); f2.Indexes[0] = face.Indexes[0]; f2.Indexes[1] = face.Indexes[2]; f2.Indexes[2] = face.Indexes[3]; f2.Colors[0] = face.Colors[0]; f2.Colors[1] = face.Colors[2]; f2.Colors[2] = face.Colors[3]; f2.UV[0].X = face.UV[0 * 2 + 0]; f2.UV[0].Y = face.UV[0 * 2 + 1]; f2.UV[1].X = face.UV[2 * 2 + 0]; f2.UV[1].Y = face.UV[2 * 2 + 1]; f2.UV[2].X = face.UV[3 * 2 + 0]; f2.UV[2].Y = face.UV[3 * 2 + 1]; f2.Material = face.MaterialIndex; if (f2.Material < 0) { f2.Material = materials.Length - 1; } faces.Add(f2); } } // 法線による分割 { var normals = new Vector3D[faces.Count]; var vertextoface = new Dictionary <int, List <int> >(); for (int i = 0; i < vertexes.Count; i++) { vertextoface.Add(i, new List <int>()); } // 法線を求める+所属頂点を設定 foreach (var fiv in faces.Select((v, i) => new { v, i })) { var fv = fiv.v; var v1 = vertexes[fv.Indexes[0]].Position - vertexes[fv.Indexes[1]].Position; var v2 = vertexes[fv.Indexes[2]].Position - vertexes[fv.Indexes[1]].Position; Vector3D n; Vector3D.Cross(out n, ref v1, ref v2); Vector3D.Normal(out n, ref n); normals[fiv.i] = n; vertextoface[fv.Indexes[0]].Add(fiv.i); vertextoface[fv.Indexes[1]].Add(fiv.i); vertextoface[fv.Indexes[2]].Add(fiv.i); } // 面の法線から頂点分離 foreach (var vf in vertextoface) { var fgroup = new List <List <int> >(); // 分別 foreach (var fi in vf.Value) { var setted = false; foreach (var fg in fgroup) { Vector3D cross; Vector3D.Cross(out cross, ref normals[fg[0]], ref normals[fi]); var s = cross.GetLength(); var c = Vector3D.Dot(ref normals[fg[0]], ref normals[fi]); if (Math.Atan2(s, c) < original.Facet / 180.0 * 3.14) { fg.Add(fi); setted = true; break; } } if (!setted) { fgroup.Add(new List <int>(new int[] { fi })); } } // 分離 if (fgroup.Count > 1) { for (int i = 1; i < fgroup.Count; i++) { // 新規頂点 vertexes.Add(new Vertex()); var oldV = vf.Key; var newV = vertexes.Count - 1; vertexes[newV] = vertexes[oldV].Clone(); foreach (var fi in fgroup[i]) { var f = faces[fi]; if (f.Indexes[0] == oldV) { f.Indexes[0] = newV; } if (f.Indexes[1] == oldV) { f.Indexes[1] = newV; } if (f.Indexes[2] == oldV) { f.Indexes[2] = newV; } faces[fi] = f; } } } } // クリア foreach (var bt in vertextoface) { bt.Value.Clear(); } // 所属頂点を設定 foreach (var fiv in faces.Select((v, i) => new { v, i })) { for (int loop = 0; loop < 3; loop++) { var fv = fiv.v; if (!vertextoface.ContainsKey(fv.Indexes[loop])) { vertextoface.Add(fv.Indexes[loop], new List <int>()); } vertextoface[fv.Indexes[loop]].Add(fiv.i); } } // 法線を設定 foreach (var vf in vertextoface) { var v = vertexes[vf.Key]; Vector3D normal = new Vector3D(); foreach (var f in vf.Value) { normal.X += normals[f].X; normal.Y += normals[f].Y; normal.Z += normals[f].Z; } normal.X /= (float)vf.Value.Count(); normal.Y /= (float)vf.Value.Count(); normal.Z /= (float)vf.Value.Count(); v.Normal = normal; vertexes[vf.Key] = v; } { } // UV,Color設定 { // 元の頂点とそこから派生した頂点インデックスへのDictoinary var originalToVertex = new Dictionary <int, List <int> >(); foreach (var v in vertexes.Select((v, i) => new { v, i })) { originalToVertex.Add(v.i, new List <int>()); } // 面の値を元に頂点を差し替え foreach (var f in faces.Select((v, i) => new { v, i })) { var face = faces[f.i]; for (int v = 0; v < 3; v++) { var vert = vertexes[face.Indexes[v]]; var o2v = originalToVertex[face.Indexes[v]]; if (o2v.Count == 0) { // 新規 vert.UV = face.UV[v]; vert.Color = face.Colors[v]; o2v.Add(face.Indexes[v]); } else { // 探索 bool found = false; foreach (var vind in o2v) { if (vertexes[vind].UV == face.UV[v] && vertexes[vind].Color == face.Colors[v]) { face.Indexes[v] = vind; found = true; break; } } if (found) { continue; } // 追加 var newVert = new Vertex(); newVert.Position = vert.Position; newVert.Normal = vert.Normal; newVert.UV = face.UV[v]; newVert.Color = face.Colors[v]; o2v.Add(vertexes.Count); face.Indexes[v] = vertexes.Count; vertexes.Add(newVert); } } } } } // 面材質によるソート { faces = faces.OrderBy(f => f.Material).ToList(); } obj.Vertexes = vertexes.ToArray(); obj.Faces = faces.ToArray(); AppendTangentAndBinormal(obj); return(obj); }