Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

222 lines
4.5 KiB

//--------------------------------------------------------------------------------------------------
// qhHalfEdge.cpp
//
// Copyright(C) 2011 by D. Gregorius. All rights reserved.
//--------------------------------------------------------------------------------------------------
#include "qhHalfEdge.h"
//--------------------------------------------------------------------------------------------------
// Utilities
//--------------------------------------------------------------------------------------------------
bool qhHalfEdge::IsConvex( qhReal Tolerance ) const
{
return Face->Plane.Distance( Twin->Face->Centroid ) < -Tolerance;
}
//--------------------------------------------------------------------------------------------------
void qhLinkFace( qhFace* Face, int Index, qhHalfEdge* Twin )
{
qhHalfEdge* Edge = Face->Edge;
while ( Index-- > 0 )
{
Edge = Edge->Next;
}
QH_ASSERT( Edge != Twin );
Edge->Twin = Twin;
Twin->Twin = Edge;
}
//--------------------------------------------------------------------------------------------------
void qhLinkFaces( qhFace* Face1, int Index1, qhFace* Face2, int Index2 )
{
qhHalfEdge* Edge1 = Face1->Edge;
while ( Index1-- > 0 )
{
Edge1 = Edge1->Next;
}
qhHalfEdge* Edge2 = Face2->Edge;
while ( Index2-- > 0 )
{
Edge2 = Edge2->Next;
}
QH_ASSERT( Edge1 != Edge2 );
Edge1->Twin = Edge2;
Edge2->Twin = Edge1;
}
//--------------------------------------------------------------------------------------------------
void qhNewellPlane( qhFace* Face )
{
int Count = 0;
qhVector3 Centroid = QH_VEC3_ZERO;
qhVector3 Normal = QH_VEC3_ZERO;
qhHalfEdge* Edge = Face->Edge;
QH_ASSERT( Edge->Face == Face );
do
{
qhHalfEdge* Twin = Edge->Twin;
QH_ASSERT( Twin->Twin == Edge );
const qhVector3& V1 = Edge->Origin->Position;
const qhVector3& V2 = Twin->Origin->Position;
Count++;
Centroid += V1;
// This seems to be more robust than N += Cross( V1, V2 )
Normal.X += ( V1.Y - V2.Y ) * ( V1.Z + V2.Z );
Normal.Y += ( V1.Z - V2.Z ) * ( V1.X + V2.X );
Normal.Z += ( V1.X - V2.X ) * ( V1.Y + V2.Y );
Edge = Edge->Next;
}
while ( Edge != Face->Edge );
QH_ASSERT( Count > 2 );
Centroid /= qhReal( Count );
Face->Centroid = Centroid;
qhReal Area = qhLength( Normal );
QH_ASSERT( Area > qhReal( 0.0 ) );
Normal /= Area;
Face->Plane = qhPlane( Normal, Centroid );
Face->Area = Area;
}
//--------------------------------------------------------------------------------------------------
bool qhIsConvex( const qhFace* Face, qhReal Tolerance )
{
const qhHalfEdge* Edge = Face->Edge;
do
{
qhVector3 Tail = Edge->Origin->Position;
qhVector3 Head = Edge->Twin->Origin->Position;
qhVector3 Offset = Head - Tail;
qhVector3 Normal = qhCross( Offset, Face->Plane.Normal );
qhPlane Plane( Normal, Head );
Plane.Normalize();
qhReal Distance = Plane.Distance( Edge->Next->Twin->Origin->Position );
if ( Distance > -Tolerance )
{
return false;
}
Edge = Edge->Next;
}
while ( Edge != Face->Edge );
return true;
}
//--------------------------------------------------------------------------------------------------
int qhVertexCount( const qhFace* Face )
{
int VertexCount = 0;
const qhHalfEdge* Edge = Face->Edge;
do
{
VertexCount++;
Edge = Edge->Next;
}
while ( Edge != Face->Edge );
return VertexCount;
}
//--------------------------------------------------------------------------------------------------
bool qhCheckConsistency( const qhFace* Face )
{
if ( Face->Mark == QH_MARK_DELETE )
{
// Face is not on the hull
return false;
}
if ( qhVertexCount( Face ) < 3 )
{
// Invalid geometry
return false;
}
const qhHalfEdge* Edge = Face->Edge;
do
{
const qhHalfEdge* Twin = Edge->Twin;
if ( Twin == NULL )
{
// Unreflected edge
return false;
}
if ( Twin->Face == NULL )
{
// Missing face
return false;
}
if ( Twin->Face == Face )
{
// Edge is connecting the same face
return false;
}
if ( Twin->Face->Mark == QH_MARK_DELETE )
{
// Face is not on hull
return false;
}
if ( Twin->Twin != Edge )
{
// Edge reflected incorrectly
return false;
}
if ( Edge->Origin != Twin->Next->Origin )
{
// Topology error
return false;
}
if ( Twin->Origin != Edge->Next->Origin )
{
// Topology error
return false;
}
if ( Edge->Face != Face )
{
// Topology error
return false;
}
Edge = Edge->Next;
}
while ( Edge != Face->Edge );
return true;
}