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.
|
|
//--------------------------------------------------------------------------------------------------
// 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; }
|