Notifications
Clear all

[Closed] [SDK] Object translation / rotation frustration

I might be missing something very small here, but I’ve gone blind on how to fix this…

What I’m doing:
Getting rotation and translation from a calculation, I then want to apply the result to my current object over time. Everything works as it should except setting translation and rotation on the object ‘at the same time’… See below:

If I only do the translation – then it works.
If I add rotation to the matrix it removes the translation…

So- here’s how I do it currently:

//store the transform
Point3 nodeTM3dsmax;
Matrix3 matrixTrans;

//get the current node we want to move \ rotate at time t
INode* currNode = maxscene->GetChildNode(a);

//Get the XYZ coordinates back from function
nodeTM3dsmax.x = trans.getOrigin().getX();
nodeTM3dsmax.y = trans.getOrigin().getZ();
nodeTM3dsmax.z = trans.getOrigin().getY();
//add it to the matrix
matrixTrans.SetTranslate(nodeTM3dsmax);

//Get the rotation back from function and apply to matrix
matrixTrans.SetRotate(trans.getRotation().x(),trans.getRotation().y(),trans.getRotation().z());
//move and rotate the object.
currNode->SetNodeTM(mytime,matrixTrans);

So, it works if I just test either translation alone, or rotation alone.
If I try rotation alone it translates all objects to 0,0,0 and rotates them there.
if I try translation alone it moves the objects as they should, but they have no rotation.
so I thought the proper way was as above, to make the translation, then add the rotation to the matrix…

14 Replies

what happens if you do it like this ?

Matrix3 tm;

tm.SetRotate(yaw,pitch,roll);
tm.Translate(Point3(x,y,z));

node->SetNodeTM(t,tm);
1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

this is not actually correct. setting matrix rotation from three floats (yaw, pitch, roll) makes the matrix rotation in order Z, Y, X.

so to make it right and clear you can:

Matrix3 BuildMatrix3(Point3 pos, float rotx, float roty, float rotz, Point3 scale = Point3(1,1,1))
{
	Matrix3 tm = ScaleMatrix(scale);
	tm.RotateX(rotx);
	tm.RotateY(roty);
	tm.RotateZ(rotz);
	tm.Translate(pos);
	return tm;
}

or

Matrix3 BuildMatrix3(Point3 pos, float rotx, float roty, float rotz, Point3 scale = Point3(1,1,1))
{
	Quat quat;
	quat.SetEuler(rotx,roty,rotz);
	Matrix3 tm;
	tm.SetRotate(quat);
	tm.PreScale(scale);
	tm.Translate(pos);
	return tm;
} 

That did the trick, thanks for the help!
Shortened down my code a lot.

I really appreciate the input, I hate getting stuck on things like this.

Thanks denisT , I like that last function, very clean and easy to use, thanks for sharing it.

this is not actually correct. setting matrix rotation from three floats (yaw, pitch, roll) makes the matrix rotation in order Z, Y, X.

unless you want that order and it was just shorthand for OP original post.

as i can see the original question is not about how to make a matrix using yaw, pitch, and roll.

I’m having a similar issue, also on the SDK… I cant for the love of what’s great replicate this:

--Setting a node's rotation relative to world space without --messing with its position:
fn setNodeWorldRotation theNode theRot =
(
in coordsys (transmatrix theNode.transform.pos)
theNode.rotation = theRot
)
 
setNodeWorldRotation $ (eulerangles 45 45 0)

This is the best I can do for now, but rotation is not working the same way

            IINode oNode = idvServer.inface.GetSelNode(0);
            
            IMatrix3 oMatrix = oNode.GetNodeTM(idvServer.inface.Time, null);

            oMatrix.SetRotate(yaw, pitch, roll);

            oMatrix.Translate(oNode.GetNodeTM(idvServer.inface.Time, null).Trans);

            oNode.SetNodeTM(idvServer.inface.Time, oMatrix);

Help

there’s a hint when your original mxs function can be rewritten as

fn setNodeWorldRotation theNode theRot =
(
	theNode.transform = (inverse (theRot as matrix3)) *  theNode.transform;
)

try something like this

void localEulerRotation(INode* node, Point3& euler)
 {
 	TimeValue t = GetCOREInterface()->GetTime();
 	Matrix3 nodeTM = node->GetObjectTM(t);
 	Matrix3 rotTM;
 	EulerToMatrix(euler,rotTM,EULERTYPE_XYZ);
 	nodeTM = Inverse(rotTM) * nodeTM;
 	node->SetNodeTM(t,nodeTM); 
 }

Thanks for the follow up, based you your previous comment I was able to make it work just by inverting the matrix before translating it. Still have no idea why it works how it works but… it works! It was actually one of the things I missed doing, inverting the matrix, most of the times this TM stuff is still magic to me!

Thanks again and here’s the code that worked out for me (I’m working in radians btw)

IMatrix3 oMatrix = oNode.GetNodeTM(idvServer.inface.Time, null);
            
            oMatrix.SetRotate(yaw, pitch, roll);
            oMatrix.Invert();            
            oMatrix.Translate(oNode.GetNodeTM(idvServer.inface.Time, null).Trans);            

            oNode.SetNodeTM(idvServer.inface.Time, oMatrix);
Page 1 / 2