1 //Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc. 2 3 //Distributed under the Boost Software License, Version 1.0. (See accompanying 4 //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #ifndef BOOST_QVM_907229FCB3A711DE83C152F855D89593 7 #define BOOST_QVM_907229FCB3A711DE83C152F855D89593 8 9 #include <limits> 10 #include <math.h> 11 #include <assert.h> 12 #include <memory.h> 13 #include <stdlib.h> 14 15 namespace 16 test_qvm 17 { 18 namespace 19 detail 20 { 21 inline 22 float sin(float a)23 sin( float a ) 24 { 25 return ::sinf(a); 26 } 27 28 inline 29 double sin(double a)30 sin( double a ) 31 { 32 return ::sin(a); 33 } 34 35 inline 36 float cos(float a)37 cos( float a ) 38 { 39 return ::cosf(a); 40 } 41 42 inline 43 double cos(double a)44 cos( double a ) 45 { 46 return ::cos(a); 47 } 48 49 inline 50 float abs(float a)51 abs( float a ) 52 { 53 return ::fabsf(a); 54 } 55 56 inline 57 double abs(double a)58 abs( double a ) 59 { 60 return ::fabs(a); 61 } 62 63 inline 64 float atan2(float a,float b)65 atan2( float a, float b ) 66 { 67 return ::atan2f(a,b); 68 } 69 70 inline 71 double atan2(double a,double b)72 atan2( double a, double b ) 73 { 74 return ::atan2(a,b); 75 } 76 77 template <class T> 78 T determinant(T ** a,int n)79 determinant( T * * a, int n ) 80 { 81 int i,j,j1,j2; 82 T det = 0; 83 T * * m = 0; 84 assert(n>=1); 85 if( n==1 ) 86 det = a[0][0]; 87 else if( n==2 ) 88 det = a[0][0] * a[1][1] - a[1][0] * a[0][1]; 89 else 90 { 91 det = 0; 92 for( j1=0; j1<n; j1++ ) 93 { 94 m = static_cast<T * *>(malloc((n-1)*sizeof(T *))); 95 for( i=0; i<n-1; i++ ) 96 m[i] = static_cast<T *>(malloc((n-1)*sizeof(T))); 97 for( i=1; i<n; i++ ) 98 { 99 j2 = 0; 100 for( j=0; j<n; j++ ) 101 { 102 if( j==j1 ) 103 continue; 104 m[i-1][j2] = a[i][j]; 105 j2++; 106 } 107 } 108 det += T(pow(-1.0,1.0+j1+1.0)) * a[0][j1] * determinant(m,n-1); 109 for( i=0; i<n-1; i++ ) 110 free(m[i]); 111 free(m); 112 } 113 } 114 return(det); 115 } 116 117 template <class T,int N> 118 void cofactor(T ** a,T (& b)[N][N])119 cofactor( T * * a, T (&b)[N][N] ) 120 { 121 int i,j,ii,jj,i1,j1; 122 T det; 123 T * * c; 124 c = static_cast<T * *>(malloc((N-1)*sizeof(T *))); 125 for( i=0; i<N-1; i++ ) 126 c[i] = static_cast<T *>(malloc((N-1)*sizeof(T))); 127 for( j=0; j<N; j++ ) 128 { 129 for( i=0; i<N; i++ ) 130 { 131 i1 = 0; 132 for( ii=0; ii<N; ii++ ) 133 { 134 if( ii==i ) 135 continue; 136 j1 = 0; 137 for( jj=0; jj<N; jj++ ) 138 { 139 if( jj==j ) 140 continue; 141 c[i1][j1] = a[ii][jj]; 142 j1++; 143 } 144 i1++; 145 } 146 det = determinant(c,N-1); 147 b[i][j] = T(pow(-1.0,i+j+2.0)) * det; 148 } 149 } 150 for( i=0; i<N-1; i++ ) 151 free(c[i]); 152 free(c); 153 } 154 } 155 156 template <class T,int D> 157 T 158 determinant( T (&in)[D][D] ) 159 { 160 T * * m = static_cast<T * *>(malloc(D*sizeof(T *))); 161 for( int i=0; i!=D; ++i ) 162 { 163 m[i] = static_cast<T *>(malloc(D*sizeof(T))); 164 for( int j=0; j!=D; ++j ) 165 m[i][j]=in[i][j]; 166 } 167 T det=::test_qvm::detail::determinant(m,D); 168 for( int i=0; i<D; ++i ) 169 free(m[i]); 170 free(m); 171 return det; 172 } 173 174 template <class T,int D> 175 void inverse(T (& out)[D][D],T (& in)[D][D])176 inverse( T (&out)[D][D], T (&in)[D][D] ) 177 { 178 T * * m = static_cast<T * *>(malloc(D*sizeof(T *))); 179 for( int i=0; i!=D; ++i ) 180 { 181 m[i] = static_cast<T *>(malloc(D*sizeof(T))); 182 for( int j=0; j!=D; ++j ) 183 m[i][j]=in[i][j]; 184 } 185 T det=::test_qvm::detail::determinant(m,D); 186 assert(det!=T(0)); 187 T f=T(1)/det; 188 T b[D][D]; 189 ::test_qvm::detail::cofactor(m,b); 190 for( int i=0; i<D; ++i ) 191 free(m[i]); 192 free(m); 193 for( int i=0; i!=D; ++i ) 194 for( int j=0; j!=D; ++j ) 195 out[j][i]=b[i][j]*f; 196 } 197 198 template <class T,int M,int N> 199 void init_m(T (& r)[M][N],T start=T (0),T step=T (0))200 init_m( T (&r)[M][N], T start=T(0), T step=T(0) ) 201 { 202 for( int i=0; i<M; ++i ) 203 for( int j=0; j<N; ++j,start+=step ) 204 r[i][j] = start; 205 } 206 207 template <class T,int D> 208 void init_v(T (& r)[D],T start=T (0),T step=T (0))209 init_v( T (&r)[D], T start=T(0), T step=T(0) ) 210 { 211 for( int i=0; i<D; ++i,start+=step ) 212 r[i] = start; 213 } 214 215 template <class T,int M,int N> 216 void zero_mat(T (& r)[M][N])217 zero_mat( T (&r)[M][N] ) 218 { 219 for( int i=0; i<M; ++i ) 220 for( int j=0; j<N; ++j ) 221 r[i][j] = T(0); 222 } 223 224 template <class T,int D> 225 void zero_vec(T (& r)[D])226 zero_vec( T (&r)[D] ) 227 { 228 for( int i=0; i<D; ++i ) 229 r[i] = T(0); 230 } 231 232 template <class T,int D> 233 void identity(T (& r)[D][D])234 identity( T (&r)[D][D] ) 235 { 236 for( int i=0; i<D; ++i ) 237 for( int j=0; j<D; ++j ) 238 r[i][j] = (i==j) ? T(1) : T(0); 239 } 240 241 template <class T,class U,class V,int M,int N> 242 void add_m(T (& r)[M][N],U (& a)[M][N],V (& b)[M][N])243 add_m( T (&r)[M][N], U (&a)[M][N], V (&b)[M][N] ) 244 { 245 for( int i=0; i<M; ++i ) 246 for( int j=0; j<N; ++j ) 247 r[i][j] = a[i][j] + b[i][j]; 248 } 249 250 template <class T,class U,class V,int D> 251 void add_v(T (& r)[D],U (& a)[D],V (& b)[D])252 add_v( T (&r)[D], U (&a)[D], V (&b)[D] ) 253 { 254 for( int i=0; i<D; ++i ) 255 r[i] = a[i] + b[i]; 256 } 257 258 template <class T,class U,class V,int M,int N> 259 void subtract_m(T (& r)[M][N],U (& a)[M][N],V (& b)[M][N])260 subtract_m( T (&r)[M][N], U (&a)[M][N], V (&b)[M][N] ) 261 { 262 for( int i=0; i<M; ++i ) 263 for( int j=0; j<N; ++j ) 264 r[i][j] = a[i][j] - b[i][j]; 265 } 266 267 template <class T,class U,class V,int D> 268 void subtract_v(T (& r)[D],U (& a)[D],V (& b)[D])269 subtract_v( T (&r)[D], U (&a)[D], V (&b)[D] ) 270 { 271 for( int i=0; i<D; ++i ) 272 r[i] = a[i] - b[i]; 273 } 274 275 template <class T,int D,class U> 276 void rotation_x(T (& r)[D][D],U angle)277 rotation_x( T (&r)[D][D], U angle ) 278 { 279 identity(r); 280 T c=::test_qvm::detail::cos(angle); 281 T s=::test_qvm::detail::sin(angle); 282 r[1][1]=c; 283 r[1][2]=-s; 284 r[2][1]=s; 285 r[2][2]=c; 286 } 287 288 template <class T,int D,class U> 289 void rotation_y(T (& r)[D][D],U angle)290 rotation_y( T (&r)[D][D], U angle ) 291 { 292 identity(r); 293 T c=::test_qvm::detail::cos(angle); 294 T s=::test_qvm::detail::sin(angle); 295 r[0][0]=c; 296 r[0][2]=s; 297 r[2][0]=-s; 298 r[2][2]=c; 299 } 300 301 template <class T,int D,class U> 302 void rotation_z(T (& r)[D][D],U angle)303 rotation_z( T (&r)[D][D], U angle ) 304 { 305 identity(r); 306 T c=::test_qvm::detail::cos(angle); 307 T s=::test_qvm::detail::sin(angle); 308 r[0][0]=c; 309 r[0][1]=-s; 310 r[1][0]=s; 311 r[1][1]=c; 312 } 313 314 template <class T,int D> 315 void translation(T (& r)[D][D],T (& t)[D-1])316 translation( T (&r)[D][D], T (&t)[D-1] ) 317 { 318 identity(r); 319 for( int i=0; i!=D-1; ++i ) 320 r[i][D-1]=t[i]; 321 } 322 323 template <class R,class T,class U,int M,int N,int P> 324 void multiply_m(R (& r)[M][P],T (& a)[M][N],U (& b)[N][P])325 multiply_m( R (&r)[M][P], T (&a)[M][N], U (&b)[N][P] ) 326 { 327 for( int i=0; i<M; ++i ) 328 for( int j=0; j<P; ++j ) 329 { 330 R x=0; 331 for( int k=0; k<N; ++k ) 332 x += R(a[i][k])*R(b[k][j]); 333 r[i][j] = x; 334 } 335 } 336 337 template <class R,class T,class U,int M,int N> 338 void multiply_mv(R (& r)[M],T (& a)[M][N],U (& b)[N])339 multiply_mv( R (&r)[M], T (&a)[M][N], U (&b)[N] ) 340 { 341 for( int i=0; i<M; ++i ) 342 { 343 R x=0; 344 for( int k=0; k<N; ++k ) 345 x += R(a[i][k])*R(b[k]); 346 r[i] = x; 347 } 348 } 349 350 template <class R,class T,class U,int N,int P> 351 void multiply_vm(R (& r)[P],T (& a)[N],U (& b)[N][P])352 multiply_vm( R (&r)[P], T (&a)[N], U (&b)[N][P] ) 353 { 354 for( int j=0; j<P; ++j ) 355 { 356 R x=0; 357 for( int k=0; k<N; ++k ) 358 x += R(a[k])*R(b[k][j]); 359 r[j] = x; 360 } 361 } 362 363 template <class T,class U,int M,int N,class S> 364 void scalar_multiply_m(T (& r)[M][N],U (& a)[M][N],S scalar)365 scalar_multiply_m( T (&r)[M][N], U (&a)[M][N], S scalar ) 366 { 367 for( int i=0; i<M; ++i ) 368 for( int j=0; j<N; ++j ) 369 r[i][j] = a[i][j]*scalar; 370 } 371 372 template <class T,class U,int D,class S> 373 void scalar_multiply_v(T (& r)[D],U (& a)[D],S scalar)374 scalar_multiply_v( T (&r)[D], U (&a)[D], S scalar ) 375 { 376 for( int i=0; i<D; ++i ) 377 r[i] = a[i]*scalar; 378 } 379 380 template <class T,int M,int N> 381 void transpose(T (& r)[M][N],T (& a)[N][M])382 transpose( T (&r)[M][N], T (&a)[N][M] ) 383 { 384 for( int i=0; i<M; ++i ) 385 for( int j=0; j<N; ++j ) 386 r[i][j] = a[j][i]; 387 } 388 389 template <class R,class T,class U,int D> 390 R 391 dot( T (&a)[D], U (&b)[D] ) 392 { 393 R r=R(0); 394 for( int i=0; i<D; ++i ) 395 r+=a[i]*b[i]; 396 return r; 397 } 398 399 template <class T,int M,int N> 400 T 401 norm_squared( T (&m)[M][N] ) 402 { 403 T f=T(0); 404 for( int i=0; i<M; ++i ) 405 for( int j=0; j<N; ++j ) 406 { 407 T x=m[i][j]; 408 f+=x*x; 409 } 410 return f; 411 } 412 413 template <class T> 414 inline 415 void matrix_perspective_lh(T (& r)[4][4],T fov_y,T aspect_ratio,T zn,T zf)416 matrix_perspective_lh( T (&r)[4][4], T fov_y, T aspect_ratio, T zn, T zf ) 417 { 418 T ys=T(1)/::tanf(fov_y/T(2)); 419 T xs=ys/aspect_ratio; 420 zero_mat(r); 421 r[0][0] = xs; 422 r[1][1] = ys; 423 r[2][2] = zf/(zf-zn); 424 r[2][3] = -zn*zf/(zf-zn); 425 r[3][2] = 1; 426 } 427 428 template <class T> 429 inline 430 void matrix_perspective_rh(T (& r)[4][4],T fov_y,T aspect_ratio,T zn,T zf)431 matrix_perspective_rh( T (&r)[4][4], T fov_y, T aspect_ratio, T zn, T zf ) 432 { 433 matrix_perspective_lh(r,fov_y,aspect_ratio,zn,zf); 434 r[2][2]=-r[2][2]; 435 r[3][2]=-r[3][2]; 436 } 437 } 438 439 #endif 440