Example #1
0
        public G3D(IEnumerable <GeometryAttribute> attributes, G3dHeader?header = null, int numCornersPerFaceOverride = -1)
            : base(attributes, numCornersPerFaceOverride)
        {
            Header = header ?? new G3dHeader();

            foreach (var attr in Attributes.ToEnumerable())
            {
                var desc = attr.Descriptor;
                switch (desc.Semantic)
                {
                case Semantic.Index:
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_corner))
                    {
                        Indices = Indices ?? attr.AsType <int>().Data;
                    }
                    if (attr.IsTypeAndAssociation <short>(Association.assoc_corner))
                    {
                        Indices = Indices ?? attr.AsType <short>().Data.Select(x => (int)x);
                    }
                    break;

                case Semantic.Position:
                    if (attr.IsTypeAndAssociation <Vector3>(Association.assoc_vertex))
                    {
                        Vertices = Vertices ?? attr.AsType <Vector3>().Data;
                    }
                    if (attr.IsTypeAndAssociation <Vector3>(Association.assoc_corner))
                    {
                        Vertices = Vertices ?? attr.AsType <Vector3>().Data;    // TODO: is this used?
                    }
                    if (attr.IsTypeAndAssociation <Vector3>(Association.assoc_shapevertex))
                    {
                        ShapeVertices = ShapeVertices ?? attr.AsType <Vector3>().Data;
                    }
                    break;

                case Semantic.Tangent:
                    if (attr.IsTypeAndAssociation <Vector3>(Association.assoc_vertex))
                    {
                        VertexTangents = VertexTangents ?? attr.AsType <Vector3>().Data.Select(v => v.ToVector4());
                    }
                    if (attr.IsTypeAndAssociation <Vector4>(Association.assoc_vertex))
                    {
                        VertexTangents = VertexTangents ?? attr.AsType <Vector4>().Data;
                    }
                    break;

                case Semantic.Uv:
                    if (attr.IsTypeAndAssociation <Vector3>(Association.assoc_vertex))
                    {
                        AllVertexUvs.Add(attr.AsType <Vector3>().Data.Select(uv => uv.ToVector2()));
                    }
                    if (attr.IsTypeAndAssociation <Vector2>(Association.assoc_vertex))
                    {
                        AllVertexUvs.Add(attr.AsType <Vector2>().Data);
                    }
                    break;

                case Semantic.Color:
                    if (desc.Association == Association.assoc_vertex)
                    {
                        AllVertexColors.Add(attr.AttributeToColors());
                    }
                    if (desc.Association == Association.assoc_shape)
                    {
                        ShapeColors = ShapeColors ?? attr.AttributeToColors();
                    }
                    if (desc.Association == Association.assoc_material)
                    {
                        MaterialColors = MaterialColors ?? attr.AttributeToColors();
                    }
                    break;

                case Semantic.VertexOffset:
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_mesh))
                    {
                        MeshVertexOffsets = MeshVertexOffsets ?? attr.AsType <int>().Data;
                    }
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_shape))
                    {
                        ShapeVertexOffsets = ShapeVertexOffsets ?? attr.AsType <int>().Data;
                    }
                    break;

                case Semantic.IndexOffset:
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_mesh))
                    {
                        MeshIndexOffsets = MeshIndexOffsets ?? attr.AsType <int>().Data;
                    }
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_submesh))
                    {
                        SubmeshIndexOffsets = SubmeshIndexOffsets ?? attr.AsType <int>().Data;
                    }
                    break;

                case Semantic.Normal:
                    if (attr.IsTypeAndAssociation <Vector3>(Association.assoc_face))
                    {
                        FaceNormals = FaceNormals ?? attr.AsType <Vector3>().Data;
                    }
                    if (attr.IsTypeAndAssociation <Vector3>(Association.assoc_vertex))
                    {
                        VertexNormals = VertexNormals ?? attr.AsType <Vector3>().Data;
                    }
                    break;

                case Semantic.Material:
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_face))
                    {
                        FaceMaterials = FaceMaterials ?? attr.AsType <int>().Data;
                    }
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_submesh))
                    {
                        SubmeshMaterials = SubmeshMaterials ?? attr.AsType <int>().Data;
                    }
                    break;

                case Semantic.Parent:
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_instance))
                    {
                        InstanceParents = InstanceParents ?? attr.AsType <int>().Data;
                    }
                    break;

                case Semantic.Mesh:
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_instance))
                    {
                        InstanceMeshes = InstanceMeshes ?? attr.AsType <int>().Data;
                    }
                    break;

                case Semantic.Transform:
                    if (attr.IsTypeAndAssociation <Matrix4x4>(Association.assoc_instance))
                    {
                        InstanceTransforms = InstanceTransforms ?? attr.AsType <Matrix4x4>().Data;
                    }
                    break;

                case Semantic.Width:
                    if (attr.IsTypeAndAssociation <float>(Association.assoc_shape))
                    {
                        ShapeWidths = ShapeWidths ?? attr.AsType <float>().Data;
                    }
                    break;

                case Semantic.Glossiness:
                    if (attr.IsTypeAndAssociation <float>(Association.assoc_material))
                    {
                        MaterialGlossiness = attr.AsType <float>().Data;
                    }
                    break;

                case Semantic.Smoothness:
                    if (attr.IsTypeAndAssociation <float>(Association.assoc_material))
                    {
                        MaterialSmoothness = attr.AsType <float>().Data;
                    }
                    break;

                case Semantic.SubMeshOffset:
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_mesh))
                    {
                        MeshSubmeshOffset = attr.AsType <int>().Data;
                    }
                    break;
                }
            }

            // If no vertices are provided, we are going to generate a list of zero vertices.
            if (Vertices == null)
            {
                Vertices = Vector3.Zero.Repeat(0);
            }

            // If no indices are provided then we are going to have to treat the index buffer as indices
            if (Indices == null)
            {
                Indices = Vertices.Indices();
            }

            // Compute face normals if possible
            if (FaceNormals == null && VertexNormals != null)
            {
                FaceNormals = NumFaces.Select(ComputeFaceNormal);
            }

            if (NumMeshes > 0)
            {
                // Mesh offset is the same as the offset of its first submesh.
                if (MeshSubmeshOffset != null)
                {
                    MeshIndexOffsets = MeshSubmeshOffset.Select(submesh => SubmeshIndexOffsets[submesh]);
                    MeshSubmeshCount = GetSubArrayCounts(MeshSubmeshOffset.Count, MeshSubmeshOffset, NumSubmeshes).Evaluate();
                }

                if (MeshIndexOffsets != null)
                {
                    MeshIndexCounts   = GetSubArrayCounts(NumMeshes, MeshIndexOffsets, NumCorners);
                    MeshVertexOffsets = MeshIndexOffsets
                                        .Zip(MeshIndexCounts, (start, count) => (start, count))
                                        .Select(range => Indices.SubArray(range.start, range.count).Min());
                }

                if (MeshVertexOffsets != null)
                {
                    MeshVertexCounts = GetSubArrayCounts(NumMeshes, MeshVertexOffsets, NumVertices);
                }
            }

            if (SubmeshIndexOffsets != null)
            {
                SubmeshIndexCount = GetSubArrayCounts(SubmeshIndexOffsets.Count, SubmeshIndexOffsets, NumCorners).Evaluate();
            }

            // Compute all meshes
            Meshes = NumMeshes.Select(i => new G3dMesh(this, i));

            if (MaterialColors != null)
            {
                Materials = MaterialColors.Count.Select(i => new G3dMaterial(this, i));
            }

            // Process the shape data
            if (ShapeVertices == null)
            {
                ShapeVertices = Vector3.Zero.Repeat(0);
            }

            if (ShapeVertexOffsets == null)
            {
                ShapeVertexOffsets = Array.Empty <int>().ToIArray();
            }

            if (ShapeColors == null)
            {
                ShapeColors = Vector4.Zero.Repeat(0);
            }

            if (ShapeWidths == null)
            {
                ShapeWidths = Array.Empty <float>().ToIArray();
            }

            ShapeVertexCounts = GetSubArrayCounts(NumShapes, ShapeVertexOffsets, ShapeVertices.Count);
            ValidateSubArrayCounts(ShapeVertexCounts, nameof(ShapeVertexCounts));

            Shapes = NumShapes.Select(i => new G3dShape(this, i));
        }
