⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mgccamera.cpp

📁 《3D游戏引擎设计》的源码
💻 CPP
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// RESTRICTED USE SOURCE CODE
// http://www.magic-software.com/License/restricted.pdf

#include "MgcBound.h"
#include "MgcCamera.h"
#include "MgcRTLib.h"

MgcImplementRTTI(MgcCamera,MgcObject);
MgcImplementStream(MgcCamera);

//---------------------------------------------------------------------------
MgcCamera::MgcCamera ()
    :
    m_kLocation(MgcVector3::ZERO),
    m_kLeft(MgcVector3::UNIT_X),
    m_kUp(MgcVector3::UNIT_Y),
    m_kDirection(MgcVector3::UNIT_Z)
{
    m_fFrustumN = 1.0;
    m_fFrustumF = 2.0;
    m_fFrustumL = -0.5;
    m_fFrustumR = 0.5;
    m_fFrustumT = 0.5;
    m_fFrustumB = -0.5;
    m_fPortL = 0.0;
    m_fPortR = 1.0;
    m_fPortT = 1.0;
    m_fPortB = 0.0;
    m_uiPlaneState = (unsigned int)(~0);  // all planes initially active

    OnFrustumChange();
    OnViewPortChange();
    OnFrameChange();
}
//---------------------------------------------------------------------------
void MgcCamera::SetFrustum (MgcReal fNear, MgcReal fFar, MgcReal fLeft,
    MgcReal fRight, MgcReal fTop, MgcReal fBottom)
{
    m_fFrustumN = fNear;
    m_fFrustumF = fFar;
    m_fFrustumL = fLeft;
    m_fFrustumR = fRight;
    m_fFrustumT = fTop;
    m_fFrustumB = fBottom;
    OnFrustumChange();
}
//---------------------------------------------------------------------------
void MgcCamera::SetFrustumNear (MgcReal fNear)
{
    m_fFrustumN = fNear;
    OnFrustumChange();
}
//---------------------------------------------------------------------------
void MgcCamera::SetFrustumFar (MgcReal fFar)
{
    m_fFrustumF = fFar;
    OnFrustumChange();
}
//---------------------------------------------------------------------------
void MgcCamera::GetFrustum (MgcReal& rfNear, MgcReal& rfFar,
    MgcReal& rfLeft, MgcReal& rfRight, MgcReal& rfTop,
    MgcReal& rfBottom) const
{
    rfNear = m_fFrustumN;
    rfFar = m_fFrustumF;
    rfLeft = m_fFrustumL;
    rfRight = m_fFrustumR;
    rfTop = m_fFrustumT;
    rfBottom = m_fFrustumB;
}
//---------------------------------------------------------------------------
MgcReal MgcCamera::GetMaxCosSqrFrustumAngle () const
{
    // Compute (cos(A))^2 where A is the largest angle between the frustum
    // axis direction D and the four edges of the frustum that lie along the
    // rays from the frustum origin.

    MgcReal fNSqr = m_fFrustumN*m_fFrustumN;

    MgcReal fDenom = fNSqr;
    if ( MgcMath::Abs(m_fFrustumL) >= MgcMath::Abs(m_fFrustumR) )
    {
        fDenom += m_fFrustumL*m_fFrustumL;
        if ( MgcMath::Abs(m_fFrustumB) >= MgcMath::Abs(m_fFrustumT) )
            fDenom += m_fFrustumB*m_fFrustumB;
        else
            fDenom += m_fFrustumT*m_fFrustumT;
    }
    else
    {
        fDenom += m_fFrustumR*m_fFrustumR;
        if ( MgcMath::Abs(m_fFrustumB) >= MgcMath::Abs(m_fFrustumT) )
            fDenom += m_fFrustumB*m_fFrustumB;
        else
            fDenom += m_fFrustumT*m_fFrustumT;
    }

    return fNSqr/fDenom;
}
//---------------------------------------------------------------------------
void MgcCamera::SetViewPort (MgcReal fLeft, MgcReal fRight, MgcReal fTop,
    MgcReal fBottom)
{
    m_fPortL = fLeft;
    m_fPortR = fRight;
    m_fPortT = fTop;
    m_fPortB = fBottom;
    OnViewPortChange();
}
//---------------------------------------------------------------------------
void MgcCamera::GetViewPort (MgcReal& rfLeft, MgcReal& rfRight,
    MgcReal& rfTop, MgcReal& rfBottom)
{
    rfLeft = m_fPortL;
    rfRight = m_fPortR;
    rfTop = m_fPortT;
    rfBottom = m_fPortB;
}
//---------------------------------------------------------------------------
void MgcCamera::SetFrame (const MgcVector3& rkLocation,
    const MgcVector3& rkLeft, const MgcVector3& rkUp,
    const MgcVector3& rkDirection)
{
    m_kLocation = rkLocation;
    m_kLeft = rkLeft;
    m_kUp = rkUp;
    m_kDirection = rkDirection;
    OnFrameChange();
}
//---------------------------------------------------------------------------
void MgcCamera::SetFrame (const MgcVector3& rkLocation,
    const MgcMatrix3& rkAxes)
{
    m_kLocation = rkLocation;
    m_kLeft = rkAxes.GetColumn(0);
    m_kUp = rkAxes.GetColumn(1);
    m_kDirection = rkAxes.GetColumn(2);
    OnFrameChange();
}
//---------------------------------------------------------------------------
void MgcCamera::SetLocation (const MgcVector3& rkLocation)
{
    m_kLocation = rkLocation;
    OnFrameChange();
}
//---------------------------------------------------------------------------
void MgcCamera::SetAxes (const MgcVector3& rkLeft, const MgcVector3& rkUp,
    const MgcVector3& rkDirection)
{
    m_kLeft = rkLeft;
    m_kUp = rkUp;
    m_kDirection = rkDirection;
    OnFrameChange();
}
//---------------------------------------------------------------------------
void MgcCamera::SetAxes (const MgcMatrix3& rkAxes)
{
    m_kLeft = rkAxes.GetColumn(0);
    m_kUp = rkAxes.GetColumn(1);
    m_kDirection = rkAxes.GetColumn(2);
    OnFrameChange();
}
//---------------------------------------------------------------------------
void MgcCamera::OnFrustumChange ()
{
    MgcReal fNSqr = m_fFrustumN*m_fFrustumN;
    MgcReal fLSqr = m_fFrustumL*m_fFrustumL;
    MgcReal fRSqr = m_fFrustumR*m_fFrustumR;
    MgcReal fBSqr = m_fFrustumB*m_fFrustumB;
    MgcReal fTSqr = m_fFrustumT*m_fFrustumT;

    MgcReal fInvLength = 1.0/MgcMath::Sqrt(fNSqr + fLSqr);
    m_afCoeffL[0] = m_fFrustumN*fInvLength;
    m_afCoeffL[1] = -m_fFrustumL*fInvLength;

    fInvLength = 1.0/MgcMath::Sqrt(fNSqr + fRSqr);
    m_afCoeffR[0] = -m_fFrustumN*fInvLength;
    m_afCoeffR[1] = m_fFrustumR*fInvLength;

    fInvLength = 1.0/MgcMath::Sqrt(fNSqr + fBSqr);
    m_afCoeffB[0] = m_fFrustumN*fInvLength;
    m_afCoeffB[1] = -m_fFrustumB*fInvLength;

    fInvLength = 1.0/MgcMath::Sqrt(fNSqr + fTSqr);
    m_afCoeffT[0] = -m_fFrustumN*fInvLength;
    m_afCoeffT[1] = m_fFrustumT*fInvLength;
}
//---------------------------------------------------------------------------
void MgcCamera::OnViewPortChange ()
{
}
//---------------------------------------------------------------------------
void MgcCamera::OnFrameChange ()
{
    MgcReal fDdE = m_kDirection.Dot(m_kLocation);
    m_akWorldPlane[PI_NEAR].Normal() = m_kDirection;
    m_akWorldPlane[PI_NEAR].Constant() = fDdE + m_fFrustumN;
    m_akWorldPlane[PI_FAR].Normal() = -m_kDirection;
    m_akWorldPlane[PI_FAR].Constant() = -(fDdE + m_fFrustumF);

    m_akWorldPlane[PI_LEFT].Normal() = m_afCoeffL[0]*m_kLeft +
        m_afCoeffL[1]*m_kDirection;
    m_akWorldPlane[PI_LEFT].Constant() =
        m_kLocation.Dot(m_akWorldPlane[PI_LEFT].Normal());

    m_akWorldPlane[PI_RIGHT].Normal() = m_afCoeffR[0]*m_kLeft +
        m_afCoeffR[1]*m_kDirection;
    m_akWorldPlane[PI_RIGHT].Constant() = 
        m_kLocation.Dot(m_akWorldPlane[PI_RIGHT].Normal());

    m_akWorldPlane[PI_BOTTOM].Normal() = m_afCoeffB[0]*m_kUp +
        m_afCoeffB[1]*m_kDirection;
    m_akWorldPlane[PI_BOTTOM].Constant() = 
        m_kLocation.Dot(m_akWorldPlane[PI_BOTTOM].Normal());

    m_akWorldPlane[PI_TOP].Normal() = m_afCoeffT[0]*m_kUp +
        m_afCoeffT[1]*m_kDirection;
    m_akWorldPlane[PI_TOP].Constant() = 
        m_kLocation.Dot(m_akWorldPlane[PI_TOP].Normal());
}
//---------------------------------------------------------------------------
void MgcCamera::Update ()
{
    OnFrustumChange();
    OnViewPortChange();
    OnFrameChange();
}
//---------------------------------------------------------------------------
bool MgcCamera::Culled (const MgcBound& kWorldBound)
{
    unsigned int uiMask = PBM_NEAR;
    for (unsigned int uiI = 0; uiI < PI_QUANTITY; uiI++, uiMask <<= 1)
    {
        if ( m_uiPlaneState & uiMask )
        {
            MgcPlane::Side eSide = kWorldBound.WhichSide(m_akWorldPlane[uiI]);

            if ( eSide == MgcPlane::NEGATIVE_SIDE )
            {
                // Object is on negative side.  Cull it.
                return true;
            }

            if ( eSide == MgcPlane::POSITIVE_SIDE )
            {
                // Object is on positive side of plane.  There is no need to
                // compare subobjects against this plane, so mark it as
                // inactive.
                m_uiPlaneState &= ~uiMask;
            }
        }
    }

    return false;
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// streaming
//---------------------------------------------------------------------------
MgcObject* MgcCamera::Factory (MgcStream& rkStream)
{
    MgcCamera* pkObject = new MgcCamera;
    MgcStream::Link* pkLink = new MgcStream::Link(pkObject);
    pkObject->Load(rkStream,pkLink);
    return pkObject;
}
//---------------------------------------------------------------------------
void MgcCamera::Load (MgcStream& rkStream, MgcStream::Link* pkLink)
{
    MgcObject::Load(rkStream,pkLink);

    // native data
    MgcStreamRead(rkStream,m_fFrustumN);
    MgcStreamRead(rkStream,m_fFrustumF);
    MgcStreamRead(rkStream,m_fFrustumL);
    MgcStreamRead(rkStream,m_fFrustumR);
    MgcStreamRead(rkStream,m_fFrustumT);
    MgcStreamRead(rkStream,m_fFrustumB);
    MgcStreamRead(rkStream,m_fPortL);
    MgcStreamRead(rkStream,m_fPortR);
    MgcStreamRead(rkStream,m_fPortT);
    MgcStreamRead(rkStream,m_fPortB);
    MgcStreamRead(rkStream,m_kLocation);
    MgcStreamRead(rkStream,m_kLeft);
    MgcStreamRead(rkStream,m_kUp);
    MgcStreamRead(rkStream,m_kDirection);
}
//---------------------------------------------------------------------------
void MgcCamera::Link (MgcStream& rkStream, MgcStream::Link* pkLink)
{
    MgcObject::Link(rkStream,pkLink);
}
//---------------------------------------------------------------------------
bool MgcCamera::Register (MgcStream& rkStream)
{
    return MgcObject::Register(rkStream);
}
//---------------------------------------------------------------------------
void MgcCamera::Save (MgcStream& rkStream)
{
    MgcObject::Save(rkStream);

    // native data
    MgcStreamWrite(rkStream,m_fFrustumN);
    MgcStreamWrite(rkStream,m_fFrustumF);
    MgcStreamWrite(rkStream,m_fFrustumL);
    MgcStreamWrite(rkStream,m_fFrustumR);
    MgcStreamWrite(rkStream,m_fFrustumT);
    MgcStreamWrite(rkStream,m_fFrustumB);
    MgcStreamWrite(rkStream,m_fPortL);
    MgcStreamWrite(rkStream,m_fPortR);
    MgcStreamWrite(rkStream,m_fPortT);
    MgcStreamWrite(rkStream,m_fPortB);
    MgcStreamWrite(rkStream,m_kLocation);
    MgcStreamWrite(rkStream,m_kLeft);
    MgcStreamWrite(rkStream,m_kUp);
    MgcStreamWrite(rkStream,m_kDirection);
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -