123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- #include <cmath>
- #include <iostream>
- #include "client/math/Quaternion.h"
- Quaternion::Quaternion() : xyz(0.0f, 0.0f, 0.0f), w(1.0f) {
- }
- Quaternion::Quaternion(float x, float y, float z, float w) : xyz(x, y, z), w(w) {
- }
- Quaternion::Quaternion(const Vector& axis, float angle) {
- Vector unit(axis);
- xyz.set(unit.normalize());
- float sin;
- sincosf(angle * (M_PI / 360.0f), &sin, &w);
- xyz.mul(sin);
- }
- Quaternion Quaternion::lerp(float f, const Quaternion& other) const {
- return interpolate(1 - f, f, other).normalize();
- }
- Quaternion Quaternion::slerp(float f, const Quaternion& other) const {
- float angle = xyz.dot(other.xyz) + w * other.w;
- if(angle >= 1.0f) {
- return *this;
- } else if(angle < -1.0f) {
- angle = -1.0f;
- }
- float arccos = acosf(angle);
- float sin = 1.0f / sinf(arccos);
- return interpolate(sinf((1 - f) * arccos) * sin, sinf(f * arccos) * sin, other);
- }
- Quaternion Quaternion::interpolate(float a, float b, const Quaternion& other) const {
- Vector interpolated(xyz);
- interpolated.mul(a).addMul(other.xyz, b);
- return Quaternion(interpolated.getX(), interpolated.getY(), interpolated.getZ(), w * a + other.w * b);
- }
- Quaternion Quaternion::squad(float f, const Quaternion& prev, const Quaternion& next, const Quaternion& nextNext) const {
- float diff = Vector(xyz).sub(next.xyz).squareLength() + (w - next.w) * (w - next.w);
- if(diff < 0.0001f) {
- return *this;
- }
- Quaternion s1 = squadControl(prev, next);
- Quaternion s2 = next.squadControl(*this, nextNext);
- return slerp(f, next).slerp(2.0f * f * (1.0f - f), s1.slerp(f, s2));
- }
- Quaternion Quaternion::squadControl(const Quaternion& prev, const Quaternion& next) const {
- Quaternion conjugate(*this);
- conjugate.conjugate();
- Quaternion s1(next);
- s1.mul(conjugate).log().add(Quaternion(prev).mul(conjugate).log()).mul(-0.25f).exp().mul(*this);
- return s1;
- }
- Quaternion& Quaternion::normalize() {
- float f = 1.0f / sqrtf(xyz.dot(xyz) + w * w);
- xyz.mul(f);
- w *= f;
- return *this;
- }
- Matrix Quaternion::toMatrix() const {
- float x = xyz.getX();
- float y = xyz.getY();
- float z = xyz.getZ();
- float x2 = 2 * x * x;
- float y2 = 2 * y * y;
- float z2 = 2 * z * z;
- float xy = 2 * x * y;
- float xz = 2 * x * z;
- float xw = 2 * x * w;
- float zw = 2 * z * w;
- float yz = 2 * y * z;
- float yw = 2 * y * w;
- Matrix m;
- m.set(0, 1 - y2 - z2).set(1, xy - zw).set(2, xz + yw);
- m.set(4, xy + zw).set(5, 1 - x2 - z2).set(6, yz - xw);
- m.set(8, xz - yw).set(9, yz + xw).set(10, 1 - x2 - y2);
- return m;
- }
- Quaternion& Quaternion::mul(const Quaternion& other) {
- Vector v;
- v.addMul(other.xyz, w).addMul(xyz, other.w).add(Vector(xyz).cross(other.xyz));
- w = w * other.w - xyz.dot(other.xyz);
- xyz.set(v);
- return *this;
- }
- Quaternion& Quaternion::mul(float f) {
- xyz.mul(f);
- w *= f;
- return *this;
- }
- Quaternion& Quaternion::add(const Quaternion& other) {
- xyz.add(other.xyz);
- w += other.w;
- return *this;
- }
- Quaternion& Quaternion::conjugate() {
- xyz.setInverse(xyz);
- return *this;
- }
- Quaternion& Quaternion::log() {
- // general log
- //float length = sqrtf(xyz.dot(xyz) + w * w);
- //float arccos = acos(w / length);
- //w = logf(length);
- //xyz.mul(arccos / xyz.length());
- // optimized use case log
- xyz.normalize().mul(acos(w));
- w = 0.0f;
- return *this;
- }
- Quaternion& Quaternion::exp() {
- // general exp
- //float expw = expf(w);
- //float length = xyz.length();
- //w = expw * cosf(length);
- //xyz.mul((expw * sin(length)) / length);
- // optimized use case exp
- float length = xyz.length();
- w = cosf(length);
- xyz.mul((sin(length)) / length);
- return *this;
- }
|