992 lines
26 KiB
C++
992 lines
26 KiB
C++
|
/*=========================================================================
|
||
|
|
||
|
EXPBONE.CPP
|
||
|
|
||
|
Author: Tim Swann @ CLIMAX
|
||
|
Created:
|
||
|
Project:
|
||
|
Purpose:
|
||
|
|
||
|
Copyright (c) 1998 Climax Development Ltd
|
||
|
|
||
|
===========================================================================*/
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
Includes
|
||
|
-------- */
|
||
|
|
||
|
#include "AsciiExp.h"
|
||
|
|
||
|
|
||
|
/* Std Lib
|
||
|
------- */
|
||
|
|
||
|
/* Glib
|
||
|
---- */
|
||
|
|
||
|
/* Local
|
||
|
----- */
|
||
|
|
||
|
/* Graphics
|
||
|
-------- */
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
Tyepdefs && Defines
|
||
|
------------------- */
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
Structure defintions
|
||
|
-------------------- */
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
Positional Vars
|
||
|
--------------- */
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
Function Prototypes
|
||
|
------------------- */
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
Vars
|
||
|
---- */
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
Data
|
||
|
---- */
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
Function:
|
||
|
Purpose:
|
||
|
Params:
|
||
|
Returns:
|
||
|
---------------------------------------------------------------------- */
|
||
|
|
||
|
|
||
|
void AsciiExp::ExportBones( INode* node )
|
||
|
{
|
||
|
|
||
|
nbBones = 0;
|
||
|
|
||
|
WriteChunkHdr( (char*)BONE_ID, 0);
|
||
|
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||
|
|
||
|
ExportLimb( node );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
Function:
|
||
|
Purpose:
|
||
|
Params:
|
||
|
Returns:
|
||
|
---------------------------------------------------------------------- */
|
||
|
|
||
|
static bool ThisIsABone( INode * node )
|
||
|
{
|
||
|
bool retval = false;
|
||
|
char * nodeName;
|
||
|
|
||
|
nodeName = node->GetName();
|
||
|
|
||
|
// if (nodeName[0] == 'R' &&
|
||
|
// nodeName[1] == 'O' &&
|
||
|
// nodeName[2] == 'O' &&
|
||
|
// nodeName[3] == 'T') retval = true;
|
||
|
|
||
|
retval = true;
|
||
|
|
||
|
return (retval);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
Function:
|
||
|
Purpose:
|
||
|
Params:
|
||
|
Returns:
|
||
|
---------------------------------------------------------------------- */
|
||
|
|
||
|
int AsciiExp::ValidateBoneKids( INode * node )
|
||
|
{
|
||
|
int nbChilds = node->NumberOfChildren();
|
||
|
int childCnt = 0;
|
||
|
|
||
|
return nbChilds;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool IsParent(INode *p, INode *c)
|
||
|
{
|
||
|
while (!c->IsRootNode()) {
|
||
|
c=c->GetParentNode();
|
||
|
if (c==p)
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
/*----------------------------------------------------------------------
|
||
|
Function:
|
||
|
Purpose:
|
||
|
Params:
|
||
|
Returns:
|
||
|
---------------------------------------------------------------------- */
|
||
|
|
||
|
void AsciiExp::ExportLimb( INode * node )
|
||
|
{
|
||
|
INode * ChildNode;
|
||
|
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||
|
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||
|
long nbChilds;
|
||
|
Matrix3 tm;
|
||
|
AffineParts ap;
|
||
|
|
||
|
Quat q;
|
||
|
char name[256];
|
||
|
Point3 fpos;
|
||
|
Point3 pos, p2;
|
||
|
|
||
|
// EXPORT BONE
|
||
|
sprintf( name, "%s", node->GetName() );
|
||
|
fprintf( tempStream, "OUTPUTTING - %s\n", name ); // DEBUG FILE
|
||
|
fwrite( &name, sizeof(char), MAX_NAME_LENGTH, expStream ); // WRITE BONE NAME
|
||
|
|
||
|
// EXPORT WEIGHTS
|
||
|
long nbVerts = 0;
|
||
|
if (nbWeights)
|
||
|
{
|
||
|
fprintf( tempStream, "WEIGHTS:\n" );
|
||
|
|
||
|
for (int i=0;i<nbWeights;i++)
|
||
|
{
|
||
|
for (int n=0;n<Weights[i].nodecount;n++)
|
||
|
{
|
||
|
if (!strcmp(node->GetName(), Weights[i].names[n])) nbVerts++;
|
||
|
}
|
||
|
}
|
||
|
fprintf( tempStream, " nbVerts = %d\n", nbVerts );
|
||
|
fwrite( &nbVerts, sizeof(long), 1, expStream ); // WRITE BONE WEIGHT COUNT
|
||
|
|
||
|
if (nbVerts)
|
||
|
{
|
||
|
for (int i=0;i<nbWeights;i++)
|
||
|
{
|
||
|
for (int n=0;n<Weights[i].nodecount;n++)
|
||
|
{
|
||
|
if (!strcmp(node->GetName(), Weights[i].names[n]))
|
||
|
{
|
||
|
fwrite( &Weights[i].vertno, sizeof(long), 1, expStream );
|
||
|
fwrite( &Weights[i].weights[n], sizeof(float), 1, expStream );
|
||
|
fwrite( &Weights[i].Offsets[n].x, sizeof(float), 1, expStream);
|
||
|
fwrite( &Weights[i].Offsets[n].z, sizeof(float), 1, expStream);
|
||
|
fwrite( &Weights[i].Offsets[n].y, sizeof(float), 1, expStream);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
fwrite( &nbVerts, sizeof(long), 1, expStream ); // WRITE BONE WEIGHT COUNT
|
||
|
}
|
||
|
|
||
|
// EXPORT CHILDREN
|
||
|
|
||
|
nbBones++;
|
||
|
nbChilds = node->NumberOfChildren();
|
||
|
fwrite( &nbChilds, sizeof(int), 1, expStream);
|
||
|
for (int c=0;c<nbChilds;c++) // RUN THROUGH ALL OF THE CHILDREN
|
||
|
{
|
||
|
ChildNode = node->GetChildNode(c);
|
||
|
if (ChildNode) ExportLimb( ChildNode );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
Function:
|
||
|
Purpose:
|
||
|
Params:
|
||
|
Returns:
|
||
|
---------------------------------------------------------------------- */
|
||
|
|
||
|
void AsciiExp::ExportBoneAnim( INode* node )
|
||
|
{
|
||
|
TimeValue start = ip->GetAnimRange().Start();
|
||
|
TimeValue end = ip->GetAnimRange().End();
|
||
|
TimeValue t;
|
||
|
int delta = GetTicksPerFrame();
|
||
|
Matrix3 tm;
|
||
|
AffineParts ap;
|
||
|
Point3 prevPos;
|
||
|
Point3 startScale;
|
||
|
Quat prevQ;
|
||
|
Quat scaleQ;
|
||
|
Quat q;
|
||
|
Quat InvQ;
|
||
|
INode * ChildNode;
|
||
|
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||
|
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||
|
long nbChilds;
|
||
|
|
||
|
|
||
|
for (t=start; t<=end; t+=delta)
|
||
|
{
|
||
|
// TRANSLATION
|
||
|
if (0)//node->IsRootNode())
|
||
|
{
|
||
|
tm = node->GetNodeTM( t );
|
||
|
} else
|
||
|
{
|
||
|
tm = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));
|
||
|
}
|
||
|
decomp_affine(tm, &ap);
|
||
|
|
||
|
fwrite( &ap.t.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||
|
fwrite( &ap.t.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||
|
fwrite( &ap.t.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||
|
|
||
|
fwrite( &ap.q.x, sizeof(float), 1, expStream ); // WRITE BONE ROT X-AXIS
|
||
|
fwrite( &ap.q.z, sizeof(float), 1, expStream ); // WRITE BONE ROT Y-AXIS
|
||
|
fwrite( &ap.q.y, sizeof(float), 1, expStream ); // WRITE BONE ROT Z-AXIS
|
||
|
fwrite( &ap.q.w, sizeof(float), 1, expStream ); // WRITE BONE ROT W ANGLE
|
||
|
|
||
|
fwrite( &ap.k.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||
|
fwrite( &ap.k.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||
|
fwrite( &ap.k.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||
|
|
||
|
fwrite( &ap.u.x, sizeof(float), 1, expStream ); // WRITE BONE ROT X-AXIS
|
||
|
fwrite( &ap.u.z, sizeof(float), 1, expStream ); // WRITE BONE ROT Y-AXIS
|
||
|
fwrite( &ap.u.y, sizeof(float), 1, expStream ); // WRITE BONE ROT Z-AXIS
|
||
|
fwrite( &ap.u.w, sizeof(float), 1, expStream ); // WRITE BONE ROT W ANGLE
|
||
|
}
|
||
|
|
||
|
nbChilds = node->NumberOfChildren();
|
||
|
for (int c=0;c<nbChilds;c++) // RUN THROUGH ALL OF THE CHILDREN
|
||
|
{
|
||
|
ChildNode = node->GetChildNode(c);
|
||
|
if (ChildNode) ExportBoneAnim( ChildNode );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void AsciiExp::ExportBoneKeyAnim( INode* node)
|
||
|
{
|
||
|
TimeValue start = ip->GetAnimRange().Start();
|
||
|
TimeValue end = ip->GetAnimRange().End();
|
||
|
int delta = GetTicksPerFrame();
|
||
|
Matrix3 tm;
|
||
|
AffineParts ap, StartAp;
|
||
|
Point3 prevPos;
|
||
|
Point3 startScale;
|
||
|
Quat prevQ;
|
||
|
Quat scaleQ;
|
||
|
Quat q;
|
||
|
Quat InvQ;
|
||
|
INode * ChildNode;
|
||
|
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||
|
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||
|
long nbChilds;
|
||
|
|
||
|
int num;
|
||
|
int i;
|
||
|
int FrameN;
|
||
|
Interval ivalid;
|
||
|
IKey k;
|
||
|
Control *c;
|
||
|
IKeyControl *ikeys;
|
||
|
ITCBPoint3Key tcbPosKey;
|
||
|
ITCBRotKey tcbRotKey;
|
||
|
ITCBScaleKey tcbSclKey;
|
||
|
IBezPoint3Key bezPosKey;
|
||
|
IBezQuatKey bezRotKey;
|
||
|
IBezScaleKey bezSclKey;
|
||
|
ILinPoint3Key linPosKey;
|
||
|
ILinRotKey linRotKey;
|
||
|
ILinScaleKey linSclKey;
|
||
|
TimeValue time;
|
||
|
|
||
|
|
||
|
if (node->EvalWorldState(ip->GetAnimRange().Start()).obj) {
|
||
|
|
||
|
TimeList tl;
|
||
|
tl.Clear();
|
||
|
INode *KeyNode = node;
|
||
|
c = KeyNode->GetTMController();
|
||
|
if (c) {
|
||
|
c = c->GetPositionController();
|
||
|
if (c) {
|
||
|
ikeys = GetKeyControlInterface(c);
|
||
|
if (ikeys) {
|
||
|
|
||
|
num = ikeys->GetNumKeys();
|
||
|
if (num >0)
|
||
|
{
|
||
|
for (i = 0; i<num; i++) {
|
||
|
if (c->ClassID() == Class_ID(TCBINTERP_POSITION_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &tcbPosKey);
|
||
|
time = tcbPosKey.time;
|
||
|
} else
|
||
|
if (c->ClassID() == Class_ID(HYBRIDINTERP_POSITION_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &bezPosKey);
|
||
|
time = bezPosKey.time;
|
||
|
} else
|
||
|
if (c->ClassID() == Class_ID(LININTERP_POSITION_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &linPosKey);
|
||
|
time = linPosKey.time;
|
||
|
}
|
||
|
tl.Add(time);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
c = KeyNode->GetTMController();
|
||
|
if (c) {
|
||
|
c = c->GetRotationController();
|
||
|
if (c) {
|
||
|
ikeys = GetKeyControlInterface(c);
|
||
|
if (ikeys) {
|
||
|
|
||
|
num = ikeys->GetNumKeys();
|
||
|
if (num >0)
|
||
|
{
|
||
|
|
||
|
for (i = 0; i<num; i++) {
|
||
|
if (c->ClassID() == Class_ID(TCBINTERP_ROTATION_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &tcbRotKey);
|
||
|
int rots;
|
||
|
if (i)
|
||
|
{
|
||
|
ITCBRotKey oldtcbRotKey;
|
||
|
ikeys->GetKey(i-1, &oldtcbRotKey);
|
||
|
rots = fabs(tcbRotKey.val.angle - oldtcbRotKey.val.angle) / (0.6667 * PI) + 1;
|
||
|
for (int k=1; k<rots; k++)
|
||
|
{
|
||
|
tl.Add(oldtcbRotKey.time+(int)((float)k*(tcbRotKey.time-oldtcbRotKey.time)/rots));
|
||
|
}
|
||
|
}
|
||
|
time = tcbRotKey.time;
|
||
|
} else
|
||
|
if (c->ClassID() == Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &bezRotKey);
|
||
|
time = bezRotKey.time;
|
||
|
} else
|
||
|
if (c->ClassID() == Class_ID(LININTERP_ROTATION_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &linRotKey);
|
||
|
time = linRotKey.time;
|
||
|
}
|
||
|
tl.Add(time);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
c = KeyNode->GetTMController();
|
||
|
if (c) {
|
||
|
c = c->GetScaleController();
|
||
|
if (c) {
|
||
|
ikeys = GetKeyControlInterface(c);
|
||
|
if (ikeys) {
|
||
|
|
||
|
num = ikeys->GetNumKeys();
|
||
|
if (num >0)
|
||
|
{
|
||
|
for (i = 0; i<num; i++) {
|
||
|
if (c->ClassID() == Class_ID(TCBINTERP_SCALE_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &tcbSclKey);
|
||
|
time = tcbSclKey.time;
|
||
|
} else
|
||
|
if (c->ClassID() == Class_ID(HYBRIDINTERP_SCALE_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &bezSclKey);
|
||
|
time = bezSclKey.time;
|
||
|
} else
|
||
|
if (c->ClassID() == Class_ID(LININTERP_SCALE_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &linSclKey);
|
||
|
time = linSclKey.time;
|
||
|
}
|
||
|
|
||
|
tl.Add(time);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (tl.Count()) {
|
||
|
num = tl.Count();
|
||
|
WriteChunkHdr( (char*)KEY_ID, 0);
|
||
|
fwrite( &CHANNEL_TYPE_BONE, sizeof( Uint32 ), 1, expStream );
|
||
|
fwrite( &CHANNEL_INFO_ALL, sizeof( Uint32) , 1, expStream);
|
||
|
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||
|
fwrite( &CurBone, sizeof( Uint32 ), 1, expStream );
|
||
|
fwrite( &num, sizeof( Uint32 ), 1, expStream );
|
||
|
|
||
|
for (num = 0; num <tl.Count(); num++) {
|
||
|
time = tl.Get(num);
|
||
|
tm = node->GetNodeTM(time) * Inverse(node->GetParentTM(time));
|
||
|
|
||
|
FrameN = (int)((float)(time - start) / delta);
|
||
|
|
||
|
decomp_affine(tm, &ap);
|
||
|
if (num == 0)
|
||
|
StartAp = ap;
|
||
|
|
||
|
fwrite( &FrameN, sizeof(Uint32), 1, expStream);
|
||
|
fwrite( &ap.t.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||
|
fwrite( &ap.t.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||
|
fwrite( &ap.t.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||
|
|
||
|
fwrite( &ap.q.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||
|
fwrite( &ap.q.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||
|
fwrite( &ap.q.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||
|
fwrite( &ap.q.w, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||
|
|
||
|
fwrite( &ap.k.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||
|
fwrite( &ap.k.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||
|
fwrite( &ap.k.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||
|
|
||
|
fwrite( &ap.u.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||
|
fwrite( &ap.u.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||
|
fwrite( &ap.u.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||
|
fwrite( &ap.u.w, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
CurBone++;
|
||
|
nbChilds = node->NumberOfChildren();
|
||
|
for (int cn=0;cn<nbChilds;cn++) // RUN THROUGH ALL OF THE CHILDREN
|
||
|
{
|
||
|
ChildNode = node->GetChildNode(cn);
|
||
|
if (ChildNode) ExportBoneKeyAnim( ChildNode);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void AsciiExp::ExportBoneKeyAnimPos( INode* node)
|
||
|
{
|
||
|
TimeValue start = ip->GetAnimRange().Start();
|
||
|
TimeValue end = ip->GetAnimRange().End();
|
||
|
int delta = GetTicksPerFrame();
|
||
|
Matrix3 tm;
|
||
|
AffineParts ap;
|
||
|
Point3 prevPos;
|
||
|
Point3 startScale;
|
||
|
Quat prevQ;
|
||
|
Quat scaleQ;
|
||
|
Quat q;
|
||
|
Quat InvQ;
|
||
|
INode * ChildNode;
|
||
|
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||
|
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||
|
long nbChilds;
|
||
|
|
||
|
int num;
|
||
|
int i;
|
||
|
int FrameN;
|
||
|
Interval ivalid;
|
||
|
IKey k;
|
||
|
Control *c;
|
||
|
IKeyControl *ikeys;
|
||
|
ITCBPoint3Key tcbPosKey;
|
||
|
ITCBRotKey tcbRotKey;
|
||
|
ITCBScaleKey tcbScaleKey;
|
||
|
IBezPoint3Key bezPosKey;
|
||
|
IBezQuatKey bezRotKey;
|
||
|
IBezScaleKey bezScaleKey;
|
||
|
ILinPoint3Key linPosKey;
|
||
|
ILinRotKey linRotKey;
|
||
|
ILinScaleKey linScaleKey;
|
||
|
TimeValue time;
|
||
|
|
||
|
if (node->EvalWorldState(ip->GetAnimRange().Start()).obj) {
|
||
|
TimeList tl;
|
||
|
tl.Clear();
|
||
|
INode *KeyNode = node;
|
||
|
while (KeyNode) {
|
||
|
c = KeyNode->GetTMController();
|
||
|
if (c) {
|
||
|
c = c->GetPositionController();
|
||
|
if (c) {
|
||
|
ikeys = GetKeyControlInterface(c);
|
||
|
if (ikeys) {
|
||
|
|
||
|
num = ikeys->GetNumKeys();
|
||
|
if (num >0)
|
||
|
{
|
||
|
for (i = 0; i<num; i++) {
|
||
|
if (c->ClassID() == Class_ID(TCBINTERP_POSITION_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &tcbPosKey);
|
||
|
time = tcbPosKey.time;
|
||
|
} else
|
||
|
if (c->ClassID() == Class_ID(HYBRIDINTERP_POSITION_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &bezPosKey);
|
||
|
time = bezPosKey.time;
|
||
|
} else
|
||
|
if (c->ClassID() == Class_ID(LININTERP_POSITION_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &linPosKey);
|
||
|
time = linPosKey.time;
|
||
|
}
|
||
|
tl.Add(time);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (KeyNode->IsRootNode())
|
||
|
break;
|
||
|
KeyNode = KeyNode->GetParentNode();
|
||
|
}
|
||
|
if (tl.Count()) {
|
||
|
num = tl.Count();
|
||
|
WriteChunkHdr( (char*)KEY_ID, 0);
|
||
|
fwrite( &CHANNEL_TYPE_BONE, sizeof( Uint32 ), 1, expStream );
|
||
|
fwrite( &CHANNEL_INFO_POSITION, sizeof( Uint32) , 1, expStream);
|
||
|
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||
|
fwrite( &CurBone, sizeof( Uint32 ), 1, expStream );
|
||
|
fwrite( &num, sizeof( Uint32 ), 1, expStream );
|
||
|
|
||
|
for (num = 0; num <tl.Count(); num++) {
|
||
|
time = tl.Get(num);
|
||
|
tm = node->GetNodeTM(time) * Inverse(node->GetParentTM(time));
|
||
|
|
||
|
FrameN = (int)((float)(time - start) / delta);
|
||
|
|
||
|
decomp_affine(tm, &ap);
|
||
|
|
||
|
fwrite( &FrameN, sizeof(Uint32), 1, expStream);
|
||
|
fwrite( &ap.t.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||
|
fwrite( &ap.t.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||
|
fwrite( &ap.t.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
CurBone++;
|
||
|
nbChilds = node->NumberOfChildren();
|
||
|
for (int cn=0;cn<nbChilds;cn++) // RUN THROUGH ALL OF THE CHILDREN
|
||
|
{
|
||
|
ChildNode = node->GetChildNode(cn);
|
||
|
if (ChildNode) ExportBoneKeyAnimPos( ChildNode);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void AsciiExp::ExportBoneKeyAnimRot( INode* node)
|
||
|
{
|
||
|
TimeValue start = ip->GetAnimRange().Start();
|
||
|
TimeValue end = ip->GetAnimRange().End();
|
||
|
int delta = GetTicksPerFrame();
|
||
|
Matrix3 tm;
|
||
|
AffineParts ap;
|
||
|
Point3 prevPos;
|
||
|
Point3 startScale;
|
||
|
Quat prevQ;
|
||
|
Quat scaleQ;
|
||
|
Quat q;
|
||
|
Quat InvQ;
|
||
|
INode * ChildNode;
|
||
|
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||
|
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||
|
long nbChilds;
|
||
|
|
||
|
|
||
|
int num;
|
||
|
int i;
|
||
|
int FrameN;
|
||
|
Interval ivalid;
|
||
|
IKey k;
|
||
|
Control *c;
|
||
|
IKeyControl *ikeys;
|
||
|
ITCBPoint3Key tcbPosKey;
|
||
|
ITCBRotKey tcbRotKey;
|
||
|
ITCBScaleKey tcbScaleKey;
|
||
|
IBezPoint3Key bezPosKey;
|
||
|
IBezQuatKey bezRotKey;
|
||
|
IBezScaleKey bezScaleKey;
|
||
|
ILinPoint3Key linPosKey;
|
||
|
ILinRotKey linRotKey;
|
||
|
ILinScaleKey linScaleKey;
|
||
|
TimeValue time;
|
||
|
|
||
|
if (node->EvalWorldState(ip->GetAnimRange().Start()).obj) {
|
||
|
TimeList tl;
|
||
|
tl.Clear();
|
||
|
INode *KeyNode = node;
|
||
|
while (KeyNode) {
|
||
|
c = KeyNode->GetTMController();
|
||
|
if (c) {
|
||
|
c = c->GetRotationController();
|
||
|
if (c) {
|
||
|
ikeys = GetKeyControlInterface(c);
|
||
|
if (ikeys) {
|
||
|
|
||
|
num = ikeys->GetNumKeys();
|
||
|
if (num >0)
|
||
|
{
|
||
|
|
||
|
for (i = 0; i<num; i++) {
|
||
|
if (c->ClassID() == Class_ID(TCBINTERP_ROTATION_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &tcbRotKey);
|
||
|
time = tcbRotKey.time;
|
||
|
} else
|
||
|
if (c->ClassID() == Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &bezRotKey);
|
||
|
time = bezRotKey.time;
|
||
|
} else
|
||
|
if (c->ClassID() == Class_ID(LININTERP_ROTATION_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &linRotKey);
|
||
|
time = linRotKey.time;
|
||
|
}
|
||
|
tl.Add(time);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (KeyNode->IsRootNode())
|
||
|
break;
|
||
|
KeyNode = KeyNode->GetParentNode();
|
||
|
}
|
||
|
|
||
|
if (tl.Count()) {
|
||
|
num = tl.Count();
|
||
|
WriteChunkHdr( (char*)KEY_ID, 0);
|
||
|
fwrite( &CHANNEL_TYPE_BONE, sizeof( Uint32 ), 1, expStream );
|
||
|
fwrite( &CHANNEL_INFO_ROTATION, sizeof( Uint32) , 1, expStream);
|
||
|
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||
|
fwrite( &CurBone, sizeof( Uint32 ), 1, expStream );
|
||
|
fwrite( &num, sizeof( Uint32 ), 1, expStream );
|
||
|
for (num = 0; num <tl.Count(); num++) {
|
||
|
time = tl.Get(num);
|
||
|
tm = node->GetNodeTM(time) * Inverse(node->GetParentTM(time));
|
||
|
|
||
|
FrameN = (int)((float)(time - start) / delta);
|
||
|
|
||
|
decomp_affine(tm, &ap);
|
||
|
|
||
|
fwrite( &FrameN, sizeof(Uint32), 1, expStream);
|
||
|
fwrite( &ap.q.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||
|
fwrite( &ap.q.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||
|
fwrite( &ap.q.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||
|
fwrite( &ap.q.w, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CurBone++;
|
||
|
|
||
|
nbChilds = node->NumberOfChildren();
|
||
|
for (int cn=0;cn<nbChilds;cn++) // RUN THROUGH ALL OF THE CHILDREN
|
||
|
{
|
||
|
ChildNode = node->GetChildNode(cn);
|
||
|
if (ChildNode) ExportBoneKeyAnimRot( ChildNode);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void AsciiExp::ExportBoneKeyAnimScl( INode* node)
|
||
|
{
|
||
|
TimeValue start = ip->GetAnimRange().Start();
|
||
|
TimeValue end = ip->GetAnimRange().End();
|
||
|
int delta = GetTicksPerFrame();
|
||
|
Matrix3 tm;
|
||
|
AffineParts ap;
|
||
|
Point3 prevPos;
|
||
|
Point3 startScale;
|
||
|
Quat prevQ;
|
||
|
Quat scaleQ;
|
||
|
Quat q;
|
||
|
Quat InvQ;
|
||
|
INode * ChildNode;
|
||
|
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||
|
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||
|
long nbChilds;
|
||
|
|
||
|
int num;
|
||
|
int i;
|
||
|
int FrameN;
|
||
|
Interval ivalid;
|
||
|
IKey k;
|
||
|
Control *c;
|
||
|
IKeyControl *ikeys;
|
||
|
ITCBPoint3Key tcbPosKey;
|
||
|
ITCBRotKey tcbRotKey;
|
||
|
ITCBScaleKey tcbSclKey;
|
||
|
IBezPoint3Key bezPosKey;
|
||
|
IBezQuatKey bezRotKey;
|
||
|
IBezScaleKey bezSclKey;
|
||
|
ILinPoint3Key linPosKey;
|
||
|
ILinRotKey linRotKey;
|
||
|
ILinScaleKey linSclKey;
|
||
|
TimeValue time;
|
||
|
|
||
|
char text[200];
|
||
|
sprintf(text, "%s", node->GetName());
|
||
|
|
||
|
if (node->EvalWorldState(ip->GetAnimRange().Start()).obj) {
|
||
|
TimeList tl;
|
||
|
tl.Clear();
|
||
|
INode *KeyNode = node;
|
||
|
while (KeyNode) {
|
||
|
c = KeyNode->GetTMController();
|
||
|
if (c) {
|
||
|
c = c->GetScaleController();
|
||
|
if (c) {
|
||
|
ikeys = GetKeyControlInterface(c);
|
||
|
if (ikeys) {
|
||
|
|
||
|
num = ikeys->GetNumKeys();
|
||
|
if (num >0)
|
||
|
{
|
||
|
for (i = 0; i<num; i++) {
|
||
|
if (c->ClassID() == Class_ID(TCBINTERP_SCALE_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &tcbSclKey);
|
||
|
time = tcbSclKey.time;
|
||
|
} else
|
||
|
if (c->ClassID() == Class_ID(HYBRIDINTERP_SCALE_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &bezSclKey);
|
||
|
time = bezSclKey.time;
|
||
|
} else
|
||
|
if (c->ClassID() == Class_ID(LININTERP_SCALE_CLASS_ID, 0)) {
|
||
|
ikeys->GetKey(i, &linSclKey);
|
||
|
time = linSclKey.time;
|
||
|
}
|
||
|
|
||
|
tl.Add(time);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (KeyNode->IsRootNode())
|
||
|
break;
|
||
|
KeyNode = KeyNode->GetParentNode();
|
||
|
}
|
||
|
|
||
|
if (tl.Count()) {
|
||
|
num = tl.Count();
|
||
|
WriteChunkHdr( (char*)KEY_ID, 0);
|
||
|
fwrite( &CHANNEL_TYPE_BONE, sizeof( Uint32 ), 1, expStream );
|
||
|
fwrite( &CHANNEL_INFO_SCALE, sizeof( Uint32) , 1, expStream);
|
||
|
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||
|
fwrite( &CurBone, sizeof( Uint32 ), 1, expStream );
|
||
|
fwrite( &num, sizeof( Uint32 ), 1, expStream );
|
||
|
|
||
|
for (num = 0; num <tl.Count(); num++) {
|
||
|
time = tl.Get(num);
|
||
|
tm = node->GetNodeTM(time) * Inverse(node->GetParentTM(time));
|
||
|
|
||
|
FrameN = (int)((float)(time - start) / delta);
|
||
|
|
||
|
decomp_affine(tm, &ap);
|
||
|
|
||
|
fwrite( &FrameN, sizeof(Uint32), 1, expStream);
|
||
|
fwrite( &ap.k.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||
|
fwrite( &ap.k.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||
|
fwrite( &ap.k.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||
|
|
||
|
fwrite( &ap.u.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||
|
fwrite( &ap.u.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||
|
fwrite( &ap.u.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||
|
fwrite( &ap.u.w, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
CurBone++;
|
||
|
nbChilds = node->NumberOfChildren();
|
||
|
for (int cn=0;cn<nbChilds;cn++) // RUN THROUGH ALL OF THE CHILDREN
|
||
|
{
|
||
|
ChildNode = node->GetChildNode(cn);
|
||
|
if (ChildNode) ExportBoneKeyAnimScl( ChildNode);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
Function:
|
||
|
Purpose:
|
||
|
Params:
|
||
|
Returns:
|
||
|
---------------------------------------------------------------------- */
|
||
|
|
||
|
void AsciiExp::ExportWeights( INode* node )
|
||
|
{
|
||
|
Object * objPtr = NULL;
|
||
|
Modifier * phyMod = NULL;
|
||
|
IPhysiqueExport * phyExport = NULL;
|
||
|
IPhyContextExport * contextExport = NULL;
|
||
|
IPhyVertexExport * vtxExport = NULL;
|
||
|
IPhyRigidVertex * rvtExport = NULL;
|
||
|
IPhyBlendedRigidVertex * brvExport = NULL;
|
||
|
Point3 offsetvector;
|
||
|
INode * bonenode = NULL;
|
||
|
float weight = 0.f;
|
||
|
int nbNodes = 0;
|
||
|
int vtype = 0;
|
||
|
INode * RootNode = NULL;
|
||
|
ModContext *mc;
|
||
|
|
||
|
|
||
|
Weights = NULL;
|
||
|
|
||
|
phyMod = FindPhysiqueModifier (node, &mc);
|
||
|
if (phyMod)
|
||
|
{
|
||
|
PhyMc = mc;
|
||
|
phyExport = (IPhysiqueExport *)phyMod->GetInterface( I_PHYINTERFACE );
|
||
|
if (phyExport)
|
||
|
{
|
||
|
contextExport = (IPhyContextExport *)phyExport->GetContextInterface( node );
|
||
|
if (contextExport)
|
||
|
{
|
||
|
contextExport->ConvertToRigid( TRUE );
|
||
|
contextExport->AllowBlending( TRUE );
|
||
|
|
||
|
nbWeights = contextExport->GetNumberVertices();
|
||
|
|
||
|
Weights = (WEIGHTS *)malloc( nbWeights * sizeof(WEIGHTS) );
|
||
|
|
||
|
for (int i=0;i<nbWeights;i++)
|
||
|
{
|
||
|
vtxExport = (IPhyVertexExport *)contextExport->GetVertexInterface( i );
|
||
|
|
||
|
if (vtxExport)
|
||
|
{
|
||
|
vtype = vtxExport->GetVertexType();
|
||
|
|
||
|
if (vtype == RIGID_TYPE)
|
||
|
{
|
||
|
rvtExport = (IPhyRigidVertex *)vtxExport;
|
||
|
bonenode = rvtExport->GetNode();
|
||
|
|
||
|
Weights[i].vertno = i;
|
||
|
Weights[i].nodecount = 1;
|
||
|
Weights[i].weights[0] = 1.f;
|
||
|
Weights[i].Offsets[0] = rvtExport->GetOffsetVector();
|
||
|
sprintf( Weights[i].names[0], "%s", bonenode->GetName() );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
brvExport = (IPhyBlendedRigidVertex *)vtxExport;
|
||
|
nbNodes = brvExport->GetNumberNodes();
|
||
|
|
||
|
Weights[i].vertno = i;
|
||
|
Weights[i].nodecount = nbNodes;
|
||
|
if (nbNodes > MAX_BONE_NODES)
|
||
|
{
|
||
|
MessageBox( MAX_hWnd, "INCREASE MAX_BONE_NODES", "ERROR", MB_OK );
|
||
|
return;
|
||
|
}
|
||
|
for (int n=0;n<nbNodes;n++)
|
||
|
{
|
||
|
bonenode = brvExport->GetNode( n );
|
||
|
|
||
|
weight = brvExport->GetWeight( n );
|
||
|
offsetvector = brvExport->GetOffsetVector( n );
|
||
|
|
||
|
Weights[i].weights[n] = weight;
|
||
|
Weights[i].Offsets[n] = brvExport->GetOffsetVector(n);
|
||
|
sprintf( Weights[i].names[n], "%s", bonenode->GetName() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
contextExport->ReleaseVertexInterface( vtxExport );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
ExportBones(ip->GetRootNode());
|
||
|
if (Weights) {
|
||
|
free (Weights);
|
||
|
Weights = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool AsciiExp::IsBoned(INode *node)
|
||
|
{
|
||
|
if (FindPhysiqueModifier(node))
|
||
|
return true;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
Function:
|
||
|
Purpose:
|
||
|
Params:
|
||
|
Returns:
|
||
|
---------------------------------------------------------------------- */
|
||
|
|
||
|
|
||
|
Modifier * AsciiExp::FindPhysiqueModifier (INode* node, ModContext**mc)
|
||
|
{
|
||
|
// Get object from node. Abort if no object.
|
||
|
Object* ObjectPtr = node->GetObjectRef();
|
||
|
|
||
|
if (!ObjectPtr) return NULL;
|
||
|
|
||
|
// Is derived object ?
|
||
|
if (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID)
|
||
|
{
|
||
|
// Yes -> Cast.
|
||
|
IDerivedObject* DerivedObjectPtr = static_cast<IDerivedObject*>(ObjectPtr);
|
||
|
|
||
|
// Iterate over all entries of the modifier stack.
|
||
|
int ModStackIndex = 0;
|
||
|
while (ModStackIndex < DerivedObjectPtr->NumModifiers())
|
||
|
{
|
||
|
// Get current modifier.
|
||
|
Modifier* ModifierPtr = DerivedObjectPtr->GetModifier(ModStackIndex);
|
||
|
|
||
|
// Is this Physique ?
|
||
|
if (ModifierPtr->ClassID() == Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B))
|
||
|
{
|
||
|
*mc = DerivedObjectPtr->GetModContext(ModStackIndex);
|
||
|
// Yes -> Exit.
|
||
|
return ModifierPtr;
|
||
|
}
|
||
|
|
||
|
// Next modifier stack entry.
|
||
|
ModStackIndex++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Not found.
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
Modifier * AsciiExp::FindPhysiqueModifier (INode* node)
|
||
|
{
|
||
|
// Get object from node. Abort if no object.
|
||
|
Object* ObjectPtr = node->GetObjectRef();
|
||
|
|
||
|
if (!ObjectPtr) return NULL;
|
||
|
|
||
|
// Is derived object ?
|
||
|
if (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID)
|
||
|
{
|
||
|
// Yes -> Cast.
|
||
|
IDerivedObject* DerivedObjectPtr = static_cast<IDerivedObject*>(ObjectPtr);
|
||
|
|
||
|
// Iterate over all entries of the modifier stack.
|
||
|
int ModStackIndex = 0;
|
||
|
while (ModStackIndex < DerivedObjectPtr->NumModifiers())
|
||
|
{
|
||
|
// Get current modifier.
|
||
|
Modifier* ModifierPtr = DerivedObjectPtr->GetModifier(ModStackIndex);
|
||
|
|
||
|
// Is this Physique ?
|
||
|
if (ModifierPtr->ClassID() == Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B))
|
||
|
{
|
||
|
// Yes -> Exit.
|
||
|
return ModifierPtr;
|
||
|
}
|
||
|
|
||
|
// Next modifier stack entry.
|
||
|
ModStackIndex++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Not found.
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*===========================================================================
|
||
|
end */
|