text: //========= Copyright Valve Corporation, All rights reserved. ============//
  //
  // Purpose:
  //
  // $NoKeywords: $
  //=============================================================================//
  
  #ifndef DISPCOLL_H
  #define DISPCOLL_H
  #pragma once
  
  #include "mathlib/vector.h"
  
  class CCoreDispInfo;
  
  //=============================================================================
  //
  // Displacement Collision Triangle Data
  //
  class CDispCollTri
  {
  public:
  
      void Init( void );
      inline void SetPoint( int index, Vector const& vert );
      inline void SetPointNormal( int index, Vector const& normal );
      void CalcPlane( void );
  
      inline void SetIntersect( bool bIntersect );
      inline bool IsIntersect( void );
  
      Vector  m_Points[3];        // polygon points
      Vector  m_PointNormals[3];  // polygon point normals
      Vector  m_Normal;           // plane normal
      float   m_Distance;         // plane distance
      short   m_ProjAxes[2];      // projection axes (2 minor axes)
      bool    m_bIntersect;       // intersected triangle???
  };
  
  //=============================================================================
  //
  // Displacement Collision Node Data
  //
  class CDispCollNode
  {
  public:
  
      CDispCollNode();
      inline bool IsLeaf( void );
      inline void SetBounds( Vector const &bMin, Vector const &bMax );
      inline void GetBounds( Vector &bMin, Vector &bMax );
  
      Vector          m_Bounds[2];        // node minimum and maximum
  
      bool            m_bIsLeaf;          // is the node a leaf? ( may have to make this an int for alignment!)
      CDispCollTri    m_Tris[2];          // two triangles contained in leaf node
  };
  
  
  //=============================================================================
  //
  // Displacement Collision Data
  //
  class CDispCollData
  {
  public:
  
      Vector  m_StartPos;
      Vector  m_EndPos;
      Vector  m_Extents;
      float   m_Fraction;
      int     m_Contents;
      Vector  m_Normal;
      float   m_Distance;
      bool    m_bOcclude;
  };
  
  
  
  // HACKHACK: JAY: Moved this out of CDispCollTree to be thread safe in vrad
  enum { TRILIST_CACHE_SIZE = 128 };
  
  class CDispCollTreeTempData
  {
  public:
      //
      // temps
      //
      int                 m_TriListCount;
      CDispCollTri        *m_ppTriList[TRILIST_CACHE_SIZE];
  
      // collision tree node cache
      float               m_AABBDistances[6];
  };
  
  
  //=============================================================================
  //
  // Displacement Collision Tree
  //
  class CDispCollTree
  {
  public:
  
      static const float COLLISION_EPSILON;
      static const float ONE_MINUS_COLLISION_EPSILON;
  
      //=========================================================================
      //
      // Creation/Destruction
      //
      CDispCollTree();
      ~CDispCollTree();
  
      virtual bool Create( CCoreDispInfo *pDisp );
  
      //=========================================================================
      //
      // Collision Functions
      //
      bool RayTest( CDispCollData *pData );
      bool RayTestAllTris( CDispCollData *pData, int power );
  
      bool AABBIntersect( CDispCollData *pData );
      bool AABBSweep( CDispCollData *pData );
  
      //=========================================================================
      //
      // Attrib Functions
      //
      inline void SetPower( int power );
      inline int GetPower( void );
  
      inline void SetCheckCount( int count );
      inline int GetCheckCount( void );
  
      inline void GetBounds( Vector& boundMin, Vector& boundMax );
  
  protected:
  
      int                 m_Power;
  
      int                 m_NodeCount;
      CDispCollNode       *m_pNodes;
  
      int                 m_CheckCount;
  
      // collision tree node cache
      Vector              m_AABBNormals[6];
      //=========================================================================
      //
      // Creation/Destruction
      //
      void InitAABBData( void );
      void InitLeaves( CCoreDispInfo *pDisp );
      void CreateNodes( CCoreDispInfo *pDisp );
      void CreateNodes_r( CCoreDispInfo *pDisp, int nodeIndex, int termLevel );
      void CalcBounds( CDispCollNode *pNode, int nodeIndex );
  
      //=========================================================================
      //
      // Collision Functions
      //
      void CreatePlanesFromBounds( CDispCollTreeTempData *pTemp, Vector const &bbMin, Vector const &bbMax );
  
  //  void RayNodeTest_r( int nodeIndex, Vector &rayStart, Vector &rayEnd );
      void RayNodeTest_r( CDispCollTreeTempData *pTemp, int nodeIndex, Vector rayStart, Vector rayEnd );
      bool RayAABBTest( CDispCollTreeTempData *pTemp, Vector &rayStart, Vector &rayEnd );
      bool RayTriListTest( CDispCollTreeTempData *pTemp, CDispCollData *pData );
      bool RayTriTest( Vector const &rayStart, Vector const &rayDir, float const rayLength, CDispCollTri const *pTri, float *fraction );
  
      void BuildTriList_r( CDispCollTreeTempData *pTemp, int nodeIndex, Vector &rayStart, Vector &rayEnd, Vector &extents, bool bIntersect );
      bool IntersectAABBAABBTest( CDispCollTreeTempData *pTemp, const Vector &pos, const Vector &extents );
      bool SweptAABBAABBTest( CDispCollTreeTempData *pTemp, const Vector &rayStart, const Vector &rayEnd, const Vector &extents );
  
      bool CullTriList( CDispCollTreeTempData *pTemp, Vector &rayStart, Vector &rayEnd, Vector &extents, bool bIntersect );
      bool SweptAABBTriTest( Vector &rayStart, Vector &rayEnd, Vector &extents, CDispCollTri const *pTri );
      bool AABBTriIntersect( CDispCollTreeTempData *pTemp, CDispCollData *pData );
      bool IntersectAABBTriTest( Vector &rayStart, Vector &extents, CDispCollTri const *pTri );
      bool SweptAABBTriIntersect( Vector &rayStart, Vector &rayEnd, Vector &extents,
                                  CDispCollTri const *pTri, Vector &plNormal, float *plDist,
                                  float *fraction );
  
      //=========================================================================
      //
      // Memory Functions
      //
      bool AllocNodes( int nodeCount );
      void FreeNodes( void );
  
      //=========================================================================
      //
      // Utility Functions
      //
      inline int CalcNodeCount( int power );
      inline int GetParentNode( int nodeIndex );
      inline int GetChildNode( int nodeIndex, int direction );
      inline int GetNodeLevel( int nodeIndex );
      int GetNodeIndexFromComponents( int x, int y );
  };
  
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  inline void CDispCollTree::SetPower( int power )
  {
      m_Power = power;
  }
  
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  inline int CDispCollTree::GetPower( void )
  {
      return m_Power;
  }
  
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  inline void CDispCollTree::SetCheckCount( int count )
  {
      m_CheckCount = count;
  }
  
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  inline int CDispCollTree::GetCheckCount( void )
  {
      return m_CheckCount;
  }
  
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  inline void CDispCollTree::GetBounds( Vector& boundMin, Vector& boundMax )
  {
      boundMin[0] = m_pNodes[0].m_Bounds[0].x;
      boundMin[1] = m_pNodes[0].m_Bounds[0].y;
      boundMin[2] = m_pNodes[0].m_Bounds[0].z;
  
      boundMax[0] = m_pNodes[0].m_Bounds[1].x;
      boundMax[1] = m_pNodes[0].m_Bounds[1].y;
      boundMax[2] = m_pNodes[0].m_Bounds[1].z;
  }
  
  
  #endif // DISPCOLL_H
  