Skip to content

Commit

Permalink
Merge pull request #28 from bawar9/master
Browse files Browse the repository at this point in the history
Improved the core model simplification algorithm
  • Loading branch information
Whinarn authored Mar 22, 2020
2 parents 8636c17 + 97b5564 commit fd95224
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Runtime/LODGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -597,11 +597,11 @@ private static Mesh SimplifyMesh(Mesh mesh, float quality, SimplificationOptions
meshSimplifier.PreserveBorderEdges = options.PreserveBorderEdges;
meshSimplifier.PreserveUVSeamEdges = options.PreserveUVSeamEdges;
meshSimplifier.PreserveUVFoldoverEdges = options.PreserveUVFoldoverEdges;
meshSimplifier.PreserveSurfaceCurvature = options.PreserveSurfaceCurvature;
meshSimplifier.EnableSmartLink = options.EnableSmartLink;
meshSimplifier.VertexLinkDistance = options.VertexLinkDistance;
meshSimplifier.MaxIterationCount = options.MaxIterationCount;
meshSimplifier.Agressiveness = options.Agressiveness;

meshSimplifier.Initialize(mesh);
meshSimplifier.SimplifyMesh(quality);

Expand Down
116 changes: 115 additions & 1 deletion Runtime/MeshSimplifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ public int Compare(BorderVertex x, BorderVertex y)
private bool preserveBorderEdges = false;
private bool preserveUVSeamEdges = false;
private bool preserveUVFoldoverEdges = false;
private bool preserveSurfaceCurvature = false;
private bool enableSmartLink = true;
private int maxIterationCount = 100;
private double agressiveness = 7.0;
Expand Down Expand Up @@ -503,6 +504,16 @@ public bool PreserveUVFoldoverEdges
set { preserveUVFoldoverEdges = value; }
}

/// <summary>
/// Gets or sets if the discrete curvature of the mesh surface be taken into account during simplification.
/// Default value: false
/// </summary>
public bool PreserveSurfaceCurvature
{
get { return preserveSurfaceCurvature; }
set { preserveSurfaceCurvature = value; }
}

/// <summary>
/// Gets or sets if a feature for smarter vertex linking should be enabled, reducing artifacts in the
/// decimated result at the cost of a slightly more expensive initialization by treating vertices at
Expand Down Expand Up @@ -763,6 +774,7 @@ public MeshSimplifier(Mesh mesh)
#endregion

#region Private Methods

#region Initialize Vertex Attribute
private void InitializeVertexAttribute<T>(T[] attributeValues, ref ResizableArray<T> attributeArray, string attributeName)
{
Expand Down Expand Up @@ -799,6 +811,45 @@ private double VertexError(ref SymmetricMatrix q, double x, double y, double z)
+ 2 * q.m5 * y * z + 2 * q.m6 * y + q.m7 * z * z + 2 * q.m8 * z + q.m9;
}



[MethodImpl(MethodImplOptions.AggressiveInlining)]
private double CurvatureError(ref Vertex Vi, ref Vertex Vj)
{
double diffVector = (Vi.p - Vj.p).Magnitude;

HashSet<Triangle> trianglesWithVi = GetTrianglesContainingVertex(ref Vi);
HashSet<Triangle> trianglesWithVj = GetTrianglesContainingVertex(ref Vj);
HashSet<Triangle> trianglesWithViOrVjOrBoth = new HashSet<Triangle>(trianglesWithVi);
trianglesWithViOrVjOrBoth.UnionWith(trianglesWithVj);
HashSet<Triangle> trianglesWithViAndVjBoth = GetTrianglesContainingBothVertices(ref Vi, ref Vj);


double maxDotOuter = 0;

foreach (var triangleWithViOrVjOrBoth in trianglesWithViOrVjOrBoth)
{
double maxDotInner = 0;

Vector3d normVecTriangleWithViOrVjOrBoth = triangleWithViOrVjOrBoth.n;

foreach (var triangleWithViAndVjBoth in trianglesWithViAndVjBoth)
{
Vector3d normVecTriangleWithViAndVjBoth = triangleWithViAndVjBoth.n;

double dot = Vector3d.Dot(ref normVecTriangleWithViOrVjOrBoth, ref normVecTriangleWithViAndVjBoth);

if (dot > maxDotInner) { maxDotInner = dot; }
}

if (maxDotInner > maxDotOuter) { maxDotOuter = maxDotInner; }

}

return diffVector * maxDotOuter;
}


