Convinced euler angles is buggy

the following program sets the plank’s rotation to gx,gy,gz on every draw cycle. every 0.1 second, it sets gx,gy,gz to the plank’s rotation’s angles, which should be the angles originally put in. but the plank rotates around. i conclude that angles is not returning the proper values.

viewer.mode=STANDARD

function setup()
    time = 0
    max = 0.1
    scene = craft.scene()
    scene.camera.position=vec3(0,1,-4)
    
    ground = scene:entity()
    ground.model = craft.model.cube(vec3(1,.2,1))
    ground.material = craft.material(asset.builtin.Materials.Specular)
    ground.material.map = readImage(asset.builtin.Surfaces.Desert_Cliff_Roughness)
    ground.position = vec3(1,1,1)
    gx,gy,gz = 45,45,45
    ground.rotation = quat.eulerAngles(gx,gy,gz)
   
    
end

function update(dt)
    time = time + dt
    if time >= max then
        time = 0
        gx,gy,gz = ground.rotation:angles():unpack() 
        -- if angles worked, this would have no effect
    end
    ground.rotation=quat.eulerAngles(gx,gy,gz)
    scene:update(dt)
end

function draw()
    update(DeltaTime)
    scene:draw()
end

If you print the values of ground.rotation at the end of setup(), it prints 6 digits past the decimal point. That reminds me of 32 bit math code. I wonder if the math isn’t precise enough.

Yeah you’re right, the returned values of angles for the given 45, 45, 45 is like 59, 8, 30 … doesn’t make any sense

My first thought was, oh just normalize the quat, but normalize doesn’t seem to fix it

I tried with using all 0 and it returns all 0, tried with just gz set at 45 an it returns 44.99…, tried with gz and gy at 45 and I get 35, 30, 54

So angles are effecting each other at values higher than 0 and normalize doesn’t seem to do anything


gx,gy,gz = 0, 45, 45
  q = quat.eulerAngles(gx,gy,gz)
  q = q:normalized()
  gx,gy,gz = q:angles():unpack()
  print(gx, gy, gz)

this change to the code above thrashes the plank, and should have no effect:

ground.rotation=quat.eulerAngles(ground.rotation:angles():unpack())

@skar we can’t expect to get the input angles back, as quat rotations choose the fastest rotation to the desired angle, but they should be equivalent, and stable.

I see, so I tested out what happened if I used those returned values from angles for the given 45, 45, 45 and it’sa completely different position and also returned new values
“66DF…” screenshot is using 45, 45, 45
“1EE2…” is using 59.63, 8.42, 30.36

You already know this since you have it happening in the update loop, but maybe it’s easier for @Simeon to see just one example

simpler example. you’d expect 90,90,0 and the same quat to repeat. the bug is in quat.

            local x,y,z,q
            x,y,z = 90,90,0
            print("x ",x, " y ", y, " z ",z)
            q = quat.eulerAngles(x,y,z)
            print(q)
            x,y,z = q:angles():unpack()
            print("x ",x, " y ", y, " z ",z)
            q = quat.eulerAngles(x,y,z)
            print(q)
            x,y,z = q:angles():unpack()
            print("x ",x, " y ", y, " z ",z)
            q = quat.eulerAngles(x,y,z)
            print(q)