Class: Bullet3::Quaternion
- Inherits:
-
Object
- Object
- Bullet3::Quaternion
- Defined in:
- lib/bullet3/linear_math/quaternion.rb,
lib/bullet3/linear_math/quaternion.rb
Constant Summary collapse
- EPSILON =
1e-6
Instance Attribute Summary collapse
-
#w ⇒ Object
Returns the value of attribute w.
-
#x ⇒ Object
Returns the value of attribute x.
-
#y ⇒ Object
Returns the value of attribute y.
-
#z ⇒ Object
Returns the value of attribute z.
Class Method Summary collapse
- .coerce(value) ⇒ Object
- .from_axis_angle(axis, angle) ⇒ Object
- .from_euler(roll, pitch, yaw) ⇒ Object
- .identity ⇒ Object
- .try_coerce(value) ⇒ Object
Instance Method Summary collapse
- #*(other) ⇒ Object
- #==(other) ⇒ Object
- #angle ⇒ Object
- #axis ⇒ Object
-
#initialize(x = 0.0, y = 0.0, z = 0.0, w = 1.0) ⇒ Quaternion
constructor
A new instance of Quaternion.
- #inverse ⇒ Object
- #normalized ⇒ Object
- #slerp(other, t) ⇒ Object
- #to_a ⇒ Object
- #to_euler ⇒ Object
- #to_matrix ⇒ Object
Constructor Details
#initialize(x = 0.0, y = 0.0, z = 0.0, w = 1.0) ⇒ Quaternion
Returns a new instance of Quaternion.
37 38 39 40 41 42 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 37 def initialize(x = 0.0, y = 0.0, z = 0.0, w = 1.0) @x = Float(x) @y = Float(y) @z = Float(z) @w = Float(w) end |
Instance Attribute Details
#w ⇒ Object
Returns the value of attribute w.
7 8 9 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 7 def w @w end |
#x ⇒ Object
Returns the value of attribute x.
7 8 9 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 7 def x @x end |
#y ⇒ Object
Returns the value of attribute y.
7 8 9 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 7 def y @y end |
#z ⇒ Object
Returns the value of attribute z.
7 8 9 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 7 def z @z end |
Class Method Details
.coerce(value) ⇒ Object
132 133 134 135 136 137 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 132 def self.coerce(value) coerced = try_coerce(value) return coerced if coerced raise TypeError, "expected Bullet3::Quaternion or a 4-element Array" end |
.from_axis_angle(axis, angle) ⇒ Object
13 14 15 16 17 18 19 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 13 def self.from_axis_angle(axis, angle) axis = Vector3.coerce(axis).normalized half_angle = Float(angle) / 2.0 scale = Math.sin(half_angle) new(axis.x * scale, axis.y * scale, axis.z * scale, Math.cos(half_angle)) end |
.from_euler(roll, pitch, yaw) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 21 def self.from_euler(roll, pitch, yaw) cr = Math.cos(Float(roll) / 2.0) sr = Math.sin(Float(roll) / 2.0) cp = Math.cos(Float(pitch) / 2.0) sp = Math.sin(Float(pitch) / 2.0) cy = Math.cos(Float(yaw) / 2.0) sy = Math.sin(Float(yaw) / 2.0) new( (sr * cp * cy) - (cr * sp * sy), (cr * sp * cy) + (sr * cp * sy), (cr * cp * sy) - (sr * sp * cy), (cr * cp * cy) + (sr * sp * sy) ) end |
.identity ⇒ Object
9 10 11 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 9 def self.identity new(0.0, 0.0, 0.0, 1.0) end |
.try_coerce(value) ⇒ Object
139 140 141 142 143 144 145 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 139 def self.try_coerce(value) return value if value.is_a?(self) return new(*value) if value.respond_to?(:to_ary) && value.to_ary.length == 4 nil end |
Instance Method Details
#*(other) ⇒ Object
44 45 46 47 48 49 50 51 52 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 44 def *(other) other = self.class.coerce(other) self.class.new( (w * other.x) + (x * other.w) + (y * other.z) - (z * other.y), (w * other.y) - (x * other.z) + (y * other.w) + (z * other.x), (w * other.z) + (x * other.y) - (y * other.x) + (z * other.w), (w * other.w) - (x * other.x) - (y * other.y) - (z * other.z) ) end |
#==(other) ⇒ Object
54 55 56 57 58 59 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 54 def ==(other) other = self.class.try_coerce(other) return false unless other to_a.zip(other.to_a).all? { |left, right| (left - right).abs <= EPSILON } end |
#angle ⇒ Object
68 69 70 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 68 def angle 2.0 * Math.acos(w.clamp(-1.0, 1.0)) end |
#axis ⇒ Object
72 73 74 75 76 77 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 72 def axis scale = Math.sqrt(1.0 - (w * w)) return Vector3.new(1.0, 0.0, 0.0) if scale <= EPSILON Vector3.new(x / scale, y / scale, z / scale) end |
#inverse ⇒ Object
61 62 63 64 65 66 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 61 def inverse magnitude = length2 raise ZeroDivisionError, "cannot invert a zero-length quaternion" if magnitude <= EPSILON self.class.new(-x / magnitude, -y / magnitude, -z / magnitude, w / magnitude) end |
#normalized ⇒ Object
121 122 123 124 125 126 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 121 def normalized magnitude = Math.sqrt(length2) return self.class.identity if magnitude <= EPSILON self.class.new(x / magnitude, y / magnitude, z / magnitude, w / magnitude) end |
#slerp(other, t) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 79 def slerp(other, t) other = self.class.coerce(other) t = Float(t) cosine = dot(other) if cosine.negative? other = self.class.new(-other.x, -other.y, -other.z, -other.w) cosine = -cosine end return linear_interpolate(other, t).normalized if cosine > 0.9995 theta = Math.acos(cosine.clamp(-1.0, 1.0)) sin_theta = Math.sin(theta) left = Math.sin((1.0 - t) * theta) / sin_theta right = Math.sin(t * theta) / sin_theta self.class.new( (x * left) + (other.x * right), (y * left) + (other.y * right), (z * left) + (other.z * right), (w * left) + (other.w * right) ) end |
#to_a ⇒ Object
128 129 130 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 128 def to_a [x, y, z, w] end |
#to_euler ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 104 def to_euler roll = Math.atan2(2.0 * ((w * x) + (y * z)), 1.0 - (2.0 * ((x * x) + (y * y)))) pitch_sin = 2.0 * ((w * y) - (z * x)) pitch = if pitch_sin.abs >= 1.0 pitch_sin.negative? ? -Math::PI / 2.0 : Math::PI / 2.0 else Math.asin(pitch_sin) end yaw = Math.atan2(2.0 * ((w * z) + (x * y)), 1.0 - (2.0 * ((y * y) + (z * z)))) [roll, pitch, yaw] end |
#to_matrix ⇒ Object
117 118 119 |
# File 'lib/bullet3/linear_math/quaternion.rb', line 117 def to_matrix Matrix3x3.from_quaternion(self) end |