Skip to content

Commit 55264ce

Browse files
committed
feat(simplifier): added options validation
1 parent e27528b commit 55264ce

File tree

6 files changed

+170
-30
lines changed

6 files changed

+170
-30
lines changed

Editor/LODGeneratorHelperEditor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ private void GenerateLODs()
523523
}
524524
catch (System.Exception ex)
525525
{
526-
Debug.LogException(ex);
526+
Debug.LogException(ex, lodGeneratorHelper);
527527
DisplayError("Failed to generate LODs!", ex.Message, "OK", lodGeneratorHelper);
528528
}
529529
finally

Runtime/Exceptions.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
3+
namespace UnityMeshSimplifier
4+
{
5+
/// <summary>
6+
/// An exception thrown when validating simplification options.
7+
/// </summary>
8+
public sealed class ValidateSimplificationOptionsException : Exception
9+
{
10+
private readonly string propertyName;
11+
12+
/// <summary>
13+
/// Creates a new simplification options validation exception.
14+
/// </summary>
15+
/// <param name="propertyName">The property name.</param>
16+
/// <param name="message">The exception message.</param>
17+
public ValidateSimplificationOptionsException(string propertyName, string message)
18+
: base(message)
19+
{
20+
this.propertyName = propertyName;
21+
}
22+
23+
/// <summary>
24+
/// Creates a new simplification options validation exception.
25+
/// </summary>
26+
/// <param name="propertyName">The property name.</param>
27+
/// <param name="message">The exception message.</param>
28+
/// <param name="innerException">The exception that caused the validation error.</param>
29+
public ValidateSimplificationOptionsException(string propertyName, string message, Exception innerException)
30+
: base(message, innerException)
31+
{
32+
this.propertyName = propertyName;
33+
}
34+
35+
/// <summary>
36+
/// Gets the property name that caused the validation error.
37+
/// </summary>
38+
public string PropertyName
39+
{
40+
get { return propertyName; }
41+
}
42+
43+
/// <summary>
44+
/// Gets the message of the exception.
45+
/// </summary>
46+
public override string Message
47+
{
48+
get { return base.Message + Environment.NewLine + "Property name: " + propertyName; }
49+
}
50+
}
51+
}

