0
\$\begingroup\$

I'm working on an animation and model exporter from Maya to use within my game. Currently, models work perfectly, and animations have some issues with the joints. Since Maya works in an OpenGL environment and my game works with DirectX, to load the mesh in I negated the Z component of all vertex positions, normals, and inverted the UV's V coordinate.

Currently, joints loaded in are reversed along the Z axis. My question is, what do I need to do to get bone matrices working properly from OpenGL to DirectX? My original thought was to just transpose them, but that doesn't work. I've also tried negating the z-column but that causes some odd stretching.

I've only been trying to invert the root bone.

Notice the feet joints pointing backward. https://i.stack.imgur.com/6kNr2.png

Inverting the root joints Z-Column, weird stretching and it looks like he's slouched. https://i.stack.imgur.com/KysH8.png

Any thoughts on this?

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Just a point of note - neither OpenGL nor D3D specify anything about matrix order or formats. You can use a CM RH matrix in D3D if you wish, just as your can use a RM LH matrix in OpenGL. \$\endgroup\$ Aug 23, 2012 at 15:42
  • \$\begingroup\$ Everything in my game is rendered with a left handed projection matrix \$\endgroup\$ Aug 23, 2012 at 15:46
  • \$\begingroup\$ mh01 has a point, OpenGL and DX essentially use float[16] for their matrices - Column-major or Row-major makes no real difference. Your question may be more clear using the title: "Exporting .X file from Maya", because that is actually what you are asking about ( right? ). \$\endgroup\$
    – Phill.Zitt
    Aug 23, 2012 at 16:04
  • \$\begingroup\$ The file format is custom, I'm writing the exporter and importer, and I'm aware of how matrices are stored in memory. Positive-Z in DirectX is negative-z in OpenGL, so there are some small differences one must account for when exporting between the two. I've seen some people export the local transforms of joints and negate the z-column on the DirectX end to get things to work, however that's causing some issues with my animations (shown above). So, my question is, what could be missing, or what else could differ between OpenGL and DirectX? \$\endgroup\$ Aug 23, 2012 at 16:46
  • \$\begingroup\$ @user1609470 I think by default OpenGL uses a right handed projection while nearly all DirectX tutorials use a left handed projection. You can use whatever projection matrix you'd like though in either. \$\endgroup\$
    – NtscCobalt
    Aug 23, 2012 at 16:54

2 Answers 2

0
\$\begingroup\$

You need to flip your matrices and all points or use a Right handed projection matrix for everything in your game.

I wrote my own exporter and noticed the same problem but like Left handed so I just multiplied all Maya matrices by the following

// A float version of a right to left handed converison matrix
float RightToLeftMatData[4][4] = {
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, -1, 0,
    0, 0, 0, 1,
};

//Not sure why but transforms must be built off of the dagPath
MStatus status;
MMatrix tMMat = dagPath.inclusiveMatrix(&status);
if (status != MS::kSuccess)
    Error("Failed to get inclusive matrix");
tMMat.get(tMat.m);

// Cobalt always uses left handed coordinates so convert the coordinate system
if (ConvertFromRightHandedCoordinate)
{
    tMat = mRightToLeft * tMat * mRightToLeft;
}

Also you'll need to modify every vertex's position, normal, binormal, tangent, and bitangent like so...

//Animation requires that we do not get vertex points pretransformed to world space
fnMesh.getPoints( vertexList, MSpace::kObject);
for ( uint32 i = 0; i < vertexList.length(); i++ )
{
    vertexList[i].cartesianize();
    MPoint point = vertexList[i];
    if (ConvertFromRightHandedCoordinate) vPoint.push_back(cVector3(point.x, point.y, -point.z));
    else vPoint.push_back(cVector3(point.x, point.y, point.z));
}

fnMesh.getNormals( normalList, MSpace::kObject);
for (uint32 i = 0; i < normalList.length(); i++)
{
    MPoint point = normalList[i];
    if (ConvertFromRightHandedCoordinate) vNormal.push_back(cVector3(point.x, point.y, -point.z));
    else vNormal.push_back(cVector3(point.x, point.y, point.z));
}

// Same thing for binormal and bitangent

I also flip the V coordinates for textures though you could always do this in a shader if you'd prefer. A lot of shader examples from NVidia actually have a flag to do that.

If you need some reference material feel free to take anything you want from my maya conversion. http://code.google.com/p/cobaltlibrary/source/browse/trunk/Tools/Source/MayaConvert/MayaFile.cpp

\$\endgroup\$
2
  • \$\begingroup\$ Np, by the way I cannot for the life of me remember why I do mRightToLeft * tMat * mRightToLeft. That doesn't make a lot of sense to me but it works. I do have a custom matrix class so maybe my multiple function has a bug. \$\endgroup\$
    – NtscCobalt
    Aug 23, 2012 at 16:50
  • \$\begingroup\$ @NtscCobalt The reason why you do that is because you are performing a change of basis (en.wikipedia.org/wiki/Change_of_basis#Change_of_basis) in your space (inverting the direction in which the z-axis points). If you have a matrix P whose columns represent the new basis vectors in the old basis, you can convert any linear transform M from the old space into a linear transform in the new space M' by doing M' = P M P^-1. When changing handedness, P^-1 = P, so you end up doing M' = PMP. \$\endgroup\$
    – pedrosorio
    Nov 1, 2012 at 18:16
0
\$\begingroup\$

I don't think you need to flip the z-coordinate of your vertex, just transpose you matrix and use it in your DirectX program A command misunderstanding about this is LH or RH system, but it's really nothing about which coordinate system you are using, it's about row-major(DirectX) or column-major(OpenGL) matrix.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .