mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-04 04:18:27 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
261 lines
5.8 KiB
C#
261 lines
5.8 KiB
C#
|
|
namespace HalfEdgeMesh;
|
|
|
|
partial class Mesh
|
|
{
|
|
public int ComputeNumEdgesInFace( FaceHandle hFace )
|
|
{
|
|
var nNumEdges = 0;
|
|
|
|
if ( hFace.IsValid )
|
|
{
|
|
var hCurrentEdge = hFace.Edge;
|
|
do
|
|
{
|
|
++nNumEdges;
|
|
hCurrentEdge = hCurrentEdge.NextEdge;
|
|
}
|
|
while ( hCurrentEdge != hFace.Edge );
|
|
}
|
|
|
|
return nNumEdges;
|
|
}
|
|
|
|
public HalfEdgeHandle GetFirstEdgeInFaceLoop( FaceHandle hFace )
|
|
{
|
|
if ( !hFace.IsValid )
|
|
return HalfEdgeHandle.Invalid;
|
|
|
|
return hFace.Edge;
|
|
}
|
|
|
|
public HalfEdgeHandle GetNextEdgeInFaceLoop( HalfEdgeHandle hEdge )
|
|
{
|
|
if ( !hEdge.IsValid )
|
|
return HalfEdgeHandle.Invalid;
|
|
|
|
return hEdge.NextEdge;
|
|
}
|
|
|
|
public HalfEdgeHandle FindPreviousEdgeInFaceLoop( HalfEdgeHandle hEdge )
|
|
{
|
|
if ( !hEdge.IsValid )
|
|
return HalfEdgeHandle.Invalid;
|
|
|
|
var hCurrentEdge = hEdge;
|
|
do
|
|
{
|
|
if ( hCurrentEdge.NextEdge == hEdge )
|
|
return hCurrentEdge;
|
|
|
|
hCurrentEdge = hCurrentEdge.NextEdge;
|
|
}
|
|
while ( hCurrentEdge != hEdge );
|
|
|
|
return HalfEdgeHandle.Invalid;
|
|
}
|
|
|
|
public HalfEdgeHandle FindEdgeConnectedToFaceEndingAtVertex( FaceHandle hFace, VertexHandle hVertex )
|
|
{
|
|
if ( !hVertex.IsValid )
|
|
return HalfEdgeHandle.Invalid;
|
|
|
|
var hFirstEdge = GetFirstEdgeInVertexLoop( hVertex );
|
|
var hOutgoingEdge = hFirstEdge;
|
|
|
|
do
|
|
{
|
|
var hIncomingEdge = hOutgoingEdge.OppositeEdge;
|
|
if ( hIncomingEdge.Face == hFace )
|
|
return hIncomingEdge;
|
|
|
|
hOutgoingEdge = hIncomingEdge.NextEdge;
|
|
}
|
|
while ( hOutgoingEdge != hFirstEdge );
|
|
|
|
return HalfEdgeHandle.Invalid;
|
|
}
|
|
|
|
public HalfEdgeHandle FindEdgeConnectingFaces( FaceHandle hFaceA, FaceHandle hFaceB )
|
|
{
|
|
if ( !hFaceA.IsValid )
|
|
return HalfEdgeHandle.Invalid;
|
|
|
|
var hCurrentEdge = hFaceA.Edge;
|
|
do
|
|
{
|
|
if ( hCurrentEdge.OppositeEdge.Face == hFaceB )
|
|
return GetFullEdgeForHalfEdge( hCurrentEdge );
|
|
|
|
hCurrentEdge = hCurrentEdge.NextEdge;
|
|
}
|
|
while ( hCurrentEdge != hFaceA.Edge );
|
|
|
|
return HalfEdgeHandle.Invalid;
|
|
}
|
|
|
|
public bool GetHalfEdgesConnectedToFace( FaceHandle hFace, out HalfEdgeHandle[] hEdges )
|
|
{
|
|
hEdges = null;
|
|
|
|
if ( !hFace.IsValid )
|
|
return false;
|
|
|
|
var nNumEdges = ComputeNumEdgesInFace( hFace );
|
|
if ( nNumEdges <= 0 )
|
|
return false;
|
|
|
|
hEdges = new HalfEdgeHandle[nNumEdges];
|
|
|
|
int i = 0;
|
|
var hEdge = hFace.Edge;
|
|
do
|
|
{
|
|
hEdges[i++] = hEdge;
|
|
hEdge = hEdge.NextEdge;
|
|
}
|
|
while ( hEdge != hFace.Edge );
|
|
|
|
return hEdges.Length == nNumEdges;
|
|
}
|
|
|
|
public bool GetFullEdgesConnectedToFace( FaceHandle hFace, out List<HalfEdgeHandle> edges )
|
|
{
|
|
edges = new List<HalfEdgeHandle>();
|
|
|
|
if ( !hFace.IsValid )
|
|
return false;
|
|
|
|
int nNumEdges = ComputeNumEdgesInFace( hFace );
|
|
if ( nNumEdges <= 0 )
|
|
return false;
|
|
|
|
edges.EnsureCapacity( nNumEdges );
|
|
|
|
var hEdge = hFace.Edge;
|
|
do
|
|
{
|
|
edges.Add( GetFullEdgeForHalfEdge( hEdge ) );
|
|
hEdge = hEdge.NextEdge;
|
|
}
|
|
while ( hEdge != hFace.Edge );
|
|
|
|
Assert.True( edges.Count == nNumEdges );
|
|
return edges.Count == nNumEdges;
|
|
}
|
|
|
|
public bool GetVerticesConnectedToFace( FaceHandle hFace, out VertexHandle[] vertices )
|
|
{
|
|
vertices = null;
|
|
|
|
if ( !hFace.IsValid )
|
|
return false;
|
|
|
|
int nNumVertices = ComputeNumEdgesInFace( hFace );
|
|
if ( nNumVertices <= 0 )
|
|
return false;
|
|
|
|
vertices = new VertexHandle[nNumVertices];
|
|
|
|
var i = 0;
|
|
var hCurrentEdge = hFace.Edge;
|
|
do
|
|
{
|
|
vertices[i++] = hCurrentEdge.Vertex;
|
|
hCurrentEdge = hCurrentEdge.NextEdge;
|
|
}
|
|
while ( hCurrentEdge != hFace.Edge );
|
|
|
|
return i == nNumVertices;
|
|
}
|
|
|
|
public void FindVerticesConnectedToFaces( IReadOnlyList<FaceHandle> pFaceList, int nNumFaces, out VertexHandle[] outVertices )
|
|
{
|
|
var uniqueVertices = new Dictionary<VertexHandle, int>();
|
|
var i = 0;
|
|
for ( var iFace = 0; iFace < nNumFaces; ++iFace )
|
|
{
|
|
var hFace = pFaceList[iFace];
|
|
var hStartEdge = GetFirstEdgeInFaceLoop( hFace );
|
|
|
|
if ( !hStartEdge.IsValid )
|
|
continue;
|
|
|
|
var hCurrentEdge = hStartEdge;
|
|
do
|
|
{
|
|
if ( !uniqueVertices.ContainsKey( hCurrentEdge.Vertex ) )
|
|
uniqueVertices.Add( hCurrentEdge.Vertex, i++ );
|
|
|
|
hCurrentEdge = GetNextEdgeInFaceLoop( hCurrentEdge );
|
|
}
|
|
while ( hCurrentEdge != hStartEdge );
|
|
}
|
|
|
|
outVertices = new VertexHandle[uniqueVertices.Count];
|
|
foreach ( var hVertex in uniqueVertices )
|
|
outVertices[hVertex.Value] = hVertex.Key;
|
|
}
|
|
|
|
public void FindFullEdgesConnectedToFaces( IReadOnlyList<FaceHandle> pFaceList, int nNumFaces, out HalfEdgeHandle[] pOutEdgeList, out int[] pOutEdgeFaceCounts )
|
|
{
|
|
var nNumTotalFaceEdges = 0;
|
|
for ( var iFace = 0; iFace < nNumFaces; ++iFace )
|
|
{
|
|
nNumTotalFaceEdges += ComputeNumEdgesInFace( pFaceList[iFace] );
|
|
}
|
|
|
|
var uniqueEdges = new Dictionary<HalfEdgeHandle, int>( nNumTotalFaceEdges );
|
|
|
|
for ( var iFace = 0; iFace < nNumFaces; ++iFace )
|
|
{
|
|
var hFace = pFaceList[iFace];
|
|
var hStartEdge = GetFirstEdgeInFaceLoop( hFace );
|
|
if ( hStartEdge == HalfEdgeHandle.Invalid )
|
|
continue;
|
|
|
|
var hCurrentEdge = hStartEdge;
|
|
do
|
|
{
|
|
var hFullEdge = GetFullEdgeForHalfEdge( hCurrentEdge );
|
|
if ( !uniqueEdges.ContainsKey( hFullEdge ) )
|
|
uniqueEdges.Add( hFullEdge, uniqueEdges.Count );
|
|
|
|
hCurrentEdge = GetNextEdgeInFaceLoop( hCurrentEdge );
|
|
}
|
|
while ( hCurrentEdge != hStartEdge );
|
|
}
|
|
|
|
var nNumUniqueEdges = uniqueEdges.Count;
|
|
pOutEdgeList = new HalfEdgeHandle[nNumUniqueEdges];
|
|
|
|
foreach ( var pair in uniqueEdges )
|
|
{
|
|
pOutEdgeList[pair.Value] = pair.Key;
|
|
}
|
|
|
|
pOutEdgeFaceCounts = new int[nNumUniqueEdges];
|
|
|
|
for ( var iFace = 0; iFace < nNumFaces; ++iFace )
|
|
{
|
|
var hFace = pFaceList[iFace];
|
|
var hStartEdge = GetFirstEdgeInFaceLoop( hFace );
|
|
if ( hStartEdge == HalfEdgeHandle.Invalid )
|
|
continue;
|
|
|
|
var hCurrentEdge = hStartEdge;
|
|
do
|
|
{
|
|
var hFullEdge = GetFullEdgeForHalfEdge( hCurrentEdge );
|
|
if ( uniqueEdges.TryGetValue( hFullEdge, out var nIndex ) )
|
|
{
|
|
pOutEdgeFaceCounts[nIndex]++;
|
|
}
|
|
|
|
hCurrentEdge = GetNextEdgeInFaceLoop( hCurrentEdge );
|
|
}
|
|
while ( hCurrentEdge != hStartEdge );
|
|
}
|
|
}
|
|
}
|