public static int ExpectedElementCount(this IGeometryAttributes self, AttributeDescriptor desc)
        {
            switch (desc.Association)
            {
            case Association.assoc_all:
                return(1);

            case Association.assoc_none:
                return(0);

            case Association.assoc_vertex:
                return(self.NumVertices);

            case Association.assoc_face:
                return(self.NumFaces);

            case Association.assoc_corner:
                return(self.NumCorners);

            case Association.assoc_edge:
                return(self.NumCorners);

            case Association.assoc_subgeometry:
                return(self.NumSubgeometries);

            case Association.assoc_instance:
                return(self.NumInstances);
            }
            return(-1);
        }
 /// <summary>
 /// Applies a transformation function to position attributes and another to normal attributes. When deforming, we may want to
 /// apply a similar deformation to the normals. For example a matrix can change the position, rotation, and scale of a geometry,
 /// but the only changes should be to the direction of the normal, not the length.
 /// </summary>
 public static IGeometryAttributes Deform(this IGeometryAttributes g, Func <Vector3, Vector3> positionTransform, Func <Vector3, Vector3> normalTransform)
 => g.Attributes.Select(
     a =>
     (a.Descriptor.Semantic == "position" && a is GeometryAttribute <Vector3> p) ? p.Data.Select(positionTransform).ToAttribute(a.Descriptor) :
     (a.Descriptor.Semantic == "normal" && a is GeometryAttribute <Vector3> n) ? n.Data.Select(normalTransform).ToAttribute(a.Descriptor) :
     a)
 .ToGeometryAttributes();
        /// <summary>
        /// Converts a quadrilateral mesh into a triangular mesh carrying over all attributes.
        /// </summary>
        public static IGeometryAttributes TriangulateQuadMesh(this IGeometryAttributes g)
        {
            if (g.NumCornersPerFace != 4)
            {
                throw new Exception("Not a quad mesh");
            }

            var cornerRemap = new int[g.NumFaces * 6];
            var faceRemap   = new int[g.NumFaces * 2];
            var cur         = 0;

            for (var i = 0; i < g.NumFaces; ++i)
            {
                cornerRemap[cur++] = i * 4 + 0;
                cornerRemap[cur++] = i * 4 + 1;
                cornerRemap[cur++] = i * 4 + 2;
                cornerRemap[cur++] = i * 4 + 0;
                cornerRemap[cur++] = i * 4 + 2;
                cornerRemap[cur++] = i * 4 + 3;

                faceRemap[i * 2 + 0] = i;
                faceRemap[i * 2 + 1] = i;
            }

            return(g.RemapFacesAndCorners(faceRemap.ToIArray(), cornerRemap.ToIArray(), 3));
        }
 /// <summary>
 /// Applies vertex colors
 /// </summary>
 public static IGeometryAttributes Color(this IGeometryAttributes g, Vector4 color)
 {
     return(g.Attributes
            .Where(a => a.Descriptor.Semantic != Semantic.Color)
            .Concat(Enumerable.Repeat(g.NumVertices.Select(_ => color).ToAttribute(new AttributeDescriptor(Association.assoc_vertex, Semantic.Color, DataType.dt_float32, 4)), 1))
            .ToGeometryAttributes());
 }
Exemple #5
0
 public static byte[] WriteToBytes(this IGeometryAttributes self)
 {
     using (var memoryStream = new MemoryStream())
     {
         self.Write(memoryStream);
         return(memoryStream.ToArray());
     }
 }
Exemple #6
0
 public G3dWriter(IGeometryAttributes g, G3dHeader?header = null)
 {
     Attributes = g;
     Meta       = (header ?? G3dHeader.Default).ToBytes().ToNamedBuffer("meta");
     Names      = new[] { Meta.Name }.Concat(g.Attributes.ToEnumerable().Select(attr => attr.Name)).ToArray();
     Sizes      = new[] { Meta.NumBytes() }.Concat(g.Attributes.ToEnumerable().Select(attr => attr.GetByteSize())).ToArray();
     Header     = BFast.BFast.CreateBFastHeader(Sizes, Names);
 }
 /// <summary>
 /// Low-level remap function. Maps faces and corners at the same time.
 /// In some cases, this is important (e.g. triangulating quads).
 /// Note: sub-geometries are lost.
 /// </summary>
 public static IGeometryAttributes RemapFacesAndCorners(this IGeometryAttributes g, IArray <int> faceRemap, IArray <int> cornerRemap, int numCornersPerFace = -1)
 => g.VertexAttributes()
 .Concat(g.NoneAttributes())
 .Concat(g.FaceAttributes().Select(attr => attr.Remap(faceRemap)))
 .Concat(g.EdgeAttributes().Select(attr => attr.Remap(cornerRemap)))
 .Concat(g.CornerAttributes().Select(attr => attr.Remap(cornerRemap)))
 .Concat(g.WholeGeometryAttributes())
 .SetFaceSizeAttribute(numCornersPerFace)
 .ToGeometryAttributes();
 public static IGeometryAttributes FlipWindingOrder(this IGeometryAttributes g)
 => g.VertexAttributes()
 .Concat(g.NoneAttributes())
 .Concat(g.FaceAttributes())
 .Concat(g.EdgeAttributes().Select(attr => attr.Remap(g.IndexFlippedRemapping())))
 .Concat(g.CornerAttributes().Select(attr => attr.Remap(g.IndexFlippedRemapping())))
 .Concat(g.WholeGeometryAttributes())
 .FlipNormalAttributes()
 .ToGeometryAttributes();
 /// <summary>
 /// Updates the vertex buffer (e.g. after identifying unwanted faces) and the index
 /// buffer. Vertices are either re-ordered, removed, or deleted. Does not affect any other
 /// </summary>
 public static IGeometryAttributes RemapVertices(this IGeometryAttributes g, IArray <int> newVertices, IArray <int> newIndices)
 => (new[] { newIndices.ToIndexAttribute() }
     .Concat(
         g.VertexAttributes()
         .Select(attr => attr.Remap(newVertices)))
     .Concat(g.NoneAttributes())
     .Concat(g.FaceAttributes())
     .Concat(g.EdgeAttributes())
     .Concat(g.CornerAttributes())
     .Concat(g.WholeGeometryAttributes())
     )
 .ToGeometryAttributes();
        /// <summary>
        /// The vertRemap is a list of vertices in the new vertex buffer, and where they came from.
        /// This could be a reordering of the original vertex buffer, it could even be a repetition.
        /// It could also be some vertices were deleted, BUT if those vertices are still referenced
        /// then this will throw an exception.
        /// The values in the index buffer will change, but it will stay the same length.
        /// </summary>
        public static IGeometryAttributes RemapVertices(this IGeometryAttributes g, IArray <int> vertRemap)
        {
            var vertLookup = (-1).Repeat(g.NumVertices).ToArray();

            for (var i = 0; i < vertRemap.Count; ++i)
            {
                var oldVert = vertRemap[i];
                vertLookup[oldVert] = i;
            }

            var oldIndices = g.GetAttributeIndex()?.Data ?? g.NumVertices.Range();
            var newIndices = oldIndices.Select(i => vertLookup[i]).Evaluate();

            if (newIndices.Any(x => x == -1))
            {
                throw new Exception("At least one of the indices references a vertex that no longer exists");
            }

            return(g.RemapVertices(vertRemap, newIndices));
        }
