Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Using a simpler version of quaternion rotation of a vector (and renames) #1634

@rcoreilly

Description

@rcoreilly

Describe the bug

This is just to document a change made in the pdf branch of math32/quaternion.go to use a simpler and possibly faster version of quaternion rotation. The method was moved from vector3 MulQuat to MulVector as a method on Quat, along with adding an inverse version as well.

This has the change in the pdf branch: 95b6a48

How to reproduce

Pasting the set of different versions from different sources below. Not sure where the original came from. Interestingly, all produce different results on non-normalized quaternions. Test added.

Example code

// MulVector applies the rotation encoded in the quaternion to the [Vector3].
func (q Quat) MulVector(v Vector3) Vector3 {
	// note: these each produce the same results when q is normalized
	// but produce very different results for non-normalized,
	// which is presumably not well defined anyway.
	// According to IsaacLab, the cross-product version is faster,
	// but the old version that it replaced is pretty weird.
	// In any case, it is much simpler!
	// https://github.com/isaac-sim/IsaacLab/issues/1711
	// https://github.com/isaac-sim/IsaacLab/pull/2129/files

	// original version:
	// // calculate quat * vector
	// ix := q.W*v.X + q.Y*v.Z - q.Z*v.Y
	// iy := q.W*v.Y + q.Z*v.X - q.X*v.Z
	// iz := q.W*v.Z + q.X*v.Y - q.Y*v.X
	// iw := -q.X*v.X - q.Y*v.Y - q.Z*v.Z
	// // calculate result * inverse quat
	// return Vec3(ix*q.W+iw*-q.X+iy*-q.Z-iz*-q.Y,
	// 	iy*q.W+iw*-q.Y+iz*-q.X-ix*-q.Z,
	// 	iz*q.W+iw*-q.Z+ix*-q.Y-iy*-q.X)

	// warp version:
	// c := 2*q.W*q.W - 1
	// d := 2 * (q.X*v.X + q.Y*v.Y + q.Z*v.Z)
	// return Vec3(v.X*c+q.X*d+(q.Y*v.Z-q.Z*v.Y)*q.W*2,
	// 	v.Y*c+q.Y*d+(q.Z*v.X-q.X*v.Z)*q.W*2,
	// 	v.Z*c+q.Z*d+(q.X*v.Y-q.Y*v.X)*q.W*2)

	// isaacLab
	xyz := Vec3(q.X, q.Y, q.Z)
	t := xyz.Cross(v).MulScalar(2)
	return v.Add(t.MulScalar(q.W)).Add(xyz.Cross(t))
}

// MulVectorInverse applies the inverse of the rotation encoded in the quaternion
// to the [Vector3].
func (q Quat) MulVectorInverse(v Vector3) Vector3 {
	xyz := Vec3(q.X, q.Y, q.Z)
	t := xyz.Cross(v).MulScalar(2)
	return v.Sub(t.MulScalar(q.W)).Add(xyz.Cross(t))
}

Relevant output

Platform

macOS

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working correctly

    Type

    No type

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions