From 9795860c6354b87924b97b354688e2b59098eda7 Mon Sep 17 00:00:00 2001 From: Mattias Edlund Date: Sat, 27 Mar 2021 00:00:18 +0100 Subject: [PATCH] feat(simplifier): set manual uv component count --- Runtime/LODGenerator.cs | 8 +- Runtime/MeshSimplifier.cs | 222 ++++++++++--------------------- Runtime/SimplificationOptions.cs | 18 ++- Runtime/Utility/MeshUtils.cs | 50 ++++++- 4 files changed, 133 insertions(+), 165 deletions(-) diff --git a/Runtime/LODGenerator.cs b/Runtime/LODGenerator.cs index 6bbbf7c..d35b122 100644 --- a/Runtime/LODGenerator.cs +++ b/Runtime/LODGenerator.cs @@ -607,6 +607,12 @@ private static void CollectChildRenderersForLOD(Transform transform, List uvs) /// /// The channel index. /// The UVs. - public void SetUVs(int channel, Vector2[] uvs) - { - if (channel < 0 || channel >= UVChannelCount) - throw new ArgumentOutOfRangeException(nameof(channel)); - - if (uvs != null && uvs.Length > 0) - { - if (vertUV2D == null) - vertUV2D = new UVChannels(); - - int uvCount = uvs.Length; - var uvSet = vertUV2D[channel]; - if (uvSet != null) - { - uvSet.Resize(uvCount); - } - else - { - uvSet = new ResizableArray(uvCount, uvCount); - vertUV2D[channel] = uvSet; - } - - var uvData = uvSet.Data; - uvs.CopyTo(uvData, 0); - } - else - { - if (vertUV2D != null) - { - vertUV2D[channel] = null; - } - } - - if (vertUV3D != null) - { - vertUV3D[channel] = null; - } - if (vertUV4D != null) - { - vertUV4D[channel] = null; - } - } - - /// - /// Sets the UVs (3D) for a specific channel. - /// - /// The channel index. - /// The UVs. - public void SetUVs(int channel, Vector3[] uvs) - { - if (channel < 0 || channel >= UVChannelCount) - throw new ArgumentOutOfRangeException(nameof(channel)); - - if (uvs != null && uvs.Length > 0) - { - if (vertUV3D == null) - vertUV3D = new UVChannels(); - - int uvCount = uvs.Length; - var uvSet = vertUV3D[channel]; - if (uvSet != null) - { - uvSet.Resize(uvCount); - } - else - { - uvSet = new ResizableArray(uvCount, uvCount); - vertUV3D[channel] = uvSet; - } - - var uvData = uvSet.Data; - uvs.CopyTo(uvData, 0); - } - else - { - if (vertUV3D != null) - { - vertUV3D[channel] = null; - } - } - - if (vertUV2D != null) - { - vertUV2D[channel] = null; - } - if (vertUV4D != null) - { - vertUV4D[channel] = null; - } - } - - /// - /// Sets the UVs (4D) for a specific channel. - /// - /// The channel index. - /// The UVs. - public void SetUVs(int channel, Vector4[] uvs) - { - if (channel < 0 || channel >= UVChannelCount) - throw new ArgumentOutOfRangeException(nameof(channel)); - - if (uvs != null && uvs.Length > 0) - { - if (vertUV4D == null) - vertUV4D = new UVChannels(); - - int uvCount = uvs.Length; - var uvSet = vertUV4D[channel]; - if (uvSet != null) - { - uvSet.Resize(uvCount); - } - else - { - uvSet = new ResizableArray(uvCount, uvCount); - vertUV4D[channel] = uvSet; - } - - var uvData = uvSet.Data; - uvs.CopyTo(uvData, 0); - } - else - { - if (vertUV4D != null) - { - vertUV4D[channel] = null; - } - } - - if (vertUV2D != null) - { - vertUV2D[channel] = null; - } - if (vertUV3D != null) - { - vertUV3D[channel] = null; - } - } - - /// - /// Sets the UVs (2D) for a specific channel. - /// - /// The channel index. - /// The UVs. - public void SetUVs(int channel, List uvs) + public void SetUVs(int channel, IList uvs) { if (channel < 0 || channel >= UVChannelCount) throw new ArgumentOutOfRangeException(nameof(channel)); @@ -1924,7 +1780,7 @@ public void SetUVs(int channel, List uvs) /// /// The channel index. /// The UVs. - public void SetUVs(int channel, List uvs) + public void SetUVs(int channel, IList uvs) { if (channel < 0 || channel >= UVChannelCount) throw new ArgumentOutOfRangeException(nameof(channel)); @@ -1972,7 +1828,7 @@ public void SetUVs(int channel, List uvs) /// /// The channel index. /// The UVs. - public void SetUVs(int channel, List uvs) + public void SetUVs(int channel, IList uvs) { if (channel < 0 || channel >= UVChannelCount) throw new ArgumentOutOfRangeException(nameof(channel)); @@ -2016,24 +1872,26 @@ public void SetUVs(int channel, List uvs) } /// - /// Sets the UVs for a specific channel and automatically detects the used components. + /// Sets the UVs for a specific channel with a specific count of UV components. /// /// The channel index. /// The UVs. - public void SetUVsAuto(int channel, List uvs) + /// The count of UV components. + public void SetUVs(int channel, IList uvs, int uvComponentCount) { if (channel < 0 || channel >= UVChannelCount) throw new ArgumentOutOfRangeException(nameof(channel)); + else if (uvComponentCount < 0 || uvComponentCount > 4) + throw new ArgumentOutOfRangeException(nameof(uvComponentCount)); - if (uvs != null && uvs.Count > 0) + if (uvs != null && uvs.Count > 0 && uvComponentCount > 0) { - int usedComponents = MeshUtils.GetUsedUVComponents(uvs); - if (usedComponents <= 2) + if (uvComponentCount <= 2) { var uv2D = MeshUtils.ConvertUVsTo2D(uvs); SetUVs(channel, uv2D); } - else if (usedComponents == 3) + else if (uvComponentCount == 3) { var uv3D = MeshUtils.ConvertUVsTo3D(uvs); SetUVs(channel, uv3D); @@ -2059,6 +1917,20 @@ public void SetUVsAuto(int channel, List uvs) } } } + + /// + /// Sets the UVs for a specific channel and automatically detects the used components. + /// + /// The channel index. + /// The UVs. + public void SetUVsAuto(int channel, IList uvs) + { + if (channel < 0 || channel >= UVChannelCount) + throw new ArgumentOutOfRangeException(nameof(channel)); + + int uvComponentCount = MeshUtils.GetUsedUVComponents(uvs); + SetUVs(channel, uvs, uvComponentCount); + } #endregion #endregion @@ -2153,12 +2025,25 @@ public void AddBlendShapes(BlendShape[] blendShapes) #region Initialize /// /// Initializes the algorithm with the original mesh. + /// Will automatically detect the count of UV components used on the mesh. /// /// The mesh. public void Initialize(Mesh mesh) + { + Initialize(mesh, -1); + } + + /// + /// Initializes the algorithm with the original mesh. + /// + /// The mesh. + /// The count of UV components that are used on the mesh. -1 means that it will be automatically detected. Note that all UV channels would use the same UV component count. + public void Initialize(Mesh mesh, int uvComponentCount) { if (mesh == null) throw new ArgumentNullException(nameof(mesh)); + if (uvComponentCount < -1 || uvComponentCount > 4) + throw new ArgumentOutOfRangeException(nameof(uvComponentCount)); this.Vertices = mesh.vertices; this.Normals = mesh.normals; @@ -2170,8 +2055,34 @@ public void Initialize(Mesh mesh) for (int channel = 0; channel < UVChannelCount; channel++) { - var uvs = MeshUtils.GetMeshUVs(mesh, channel); - SetUVsAuto(channel, uvs); + switch (uvComponentCount) + { + case -1: + { + var uvs = MeshUtils.GetMeshUVs(mesh, channel); + SetUVsAuto(channel, uvs); + break; + } + case 1: + case 2: + { + var uvs = MeshUtils.GetMeshUVs2D(mesh, channel); + SetUVs(channel, uvs); + break; + } + case 3: + { + var uvs = MeshUtils.GetMeshUVs3D(mesh, channel); + SetUVs(channel, uvs); + break; + } + case 4: + { + var uvs = MeshUtils.GetMeshUVs(mesh, channel); + SetUVs(channel, uvs); + break; + } + } } var blendShapes = MeshUtils.GetMeshBlendShapes(mesh); @@ -2329,6 +2240,7 @@ public Mesh ToMesh() List[] uvs2D = null; List[] uvs3D = null; List[] uvs4D = null; + if (vertUV2D != null) { uvs2D = new List[UVChannelCount]; diff --git a/Runtime/SimplificationOptions.cs b/Runtime/SimplificationOptions.cs index e83b215..25bab3f 100644 --- a/Runtime/SimplificationOptions.cs +++ b/Runtime/SimplificationOptions.cs @@ -1,4 +1,4 @@ -#region License +#region License /* MIT License @@ -49,7 +49,9 @@ public struct SimplificationOptions EnableSmartLink = true, VertexLinkDistance = double.Epsilon, MaxIterationCount = 100, - Agressiveness = 7.0 + Agressiveness = 7.0, + ManualUVComponentCount = false, + UVComponentCount = 2 }; /// @@ -104,5 +106,17 @@ public struct SimplificationOptions /// [Tooltip("The agressiveness of the mesh simplification. Higher number equals higher quality, but more expensive to run.")] public double Agressiveness; + /// + /// If a manual UV component count should be used (set by UVComponentCount), instead of the automatic detection. + /// Default value: false + /// + [Tooltip("If a manual UV component count should be used (set by UV Component Count below), instead of the automatic detection.")] + public bool ManualUVComponentCount; + /// + /// The UV component count. The same UV component count will be used on all UV channels. + /// Default value: 2 + /// + [Range(0, 4), Tooltip("The UV component count. The same UV component count will be used on all UV channels.")] + public int UVComponentCount; } } diff --git a/Runtime/Utility/MeshUtils.cs b/Runtime/Utility/MeshUtils.cs index 2df867b..0453c67 100644 --- a/Runtime/Utility/MeshUtils.cs +++ b/Runtime/Utility/MeshUtils.cs @@ -287,12 +287,12 @@ public static void ApplyMeshBlendShapes(Mesh mesh, BlendShape[] blendShapes) /// /// The mesh. /// The UV sets. - public static List[] GetMeshUVs(Mesh mesh) + public static IList[] GetMeshUVs(Mesh mesh) { if (mesh == null) throw new ArgumentNullException(nameof(mesh)); - var uvs = new List[UVChannelCount]; + var uvs = new IList[UVChannelCount]; for (int channel = 0; channel < UVChannelCount; channel++) { uvs[channel] = GetMeshUVs(mesh, channel); @@ -301,12 +301,48 @@ public static List[] GetMeshUVs(Mesh mesh) } /// - /// Returns the UV list for a specific mesh and UV channel. + /// Returns the 2D UV list for a specific mesh and UV channel. /// /// The mesh. /// The UV channel. /// The UV list. - public static List GetMeshUVs(Mesh mesh, int channel) + public static IList GetMeshUVs2D(Mesh mesh, int channel) + { + if (mesh == null) + throw new ArgumentNullException(nameof(mesh)); + else if (channel < 0 || channel >= UVChannelCount) + throw new ArgumentOutOfRangeException(nameof(channel)); + + var uvList = new List(mesh.vertexCount); + mesh.GetUVs(channel, uvList); + return uvList; + } + + /// + /// Returns the 3D UV list for a specific mesh and UV channel. + /// + /// The mesh. + /// The UV channel. + /// The UV list. + public static IList GetMeshUVs3D(Mesh mesh, int channel) + { + if (mesh == null) + throw new ArgumentNullException(nameof(mesh)); + else if (channel < 0 || channel >= UVChannelCount) + throw new ArgumentOutOfRangeException(nameof(channel)); + + var uvList = new List(mesh.vertexCount); + mesh.GetUVs(channel, uvList); + return uvList; + } + + /// + /// Returns the 4D UV list for a specific mesh and UV channel. + /// + /// The mesh. + /// The UV channel. + /// The UV list. + public static IList GetMeshUVs(Mesh mesh, int channel) { if (mesh == null) throw new ArgumentNullException(nameof(mesh)); @@ -323,7 +359,7 @@ public static List GetMeshUVs(Mesh mesh, int channel) /// /// The UV set. /// The number of used UV components. - public static int GetUsedUVComponents(List uvs) + public static int GetUsedUVComponents(IList uvs) { if (uvs == null || uvs.Count == 0) return 0; @@ -358,7 +394,7 @@ public static int GetUsedUVComponents(List uvs) /// /// The list of UVs. /// The array of 2D UVs. - public static Vector2[] ConvertUVsTo2D(List uvs) + public static Vector2[] ConvertUVsTo2D(IList uvs) { if (uvs == null) return null; @@ -377,7 +413,7 @@ public static Vector2[] ConvertUVsTo2D(List uvs) /// /// The list of UVs. /// The array of 3D UVs. - public static Vector3[] ConvertUVsTo3D(List uvs) + public static Vector3[] ConvertUVsTo3D(IList uvs) { if (uvs == null) return null;