Exemple #11
0
 public static GeometryAttribute <int> GetAttributeIndex(this IGeometryAttributes self) => self.GetAttribute <int>(CommonAttributes.Index);
Exemple #12
0
 public static IArray <int> GetAttributeDataObjectFaceSize(this IGeometryAttributes self) => self.GetAttributeObjectFaceSize()?.Data;
Exemple #13
0
 public static GeometryAttribute <Vector4> GetAttributeVertexTangent(this IGeometryAttributes self) => self.GetAttribute <Vector4>(CommonAttributes.VertexTangent);
Exemple #14
0
 public static GeometryAttribute <Byte4> GetAttributeVertexColor8Bit(this IGeometryAttributes self) => self.GetAttribute <Byte4>(CommonAttributes.VertexColor8Bit);
Exemple #15
0
 public static IArray <Vector3> GetAttributeDataVertexNormal(this IGeometryAttributes self) => self.GetAttributeVertexNormal()?.Data;
Exemple #16
0
 public static IArray <Vector2> GetAttributeDataVertexUv(this IGeometryAttributes self) => self.GetAttributeVertexUv()?.Data;
Exemple #17
0
 public static IArray <Vector3> GetAttributeDataPosition(this IGeometryAttributes self) => self.GetAttributePosition()?.Data;
Exemple #18
0
 public static IArray <int> GetAttributeDataIndex(this IGeometryAttributes self) => self.GetAttributeIndex()?.Data;
Exemple #19
0
 public static GeometryAttribute <Vector3> GetAttributePosition(this IGeometryAttributes self) => self.GetAttribute <Vector3>(CommonAttributes.Position);
Exemple #20
0
 public static GeometryAttribute <Matrix4x4> GetAttributeInstanceTransforms(this IGeometryAttributes self) => self.GetAttribute <Matrix4x4>(CommonAttributes.InstanceTransforms);
Exemple #21
0
 public static GeometryAttribute <Vector2> GetAttributeVertexUv(this IGeometryAttributes self) => self.GetAttribute <Vector2>(CommonAttributes.VertexUv);
Exemple #22
0
 public static IArray <Matrix4x4> GetAttributeDataInstanceTransforms(this IGeometryAttributes self) => self.GetAttributeInstanceTransforms()?.Data;
Exemple #23
0
 public static GeometryAttribute <Vector3> GetAttributeVertexNormal(this IGeometryAttributes self) => self.GetAttribute <Vector3>(CommonAttributes.VertexNormal);
Exemple #24
0
 public static GeometryAttribute <int> GetAttributeInstanceGeometries(this IGeometryAttributes self) => self.GetAttribute <int>(CommonAttributes.InstanceGeometries);
Exemple #25
0
 public static GeometryAttribute <Vector4> GetAttributeVertexColor(this IGeometryAttributes self) => self.GetAttribute <Vector4>(CommonAttributes.VertexColor);
Exemple #26
0
 public static GeometryAttribute <Vector3> GetAttributeLineTangentOut(this IGeometryAttributes self) => self.GetAttribute <Vector3>(CommonAttributes.LineTangentOut);
Exemple #27
0
 public static IArray <Byte4> GetAttributeDataVertexColor8Bit(this IGeometryAttributes self) => self.GetAttributeVertexColor8Bit()?.Data;
Exemple #28
0
 public static IArray <Vector3> GetAttributeDataLineTangentOut(this IGeometryAttributes self) => self.GetAttributeLineTangentOut()?.Data;
Exemple #29
0
 public static IArray <Vector4> GetAttributeDataVertexTangent(this IGeometryAttributes self) => self.GetAttributeVertexTangent()?.Data;
Exemple #30
0
 public static GeometryAttribute <int> GetAttributeObjectFaceSize(this IGeometryAttributes self) => self.GetAttribute <int>(CommonAttributes.ObjectFaceSize);