3DSMAX convert OGRE(D3D)
1. 坐标转换:
坐标变换比较简单,按照轴的对应关系转换就可以了,按照多数插件的做法是yz互换,但是会发现场景是左右颠倒的,因为3dsmax是右手坐标系(Z向上,Y向内),而D3D是左手坐标系(Y向上,Z向内),所以x应该取负。
void MaxVtx2DX( Point3& p,Vec3& v )
{
v.x = -p.x;
v.y = p.z;
v.z = p.y;
}
2.旋转转换
通常动画场景我们需要独立的旋转分量,一般是Quatnion,quat的转换就不是这么简单了。因为quat包含了正余弦值。
一个可以保证正确性的方法是,把Quat转成旋转矩阵,取得三根轴向,把轴看作矢量,按照上面规则进行处理。轴取自于行,还是取自于列,可能不同系统规定不同,但是我们可以用普适的方法去获得:用矩阵去变换基向量:
比如 M.Transform( Vector(1,0,0)) 得到的一定是X轴的朝向。
void MaxMtx2OgreTransform( Matrix3& mtx,Ogre::Vector3& pos,Ogre::Vector3& scale,Ogre::Quaternion&quat )
{
Point3 p,s;
Quat q;
AffineParts ap;
decomp_affine(mtx,&ap);
s = Point3( ap.f,ap.f,ap.f);
p = ap.t;
q = ap.q;
AngAxis aa(q);
Matrix3 rtm;
rtm.SetRotate(q);
Vec3 ax,ay,az;
Point3 right(1,0,0);
Point3 up(0,0,1);
Point3 dir(0,1,0);
right = rtm.VectorTransform( right );
up = rtm.VectorTransform( up );
dir = rtm.VectorTransform( dir );
MaxVtx2DX( right,ax );
MaxVtx2DX( up,ay );
MaxVtx2DX( dir,az );
Vec3 tr,sc;
MaxVtx2DX( p,tr );
sc.x = s.x;
sc.y = s.y;
sc.z = s.z;
quat.FromAxes(
Ogre::Vector3(-ax.x,-ax.y,-ax.z),
Ogre::Vector3(ay.x,ay.y,ay.z),
Ogre::Vector3(az.x,az.y,az.z)
);
pos = Ogre::Vector3( tr.x,tr.y,tr.z );
scale = Ogre::Vector3( sc.x,sc.y,sc.z );
}
3.相对变换
3DSMAX自身取相对变换是 Invert(ptm)*ntm,但是对于OGRE-D3D应该是反过来。
Matrix3 GetRelativeTM( Matrix3 ptm,Matrix3 ntm )
{
Matrix3 iptm = ptm;
iptm.Invert();
Matrix3 tm = ntm *iptm ;
return tm;
}
4.骨骼动画
骨骼动画的相对变换,应该是相对BindingPose,并且是局部变换对局部变换求相对变换:
AnimTransofrmMatrix = GetRelativeTM(BindingPoseLocalMatrix,NodeLocalMatrix(t))
t是time。