TViewPoint

Subclasses: Rviewpoint

 public:
        TViewPoint()    { nLists = 0; };
        ~TViewPoint()   { if (nLists != 0)  Cleanup(); };

        void Setup( int minimumLOD, int maximumLOD, float *fetchRanges );
        virtual void Cleanup( void );

        BOOL IsReady(void)              { return (nLists != 0 ); };

        // Move the viewer and swap blocks as needed
        void    Update( Tpoint *position );

        // Return the Nth feature of the required type from the tile containing the viewpoint
        int             GetTileID( int r, int c );
        BOOL    GetPath( int TileID, int type, int offset, TpathFeature *target );
        BOOL    GetArea( int TileID, int type, int offset, TareaFeature *target );

        // Return the min and max LODs ever useable by this viewpoint
        int             GetMinLOD(void)         { return minLOD; };
        int             GetMaxLOD(void)         { return maxLOD; };

        // Return the highest and lowest terrain elevation within range of this viewpoint
        void    GetAreaFloorAndCeiling( float *floor, float *ceiling );

        // Return the low and high detail levels to be used for drawing the next frame
        int             GetHighLOD(void)        { return highDetail; };
        int             GetLowLOD(void)         { return lowDetail; };

        // Return the largest distance from the viewer a post will ever want to be drawn
        // in world space and level post space
        float   GetMaxRange( void )                     { return maxRange[maxLOD]; };
        float   GetMaxRange( int LOD )          { return maxRange[LOD]; };
        int             GetMaxPostRange( int LOD )      { return blockLists[LOD].GetMaxPostRange(); };

        // Return the maximum distance from the current postion at which all
        // data is owned by the specified LOD list in world space and in level posts
        float   GetAvailableRange( void )                       { return LEVEL_POST_TO_WORLD( blockLists[maxLOD].GetAvailablePostRange(), maxLOD ); };
        float   GetAvailableRange( int LOD )            { return LEVEL_POST_TO_WORLD( blockLists[LOD].GetAvailablePostRange(), LOD ); };
        int             GetAvailablePostRange( int LOD )        { return blockLists[LOD].GetAvailablePostRange(); };

        // Return the distance to the farthest piece of terrain that will be drawn in the next frame
        // (The .65 factor is a magic number that seems to work to account for the fact that
        //  the terrain engine leaves a safty margin of undrawn posts arround the viewpoint).
        float   GetDrawingRange( void )         { return LEVEL_POST_TO_WORLD( blockLists[lowDetail].GetAvailablePostRange(), lowDetail ) * 0.65f; };

        // Return a pointer to the requested post in the given level.
        // The caller of this function must ensure that the post is within
        // the available range.  Also, the post pointer may become invalid
        // after a call to "Update"
        Tpost* GetPost( int levelPostRow, int levelPostCol, int LOD ) {
                return blockLists[LOD].GetPost( levelPostRow, levelPostCol );
        };

        // Return the type of ground under the specified point on the ground
        // (requires terrain data including textures to be loaded at that point,
        //  otherwise, 0 is returned.)
        int             GetGroundType( float x, float y );

        // Return the z value of the terrain at the specified point.  (positive Z down)
        // If the third argument is provided to the exact version, then the normal
        // will also be returned
        float   GetGroundLevelApproximation( float x, float y );
        float   GetGroundLevel( float x, float y, Tpoint *normal=NULL );

        // Return TRUE if the given point is on or under the terrain
        BOOL    UnderGround( Tpoint *position );

        // Return TRUE if the two specified points can see each other over the terrain
        BOOL    LineOfSight( Tpoint *p1, Tpoint *p2 );

        // Find the intersection with the terrain (return FALSE if there isn't one)
        BOOL    GroundIntersection( Tpoint *dir, Tpoint *intersection );
 

        // Get the position and orientation matrix for this viewpoint
        float   X( void )       { return pos.x; };
        float   Y( void )       { return pos.y; };
        float   Z( void )       { return pos.z; };

        void    GetPos( Tpoint *p )             { *p = pos; };

  private:
        // Line of Sight helpers
        BOOL SingleLODLineOfSight( int Px, int Py, int Qx, int Qy, float z, float dz, int LOD );
        BOOL TestVertex(int row, int col, float z, int LOD);
        BOOL TestEast(  int row, int col, float z, int LOD);
        BOOL TestNorth( int row, int col, float z, int LOD);
        BOOL TestWest(  int row, int col, float z, int LOD);
        BOOL TestSouth( int row, int col, float z, int LOD);

        // Ground Intersection helpers
        BOOL horizontalEdgeTest( int row, int col, float x, float y, float z, int LOD );
        BOOL verticalEdgeTest(   int row, int col, float x, float y, float z, int LOD );
        void LineSquareIntersection( int row, int col, Tpoint *dir, Tpoint *intersection, int LOD );
 

  protected:
        // Last reported world space location of the viewer (X north, Y east, Z down)
        Tpoint          pos;

        // Range sorted lists of pointers to data blocks at each map level
        // (level 0 is highest level of detail)
        int                                     nLists;
        TBlockList                      *blockLists;
        CRITICAL_SECTION        cs_update;
 

        // The farest into the distance this viewer should ever see (in world space)
        float   *maxRange;

        // The lowest and highest detail levels ever to be used by this viewpoint
        int             minLOD;
        int             maxLOD;

        // The lowest and highest detail levels currently turned on for drawing
        int             highDetail;             // 0 <= highDetail <= lowDetail
        int             lowDetail;              // higheDetail <= lowDetail <= nLevels-1;