Solved MatrixToHPB Negative values

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.

import c4d
from c4d.modules import mograph as mo

def main():
    #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))
    print marr[0]
    #Conversion shows positive values   Vector(5.76, 0, 0)
    print c4d.utils.MatrixToHPB(marr[0])

if __name__=='__main__':


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

def main():
    # 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)
    print optimalHPB

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).

Best, Riccardo