commit 1a32c72cca5be663e968fbd123f2448f93befe64 parent 40475d5e75ca5d7130b370c1d048ca877b7ca22f Author: Michael Savage <mikejsavage@gmail.com> Date: Mon Nov 7 22:18:01 +0200 Add m3/m4/v4/misc functions to linear_algebra.h Diffstat:
linear_algebra.h | | | 444 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
diff --git a/linear_algebra.h b/linear_algebra.h @@ -35,7 +35,6 @@ struct v2 { }; struct m2 { - // row major 2x2 matrix float a, b, c, d; m2() { } @@ -85,6 +84,130 @@ struct v3 { #define GLMV3( v ) v3( ( v ).x, ( v ).y, ( v ).z ) +struct m3 { + v3 row0, row1, row2; + + m3() { } + + explicit m3( + float e0, float e1, float e2, + float e3, float e4, float e5, + float e6, float e7, float e8 + ) { + row0 = v3( e0, e1, e2 ); + row1 = v3( e3, e4, e5 ); + row2 = v3( e6, e7, e8 ); + } + + explicit m3( v3 r0, v3 r1, v3 r2 ) { + row0 = r0; + row1 = r1; + row2 = r2; + } + + v3 col0() const { return v3( row0.x, row1.x, row2.x ); } + v3 col1() const { return v3( row0.y, row1.y, row2.y ); } + v3 col2() const { return v3( row0.z, row1.z, row2.z ); } +}; + +struct v4 { + float x, y, z, w; + + v4() { } + + explicit v4( float a ) { + x = a; + y = a; + z = a; + w = a; + } + + explicit v4( float a, float b, float c, float d ) { + x = a; + y = b; + z = c; + w = d; + } + + explicit v4( v3 abc, float d ) { + x = abc.x; + y = abc.y; + z = abc.z; + w = d; + } + + float & operator[]( size_t idx ) { + ASSERT( idx < 4 ); + if( idx == 0 ) return x; + if( idx == 1 ) return y; + if( idx == 2 ) return z; + return w; + } + + const float & operator[]( size_t idx ) const { + ASSERT( idx < 4 ); + if( idx == 0 ) return x; + if( idx == 1 ) return y; + if( idx == 2 ) return z; + return w; + } +}; + +struct m4 { + v4 row0, row1, row2, row3; + + m4() { } + + explicit m4( + float e0, float e1, float e2, float e3, + float e4, float e5, float e6, float e7, + float e8, float e9, float e10, float e11, + float e12, float e13, float e14, float e15 + ) { + row0 = v4( e0, e1, e2, e3 ); + row1 = v4( e4, e5, e6, e7 ); + row2 = v4( e8, e9, e10, e11 ); + row3 = v4( e12, e13, e14, e15 ); + } + + explicit m4( v4 r0, v4 r1, v4 r2, v4 r3 ) { + row0 = r0; + row1 = r1; + row2 = r2; + row3 = r3; + } + + explicit m4( const m3 & m ) { + row0 = v4( m.row0, 0 ); + row1 = v4( m.row1, 0 ); + row2 = v4( m.row2, 0 ); + row3 = v4( 0, 0, 0, 1 ); + } + + v4 col0() const { return v4( row0.x, row1.x, row2.x, row3.x ); } + v4 col1() const { return v4( row0.y, row1.y, row2.y, row3.y ); } + v4 col2() const { return v4( row0.z, row1.z, row2.z, row3.z ); } + v4 col3() const { return v4( row0.w, row1.w, row2.w, row3.w ); } + + float & operator[]( size_t idx ) { + ASSERT( idx < 16 ); + v4 rows[] = { row0, row1, row2, row3 }; + return rows[ idx / 4 ][ idx % 4 ]; + } + + const float & operator[]( size_t idx ) const { + ASSERT( idx < 16 ); + const v4 rows[] = { row0, row1, row2, row3 }; + return rows[ idx / 4 ][ idx % 4 ]; + } +}; + +struct quat { + float x, y, z, w; +}; + +// TODO: v3x4, v4x4, simd matrices, v3u32? + /* * v2 */ @@ -110,10 +233,22 @@ forceinline v2 operator/( v2 v, float scale ) { return v * inv_scale; } +forceinline v2 operator-( v2 v ) { + return v2( -v.x, -v.y ); +} + forceinline float dot( v2 lhs, v2 rhs ) { return lhs.x * rhs.x + lhs.y * rhs.y; } +forceinline float length( v2 v ) { + return sqrtf( v.x * v.x + v.y * v.y ); +} + +forceinline v2 normalize( v2 v ) { + return v / length( v ); +} + /* * m2 */ @@ -179,6 +314,10 @@ forceinline v3 operator/( v3 v, float scale ) { return v * inv_scale; } +forceinline v3 operator-( v3 v ) { + return v3( -v.x, -v.y, -v.z ); +} + forceinline float dot( v3 u, v3 v ) { return u.x * v.x + u.y * v.y + u.z * v.z; } @@ -199,4 +338,307 @@ forceinline v3 normalize( v3 v ) { return v / length( v ); } +/* + * m3 + */ + +forceinline m3 m3_identity() { + return m3( + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 + ); +} + +forceinline m3 m3_scale( float s ) { + return m3( + s, 0, 0, + 0, s, 0, + 0, 0, s + ); +} + +forceinline m3 m3_scale( float x, float y, float z ) { + return m3( + x, 0, 0, + 0, y, 0, + 0, 0, z + ); +} + +forceinline m3 m3_rotx( float theta ) { + float s = sinf( theta ); + float c = cosf( theta ); + return m3( + 1, 0, 0, + 0, c, -s, + 0, s, c + ); +} + +forceinline m3 m3_roty( float theta ) { + float s = sinf( theta ); + float c = cosf( theta ); + return m3( + c, 0, s, + 0, 1, 0, + -s, 0, c + ); +} + +forceinline m3 m3_rotz( float theta ) { + float s = sinf( theta ); + float c = cosf( theta ); + return m3( + c, -s, 0, + s, c, 0, + 0, 0, 1 + ); +} + +forceinline m3 operator*( const m3 & lhs, const m3 & rhs ) { + return m3( + dot( lhs.row0, rhs.col0() ), + dot( lhs.row0, rhs.col1() ), + dot( lhs.row0, rhs.col2() ), + + dot( lhs.row1, rhs.col0() ), + dot( lhs.row1, rhs.col1() ), + dot( lhs.row1, rhs.col2() ), + + dot( lhs.row2, rhs.col0() ), + dot( lhs.row2, rhs.col1() ), + dot( lhs.row2, rhs.col2() ) + ); +} + +forceinline v3 operator*( const m3 & m, v3 v ) { + return v3( + dot( m.row0, v ), + dot( m.row1, v ), + dot( m.row2, v ) + ); +} + +/* + * v4 + */ + +forceinline v4 operator+( v4 lhs, v4 rhs ) { + return v4( + lhs.x + rhs.x, + lhs.y + rhs.y, + lhs.z + rhs.z, + lhs.w + rhs.w + ); +} + +forceinline v4 operator-( v4 lhs, v4 rhs ) { + return v4( + lhs.x - rhs.x, + lhs.y - rhs.y, + lhs.z - rhs.z, + lhs.w - rhs.w + ); +} + +forceinline v4 operator*( v4 v, float scale ) { + return v4( + v.x * scale, + v.y * scale, + v.z * scale, + v.w * scale + ); +} + +forceinline v4 operator*( float scale, v4 v ) { + return v * scale; +} + +forceinline v4 operator/( v4 v, float scale ) { + float inv_scale = 1.0f / scale; + return v * inv_scale; +} + +forceinline v4 operator-( v4 v ) { + return v4( -v.x, -v.y, -v.z, -v.w ); +} + +forceinline float dot( v4 lhs, v4 rhs ) { + return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z + lhs.w * rhs.w; +} + +forceinline float length( v4 v ) { + return sqrtf( v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w ); +} + +forceinline v4 normalize( v4 v ) { + return v / length( v ); +} + +/* + * m4 + */ + +forceinline m4 m4_identity() { + return m4( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ); +} + +forceinline m4 m4_scale( float s ) { + return m4( + s, 0, 0, 0, + 0, s, 0, 0, + 0, 0, s, 0, + 0, 0, 0, 1 + ); +} + +forceinline m4 m4_scale( float x, float y, float z ) { + return m4( + x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, 0, + 0, 0, 0, 1 + ); +} + +forceinline m4 m4_rotx( float theta ) { + float s = sinf( theta ); + float c = cosf( theta ); + return m4( + 1, 0, 0, 0, + 0, c, -s, 0, + 0, s, c, 0, + 0, 0, 0, 1 + ); +} + +forceinline m4 m4_roty( float theta ) { + float s = sinf( theta ); + float c = cosf( theta ); + return m4( + c, 0, s, 0, + 0, 1, 0, 0, + -s, 0, c, 0, + 0, 0, 0, 1 + ); +} + +forceinline m4 m4_rotz( float theta ) { + float s = sinf( theta ); + float c = cosf( theta ); + return m4( + c, -s, 0, 0, + s, c, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ); +} + +forceinline m4 m4_translation( float x, float y, float z ) { + return m4( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + x, y, z, 1 + ); +} + +forceinline m4 m4_translation( v3 xyz ) { + return m4_translation( xyz.x, xyz.y, xyz.z ); +} + +forceinline m4 m4_ortho( float left, float right, float top, float bottom, float near, float far ) { + return m4( + 2.0f / ( right - left ), + 0.0f, + 0.0f, + 0.0f, + + 0.0f, + 2.0f / ( top - bottom ), + 0.0f, + 0.0f, + + 0.0f, + 0.0f, + -2.0f / ( far - near ), + 0.0f, + + ( right + left ) / ( left - right ), + ( top + bottom ) / ( bottom - top ), + ( far + near ) / ( near - far ), + 1.0f + ); +} + +forceinline m4 m4_perspective( float vertical_fov_degrees, float aspect_ratio, float near, float far ) { + float vertical_fov = vertical_fov_degrees * M_PI / 180.0f / 2.0f; + float horizontal_fov = atanf( tanf( vertical_fov ) * aspect_ratio ); + + return m4( + 1.0f / tanf( horizontal_fov ), + 0.0f, + 0.0f, + 0.0f, + + 0.0f, + 1.0f / tanf( vertical_fov ), + 0.0f, + 0.0f, + + 0.0f, + 0.0f, + ( far + near ) / ( near - far ), + -1.0f, + + 0.0f, + 0.0f, + ( 2.0f * far * near ) / ( near - far ), + 0.0f + ); +} + +forceinline v4 operator*( const m4 & m, v4 v ) { + return v4( + dot( m.row0, v ), + dot( m.row1, v ), + dot( m.row2, v ), + dot( m.row3, v ) + ); +} + +forceinline m4 operator*( const m4 & lhs, const m4 & rhs ) { + return m4( + dot( lhs.row0, rhs.col0() ), + dot( lhs.row0, rhs.col1() ), + dot( lhs.row0, rhs.col2() ), + dot( lhs.row0, rhs.col3() ), + + dot( lhs.row1, rhs.col0() ), + dot( lhs.row1, rhs.col1() ), + dot( lhs.row1, rhs.col2() ), + dot( lhs.row1, rhs.col3() ), + + dot( lhs.row2, rhs.col0() ), + dot( lhs.row2, rhs.col1() ), + dot( lhs.row2, rhs.col2() ), + dot( lhs.row2, rhs.col3() ), + + dot( lhs.row3, rhs.col0() ), + dot( lhs.row3, rhs.col1() ), + dot( lhs.row3, rhs.col2() ), + dot( lhs.row3, rhs.col3() ) + ); +} + +/* + * quat + */ + #endif // _LINEAR_ALGEBRA_H_