mirror of
https://gitgud.io/AbstractConcept/rimworld-animation-studio.git
synced 2024-08-15 00:43:27 +00:00
Initial commit
This commit is contained in:
commit
3c7cc0c973
8391 changed files with 704313 additions and 0 deletions
|
@ -0,0 +1,214 @@
|
|||
// -----------------------------------------------------------------------
|
||||
// <copyright file="MeshValidator.cs">
|
||||
// Original Triangle code by Jonathan Richard Shewchuk, http://www.cs.cmu.edu/~quake/triangle.html
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace UnityEngine.U2D.Animation.TriangleNet
|
||||
{
|
||||
using System;
|
||||
using Animation.TriangleNet.Topology;
|
||||
using Animation.TriangleNet.Geometry;
|
||||
|
||||
internal static class MeshValidator
|
||||
{
|
||||
private static RobustPredicates predicates = RobustPredicates.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Test the mesh for topological consistency.
|
||||
/// </summary>
|
||||
internal static bool IsConsistent(Mesh mesh)
|
||||
{
|
||||
Otri tri = default(Otri);
|
||||
Otri oppotri = default(Otri), oppooppotri = default(Otri);
|
||||
Vertex org, dest, apex;
|
||||
Vertex oppoorg, oppodest;
|
||||
|
||||
var logger = Log.Instance;
|
||||
|
||||
// Temporarily turn on exact arithmetic if it's off.
|
||||
bool saveexact = Behavior.NoExact;
|
||||
Behavior.NoExact = false;
|
||||
|
||||
int horrors = 0;
|
||||
|
||||
// Run through the list of triangles, checking each one.
|
||||
foreach (var t in mesh.triangles)
|
||||
{
|
||||
tri.tri = t;
|
||||
|
||||
// Check all three edges of the triangle.
|
||||
for (tri.orient = 0; tri.orient < 3; tri.orient++)
|
||||
{
|
||||
org = tri.Org();
|
||||
dest = tri.Dest();
|
||||
if (tri.orient == 0)
|
||||
{
|
||||
// Only test for inversion once.
|
||||
// Test if the triangle is flat or inverted.
|
||||
apex = tri.Apex();
|
||||
if (predicates.CounterClockwise(org, dest, apex) <= 0.0)
|
||||
{
|
||||
if (Log.Verbose)
|
||||
{
|
||||
logger.Warning(String.Format("Triangle is flat or inverted (ID {0}).", t.id),
|
||||
"MeshValidator.IsConsistent()");
|
||||
}
|
||||
|
||||
horrors++;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the neighboring triangle on this edge.
|
||||
tri.Sym(ref oppotri);
|
||||
if (oppotri.tri.id != Mesh.DUMMY)
|
||||
{
|
||||
// Check that the triangle's neighbor knows it's a neighbor.
|
||||
oppotri.Sym(ref oppooppotri);
|
||||
if ((tri.tri != oppooppotri.tri) || (tri.orient != oppooppotri.orient))
|
||||
{
|
||||
if (tri.tri == oppooppotri.tri && Log.Verbose)
|
||||
{
|
||||
logger.Warning("Asymmetric triangle-triangle bond: (Right triangle, wrong orientation)",
|
||||
"MeshValidator.IsConsistent()");
|
||||
}
|
||||
|
||||
horrors++;
|
||||
}
|
||||
// Check that both triangles agree on the identities
|
||||
// of their shared vertices.
|
||||
oppoorg = oppotri.Org();
|
||||
oppodest = oppotri.Dest();
|
||||
if ((org != oppodest) || (dest != oppoorg))
|
||||
{
|
||||
if (Log.Verbose)
|
||||
{
|
||||
logger.Warning("Mismatched edge coordinates between two triangles.",
|
||||
"MeshValidator.IsConsistent()");
|
||||
}
|
||||
|
||||
horrors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for unconnected vertices
|
||||
mesh.MakeVertexMap();
|
||||
foreach (var v in mesh.vertices.Values)
|
||||
{
|
||||
if (v.tri.tri == null && Log.Verbose)
|
||||
{
|
||||
logger.Warning("Vertex (ID " + v.id + ") not connected to mesh (duplicate input vertex?)",
|
||||
"MeshValidator.IsConsistent()");
|
||||
}
|
||||
}
|
||||
|
||||
// Restore the status of exact arithmetic.
|
||||
Behavior.NoExact = saveexact;
|
||||
|
||||
return (horrors == 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the mesh is (conforming) Delaunay.
|
||||
/// </summary>
|
||||
internal static bool IsDelaunay(Mesh mesh)
|
||||
{
|
||||
return IsDelaunay(mesh, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if that the mesh is (constrained) Delaunay.
|
||||
/// </summary>
|
||||
internal static bool IsConstrainedDelaunay(Mesh mesh)
|
||||
{
|
||||
return IsDelaunay(mesh, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure that the mesh is (constrained) Delaunay.
|
||||
/// </summary>
|
||||
private static bool IsDelaunay(Mesh mesh, bool constrained)
|
||||
{
|
||||
Otri loop = default(Otri);
|
||||
Otri oppotri = default(Otri);
|
||||
Osub opposubseg = default(Osub);
|
||||
Vertex org, dest, apex;
|
||||
Vertex oppoapex;
|
||||
|
||||
bool shouldbedelaunay;
|
||||
|
||||
var logger = Log.Instance;
|
||||
|
||||
// Temporarily turn on exact arithmetic if it's off.
|
||||
bool saveexact = Behavior.NoExact;
|
||||
Behavior.NoExact = false;
|
||||
|
||||
int horrors = 0;
|
||||
|
||||
var inf1 = mesh.infvertex1;
|
||||
var inf2 = mesh.infvertex2;
|
||||
var inf3 = mesh.infvertex3;
|
||||
|
||||
// Run through the list of triangles, checking each one.
|
||||
foreach (var tri in mesh.triangles)
|
||||
{
|
||||
loop.tri = tri;
|
||||
|
||||
// Check all three edges of the triangle.
|
||||
for (loop.orient = 0; loop.orient < 3; loop.orient++)
|
||||
{
|
||||
org = loop.Org();
|
||||
dest = loop.Dest();
|
||||
apex = loop.Apex();
|
||||
|
||||
loop.Sym(ref oppotri);
|
||||
oppoapex = oppotri.Apex();
|
||||
|
||||
// Only test that the edge is locally Delaunay if there is an
|
||||
// adjoining triangle whose pointer is larger (to ensure that
|
||||
// each pair isn't tested twice).
|
||||
shouldbedelaunay = (loop.tri.id < oppotri.tri.id) &&
|
||||
!Otri.IsDead(oppotri.tri) && (oppotri.tri.id != Mesh.DUMMY) &&
|
||||
(org != inf1) && (org != inf2) && (org != inf3) &&
|
||||
(dest != inf1) && (dest != inf2) && (dest != inf3) &&
|
||||
(apex != inf1) && (apex != inf2) && (apex != inf3) &&
|
||||
(oppoapex != inf1) && (oppoapex != inf2) && (oppoapex != inf3);
|
||||
|
||||
if (constrained && mesh.checksegments && shouldbedelaunay)
|
||||
{
|
||||
// If a subsegment separates the triangles, then the edge is
|
||||
// constrained, so no local Delaunay test should be done.
|
||||
loop.Pivot(ref opposubseg);
|
||||
|
||||
if (opposubseg.seg.hash != Mesh.DUMMY)
|
||||
{
|
||||
shouldbedelaunay = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldbedelaunay)
|
||||
{
|
||||
if (predicates.NonRegular(org, dest, apex, oppoapex) > 0.0)
|
||||
{
|
||||
if (Log.Verbose)
|
||||
{
|
||||
logger.Warning(String.Format("Non-regular pair of triangles found (IDs {0}/{1}).",
|
||||
loop.tri.id, oppotri.tri.id), "MeshValidator.IsDelaunay()");
|
||||
}
|
||||
|
||||
horrors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restore the status of exact arithmetic.
|
||||
Behavior.NoExact = saveexact;
|
||||
|
||||
return (horrors == 0);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue