Rotate game object in collection to absolute north (SOLVED)

I am trying to rotate a game object to absolute north so that a particlefx emitter inside of it always will send particles in the same direction.

I have seen that there is something calle go.get_world_rotation("#id"), this gives me a Quat indicating the absolute rotating compared to the world.

Now, where do I go from here? I have tried using some simple vector math to get the angle and use the vmath.quat_rotation_z, but to no success. Maybe someone have solved this type of thing before, and could help me out?

Hi. With the help of collective hive mind that is the Defold engine devs I came to the following solution that should work:

function update(self, dt)
	msg.post(".", "update_rotation")
end

function on_message(self, message_id, message, sender)
	if message_id == hash("update_rotation") then
		local quat_to_north = vmath.quat_rotation_z(math.rad(0)) -- the rotation around z to rotate to due north
		local parent_quat = go.get_world_rotation("parent") -- the parents world rotation
		go.set_rotation(vmath.conj(parent_quat) * quat_to_north) -- inverse parent rotation * rotation to north = local rotation
	end
end

The msg.post() in update might look strange but since we need the world rotation of the parent we must wait until all objects have had their positions updated before doing any calculations.

Thanks for your feedback, but this appears to spin out of control and end up as a nan after a short while. I have tried normalizing the quat, but that does not seem to do the trick as the angle keeps changing back and forth. I have tried a whole lot of possible solutions like math.acos on the w part of a dot-product between what you describe above. No luch on any of my attempts.

My vector-foo is apparently too weak :frowning: Who would have know that such a simple sounding problem would cause this much trouble?

I’ve added my code and live demo. My demo uses a root game object that rotates based on mouse movement, a middle game object that constantly rotates around the root object and finally a child game object that is fixed due north regardless of the rotation of it’s parent or the root.

SOURCE: https://github.com/britzl/publicexamples/tree/master/examples/fixed_rotation
HTML5: http://britzl.github.io/publicexamples/fixed_rotation/index.html

4 Likes

Thanks a lot! Great example!

Can I somehow mark this as the solution?

Sure, just add “(SOLVED)” to your topic title!

Hi, Im really new to this engine, I only started a week ago and looking at the source I managed to put it into my game with no problem but where can I find the description of what each funtions do here:

local to = go.get_world_position()
local from = **vmath.vector3(action.x, action.y, 0)**
local angle = math.atan2(to.x - from.x, from.y - to.y)
local quat = vmath.quat_rotation_z(angle)
go.set_rotation(quat)

like for example what is vmath.vector3() actually doing?

function on_input(self, action_id, action) -- script function
  local to = go.get_world_position() -- 1
  local from = vmath.vector3(action.x, action.y, 0) -- 2
  local angle = math.atan2(to.x - from.x, from.y - to.y) -- 3
  local quat = vmath.quat_rotation_z(angle) -- 4
  go.set_rotation(quat) -- 5
end

1.

This gets the world position of the game object the script is attached to.
go.get_position get the local position of an object, meaning if its parent have been moved it will not report that.

2.

To understand what is happening here we first need to understand what the on_input does. on_input is a defold standard function that defold run everytime you provide any type of input, be it touch/mouse or keyboard clicks.

action_id holds the “name” of the input as defined in your input_bindings. We do do not check against that here, so it isn’t important for this example.

The action variable holds a table consisting of values that are important to you when handling input, such as where on the screen the user is interaction (action.x and action.y).

Now for what it actually does, it creates a new vector with 3 axis (commonly refered to as x, y and z). Here x, y and z are set on creation, the values for x and y is used from the action table. That means that the local from variable will be set to where the user is touching.

3.

This get us the angle in radians using the arctan. It will gives us the angle given the ratio of the supplied arguments.

4.

We use the angle and convert it to a quaternion, they are used for rotations because Euler angles (“common angles”) are prone to gimbal locks and such issues.

5.

We now set the rotation of the game object the script is attached to.

4 Likes