3d – The way to rotate spaceship quaternion to face goal path with fixed angular velocity?

3d – The way to rotate spaceship quaternion to face goal path with fixed angular velocity?

[ad_1]

I bought it. I used to be almost there for ages, and flipping the multiplication on the ultimate assertion (rotationToApply * orientation, not orientation * rotationToApply) mounted it. Apparently whether or not you might be working in an absolute body of reference (like right here) you set the second rotation to use on the left aspect of the multiplication, however in an object’s personal body of reference (like when making use of angular velocity) you set it on the fitting. I do not perceive any greater than that but.

I’ve some Lua code that does all the things right here (~= is “not equal to”, and situation and a or b is Lua’s equal to the ternary operator):

if state.participant.place ~= entity.place then
    native entityToTargetDirection = vec3.normalise(state.participant.place - entity.place)
    native curDirection = vec3.rotate(consts.forwardVector, entity.orientation)

    native crossResult = vec3.cross(curDirection, entityToTargetDirection)
    native rotationRequiredAxis = vec3.normalise(
        crossResult == vec3() -- This implies the 2 vectors are parallel, so...
        and vec3.rotate(vec3(0, 1, 0), entity.orientation) -- ...decide an arbitrary path (yaw proper on this case)
        or crossResult
    )

    native dotClamped = math.max(-1, math.min(1, -- Clamping as a result of it will typically be outdoors of [-1, 1] and due to this fact trigger acos to return nan
        vec3.dot(curDirection, entityToTargetDirection)
    ))
    native rotationRequiredAngle = math.acos(dotClamped)

    native maxAngle = entity.maxAngularSpeed * dt
    native cappedAngle = math.min(maxAngle, math.max(-maxAngle, rotationRequiredAngle))

    native rotationAxisAngle = rotationRequiredAxis * cappedAngle

    -- if math.abs(getShortestAngleDifference(0, rotationRequiredAngle)) > consts.targettingAngleDistanceThreshold then
        entity.orientation = quat.normalise(quat.fromAxisAngle(rotationAxisAngle) * entity.orientation) -- Normalised to forestall numeric drift
    -- finish
finish

Convert to your use case as required. I will refactor it to face arbitrary goal factors.

The rotate perform’s supply code from my maths library (new creates a vec3 on this context):

native perform rotate(v, q)
    native qxyz = new(q.x, q.y, q.z)
    native uv = cross(qxyz, v)
    native uuv = cross(qxyz, uv)
    return v + ((uv * q.w) + uuv) * 2
finish

And getShortestAngleDifference, in case you select to make the entity cease rotating when inside a threshold (I am positive the maths will be simplified contemplating how it’s used within the code above):

native perform getShortestAngleDifference(a, b)
    -- a to b is b - a
    return (b - a + consts.tau / 2) % consts.tau - consts.tau / 2
finish

Additionally fromAxisAngle from my maths library (# is size, rawnew creates a quaternion (so as x, y, z, w)):

native perform fromAxisAngle(v)
    native angle = #v
    if angle == 0 then return rawnew(0, 0, 0, 1) finish
    native axis = v / angle
    native s, c = sin(angle / 2), cos(angle / 2)
    return normalise(new(axis.x * s, axis.y * s, axis.z * s, c))
finish

[ad_2]

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply