public void SetStreamedVertices(IPrimitiveReader <TMaterial> srcPrim, PackedEncoding vertexEncoding) { Guard.NotNull(srcPrim, nameof(srcPrim)); var attributeNames = VertexTypes.VertexUtils .GetVertexAttributes(srcPrim.Vertices[0], srcPrim.Vertices.Count, vertexEncoding) .Select(item => item.Name) .ToList(); var vAccessors = new List <MACCESSOR>(); GuardAll.MustBeEqualTo(vAccessors.Select(item => item.Attribute.ByteOffset), 0, nameof(vAccessors)); GuardAll.MustBeEqualTo(vAccessors.Select(item => item.Attribute.ByteStride), 0, nameof(vAccessors)); foreach (var an in attributeNames) { var vAccessor = VertexTypes.VertexUtils.CreateVertexMemoryAccessor(srcPrim.Vertices, an, vertexEncoding); if (vAccessor == null) { continue; } vAccessors.Add(vAccessor); } _VertexAccessors = vAccessors.ToArray(); MACCESSOR.SanitizeVertexAttributes(_VertexAccessors); }
public void SetMorphTargets(IPrimitiveReader <TMaterial> srcPrim, PackedEncoding vertexEncodings, ISet <string> morphTargetAttributes) { bool hasPositions = _VertexAccessors.Any(item => item.Attribute.Name == "POSITION"); bool hasNormals = _VertexAccessors.Any(item => item.Attribute.Name == "NORMAL"); bool hasTangents = _VertexAccessors.Any(item => item.Attribute.Name == "TANGENT"); bool hasColors0 = _VertexAccessors.Any(item => item.Attribute.Name == "COLOR_0"); bool hasColors1 = _VertexAccessors.Any(item => item.Attribute.Name == "COLOR_1"); bool hasTexCoords0 = _VertexAccessors.Any(item => item.Attribute.Name == "TEXCOORD_0"); bool hasTexCoords1 = _VertexAccessors.Any(item => item.Attribute.Name == "TEXCOORD_1"); bool hasTexCoords2 = _VertexAccessors.Any(item => item.Attribute.Name == "TEXCOORD_2"); bool hasTexCoords3 = _VertexAccessors.Any(item => item.Attribute.Name == "TEXCOORD_3"); for (int i = 0; i < srcPrim.MorphTargets.Count; ++i) { var(pAccessor, nAccessor, tAccessor, c0Accessor, c1Accessor, uv0Accessor, uv1Accessor, uv2Accessor, uv3Accessor) = srcPrim._GetMorphTargetAccessors(i, vertexEncodings, morphTargetAttributes); if (!hasPositions) { pAccessor = null; } if (!hasNormals) { nAccessor = null; } if (!hasTangents) { tAccessor = null; } if (!hasColors0) { c0Accessor = null; } if (!hasColors1) { c1Accessor = null; } if (!hasTexCoords0) { uv0Accessor = null; } if (!hasTexCoords1) { uv1Accessor = null; } if (!hasTexCoords2) { uv2Accessor = null; } if (!hasTexCoords3) { uv3Accessor = null; } AddMorphTarget(pAccessor, nAccessor, tAccessor, c0Accessor, c1Accessor, uv0Accessor, uv1Accessor, uv2Accessor, uv3Accessor); } }
/// <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); } }
public void SetStridedVertices(IPrimitiveReader <TMaterial> srcPrim, PackedEncoding vertexEncoding) { Guard.NotNull(srcPrim, nameof(srcPrim)); var vAccessors = VertexTypes.VertexUtils.CreateVertexMemoryAccessors(srcPrim.Vertices, vertexEncoding); Guard.NotNull(vAccessors, nameof(srcPrim)); _StridedVertexType = srcPrim.VertexType; _VertexAccessors = vAccessors; }
public static void _GatherMorphTargetAttributes <TMaterial>(this IPrimitiveReader <TMaterial> srcPrim, HashSet <string> attributes) { var vertexEncodings = new PackedEncoding(); vertexEncodings.ColorEncoding = EncodingType.FLOAT; for (int i = 0; i < srcPrim.MorphTargets.Count; ++i) { var accessors = srcPrim._GetMorphTargetAccessors(i, vertexEncodings, new HashSet <string>()); if (accessors.Pos != null) { attributes.Add("POSITIONDELTA"); } if (accessors.Nrm != null) { attributes.Add("NORMALDELTA"); } if (accessors.Tgt != null) { attributes.Add("TANGENTDELTA"); } if (accessors.Col0 != null) { attributes.Add("COLOR_0DELTA"); } if (accessors.Col1 != null) { attributes.Add("COLOR_1DELTA"); } if (accessors.Tuv0 != null) { attributes.Add("TEXCOORD_0DELTA"); } if (accessors.Tuv1 != null) { attributes.Add("TEXCOORD_1DELTA"); } if (accessors.Tuv2 != null) { attributes.Add("TEXCOORD_2DELTA"); } if (accessors.Tuv3 != null) { attributes.Add("TEXCOORD_3DELTA"); } } }
public void SetMorphTargets(IPrimitiveReader <TMaterial> srcPrim, PackedEncoding vertexEncodings) { bool hasPositions = _VertexAccessors.Any(item => item.Attribute.Name == "POSITION"); bool hasNormals = _VertexAccessors.Any(item => item.Attribute.Name == "NORMAL"); bool hasTangents = _VertexAccessors.Any(item => item.Attribute.Name == "TANGENT"); if (!hasPositions) { throw new InvalidOperationException("Set vertices before morph targets."); } for (int i = 0; i < srcPrim.MorphTargets.Count; ++i) { var mtv = srcPrim.MorphTargets[i].GetMorphTargetVertices(srcPrim.Vertices.Count); var pAccessor = VertexTypes.VertexUtils.CreateVertexMemoryAccessor(mtv, "POSITIONDELTA", vertexEncodings); var nAccessor = !hasNormals ? null : VertexTypes.VertexUtils.CreateVertexMemoryAccessor(mtv, "NORMALDELTA", vertexEncodings); var tAccessor = !hasTangents ? null : VertexTypes.VertexUtils.CreateVertexMemoryAccessor(mtv, "TANGENTDELTA", vertexEncodings); AddMorphTarget(pAccessor, nAccessor, tAccessor); } }
public static (MACCESSOR Pos, MACCESSOR Nrm, MACCESSOR Tgt, MACCESSOR Col0, MACCESSOR Col1, MACCESSOR Tuv0, MACCESSOR Tuv1, MACCESSOR Tuv2, MACCESSOR Tuv3) _GetMorphTargetAccessors <TMaterial>(this IPrimitiveReader <TMaterial> srcPrim, int morphTargetIdx, PackedEncoding vertexEncodings, ISet <string> requiredAttributes) {
/// <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); } }