Archived

This topic is now archived and is closed to further replies.

supagu

3d max exporter problem

Recommended Posts

has any one here developed thier own exporter? if so, i am having some issues trying to export animation data. if you have had experience in this area and are willing to help, please post (no point posting code if no one has done a max exporter is there )

Share this post


Link to post
Share on other sites
Consider MaxScript or the IGAME interface.

MaxScript is straight forward and easy to learn.

There is a XML file exporter for IGame which exports skin data/bones data and other nice things so all you have to do is modify it''s source to suit your needs.

Share this post


Link to post
Share on other sites
ah great
my problem is:
i want to export bone animation data from 3d max, so i need the roation and position and scale of each bone at each keyframe.
I had a look through same sample code on converting quaterions to euler angles, and ironing out the flips when converting them, but the data i get out is just stupid(wrong ;p)
and for the position of the bone, it needs to be te distance to the parent bone.

here is my code:

[cpp]
//rC is
Control* rC = node->GetTMController()->GetRotationController();








Quat qPrev;
Quat qCur;
Interval iv;
Matrix3 mPrev;
Matrix3 mCur;
Matrix3 rmat;
float rotation[3] = {0,0,0};
float curRotation[3] = {0,0,0};
float prevRotation[3] = {0,0,0};
float eaCur[3] = {0,0,0};
float eaPrev[3] = {0,0,0};
float EulerAng[3] = {0,0,0};
float dEuler[3] = {0,0,0};

//range.SetEnd( rC->GetKeyTime( rC->NumKeys() - 1 ) );

rC->GetValue( (range.End() - range.Start())/2 ,&qPrev,iv);

Matrix3 tm;
qPrev.MakeMatrix(tm);
MatrixToEuler(tm,EulerAng, EULERTYPE_XYZ);

//float fXYZAngles[3];
//QuatToEuler( qPrev, fXYZAngles );

//fprintf(animFile, "INITIAL rotation: %f %f %f\n", fXYZAngles[0], fXYZAngles[1], fXYZAngles[2]);

for( TimeValue t = range.Start(); t <= range.End(); t++)
{
//qPrev = qCur;
rC->GetValue( t, &qCur , iv);//rC->GetKeyTime(i)

qCur.MakeMatrix(mCur);
qPrev.MakeMatrix(mPrev);

//mPrev = mCur;
//rC->GetValue( t, &mCur , iv);

for(int j=0 ; j < 3 ; j++)
{
dEuler[j] = 0;
}

//check sign flip
float f = GetEulerMatAngleRatio(mPrev,mCur,eaPrev,eaCur,EULERTYPE_XYZ);
if( f > PI)
{
// We found a flip here
for(int j=0 ; j < 3 ; j++)
{
// find the sign flip :
if( fabs((eaCur[j] - eaPrev[j])) < 2*PI - THRESHHOLD )
dEuler[j] = eaCur[j] - eaPrev[j];
else
// unflip the flip
dEuler[j] = (2*PI - (float) (fabs(eaCur[j]) + fabs(eaPrev[j]))) * (eaPrev[j] > 0 ? 1 : -1);

EulerAng[j] += dEuler[j];
}


}
else
{
// Add up the angle difference
for(int j=0 ; j < 3 ; j++)
{
dEuler[j] = eaCur[j] - eaPrev[j];
EulerAng[j] += dEuler[j];
}
}

//fprintf(animFile, "(time: %i) %f %f %f\n", (int)t, dEuler[0], dEuler[1], dEuler[2] );

if( rC->IsKeyAtTime(t,KEYAT_ROTATION) || pC->IsKeyAtTime(t,KEYAT_POSITION) )
{


//fprintf(animFile, "(time: %i) fixed roation: %f %f %f\n", (int)t, EulerAng[0], EulerAng[1], EulerAng[2] );
/*
//now we need to push the data onto the frame data
std::vector::iterator frameIt;
bool bFound = false;
for(frameIt = frameData.begin(); frameIt != frameData.end(); frameIt++)
{
if( frameIt->time == t )//rC->GetKeyTime(a) )
{
if( frameIt->rotation == true )
{
bFound = true;
break;
}

frameIt->rotation = true;
frameIt->yaw = -EulerAng[2] ;//yaw;
frameIt->pitch = EulerAng[0] - PI/2;//pitch;
frameIt->roll = (EulerAng[1]);//roll;

bFound = true;
}
}
if( !bFound )
{*/
keyFrame newKeyFrame;

newKeyFrame.time = t; //rC->GetKeyTime(a);
newKeyFrame.rotation = true;
//newKeyFrame.yaw = -EulerAng[2];
//newKeyFrame.pitch = - EulerAng[0] + PI/2;
//newKeyFrame.roll = (EulerAng[1] + PI/2 );

newKeyFrame.yaw = EulerAng[2];
newKeyFrame.pitch = EulerAng[0];
newKeyFrame.roll = EulerAng[1];

/*
Point3 trans;
Matrix3 pmat;
Interval ivalid;
ivalid = FOREVER;
pmat = node->GetParentTM( t );
//pC->GetValue( t , &pmat, ivalid, CTRL_RELATIVE);
trans = pmat.GetTrans();

//get my tm/position
Matrix3 nMat;
Point3 nTrans;
nMat = node->GetNodeTM(0);
nTrans = nMat.GetTrans();

Point3 fTrans = nTrans - trans;*/

TimeValue currtime = ip->GetTime();
Matrix3 tm = node->GetObjTMBeforeWSM(currtime);
Matrix3 pTm = node->GetParentNode()->GetObjTMBeforeWSM(currtime);
Point3 trans = tm.GetTrans() - pTm.GetTrans();

newKeyFrame.position = true;
newKeyFrame.x = trans.x;
newKeyFrame.y = trans.z;
newKeyFrame.z = trans.y;

frameData.push_back( newKeyFrame );
//}

}

qPrev = qCur;
}

[/cpp]




Share this post


Link to post
Share on other sites
This is how i do it.


void GetKeyData(INode* pNode, int iFrame) {
// cout << pNode->GetName() << endl;

int idx = GetBoneIdx(pNode);

if(idx < 0)
return;

TimeValue time = iFrame*GetTicksPerFrame();
INode* parent = pNode->GetParentNode();
Matrix3 m = pNode->GetNodeTM(time);
m.NoScale();

if(!parent->IsRootNode()) {
Matrix3 pm = parent->GetNodeTM(time);
pm.NoScale();

m = m*Inverse(pm);
}

AffineParts ap;
decomp_affine(m ,&ap);

bone[idx].key[iFrame].p.set(ap.t.x, ap.t.y, ap.t.z);
bone[idx].key[iFrame].q.SetValues(ap.q.x, ap.q.y, ap.q.z, ap.q.w);


for(int i = 0; i < pNode->NumberOfChildren(); ++i)
GetKeyData(pNode->GetChildNode(i), iFrame);

return;
}


GetBoneIdx returns the index of the INode in the bone array.

Share this post


Link to post
Share on other sites