Hello, I'm trying to get the rotation values of clones but having some trouble with negative rotations. It looks like the code is working as expected for positive values, but if a clone is rotated to a negative value, the MatrixToHPB spits out a positive value.
from c4d.modules import mograph as mo
#Starting object has a rotation value of H = -30 degrees
Export_Manager = doc.SearchObject("Export_Manager")
Obj_1 = Export_Manager[c4d.ID_USERDATA, 9]
MoData = mo.GeGetMoData(Obj_1)
marr = MoData.GetArray(c4d.MODATA_MATRIX)
#Matrix is showing negative values Matrix(v1: (0.866, 0, -0.5); v2: (0, 1, 0); v3: (0.5, 0, 0.866); off: (0, 0, 0))
#Conversion shows positive values Vector(5.76, 0, 0)
Hi @owen, first of all, I wish you a happy new year.
Regarding the issue, I would like to remind you a rotation of 90° is the same as a rotation of -270° you can't distinguish them.
And the matrix for both will be the same one. So if you only get the current matrix, there is no way to "force" a negative value.
Finally note in a 4x4 matrix, the v1, v2, v3 store information about rotation and scaling, for more information please read Matrix Fundamentals.
With that say you can try to use GetOptimalAngle. By filling the original HPB and the returned HPB of MatrixToHPB.
Thanks @m_adam and happy new year!
I should explain some of the use case for this. I have a large array of clones that have some set parameters they must stay in (a cube can have a rotation value between -500 degrees and +1200 degrees and so on). When I'm trying to get the rotation values from the cloned objects the only thing I'm seeing in the SDK is the MatrixToHPB; but like you said because -270 is essentially the same position as +90 both values in the matrix are identical. Do you know if there is a way to get the value in a similar way that .GetAbsRot() works for single objects?
Hi @owen, thanks for following up.
As @m_adam has already pointed out there's actually no difference in the values defininig a matrix representing a rotation on -30, -390, 330 or 690 on a certain axis.
The lifesafer in this case is to use the already mentioned GetOptimalAngle which actually provides you with the HPB vector that would minimize the rotation given the previous HPB and the current HPB.
For the sake of completeness let's assume that at frame 0 H = 0 whilst at frame 1 H = -5.
Running the following code just returns the "expected" HPB vector
# set the lastHPB to the previous frame value (in this case zero)
lastHPB = c4d.Vector(0,0,0)
# retrieve the current rotation order
rotOrder = op.GetRotationOrder()
# convert from matrix to HPB representation
currentHPB = c4d.utils.MatrixToHPB(op.GetMg(), rotOrder)
# get the optimal HPB vector
optimalHPB = c4d.utils.GetOptimalAngle(lastHPB, currentHPB, rotOrder)
Now using this strategy and knowing the HPB of a clone at the previous frame, you are able to obtain a meaningful HPB representing of the matrix describing the rotation at the current frame of a certain clone (or object).