Example #2
0
        }                                                 // The SubGeometry associated with the index

        public G3D(IEnumerable <GeometryAttribute> attributes, G3dHeader?header = null, int numCornersPerFaceOverride = -1)
            : base(attributes, numCornersPerFaceOverride)
        {
            Header = header ?? new G3dHeader();

            foreach (var attr in Attributes.ToEnumerable())
            {
                var desc = attr.Descriptor;
                switch (desc.Semantic)
                {
                case Semantic.Index:
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_corner))
                    {
                        Indices = Indices ?? attr.AsType <int>().Data;
                    }
                    if (attr.IsTypeAndAssociation <short>(Association.assoc_corner))
                    {
                        Indices = Indices ?? attr.AsType <short>().Data.Select(x => (int)x);
                    }
                    break;

                case Semantic.Position:
                    if (attr.IsTypeAndAssociation <Vector3>(Association.assoc_vertex))
                    {
                        Vertices = Vertices ?? attr.AsType <Vector3>().Data;
                    }
                    if (attr.IsTypeAndAssociation <Vector3>(Association.assoc_corner))
                    {
                        Vertices = Vertices ?? attr.AsType <Vector3>().Data;
                    }
                    break;

                case Semantic.Tangent:
                    if (attr.IsTypeAndAssociation <Vector3>(Association.assoc_vertex))
                    {
                        VertexTangents = VertexTangents ?? attr.AsType <Vector3>().Data.Select(v => v.ToVector4());
                    }
                    if (attr.IsTypeAndAssociation <Vector4>(Association.assoc_vertex))
                    {
                        VertexTangents = VertexTangents ?? attr.AsType <Vector4>().Data;
                    }
                    break;

                case Semantic.Uv:
                    if (attr.IsTypeAndAssociation <Vector3>(Association.assoc_vertex))
                    {
                        AllVertexUvs.Add(attr.AsType <Vector3>().Data.Select(uv => uv.ToVector2()));
                    }
                    if (attr.IsTypeAndAssociation <Vector2>(Association.assoc_vertex))
                    {
                        AllVertexUvs.Add(attr.AsType <Vector2>().Data);
                    }
                    break;

                case Semantic.Color:
                    if (desc.Association == Association.assoc_vertex)
                    {
                        AllVertexColors.Add(attr.AttributeToColors());
                    }
                    break;

                case Semantic.VertexOffset:
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_subgeometry))
                    {
                        SubGeometryVertexOffsets = SubGeometryVertexOffsets ?? attr.AsType <int>().Data;
                    }
                    break;

                case Semantic.IndexOffset:
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_subgeometry))
                    {
                        SubGeometryIndexOffsets = SubGeometryIndexOffsets ?? attr.AsType <int>().Data;
                    }
                    break;

                case Semantic.Normal:
                    if (attr.IsTypeAndAssociation <Vector3>(Association.assoc_face))
                    {
                        FaceNormals = FaceNormals ?? attr.AsType <Vector3>().Data;
                    }
                    if (attr.IsTypeAndAssociation <Vector3>(Association.assoc_vertex))
                    {
                        VertexNormals = VertexNormals ?? attr.AsType <Vector3>().Data;
                    }
                    break;

                case Semantic.MaterialId:
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_face))
                    {
                        FaceMaterialIds = FaceMaterialIds ?? attr.AsType <int>().Data;
                    }
                    break;

                // NOTE: some VIMs have Group and others have GroupId
                case Semantic.Group:
                case Semantic.GroupId:
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_face))
                    {
                        FaceGroups = FaceGroups ?? attr.AsType <int>().Data;
                    }
                    break;

                case Semantic.Parent:
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_instance))
                    {
                        InstanceParents = InstanceParents ?? attr.AsType <int>().Data;
                    }
                    break;

                case Semantic.SubGeometry:
                    if (attr.IsTypeAndAssociation <int>(Association.assoc_instance))
                    {
                        InstanceSubGeometries = InstanceSubGeometries ?? attr.AsType <int>().Data;
                    }
                    break;

                case Semantic.Transform:
                    if (attr.IsTypeAndAssociation <Matrix4x4>(Association.assoc_instance))
                    {
                        InstanceTransforms = InstanceTransforms ?? attr.AsType <Matrix4x4>().Data;
                    }
                    break;
                }
            }

            // If no vertices are provided, we are going to generate a list of zero vertices.
            if (Vertices == null)
            {
                Vertices = Vector3.Zero.Repeat(0);
            }

            // If no indices are provided then we are going to have to treat the index buffer as indices
            if (Indices == null)
            {
                Indices = Vertices.Indices();
            }

            // Compute face normals if possible
            if (FaceNormals == null && VertexNormals != null)
            {
                FaceNormals = NumFaces.Select(ComputeFaceNormal);
            }

            if (NumSubgeometries > 0)
            {
                if (Indices == null)
                {
                    Debug.WriteLine($"If the number of Subgeometries is greater than zero then the number of index buffer should be present");
                }
                if (Vertices == null)
                {
                    Debug.WriteLine($"If the number of Subgeometries is greater than zero then the vertex buffer is expected");
                }
                if (SubGeometryIndexOffsets == null)
                {
                    Debug.WriteLine($"If the number of Subgeometries is greater than zero then the Subgeometries index buffer is expected ");
                }
                if (SubGeometryVertexOffsets == null)
                {
                    Debug.WriteLine($"If the number of Subgeometries is greater than zero then the Subgeometries vertex buffer is expected ");
                }

                if (SubGeometryIndexCounts == null)
                {
                    if (NumSubgeometries != SubGeometryIndexOffsets.Count)
                    {
                        throw new Exception($"Internal error: SubGeometry index offsets count {SubGeometryIndexOffsets.Count} is different than number of Subgeometries {NumSubgeometries}");
                    }
                    SubGeometryIndexCounts = NumSubgeometries.Select(i => i < (NumSubgeometries - 1) ? SubGeometryIndexOffsets[i + 1] - SubGeometryIndexOffsets[i] : Indices.Count - SubGeometryIndexOffsets[i]);
                }
                for (var i = 0; i < SubGeometryIndexCounts.Count; ++i)
                {
                    var n = SubGeometryIndexCounts[i];
                    if (n < 0)
                    {
                        throw new Exception($"SubGeometry {i} has negative number of indices {n}");
                    }

                    if (NumCornersPerFace > 0 && (n % NumCornersPerFace) != 0)
                    {
                        throw new Exception($"SubGeometry {i} does not have an index buffer count {n} that is divisible by {NumCornersPerFace}");
                    }
                }

                if (SubGeometryVertexCounts == null)
                {
                    if (NumSubgeometries != SubGeometryVertexOffsets.Count)
                    {
                        throw new Exception($"Internal error: SubGeometry index offsets count {SubGeometryVertexOffsets.Count} is different than number of Subgeometries {NumSubgeometries}");
                    }

                    SubGeometryVertexCounts = NumSubgeometries.Select(i =>
                                                                      i < (NumSubgeometries - 1)
                            ? SubGeometryVertexOffsets[i + 1] - SubGeometryVertexOffsets[i]
                            : Vertices.Count - SubGeometryVertexOffsets[i]
                                                                      );
                }
                for (var i = 0; i < SubGeometryVertexCounts.Count; ++i)
                {
                    var n = SubGeometryVertexCounts[i];
                    if (n < 0)
                    {
                        throw new Exception($"SubGeometry {i} has negative number of indices {n}");
                    }
                }
            }

            // Compute all of the sub-geometries
            SubGeometries = NumSubgeometries.Select(i => new G3dSubGeometry(this, i));
        }