15d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy/*
25d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * Copyright 2013 The Android Open Source Project
35d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy *
45d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
55d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * you may not use this file except in compliance with the License.
65d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * You may obtain a copy of the License at
75d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy *
85d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
95d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy *
105d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * Unless required by applicable law or agreed to in writing, software
115d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
125d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * See the License for the specific language governing permissions and
145d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * limitations under the License.
155d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy */
165d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
171d77b719d51a01cbd6954a048fb64e79d50a950eMathias Agopian#pragma once
185d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
191d77b719d51a01cbd6954a048fb64e79d50a950eMathias Agopian#include <math/half.h>
201d77b719d51a01cbd6954a048fb64e79d50a950eMathias Agopian#include <math/TQuatHelpers.h>
211d77b719d51a01cbd6954a048fb64e79d50a950eMathias Agopian#include <math/vec3.h>
221d77b719d51a01cbd6954a048fb64e79d50a950eMathias Agopian#include <math/vec4.h>
235d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
245d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#include <stdint.h>
255d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#include <sys/types.h>
265d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
275d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#ifndef PURE
285d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#define PURE __attribute__((pure))
295d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#endif
305d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
31caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#pragma clang diagnostic push
32caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
33caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#pragma clang diagnostic ignored "-Wnested-anon-types"
34caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy
355d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guynamespace android {
365d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy// -------------------------------------------------------------------------------------
375d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
385d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guynamespace details {
395d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
405d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytemplate <typename T>
415d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyclass TQuaternion : public TVecAddOperators<TQuaternion, T>,
425d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy                    public TVecUnaryOperators<TQuaternion, T>,
435d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy                    public TVecComparisonOperators<TQuaternion, T>,
445d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy                    public TQuatProductOperators<TQuaternion, T>,
455d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy                    public TQuatFunctions<TQuaternion, T>,
465d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy                    public TQuatDebug<TQuaternion, T> {
475d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guypublic:
485d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    enum no_init { NO_INIT };
495d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    typedef T value_type;
505d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    typedef T& reference;
515d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    typedef T const& const_reference;
525d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    typedef size_t size_type;
535d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
545d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    /*
555d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     * quaternion internals stored as:
565d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     *
575d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     * q = w + xi + yj + zk
585d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     *
595d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     *  q[0] = x;
605d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     *  q[1] = y;
615d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     *  q[2] = z;
625d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     *  q[3] = w;
635d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     *
645d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     */
655d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    union {
665d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        struct { T x, y, z, w; };
675d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        TVec4<T> xyzw;
685d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        TVec3<T> xyz;
695d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        TVec2<T> xy;
705d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    };
715d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
725d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    enum { SIZE = 4 };
735d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    inline constexpr static size_type size() { return SIZE; }
745d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
755d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    // array access
765d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    inline constexpr T const& operator[](size_t i) const {
775d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#if __cplusplus >= 201402L
785d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        // only possible in C++0x14 with constexpr
795d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        assert(i < SIZE);
805d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#endif
815d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return (&x)[i];
825d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
835d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
845d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    inline T& operator[](size_t i) {
855d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        assert(i < SIZE);
865d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return (&x)[i];
875d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
885d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
895d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    // -----------------------------------------------------------------------
905d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    // we want the compiler generated versions for these...
915d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    TQuaternion(const TQuaternion&) = default;
925d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    ~TQuaternion() = default;
935d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    TQuaternion& operator = (const TQuaternion&) = default;
945d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
955d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    // constructors
965d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
975d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    // leaves object uninitialized. use with caution.
985d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    explicit
995d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    constexpr TQuaternion(no_init) : xyzw(TVec4<T>::NO_INIT) {}
1005d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1015d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    // default constructor. sets all values to zero.
1025d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    constexpr TQuaternion() : x(0), y(0), z(0), w(0) { }
1035d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1045d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    // handles implicit conversion to a tvec4. must not be explicit.
1055d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    template<typename A>
1065d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    constexpr TQuaternion(A w) : x(0), y(0), z(0), w(w) {
1075d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        static_assert(std::is_arithmetic<A>::value, "requires arithmetic type");
1085d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
1095d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1105d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    // initialize from 4 values to w + xi + yj + zk
1115d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    template<typename A, typename B, typename C, typename D>
1125d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    constexpr TQuaternion(A w, B x, C y, D z) : x(x), y(y), z(z), w(w) { }
1135d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1145d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    // initialize from a vec3 + a value to : v.xi + v.yj + v.zk + w
1155d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    template<typename A, typename B>
1165d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    constexpr TQuaternion(const TVec3<A>& v, B w) : x(v.x), y(v.y), z(v.z), w(w) { }
1175d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1185d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    // initialize from a double4
1195d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    template<typename A>
1205d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    constexpr explicit TQuaternion(const TVec4<A>& v) : x(v.x), y(v.y), z(v.z), w(v.w) { }
1215d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1225d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    // initialize from a quaternion of a different type
1235d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    template<typename A>
1245d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    constexpr explicit TQuaternion(const TQuaternion<A>& v) : x(v.x), y(v.y), z(v.z), w(v.w) { }
1255d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1265d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    // conjugate operator
1275d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    constexpr TQuaternion operator~() const {
1285d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return conj(*this);
1295d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
1305d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1315d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    // constructs a quaternion from an axis and angle
1325d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    template <typename A, typename B>
1335d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    constexpr static TQuaternion PURE fromAxisAngle(const TVec3<A>& axis, B angle) {
1345d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return TQuaternion(std::sin(angle*0.5) * normalize(axis), std::cos(angle*0.5));
1355d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
1365d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy};
1375d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1385d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}  // namespace details
1395d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1405d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy// ----------------------------------------------------------------------------------------
1415d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1425d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytypedef details::TQuaternion<double> quatd;
1435d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytypedef details::TQuaternion<float> quat;
1445d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytypedef details::TQuaternion<float> quatf;
1455d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytypedef details::TQuaternion<half> quath;
1465d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1475d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyconstexpr inline quat operator"" _i(long double v) {
148caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    return quat(0, static_cast<float>(v), 0, 0);
1495d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}
1505d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyconstexpr inline quat operator"" _j(long double v) {
151caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    return quat(0, 0, static_cast<float>(v), 0);
1525d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}
1535d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyconstexpr inline quat operator"" _k(long double v) {
154caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    return quat(0, 0, 0, static_cast<float>(v));
1555d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}
1565d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1575d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyconstexpr inline quat operator"" _i(unsigned long long v) {  // NOLINT
158caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    return quat(0, static_cast<float>(v), 0, 0);
1595d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}
1605d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyconstexpr inline quat operator"" _j(unsigned long long v) {  // NOLINT
161caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    return quat(0, 0, static_cast<float>(v), 0);
1625d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}
1635d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyconstexpr inline quat operator"" _k(unsigned long long v) {  // NOLINT
164caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    return quat(0, 0, 0, static_cast<float>(v));
1655d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}
1665d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1675d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyconstexpr inline quatd operator"" _id(long double v) {
168caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    return quatd(0, static_cast<double>(v), 0, 0);
1695d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}
1705d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyconstexpr inline quatd operator"" _jd(long double v) {
171caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    return quatd(0, 0, static_cast<double>(v), 0);
1725d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}
1735d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyconstexpr inline quatd operator"" _kd(long double v) {
174caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    return quatd(0, 0, 0, static_cast<double>(v));
1755d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}
1765d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1775d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyconstexpr inline quatd operator"" _id(unsigned long long v) {  // NOLINT
178caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    return quatd(0, static_cast<double>(v), 0, 0);
1795d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}
1805d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyconstexpr inline quatd operator"" _jd(unsigned long long v) {  // NOLINT
181caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    return quatd(0, 0, static_cast<double>(v), 0);
1825d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}
1835d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyconstexpr inline quatd operator"" _kd(unsigned long long v) {  // NOLINT
184caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    return quatd(0, 0, 0, static_cast<double>(v));
1855d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}
1865d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
1875d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy// ----------------------------------------------------------------------------------------
1885d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}  // namespace android
1895d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
190caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#pragma clang diagnostic pop
191caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy
1925d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#undef PURE
193