Problem with rotation around point with matrices



  • On 11/01/2013 at 07:36, xxxxxxxx wrote:

    Hi together!

    I have a problem regarding the simple rotation of a camera around a cube. This is just a testcase, so I kept it simple. The cube is in offset (0,0,1000), the camera is in (0,0,0). I want to rotate the camera around the center of the cube with the help of matrix algebra.

    According to my knowledge, I have to separate the whole rotation in three steps. First translate the camera to the cube, rotate the camera, finally retranslate the camera. To get a matrix which does all that, I calculate this: [M] = [T]^-1 * [R] * [T]
    C4D delievers functions to calculate the rotation and the translation matrices, which work just fine. I have to calculate [M] by myself, but this is not a big problem.
    To finally rotate my camera I simply have to multiply [M] with the GetMg() of the camera.
    Tell me, if I'm wrong in my approach.

    So here's the code for the rotation:

    def RotAroundPoint(op = c4d.BaseObject, rotPoint = c4d.Vector, H = float(), P = float(), B = float()) :  
      hpb = c4d.Vector(Rad(H), Rad(P), Rad(B))  
      rotMat = c4d.utils.HPBToMatrix(hpb)  
      print 'RotMat: {0}'.format(rotMat)  
       
      moveVec = rotPoint - op.GetMg().off  
      print 'moveVec: {0}'.format(moveVec)  
      moveMat = c4d.utils.MatrixMove(moveVec)  
      print 'moveMat: {0}'.format(moveMat)   
       
      mulRotMoveMat = rotMat  
      mulRotMoveMat = mulRotMoveMat.__rmul__(moveMat)  
      print 'mulRotMoveMat: {0}'.format(mulRotMoveMat)  
       
      complRotMoveMat = moveMat.__invert__()  
      print 'MoveMatInv: {0}'.format(complRotMoveMat)  
      complRotMoveMat = complRotMoveMat.__rmul__(mulRotMoveMat)  
      print 'complRotMoveMat: {0}'.format(complRotMoveMat)  
       
      rotMat = op.GetMg() * complRotMoveMat  
       
      op.SetMg(rotMat)  
       
      distVec = rotPoint - op.GetMg().off   
      print 'Distance: {0}'.format(distVec.GetLength())  
      c4d.EventAdd()  
    

    The printlines are just for debugging, as you'll see later ;)

    The function works, but only once. I want to call the function repeatedly and the first calculation is always correct. But each call after that returns a (partially) incorrect result.

    Here is my function call:

         print 'CamMg before Rotation: {0}'.format(camMg)  
      for i in range(8) :  
          print '---------------'  
          print 'i: {0}'.format(i)          
          RotAroundPoint(cam, cube.GetMg().off, 45, 0, 0)  
          print 'CamMg: {0}'.format(cam.GetMg())  
    

    You see, the camera should do a complete circle in 45° steps in a steady distance of 1000 to the cube. But I get the following console log:

    CamMg before Rotation: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (0, 0, 0))  
    ---------------  
    i: 0  
    RotMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (0, 0, 0))  
    moveVec: Vector(0, 0, 1000)  
    moveMat: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (0, 0, 1000))  
    mulRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (0, 0, 1000))  
    MoveMatInv: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (0, 0, -1000))  
    complRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (707.107, 0, 292.893))  
    Distance: 1000.0  
    CamMg: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (707.107, 0, 292.893))  
    ---------------  
    i: 1  
    RotMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (0, 0, 0))  
    moveVec: Vector(-707.107, 0, 707.107)  
    moveMat: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (-707.107, 0, 707.107))  
    mulRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (-707.107, 0, 707.107))  
    MoveMatInv: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (707.107, 0, -707.107))  
    complRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (292.893, 0, 707.107))  
    Distance: 414.213562373  
    CamMg: Matrix(v1: (0, 0, 1); v2: (0, 1, 0); v3: (-1, 0, 0); off: (414.214, 0, 1000))  
    ---------------  
    i: 2  
    RotMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (0, 0, 0))  
    moveVec: Vector(-414.214, 0, 0)  
    moveMat: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (-414.214, 0, 0))  
    mulRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (-414.214, 0, 0))  
    MoveMatInv: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (414.214, 0, 0))  
    complRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (-121.32, 0, 292.893))  
    Distance: 171.572875254  
    CamMg: Matrix(v1: (-0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, -0.707); off: (121.32, 0, 878.68))  
    ---------------  
    i: 3  
    RotMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (0, 0, 0))  
    moveVec: Vector(-121.32, 0, 121.32)  
    moveMat: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (-121.32, 0, 121.32))  
    mulRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (-121.32, 0, 121.32))  
    MoveMatInv: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (121.32, 0, -121.32))  
    complRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (50.253, 0, 121.32))  
    Distance: 171.572875254  
    CamMg: Matrix(v1: (-1, 0, 0); v2: (0, 1, 0); v3: (0, 0, -1); off: (0, 0, 828.427))  
    ---------------  
    i: 4  
    RotMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (0, 0, 0))  
    moveVec: Vector(0, 0, 171.573)  
    moveMat: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (0, 0, 171.573))  
    mulRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (0, 0, 171.573))  
    MoveMatInv: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (0, 0, -171.573))  
    complRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (121.32, 0, 50.253))  
    Distance: 252.834208384  
    CamMg: Matrix(v1: (-0.707, 0, -0.707); v2: (0, 1, 0); v3: (0.707, 0, -0.707); off: (-121.32, 0, 778.175))  
    ---------------  
    i: 5  
    RotMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (0, 0, 0))  
    moveVec: Vector(121.32, 0, 221.825)  
    moveMat: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (121.32, 0, 221.825))  
    mulRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (121.32, 0, 221.825))  
    MoveMatInv: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (-121.32, 0, -221.825))  
    complRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (192.388, 0, -20.815))  
    Distance: 437.921694812  
    CamMg: Matrix(v1: (0, 0, -1); v2: (0, 1, 0); v3: (1, 0, 0); off: (-272.078, 0, 656.854))  
    ---------------  
    i: 6  
    RotMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (0, 0, 0))  
    moveVec: Vector(272.078, 0, 343.146)  
    moveMat: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (272.078, 0, 343.146))  
    mulRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (272.078, 0, 343.146))  
    MoveMatInv: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (-272.078, 0, -343.146))  
    complRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (322.33, 0, -91.883))  
    Distance: 758.502625151  
    CamMg: Matrix(v1: (0.707, 0, -0.707); v2: (0, 1, 0); v3: (0.707, 0, 0.707); off: (-363.961, 0, 334.524))  
    ---------------  
    i: 7  
    RotMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (0, 0, 0))  
    moveVec: Vector(363.961, 0, 665.476)  
    moveMat: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (363.961, 0, 665.476))  
    mulRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (363.961, 0, 665.476))  
    MoveMatInv: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (-363.961, 0, -665.476))  
    complRotMoveMat: Matrix(v1: (0.707, 0, 0.707); v2: (0, 1, 0); v3: (-0.707, 0, 0.707); off: (577.164, 0, -62.446))  
    Distance: 1117.74900609  
    CamMg: Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (0, 0, -117.749))  
    

    As you can see (or recalculate) the first call is correct. The last call should result again in a camera offset of (0,0,0). You can see, that the x- and y-axis is calulated correct, but the z-axis differs. The problem is definitly the multiplication of rotMat with cam.GetMg(). When I add the following line to my function, the results are correct all over the calls:

    rotMat = op.GetMg() * complRotMoveMat  
    rotMat.off = op.GetMg().off + complRotMoveMat.off #the inserted line  
    op.SetMg(rotMat)  
    

    Where I get confused is: Why does it work on the first call? Do I really have to add this line? This makes completely no sense to me, because there is definitly a calculation going on in the off-Vektor when I multiply it with rotMat. So what does C4D calculate there? Please help me to clear my confusion!

    Thanks in advance!



  • On 15/01/2013 at 04:41, xxxxxxxx wrote:

    The problem changed a bit due to further research on that topic, so I opened a new thread for this: https://plugincafe.maxon.net/topic/6863/7678_rotation-of-a-camera-around-an-object


Log in to reply