/// <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); } }
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); } }
/// <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); } }
/// <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); } }