Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Problem with rotation around point with matrices

    Scheduled Pinned Locked Moved PYTHON Development
    2 Posts 0 Posters 302 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H Offline
      Helper
      last edited by

      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!

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        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://developers.maxon.net/forum/topic/6863/7678_rotation-of-a-camera-around-an-object

        1 Reply Last reply Reply Quote 0
        • First post
          Last post