Attaching matrices to nodes is a little confusing at first. Never fear, there are samples to help you through it. The basic idea is you attach a xform rec to the rec you want to transform using mgAttach.
If you are in to scripting, take a look at the sample script egxform1.py
Or you can look at the sample apps egxform1.c
both of these are found in the OpenFlight API's samples folder.
I dug into the old MultiGen-Paradigm User Forum and found several posts on Transformations and Matrices. I cobbled several of them together to give you a little more info on how Transformations work on nodes.
Note that mgSetMatrix is NOT intended to be used to apply a transformation to a node. Instead, you must attach individual transformation records to the node you want to transform. These include fltXmTranslate, fltXmScale, fltXmRotate, fltXmGeneral, etc. There are many benefits (from a modeling and programming point of view) to attaching separate transformations rather than just one single matrix. The biggest benefit is that you can more easily compose and decompose the transformation if they are broken out into separate parts. For example if you Translate, Rotate and Scale a node, you can modify the Rotate part separately and the model will just "be right" without having to do all the matrix math to make the "final" matrix.
Of course, if you'd rather just apply a matrix to a node, there is the fltXmGeneral transformation type. Use it (and not mgSetMatrix) and you are free to make the matrix however you want to.
More on mgSetMatrix: You'll notice that the first parameter to this function is an mgrec*. While this mgrec* can be a node record, it really should be a transformation (fltXmGeneral) record. That is because the fltMatrix attribute of a node record is a transient one. It represents the cumulative matrix applied to the node (which is the combination of all transformation nodes currently applied to that node) and gets reset by the API automatically as you manipulate the transformation records on the node. So if you did set the fltMatrix attribute of the node, it will get reset immediately as it ALWAYS reflects the current cumulation of the transformations on the node !
So you see how the fltMatrix attribute on a node is completely useless in terms of "Set", the fltMatrix attribute on the node is very useful from a "Get" point of view. If you wanted to know how your node is transformed, you have two choices. You could traverse all the transformation records attached to a node and form the cumulative matrix yourself (UGH!) or simply call mgGetMatrix on the node to get the cumulative matrix.
So in conclusion:
NEVER use mgSetMatrix on a node record, INSTEAD construct transformation records and attach them to nodes.
Ahh much clearer now. Thanks!
I got it to work by adding a fltXmGeneral as suggested. I have one question though, are you telling me that to get the cumulative transformation of a node all I have to do is mgGetMatrix? Hell, I've been using mgWalk and mgWalkGetMatrix to get the cumulative transform. Also, does mgGetMatrix include or exclude the current node's matrix?
There are two types of cumulative in play here. Steve is talking about the accumulation of all the transforms on the single node (rotate, scale...) This does not take into account transforms on parent nodes. You are right to use the mgWalk matrix because that is the easiest way to get the accumulation of all the parent matrices that affect a node's position.
Good catch Chris...
This picture illustrates Chris' points...
Ok got it! Thanks for all the info.
Craig
Hi,
I'm unable to set a newly created node's matrix. I've tried several different ways and it always fails. What I'm I doing wrong. Here's a sample code of numerous ways I'm trying to set the matrix:
mgmatrix wAnchorPointMatrix;
wXRefDBHandler.GetPostNodeMatrix(wAttachPoint, wAnchorPointMatrix);
mgrec* wAnchorPointNode = CreateNode(fltGroup);
mgSetName(wAnchorPointNode, "AnchorPoint");
mgmatrix wTempMatrix;
mgrec* wTempMatrixRec = CreateNode(fltMatrix);
int wNbGet = mgGetAttList(wAnchorPointNode, fltMatrix, &wTempMatrix;, MG_NULL);
mgbool wGetMatrixResult = mgGetMatrix(wAnchorPointNode, fltMatrix, &wTempMatrix;);
mgbool wResult = mgSetMatrix(wAnchorPointNode, fltMatrix, wAnchorPointMatrix);
int wNbSet = mgSetAttList(wAnchorPointNode, fltMatrix, wAnchorPointMatrix, MG_NULL);
int wNbGet2 = mgGetAttList(wAnchorPointNode, fltMatrix, &wTempMatrix;, MG_NULL);
mgrec* xForm;
mgxfllcode xType;
if (mgHasXform (wAttachPoint))
{
xForm = mgGetXform (wAttachPoint);
while (xForm)
{
mgbool wAppendResult = mgAppend(wAnchorPointNode, xForm);
// Do something with xForm
xType = mgGetXformType (xForm);
xForm = mgGetNext (xForm);
}
}
AddNode(wAnchorPointNode, iNodeParent);
The mgGetAttList and mgSetAttList all return 1 indicating that the matrix was set but when I get the matrix right after setting it, it is that same value as it was before trying to set it. Also, all other functions, mgAppend, mgGetMatrix, mgSetMatrix, all fail. So what I'm I missing here?
Thanks,
Steven