Warning, /include/assimp/quaternion.inl is written in an unsupported language. File is not indexed.
0001 /*
0002 ---------------------------------------------------------------------------
0003 Open Asset Import Library (assimp)
0004 ---------------------------------------------------------------------------
0005
0006 Copyright (c) 2006-2024, assimp team
0007
0008
0009
0010 All rights reserved.
0011
0012 Redistribution and use of this software in source and binary forms,
0013 with or without modification, are permitted provided that the following
0014 conditions are met:
0015
0016 * Redistributions of source code must retain the above
0017 copyright notice, this list of conditions and the
0018 following disclaimer.
0019
0020 * Redistributions in binary form must reproduce the above
0021 copyright notice, this list of conditions and the
0022 following disclaimer in the documentation and/or other
0023 materials provided with the distribution.
0024
0025 * Neither the name of the assimp team, nor the names of its
0026 contributors may be used to endorse or promote products
0027 derived from this software without specific prior
0028 written permission of the assimp team.
0029
0030 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0031 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0032 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0033 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0034 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0035 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0036 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0037 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0038 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0039 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0040 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0041 ---------------------------------------------------------------------------
0042 */
0043
0044 /** @file quaternion.inl
0045 * @brief Inline implementation of aiQuaterniont<TReal> operators
0046 */
0047 #pragma once
0048 #ifndef AI_QUATERNION_INL_INC
0049 #define AI_QUATERNION_INL_INC
0050
0051 #ifdef __GNUC__
0052 # pragma GCC system_header
0053 #endif
0054
0055 #ifdef __cplusplus
0056 #include <assimp/quaternion.h>
0057
0058 #include <cmath>
0059
0060 // ------------------------------------------------------------------------------------------------
0061 /** Transformation of a quaternion by a 4x4 matrix */
0062 template <typename TReal>
0063 AI_FORCE_INLINE
0064 aiQuaterniont<TReal> operator * (const aiMatrix4x4t<TReal>& pMatrix, const aiQuaterniont<TReal>& pQuaternion) {
0065 aiQuaterniont<TReal> res;
0066 res.x = pMatrix.a1 * pQuaternion.x + pMatrix.a2 * pQuaternion.y + pMatrix.a3 * pQuaternion.z + pMatrix.a4 * pQuaternion.w;
0067 res.y = pMatrix.b1 * pQuaternion.x + pMatrix.b2 * pQuaternion.y + pMatrix.b3 * pQuaternion.z + pMatrix.b4 * pQuaternion.w;
0068 res.z = pMatrix.c1 * pQuaternion.x + pMatrix.c2 * pQuaternion.y + pMatrix.c3 * pQuaternion.z + pMatrix.c4 * pQuaternion.w;
0069 res.w = pMatrix.d1 * pQuaternion.x + pMatrix.d2 * pQuaternion.y + pMatrix.d3 * pQuaternion.z + pMatrix.d4 * pQuaternion.w;
0070 return res;
0071 }
0072 // ---------------------------------------------------------------------------
0073 template<typename TReal>
0074 bool aiQuaterniont<TReal>::operator== (const aiQuaterniont& o) const
0075 {
0076 return x == o.x && y == o.y && z == o.z && w == o.w;
0077 }
0078
0079 // ---------------------------------------------------------------------------
0080 template<typename TReal>
0081 bool aiQuaterniont<TReal>::operator!= (const aiQuaterniont& o) const
0082 {
0083 return !(*this == o);
0084 }
0085
0086 // ------------------------------------------------------------------------------------------------
0087 template <typename TReal>
0088 AI_FORCE_INLINE
0089 aiQuaterniont<TReal>& aiQuaterniont<TReal>::operator *= (const aiMatrix4x4t<TReal>& mat){
0090 return (*this = mat * (*this));
0091 }
0092 // ------------------------------------------------------------------------------------------------
0093
0094 // ---------------------------------------------------------------------------
0095 template<typename TReal>
0096 inline bool aiQuaterniont<TReal>::Equal(const aiQuaterniont& o, TReal epsilon) const {
0097 return
0098 std::abs(x - o.x) <= epsilon &&
0099 std::abs(y - o.y) <= epsilon &&
0100 std::abs(z - o.z) <= epsilon &&
0101 std::abs(w - o.w) <= epsilon;
0102 }
0103
0104 // ---------------------------------------------------------------------------
0105 // Constructs a quaternion from a rotation matrix
0106 template<typename TReal>
0107 inline aiQuaterniont<TReal>::aiQuaterniont( const aiMatrix3x3t<TReal> &pRotMatrix)
0108 {
0109 TReal t = pRotMatrix.a1 + pRotMatrix.b2 + pRotMatrix.c3;
0110
0111 // large enough
0112 if( t > static_cast<TReal>(0))
0113 {
0114 TReal s = std::sqrt(1 + t) * static_cast<TReal>(2.0);
0115 x = (pRotMatrix.c2 - pRotMatrix.b3) / s;
0116 y = (pRotMatrix.a3 - pRotMatrix.c1) / s;
0117 z = (pRotMatrix.b1 - pRotMatrix.a2) / s;
0118 w = static_cast<TReal>(0.25) * s;
0119 } // else we have to check several cases
0120 else if( pRotMatrix.a1 > pRotMatrix.b2 && pRotMatrix.a1 > pRotMatrix.c3 )
0121 {
0122 // Column 0:
0123 TReal s = std::sqrt( static_cast<TReal>(1.0) + pRotMatrix.a1 - pRotMatrix.b2 - pRotMatrix.c3) * static_cast<TReal>(2.0);
0124 x = static_cast<TReal>(0.25) * s;
0125 y = (pRotMatrix.b1 + pRotMatrix.a2) / s;
0126 z = (pRotMatrix.a3 + pRotMatrix.c1) / s;
0127 w = (pRotMatrix.c2 - pRotMatrix.b3) / s;
0128 }
0129 else if( pRotMatrix.b2 > pRotMatrix.c3)
0130 {
0131 // Column 1:
0132 TReal s = std::sqrt( static_cast<TReal>(1.0) + pRotMatrix.b2 - pRotMatrix.a1 - pRotMatrix.c3) * static_cast<TReal>(2.0);
0133 x = (pRotMatrix.b1 + pRotMatrix.a2) / s;
0134 y = static_cast<TReal>(0.25) * s;
0135 z = (pRotMatrix.c2 + pRotMatrix.b3) / s;
0136 w = (pRotMatrix.a3 - pRotMatrix.c1) / s;
0137 } else
0138 {
0139 // Column 2:
0140 TReal s = std::sqrt( static_cast<TReal>(1.0) + pRotMatrix.c3 - pRotMatrix.a1 - pRotMatrix.b2) * static_cast<TReal>(2.0);
0141 x = (pRotMatrix.a3 + pRotMatrix.c1) / s;
0142 y = (pRotMatrix.c2 + pRotMatrix.b3) / s;
0143 z = static_cast<TReal>(0.25) * s;
0144 w = (pRotMatrix.b1 - pRotMatrix.a2) / s;
0145 }
0146 }
0147
0148 // ---------------------------------------------------------------------------
0149 // Construction from euler angles
0150 template<typename TReal>
0151 inline aiQuaterniont<TReal>::aiQuaterniont( TReal fPitch, TReal fYaw, TReal fRoll )
0152 {
0153 const TReal fSinPitch(std::sin(fPitch*static_cast<TReal>(0.5)));
0154 const TReal fCosPitch(std::cos(fPitch*static_cast<TReal>(0.5)));
0155 const TReal fSinYaw(std::sin(fYaw*static_cast<TReal>(0.5)));
0156 const TReal fCosYaw(std::cos(fYaw*static_cast<TReal>(0.5)));
0157 const TReal fSinRoll(std::sin(fRoll*static_cast<TReal>(0.5)));
0158 const TReal fCosRoll(std::cos(fRoll*static_cast<TReal>(0.5)));
0159 const TReal fCosPitchCosYaw(fCosPitch*fCosYaw);
0160 const TReal fSinPitchSinYaw(fSinPitch*fSinYaw);
0161 x = fSinRoll * fCosPitchCosYaw - fCosRoll * fSinPitchSinYaw;
0162 y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
0163 z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
0164 w = fCosRoll * fCosPitchCosYaw + fSinRoll * fSinPitchSinYaw;
0165 }
0166
0167 // ---------------------------------------------------------------------------
0168 // Returns a matrix representation of the quaternion
0169 template<typename TReal>
0170 inline aiMatrix3x3t<TReal> aiQuaterniont<TReal>::GetMatrix() const
0171 {
0172 aiMatrix3x3t<TReal> resMatrix;
0173 resMatrix.a1 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (y * y + z * z);
0174 resMatrix.a2 = static_cast<TReal>(2.0) * (x * y - z * w);
0175 resMatrix.a3 = static_cast<TReal>(2.0) * (x * z + y * w);
0176 resMatrix.b1 = static_cast<TReal>(2.0) * (x * y + z * w);
0177 resMatrix.b2 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (x * x + z * z);
0178 resMatrix.b3 = static_cast<TReal>(2.0) * (y * z - x * w);
0179 resMatrix.c1 = static_cast<TReal>(2.0) * (x * z - y * w);
0180 resMatrix.c2 = static_cast<TReal>(2.0) * (y * z + x * w);
0181 resMatrix.c3 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (x * x + y * y);
0182
0183 return resMatrix;
0184 }
0185
0186 // ---------------------------------------------------------------------------
0187 // Construction from an axis-angle pair
0188 template<typename TReal>
0189 inline aiQuaterniont<TReal>::aiQuaterniont( aiVector3t<TReal> axis, TReal angle)
0190 {
0191 axis.Normalize();
0192
0193 const TReal sin_a = std::sin( angle / 2 );
0194 const TReal cos_a = std::cos( angle / 2 );
0195 x = axis.x * sin_a;
0196 y = axis.y * sin_a;
0197 z = axis.z * sin_a;
0198 w = cos_a;
0199 }
0200 // ---------------------------------------------------------------------------
0201 // Construction from am existing, normalized quaternion
0202 template<typename TReal>
0203 inline aiQuaterniont<TReal>::aiQuaterniont( aiVector3t<TReal> normalized)
0204 {
0205 x = normalized.x;
0206 y = normalized.y;
0207 z = normalized.z;
0208
0209 const TReal t = static_cast<TReal>(1.0) - (x*x) - (y*y) - (z*z);
0210
0211 if (t < static_cast<TReal>(0.0)) {
0212 w = static_cast<TReal>(0.0);
0213 }
0214 else w = std::sqrt (t);
0215 }
0216
0217 // ---------------------------------------------------------------------------
0218 // Performs a spherical interpolation between two quaternions
0219 // Implementation adopted from the gmtl project. All others I found on the net fail in some cases.
0220 // Congrats, gmtl!
0221 template<typename TReal>
0222 inline void aiQuaterniont<TReal>::Interpolate( aiQuaterniont& pOut, const aiQuaterniont& pStart, const aiQuaterniont& pEnd, TReal pFactor)
0223 {
0224 // calc cosine theta
0225 TReal cosom = pStart.x * pEnd.x + pStart.y * pEnd.y + pStart.z * pEnd.z + pStart.w * pEnd.w;
0226
0227 // adjust signs (if necessary)
0228 aiQuaterniont end = pEnd;
0229 if( cosom < static_cast<TReal>(0.0))
0230 {
0231 cosom = -cosom;
0232 end.x = -end.x; // Reverse all signs
0233 end.y = -end.y;
0234 end.z = -end.z;
0235 end.w = -end.w;
0236 }
0237
0238 // Calculate coefficients
0239 TReal sclp, sclq;
0240
0241 if ((static_cast<TReal>(1.0) - cosom) > ai_epsilon) // 0.0001 -> some epsillon
0242 {
0243 // Standard case (slerp)
0244 TReal omega, sinom;
0245 omega = std::acos( cosom); // extract theta from dot product's cos theta
0246 sinom = std::sin( omega);
0247 sclp = std::sin( (static_cast<TReal>(1.0) - pFactor) * omega) / sinom;
0248 sclq = std::sin( pFactor * omega) / sinom;
0249 } else
0250 {
0251 // Very close, do linear interp (because it's faster)
0252 sclp = static_cast<TReal>(1.0) - pFactor;
0253 sclq = pFactor;
0254 }
0255
0256 pOut.x = sclp * pStart.x + sclq * end.x;
0257 pOut.y = sclp * pStart.y + sclq * end.y;
0258 pOut.z = sclp * pStart.z + sclq * end.z;
0259 pOut.w = sclp * pStart.w + sclq * end.w;
0260 }
0261
0262 // ---------------------------------------------------------------------------
0263 template<typename TReal>
0264 inline aiQuaterniont<TReal>& aiQuaterniont<TReal>::Normalize()
0265 {
0266 // compute the magnitude and divide through it
0267 const TReal mag = std::sqrt(x*x + y*y + z*z + w*w);
0268 if (mag)
0269 {
0270 const TReal invMag = static_cast<TReal>(1.0)/mag;
0271 x *= invMag;
0272 y *= invMag;
0273 z *= invMag;
0274 w *= invMag;
0275 }
0276 return *this;
0277 }
0278
0279 // ---------------------------------------------------------------------------
0280 template<typename TReal>
0281 inline aiQuaterniont<TReal> aiQuaterniont<TReal>::operator* (const aiQuaterniont& t) const
0282 {
0283 return aiQuaterniont(w*t.w - x*t.x - y*t.y - z*t.z,
0284 w*t.x + x*t.w + y*t.z - z*t.y,
0285 w*t.y + y*t.w + z*t.x - x*t.z,
0286 w*t.z + z*t.w + x*t.y - y*t.x);
0287 }
0288
0289 // ---------------------------------------------------------------------------
0290 template<typename TReal>
0291 inline aiQuaterniont<TReal>& aiQuaterniont<TReal>::Conjugate ()
0292 {
0293 x = -x;
0294 y = -y;
0295 z = -z;
0296 return *this;
0297 }
0298
0299 // ---------------------------------------------------------------------------
0300 template<typename TReal>
0301 inline aiVector3t<TReal> aiQuaterniont<TReal>::Rotate (const aiVector3t<TReal>& v) const
0302 {
0303 aiQuaterniont q2(0.f,v.x,v.y,v.z), q = *this, qinv = q;
0304 qinv.Conjugate();
0305
0306 q = q*q2*qinv;
0307 return aiVector3t<TReal>(q.x,q.y,q.z);
0308 }
0309
0310 #endif
0311 #endif // AI_QUATERNION_INL_INC