📄 mgccamera.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 + -