Successive 3D rotations

55 views
Skip to first unread message

kumo...@gmail.com

unread,
Oct 29, 2016, 7:27:57 AM10/29/16
to Kivy users support
Hi all,

I hope I didn't miss this question while browsing the forum. Anyway, I didn't find a solution to my problem yet and although I'm a newbie in OpenGL and Kivy, this seems somehow nontrivial to me. But here's the background:
I'm currently trying to build a molecular viewer, i.e. I just attach some spheres and cylinders to 3D coordinates.
I have been basing my work on nskrypnik's nice work: https://github.com/nskrypnik/kivy3
This worked quite well for a start, but I am having problems with the rotation. Since in his code every Mesh has Rotations added to an instructiongroup for every axis, I was basically grouping all the instructions into one object, translated it to the origin and converted the mouse movement/touch to a change in angle around the axes. This works quite well, except for the fact that one of the two rotations I use are of course dependent on the first, i.e. the rotation around the x-axis is actually around the z-axis, if I rotate 90° around the y-axis first. This is actually obvious and can be circumvented if I rotate around a common axis afaik (and as far as I tried).
But then I don't know how to multiply rotations since the Rotation instructions do not seem to feature the same methods as matrices.
I also tried storing matrices for rotation and multiplying the modelview_matrix. This led to similar behaviour however, with added numerical problems it seemed.
Another option was to just move the camera and rotate by the look_at() method. That raised other issues again.

So, in the end I could not get rid of the dependence of rotation on previous rotations and I wonder if there is any official mechanism to achieve that. Any hint in that direction is highly appreciated :).

Kumo

Alexander Taylor

unread,
Oct 29, 2016, 7:55:07 AM10/29/16
to Kivy users support
I'm not quite clear what you're trying to do here. Multiplying rotation matrices should be fine, but the problem is that the matrices you generate use the wrong reference frame because they don't account for previous rotations?

If this is all about implementing a Camera system, you may find it useful to check out something like Vispy to see how mouse movement can be translated to camera movement in different ways.

kumo...@gmail.com

unread,
Oct 29, 2016, 5:09:30 PM10/29/16
to Kivy users support
Yes, exactly, at least that's the way it looks. It's obvious with the method of adding Rotate-Instructions for every principal axis and just updating the angles. But my aim is to always rotate the view in the same way, i.e. around the x- and y-axis with both in the screen plane.

Currently, however, I am using the method of rotating the modelview matrix, which works about as well. It works roughly as follows:
I) At the beginning, the modelview is set up using the look_at method.
        m = Matrix()
        pos
= self._position * -1
        m
= m.look_at(pos[0], pos[1], pos[2], v[0], v[1], v[2],
                     
self.up[0], self.up[1], self.up[2])
       
self.modelview_matrix = m
(This is an excerpt out of nskrypnik's code.)
II) For rotation the current modelview matrix is rotated:
a) Back up old MV
  def on_touch_down(self, touch):
   
if self.collide_point(*touch.pos):
       
self.touch_start_pos = touch.pos
       
self.old_mv = self.camera.modelview_matrix
        touch
.grab(self)
       
return True
b) Calculate current rotation
  def on_touch_move(self, touch):
   
if touch.grab_current is self:
        dx
= touch.pos[0] - self.touch_start_pos[0]
        dy
= touch.pos[1] - self.touch_start_pos[1]
        r
= sqrt(power(dx, 2) + power(dy, 2))
       
self.rotmat.identity()
       
self.rotmat.rotate(float(r)*0.02, dy/r, dx/r, 0.0)
       
self.camera.modelview_matrix = self.old_mv.multiply(self.rotmat)
       
self.camera.update()
       
return True
c) Save current view
  def on_touch_up(self, touch):
   
if touch.grab_current is self:
       
self.touch_start_pos = None
       
self.old_mv = self.camera.modelview_matrix
        touch
.ungrab(self)
       
return True
But as I said, I still get the same effect as before.

Also, this approach seems un-kivyish to me, since there are the Rotate-Instructions for this. Thus my question also aims at the right way (read: most/resonably efficient) to do this. Since I just saw instructions can also be inserted at any index, my next try will be adding single Rotate-Instructions to the instruction group for every rotation. But isn't this going to cost much memory, when many rotations are done?

Thank you for the hint with vispy, I will definitely have a look.

kumo...@gmail.com

unread,
Oct 29, 2016, 5:40:33 PM10/29/16
to Kivy users support
Funnily enough, the approach with adding a Rotate-Instruction per successive rotation seems to work as expected. Still the question remains, if that is going to pose a memory problem at some point.
And I am a bit at a loss why this is method is such a difference to the one I posted, for example.
Reply all
Reply to author
Forward
0 new messages