Warning, /include/assimp/matrix3x3.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 All rights reserved.
0009
0010 Redistribution and use of this software in source and binary forms,
0011 with or without modification, are permitted provided that the following
0012 conditions are met:
0013
0014 * Redistributions of source code must retain the above
0015 copyright notice, this list of conditions and the
0016 following disclaimer.
0017
0018 * Redistributions in binary form must reproduce the above
0019 copyright notice, this list of conditions and the
0020 following disclaimer in the documentation and/or other
0021 materials provided with the distribution.
0022
0023 * Neither the name of the assimp team, nor the names of its
0024 contributors may be used to endorse or promote products
0025 derived from this software without specific prior
0026 written permission of the assimp team.
0027
0028 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0029 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0030 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0031 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0032 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0033 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0034 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0035 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0036 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0037 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0038 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0039 ---------------------------------------------------------------------------
0040 */
0041
0042 /** @file matrix3x3.inl
0043 * @brief Inline implementation of the 3x3 matrix operators
0044 */
0045 #pragma once
0046 #ifndef AI_MATRIX3X3_INL_INC
0047 #define AI_MATRIX3X3_INL_INC
0048
0049 #ifdef __GNUC__
0050 # pragma GCC system_header
0051 #endif
0052
0053 #ifdef __cplusplus
0054 #include <assimp/matrix3x3.h>
0055 #include <assimp/matrix4x4.h>
0056
0057 #include <algorithm>
0058 #include <cmath>
0059 #include <limits>
0060
0061 // ------------------------------------------------------------------------------------------------
0062 // Construction from a 4x4 matrix. The remaining parts of the matrix are ignored.
0063 template <typename TReal>
0064 AI_FORCE_INLINE
0065 aiMatrix3x3t<TReal>::aiMatrix3x3t( const aiMatrix4x4t<TReal>& pMatrix) {
0066 a1 = pMatrix.a1; a2 = pMatrix.a2; a3 = pMatrix.a3;
0067 b1 = pMatrix.b1; b2 = pMatrix.b2; b3 = pMatrix.b3;
0068 c1 = pMatrix.c1; c2 = pMatrix.c2; c3 = pMatrix.c3;
0069 }
0070
0071 // ------------------------------------------------------------------------------------------------
0072 template <typename TReal>
0073 AI_FORCE_INLINE
0074 aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::operator *= (const aiMatrix3x3t<TReal>& m) {
0075 *this = aiMatrix3x3t<TReal>(m.a1 * a1 + m.b1 * a2 + m.c1 * a3,
0076 m.a2 * a1 + m.b2 * a2 + m.c2 * a3,
0077 m.a3 * a1 + m.b3 * a2 + m.c3 * a3,
0078 m.a1 * b1 + m.b1 * b2 + m.c1 * b3,
0079 m.a2 * b1 + m.b2 * b2 + m.c2 * b3,
0080 m.a3 * b1 + m.b3 * b2 + m.c3 * b3,
0081 m.a1 * c1 + m.b1 * c2 + m.c1 * c3,
0082 m.a2 * c1 + m.b2 * c2 + m.c2 * c3,
0083 m.a3 * c1 + m.b3 * c2 + m.c3 * c3);
0084 return *this;
0085 }
0086
0087 // ------------------------------------------------------------------------------------------------
0088 template <typename TReal>
0089 template <typename TOther>
0090 aiMatrix3x3t<TReal>::operator aiMatrix3x3t<TOther> () const {
0091 return aiMatrix3x3t<TOther>(static_cast<TOther>(a1),static_cast<TOther>(a2),static_cast<TOther>(a3),
0092 static_cast<TOther>(b1),static_cast<TOther>(b2),static_cast<TOther>(b3),
0093 static_cast<TOther>(c1),static_cast<TOther>(c2),static_cast<TOther>(c3));
0094 }
0095
0096 // ------------------------------------------------------------------------------------------------
0097 template <typename TReal>
0098 AI_FORCE_INLINE
0099 aiMatrix3x3t<TReal> aiMatrix3x3t<TReal>::operator* (const aiMatrix3x3t<TReal>& m) const {
0100 aiMatrix3x3t<TReal> temp( *this);
0101 temp *= m;
0102 return temp;
0103 }
0104
0105 // ------------------------------------------------------------------------------------------------
0106 template <typename TReal>
0107 AI_FORCE_INLINE
0108 TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex) {
0109 switch ( p_iIndex ) {
0110 case 0:
0111 return &a1;
0112 case 1:
0113 return &b1;
0114 case 2:
0115 return &c1;
0116 default:
0117 break;
0118 }
0119 return &a1;
0120 }
0121
0122 // ------------------------------------------------------------------------------------------------
0123 template <typename TReal>
0124 AI_FORCE_INLINE
0125 const TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex) const {
0126 switch ( p_iIndex ) {
0127 case 0:
0128 return &a1;
0129 case 1:
0130 return &b1;
0131 case 2:
0132 return &c1;
0133 default:
0134 break;
0135 }
0136 return &a1;
0137 }
0138
0139 // ------------------------------------------------------------------------------------------------
0140 template <typename TReal>
0141 AI_FORCE_INLINE
0142 bool aiMatrix3x3t<TReal>::operator== (const aiMatrix3x3t<TReal>& m) const {
0143 return a1 == m.a1 && a2 == m.a2 && a3 == m.a3 &&
0144 b1 == m.b1 && b2 == m.b2 && b3 == m.b3 &&
0145 c1 == m.c1 && c2 == m.c2 && c3 == m.c3;
0146 }
0147
0148 // ------------------------------------------------------------------------------------------------
0149 template <typename TReal>
0150 AI_FORCE_INLINE
0151 bool aiMatrix3x3t<TReal>::operator!= (const aiMatrix3x3t<TReal>& m) const {
0152 return !(*this == m);
0153 }
0154
0155 // ---------------------------------------------------------------------------
0156 template<typename TReal>
0157 AI_FORCE_INLINE
0158 bool aiMatrix3x3t<TReal>::Equal(const aiMatrix3x3t<TReal>& m, TReal epsilon) const {
0159 return
0160 std::abs(a1 - m.a1) <= epsilon &&
0161 std::abs(a2 - m.a2) <= epsilon &&
0162 std::abs(a3 - m.a3) <= epsilon &&
0163 std::abs(b1 - m.b1) <= epsilon &&
0164 std::abs(b2 - m.b2) <= epsilon &&
0165 std::abs(b3 - m.b3) <= epsilon &&
0166 std::abs(c1 - m.c1) <= epsilon &&
0167 std::abs(c2 - m.c2) <= epsilon &&
0168 std::abs(c3 - m.c3) <= epsilon;
0169 }
0170
0171 // ------------------------------------------------------------------------------------------------
0172 template <typename TReal>
0173 AI_FORCE_INLINE
0174 aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Transpose() {
0175 // (TReal&) don't remove, GCC complains cause of packed fields
0176 std::swap( (TReal&)a2, (TReal&)b1);
0177 std::swap( (TReal&)a3, (TReal&)c1);
0178 std::swap( (TReal&)b3, (TReal&)c2);
0179 return *this;
0180 }
0181
0182 // ----------------------------------------------------------------------------------------
0183 template <typename TReal>
0184 AI_FORCE_INLINE
0185 TReal aiMatrix3x3t<TReal>::Determinant() const {
0186 return a1*b2*c3 - a1*b3*c2 + a2*b3*c1 - a2*b1*c3 + a3*b1*c2 - a3*b2*c1;
0187 }
0188
0189 // ----------------------------------------------------------------------------------------
0190 template <typename TReal>
0191 AI_FORCE_INLINE
0192 aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Inverse() {
0193 // Compute the reciprocal determinant
0194 TReal det = Determinant();
0195 if(det == static_cast<TReal>(0.0))
0196 {
0197 // Matrix not invertible. Setting all elements to nan is not really
0198 // correct in a mathematical sense; but at least qnans are easy to
0199 // spot. XXX we might throw an exception instead, which would
0200 // be even much better to spot :/.
0201 const TReal nan = std::numeric_limits<TReal>::quiet_NaN();
0202 *this = aiMatrix3x3t<TReal>( nan,nan,nan,nan,nan,nan,nan,nan,nan);
0203
0204 return *this;
0205 }
0206
0207 TReal invdet = static_cast<TReal>(1.0) / det;
0208
0209 aiMatrix3x3t<TReal> res;
0210 res.a1 = invdet * (b2 * c3 - b3 * c2);
0211 res.a2 = -invdet * (a2 * c3 - a3 * c2);
0212 res.a3 = invdet * (a2 * b3 - a3 * b2);
0213 res.b1 = -invdet * (b1 * c3 - b3 * c1);
0214 res.b2 = invdet * (a1 * c3 - a3 * c1);
0215 res.b3 = -invdet * (a1 * b3 - a3 * b1);
0216 res.c1 = invdet * (b1 * c2 - b2 * c1);
0217 res.c2 = -invdet * (a1 * c2 - a2 * c1);
0218 res.c3 = invdet * (a1 * b2 - a2 * b1);
0219 *this = res;
0220
0221 return *this;
0222 }
0223
0224 // ------------------------------------------------------------------------------------------------
0225 template <typename TReal>
0226 AI_FORCE_INLINE
0227 aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::RotationZ(TReal a, aiMatrix3x3t<TReal>& out) {
0228 out.a1 = out.b2 = std::cos(a);
0229 out.b1 = std::sin(a);
0230 out.a2 = - out.b1;
0231
0232 out.a3 = out.b3 = out.c1 = out.c2 = 0.f;
0233 out.c3 = 1.f;
0234
0235 return out;
0236 }
0237
0238 // ------------------------------------------------------------------------------------------------
0239 // Returns a rotation matrix for a rotation around an arbitrary axis.
0240 template <typename TReal>
0241 AI_FORCE_INLINE
0242 aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Rotation( TReal a, const aiVector3t<TReal>& axis, aiMatrix3x3t<TReal>& out) {
0243 TReal c = std::cos( a), s = std::sin( a), t = 1 - c;
0244 TReal x = axis.x, y = axis.y, z = axis.z;
0245
0246 // Many thanks to MathWorld and Wikipedia
0247 out.a1 = t*x*x + c; out.a2 = t*x*y - s*z; out.a3 = t*x*z + s*y;
0248 out.b1 = t*x*y + s*z; out.b2 = t*y*y + c; out.b3 = t*y*z - s*x;
0249 out.c1 = t*x*z - s*y; out.c2 = t*y*z + s*x; out.c3 = t*z*z + c;
0250
0251 return out;
0252 }
0253
0254 // ------------------------------------------------------------------------------------------------
0255 template <typename TReal>
0256 AI_FORCE_INLINE
0257 aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Translation( const aiVector2t<TReal>& v, aiMatrix3x3t<TReal>& out) {
0258 out = aiMatrix3x3t<TReal>();
0259 out.a3 = v.x;
0260 out.b3 = v.y;
0261 return out;
0262 }
0263
0264 // ----------------------------------------------------------------------------------------
0265 /** A function for creating a rotation matrix that rotates a vector called
0266 * "from" into another vector called "to".
0267 * Input : from[3], to[3] which both must be *normalized* non-zero vectors
0268 * Output: mtx[3][3] -- a 3x3 matrix in colum-major form
0269 * Authors: Tomas Möller, John Hughes
0270 * "Efficiently Building a Matrix to Rotate One Vector to Another"
0271 * Journal of Graphics Tools, 4(4):1-4, 1999
0272 */
0273 // ----------------------------------------------------------------------------------------
0274 template <typename TReal>
0275 AI_FORCE_INLINE aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::FromToMatrix(const aiVector3t<TReal>& from,
0276 const aiVector3t<TReal>& to, aiMatrix3x3t<TReal>& mtx) {
0277 const TReal e = from * to;
0278 const TReal f = (e < 0)? -e:e;
0279
0280 if (f > static_cast<TReal>(1.0) - static_cast<TReal>(0.00001)) /* "from" and "to"-vector almost parallel */
0281 {
0282 aiVector3D u,v; /* temporary storage vectors */
0283 aiVector3D x; /* vector most nearly orthogonal to "from" */
0284
0285 x.x = (from.x > 0.0)? from.x : -from.x;
0286 x.y = (from.y > 0.0)? from.y : -from.y;
0287 x.z = (from.z > 0.0)? from.z : -from.z;
0288
0289 if (x.x < x.y)
0290 {
0291 if (x.x < x.z)
0292 {
0293 x.x = static_cast<TReal>(1.0);
0294 x.y = x.z = static_cast<TReal>(0.0);
0295 }
0296 else
0297 {
0298 x.z = static_cast<TReal>(1.0);
0299 x.x = x.y = static_cast<TReal>(0.0);
0300 }
0301 }
0302 else
0303 {
0304 if (x.y < x.z)
0305 {
0306 x.y = static_cast<TReal>(1.0);
0307 x.x = x.z = static_cast<TReal>(0.0);
0308 }
0309 else
0310 {
0311 x.z = static_cast<TReal>(1.0);
0312 x.x = x.y = static_cast<TReal>(0.0);
0313 }
0314 }
0315
0316 u.x = x.x - from.x; u.y = x.y - from.y; u.z = x.z - from.z;
0317 v.x = x.x - to.x; v.y = x.y - to.y; v.z = x.z - to.z;
0318
0319 const TReal c1_ = static_cast<TReal>(2.0) / (u * u);
0320 const TReal c2_ = static_cast<TReal>(2.0) / (v * v);
0321 const TReal c3_ = c1_ * c2_ * (u * v);
0322
0323 for (unsigned int i = 0; i < 3; i++)
0324 {
0325 for (unsigned int j = 0; j < 3; j++)
0326 {
0327 mtx[i][j] = - c1_ * u[i] * u[j] - c2_ * v[i] * v[j]
0328 + c3_ * v[i] * u[j];
0329 }
0330 mtx[i][i] += static_cast<TReal>(1.0);
0331 }
0332 }
0333 else /* the most common case, unless "from"="to", or "from"=-"to" */
0334 {
0335 const aiVector3D v = from ^ to;
0336 /* ... use this hand optimized version (9 mults less) */
0337 const TReal h = static_cast<TReal>(1.0)/(static_cast<TReal>(1.0) + e); /* optimization by Gottfried Chen */
0338 const TReal hvx = h * v.x;
0339 const TReal hvz = h * v.z;
0340 const TReal hvxy = hvx * v.y;
0341 const TReal hvxz = hvx * v.z;
0342 const TReal hvyz = hvz * v.y;
0343 mtx[0][0] = e + hvx * v.x;
0344 mtx[0][1] = hvxy - v.z;
0345 mtx[0][2] = hvxz + v.y;
0346
0347 mtx[1][0] = hvxy + v.z;
0348 mtx[1][1] = e + h * v.y * v.y;
0349 mtx[1][2] = hvyz - v.x;
0350
0351 mtx[2][0] = hvxz - v.y;
0352 mtx[2][1] = hvyz + v.x;
0353 mtx[2][2] = e + hvz * v.z;
0354 }
0355 return mtx;
0356 }
0357
0358 #endif // __cplusplus
0359 #endif // AI_MATRIX3X3_INL_INC