/// <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);
            }
        }
Esempio n. 2
0
        internal static IEnumerable <PackedMeshBuilder <TMaterial> > CreatePackedMeshes(IEnumerable <IMeshBuilder <TMaterial> > meshBuilders, bool prefferStrided)
        {
            try
            {
                foreach (var m in meshBuilders)
                {
                    m.Validate();
                }
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message, nameof(meshBuilders), ex);
            }

            var jointEncoding = meshBuilders.GetOptimalJointEncoding();
            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 = prefferStrided;
                    if (srcPrim.MorphTargets.Count > 0)
                    {
                        useStrided = false;
                    }

                    if (useStrided)
                    {
                        dstPrim.SetStridedVertices(srcPrim, jointEncoding);
                    }
                    else
                    {
                        dstPrim.SetStreamedVertices(srcPrim, jointEncoding);
                    }

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

                yield return(dstMesh);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Converts a collection of <see cref="MeshBuilder{TMaterial, TvP, TvM, TvS}"/>
        /// to a collection of <see cref="PackedMeshBuilder{TMaterial}"/>, trying to use
        /// a single vertex buffer and a single index buffer shared by all meshes.
        /// </summary>
        /// <typeparam name="TvP">The vertex fragment type with Position, Normal and Tangent.</typeparam>
        /// <typeparam name="TvM">The vertex fragment type with Colors and Texture Coordinates.</typeparam>
        /// <typeparam name="TvS">The vertex fragment type with Skin Joint Weights.</typeparam>
        /// <param name="meshBuilders">A collection of <see cref="MeshBuilder{TMaterial, TvP, TvM, TvS}"/> instances.</param>
        /// <returns>A collection of <see cref="PackedMeshBuilder{TMaterial}"/> instances.</returns>
        internal static IEnumerable <PackedMeshBuilder <TMaterial> > PackMeshes <TvP, TvM, TvS>(IEnumerable <MeshBuilder <TMaterial, TvP, TvM, TvS> > meshBuilders)
            where TvP : struct, VertexTypes.IVertexPosition
            where TvM : struct, VertexTypes.IVertexMaterial
            where TvS : struct, VertexTypes.IVertexSkinning
        {
            try
            {
                foreach (var m in meshBuilders)
                {
                    m.Validate();
                }
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message, nameof(meshBuilders), ex);
            }

            var vertexBlocks = VertexTypes.VertexUtils.CreateVertexMemoryAccessors
                               (
                meshBuilders
                .SelectMany(item => item.Primitives)
                .Select(item => item.Vertices)
                               ).ToList();

            var indexBlocks = VertexTypes.VertexUtils.CreateIndexMemoryAccessors
                              (
                meshBuilders
                .SelectMany(item => item.Primitives)
                .Select(item => item.Indices)
                              ).ToList();

            int idx = 0;

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

                foreach (var primitiveBuilder in meshBuilder.Primitives)
                {
                    dstMesh.AddPrimitive(primitiveBuilder.Material, vertexBlocks[idx], indexBlocks[idx]);

                    ++idx;
                }

                yield return(dstMesh);
            }
        }
Esempio n. 4
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);
            }
        }