public G3dMesh(G3D parent, int index) { (G3D, Index) = (parent, index); Vertices = G3D.Vertices?.SubArray(VertexOffset, NumVertices); var offset = VertexOffset; Indices = G3D.Indices?.SubArray(IndexOffset, NumCorners).Select(i => i - offset); VertexUvs = G3D.VertexUvs?.SubArray(VertexOffset, NumVertices); VertexNormals = G3D.VertexNormals?.SubArray(VertexOffset, NumVertices); VertexColors = G3D.VertexColors?.SubArray(VertexOffset, NumVertices); VertexTangents = G3D.VertexTangents?.SubArray(VertexOffset, NumVertices); FaceNormals = G3D.FaceNormals?.SubArray(FaceOffset, NumFaces); // TODO: Remove need for this. var submeshArray = (G3D.SubmeshIndexOffsets as ArrayAdapter <int>).Array; var submeshIndex = Array.BinarySearch(submeshArray, IndexOffset); var submeshCount = 0; for (var i = submeshIndex; i < submeshArray.Length; i++) { var indexOffset = submeshArray[i]; if (indexOffset - IndexOffset >= NumCorners) { break; } submeshCount++; } SubmeshMaterials = G3D.SubmeshMaterials?.SubArray(submeshIndex, submeshCount); SubmeshIndexOffsets = G3D.SubmeshIndexOffsets?.SubArray(submeshIndex, submeshCount).Select(i => i - IndexOffset); MeshSubmeshOffset = new List <int>() { 0 }.ToIArray(); }
public static Mesh CopyTo(this G3D g3d, Mesh mesh) { mesh.vertices = g3d.Vertices.ToUnityVector3Array(); mesh.uv = g3d.AllVertexUvs.ElementAtOrDefault(0).ToUnityVector2Array(); mesh.uv2 = g3d.AllVertexUvs.ElementAtOrDefault(1).ToUnityVector2Array(); mesh.uv3 = g3d.AllVertexUvs.ElementAtOrDefault(2).ToUnityVector2Array(); mesh.uv4 = g3d.AllVertexUvs.ElementAtOrDefault(3).ToUnityVector2Array(); mesh.uv5 = g3d.AllVertexUvs.ElementAtOrDefault(4).ToUnityVector2Array(); mesh.uv6 = g3d.AllVertexUvs.ElementAtOrDefault(5).ToUnityVector2Array(); mesh.uv7 = g3d.AllVertexUvs.ElementAtOrDefault(6).ToUnityVector2Array(); mesh.uv8 = g3d.AllVertexUvs.ElementAtOrDefault(7).ToUnityVector2Array(); mesh.colors = g3d.AllVertexColors.ElementAtOrDefault(0)?.ToUnityColorArray(); mesh.normals = g3d.VertexNormals.ToUnityVector3Array(); mesh.tangents = g3d.VertexTangents.ToUnityVector4Array(); mesh.indexFormat = IndexFormat.UInt32; mesh.SetIndices(g3d.Indices.ToArray(), TopologyFromPointsPerFace(g3d.NumCornersPerFace), 0); if (mesh.normals == null || mesh.normals.Length == 0) { mesh.RecalculateNormals(); } return(mesh); }
public G3dSubGeometry(G3D parent, int index) { (G3D, Index) = (parent, index); Vertices = G3D.Vertices?.SubArray(VertexOffset, NumVertices); Indices = G3D.Indices?.SubArray(IndexOffset, NumCorners).Select(i => i - VertexOffset); VertexUvs = G3D.VertexUvs?.SubArray(VertexOffset, NumVertices); VertexNormals = G3D.VertexNormals?.SubArray(VertexOffset, NumVertices); VertexColors = G3D.VertexColors?.SubArray(VertexOffset, NumVertices); VertexTangents = G3D.VertexTangents?.SubArray(VertexOffset, NumVertices); FaceGroups = G3D.FaceGroups?.SubArray(FaceOffset, NumFaces); FaceNormals = G3D.FaceNormals?.SubArray(FaceOffset, NumFaces); FaceMaterialIds = G3D.FaceMaterialIds?.SubArray(FaceOffset, NumFaces); }
public static IEnumerable <string> ObjLines(G3D g3d) { // Write the vertices var vertices = g3d.Vertices; var uvs = g3d.VertexUvs; foreach (var v in vertices.ToEnumerable()) { yield return($"v {v.X} {v.Y} {v.Z}"); } if (uvs != null) { for (var v = 0; v < uvs.Count; v++) { yield return($"vt {uvs[v].X} {uvs[v].Y}"); } } var indices = g3d.Indices; var sb = new StringBuilder(); var i = 0; var faceSize = g3d.NumCornersPerFace; while (i < indices.Count) { sb.Append("f"); if (uvs == null) { for (var j = 0; j < faceSize; ++j) { var index = g3d.Indices[i++] + 1; sb.Append(" ").Append(index); } } else { for (var j = 0; j < faceSize; ++j) { var index = g3d.Indices[i++] + 1; sb.Append(" ").Append(index).Append("/").Append(index); } } yield return(sb.ToString()); sb.Clear(); } }
public static IEnumerable <G3dErrors> Validate(G3D g3d) { var errors = new List <G3dErrors>(); void Validate(bool value, G3dErrors error) { if (!value) { errors.Add(error); } } //Indices Validate(g3d.Indices.Count % 3 == 0, G3dErrors.IndicesInvalidCount); Validate(g3d.Indices.All(i => i >= 0 && i < g3d.NumVertices), G3dErrors.IndicesOutOfRange); //Triangle should have 3 distinct vertices //Assert.That(g3d.Indices.SubArrays(3).Select(face => face.ToEnumerable().Distinct().Count()).All(c => c == 3)); //Submeshes Validate(g3d.NumSubmeshes >= g3d.NumMeshes, G3dErrors.SubmeshesCountMismatch); Validate(g3d.NumSubmeshes == g3d.SubmeshMaterials.Count, G3dErrors.SubmeshesCountMismatch); Validate(g3d.NumSubmeshes == g3d.SubmeshIndexOffsets.Count, G3dErrors.SubmeshesCountMismatch); Validate(g3d.SubmeshIndexOffsets.All(i => i % 3 == 0), G3dErrors.SubmeshesIndesxOffsetInvalidIndex); Validate(g3d.SubmeshIndexOffsets.All(i => i >= 0 && i < g3d.NumCorners), G3dErrors.SubmeshesIndexOffsetOutOfRange); Validate(g3d.SubmeshIndexCount.All(i => i > 0), G3dErrors.SubmeshesNonPositive); Validate(g3d.SubmeshMaterials.All(m => m < g3d.NumMaterials), G3dErrors.SubmeshesMaterialOutOfRange); //Mesh Validate(g3d.MeshSubmeshOffset.All(i => i >= 0 && i < g3d.NumSubmeshes), G3dErrors.MeshesSubmeshOffsetOutOfRange); Validate(g3d.MeshSubmeshCount.All(i => i > 0), G3dErrors.MeshesSubmeshCountNonPositive); //Instances Validate(g3d.NumInstances == g3d.InstanceParents.Count, G3dErrors.InstancesCountMismatch); Validate(g3d.NumInstances == g3d.InstanceMeshes.Count, G3dErrors.InstancesCountMismatch); Validate(g3d.NumInstances == g3d.InstanceTransforms.Count, G3dErrors.InstancesCountMismatch); Validate(g3d.InstanceParents.All(i => i < g3d.NumInstances), G3dErrors.InstancesParentOutOfRange); Validate(g3d.InstanceMeshes.All(i => i < g3d.NumMeshes), G3dErrors.InstancesMeshOutOfRange); //Materials Validate(g3d.NumMaterials == g3d.MaterialColors.Count, G3dErrors.MaterialsCountMismatch); Validate(g3d.NumMaterials == g3d.MaterialGlossiness.Count, G3dErrors.MaterialsCountMismatch); Validate(g3d.NumMaterials == g3d.MaterialSmoothness.Count, G3dErrors.MaterialsCountMismatch); return(errors); }
public G3dMaterial(G3D g3D, int index) { G3d = g3D; Index = index; }
public G3dShape(G3D parent, int index) { (G3D, Index) = (parent, index); Vertices = G3D.ShapeVertices?.SubArray(ShapeVertexOffset, NumVertices); }
public static IEnumerable <string> PlyStrings(G3D g) { var vertices = g.Vertices; var indices = g.Indices; var colors = g.VertexColors; //Write the header yield return("ply"); yield return("format ascii 1.0"); yield return("element vertex " + vertices.Count + ""); yield return("property float x"); yield return("property float y"); yield return("property float z"); if (colors != null) { yield return("property uint8 red"); yield return("property uint8 green"); yield return("property uint8 blue"); } yield return("element face " + g.NumFaces); yield return("property list uint8 int32 vertex_index"); yield return("end_header"); // Write the vertices if (colors != null) { for (var i = 0; i < vertices.Count; i++) { var v = vertices[i]; var c = (colors[i] * 255f).Clamp(Vector4.Zero, new Vector4(255, 255, 255, 255)); yield return ($"{v.X} {v.Y} {v.Z} {(byte) c.X} {(byte) c.Y} {(byte) c.Z}"); } } else { for (var i = 0; i < vertices.Count; i++) { var v = vertices[i]; yield return ($"{v.X} {v.Y} {v.Z}"); } } // Write the face indices var index = 0; var sb = new StringBuilder(); var faceSize = g.NumCornersPerFace; for (var i = 0; i < g.NumFaces; i++) { sb.Append(faceSize); for (var j = 0; j < faceSize; j++) { sb.Append(" ").Append(indices[index++]); } yield return(sb.ToString()); sb.Clear(); } }
public static void WritePly(this G3D g, string filePath) => File.WriteAllLines(filePath, PlyStrings(g));
public static void WriteObj(this G3D g3d, string filePath) => File.WriteAllLines(filePath, ObjLines(g3d));
public static G3D ToG3d(this IGeometryAttributes self) => G3D.Create(self.Attributes.ToArray());
public static Mesh ToMesh(this G3D g3d) => g3d.CopyTo(new Mesh());