Runtime/Exceptions/ValidateSimplificationOptionsException.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/LODGenerator.cs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ public static LODGroup GenerateLODs(GameObject gameObject, LODLevel[] levels, bo
137137
if (existingLodGroup != null)
138138
throw new System.InvalidOperationException("The game object already appears to have a LOD Group. Please remove it first.");
139139

140+
MeshSimplifier.ValidateOptions(simplificationOptions);
141+
140142
saveAssetsPath = ValidateSaveAssetsPath(saveAssetsPath);
141143

142144
var lodParentGameObject = new GameObject(LODParentGameObjectName);
@@ -195,7 +197,7 @@ public static LODGroup GenerateLODs(GameObject gameObject, LODLevel[] levels, bo
195197
for (int rendererIndex = 0; rendererIndex < staticRenderers.Length; rendererIndex++)
196198
{
197199
var renderer = staticRenderers[rendererIndex];
198-
var levelRenderer = CreateLevelRenderer(gameObject, levelIndex, ref level, levelTransform, rendererIndex, renderer, ref simplificationOptions, saveAssetsPath);
200+
var levelRenderer = CreateLevelRenderer(gameObject, levelIndex, level, levelTransform, rendererIndex, renderer, simplificationOptions, saveAssetsPath);
199201
levelRenderers.Add(levelRenderer);
200202
}
201203
}
@@ -205,7 +207,7 @@ public static LODGroup GenerateLODs(GameObject gameObject, LODLevel[] levels, bo
205207
for (int rendererIndex = 0; rendererIndex < skinnedRenderers.Length; rendererIndex++)
206208
{
207209
var renderer = skinnedRenderers[rendererIndex];
208-
var levelRenderer = CreateLevelRenderer(gameObject, levelIndex, ref level, levelTransform, rendererIndex, renderer, ref simplificationOptions, saveAssetsPath);
210+
var levelRenderer = CreateLevelRenderer(gameObject, levelIndex, level, levelTransform, rendererIndex, renderer, simplificationOptions, saveAssetsPath);
209211
levelRenderers.Add(levelRenderer);
210212
}
211213
}
@@ -454,7 +456,7 @@ private static void ParentAndOffsetTransform(Transform transform, Transform pare
454456
transform.SetParent(parentTransform, true);
455457
}
456458

457-
private static Renderer CreateLevelRenderer(GameObject gameObject, int levelIndex, ref LODLevel level, Transform levelTransform, int rendererIndex, RendererInfo renderer, ref SimplificationOptions simplificationOptions, string saveAssetsPath)
459+
private static Renderer CreateLevelRenderer(GameObject gameObject, int levelIndex, in LODLevel level, Transform levelTransform, int rendererIndex, in RendererInfo renderer, in SimplificationOptions simplificationOptions, string saveAssetsPath)
458460
{
459461
var mesh = renderer.mesh;
460462

@@ -476,16 +478,16 @@ private static Renderer CreateLevelRenderer(GameObject gameObject, int levelInde
476478
if (renderer.isStatic)
477479
{
478480
string rendererName = string.Format("{0:000}_static_{1}", rendererIndex, renderer.name);
479-
return CreateStaticLevelRenderer(rendererName, levelTransform, renderer.transform, mesh, renderer.materials, ref level);
481+
return CreateStaticLevelRenderer(rendererName, levelTransform, renderer.transform, mesh, renderer.materials, level);
480482
}
481483
else
482484
{
483485
string rendererName = string.Format("{0:000}_skinned_{1}", rendererIndex, renderer.name);
484-
return CreateSkinnedLevelRenderer(rendererName, levelTransform, renderer.transform, mesh, renderer.materials, renderer.rootBone, renderer.bones, ref level);
486+
return CreateSkinnedLevelRenderer(rendererName, levelTransform, renderer.transform, mesh, renderer.materials, renderer.rootBone, renderer.bones, level);
485487
}
486488
}
487489

488-
private static MeshRenderer CreateStaticLevelRenderer(string name, Transform parentTransform, Transform originalTransform, Mesh mesh, Material[] materials, ref LODLevel level)
490+
private static MeshRenderer CreateStaticLevelRenderer(string name, Transform parentTransform, Transform originalTransform, Mesh mesh, Material[] materials, in LODLevel level)
489491
{
490492
var levelGameObject = new GameObject(name, typeof(MeshFilter), typeof(MeshRenderer));
491493
var levelTransform = levelGameObject.transform;
@@ -503,11 +505,11 @@ private static MeshRenderer CreateStaticLevelRenderer(string name, Transform par
503505

504506
var meshRenderer = levelGameObject.GetComponent<MeshRenderer>();
505507
meshRenderer.sharedMaterials = materials;
506-
SetupLevelRenderer(meshRenderer, ref level);
508+
SetupLevelRenderer(meshRenderer, level);
507509
return meshRenderer;
508510
}
509511

510-
private static SkinnedMeshRenderer CreateSkinnedLevelRenderer(string name, Transform parentTransform, Transform originalTransform, Mesh mesh, Material[] materials, Transform rootBone, Transform[] bones, ref LODLevel level)
512+
private static SkinnedMeshRenderer CreateSkinnedLevelRenderer(string name, Transform parentTransform, Transform originalTransform, Mesh mesh, Material[] materials, Transform rootBone, Transform[] bones, in LODLevel level)
511513
{
512514
var levelGameObject = new GameObject(name, typeof(SkinnedMeshRenderer));
513515
var levelTransform = levelGameObject.transform;
@@ -525,7 +527,7 @@ private static SkinnedMeshRenderer CreateSkinnedLevelRenderer(string name, Trans
525527
skinnedMeshRenderer.sharedMaterials = materials;
526528
skinnedMeshRenderer.rootBone = rootBone;
527529
skinnedMeshRenderer.bones = bones;
528-
SetupLevelRenderer(skinnedMeshRenderer, ref level);
530+
SetupLevelRenderer(skinnedMeshRenderer, level);
529531
return skinnedMeshRenderer;
530532
}
531533

@@ -553,7 +555,7 @@ private static Transform FindBestRootBone(Transform transform, SkinnedMeshRender
553555
return bestBone;
554556
}
555557

556-
private static void SetupLevelRenderer(Renderer renderer, ref LODLevel level)
558+
private static void SetupLevelRenderer(Renderer renderer, in LODLevel level)
557559
{
558560
renderer.shadowCastingMode = level.ShadowCastingMode;
559561
renderer.receiveShadows = level.ReceiveShadows;
@@ -605,7 +607,7 @@ private static void CollectChildRenderersForLOD(Transform transform, List<Render
605607
}
606608
}
607609

608-
private static Mesh SimplifyMesh(Mesh mesh, float quality, SimplificationOptions options)
610+
private static Mesh SimplifyMesh(Mesh mesh, float quality, in SimplificationOptions options)
609611
{
610612
var meshSimplifier = new MeshSimplifier();
611613
meshSimplifier.SimplificationOptions = options;

Runtime/MeshSimplifier.cs

Lines changed: 86 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,11 @@ public sealed class MeshSimplifier
9999
public SimplificationOptions SimplificationOptions
100100
{
101101
get { return this.simplificationOptions; }
102-
set { this.simplificationOptions = value; }
102+
set
103+
{
104+
ValidateOptions(value);
105+
this.simplificationOptions = value;
106+
}
103107
}
104108

105109
/// <summary>
@@ -110,7 +114,12 @@ public SimplificationOptions SimplificationOptions
110114
public bool PreserveBorderEdges
111115
{
112116
get { return simplificationOptions.PreserveBorderEdges; }
113-
set { simplificationOptions.PreserveBorderEdges = value; }
117+
set
118+
{
119+
var simplificationOptions = this.simplificationOptions;
120+
simplificationOptions.PreserveBorderEdges = value;
121+
SimplificationOptions = simplificationOptions;
122+
}
114123
}
115124

116125
/// <summary>
@@ -121,7 +130,12 @@ public bool PreserveBorderEdges
121130
public bool PreserveUVSeamEdges
122131
{
123132
get { return simplificationOptions.PreserveUVSeamEdges; }
124-
set { simplificationOptions.PreserveUVSeamEdges = value; }
133+
set
134+
{
135+
var simplificationOptions = this.simplificationOptions;
136+
simplificationOptions.PreserveUVSeamEdges = value;
137+
SimplificationOptions = simplificationOptions;
138+
}
125139
}
126140

127141
/// <summary>
@@ -132,7 +146,12 @@ public bool PreserveUVSeamEdges
132146
public bool PreserveUVFoldoverEdges
133147
{
134148
get { return simplificationOptions.PreserveUVFoldoverEdges; }
135-
set { simplificationOptions.PreserveUVFoldoverEdges = value; }
149+
set
150+
{
151+
var simplificationOptions = this.simplificationOptions;
152+
simplificationOptions.PreserveUVFoldoverEdges = value;
153+
SimplificationOptions = simplificationOptions;
154+
}
136155
}
137156

138157
/// <summary>
@@ -143,7 +162,12 @@ public bool PreserveUVFoldoverEdges
143162
public bool PreserveSurfaceCurvature
144163
{
145164
get { return simplificationOptions.PreserveSurfaceCurvature; }
146-
set { simplificationOptions.PreserveSurfaceCurvature = value; }
165+
set
166+
{
167+
var simplificationOptions = this.simplificationOptions;
168+
simplificationOptions.PreserveSurfaceCurvature = value;
169+
SimplificationOptions = simplificationOptions;
170+
}
147171
}
148172

149173
/// <summary>
@@ -156,7 +180,12 @@ public bool PreserveSurfaceCurvature
156180
public bool EnableSmartLink
157181
{
158182
get { return simplificationOptions.EnableSmartLink; }
159-
set { simplificationOptions.EnableSmartLink = value; }
183+
set
184+
{
185+
var simplificationOptions = this.simplificationOptions;
186+
simplificationOptions.EnableSmartLink = value;
187+
SimplificationOptions = simplificationOptions;
188+
}
160189
}
161190

162191
/// <summary>
@@ -168,7 +197,12 @@ public bool EnableSmartLink
168197
public int MaxIterationCount
169198
{
170199
get { return simplificationOptions.MaxIterationCount; }
171-
set { simplificationOptions.MaxIterationCount = value; }
200+
set
201+
{
202+
var simplificationOptions = this.simplificationOptions;
203+
simplificationOptions.MaxIterationCount = value;
204+
SimplificationOptions = simplificationOptions;
205+
}
172206
}
173207

174208
/// <summary>
@@ -179,7 +213,12 @@ public int MaxIterationCount
179213
public double Agressiveness
180214
{
181215
get { return simplificationOptions.Agressiveness; }
182-
set { simplificationOptions.Agressiveness = value; }
216+
set
217+
{
218+
var simplificationOptions = this.simplificationOptions;
219+
simplificationOptions.Agressiveness = value;
220+
SimplificationOptions = simplificationOptions;
221+
}
183222
}
184223

185224
/// <summary>
@@ -200,7 +239,12 @@ public bool Verbose
200239
public double VertexLinkDistance
201240
{
202241
get { return simplificationOptions.VertexLinkDistance; }
203-
set { simplificationOptions.VertexLinkDistance = value > double.Epsilon ? value : double.Epsilon; }
242+
set
243+
{
244+
var simplificationOptions = this.simplificationOptions;
245+
simplificationOptions.VertexLinkDistance = value > double.Epsilon ? value : double.Epsilon;
246+
SimplificationOptions = simplificationOptions;
247+
}
204248
}
205249

206250
/// <summary>
@@ -212,7 +256,12 @@ public double VertexLinkDistance
212256
public double VertexLinkDistanceSqr
213257
{
214258
get { return simplificationOptions.VertexLinkDistance * simplificationOptions.VertexLinkDistance; }
215-
set { simplificationOptions.VertexLinkDistance = Math.Sqrt(value); }
259+
set
260+
{
261+
var simplificationOptions = this.simplificationOptions;
262+
simplificationOptions.VertexLinkDistance = Math.Sqrt(value);
263+
SimplificationOptions = simplificationOptions;
264+
}
216265
}
217266

218267
/// <summary>
@@ -2000,13 +2049,6 @@ public void Initialize(Mesh mesh)
20002049
if (mesh == null)
20012050
throw new ArgumentNullException(nameof(mesh));
20022051

2003-
int uvComponentCount = simplificationOptions.UVComponentCount;
2004-
if (simplificationOptions.ManualUVComponentCount)
2005-
{
2006-
if (uvComponentCount < 0 || uvComponentCount > 4)
2007-
throw new InvalidOperationException("The UV component count cannot be below 0 or above 4.");
2008-
}
2009-
20102052
this.Vertices = mesh.vertices;
20112053
this.Normals = mesh.normals;
20122054
this.Tangents = mesh.tangents;
@@ -2019,7 +2061,7 @@ public void Initialize(Mesh mesh)
20192061
{
20202062
if (simplificationOptions.ManualUVComponentCount)
20212063
{
2022-
switch (uvComponentCount)
2064+
switch (simplificationOptions.UVComponentCount)
20232065
{
20242066
case 1:
20252067
case 2:
@@ -2248,6 +2290,32 @@ public Mesh ToMesh()
22482290
return MeshUtils.CreateMesh(vertices, indices, normals, tangents, colors, boneWeights, uvs2D, uvs3D, uvs4D, bindposes, blendShapes);
22492291
}
22502292
#endregion
2293+
2294+
#region Validate Options
2295+
/// <summary>
2296+
/// Validates simplification options.
2297+
/// Will throw an exception if the options are invalid.
2298+
/// </summary>
2299+
/// <param name="options">The simplification options to validate.</param>
2300+
/// <exception cref="ValidateSimplificationOptionsException">The exception thrown in case of invalid options.</exception>
2301+
public static void ValidateOptions(SimplificationOptions options)
2302+
{
2303+
if (options.EnableSmartLink && options.VertexLinkDistance < 0.0)
2304+
throw new ValidateSimplificationOptionsException(nameof(options.VertexLinkDistance), "The vertex link distance cannot be negative when smart linking is enabled.");
2305+
2306+
if (options.MaxIterationCount <= 0)
2307+
throw new ValidateSimplificationOptionsException(nameof(options.MaxIterationCount), "The max iteration count cannot be zero or negative, since there would be nothing for the algorithm to do.");
2308+
2309+
if (options.Agressiveness <= 0.0)
2310+
throw new ValidateSimplificationOptionsException(nameof(options.Agressiveness), "The aggressiveness has to be above zero to make sense. Recommended is around 7.");
2311+
2312+
if (options.ManualUVComponentCount)
2313+
{
2314+
if (options.UVComponentCount < 0 || options.UVComponentCount > 4)
2315+
throw new ValidateSimplificationOptionsException(nameof(options.UVComponentCount), "The UV component count cannot be below 0 or above 4 when manual UV component count is enabled.");
2316+
}
2317+
}
2318+
#endregion
22512319
#endregion
22522320
}
22532321
}

0 commit comments

Comments
 (0)