private double CalculateError(ref Vertex vert0, ref Vertex vert1, out Vector3d result)
{
// compute interpolated vertex
Expand All @@ -813,7 +864,15 @@ private double CalculateError(ref Vertex vert0, ref Vertex vert1, out Vector3d r
-1.0 / det * q.Determinant2(), // vx = A41/det(q_delta)
1.0 / det * q.Determinant3(), // vy = A42/det(q_delta)
-1.0 / det * q.Determinant4()); // vz = A43/det(q_delta)
error = VertexError(ref q, result.x, result.y, result.z);

double curvatureError = 0;

if (preserveSurfaceCurvature)
{
curvatureError = CurvatureError(ref vert0, ref vert1);
}

error = VertexError(ref q, result.x, result.y, result.z) + curvatureError;
}
else
{
Expand Down Expand Up @@ -844,6 +903,7 @@ private double CalculateError(ref Vertex vert0, ref Vertex vert1, out Vector3d r
}
return error;
}

#endregion

#region Calculate Barycentric Coordinates
Expand Down Expand Up @@ -1675,6 +1735,60 @@ private void CalculateSubMeshOffsets()
}
}
#endregion

#region Triangle helper functions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private HashSet<Triangle> GetTrianglesContainingVertex(ref Vertex toCheck)
{
int trianglesCount = toCheck.tcount;
int startIndex = toCheck.tstart;

HashSet<Triangle> tris = new HashSet<Triangle>();

for (int a = startIndex; a < startIndex + trianglesCount; a++)
{
tris.Add(triangles[refs[a].tid]);
}

return tris;
}


[MethodImpl(MethodImplOptions.AggressiveInlining)]
private HashSet<Triangle> GetTrianglesContainingBothVertices(ref Vertex vertex1, ref Vertex vertex2)
{
HashSet<Triangle> tris = new HashSet<Triangle>();


int trianglesCount = vertex1.tcount;
int startIndex = vertex1.tstart;

for (int a = startIndex; a < startIndex + trianglesCount; a++)
{
Triangle tri = triangles[refs[a].tid];

Vertex v1 = vertices[tri.v0];
Vertex v2 = vertices[tri.v1];
Vertex v3 = vertices[tri.v2];

int hashcode = vertex2.GetHashCode();

if (v1.GetHashCode().Equals(hashcode) || v2.GetHashCode().Equals(hashcode) || v3.GetHashCode().Equals(hashcode))
{
tris.Add(tri);
}

}



return tris;
}


#endregion Triangle helper functions


#endregion

#region Public Methods
Expand Down
7 changes: 7 additions & 0 deletions Runtime/SimplificationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public struct SimplificationOptions
PreserveBorderEdges = false,
PreserveUVSeamEdges = false,
PreserveUVFoldoverEdges = false,
PreserveSurfaceCurvature = false,
EnableSmartLink = true,
VertexLinkDistance = double.Epsilon,
MaxIterationCount = 100,
Expand All @@ -68,6 +69,12 @@ public struct SimplificationOptions
[Tooltip("If the UV foldover edges should be preserved.")]
public bool PreserveUVFoldoverEdges;
/// <summary>
/// If the discrete curvature of the mesh surface be taken into account during simplification. Taking surface curvature into account can result in good quality mesh simplification, but it can slow the simplification process significantly.
/// Default value: false
/// </summary>
[Tooltip("If the discrete curvature of the mesh surface be taken into account during simplification. Taking surface curvature into account can result in very good quality mesh simplification, but it can slow the simplification process significantly.")]
public bool PreserveSurfaceCurvature;
/// <summary>
/// If a feature for smarter vertex linking should be enabled, reducing artifacts in the
/// decimated result at the cost of a slightly more expensive initialization by treating vertices at
/// the same position as the same vertex while separating the attributes.
Expand Down

0 comments on commit fd95224

Please sign in to comment.