Ejemplo n.º 1
0
        public static IReadOnlyList <Mesh> CreateMeshes <TMaterial>(this ModelRoot root, Converter <TMaterial, Material> materialConverter, Scenes.SceneBuilderSchema2Settings settings, params IMeshBuilder <TMaterial>[] meshBuilders)
        {
            Guard.NotNull(root, nameof(root));
            Guard.NotNull(materialConverter, nameof(materialConverter));
            Guard.NotNull(meshBuilders, nameof(meshBuilders));
            Guard.IsTrue(meshBuilders.Length == meshBuilders.Distinct().Count(), nameof(meshBuilders), "The collection has repeated meshes.");

            foreach (var m in meshBuilders)
            {
                m.Validate();
            }

            // create a new material for every unique (byRef) material in the mesh builders.
            var mapMaterials = meshBuilders
                               .SelectMany(item => item.Primitives)
                               .Where(item => !item.IsEmpty())
                               .Select(item => item.Material)
                               .Distinct()
                               .ToDictionary(m => m, m => materialConverter(m));

            // create Schema2.Mesh collections for every gathered group.

            var srcMeshes = PackedMeshBuilder <TMaterial>
                            .CreatePackedMeshes(meshBuilders, settings)
                            .ToList();

            PackedMeshBuilder <TMaterial> .MergeBuffers(srcMeshes);

            // create schema2 meshes

            var dstMeshes = new List <Mesh>();

            foreach (var srcMesh in srcMeshes)
            {
                var dstMesh = srcMesh.CreateSchema2Mesh(root, m => mapMaterials[m]);

                dstMeshes.Add(dstMesh);
            }

            return(dstMeshes);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Converts a collection of <see cref="IMeshBuilder{TMaterial}"/> meshes into a collection of <see cref="PackedMeshBuilder{TMaterial}"/> meshes,
        /// ensuring that the resources are shared across all meshes.
        /// </summary>
        /// <param name="meshBuilders">A collection of <see cref="IMeshBuilder{TMaterial}"/> meshes.</param>
        /// <param name="settings">Mesh packaging settings.</param>
        /// <returns>A collectio of <see cref="PackedMeshBuilder{TMaterial}"/> meshes.</returns>
        internal static IEnumerable <PackedMeshBuilder <TMaterial> > CreatePackedMeshes(IEnumerable <IMeshBuilder <TMaterial> > meshBuilders, Scenes.SceneBuilderSchema2Settings settings)
        {
            try
            {
                foreach (var m in meshBuilders)
                {
                    m.Validate();
                }
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message, nameof(meshBuilders), ex);
            }

            var vertexEncodings = new PackedEncoding();

            vertexEncodings.JointsEncoding  = meshBuilders.GetOptimalJointEncoding();
            vertexEncodings.WeightsEncoding = settings.CompactVertexWeights ? EncodingType.UNSIGNED_SHORT : EncodingType.FLOAT;

            var indexEncoding = meshBuilders.GetOptimalIndexEncoding();

            foreach (var srcMesh in meshBuilders)
            {
                var dstMesh = new PackedMeshBuilder <TMaterial>(srcMesh.Name);

                foreach (var srcPrim in srcMesh.Primitives)
                {
                    if (srcPrim.Vertices.Count == 0)
                    {
                        continue;
                    }

                    var dstPrim = dstMesh.AddPrimitive(srcPrim.Material, srcPrim.VerticesPerPrimitive);

                    bool useStrided = settings.UseStridedBuffers;
                    if (srcPrim.MorphTargets.Count > 0)
                    {
                        useStrided = false;                                 // if the primitive has morphing, it is better not to use strided vertex buffers.
                    }
                    if (useStrided)
                    {
                        dstPrim.SetStridedVertices(srcPrim, vertexEncodings);
                    }
                    else
                    {
                        dstPrim.SetStreamedVertices(srcPrim, vertexEncodings);
                    }

                    dstPrim.SetIndices(srcPrim, indexEncoding);
                    dstPrim.SetMorphTargets(srcPrim, vertexEncodings);
                }

                yield return(dstMesh);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Converts a collection of <see cref="IMeshBuilder{TMaterial}"/> meshes into a collection of <see cref="PackedMeshBuilder{TMaterial}"/> meshes,
        /// ensuring that the resources are shared across all meshes.
        /// </summary>
        /// <param name="meshBuilders">A collection of <see cref="IMeshBuilder{TMaterial}"/> meshes.</param>
        /// <param name="settings">Mesh packaging settings.</param>
        /// <returns>A collectio of <see cref="PackedMeshBuilder{TMaterial}"/> meshes.</returns>
        internal static IEnumerable <PackedMeshBuilder <TMaterial> > CreatePackedMeshes(IEnumerable <IMeshBuilder <TMaterial> > meshBuilders, Scenes.SceneBuilderSchema2Settings settings)
        {
            try
            {
                foreach (var m in meshBuilders)
                {
                    m.Validate();
                }
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message, nameof(meshBuilders), ex);
            }

            var vertexEncodings = new PackedEncoding();

            vertexEncodings.JointsEncoding  = meshBuilders.GetOptimalJointEncoding();
            vertexEncodings.WeightsEncoding = settings.CompactVertexWeights ? EncodingType.UNSIGNED_SHORT : EncodingType.FLOAT;

            var indexEncoding = meshBuilders.GetOptimalIndexEncoding();

            foreach (var srcMesh in meshBuilders)
            {
                // Gather all the primitives of the mesh

                var srcPrims = srcMesh
                               .Primitives
                               .Where(item => item.Vertices.Count > 0)
                               .ToList();

                // identify morph target attributes in use

                var morphTargetsAttributes = new HashSet <string>();

                foreach (var srcPrim in srcPrims)
                {
                    srcPrim._GatherMorphTargetAttributes(morphTargetsAttributes);
                }

                // adjust vertex encoding

                if (morphTargetsAttributes.Count > 0)
                {
                    // if any primitive has morph targets, it is better not to use strided vertex buffers.
                    settings.UseStridedBuffers = false;
                }

                bool hasColorMorph = morphTargetsAttributes.Contains("COLOR_0DELTA") ||
                                     morphTargetsAttributes.Contains("COLOR_1DELTA") ||
                                     morphTargetsAttributes.Contains("COLOR_2DELTA") ||
                                     morphTargetsAttributes.Contains("COLOR_3DELTA");

                // if any primitive has color morphing, we need to ensure the vertex
                // color attribute encoding is FLOAT to allow negative delta values.

                vertexEncodings.ColorEncoding = hasColorMorph
                    ? EncodingType.FLOAT
                    : (EncodingType?)null;

                // Create a packed mesh

                var dstMesh = new PackedMeshBuilder <TMaterial>(srcMesh.Name, srcMesh.Extras);

                foreach (var srcPrim in srcPrims)
                {
                    var dstPrim = dstMesh.AddPrimitive(srcPrim.Material, srcPrim.VerticesPerPrimitive);

                    if (settings.UseStridedBuffers)
                    {
                        dstPrim.SetStridedVertices(srcPrim, vertexEncodings);
                    }
                    else
                    {
                        dstPrim.SetStreamedVertices(srcPrim, vertexEncodings);
                    }

                    dstPrim.SetIndices(srcPrim, indexEncoding);

                    if (morphTargetsAttributes.Count > 0)
                    {
                        dstPrim.SetMorphTargets(srcPrim, vertexEncodings, morphTargetsAttributes);
                    }
                }

                yield return(dstMesh);
            }
        }