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