📄 camera.cpp
字号:
////////////////////////////////////////////////////////////////////////
//
// Camera.cpp
//
// Copyright (c) 2003 Nokia Mobile Phones Ltd. All rights reserved.
//
////////////////////////////////////////////////////////////////////////
#include "Camera.h"
#include "Face.h"
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
void TCamera::SetFieldOfView(const TReal &aAngle,const TReal &aPixelSize)
{
// Calculate the screen depth that would give us exactly the desired FOV,
// and then round this off to an integer value:
TReal degreesToRadians = 3.141592 / 180.0;
TReal tanHalfAngle;
Math::Tan(tanHalfAngle, (aAngle * 0.5 * degreesToRadians));
TReal idealScreenDepth = aPixelSize / tanHalfAngle;
TInt32 screenDepthAsInt;
Math::Int(screenDepthAsInt, idealScreenDepth);
iScreenDepth = screenDepthAsInt;
// Generate lookup table for perspective transform:
TReal screenDepth = screenDepthAsInt * ratioUnity;
TInt depth;
for ( depth = depthTableSize - 1 ; depth > 0 ; depth-- )
{
TReal depthRatio = screenDepth / ( depth + 0.5 );
TInt32 depthRatioAsInt;
Math::Int(depthRatioAsInt, depthRatio);
if ( depthRatioAsInt > maxRatio )
{
break;
}
iDepthRatio[ depth ] = ( TInt16 )depthRatioAsInt;
}
iMinDepth = depth + 1;
}
////////////////////////////////////////////////////////////////////////
void TCamera::SetBounds
(
TInt aLeftX,
TInt aTopY,
TInt aRightX,
TInt aBottomY,
TInt aCenterX,
TInt aCenterY
)
{
//
// Adjust coords to leave half-pixel safety margin.
// (Note that we are in effect using a fixed-point
// representation with a unity value of 2.)
//
TInt leftX = ( aLeftX << 1 ) + 1;
TInt topY = ( aTopY << 1 ) + 1;
TInt rightX = ( aRightX << 1 ) + 1;
TInt bottomY = ( aBottomY << 1 ) + 1;
TInt screenZ = iScreenDepth << 1;
TInt centerX = aCenterX << 1;
TInt centerY = aCenterY << 1;
// Map center and bounds into screen coords:
iCenterX = aCenterX << Geometry3D::screenCoordUnityLog;
iCenterY = aCenterY << Geometry3D::screenCoordUnityLog;
iLeftX = ( aLeftX << Geometry3D::screenCoordUnityLog ) + Geometry3D::screenCoordBias;
iTopY = ( aTopY << Geometry3D::screenCoordUnityLog ) + Geometry3D::screenCoordBias;
iRightX = ( aRightX << Geometry3D::screenCoordUnityLog ) + Geometry3D::screenCoordBias;
iBottomY = ( aBottomY << Geometry3D::screenCoordUnityLog ) + Geometry3D::screenCoordBias;
// Map screen bounds into space coords:
TInt screenXL = leftX - centerX;
TInt screenXR = rightX - centerX;
TInt screenYT = topY - centerY;
TInt screenYB = bottomY - centerY;
// Take vertices of screen frustrum (in camera space coords):
TVector3 origin( 0, 0, 0 );
TVector3 screenTL(screenXL, screenYT, screenZ);
TVector3 screenTR(screenXR, screenYT, screenZ);
TVector3 screenBR(screenXR, screenYB, screenZ);
TVector3 screenBL(screenXL, screenYB, screenZ);
// Use these vertices to define clipping planes for the view volume:
iClipPlane[Geometry3D::leftBound] = TPlane(origin, screenTL, screenBL);
iClipPlane[Geometry3D::topBound] = TPlane(origin, screenTR, screenTL);
iClipPlane[Geometry3D::rightBound] = TPlane(origin, screenBR, screenTR);
iClipPlane[Geometry3D::bottomBound] = TPlane(origin, screenBL, screenBR);
}
////////////////////////////////////////////////////////////////////////
void TCamera::SetAffine(TAffineTransform &aAffine)
{
iAffine = aAffine;
}
////////////////////////////////////////////////////////////////////////
void TCamera::TransformVerts
(
TInt aNumVerts,
const TVector3 * aSrcVertPtr,
TAffineTransform &aAffine,
TScreenVertex * aDestVertPtr,
TVector3 &aCameraInModelSpace
)
{
// Get affine transform to map model into camera space:
TAffineTransform modelToCameraAff;
modelToCameraAff.MakeCompound(aAffine, iAffine);
// Use this to transform model:
const TVector3 * srcPtr = aSrcVertPtr;
TScreenVertex * destPtr = aDestVertPtr;
for (TInt v = 0 ; v < aNumVerts ; v++)
{
modelToCameraAff.Transform(*srcPtr, destPtr->iSpacePos);
PrepareForScreen(*destPtr, 0);
srcPtr++;
destPtr++;
}
// Find position of camera in model space (for facing tests):
modelToCameraAff.GetInverseVector(aCameraInModelSpace);
}
////////////////////////////////////////////////////////////////////////
void TCamera::ClipAndRender
(
TClipFace &aFaceA,
TClipFace &aFaceB,
TMathLookup &aMath,
TScanConverter &aScanConverter
)
{
TClipFace * validFacePtr = &aFaceA;
TClipFace * invalidFacePtr = &aFaceB;
for ( TInt b = 0 ; b < Geometry3D::numBounds ; b++ )
{
validFacePtr->ClipSelf(*invalidFacePtr, iClipPlane[b], b, *this, aMath);
TClipFace * tempFacePtr = validFacePtr;
validFacePtr = invalidFacePtr;
invalidFacePtr = tempFacePtr;
if ( !validFacePtr->IsDrawable() )
{
return;
}
}
validFacePtr->RenderUnclipped(aScanConverter, aMath);
}
////////////////////////////////////////////////////////////////////////
void TCamera::PrepareForScreen(TScreenVertex &aVertex, TInt aBoundIndex)
{
aVertex.iOutcodes = 0;
for ( TInt b = aBoundIndex ; b < Geometry3D::numBounds ; b++ )
{
if ( iClipPlane[b].PointIsOutside(aVertex.iSpacePos) )
{
aVertex.iOutcodes |= 1 << b;
}
}
if ( aVertex.iOutcodes == 0 )
{
aVertex.iScreenX = iCenterX + PerspectiveTransform(aVertex.iSpacePos.iX, aVertex.iSpacePos.iZ);
aVertex.iScreenY = iCenterY + PerspectiveTransform(aVertex.iSpacePos.iY, aVertex.iSpacePos.iZ);
if ( aVertex.iScreenX < iLeftX )
{
aVertex.iScreenX = iLeftX;
}
else if ( aVertex.iScreenX > iRightX )
{
aVertex.iScreenX = iRightX;
}
if ( aVertex.iScreenY < iTopY )
{
aVertex.iScreenY = iTopY;
}
else if ( aVertex.iScreenY > iBottomY )
{
aVertex.iScreenY = iBottomY;
}
}
}
////////////////////////////////////////////////////////////////////////
TInt TCamera::PerspectiveTransform(TInt &aInput, TInt &aDepth)
{
TInt input = aInput;
TInt depth = aDepth;
TInt shift = resultDownshift;
if ( depth <= 0 )
{
return 0;
}
while ( depth >= depthTableSize )
{
depth >>= 1;
//
// Downshifting input here would discard precision, so instead we will
// fold the operation into the downshifting of the result.
//
shift++;
}
while ( depth < iMinDepth )
{
depth <<= 1;
shift--;
}
TInt ratio = iDepthRatio[ depth ];
TInt result = ( input * ratio ) >> shift;
return result;
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -