public static void CheckStandardGeometryAttributes(IG3D g3d) { var vertexBuffer = g3d.VertexAttribute; var indexBuffer = g3d.IndexAttribute; CheckAttribute(vertexBuffer, Association.assoc_vertex, AttributeType.attr_vertex, DataType.dt_float32, 3); CheckAttribute(indexBuffer, Association.assoc_corner, AttributeType.attr_index, DataType.dt_int32, 1); }
public static BFast ToBFast(this IG3D g3D) { var buffers = new List <IBytes>(); buffers.Add(G3D.DefaultHeader.ToBytesAscii().Pin()); var descriptors = g3D.Descriptors().ToArray().Pin(); buffers.Add(descriptors); foreach (var attr in g3D.Attributes) { buffers.Add(attr.Bytes); } return(new BFast(buffers)); }
public G3DAdapter(IG3D g3D) { //g3D.Validate(); G3D = g3D; FaceSizes = g3D.FaceSizes(); PointsPerFace = g3D.HasFixedFaceSize() ? g3D.FirstFaceSize() : 0; Vertices = g3D.VertexAttribute.ToVector3s(); Indices = g3D.CornerVertexIndices(); NumFaces = g3D.FaceCount(); FaceIndices = g3D.FaceIndices(); MaterialIds = g3D.MaterialIds(); }
public static IAttribute FindAttribute(this IG3D g3D, AttributeType attributeType, bool throwIfMissing = true) { var candidates = g3D.FindAttributes(attributeType).ToList(); if (candidates.Count > 1) { throw new Exception($"Multiple matching attributes of type {attributeType.AttributeTypeString()}"); } if (candidates.Count == 0) { if (throwIfMissing) { throw new Exception($"No matching attributes of type {attributeType.AttributeTypeString()}"); } return(null); } return(candidates[0]); }
public static int FaceCount(this IG3D g3d) => g3d.HasFixedFaceSize() ? g3d.CornerVertexIndices().Count / g3d.FirstFaceSize() : g3d.FaceSizeAttribute.ToInts().Count;
public static bool HasFixedFaceSize(this IG3D g3d) => g3d.FaceSizeAttribute == null || g3d.FaceSizeAttribute.Descriptor.Association == Association.assoc_object;
public static int FirstFaceSize(this IG3D g3d) => g3d.FaceSizeAttribute?.ToInts()[0] ?? 3;
public static IEnumerable <IAttribute> FindAttributes(this IG3D g3D, Func <AttributeDescriptor, bool> predicate) => g3D.Attributes.Where(a => predicate(a.Descriptor));
public static IEnumerable <IAttribute> VertexAttributes(this IG3D g3d) => g3d.Attributes(Association.assoc_vertex);
public static int VertexCount(this IG3D g3d) => g3d.VertexAttribute.Count;
public static void Validate(this IG3D g3d) { // Check that no attributes are null var n = g3d.Attributes.Count(attr => attr == null); if (n > 0) { throw new Exception("Attributes cannot be null"); } // Assure that there are no duplicates g3d.Attributes.ToDictionary(); // Validate the descriptors foreach (var attr in g3d.Attributes) { attr.Descriptor.Validate(); } // Compute the number of faces var faceCount = g3d.FaceCount(); // Assure that there is a vertex attribute if (g3d.VertexAttribute.Descriptor.Association != Association.assoc_vertex) { throw new Exception("Vertex buffer is not associated with vertex: " + g3d.VertexAttribute.Descriptor); } if (g3d.VertexAttribute.Descriptor.DataArity != 3) { throw new Exception("Vertices should have an arity of 3"); } if (g3d.Attributes(AttributeType.attr_vertex).Count() > 1) { throw new Exception("There can only be one vertex data set"); } // Compute the number of vertices var vertexCount = g3d.VertexCount(); // Computes the number of corners var cornerCount = g3d.CornerVertexIndices().Count; // Compute the number of groups. Groups requires the precense of a GroupIndex attribute var groupCount = g3d.GroupIndexAttributes().FirstOrDefault()?.Count ?? -1; // Compute the number of instance. The first instance channel determines the number of instances var instanceCount = g3d.Attributes(Association.assoc_instance).FirstOrDefault()?.Count ?? -1; // Check the number of items in each attribute foreach (var attr in g3d.Attributes) { switch (attr.Descriptor.Association) { case Association.assoc_vertex: if (attr.Count != vertexCount) { throw new Exception($"Attribute {attr.Descriptor} has {attr.Count} items, expected {vertexCount}"); } break; case Association.assoc_face: if (attr.Count != faceCount) { throw new Exception($"Attribute {attr.Descriptor} has {attr.Count} items, expected {faceCount}"); } break; case Association.assoc_corner: if (attr.Count != cornerCount) { throw new Exception($"Attribute {attr.Descriptor} has {attr.Count} items, expected {cornerCount}"); } break; case Association.assoc_edge: if (attr.Count != cornerCount) { throw new Exception($"Attribute {attr.Descriptor} has {attr.Count} items, expected {cornerCount}"); } break; case Association.assoc_object: if (attr.Count != 1) { throw new Exception($"Attribute {attr.Descriptor} has {attr.Count} items, expected 1"); } break; case Association.assoc_group: if (attr.Count != groupCount) { throw new Exception($"Attribute {attr.Descriptor} has {attr.Count} items, expected {groupCount}"); } break; case Association.assoc_instance: if (attr.Count != instanceCount) { throw new Exception($"Attribute {attr.Descriptor} has {attr.Count} items, expected {instanceCount}"); } break; case Association.assoc_none: break; default: throw new Exception($"Attribute {attr.Descriptor} has invalid association"); } } // The following rules are stricter than absolutely necessary, but respecting them // will make coding geometry libraries easier to write on top of the thing. g3d.Attributes(AttributeType.attr_binormal).ToList() .ValidateDataType(DataType.dt_float32) .ValidateArity(3) .ValidateAssociation(Association.assoc_vertex); g3d.Attributes(AttributeType.attr_tangent).ToList() .ValidateDataType(DataType.dt_float32) .ValidateArity(3) .ValidateAssociation(Association.assoc_vertex); g3d.Attributes(AttributeType.attr_normal).ToList() .ValidateDataType(DataType.dt_float32) .ValidateArity(3) .ValidateAssociation(Association.assoc_face, Association.assoc_corner, Association.assoc_vertex); g3d.Attributes(AttributeType.attr_color).ToList() .ValidateArity(1, 3, 4) .ValidateAssociation(Association.assoc_face, Association.assoc_corner, Association.assoc_vertex, Association.assoc_object); g3d.Attributes(AttributeType.attr_visibility).ToList() .ValidateArity(1) .ValidateDataType(DataType.dt_int8, DataType.dt_int32, DataType.dt_float32); g3d.Attributes(AttributeType.attr_faceindex).ToList() .ValidateArity(1) .ValidateDataType(DataType.dt_int32) .ValidateAssociation(Association.assoc_face) .ValidateMaxOne(); g3d.Attributes(AttributeType.attr_facesize).ToList() .ValidateArity(1) .ValidateDataType(DataType.dt_int32) .ValidateAssociation(Association.assoc_face, Association.assoc_object) .ValidateMaxOne(); g3d.Attributes(AttributeType.attr_index).ToList() .ValidateArity(1) .ValidateDataType(DataType.dt_int32) .ValidateAssociation(Association.assoc_corner) .ValidateMaxOne(); g3d.Attributes(AttributeType.attr_uv).ToList() .ValidateArity(2, 3) .ValidateDataType(DataType.dt_float32) .ValidateAssociation(Association.assoc_vertex, Association.assoc_corner); g3d.Attributes(AttributeType.attr_invalid).ToList() .ValidateNone(); g3d.Attributes(AttributeType.attr_index).ToList() .ValidateArity(1) .ValidateDataType(DataType.dt_int32) .ValidateAssociation(Association.assoc_corner) .ValidateMaxOne(); g3d.Attributes(AttributeType.attr_mapchannel_data).ToList() .ValidateArity(3) .ValidateDataType(DataType.dt_float32) .ValidateAssociation(Association.assoc_none); g3d.Attributes(AttributeType.attr_mapchannel_index).ToList() .ValidateArity(1) .ValidateDataType(DataType.dt_int32) .ValidateAssociation(Association.assoc_corner); g3d.Attributes(AttributeType.attr_materialid).ToList() .ValidateArity(1) .ValidateDataType(DataType.dt_int32) .ValidateAssociation(Association.assoc_face); g3d.Attributes(AttributeType.attr_pervertex).ToList() .ValidateArity(1) .ValidateDataType(DataType.dt_float32) .ValidateAssociation(Association.assoc_vertex); g3d.Attributes(AttributeType.attr_polygroup).ToList() .ValidateArity(1) .ValidateDataType(DataType.dt_int32) .ValidateAssociation(Association.assoc_face); g3d.Attributes(AttributeType.attr_smoothing).ToList() .ValidateArity(1) .ValidateDataType(DataType.dt_int32) .ValidateAssociation(Association.assoc_face); g3d.Attributes(AttributeType.attr_instance_transform).ToList() .ValidateArity(16) .ValidateDataType(DataType.dt_float32) .ValidateAssociation(Association.assoc_instance); g3d.Attributes(AttributeType.attr_vertex).ToList() .ValidateArity(3) .ValidateDataType(DataType.dt_float32, DataType.dt_float64) .ValidateAssociation(Association.assoc_vertex) .ValidateExactlyOne(); }
public static IEnumerable <IAttribute> UVAttributes(this IG3D g3D) => g3D.Attributes(AttributeType.attr_uv);
public static IEnumerable <IAttribute> NormalAttributes(this IG3D g3D) => g3D.Attributes(AttributeType.attr_normal);
public static IEnumerable <IAttribute> ObjectAttributes(this IG3D g3d) => g3d.Attributes(Association.assoc_object);
public static IEnumerable <IAttribute> NoneAttributes(this IG3D g3d) => g3d.Attributes(Association.assoc_none);
public static IEnumerable <IAttribute> EdgeAttributes(this IG3D g3d) => g3d.Attributes(Association.assoc_edge);
public static IEnumerable <IAttribute> FaceAttributes(this IG3D g3d) => g3d.Attributes(Association.assoc_face);
public static IEnumerable <IAttribute> CornerAttributes(this IG3D g3d) => g3d.Attributes(Association.assoc_corner);
public static IArray <int> MaterialIds(this IG3D g3d) => g3d.MaterialIdAttribute?.ToInts() ?? (-1).Repeat(g3d.FaceCount());
public static IEnumerable <IAttribute> GroupIndexAttributes(this IG3D g3D) => g3D.Attributes(AttributeType.attr_group_index);
public static IArray <int> FaceIndices(this IG3D g3d) => g3d.FaceIndexAttribute?.ToInts() ?? (g3d.HasFixedFaceSize() ? g3d.CornerVertexIndices().Indices().Stride(g3d.FirstFaceSize()) : g3d.FaceSizes().Accumulate((x, y) => x + y));
public static IG3D AddAttributes(this IG3D g3d, params IAttribute[] attributes) => g3d.Attributes.Concat(attributes).ToG3D();
public static IArray <int> FaceSizes(this IG3D g3d) => g3d.HasFixedFaceSize() ? g3d.FaceCount().Select(i => g3d.FirstFaceSize()) : g3d.FaceSizeAttribute.ToInts();
public static IG3D ReplaceAttribute(this IG3D g3d, IAttribute attr) => g3d.AttributesExcept(attr.Descriptor).Concat(new[] { attr }).ToG3D();
public static IEnumerable <AttributeDescriptor> Descriptors(this IG3D g3D) => g3D.Attributes.Select(attr => attr.Descriptor);
public static IArray <int> CornerVertexIndices(this IG3D g3d) => g3d.IndexAttribute == null ? g3d.VertexCount().Range() : g3d.IndexAttribute.ToInts();
public static IEnumerable <IAttribute> InstanceTransforms(this IG3D g3D) => g3D.Attributes(AttributeType.attr_instance_transform);
public static IEnumerable <IAttribute> Attributes(this IG3D g3d, Association assoc, AttributeType attrType) => g3d.Attributes.Where(attr => attr.Descriptor.Association == assoc && attr.Descriptor.AttributeType == attrType);
public static IGeometry ToIGeometry(this IG3D g) => new G3DAdapter(g);
public static IEnumerable <IAttribute> InstanceGroups(this IG3D g3D) => g3D.Attributes(AttributeType.attr_instance_group);