#ifndef __SPATIAL_TREE_ITER_H__
#define __SPATIAL_TREE_ITER_H__

#include <p3d/utility.hpp>
#include <render/culling/SpatialTree.h>
#include <render/culling/ISpatialProxy.h>
#include <render/culling/SphereSP.h>
#include <render/culling/Bounds.h>
#include <render/culling/BoxPts.h>
#include <render/culling/FixedArray.h>
#include <render/culling/UseArray.h>

typedef int tMark;


class SpatialTreeIter
{
public:
   SpatialTreeIter();
   ~SpatialTreeIter();

   void SetToRoot( SpatialTree& irTree );
   void Clear();

   //Allocation&Placement Navigation
/*
   void              Place(          ISpatialProxyAA& irTVolume, T*  ipT );
   void              ReservePlaceT(  ISpatialProxyAA& irTVolume, int iCount );
   void              Place(          ISpatialProxyAA& irTVolume, D*  ipD );
   void              ReservePlaceD(  ISpatialProxyAA& irTVolume, int iCount );
   void              Place(          ISpatialProxyAA& irIVolume, I*  ipI );
   void              ReservePlaceI(  ISpatialProxyAA& irIVolume, int iCount );
   void              AllocateAllReservations();
*/

   //Node Retrieval Methods
   SpatialNode&   rSeekNode(     ISpatialProxyAA& irTVolume, 
                                        int              iCurNodeOffset=0 );
   SpatialNode&   rIthNode(      int              iIth );
   int                   NumNodes();

   void                  SeekSubNodes(  ISpatialProxyAA& irTVolume,
                                        UseArray<int>&   orNodeOffsets, 
                                        int              iCurNodeOffset=0 );
   void                  SeekAllNodes(  ISpatialProxyAA& irTVolume,
                                        UseArray<int>&   orNodeOffsets, 
                                        int              iCurNodeOffset=0 );
   void                  SetUpNodeList( UseArray<int>&   orNodeOffsets );

   //Iteration Initialization
   void              MarkAll( SphereSP& irDesiredVolume, tMark iMark );
   void              MarkAllSphere( SphereSP& irSphere, tMark iMark );
   void              MarkSubTrees( ISpatialProxyAA& irDesiredVolume, tMark iMark );
   void              MarkTree( tMark iMark );
   void              AndTree(  tMark iMark );
   void              OrTree(   tMark iMark );
   void              OrTreeVis(   tMark iMark );


   //Iteration Navigation
   SpatialNode&   rSeekLeaf( Vector3f& irPt );

   void              SetIterFilter( tMark iMark );
   void              MoveToFirst();
   
   SpatialNode&   rCurrent();
   inline SpatialNode*   pCurrent();

   void              MoveToNext(bool ibIncludeVis=false);
   SpatialNode&   rMoveToNext(bool ibIncludeVis=false);
   SpatialNode*   pMoveToNext(bool ibIncludeVis=false);
   
   bool              NotDone();
   bool              IsCurrentLeaf();

   //Debug Functionality
//   void              DisplayBoundingBox();
   void              DisplayCurrentBoundingBox( const tColour& irColour );
   bool              IsSetUp();
   BoxPts*           CurrentBBox();
   
   BoxPts&           rBBox();
   void              BuildBBoxes( BoxPts iBoxPts, int iCurNodeOffset = 0);

   enum 
   {
      msFilterInvisible = 0xF0000000,  
      msFilterVisible   = 0x0F000000,
      msFilterAll       = 0x00FFFFFF
   };

   SwapArray<SpatialNode*> mCurNodes;
   SwapArray<SpatialNode*> mCurAlwaysVisNodes;

protected:
   SwapArray<SpatialNode*>* mpCurNodeList;
   ContiguousBinNode< SpatialNode >* mpRootNode;
   ContiguousBinNode< SpatialNode >* mpCurNode;
   
   int mCurNodeOffset;

   FixedArray<tMark>   mNodeMarks;
   tMark               mCurMarkFilter;

   int mCurNodeI;

   //Bounding Box is left as series of defining points to make iteration simpler
   BoxPts mBBox;


