283 lines
7 KiB
C++
283 lines
7 KiB
C++
#include "Stdafx.h"
|
|
#include "SaveCamera.h"
|
|
#include "DumpUtil.h"
|
|
|
|
CSaveCamera::CSaveCamera(void)
|
|
{
|
|
m_pNode = NULL;
|
|
m_pMaxInterface = NULL;
|
|
}
|
|
|
|
CSaveCamera::~CSaveCamera(void)
|
|
{
|
|
}
|
|
|
|
void CSaveCamera::ProcessCamera( FILE *fp, INode *pNode, Interface *pMaxInterface, bool bExportTargetCamera )
|
|
{
|
|
m_pNode = pNode;
|
|
m_pMaxInterface = pMaxInterface;
|
|
|
|
Matrix3 LocalMat;
|
|
TimeValue StartTime;
|
|
AffineParts Affine;
|
|
|
|
StartTime = m_pMaxInterface->GetAnimRange().Start();
|
|
LocalMat = m_pNode->GetNodeTM( StartTime );
|
|
LocalMat.PreRotateX( -90.0f * ( 3.141592654f / 180.0f ) );
|
|
decomp_affine( LocalMat, &Affine );
|
|
|
|
memset( &m_Header, 0, sizeof( SCameraFileHeader ) );
|
|
|
|
m_Header.nType = CT_FREE_CAMERA;
|
|
if( ( m_pNode->GetTarget() ) && ( bExportTargetCamera ) )
|
|
{
|
|
m_Header.nType = CT_TARGET_CAMERA;
|
|
}
|
|
strcpy( m_Header.szHeaderString, CAMERA_FILE_STRING );
|
|
m_Header.nVersion = CAMERA_FILE_VERSION;
|
|
m_Header.nFrame = m_pMaxInterface->GetAnimRange().End() / GetTicksPerFrame() - m_pMaxInterface->GetAnimRange().Start() / GetTicksPerFrame() + 1;
|
|
|
|
int nStrlen;
|
|
|
|
nStrlen = strlen( pNode->GetName() );
|
|
if( nStrlen >= 32 )
|
|
{
|
|
memcpy( m_Header.szCameraName, pNode->GetName(), 31 );
|
|
m_Header.szCameraName[ 31 ] = 0;
|
|
}
|
|
else
|
|
{
|
|
strcpy( m_Header.szCameraName, pNode->GetName() );
|
|
}
|
|
|
|
m_Header.vDefaultPosition.x = Affine.t.x;
|
|
m_Header.vDefaultPosition.y = Affine.t.z;
|
|
m_Header.vDefaultPosition.z = Affine.t.y;
|
|
|
|
m_Header.qDefaultRotation.x = Affine.q.x;
|
|
m_Header.qDefaultRotation.y = Affine.q.z;
|
|
m_Header.qDefaultRotation.z = Affine.q.y;
|
|
m_Header.qDefaultRotation.w = Affine.q.w;
|
|
|
|
if( m_Header.nType == CT_TARGET_CAMERA )
|
|
{
|
|
LocalMat = m_pNode->GetTarget()->GetNodeTM( StartTime );
|
|
LocalMat.PreRotateX( -90.0f * ( 3.141592654f / 180.0f ) );
|
|
decomp_affine( LocalMat, &Affine );
|
|
|
|
m_Header.vDefaultPosition.x = m_Header.vDefaultPosition.x - Affine.t.x;
|
|
m_Header.vDefaultPosition.y = m_Header.vDefaultPosition.y - Affine.t.z;
|
|
m_Header.vDefaultPosition.z = m_Header.vDefaultPosition.z - Affine.t.y;
|
|
}
|
|
|
|
GetAniData();
|
|
WriteCameraInfo( fp );
|
|
}
|
|
|
|
void CSaveCamera::GetAniData()
|
|
{
|
|
DumpFOVSample();
|
|
DumpPosSample( m_pNode, m_vecPosition );
|
|
DumpRotSample();
|
|
}
|
|
|
|
void CSaveCamera::DumpFOVSample()
|
|
{
|
|
int i, j;
|
|
int nStart, nEnd;
|
|
GenCamera *pObject;
|
|
SCameraFOVKey FOVKey;
|
|
float fFOVRatio;
|
|
std::vector< SCameraFOVKey > vecFOV;
|
|
|
|
pObject = ( GenCamera * )m_pNode->EvalWorldState( 0 ).obj;
|
|
if( pObject->GetFOVType() == FOV_W )
|
|
{
|
|
fFOVRatio = m_pMaxInterface->GetRendImageAspect();
|
|
}
|
|
else
|
|
{
|
|
fFOVRatio = 1.0f;
|
|
}
|
|
|
|
nStart = m_pMaxInterface->GetAnimRange().Start() / GetTicksPerFrame();
|
|
nEnd = m_pMaxInterface->GetAnimRange().End() / GetTicksPerFrame();
|
|
nEnd++;
|
|
|
|
m_Header.fDefaultFOV = pObject->GetFOV( m_pMaxInterface->GetAnimRange().Start() ) / fFOVRatio;
|
|
for( i = nStart; i < nEnd; i++ )
|
|
{
|
|
FOVKey.nTime = i - nStart;
|
|
FOVKey.fFOV = pObject->GetFOV( i * GetTicksPerFrame() ) / fFOVRatio;
|
|
vecFOV.push_back( FOVKey );
|
|
}
|
|
|
|
m_vecFOV.push_back( vecFOV[ 0 ] );
|
|
for( i = 0; i < ( int )vecFOV.size() - 2; i++ )
|
|
{
|
|
bool bIsInterpolate = true;
|
|
for( j = i + 2; j < ( int )vecFOV.size(); j++ )
|
|
{
|
|
float fCalcFOV, fWeight;
|
|
|
|
fWeight = ( j - i - 1 ) / ( float )( j - i );
|
|
fCalcFOV = vecFOV[ i ].fFOV * ( 1.0f - fWeight ) + vecFOV[ j ].fFOV * fWeight;
|
|
if( fabs( vecFOV[ j ].fFOV - fCalcFOV ) > 0.0001f )
|
|
{
|
|
bIsInterpolate = false;
|
|
break;
|
|
}
|
|
}
|
|
if( bIsInterpolate )
|
|
{
|
|
m_vecFOV.push_back( vecFOV[ vecFOV.size() - 1 ] );
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
m_vecFOV.push_back( vecFOV[ j - 1 ] );
|
|
i += j - i - 2;
|
|
}
|
|
}
|
|
/*if( m_vecFOV.size() == 2 )
|
|
{
|
|
if( m_vecFOV[ 0 ].fFOV == m_vecFOV[ 1 ].fFOV )
|
|
{
|
|
if( m_vecFOV[ 0 ].fFOV == m_Header.fDefaultFOV )
|
|
{
|
|
m_vecFOV.clear();
|
|
}
|
|
}
|
|
}*/
|
|
}
|
|
|
|
void CSaveCamera::DumpPosSample( INode *pNode, std::vector< SCameraPositionKey > &vecTargetPosition )
|
|
{
|
|
int i, j;
|
|
int nStart, nEnd;
|
|
GenCamera *pObject;
|
|
SCameraPositionKey PosKey;
|
|
std::vector< SCameraPositionKey > vecPos;
|
|
|
|
pObject = ( GenCamera * )pNode->EvalWorldState( 0 ).obj;
|
|
|
|
nStart = m_pMaxInterface->GetAnimRange().Start() / GetTicksPerFrame();
|
|
nEnd = m_pMaxInterface->GetAnimRange().End() / GetTicksPerFrame();
|
|
nEnd++;
|
|
|
|
for( i = nStart; i < nEnd; i++ )
|
|
{
|
|
Matrix3 LocalMat;
|
|
AffineParts Affine;
|
|
|
|
LocalMat = pNode->GetNodeTM( i * GetTicksPerFrame() );
|
|
LocalMat.PreRotateX( -90.0f * ( 3.141592654f / 180.0f ) );
|
|
|
|
decomp_affine( LocalMat, &Affine );
|
|
|
|
PosKey.nTime = i - nStart;
|
|
PosKey.Position = Affine.t;
|
|
if( m_Header.nType == CT_TARGET_CAMERA )
|
|
{
|
|
LocalMat = pNode->GetTarget()->GetNodeTM( i * GetTicksPerFrame() );
|
|
LocalMat.PreRotateX( -90.0f * ( 3.141592654f / 180.0f ) );
|
|
decomp_affine( LocalMat, &Affine );
|
|
PosKey.Position = PosKey.Position - Affine.t;
|
|
}
|
|
vecPos.push_back( PosKey );
|
|
}
|
|
|
|
vecTargetPosition.push_back( vecPos[ 0 ] );
|
|
for( i = 0; i < ( int )vecPos.size() - 2; i++ )
|
|
{
|
|
bool bIsInterpolate = true;
|
|
for( j = i + 2; j < ( int )vecPos.size(); j++ )
|
|
{
|
|
Point3 CalcPos, PosDiff;
|
|
float fWeight;
|
|
|
|
fWeight = ( j - i - 1 ) / ( float )( j - i );
|
|
CalcPos = vecPos[ i ].Position * ( 1.0f - fWeight ) + vecPos[ j ].Position * fWeight;
|
|
PosDiff = vecPos[ j ].Position - CalcPos;
|
|
if( PosDiff.Length() > 0.01f )
|
|
{
|
|
bIsInterpolate = false;
|
|
break;
|
|
}
|
|
}
|
|
if( bIsInterpolate )
|
|
{
|
|
vecTargetPosition.push_back( vecPos[ vecPos.size() - 1 ] );
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
vecTargetPosition.push_back( vecPos[ j - 1 ] );
|
|
i += j - i - 2;
|
|
}
|
|
}
|
|
if( vecTargetPosition.size() == 2 )
|
|
{
|
|
if( vecTargetPosition[ 0 ].Position == vecTargetPosition[ 1 ].Position )
|
|
{
|
|
if( vecTargetPosition[ 0 ].Position == m_Header.vDefaultPosition )
|
|
{
|
|
vecTargetPosition.clear();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CSaveCamera::DumpRotSample()
|
|
{
|
|
int i;
|
|
int nStart, nEnd;
|
|
GenCamera *pObject;
|
|
SCameraRotationKey RotKey;
|
|
std::vector< SCameraRotationKey > vecRot;
|
|
|
|
pObject = ( GenCamera * )m_pNode->EvalWorldState( 0 ).obj;
|
|
|
|
nStart = m_pMaxInterface->GetAnimRange().Start() / GetTicksPerFrame();
|
|
nEnd = m_pMaxInterface->GetAnimRange().End() / GetTicksPerFrame();
|
|
nEnd++;
|
|
|
|
for( i = nStart; i < nEnd; i++ )
|
|
{
|
|
Matrix3 LocalMat;
|
|
AffineParts Affine;
|
|
|
|
LocalMat = m_pNode->GetNodeTM( i * GetTicksPerFrame() );
|
|
LocalMat.PreRotateX( -90.0f * ( 3.141592654f / 180.0f ) );
|
|
decomp_affine( LocalMat, &Affine );
|
|
|
|
RotKey.nTime = i - nStart;
|
|
RotKey.Rotation = Affine.q;
|
|
m_vecRotation.push_back( RotKey );
|
|
}
|
|
}
|
|
|
|
void CSaveCamera::WriteCameraInfo( FILE *fp )
|
|
{
|
|
int i;
|
|
|
|
m_Header.nFOVKeyCount = ( int )m_vecFOV.size();
|
|
m_Header.nPositionKeyCount = ( int )m_vecPosition.size();
|
|
m_Header.nRotationKeyCount = ( int )m_vecRotation.size();
|
|
|
|
fwrite( &m_Header, sizeof( SCameraFileHeader ), 1, fp );
|
|
for( i = 0; i < m_Header.nFOVKeyCount; i++ )
|
|
{
|
|
fwrite( &m_vecFOV[ i ], sizeof( SCameraFOVKey ), 1, fp );
|
|
}
|
|
for( i = 0; i < m_Header.nPositionKeyCount; i++ )
|
|
{
|
|
fwrite( &m_vecPosition[ i ].nTime, sizeof( int ), 1, fp );
|
|
DumpPoint3( fp, m_vecPosition[ i ].Position );
|
|
}
|
|
for( i = 0; i < m_Header.nRotationKeyCount; i++ )
|
|
{
|
|
fwrite( &m_vecRotation[ i ].nTime, sizeof( int ), 1, fp );
|
|
DumpQuat( fp, m_vecRotation[ i ].Rotation );
|
|
}
|
|
}
|