How to rotate object around a dynamic pivot point.

During run-time, how can I rotate an object around a dynamic pivot point?

I know the objects position and the pivot position.

The code below is what I have so far. I think I’m in the right direction but it’s not right yet.

I’m open to BGE specific or general mathematical solutions as I will likely need to do this in C++ also later on.

def rotate_world(obj, pivot_object):
    
    pivot_position = (pivot_object.worldPosition)
    
    vec_diff = obj.worldPosition - pivot_position 
    
    obj.worldPosition = pivot_position
    obj.applyRotation((0.0,90.0,0.0), True)
    
    obj.worldPosition = vec_diff + obj.rotation

Actually, I think I have an easier solution.

Just have a empty that is moved to desired point, of which world objects are parented too. I then just rotate the parent empty. That should work a bit better.

EDIT: Actually no, that won’t work, they will keep moving when the pivot is moved. arg

I wonder how to rotate a vector?

Like

PositionZero = object1.worldPosition+(object1.worldOreintation*Vector)

Will give you a point in space relative to another object, but how do you rotate that vector using a local axis of object 1? Of course you can rotate object 1,

But I wonder how to rotate the vector by a point, without rotating the object1.

I’m watching some matrix maths for game programming videos. I feared I might be going down this route. :confused:

Rotations, Vectors and linV and angV kinda eventually demand you learn all about math, but don’t worry, math with application is much easier to learn then absrtact paper work.

I think teaching kids to make games would do more good then trying to push abstract paper math…

You’ve almost got the idea with your code, but here’s how you should use vec_diff:


import mathutils
import math

def rotateAroundPivot(obj, pivot, rotation_degrees):
    vec_diff = obj.worldPosition - pivot.worldPosition
    vec_diff.rotate(mathutils.Euler((0.0, math.radians(rotation_degrees), 0.0), 'XYZ'))
    obj.worldPosition = vec_diff + pivot.worldPosition

You are correct in how you get the vec_diff, you just need to rotate that vector, then set the object’s world position to be that vector (plus the pivot’s world position, since vectors are based at the origin). I tested this out myself and it does the trick.

If you want to rotate the obj around it’s own center as well (and not just have it move around the pivot), just don’t forget to add the line:

obj.applyRotation((0.0, rotation_degrees, 0.0), True)

See the attached .blend file for a running example.

Attachments

dynamic_pivot.blend (425 KB)

Awesome! Thank you!! :smiley:

This is much simpler if you use mathutils.matrix.
It’s also more flexible as you can use lerp to transition smoothly from one matrix to another, for example a spaceship going in to orbit around a planet. Or a small drone which orbits the player but can fly off and pick up loot…

With matrix, lerp and smoothstep you can do some pretty awesome simple animations without rigging.

Care to provide a simple example? (:D)

I thought that might be the case.

I don’t suppose you know some good maths for games programming tutorials? I can’t imagine there are any specific to BGE it’self.
My book on DirectX 9.0 does have a maths section covering basic trigonometry, vectors, matrices etc, which I’ve gone over a couple of times, it just doesn’t digest though. It’s not the most friendliest of text’s ever.

You don’t really need to know all the math in order to use matrices, since we have the wonderful mathutils.Matrix

All the toolsyou need are there, just have to use them in the right way.

Here’s a little example of using mathutils.matrix to rotate one object around another, or around any dynamic point:
planets.blend (571 KB)

Comment out line 74 and use line 75, and you’ll see the red planet continue to go through its motions, even though they are not based on a current relation to any other object other than the offsets you saved during initiation.

For reference:
rotation * offset:
object rotates around the original point at the length of the offset

offset * rotation:
object rotates in place, at its new origin which is the offset

If we want the planets to rotate as well as orbit we would just create a new rotation matrix and put it at the end of the multiplication chain:

green_spin = mathutils.Matrix.Rotation(math.radians(-1.4 * own['timer']), 4, 'Z')       
                                
own['green_planet'].worldTransform = green_mat * green_rotate * green_offset * green_spin

If you ever have trouble with getting the order right, you can just try different combinations and see the result instantly by pressing play.