   SpatialNode& rSeekLeaf( int iCurNodeOffset, Vector3f& irPt );

   void MarkAll( int                ipCurNode,
                 BoxPts&            irBoxPts, 
                 SphereSP&   irDesiredVolume, 
                 tMark              iMark );

   void MarkSubTrees( int                ipCurNode,
                      BoxPts&            irBoxPts, 
                      ISpatialProxyAA&   irDesiredVolume, 
                      tMark              iMark );

   void MarkAllSphere(  int         ipCurNode,
                        BoxPts&     irBoxPts, 
                        SphereSP&   irSphere, 
                        tMark       iMark );

   void MarkAllSphereIntersect(  int        ipCurNode,
                                BoxPts&     irBoxPts, 
                                SphereSP&   irSphere, 
                                tMark       iMark );

   void MarkSubTree( int   iCurNodeOffset,
                     tMark iMark );

/*
   void Place(           int iCurNodeOffset, ISpatialProxyAA& irTVolume, T*  ipT );
   void ReservePlaceT(   int iCurNodeOffset, ISpatialProxyAA& irTVolume, int iCount );
   void Place(           int iCurNodeOffset, ISpatialProxyAA& irTVolume, D*  ipD );
   void ReservePlaceD(   int iCurNodeOffset, ISpatialProxyAA& irTVolume, int iCount );
   void Place(           int iCurNodeOffset, ISpatialProxyAA& irIVolume, I*  ipI );
   void ReservePlaceI(   int iCurNodeOffset, ISpatialProxyAA& irIVolume, int iCount );
*/
   //Debug functionality
//   void DisplayBoundingBox( int iCurNodeOffset, BoxPts& orBBox, tColour colour );
   void DisplayBoundingBox( BoxPts& irBBox, tColour colour );

};

