Jump to content
  • Advertisement

Archived

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

supagu

3d max exporter problem

This topic is 5326 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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
Advertisement
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
that using quaterions? i wanna use euler angles, which is the problem, as converting from quats to euler can have sign flips

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!