reman3/Rayman_X/cpa/Appli/CvrtA3DtoA3i/Src/l_a3d_v6.cpp

1716 lines
59 KiB
C++

// **********************************************************************************
// * "l_a3d_v6.c" *
// * Written by : Sébastien Rubens *
// * Tabulations : 4 char *
// **********************************************************************************
#define L_A3D_V6_C
// **********************************************************************************
//#define ShowInfos
//#define WaitGetChar
#define Details
// **********************************************************************************
// Included files
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "SCR.h"
//#include "LRM.h"
#include "specif\\a3x_pref.h"
#include "structur\\anim_s.h"
#include "a3x_glob.h"
#include "makeanim.h"
#include "l_global_v6.h"
#include "l_a3d_v6.h"
#include "l_Tbl_v6.h"
#include "l_chl_v6.h"
#include "a3x_int.h"
#include "a3x_intb.h"
// **********************************************************************************
#define NbChannelAlreadyUsed 1000
#define UNKNOW_CHANNEL 0xFFFE
static unsigned long ulNoInvalid= 1; // 0= undefined to graphic, 1= Undefined to empty
static unsigned short ax_uwChannelAlreadyUsed[NbChannelAlreadyUsed];
static signed long slWaitedStringsTableEntry;
static signed long slWaitedVertexesTableEntry;
static signed long slWaitedQuaternionsTableEntry;
static signed long slWaitedChannelNumber;
static signed long slLastFrame, slCurrentFrame, slHierFrame;
static signed long slWaitedMax;
//static signed long slMaxInChannel; // Max in channel name le to set ChannelNumber value !!!
static unsigned short uwPivotDefined; // Flag
static unsigned short uwOkAnimationFile; // Flag
static unsigned short uwHierDef; // Flag
static unsigned short uwNbReadedKeys;
static tdstBinA3dAnimationGENERAL *p_stGENERAL;
static tdstBinFrame stReadFrame;
typedef char tdString[50];
static tdString ax_tdEventType[]=
{ "SOUND_EVENT", "MECHANIC_EVENT", "GENERATE_EVENT", "GENERIC_EVENT" };
static tdString ax_tdMechanicType[]=
{ "NoAction", "TurnUp", "TurnDown", "TurnLeft",
"TurnRight", "TurnAbsolute", "Jump", "JumpAbsolute",
"JumpWithoutAddingSpeed", "Accelerate", "Pulse", "Brake",
"GoRelative", "GoAbsolute", "Start", "Continue",
"TrackingDirection", "ActionOnCamera", "TurnAbsoluteInProgress", "GoTarget",
"GoInDirection", "Fire", "ReachTarget", "TurnAround",
"BePushed"
};
// **********************************************************************************
// HEADER CALLBACK
// **********************************************************************************
static SCR_tde_Anl_ReturnValue fn_eA3dHEADERCallBackV6i( SCR_tdst_File_Description *_p_stFile,
char *_p_szName,
char *_ap_SzParam[],
SCR_tde_Anl_Action _eAction )
{
// Section already analysed
if (_eAction == SCR_EA_Anl_AlreadyAnalysed)
{ fprintf( ErrorFile, "%s : A3dHEADER already analysed\n", AnimationName );
}
// Beginning of section
if (_eAction == SCR_EA_Anl_BeginSection)
{
#ifdef ShowInfos
fn_v_LogSectionBegin( D_BINSCR_LogNew,
"A3dHEADER",
AnimationName );
#endif
// No memory allocation for A3dHEADER
uwNbReadedKeys= 0;
}
// We are in the section
else if (_eAction == SCR_EA_Anl_Entry)
{
// FileType
if ( !stricmp(_p_szName, "FileType") )
{ if ( stricmp(_ap_SzParam[0], "Animations") )
{
fprintf( ErrorFile, "%s : A3dHEADER.FileType is not equal to 'Animations' (%s)\n", AnimationName, _ap_SzParam[0] );
uwOkAnimationFile= 1;
bValid(&stAnims[uwAnalysedAnim]) = 1;
}
else
{ uwOkAnimationFile= 0;
//bValid(&stAnims[uwAnalysedAnim]) = 0;
}
}
// VersionNumber
else if ( (uwOkAnimationFile == 0) && !stricmp(_p_szName, "VersionNumber") )
{ if ( atoi(_ap_SzParam[0]) != 6 ) {
uwOkAnimationFile= 1;
bValid(&stAnims[uwAnalysedAnim]) = 1;
printf("\nAnimation dans l'ancien format (%s) \n", AnimationName );
fprintf( ErrorFile, "\nAnimation dans l'ancien format (%s) \n", AnimationName );
}
else {
uwOkAnimationFile= 0;
//bValid(&stAnims[uwAnalysedAnim]) = 0;
}
}
// Unknown field
else if (uwOkAnimationFile == 0)
{ fprintf( ErrorFile, "%s : Unknown field in A3d file, A3dHEADER (%s)\n", AnimationName, _ap_SzParam[0] );
}
}
// End of section
else if (_eAction == SCR_EA_Anl_EndSection)
{
#ifdef ShowInfos
fn_v_LogSectionEnd();
#endif
}
return SCR_ERV_Anl_NormalReturn;
}
// **********************************************************************************
// STRING TABLE CALLBACK
// **********************************************************************************
SCR_tde_Anl_ReturnValue fn_eA3dStringsTableCallBackV6i( SCR_tdst_File_Description *_p_stFile,
char *_p_szName,
char *_ap_SzParam[],
SCR_tde_Anl_Action _eAction )
{
// Section already analysed
if (_eAction == SCR_EA_Anl_AlreadyAnalysed)
{ if (uwOkAnimationFile == 0)
{ fprintf( ErrorFile, "%s : A3dStringsTable already analysed\n", AnimationName );
}
}
// Beginning of section
if (_eAction == SCR_EA_Anl_BeginSection)
{
if (uwOkAnimationFile == 0)
{
#ifdef ShowInfos
fn_v_LogSectionBegin( D_BINSCR_LogNew,
"A3dStringsTable",
AnimationName );
#endif
//p_szName contains NumberOfStrings and _ap_SzParam[0] contains nothing ( (nothing) )
//Allocate memory for StringsTable
slWaitedMax= (signed long) atoi(_p_szName);
fn_v_AllocateOnStack( eStackBinStrings, slWaitedMax );
slWaitedStringsTableEntry= 0L;
}
}
// We are in the section
else if (_eAction == SCR_EA_Anl_Entry)
{
if (uwOkAnimationFile == 0)
{
// Add
if ( !stricmp(_p_szName, "Add") )
{
if ( slWaitedStringsTableEntry == ReadSLong(0) )
strcpy( &ax_xStrings[M_GetStackAlloc(eStackBinStrings)+slWaitedStringsTableEntry][0], _ap_SzParam[1] );
else
fprintf( ErrorFile, "%s : Wrong (first) parameter in A3dStringsTable (%s)\n", AnimationName, _ap_SzParam[0] );
slWaitedStringsTableEntry++;
}
// Unknown field
else
{ fprintf( ErrorFile, "%s : Unknown field in A3d file, A3dStringsTable (%s)\n", AnimationName, _p_szName );
}
}
}
// End of section
else if (_eAction == SCR_EA_Anl_EndSection)
{
if (uwOkAnimationFile == 0)
{
if ( slWaitedStringsTableEntry != slWaitedMax )
fprintf(WarningFile, "%s : Not enough entries in StringsTable (%d)\n", AnimationName, slWaitedStringsTableEntry );
#ifdef ShowInfos
fn_v_LogSectionEnd();
#endif
}
}
return SCR_ERV_Anl_NormalReturn;
}
// **********************************************************************************
// VERTEX TABLE CALLBACK
// **********************************************************************************
SCR_tde_Anl_ReturnValue fn_eA3dVertexesTableCallBackV6i( SCR_tdst_File_Description *_p_stFile,
char *_p_szName,
char *_ap_SzParam[],
SCR_tde_Anl_Action _eAction )
{ signed long slInd;
SEB_xReal *p_stVector;
// Section already analysed
if (_eAction == SCR_EA_Anl_AlreadyAnalysed)
{ if (uwOkAnimationFile == 0)
{ fprintf( ErrorFile, "%s : A3dVertexesTable already analysed\n", AnimationName );
}
}
// Beginning of section
if (_eAction == SCR_EA_Anl_BeginSection)
{
if (uwOkAnimationFile == 0)
{
#ifdef ShowInfos
fn_v_LogSectionBegin( D_BINSCR_LogNew,
"A3dVertexesTable",
AnimationName );
#endif
//Allocate memory for VertexesTable
slWaitedMax= (signed long) atoi(_p_szName);
fn_v_AllocateOnStack( eStackBinVertexes, slWaitedMax );
slWaitedVertexesTableEntry= 0;
}
}
// We are in the section
else if (_eAction == SCR_EA_Anl_Entry)
{
if (uwOkAnimationFile == 0)
{
// Add
if ( !stricmp(_p_szName, "Add") )
{
if ( slWaitedVertexesTableEntry == ReadSLong(0) )
{ slInd= M_GetStackAlloc(eStackBinVertexes) + slWaitedVertexesTableEntry;
p_stVector= &axa3_xVertexes[slInd][0];
p_stVector[0]= ReadDouble(1);
p_stVector[1]= ReadDouble(2);
p_stVector[2]= ReadDouble(3);
slWaitedVertexesTableEntry++;
}
else
{ fprintf( ErrorFile, "%s : Wrong (first) parameter in A3dStringsTable (%s)\n", AnimationName, _ap_SzParam[0] );
}
}
// Unknown field
else
{ fprintf( ErrorFile, "%s : Unknown field in A3d file, A3dVertexesTable (%s)\n", AnimationName, _p_szName );
}
}
}
// End of section
else if (_eAction == SCR_EA_Anl_EndSection)
{
if (uwOkAnimationFile == 0)
{
if ( slWaitedVertexesTableEntry != slWaitedMax )
fprintf( ErrorFile, "%s : Not enough entries in VertexesTable (%d)\n", AnimationName, slWaitedVertexesTableEntry );
#ifdef ShowInfos
fn_v_LogSectionEnd();
#endif
}
}
return SCR_ERV_Anl_NormalReturn;
}
// **********************************************************************************
// QUATERNIONS TABLE CALLBACK
// **********************************************************************************
SCR_tde_Anl_ReturnValue fn_eA3dQuaternionsTableCallBackV6i( SCR_tdst_File_Description *_p_stFile,
char *_p_szName,
char *_ap_SzParam[],
SCR_tde_Anl_Action _eAction )
{ signed long slInd;
SEB_xReal *p_stQuater;
// Section already analysed
if (_eAction == SCR_EA_Anl_AlreadyAnalysed)
{ if (uwOkAnimationFile == 0)
{ fprintf( ErrorFile, "%s : A3dQuaternionsTable already analysed\n", AnimationName );
}
}
// Beginning of section
if (_eAction == SCR_EA_Anl_BeginSection)
{ if (uwOkAnimationFile == 0)
{
#ifdef ShowInfos
fn_v_LogSectionBegin( D_BINSCR_LogNew,
"A3dQuaternionsTable",
AnimationName );
#endif
//Allocate memory for QuaternionsTable
slWaitedMax= atoi(_p_szName);
fn_v_AllocateOnStack( eStackBinQuaternions, slWaitedMax );
slWaitedQuaternionsTableEntry= 0L;
}
}
// We are in the section
else if (_eAction == SCR_EA_Anl_Entry)
{ if (uwOkAnimationFile == 0)
{
// Add
if ( !stricmp(_p_szName, "Add") )
{
if ( slWaitedQuaternionsTableEntry == ReadSLong(0) )
{ slInd= M_GetStackAlloc(eStackBinQuaternions) + slWaitedQuaternionsTableEntry;
p_stQuater= &axa4_xBinQuaternions[slInd][0];
p_stQuater[0]= ReadDouble(1);
p_stQuater[1]= ReadDouble(2);
p_stQuater[2]= ReadDouble(3);
p_stQuater[3]= ReadDouble(4);
slWaitedQuaternionsTableEntry++;
}
else
{ fprintf( ErrorFile, "%s : Wrong (first) parameter in A3dStringsTable (%s)\n", AnimationName, _ap_SzParam[0] );
}
}
// Unknown field
else
{ fprintf( ErrorFile, "%s : Unknown field in A3d file, A3dQuaternionsTable (%s)\n", AnimationName, _p_szName );
}
}
}
// End of section
else if (_eAction == SCR_EA_Anl_EndSection)
{
if (uwOkAnimationFile == 0)
{
if ( slWaitedQuaternionsTableEntry != slWaitedMax )
fprintf( ErrorFile, "%s : Not enough entries in QuaternionsTable (%d)\n", AnimationName, slWaitedQuaternionsTableEntry );
#ifdef ShowInfos
fn_v_LogSectionEnd();
#endif
}
}
return SCR_ERV_Anl_NormalReturn;
}
// **********************************************************************************
// ANIMATION GENERAL CALLBACK
// **********************************************************************************
// Modif 17/08/98 : New Key CameraAngle(do nothing) - Carlos Torres
// Modif 27/08/98 : Supress Morph allocation - Carlos Torres
SCR_tde_Anl_ReturnValue fn_eA3dAnimationGENERALCallBackV6i( SCR_tdst_File_Description *_p_stFile,
char *_p_szName,
char *_ap_SzParam[],
SCR_tde_Anl_Action _eAction )
{
// Section already analysed
if (_eAction == SCR_EA_Anl_AlreadyAnalysed)
{
if (uwOkAnimationFile == 0)
{
fprintf( ErrorFile, "%s : A3dAnimationGENERAL already analysed\n", AnimationName );
}
}
// Beginning of section
else if (_eAction == SCR_EA_Anl_BeginSection)
{
if (uwOkAnimationFile == 0)
{
#ifdef ShowInfos
fn_v_LogSectionBegin( D_BINSCR_LogNew,
"A3dAnimationGENERAL",
AnimationName );
#endif
// Set pointer on A3dAnimationGENERAL structure
p_stGENERAL= &ax_tdstA3dGENERAL[M_GetStackAlloc(eStackBinA3dGENERAL)];
p_stGENERAL->uwNumberOfFrames= 0;
p_stGENERAL->uwNumberOfChannels= 0;
p_stGENERAL->uwNumberOfVectors= (unsigned short) (M_GetStackPos(eStackBinVertexes) - M_GetStackAlloc(eStackBinVertexes));
p_stGENERAL->uwNumberOfQuaternions= (unsigned short) (M_GetStackPos(eStackBinQuaternions) - M_GetStackAlloc(eStackBinQuaternions));
p_stGENERAL->uwNumberOfHierarchies= 0;
p_stGENERAL->uwNumberOfEvents= 0;
p_stGENERAL->uwNumberOfMorphData= 0;
p_stGENERAL->slNumOfHierarchies= M_GetStackPos(eStackBinHierarchies);
p_stGENERAL->slNumOfVectors= M_GetStackPos(eStackBinVertexes);
p_stGENERAL->slNumOfQuaternions= M_GetStackPos(eStackBinQuaternions);
p_stGENERAL->slNumOfEvents= M_GetStackPos(eStackBinEvent);
p_stGENERAL->slNumOfMorphData= M_GetStackPos(eStackBinMorphInformation);
{ unsigned long ulCnt;
for ( ulCnt=0 ; ulCnt<NbChannelAlreadyUsed ; ulCnt++ )
ax_uwChannelAlreadyUsed[ulCnt]= 0;
}
}
}
// We are in the section
else if (_eAction == SCR_EA_Anl_Entry)
{
if (uwOkAnimationFile == 0)
{
// Actor
if ( !stricmp(_p_szName, "Actor") )
{ // Not used
// String : Actor's name
}
// NumberOfChannels
else if ( !stricmp(_p_szName, "NumberOfChannels") )
{ // Integer
p_stGENERAL->uwNumberOfChannels= ReadUShort(0);
}
// NumberOfFrames
else if ( !stricmp(_p_szName, "NumberOfFrames") )
{ // Integer
p_stGENERAL->uwNumberOfFrames= ReadUShort(0);
}
// CurrentFrame
else if ( !stricmp(_p_szName, "CurrentFrame") )
{ // Integer
// Not used -------
}
// AnimationTranslationOffset
else if ( !stricmp(_p_szName, "AnimationTranslationOffset") )
{ // Unpacked Vector
fn_v_CopyVect( p_stGENERAL->uwAnimationTranslationOffset,
axa3_xVertexes[M_GetStackAlloc(eStackBinVertexes) + ReadUShort(0)] );
}
// AnimationRotationOffset
else if ( !stricmp(_p_szName, "AnimationRotationOffset") )
{ // Packed quaternion
fn_v_CopyQuat( p_stGENERAL->uwAnimationRotationOffset,
axa4_xBinQuaternions[M_GetStackAlloc(eStackBinQuaternions) + ReadUShort(0)] );
}
// AnimReferenceChannel
else if ( !stricmp(_p_szName, "AnimReferenceChannel") )
{ // Integer
// Not used -------
}
// AnimationSpeed
else if ( !stricmp(_p_szName, "AnimationSpeed") )
{ // Integer
p_stGENERAL->uwAnimationSpeed= ReadUShort(0);
}
// CameraAngle
else if ( !stricmp(_p_szName, "CameraAngle") )
{ // ???
// Used by Rayman TV !!!
}
// Unknown field
else
{ fprintf( ErrorFile, "%s : Unknown field in A3d, AnimationGENERAL (%s)\n", AnimationName, _p_szName );
}
}
}
// End of section
else if (_eAction == SCR_EA_Anl_EndSection)
{
if (uwOkAnimationFile == 0)
{ signed long slCnt;
// Set pointer on A3dAnimationGENERAL structure
p_stGENERAL= &ax_tdstA3dGENERAL[M_GetStackAlloc(eStackBinA3dGENERAL)];
p_stGENERAL->uwStartFrame= 0;
p_stGENERAL->uwEndFrame= 0;
p_stGENERAL->uwFlags= 0;
p_stGENERAL->uwFakeAnimSpeed= p_stGENERAL->uwAnimationSpeed;
// Allocate memory for all Channels structures
fn_v_AllocateOnStack( eStackBinChannels, p_stGENERAL->uwNumberOfChannels );
p_stGENERAL->slNumOfChannels= M_GetStackAlloc(eStackBinChannels);
// Allocate memory for all OnlyFrame structures
fn_v_AllocateOnStack( eStackBinOnlyFrames, p_stGENERAL->uwNumberOfFrames );
p_stGENERAL->slNumOfOnlyFrames= M_GetStackAlloc(eStackBinOnlyFrames);
for ( slCnt=0 ; slCnt<p_stGENERAL->uwNumberOfFrames ; slCnt++ )
{ fn_v_SetIdQuater( ax_tdstOnlyFrames[p_stGENERAL->slNumOfOnlyFrames + slCnt].tdxAngularSpeedQuat );
fn_v_SetZeroVector( ax_tdstOnlyFrames[p_stGENERAL->slNumOfOnlyFrames + slCnt].tdxSpeedVector );
ax_tdstOnlyFrames[p_stGENERAL->slNumOfOnlyFrames + slCnt].slNumOfAngularSpeedQuat= 0xFFFFFFFF;
ax_tdstOnlyFrames[p_stGENERAL->slNumOfOnlyFrames + slCnt].slNumOfSpeedVector= 0xFFFFFFFF;
ax_tdstOnlyFrames[p_stGENERAL->slNumOfOnlyFrames + slCnt].uwHierarchyNbCouples= 0;
ax_tdstOnlyFrames[p_stGENERAL->slNumOfOnlyFrames + slCnt].slNumOfHierarchyCouples= p_stGENERAL->slNumOfHierarchies;
}
slWaitedChannelNumber= 0;
#ifdef ShowInfos
fn_v_LogSectionEnd();
#endif
}
}
return SCR_ERV_Anl_NormalReturn;
}
// **********************************************************************************
// CHANNEL CALLBACK
// **********************************************************************************
SCR_tde_Anl_ReturnValue fn_eChannelCallBackV6i( SCR_tdst_File_Description *_p_stFile,
char *_p_szName,
char *_ap_SzParam[],
SCR_tde_Anl_Action _eAction )
{
// Section already analysed
if (_eAction == SCR_EA_Anl_AlreadyAnalysed)
{
if (uwOkAnimationFile == 0)
{
fprintf( ErrorFile, "%s : Channel already analysed (Channel %d)\n", AnimationName, (slWaitedChannelNumber+1) );
}
}
// Beginning of section
else if (_eAction == SCR_EA_Anl_BeginSection)
{
if (uwOkAnimationFile == 0)
{ signed long slCnt, slNumCHL;
#ifdef ShowInfos
fn_v_LogSectionBegin( D_BINSCR_LogNew,
"Channel",
AnimationName );
#endif
// Verify ChannelNumber
if ( slWaitedChannelNumber != (signed long) (atoi(_p_szName)-1) )
fprintf( ErrorFile, "%s : Wrong (waited) Channel Number (%s)\n", AnimationName, _ap_SzParam[0] );
// Allocate memory for Frame structures
fn_v_AllocateOnStack( eStackBinFrames, p_stGENERAL->uwNumberOfFrames );
ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].slNumOfFrames= M_GetStackAlloc(eStackBinFrames);
// Initialize info structure
fn_v_CopyVect( ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].a3_xLocalPivotPos, a3_xVector0 );
uwPivotDefined= 0;
stReadFrame.swNumberInTable= -1;
stReadFrame.uwTypeOfObject= 0;
stReadFrame.uwFrameNumber= 0;
stReadFrame.uwMask= 0x0000;
stReadFrame.uwAttribute= 0;
stReadFrame.uwTypeOfObject= TE_EmptyObject;
stReadFrame.xInterpolationParameter= 0.0;
fn_v_CopyQuat( stReadFrame.a4_xQuatOri, a4_xQuater1 );
fn_v_CopyQuat( stReadFrame.a4_xQuatSca, a4_xQuater1 );
fn_v_CopyVect( stReadFrame.a3_xScaleValues, a3_xVector0 );
fn_v_CopyVect( stReadFrame.a3_xPosition, a3_xVector0 );
stReadFrame.ucTransparency=0xFF;
slNumCHL= ReadUShort(0);
slCnt= 0;
// Channel name search is case sensitive !!!
while ((slCnt < slMaxInChannel) &&
(stricmp(ax_xChannelNames[slCnt],ax_xStrings[M_GetStackAlloc(eStackBinStrings) + slNumCHL])))
slCnt++;
if (slCnt < slMaxInChannel) {
ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].uwChannelNumber= (unsigned short) slCnt;
if (ax_uwChannelAlreadyUsed[slCnt] == 1)
fprintf( ErrorFile, "%s : Channel Name (%s) already used in animation (Channel %d) : possible error !!!\n", AnimationName, ax_xChannelNames[slCnt], (slWaitedChannelNumber+1) );
ax_uwChannelAlreadyUsed[slCnt]= 1;
}
// unknow channel name
else
ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].uwChannelNumber = UNKNOW_CHANNEL;
slLastFrame= 0;
}
}
// We are in the section
else if (_eAction == SCR_EA_Anl_Entry)
{
if (uwOkAnimationFile == 0)
{
if ( !stricmp(_p_szName, "TrajectorySettings") )
{ // Editor datas
}
else if ( !stricmp(_p_szName, "ActiveStatus") )
{ // Editor datas
}
else if ( !stricmp(_p_szName, "IsCamera") )
{ // Editor datas
}
// Unknown field
else fprintf( ErrorFile, "%s : Unknown field in A3d file (%s) (Channel %d)\n", AnimationName, _p_szName, (slWaitedChannelNumber+1) );
}
}
// End of section
else if (_eAction == SCR_EA_Anl_EndSection)
{ if (uwOkAnimationFile == 0)
{ signed long slCnt;
tdxMatrix33 a3a3_xScaleMatrix, a3a3_xMtxSca, a3a3_xMtxOri;
tdxVector3 a3_xTmpVec;
// Invalid unknow channel channel
if (ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].uwChannelNumber == UNKNOW_CHANNEL)
ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].uwChannelNumber = SEB_Invalid;
slWaitedChannelNumber++;
// Set other values
fn_v_QuatToMatrix( a3a3_xMtxSca, stReadFrame.a4_xQuatSca );
fn_v_QuatToMatrix( a3a3_xMtxOri, stReadFrame.a4_xQuatOri );
fn_v_InvRotDiaRot( a3a3_xScaleMatrix, a3a3_xMtxSca, stReadFrame.a3_xScaleValues );
fn_v_MatrixByVector( a3_xTmpVec, a3a3_xScaleMatrix, ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].a3_xLocalPivotPos );
fn_v_MatrixByVector( stReadFrame.a3_xWorldPivotPosition, a3a3_xMtxOri, a3_xTmpVec );
stReadFrame.a3_xWorldPivotPosition[0]+= stReadFrame.a3_xPosition[0];
stReadFrame.a3_xWorldPivotPosition[1]+= stReadFrame.a3_xPosition[1];
stReadFrame.a3_xWorldPivotPosition[2]+= stReadFrame.a3_xPosition[2];
stReadFrame.xDistMaster= fn_x_VectorLength( stReadFrame.a3_xPosition );
stReadFrame.uwFrameNumber= (unsigned short) slCurrentFrame;
// Copy datas to Table
stReadFrame.uwMask= 0x0000;
stReadFrame.uwAttribute= 0;
// On copie les frames jusqu'à la dernière frame
ax_tdstFrames[M_GetStackAlloc(eStackBinFrames) + slLastFrame].uwFrameNumber= (unsigned short) slLastFrame;
for ( slCnt=slLastFrame+1 ; slCnt<p_stGENERAL->uwNumberOfFrames ; slCnt++ )
{ ax_tdstFrames[M_GetStackAlloc(eStackBinFrames) + slCnt]=
ax_tdstFrames[M_GetStackAlloc(eStackBinFrames) + slLastFrame];
ax_tdstFrames[M_GetStackAlloc(eStackBinFrames) + slCnt].uwAttribute= 0x0000;
ax_tdstFrames[M_GetStackAlloc(eStackBinFrames) + slCnt].uwFrameNumber= (unsigned short) slCnt;
}
slLastFrame= slCurrentFrame;
#ifdef ShowInfos
fn_v_LogSectionEnd();
#endif
if (slWaitedChannelNumber == p_stGENERAL->uwNumberOfChannels)
{
if (p_stGENERAL->uwNumberOfFrames > 2)
{
if (uwNbReadedKeys == 0)
fprintf( WarningFile, "%s : this animation is optimized ???\n", AnimationName );
}
}
}
}
return SCR_ERV_Anl_NormalReturn;
}
// **********************************************************************************
// FRAME CALLBACK
// **********************************************************************************
// Modif 27/08/98 : Alloc Morph element and fill new structure - Carlos Torres
SCR_tde_Anl_ReturnValue fn_eFrameCallBackV6i( SCR_tdst_File_Description *_p_stFile,
char *_p_szName,
char *_ap_SzParam[],
SCR_tde_Anl_Action _eAction )
{ static unsigned short uwEventType;
// Section already analysed
if (_eAction == SCR_EA_Anl_AlreadyAnalysed)
{ if (uwOkAnimationFile == 0)
{ fprintf( ErrorFile, "%s : Frame already analysed (Channel %d, Frame %d)\n", AnimationName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
}
// Beginning of section
else if (_eAction == SCR_EA_Anl_BeginSection)
{ if (uwOkAnimationFile == 0)
{
uwEventType= 0;
#ifdef ShowInfos
fn_v_LogSectionBegin( D_BINSCR_LogNew,
"Frame",
AnimationName );
#endif
slCurrentFrame= (atoi(_p_szName) - 1);
stReadFrame.uwFrameNumber= 0;
}
}
// We are in the section
else if (_eAction == SCR_EA_Anl_Entry)
{
if (uwOkAnimationFile == 0)
{
// ObjectType
if ( !stricmp(_p_szName, "ObjectType") )
{ // String : Object type
// No SubAnim
// unsigned short uwTypeOfObject
if (( !stricmp(_ap_SzParam[0], "3dObject"))||( !stricmp(_ap_SzParam[0], "Morphed"))) {
stReadFrame.uwTypeOfObject= TE_GraphicObject;
// check if channel is valid
if (ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].uwChannelNumber == UNKNOW_CHANNEL) {
fprintf(ErrorFile,"%s : Channel Name not found (Channel %d)\n",AnimationName,slWaitedChannelNumber+1);
ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].uwChannelNumber = SEB_Invalid;
}
}
else if ( !stricmp(_ap_SzParam[0], "Light") ) {
stReadFrame.uwTypeOfObject= TE_Light;
fprintf(ErrorFile,"%s : Light Object isn't suported (Channel %d, Frame %d)\n",AnimationName,slWaitedChannelNumber+1,slCurrentFrame+1);
}
else if ( !stricmp(_ap_SzParam[0], "SoundEvent") ) {
stReadFrame.uwTypeOfObject= TE_Event; // Transform to simple event
uwEventType= C_ucSOUND_EVENT;
}
else if ( !stricmp(_ap_SzParam[0], "CameraEvent") ) {
stReadFrame.uwTypeOfObject= TE_Event; // Transform to simple event
fprintf(ErrorFile,"%s : Camera Event isn't suported (Channel %d, Frame %d)\n",AnimationName,slWaitedChannelNumber+1,slCurrentFrame+1);
}
else if ( !stricmp(_ap_SzParam[0], "GenericEvent") ) {
stReadFrame.uwTypeOfObject= TE_Event; // Transform to simple event
uwEventType= C_ucGENERIC_EVENT;
// check if channel is valid
if (ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].uwChannelNumber == UNKNOW_CHANNEL) {
fprintf(ErrorFile,"%s : Channel Name not found (Channel %d)\n",AnimationName,slWaitedChannelNumber+1);
ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].uwChannelNumber = SEB_Invalid;
}
}
else if ( !stricmp(_ap_SzParam[0], "GenerateEvent") ) {
stReadFrame.uwTypeOfObject= TE_Event; // Transform to simple event
uwEventType= C_ucGENERATE_EVENT;
// check if channel is valid
if (ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].uwChannelNumber == UNKNOW_CHANNEL) {
fprintf(ErrorFile,"%s : Channel Name not found (Channel %d)\n",AnimationName,slWaitedChannelNumber+1);
ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].uwChannelNumber = SEB_Invalid;
}
}
else if ( !stricmp(_ap_SzParam[0], "MechanicEvent") ) {
stReadFrame.uwTypeOfObject= TE_Event; // Transform to simple event
uwEventType= C_ucMECHANIC_EVENT;
fprintf(ErrorFile,"%s : Machanic Event isn't supported (Channel %d, Frame %d)\n",AnimationName,slWaitedChannelNumber+1,slCurrentFrame+1);
}
else if ( !stricmp(_ap_SzParam[0], "Fake") ) {
stReadFrame.uwTypeOfObject= TE_Fake;
// check if channel is valid
if (ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].uwChannelNumber == UNKNOW_CHANNEL) {
fprintf(ErrorFile,"%s : Channel Name not found (Channel %d)\n",AnimationName,slWaitedChannelNumber+1);
ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].uwChannelNumber = SEB_Invalid;
}
}
else if ( !stricmp(_ap_SzParam[0], "Empty") ) {
stReadFrame.uwTypeOfObject= TE_EmptyObject;
stReadFrame.swNumberInTable= -1;
}
else if ( !stricmp(_ap_SzParam[0], "Undefined") ) {
stReadFrame.uwTypeOfObject= TE_Undefined;
fprintf(WarningFile,"%s : ObjectType is undefined (Channel %d, Frame %d)\n",AnimationName,slWaitedChannelNumber+1,slCurrentFrame+1);
}
else
{ stReadFrame.swNumberInTable= -1;
stReadFrame.uwTypeOfObject= TE_EmptyObject;
fprintf( ErrorFile, "%s : Unknow type of object (%s) (Channel %d, Frame %d)\n", AnimationName, _ap_SzParam[0], (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
}
// Bank
else if ( !stricmp(_p_szName, "Bank") )
{ // Integer
// Not used -------
}
// Object
else if ( !stricmp(_p_szName, "Object") )
{ // Reference to StringsTable (Name of object)
// Not used
}
// NumberInTable
else if ( !stricmp(_p_szName, "NumberInTable") ) {
// set number in table and object presence in anim
stReadFrame.swNumberInTable= (signed short)(ReadUShort(0)-1);
ax_tdstTabTBL[stReadFrame.swNumberInTable].ucFlag |= OBJECT_IN_ANIM;
if (stReadFrame.swNumberInTable >= 0)
{
// objet non present dans la TBL
if (!(ax_tdstTabTBL[stReadFrame.swNumberInTable].ucFlag & OBJECT_IN_TBL))
{ fprintf( ErrorFile, "%s : NumberInTable #%d not existing in Table of Objects (Channel %d, Frame %d)\n", AnimationName, (stReadFrame.swNumberInTable+1), (slWaitedChannelNumber+1), (slCurrentFrame+1) );
stReadFrame.uwTypeOfObject= TE_EmptyObject;
stReadFrame.swNumberInTable= -1;
ax_tdstTabTBL[stReadFrame.swNumberInTable].ucFlag &= ~OBJECT_IN_ANIM;
}
// object undefined choose depending on TBL
else if (stReadFrame.uwTypeOfObject == TE_Undefined) {
stReadFrame.uwTypeOfObject = (ax_tdstTabTBL[stReadFrame.swNumberInTable].ucIsObject)?TE_GraphicObject:TE_Event;
}
// type Object and Event in TBL !! Strange
else if ((stReadFrame.uwTypeOfObject == TE_GraphicObject) &&
(!ax_tdstTabTBL[stReadFrame.swNumberInTable].ucIsObject) )
{
stReadFrame.uwTypeOfObject= TE_Event;
fprintf( ErrorFile, "%s : 3dObject in A3d, Not a 3dObject in Object Table (NumberInTable %d, Channel %d, Frame %d)\n", AnimationName, (stReadFrame.swNumberInTable+1), (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
// type Event and Object in TBL !! Strange
else if ((stReadFrame.uwTypeOfObject == TE_Event) &&
(ax_tdstTabTBL[stReadFrame.swNumberInTable].ucIsObject) )
{
stReadFrame.uwTypeOfObject= TE_GraphicObject;
fprintf( ErrorFile, "%s : Event in A3d, 3dObject in Object Table (NumberInTable %d, Channel %d, Frame %d)\n", AnimationName, (stReadFrame.swNumberInTable+1), (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
}
}
// IncludingBox
else if ( !stricmp(_p_szName, "IncludingBox") )
{ // Reference to vector + reference to vector
// Not used
}
// Position
else if ( !stricmp(_p_szName, "Position") )
{ // Reference to vector
fn_v_CopyVect( stReadFrame.a3_xPosition, axa3_xVertexes[M_GetStackAlloc(eStackBinVertexes) + ReadUShort(0)] );
}
// Orientation
else if ( !stricmp(_p_szName, "Orientation") )
{ // Reference to quaternion
fn_v_CopyQuat( stReadFrame.a4_xQuatOri, axa4_xBinQuaternions[M_GetStackAlloc(eStackBinQuaternions) + ReadUShort(0)] );
}
// Scale
else if ( !stricmp(_p_szName, "Scale") )
{ // Reference to quaternions
fn_v_CopyQuat( stReadFrame.a4_xQuatSca, axa4_xBinQuaternions[M_GetStackAlloc(eStackBinQuaternions) + ReadUShort(0)] );
// Reference to vector
fn_v_CopyVect( stReadFrame.a3_xScaleValues, axa3_xVertexes[M_GetStackAlloc(eStackBinVertexes) + ReadUShort(1)] );
}
// PivotPosition
else if ( !stricmp(_p_szName, "PivotPosition") )
{ // Reference to vector
if ( uwPivotDefined == 0 )
{ uwPivotDefined= 1;
fn_v_CopyVect( ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].a3_xLocalPivotPos,
axa3_xVertexes[M_GetStackAlloc(eStackBinVertexes) + ReadUShort(0)] );
}
else
{ if ( fn_uw_CompVect( ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].a3_xLocalPivotPos,
axa3_xVertexes[M_GetStackAlloc(eStackBinVertexes) + ReadUShort(0)] ) != 0 )
fprintf(WarningFile, "%s : PivotPosition is changed, changing is ignore (Channel %d, Frame %d)\n", AnimationName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
}
// PivotOrientation
else if ( !stricmp(_p_szName, "PivotOrientation") )
{ SEB_xReal *p_tdxQuat;
// Reference to quaternion
// Must be equal to identity in this version !
p_tdxQuat= &axa4_xBinQuaternions[M_GetStackAlloc(eStackBinQuaternions) + ReadUShort(0)][0];
//if ( (p_tdxQuat[0]!=xZero) || (p_tdxQuat[1]!=xZero) || (p_tdxQuat[2]!=xZero) || (p_tdxQuat[3]!=xOne) )
// fprintf( ErrorFile, "%s : PivotOrientation must be equal to Identity (Channel %d, Frame %d)\n", AnimationName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
fn_v_CopyQuat( axa4_xBinQuaternions[M_GetStackAlloc(eStackBinQuaternions) + ReadUShort(0)], a4_xQuater1 );
}
// Morphing AR980304
else if ( !stricmp(_p_szName, "Morphing") )
{
unsigned short uwTargetObjectNumber=(unsigned short)(ReadUChar(0)-1);
if (!(ax_tdstTabTBL[uwTargetObjectNumber].ucFlag & OBJECT_IN_TBL) ||
(!ax_tdstTabTBL[uwTargetObjectNumber].ucIsObject) )
{
fprintf( ErrorFile, "%s : Morphing Target #%d not existing in Table of Objects (Channel %d, Frame %d)\n",
AnimationName, uwTargetObjectNumber+1, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
else {
ax_tdstTabTBL[uwTargetObjectNumber].ucFlag |= OBJECT_IN_ANIM;
// Add 1 Morphing info
fn_v_AllocateOnStack(eStackBinMorphInformation,1);
p_stGENERAL->uwNumberOfMorphData++;
// Fill the array
ax_tdstBinMorphInfos[M_GetStackAlloc(eStackBinMorphInformation)].ucTarget=(unsigned char)(ReadUChar(0)-1);
ax_tdstBinMorphInfos[M_GetStackAlloc(eStackBinMorphInformation)].ucMorphingAmount=ReadUChar(1);
ax_tdstBinMorphInfos[M_GetStackAlloc(eStackBinMorphInformation)].uwChannelNumber=ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].uwChannelNumber;
ax_tdstBinMorphInfos[M_GetStackAlloc(eStackBinMorphInformation)].uwFrameNumber=(unsigned short)slCurrentFrame;
}
}
// Transparency
else if ( !stricmp(_p_szName, "Transparency") ) {
unsigned short uwTransparency = ReadUShort(0);
if (uwTransparency > 255) {
uwTransparency = 255;
fprintf( ErrorFile, "%s : Transparency %d > 255 (Channel %d, Frame %d)\n", AnimationName,uwTransparency, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
stReadFrame.ucTransparency = (unsigned char)uwTransparency;
}
// FakeProperties
else if ( !stricmp(_p_szName, "FakeProperties") ) {
} // Nothing To do
// Unknown field
else {
fprintf( ErrorFile, "%s : Unknown field in A3d (%s) (Channel %d, Frame %d)\n", AnimationName, _p_szName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
}
}
// End of section
else if (_eAction == SCR_EA_Anl_EndSection)
{ if (uwOkAnimationFile == 0)
{ signed long slCnt;
tdxMatrix33 a3a3_xScaleMatrix, a3a3_xMtxSca, a3a3_xMtxOri;
tdxVector3 a3_xTmpVec;
// Copy Event (if we have an event of course !)
if ((stReadFrame.uwTypeOfObject & 0x00FF) == TE_Event)
{
if (stReadFrame.swNumberInTable < 0)
{ stReadFrame.uwTypeOfObject= (stReadFrame.uwTypeOfObject & 0xFF00) | TE_EmptyObject;
fprintf( ErrorFile, "%s : NumberInTable #%d not valid for event\n", AnimationName, (stReadFrame.swNumberInTable+1) );
}
else
{ unsigned short uwNumOfEntry;
signed long slEventInd;
fn_v_AllocateOnStack( eStackBinEvent, 1 );
slEventInd= M_GetStackAlloc(eStackBinEvent);
uwNumOfEntry= stReadFrame.swNumberInTable;
ax_tdstEvents[slEventInd].usEventNumberInTBL= uwNumOfEntry;
ax_tdstEvents[slEventInd].uwFrameNumber= (unsigned short) slCurrentFrame;
ax_tdstEvents[slEventInd].uwChannelNumber= ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].uwChannelNumber;
p_stGENERAL->uwNumberOfEvents++;
}
}
// Set other values
fn_v_QuatToMatrix( a3a3_xMtxSca, stReadFrame.a4_xQuatSca );
fn_v_QuatToMatrix( a3a3_xMtxOri, stReadFrame.a4_xQuatOri );
fn_v_InvRotDiaRot( a3a3_xScaleMatrix, a3a3_xMtxSca, stReadFrame.a3_xScaleValues );
fn_v_MatrixByVector( a3_xTmpVec, a3a3_xScaleMatrix, ax_tdstChannels[p_stGENERAL->slNumOfChannels + slWaitedChannelNumber].a3_xLocalPivotPos );
fn_v_MatrixByVector( stReadFrame.a3_xWorldPivotPosition, a3a3_xMtxOri, a3_xTmpVec );
stReadFrame.a3_xWorldPivotPosition[0]+= stReadFrame.a3_xPosition[0];
stReadFrame.a3_xWorldPivotPosition[1]+= stReadFrame.a3_xPosition[1];
stReadFrame.a3_xWorldPivotPosition[2]+= stReadFrame.a3_xPosition[2];
stReadFrame.xDistMaster= fn_x_VectorLength( stReadFrame.a3_xPosition );
stReadFrame.uwFrameNumber= (unsigned short) slCurrentFrame;
// Copy datas to Table
ax_tdstFrames[M_GetStackAlloc(eStackBinFrames) + slCurrentFrame]= stReadFrame;
stReadFrame.uwMask= 0x0000;
stReadFrame.uwAttribute= 0;
// On copie les frames jusqu'à la dernière frame
for ( slCnt=slLastFrame+1 ; slCnt<slCurrentFrame ; slCnt++ )
{ ax_tdstFrames[M_GetStackAlloc(eStackBinFrames) + slCnt]=
ax_tdstFrames[M_GetStackAlloc(eStackBinFrames) + slLastFrame];
ax_tdstFrames[M_GetStackAlloc(eStackBinFrames) + slCnt].uwAttribute= 0x0000;
ax_tdstFrames[M_GetStackAlloc(eStackBinFrames) + slCnt].uwFrameNumber= (unsigned short) slCnt;
}
slLastFrame= slCurrentFrame;
#ifdef ShowInfos
fn_v_LogSectionEnd();
#endif
}
}
return SCR_ERV_Anl_NormalReturn;
}
// **********************************************************************************
// KEY CALLBACK
// **********************************************************************************
// Modif 27/08/98 : Treat Morphing Entry (do nothing)
// Modif 28/08/98 : Treat Interpolation - type 1 (Non Linear)
SCR_tde_Anl_ReturnValue fn_eKeyCallBackV6i( SCR_tdst_File_Description *_p_stFile,
char *_p_szName,
char *_ap_SzParam[],
SCR_tde_Anl_Action _eAction )
{
// Section already analysed
if (_eAction == SCR_EA_Anl_AlreadyAnalysed)
{ if (uwOkAnimationFile == 0)
{ fprintf( ErrorFile, "%s : Key already analysed (Channel %d, Frame %d)\n", AnimationName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
}
// Beginning of section
else if (_eAction == SCR_EA_Anl_BeginSection)
{ if (uwOkAnimationFile == 0)
{
#ifdef ShowInfos
fn_v_LogSectionBegin( D_BINSCR_LogNew,
"Key",
AnimationName );
#endif
uwNbReadedKeys++;
}
}
// We are in the section
else if (_eAction == SCR_EA_Anl_Entry)
{
if (uwOkAnimationFile == 0)
{
// Attribute
if ( !stricmp(_p_szName, "Attribute") )
{ // Integer
stReadFrame.uwAttribute= ReadUShort(0); // Key type (0= none, 1= simple, 2=double)
}
// Mask
else if ( !stricmp(_p_szName, "Mask") )
{ unsigned short uwMask;
SEB_xReal *p_tdxVertex;
// Reference to vector (3 times)
uwMask= 0L;
p_tdxVertex= &axa3_xVertexes[M_GetStackAlloc(eStackBinVertexes) + ReadUShort(0)][0];
uwMask|= ((signed long) p_tdxVertex[0])<<10;
uwMask|= ((signed long) p_tdxVertex[1])<<9;
uwMask|= ((signed long) p_tdxVertex[2])<<8;
p_tdxVertex= &axa3_xVertexes[M_GetStackAlloc(eStackBinVertexes) + ReadUShort(1)][0];
uwMask|= ((signed long) p_tdxVertex[0])<<6;
uwMask|= ((signed long) p_tdxVertex[1])<<5;
uwMask|= ((signed long) p_tdxVertex[2])<<4;
p_tdxVertex= &axa3_xVertexes[M_GetStackAlloc(eStackBinVertexes) + ReadUShort(2)][0];
uwMask|= ((signed long) p_tdxVertex[0])<<2;
uwMask|= ((signed long) p_tdxVertex[1])<<1;
uwMask|= ((signed long) p_tdxVertex[2]);
stReadFrame.uwMask= uwMask;
}
// Type (of interpolation, 0= linear)
else if ( !stricmp(_p_szName, "Type") ) {
unsigned long ulInterpolation;
SEB_xReal xInterpolation;
ulInterpolation= ReadULong(0);
if (ulInterpolation == 0) // Linear interpolation
{ stReadFrame.xInterpolationParameter= 0.0;
}
// Non linear interpolation
else if (ulInterpolation == 1) {
xInterpolation= axa4_xBinQuaternions[M_GetStackAlloc(eStackBinQuaternions) + ReadULong(2)][0];
if (xInterpolation < 0.0) {
xInterpolation= 0.0;
fprintf( ErrorFile, "%s : Interpolation (mode 1) parameter is less than 0, and will set to 0 (Channel %d, Frame %d)\n", AnimationName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
else if (xInterpolation > 1.0) {
xInterpolation= 1.0;
fprintf( ErrorFile, "%s : Interpolation (mode 1) parameter is greater than 1, and will set to 1 (Channel %d, Frame %d)\n", AnimationName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
stReadFrame.xInterpolationParameter = (SEB_xReal)(2.0 - (4.0 * xInterpolation));
}
else // Unknow interpolation type
fprintf( ErrorFile, "%s : Interpolation type is not equal to 0 (linear) (Channel %d, Frame %d)\n", AnimationName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
// Morphing
else if ( !stricmp(_p_szName, "Morphing") ) {
} // Nothing To do
// Unknown field
else
{ fprintf( ErrorFile, "%s : Unknown field in A3d (%s) (Channel %d, Frame %d)\n", AnimationName, _p_szName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
}
}
// End of section
else if (_eAction == SCR_EA_Anl_EndSection)
{
if (uwOkAnimationFile == 0)
{
#ifdef ShowInfos
fn_v_LogSectionEnd();
#endif
}
}
return SCR_ERV_Anl_NormalReturn;
}
// **********************************************************************************
// SPEED LIST CALLBACK
// **********************************************************************************
SCR_tde_Anl_ReturnValue fn_eSpeedsListCallBackV6i( SCR_tdst_File_Description *_p_stFile,
char *_p_szName,
char *_ap_SzParam[],
SCR_tde_Anl_Action _eAction )
{
// Section already analysed
if (_eAction == SCR_EA_Anl_AlreadyAnalysed)
{ if (uwOkAnimationFile == 0)
{ fprintf( ErrorFile, "%s : SpeedsList already analysed (Channel %d, Frame %d)\n", AnimationName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
}
// Beginning of section
else if (_eAction == SCR_EA_Anl_BeginSection)
{
if (uwOkAnimationFile == 0)
{ signed long slCnt;
#ifdef ShowInfos
fn_v_LogSectionBegin( D_BINSCR_LogNew,
"SpeedsList",
AnimationName );
#endif
// Initialise memory
fn_v_CopyQuat( ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames)].tdxAngularSpeedQuat, a4_xQuater1 );
fn_v_CopyVect( ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames)].tdxSpeedVector, a3_xVector0 );
slLastFrame= 0;
for ( slCnt=0 ; slCnt<p_stGENERAL->uwNumberOfFrames ; slCnt++ )
{ ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slCnt].slNumOfAngularSpeedQuat= 0xFFFFFFFF;
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slCnt].slNumOfSpeedVector= 0xFFFFFFFF;
}
}
}
// We are in the section
else if (_eAction == SCR_EA_Anl_Entry)
{
if (uwOkAnimationFile == 0)
{
// Unknown field
fprintf( ErrorFile, "%s : Unknown field in A3d file, SpeedsList (%s) (Channel %d, Frame %d)\n", AnimationName, _p_szName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
}
// End of section
else if (_eAction == SCR_EA_Anl_EndSection)
{
if (uwOkAnimationFile == 0)
{ unsigned long ulFrameNumber, ulLastFrameNumber;
ulLastFrameNumber= M_GetStackAlloc(eStackBinOnlyFrames);
// SpeedQuaternion
for ( ulFrameNumber=0 ; ulFrameNumber<p_stGENERAL->uwNumberOfFrames ; ulFrameNumber++ )
{
if (ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + ulFrameNumber].slNumOfAngularSpeedQuat != 0xFFFFFFFF)
{ break;
}
}
if (ulFrameNumber < p_stGENERAL->uwNumberOfFrames)
{
ulLastFrameNumber= 0;
if (ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames)].slNumOfAngularSpeedQuat == 0xFFFFFFFF)
{ fn_v_SetIdQuater( ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames)].tdxAngularSpeedQuat );
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames)].slNumOfAngularSpeedQuat= 0;
}
// Fill gaps between AngularSpeed changes.
for ( ulFrameNumber=1 ; ulFrameNumber<p_stGENERAL->uwNumberOfFrames ; ulFrameNumber++ )
{
if (ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + ulFrameNumber].slNumOfAngularSpeedQuat == 0xFFFFFFFF)
{
fn_v_CopyQuat( ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + ulFrameNumber ].tdxAngularSpeedQuat,
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + ulLastFrameNumber].tdxAngularSpeedQuat );
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + ulFrameNumber].slNumOfAngularSpeedQuat= 0;
}
else
{ ulLastFrameNumber= ulFrameNumber;
}
}
}
else
printf("Pas de speed\n");
// SpeedVector
for ( ulFrameNumber=0 ; ulFrameNumber<p_stGENERAL->uwNumberOfFrames ; ulFrameNumber++ )
{
if (ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + ulFrameNumber].slNumOfSpeedVector != 0xFFFFFFFF)
{ break;
}
}
if (ulFrameNumber < p_stGENERAL->uwNumberOfFrames)
{
ulLastFrameNumber= 0;
if (ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames)].slNumOfSpeedVector == 0xFFFFFFFF)
{ fn_v_SetIdQuater( ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames)].tdxSpeedVector );
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames)].slNumOfSpeedVector= 0;
}
// Fill gaps between AngularSpeed changes.
for ( ulFrameNumber=1 ; ulFrameNumber<p_stGENERAL->uwNumberOfFrames ; ulFrameNumber++ )
{
if (ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + ulFrameNumber].slNumOfSpeedVector == 0xFFFFFFFF)
{
fn_v_CopyVect( ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + ulFrameNumber ].tdxSpeedVector,
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + ulLastFrameNumber].tdxSpeedVector );
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + ulFrameNumber].slNumOfSpeedVector= 0;
}
else
{ ulLastFrameNumber= ulFrameNumber;
}
}
}
else
printf("Pas de speed\n");
#ifdef ShowInfos
fn_v_LogSectionEnd();
#endif
}
}
return SCR_ERV_Anl_NormalReturn;
}
// **********************************************************************************
// SPEED CALLBACK
// **********************************************************************************
SCR_tde_Anl_ReturnValue fn_eSpeedCallBackV6i( SCR_tdst_File_Description *_p_stFile,
char *_p_szName,
char *_ap_SzParam[],
SCR_tde_Anl_Action _eAction )
{
// Section already analysed
if (_eAction == SCR_EA_Anl_AlreadyAnalysed) {
if (uwOkAnimationFile == 0) {
fprintf( ErrorFile, "%s : Speed already analysed (Channel %d, Frame %d)\n",
AnimationName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
}
// Beginning of section
else if (_eAction == SCR_EA_Anl_BeginSection)
{ if (uwOkAnimationFile == 0)
{
#ifdef ShowInfos
fn_v_LogSectionBegin( D_BINSCR_LogNew,
"Speed",
AnimationName );
#endif
// Readed Frame
slCurrentFrame= (atoi(_p_szName) - 1);
}
}
// We are in the section
else if (_eAction == SCR_EA_Anl_Entry)
{ if (uwOkAnimationFile == 0)
{
// RotationSpeed
if ( !stricmp(_p_szName, "RotationSpeed") )
{ // Reference to quaternion
fn_v_CopyQuat( ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slCurrentFrame].tdxAngularSpeedQuat,
axa4_xBinQuaternions[M_GetStackAlloc(eStackBinQuaternions) + ReadUShort(0)] );
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slCurrentFrame].slNumOfAngularSpeedQuat= 0;
}
// TranslationSpeed
else if ( !stricmp(_p_szName, "TranslationSpeed") )
{ // Reference to vector
fn_v_CopyVect( ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slCurrentFrame].tdxSpeedVector,
axa3_xVertexes[M_GetStackAlloc(eStackBinVertexes) + ReadUShort(0)] );
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slCurrentFrame].slNumOfSpeedVector= 0;
}
// Unknown field
else
{ fprintf( ErrorFile, "%s : Unknown field in A3d, SpeedsList, Speed (%s) (Channel %d, Frame %d)\n", AnimationName, _p_szName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
}
}
// End of section
else if (_eAction == SCR_EA_Anl_EndSection)
{ if (uwOkAnimationFile == 0)
{
slLastFrame= slCurrentFrame;
#ifdef ShowInfos
fn_v_LogSectionEnd();
#endif
}
}
return SCR_ERV_Anl_NormalReturn;
}
// **********************************************************************************
// HIERARCHIES LIST CALLBACK
// **********************************************************************************
SCR_tde_Anl_ReturnValue fn_eHierarchiesListCallBackV6i( SCR_tdst_File_Description *_p_stFile,
char *_p_szName,
char *ap_SzParam[],
SCR_tde_Anl_Action _eAction )
{
// Section already analysed
if (_eAction == SCR_EA_Anl_AlreadyAnalysed)
{ if (uwOkAnimationFile == 0)
{ fprintf( ErrorFile, "%s : HierarchiesList already analysed (Channel %d, Frame %d)\n", AnimationName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
}
// Beginning of section
else if (_eAction == SCR_EA_Anl_BeginSection)
{
if (uwOkAnimationFile == 0)
{
#ifdef ShowInfos
fn_v_LogSectionBegin( D_BINSCR_LogNew,
"Hierarchy",
AnimationName );
#endif
// Initialise memory
p_stGENERAL->slNumOfHierarchies= M_GetStackPos(eStackBinHierarchies);
p_stGENERAL->uwNumberOfHierarchies= 0;
slLastFrame= 0;
uwHierDef= 0;
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames)].uwHierarchyNbCouples= 0;
}
}
// We are in the section
else if (_eAction == SCR_EA_Anl_Entry)
{ if (uwOkAnimationFile == 0)
{
// Unknown field
fprintf( ErrorFile, "%s : Unknown field in A3d file, HierarchiesList (%s) (Channel %d, Frame %d)\n", AnimationName, _p_szName, (slWaitedChannelNumber+1), (slCurrentFrame+1) );
}
}
// End of section
else if (_eAction == SCR_EA_Anl_EndSection)
{ if (uwOkAnimationFile == 0)
{ signed long slCnt;
// On copie les Hierarchy de la dernière frame jusqu'à celle-ci
for ( slCnt=slLastFrame+1 ; slCnt<p_stGENERAL->uwNumberOfFrames ; slCnt++ )
{ ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slCnt].uwHierarchyNbCouples=
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slLastFrame].uwHierarchyNbCouples;
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slCnt].slNumOfHierarchyCouples=
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slLastFrame].slNumOfHierarchyCouples;
}
p_stGENERAL->uwNumberOfHierarchies= (unsigned short) (M_GetStackPos(eStackBinHierarchies) - p_stGENERAL->slNumOfHierarchies);
#ifdef ShowInfos
fn_v_LogSectionEnd();
#endif
}
}
return SCR_ERV_Anl_NormalReturn;
}
// **********************************************************************************
unsigned long fn_uw_CompareHierarchy( signed long slOldFrame,
signed long slNewFrame )
{ signed long slCnt1, slCnt2, slCnt3;
if ( ax_tdstOnlyFrames[slOldFrame].uwHierarchyNbCouples == ax_tdstOnlyFrames[slNewFrame].uwHierarchyNbCouples )
{
// For all hierarchy couples in CurrentFrame
for ( slCnt1=0 ; slCnt1<ax_tdstOnlyFrames[slNewFrame].uwHierarchyNbCouples ; slCnt1++ )
{ // For all hierarchy couples in OldFrame
slCnt2= 0;
slCnt3= 0;
while ( (slCnt2<ax_tdstOnlyFrames[slOldFrame].uwHierarchyNbCouples) && (slCnt3==0) )
{ if ( ( ax_tdstHierarchies[ ax_tdstOnlyFrames[slNewFrame].slNumOfHierarchyCouples + slCnt1 ].uwChild ==
ax_tdstHierarchies[ ax_tdstOnlyFrames[slOldFrame].slNumOfHierarchyCouples + slCnt2 ].uwChild ) &&
( ax_tdstHierarchies[ ax_tdstOnlyFrames[slNewFrame].slNumOfHierarchyCouples + slCnt1 ].uwFather ==
ax_tdstHierarchies[ ax_tdstOnlyFrames[slOldFrame].slNumOfHierarchyCouples + slCnt2 ].uwFather ) )
slCnt3= 1;
slCnt2++;
}
// If not found
if ( slCnt3==0)
return 1;
}
return 0;
}
return 1;
}
signed long fn_uw_HierarchyIsDefined( signed long slFirstFrame,
signed long slNewFrame )
{ signed long slCnt1, slLastHier;
// Search hierarchy before this frame
slLastHier= SEB_Invalid;
for ( slCnt1=slFirstFrame ; slCnt1<slNewFrame ; slCnt1++ )
{ if ( (ax_tdstOnlyFrames[slCnt1].slNumOfHierarchyCouples != slLastHier) && (ax_tdstOnlyFrames[slCnt1].uwHierarchyNbCouples != 0) )
{ slLastHier= ax_tdstOnlyFrames[slCnt1].slNumOfHierarchyCouples;
if ( fn_uw_CompareHierarchy( slCnt1, slNewFrame ) == 0 )
return slCnt1;
}
}
return -1;
}
// **********************************************************************************
// HIERARCHY CALLBACK
// **********************************************************************************
SCR_tde_Anl_ReturnValue fn_eA3dHIERARCHYCallBackV6i( SCR_tdst_File_Description *_p_stFile,
char *_p_szName,
char *_ap_SzParam[],
SCR_tde_Anl_Action _eAction )
{
// Section already analysed
if (_eAction == SCR_EA_Anl_AlreadyAnalysed)
{ if (uwOkAnimationFile == 0)
{ fprintf( ErrorFile, "%s : A3dHIERARCHY already analysed (Channel %d, Frame %d)\n", AnimationName, (slWaitedChannelNumber+1), (slHierFrame+1) );
}
}
// Beginning of section
else if (_eAction == SCR_EA_Anl_BeginSection)
{
if (uwOkAnimationFile == 0)
{
#ifdef ShowInfos
fn_v_LogSectionBegin( D_BINSCR_LogNew,
"A3dHIERARCHY",
AnimationName );
#endif
// Readed Frame
slHierFrame= (atoi(_p_szName) - 1);
// Allocate memory for Hierarchy structures
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slHierFrame].slNumOfHierarchyCouples=
M_GetStackPos(eStackBinHierarchies);
// Number of hierarchy couples equal to 0
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slHierFrame].uwHierarchyNbCouples= 0;
}
}
// We are in the section
else if (_eAction == SCR_EA_Anl_Entry)
{
if (uwOkAnimationFile == 0)
{
// ChannelAndFather
if ( !stricmp(_p_szName, "ChannelAndFather") )
{ signed long slInd;
uwHierDef= 1;
// Integer + integer
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slHierFrame].uwHierarchyNbCouples++;
fn_v_AllocateOnStack( eStackBinHierarchies, 1 );
slInd= M_GetStackAlloc(eStackBinHierarchies);
ax_tdstHierarchies[slInd].uwChild= (ReadUShort(0) - 1);
ax_tdstHierarchies[slInd].uwFather= (ReadUShort(1) - 1);
if ( (ReadUShort(0) <= 0) || (ReadUShort(0) > p_stGENERAL->uwNumberOfChannels) )
fprintf( ErrorFile, "%s : Invalid hierarchy channel number (%s) (Channel %d, Frame %d)\n", AnimationName, _p_szName, (slWaitedChannelNumber+1), (slHierFrame+1) );
if ( (ReadUShort(1) <= 0) || (ReadUShort(1) > p_stGENERAL->uwNumberOfChannels) )
fprintf( ErrorFile, "%s : Invalid hierarchy channel number (%s) (Channel %d, Frame %d)\n", AnimationName, _p_szName, (slWaitedChannelNumber+1), (slHierFrame+1) );
}
// Unknown field
else
{ fprintf( ErrorFile, "%s : Unknown field in A3d, HierarchiesList, A3dHIERARCHY (%s) (Channel %d, Frame %d)\n", AnimationName, _p_szName, (slWaitedChannelNumber+1), (slHierFrame+1) );
}
}
}
// End of section
else if (_eAction == SCR_EA_Anl_EndSection)
{ if (uwOkAnimationFile == 0)
{ signed long slInd, slCnt, slRet;
// On copie les hierarchies de la dernière frame jusqu'à celle-ci
for ( slCnt=slLastFrame+1 ; slCnt<slHierFrame ; slCnt++ )
{ ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slCnt].uwHierarchyNbCouples=
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slLastFrame].uwHierarchyNbCouples;
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slCnt].slNumOfHierarchyCouples=
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slLastFrame].slNumOfHierarchyCouples;
}
slLastFrame= slHierFrame;
slInd= M_GetStackAlloc(eStackBinOnlyFrames);
if (ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slHierFrame].uwHierarchyNbCouples == 0)
{ if ( uwHierDef == 0 )
fprintf( WarningFile, "%s : This hierarchy is empty (can't be change) (Channel %d, Frame %d)\n", AnimationName, (slWaitedChannelNumber+1), (slHierFrame+1) );
else ax_tdstOnlyFrames[slInd + slHierFrame].uwHierarchyNbCouples= 0;
}
else
{
slRet= fn_uw_HierarchyIsDefined( M_GetStackAlloc(eStackBinOnlyFrames), M_GetStackAlloc(eStackBinOnlyFrames) + slHierFrame );
// The hierarchy is defined before
if ( slRet >= 0 ) {
if (fn_uw_CompareHierarchy( M_GetStackAlloc(eStackBinOnlyFrames) + slHierFrame - 1, M_GetStackAlloc(eStackBinOnlyFrames) + slHierFrame ) == 0 )
fprintf(WarningFile, "%s : This hierarchy is duplicated (can be change) (Channel %d, Frame %d)\n", AnimationName, (slWaitedChannelNumber+1), (slHierFrame+1) );
fn_v_DeAllocateOnStack( eStackBinHierarchies, ax_tdstOnlyFrames[slInd + slHierFrame].uwHierarchyNbCouples);
ax_tdstOnlyFrames[M_GetStackAlloc(eStackBinOnlyFrames) + slHierFrame].slNumOfHierarchyCouples=
ax_tdstOnlyFrames[slRet].slNumOfHierarchyCouples;
}
}
#ifdef ShowInfos
fn_v_LogSectionEnd();
#endif
}
}
return SCR_ERV_Anl_NormalReturn;
}
// **********************************************************************************
// A3D FILE CALLBACK
// **********************************************************************************
// Modif 28/10/98 Allocate A3dGeneral - Carlos Torres
// **********************************************************************************
SCR_tde_Anl_ReturnValue fn_eA3DfileCallBackV6i( SCR_tdst_File_Description *_p_stFile,
char *_p_szName,
char *_ap_SzParam[],
SCR_tde_Anl_Action _eAction )
{
if (_eAction == SCR_EA_Anl_AlreadyAnalysed)
{
}
else if (_eAction == SCR_EA_Anl_BeginSection)
{
fn_v_LogSectionBegin( D_BINSCR_LogNew,
".a3d",
AnimationName );
// always allocate A3D General in stack to respect indexing
fn_v_AllocateOnStack( eStackBinA3dGENERAL, 1 );
}
else if (_eAction == SCR_EA_Anl_Entry)
{
fprintf( ErrorFile, "%s : Unknown field in .a3d (%s)\n", AnimationName, _p_szName );
}
else if (_eAction == SCR_EA_Anl_EndSection) {
fn_v_LogSectionEnd();
}
return SCR_ERV_Anl_NormalReturn;
}
// **********************************************************************************
// Modif 28/10/98 init validAnim table - Carlos Torres
// **********************************************************************************
void fn_v_InitA3dV6i( void ) {
// Register CallBack on A3dHeader
SCR_fn_v_RdL0_RegisterCallback( "A3dHEADER",
fn_eA3dHEADERCallBackV6i,
SCR_CRC_c_RdL0_ForSection );
// Register CallBack on A3dStringsTable
SCR_fn_v_RdL0_RegisterCallback( "A3dStringsTable",
fn_eA3dStringsTableCallBackV6i,
SCR_CRC_c_RdL0_ForSection );
// Register CallBack on A3dVertexesTable
SCR_fn_v_RdL0_RegisterCallback( "A3dVertexesTable",
fn_eA3dVertexesTableCallBackV6i,
SCR_CRC_c_RdL0_ForSection );
// Register CallBack on A3dQuaternionsTable
SCR_fn_v_RdL0_RegisterCallback( "A3dQuaternionsTable",
fn_eA3dQuaternionsTableCallBackV6i,
SCR_CRC_c_RdL0_ForSection );
// Register CallBack on A3dAnimationGENERAL
SCR_fn_v_RdL0_RegisterCallback( "A3dAnimationGENERAL",
fn_eA3dAnimationGENERALCallBackV6i,
SCR_CRC_c_RdL0_ForSection );
// Register CallBack on Channel
SCR_fn_v_RdL0_RegisterCallback( "Channel",
fn_eChannelCallBackV6i,
SCR_CRC_c_RdL0_ForSection );
// Register CallBack on Frame
SCR_fn_v_RdL0_RegisterCallback( "Frame",
fn_eFrameCallBackV6i,
SCR_CRC_c_RdL0_ForSection );
// Register CallBack on Key
SCR_fn_v_RdL0_RegisterCallback( "Key",
fn_eKeyCallBackV6i,
SCR_CRC_c_RdL0_ForSection );
// Register CallBack on SpeedsList
SCR_fn_v_RdL0_RegisterCallback( "SpeedsList",
fn_eSpeedsListCallBackV6i,
SCR_CRC_c_RdL0_ForSection );
// Register CallBack on Speed
SCR_fn_v_RdL0_RegisterCallback( "Speed",
fn_eSpeedCallBackV6i,
SCR_CRC_c_RdL0_ForSection );
// Register CallBack on HierarchiesList
SCR_fn_v_RdL0_RegisterCallback( "HierarchiesList",
fn_eHierarchiesListCallBackV6i,
SCR_CRC_c_RdL0_ForSection );
// Register CallBack on A3dHIERARCHY
SCR_fn_v_RdL0_RegisterCallback( "A3dHIERARCHY",
fn_eA3dHIERARCHYCallBackV6i,
SCR_CRC_c_RdL0_ForSection );
// Register CallBack on ".a3d"
SCR_fn_v_RdL0_RegisterCallback( ".a3d",
fn_eA3DfileCallBackV6i,
SCR_CRC_c_RdL0_ForFile );
}
// **********************************************************************************
#undef L_A3D_V6_C