/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline 
SpatialTreeIter::SpatialTreeIter()
:    mpRootNode( NULL )
{
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
bool SpatialTreeIter::IsSetUp()
{
   return ( mpRootNode != NULL );
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
SpatialTreeIter::~SpatialTreeIter()
{
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
void SpatialTreeIter::SetToRoot( SpatialTree& irTree )
{
   mpRootNode = irTree.GetRoot();

   mBBox.SetTo( irTree.GetBounds() );

   mNodeMarks.Allocate( mpRootNode->GetSubTreeSize()+1 );
   mCurNodes.Allocate( mpRootNode->GetSubTreeSize()+1 );
   mCurAlwaysVisNodes.Allocate( mpRootNode->GetSubTreeSize()+1 );
   mpCurNodeList = &mCurNodes;
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
void SpatialTreeIter::Clear()
{
   mpRootNode  = NULL;
}

//========================================================================
// SpatialTreeIter::
//========================================================================
//
// Description: 
//
// Parameters:  None.
//
// Return:      None.
//
// Constraints: None.
//
//========================================================================
inline 
SpatialNode&   SpatialTreeIter::rIthNode
(
   int              iIth
)
{
   return (mpRootNode+iIth)->mData;
}
//========================================================================
// SpatialTreeIter::
//========================================================================
//
// Description: 
//
// Parameters:  None.
//
// Return:      None.
//
// Constraints: None.
//
//========================================================================
inline  
int   SpatialTreeIter::NumNodes
(
)
{
   return (mpRootNode->GetSubTreeSize()+1);
}

//========================================================================
// SpatialTreeIter::
//========================================================================
//
// Description: 
//
// Parameters:  None.
//
// Return:      None.
//
// Constraints: None.
//
//========================================================================
inline  
void SpatialTreeIter::SetUpNodeList
( 
   UseArray<int>&   orNodeOffsets 
)
{
   orNodeOffsets.Allocate( mpRootNode->GetSubTreeSize()+1 );
}
/*
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
void SpatialTreeIter::ReservePlaceD(   ISpatialProxyAA& irDVolume, int iCount)
{
   ReservePlaceD( 0, irDVolume, iCount );   
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
void SpatialTreeIter::ReservePlaceD
( 
   int               iCurNodeOffset, 
   ISpatialProxyAA&  irDVolume, 
   int               iCount
)
{
   ContiguousBinNode< SpatialNode >* pCurNode = (mpRootNode+iCurNodeOffset);

   if( pCurNode->GetSubTreeSize() > 0 )
   {
      float PlaneVolResult = irDVolume.CompareTo( pCurNode->mData.mSubDivPlane );

      if( PlaneVolResult > 0.0f ) //The Plane is greater than TVolume in Posn, so TVolume is in the LT Partitiion..
      {
         ReservePlaceD( iCurNodeOffset + pCurNode->LChildOffset(), irDVolume, iCount );
      } 
      else
      {
         if( PlaneVolResult < 0.0f ) //The Plane is less han TVolume in Posn, so TVolume is in the GT Partitiion..
         {
            ReservePlaceD( iCurNodeOffset + pCurNode->RChildOffset(), irDVolume, iCount );
         }
         else //  PlaneVolResult == 0 
         {
            //pCurNode = pCurNode->Parent();
            pCurNode->mData.mDynamicElems.Reserve(iCount);
         }
      }
   }
   else
   {
      pCurNode->mData.mDynamicElems.Reserve(iCount);
   }
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
void SpatialTreeIter::ReservePlaceT(   ISpatialProxyAA& irTVolume, int iCount)
{
   ReservePlaceT( 0, irTVolume, iCount );   
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
void SpatialTreeIter::ReservePlaceT
( 
   int               iCurNodeOffset, 
   ISpatialProxyAA&  irTVolume, 
   int               iCount
)
{
   ContiguousBinNode< SpatialNode >* pCurNode = (mpRootNode+iCurNodeOffset);

   if( pCurNode->GetSubTreeSize() > 0 )
   {
      float PlaneVolResult = irTVolume.CompareTo( pCurNode->mData.mSubDivPlane );

      if( PlaneVolResult > 0.0f ) //The Plane is greater than TVolume in Posn, so TVolume is in the LT Partitiion..
      {
         ReservePlaceT( iCurNodeOffset + pCurNode->LChildOffset(), irTVolume, iCount );
      } 
      else
      {
         if( PlaneVolResult < 0.0f ) //The Plane is less han TVolume in Posn, so TVolume is in the GT Partitiion..
         {
            ReservePlaceT( iCurNodeOffset + pCurNode->RChildOffset(), irTVolume, iCount );
         }
         else //  PlaneVolResult == 0 
         {
            //pCurNode = pCurNode->Parent();
            pCurNode->mData.mSpatialElems.Reserve(iCount);
         }
      }
   }
   else
   {
      pCurNode->mData.mSpatialElems.Reserve(iCount);
   }
}
*/
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
SpatialNode& SpatialTreeIter::rSeekLeaf( Vector3f& irPt )
{
   return rSeekLeaf( 0, irPt );
}
/*
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
void SpatialTreeIter::ReservePlaceI(   ISpatialProxyAA& irIVolume, int iCount)
{
   ReservePlaceI( 0, irIVolume, iCount );   
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
void SpatialTreeIter::ReservePlaceI
( 
   int               iCurNodeOffset, 
   ISpatialProxyAA&  irIVolume, 
   int               iCount
)
{
   ContiguousBinNode< SpatialNode >* pCurNode = (mpRootNode+iCurNodeOffset);

   if( pCurNode->GetSubTreeSize() > 0 )
   {
      float PlaneVolResult = irIVolume.CompareTo( pCurNode->mData.mSubDivPlane );

      if( PlaneVolResult > 0.0f ) //The Plane is greater than TVolume in Posn, so TVolume is in the LT Partitiion..
      {
         ReservePlaceI( iCurNodeOffset + pCurNode->LChildOffset(), irIVolume, iCount );
      } 
      else
      {
         if( PlaneVolResult < 0.0f ) //The Plane is less han TVolume in Posn, so TVolume is in the GT Partitiion..
         {
            ReservePlaceI( iCurNodeOffset + pCurNode->RChildOffset(), irIVolume, iCount );
         }
         else //  PlaneVolResult == 0 
         {
            //pCurNode = pCurNode->Parent();
            pCurNode->mData.mIntersectElems.Reserve(iCount);
         }
      }
   }
   else
   {
      pCurNode->mData.mIntersectElems.Reserve(iCount);
   }
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
void SpatialTreeIter::Place(   ISpatialProxyAA& irDVolume,       D* ipD )
{
   Place( 0, irDVolume, ipD );   
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
void SpatialTreeIter::Place
( 
   int               iCurNodeOffset, 
   ISpatialProxyAA&  irDVolume, 
   D*                ipD
)
{
   ContiguousBinNode< SpatialNode >* pCurNode = (mpRootNode+iCurNodeOffset);

   if( pCurNode->GetSubTreeSize() > 0 )
   {
      float PlaneVolResult = irDVolume.CompareTo( pCurNode->mData.mSubDivPlane );

      if( PlaneVolResult > 0.0f ) //The Plane is greater than TVolume in Posn, so TVolume is in the LT Partitiion..
      {
         Place( iCurNodeOffset + pCurNode->LChildOffset(), irDVolume, ipD );
      } 
      else
      {
         if( PlaneVolResult < 0.0f ) //The Plane is less han TVolume in Posn, so TVolume is in the GT Partitiion..
         {
            Place( iCurNodeOffset + pCurNode->RChildOffset(), irDVolume, ipD );
         }
         else //  PlaneVolResult == 0 
         {
            //pCurNode = pCurNode->Parent();
            pCurNode->mData.mDynamicElems.Add(ipD);
         }
      }
   }
   else
   {
      pCurNode->mData.mDynamicElems.Add(ipD);
   }
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
void SpatialTreeIter::Place(   ISpatialProxyAA& irTVolume,       T* ipT )
{
   Place( 0, irTVolume, ipT );   
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
void SpatialTreeIter::Place
( 
   int               iCurNodeOffset, 
   ISpatialProxyAA&  irTVolume, 
   T*                ipT
)
{
   ContiguousBinNode< SpatialNode >* pCurNode = (mpRootNode+iCurNodeOffset);

   if( pCurNode->GetSubTreeSize() > 0 )
   {
      float PlaneVolResult = irTVolume.CompareTo( pCurNode->mData.mSubDivPlane );

      if( PlaneVolResult > 0.0f ) //The Plane is greater than TVolume in Posn, so TVolume is in the LT Partitiion..
      {
         Place( iCurNodeOffset + pCurNode->LChildOffset(), irTVolume, ipT );
      } 
      else
      {
         if( PlaneVolResult < 0.0f ) //The Plane is less han TVolume in Posn, so TVolume is in the GT Partitiion..
         {
            Place( iCurNodeOffset + pCurNode->RChildOffset(), irTVolume, ipT );
         }
         else //  PlaneVolResult == 0 
         {
            //pCurNode = pCurNode->Parent();
            pCurNode->mData.mSpatialElems.Add(ipT);
         }
      }
   }
   else
   {
      pCurNode->mData.mSpatialElems.Add(ipT);
   }
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
void SpatialTreeIter::Place(   ISpatialProxyAA& irIVolume,       I* ipI )
{
   Place( 0, irIVolume, ipI );   
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
void SpatialTreeIter::Place
( 
   int               iCurNodeOffset, 
   ISpatialProxyAA&  irIVolume, 
   I*                ipI
)
{
   ContiguousBinNode< SpatialNode >* pCurNode = (mpRootNode+iCurNodeOffset);

   if( pCurNode->GetSubTreeSize() > 0 )
   {
      float PlaneVolResult = irIVolume.CompareTo( pCurNode->mData.mSubDivPlane );

      if( PlaneVolResult > 0.0f ) //The Plane is greater than TVolume in Posn, so TVolume is in the LT Partitiion..
      {
         Place( iCurNodeOffset + pCurNode->LChildOffset(), irIVolume, ipI );
      } 
      else
      {
         if( PlaneVolResult < 0.0f ) //The Plane is less han TVolume in Posn, so TVolume is in the GT Partitiion..
         {
            Place( iCurNodeOffset + pCurNode->RChildOffset(), irIVolume, ipI );
         }
         else //  PlaneVolResult == 0 
         {
            //pCurNode = pCurNode->Parent();
            pCurNode->mData.mIntersectElems.Add(ipI);
         }
      }
   }
   else
   {
      pCurNode->mData.mIntersectElems.Add(ipI);
   }
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
void SpatialTreeIter::AllocateAllReservations()
{
   int TreeSize = mpRootNode->GetSubTreeSize();

   for( int i=0; i<=TreeSize; i++ )
   {
      (mpRootNode+i)->mData.mSpatialElems.Allocate();
      (mpRootNode+i)->mData.mDynamicElems.Allocate();
      (mpRootNode+i)->mData.mIntersectElems.Allocate();
   }
}
*/
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
void SpatialTreeIter::MarkAll( SphereSP& irDesiredVolume, tMark iMark )
{
   mCurNodes.ClearUse();
   BoxPts tmpBBox(mBBox);
   MarkAll( 0, tmpBBox, irDesiredVolume, iMark );   
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
void SpatialTreeIter::MarkAllSphere( SphereSP& irSphere, tMark iMark )
{
   mCurNodes.ClearUse();
   BoxPts tmpBBox(mBBox);
   MarkAllSphere( 0, tmpBBox, irSphere, iMark );   
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
void SpatialTreeIter::MarkSubTrees( ISpatialProxyAA& irDesiredVolume, tMark iMark )
{
   BoxPts tmpBBox(mBBox);
   MarkSubTrees( 0, tmpBBox, irDesiredVolume, iMark );   
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/*inline  
void SpatialTreeIter::CallBackAll( ISpatialProxyAA& irDesiredVolume, void (*pCB)(SpatialNode*) )
{
   BoxPts tmpBBox(mBBox);
   CallBackAll( 0, tmpBBox, irDesiredVolume, pCB );   
}
*/
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
BoxPts* SpatialTreeIter::CurrentBBox()
{
   return &(mpCurNode->mData.mBBox);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/*
 
void SpatialTreeIter::DisplayBoundingBox( )
{
   BoxPts tmpBBox( mBBox );

   DisplayBoundingBox( 0, tmpBBox, tColour(0,255,0) );
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
 
void SpatialTreeIter::DisplayBoundingBox( int iCurNodeOffset, BoxPts& orBBox, tColour colour )
{
   DisplayBoundingBox( orBBox, colour );

   
   ContiguousBinNode< SpatialNode >* pCurNode = (mpRootNode+iCurNodeOffset);

   if( pCurNode->GetSubTreeSize() > 0 )
   {
      //split subspace representation, and recurse
      BoxPts BBoxLT;
      BBoxLT = orBBox;

      BBoxLT.CutOffGT( pCurNode->mData.mSubDivPlane );

      DisplayBoundingBox( iCurNodeOffset + pCurNode->LChildOffset(), BBoxLT, colour );   

      orBBox.CutOffLT( pCurNode->mData.mSubDivPlane );

      DisplayBoundingBox( iCurNodeOffset + pCurNode->RChildOffset(), orBBox, colour );
   }
}
*/
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
inline 
BoxPts& SpatialTreeIter::rBBox()
{
   return mBBox;
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
void SpatialTreeIter::DisplayBoundingBox( BoxPts& irBBox, tColour colour )
{
//#if PURE3D_VERSION_MAJOR < 15
//   tShader* testMat = p3d::find<tShader>("p3d_default");
//#endif

//#if PURE3D_VERSION_MAJOR < 15
//   pddiPrimStream* stream = p3d::pddi->BeginPrims(testMat->GetShader(), PDDI_PRIM_LINESTRIP, PDDI_V_C );
//#else
   pddiPrimStream* stream = p3d::pddi->BeginPrims(NULL, PDDI_PRIM_LINESTRIP, PDDI_V_C, 5);
//#endif
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMin.x, irBBox.mBounds.mMin.y, irBBox.mBounds.mMin.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMax.x, irBBox.mBounds.mMin.y, irBBox.mBounds.mMin.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMax.x, irBBox.mBounds.mMax.y, irBBox.mBounds.mMin.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMin.x, irBBox.mBounds.mMax.y, irBBox.mBounds.mMin.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMin.x, irBBox.mBounds.mMin.y, irBBox.mBounds.mMin.z);
   p3d::pddi->EndPrims(stream);

//#if PURE3D_VERSION_MAJOR < 15
//   stream = p3d::pddi->BeginPrims(testMat->GetShader(), PDDI_PRIM_LINESTRIP, PDDI_V_C );
//#else
   stream = p3d::pddi->BeginPrims(NULL, PDDI_PRIM_LINESTRIP, PDDI_V_C, 5);
//#endif
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMax.x, irBBox.mBounds.mMax.y, irBBox.mBounds.mMax.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMin.x, irBBox.mBounds.mMax.y, irBBox.mBounds.mMax.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMin.x, irBBox.mBounds.mMin.y, irBBox.mBounds.mMax.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMax.x, irBBox.mBounds.mMin.y, irBBox.mBounds.mMax.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMax.x, irBBox.mBounds.mMax.y, irBBox.mBounds.mMax.z);
   p3d::pddi->EndPrims(stream);

//#if PURE3D_VERSION_MAJOR < 15
//   stream = p3d::pddi->BeginPrims(testMat->GetShader(), PDDI_PRIM_LINESTRIP, PDDI_V_C );
//#else
   stream = p3d::pddi->BeginPrims(NULL, PDDI_PRIM_LINESTRIP, PDDI_V_C, 5);
//#endif
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMax.x, irBBox.mBounds.mMax.y, irBBox.mBounds.mMax.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMax.x, irBBox.mBounds.mMin.y, irBBox.mBounds.mMax.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMax.x, irBBox.mBounds.mMin.y, irBBox.mBounds.mMin.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMax.x, irBBox.mBounds.mMax.y, irBBox.mBounds.mMin.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMax.x, irBBox.mBounds.mMax.y, irBBox.mBounds.mMax.z);
   p3d::pddi->EndPrims(stream);

//#if PURE3D_VERSION_MAJOR < 15
//   stream = p3d::pddi->BeginPrims(testMat->GetShader(), PDDI_PRIM_LINESTRIP, PDDI_V_C );
//#else
   stream = p3d::pddi->BeginPrims(NULL, PDDI_PRIM_LINESTRIP, PDDI_V_C, 5);
//#endif
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMin.x, irBBox.mBounds.mMax.y, irBBox.mBounds.mMax.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMin.x, irBBox.mBounds.mMin.y, irBBox.mBounds.mMax.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMin.x, irBBox.mBounds.mMin.y, irBBox.mBounds.mMin.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMin.x, irBBox.mBounds.mMax.y, irBBox.mBounds.mMin.z);
   stream->Colour(colour);
   stream->Coord(irBBox.mBounds.mMin.x, irBBox.mBounds.mMax.y, irBBox.mBounds.mMax.z);
   p3d::pddi->EndPrims(stream);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
SpatialNode*   SpatialTreeIter::pCurrent()
{
   return (*mpCurNodeList)[mCurNodeI];
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
void SpatialTreeIter::DisplayCurrentBoundingBox( const tColour& irColour )
{
   DisplayBoundingBox( pCurrent()->mBBox, irColour );
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
void SpatialTreeIter::MarkTree( tMark iMark )
{
   for( int i=mNodeMarks.mSize-1; i>= 0; i-- )
   {
      mNodeMarks[i] = iMark;
   }
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
void SpatialTreeIter::AndTree(  tMark iMark )
{
    //If we're clearing all flags including the visibility flags, then we want 
    //to clear away our extra visible set of nodes
   if(iMark==0x00000000) 
   {
      mCurAlwaysVisNodes.ClearUse();
   }

   for( int i=mNodeMarks.mSize-1; i>= 0; i-- )
   {
      mNodeMarks[i] &= iMark;
   }
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
void SpatialTreeIter::OrTree(   tMark iMark )
{
   for( int i=mNodeMarks.mSize-1; i>= 0; i-- )
   {
      mNodeMarks[i] |= iMark;
   }
}
inline  
void SpatialTreeIter::OrTreeVis(   tMark iMark )
{
   mCurNodes.ClearUse();
   SpatialNode* pFuckinCast;
   for( int i=mNodeMarks.mSize-1; i>= 0; i-- )
   {
      mNodeMarks[i] |= iMark;
      pFuckinCast = &(mpRootNode[i].mData);
      mCurNodes.Add( pFuckinCast );
   }
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline 
void SpatialTreeIter::MarkSubTree(  int   iCurNodeOffset,
                                       tMark iMark )
{
  SpatialNode* pSNCastPtr;
   ContiguousBinNode< SpatialNode >* pCurNode = (mpRootNode+iCurNodeOffset);
   int StopCondition = iCurNodeOffset+pCurNode->GetSubTreeSize();
   for( int i=iCurNodeOffset; i<=StopCondition; i++, pCurNode++ )
   {
      if((iMark & msFilterVisible)&&(mNodeMarks[i] & msFilterInvisible))
      {
          //Skip over invisible branches, if we're doing an visible pass
          i+=pCurNode->GetSubTreeSize();
          pCurNode+=pCurNode->GetSubTreeSize();
      }
      else
      {
          mNodeMarks[i] |= iMark;
          pSNCastPtr = &(pCurNode->mData);
          (*mpCurNodeList).Add( pSNCastPtr );
      }
   }
  
 
/*     SpatialNode* pSNCastPtr;
 
    for( int i=mpRootNode->GetSubTreeSize(); i>=iCurNodeOffset; i-- )
    {
        mNodeMarks[i] |= iMark;
        pSNCastPtr = &(this->rIthNode(i));
        mCurNodes.Add(pSNCastPtr);
    }
  */  
/*
   mNodeMarks[iCurNodeOffset] = iMark;
   
   if( (mpRootNode+iCurNodeOffset)->GetSubTreeSize() > 0 )
   {
      int newOffset =  (mpRootNode+iCurNodeOffset)->LChildOffset();
      MarkSubTree( newOffset + iCurNodeOffset, iMark ); 

      newOffset =  (mpRootNode+iCurNodeOffset)->RChildOffset();
      MarkSubTree( newOffset + iCurNodeOffset, iMark ); 
   }
*/
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
void SpatialTreeIter::SetIterFilter( tMark iMark )
{
   mCurMarkFilter = iMark;
}
/////////////////////////////////////////////////////////////////////////////////////
//-------------------------Iteration Navigation------------------------------------//
/////////////////////////////////////////////////////////////////////////////////////
inline  
void SpatialTreeIter::MoveToFirst()
{
   mpCurNode = mpRootNode;
   mCurNodeOffset = 0;

   mCurNodeI = 0;
   mpCurNodeList = &mCurNodes;
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
SpatialNode&   SpatialTreeIter::rCurrent()
{
   return *(*mpCurNodeList)[mCurNodeI];
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
void SpatialTreeIter::MoveToNext(bool ibIncludeVis)
{
    mCurNodeI++;
    if(ibIncludeVis 
        && (mCurNodeI >= (*mpCurNodeList).mUseSize)
        && (mpCurNodeList != &mCurAlwaysVisNodes))
    {
        mpCurNodeList= &mCurAlwaysVisNodes;
        mCurNodeI=0;
    }
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
SpatialNode&   SpatialTreeIter::rMoveToNext(bool ibIncludeVis)
{
   MoveToNext(ibIncludeVis);
   return *(*mpCurNodeList)[mCurNodeI];
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
SpatialNode*   SpatialTreeIter::pMoveToNext(bool ibIncludeVis)
{
   MoveToNext(ibIncludeVis);
   return (*mpCurNodeList)[mCurNodeI];
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
bool SpatialTreeIter::NotDone()
{
    return (mCurNodeI < (*mpCurNodeList).mUseSize);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
inline  
bool SpatialTreeIter::IsCurrentLeaf()
{
    return ((*mpCurNodeList)[mCurNodeI]->mSubDivPlane.mAxis == -1);
}


#endif
