3d max exporter problem

Started by
4 comments, last by supagu 20 years, 3 months ago
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 )
Advertisement
Yeah, I''ve done some exporters. What problem are you running into?

-John
- John
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.
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]




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

This topic is closed to new replies.

Advertisement