/*****************************************************************************
 * $LastChangedDate: 2011-08-20 12:07:38 -0400 (Sat, 20 Aug 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Viewpoint class (out-the-window).
 *//*
 * LEGAL:   COPYRIGHT (C) 2008 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#define VIEW_OTW_VIEWPOINT_CC 1
#include "base/module.hh"
using namespace base;
#include "math/module.hh"
#include "math/defs_trig.hh"
#include "math/matrix.hh"
#include "math/matrix_funcs.hh"
using namespace math;
#include "view/module.hh"
#include "view/conf.hh"
#include "view/viewpoint.hh"
#include "view/viewpoint_otw.hh"
#include "view/view.hh"

namespace view {

////////////////////////////////////////////////////////////////////////////////
//////////////////////////////  OtwViewpoint  //////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/*****************************************************************************
 * ctor/dtor.
 *****************************************************************************/
OtwViewpoint::OtwViewpoint( shptr<Observer> observer )
:   mObserver(observer),
    mOtwMode(eOtwMode_OTW_FRONT)
{
CHECK_TYPESIG(observer,TYPESIG_OBSERVER);

    SET_TYPESIG(this,TYPESIG_OTW_VIEWPOINT);
}

OtwViewpoint::~OtwViewpoint()
{
    INVALIDATE_TYPESIG(this,TYPESIG_OTW_VIEWPOINT);
}

/*****************************************************************************
 * Computes view-matrix every frame.
 * A View object is composed with a Viewpoint object.
 *****************************************************************************/
Matrix
OtwViewpoint::ComputeViewMatrix( shptr<View> view )
{
CHECK_TYPESIG(this,TYPESIG_OTW_VIEWPOINT);
CHECK_TYPESIG(view,TYPESIG_VIEW);
CHECK_TYPESIG(mObserver,TYPESIG_OBSERVER);

    // Compute a view matrix by transposing the observer's matrix.
    Matrix m = mObserver->GetObserverMatrix();

    // Mitigate frustum clipping when at low altitudes (carrier deck)
    // by adjusting the position (mOtwViewpointOffset is a raw world coordinate).
    MatrixTranslateLocal( m, YY, VIEW_CONF.mOtwViewpointOffset );

    switch ( mOtwMode )
    {
        case eOtwMode_OTW_FRONT: default:
            // NOP
        break;

        case eOtwMode_OTW_REAR:
        {
            MatrixRotateLocal( m, ZZ, math::RADIAN_180 );
            MatrixRotateLocal( m, YY, math::RADIAN_180 );
            MatrixRotateLocal( m, ZZ, math::RADIAN_180 );
        }
        break;

        case eOtwMode_OTW_LEFT:
        {
            MatrixRotateLocal( m, YY, math::RADIAN_90 );
        }
        break;

        case eOtwMode_OTW_RIGHT:
        {
            MatrixRotateLocal( m, YY, -math::RADIAN_90 );
        }
        break;
    }

    return MatrixInvert( m );
}

/*****************************************************************************
 * Set/get OTW modes.
 *****************************************************************************/
void
OtwViewpoint::SetOtwMode( const eOtwMode otwMode )
{
CHECK_TYPESIG(this,TYPESIG_OTW_VIEWPOINT);

    mOtwMode = otwMode;
}

OtwViewpoint::eOtwMode
OtwViewpoint::GetOtwMode( void )
{
CHECK_TYPESIG(this,TYPESIG_OTW_VIEWPOINT);

    return mOtwMode;
}

/*****************************************************************************
 * Switch the observer.
 * The observer is the source of the viewpoint.
 *****************************************************************************/
void
OtwViewpoint::SetObserver( shptr<Observer> observer )
{
CHECK_TYPESIG(this,TYPESIG_OTW_VIEWPOINT);

    mObserver = observer;
}

} // namespace view
