/*************************************************************************** * Vec3.h * * * * Basic operations on 3-dimensional vectors. This special case is useful * * because many operations are performed inline. * * * * HISTORY * * Name Date Description * * * * arvo 10/27/94 Reorganized (removed Col & Row distinction). * * arvo 06/14/93 Initial coding. * * * *--------------------------------------------------------------------------* * Copyright (C) 1994, James Arvo * * * * This program is free software; you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the * * Free Software Foundation. See http://www.fsf.org/copyleft/gpl.html * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT EXPRESS OR IMPLIED WARRANTY of merchantability or fitness for * * any particular purpose. See the GNU General Public License for more * * details. * * * ***************************************************************************/ #ifndef __VEC3_INCLUDED__ #define __VEC3_INCLUDED__ #include #include #include class Vec3 { public: Vec3( float c = 0.0 ) { x = c; y = c; z = c; } Vec3( float a, float b, float c ) { x = a; y = b; z = c; } Vec3( const Vec3 &A ) { x = A.X(); y = A.Y(); z = A.Z(); } void operator=( float c ) { x = c; y = c; z = c; } void operator=( const Vec3 &A ) { x = A.X(); y = A.Y(); z = A.Z(); } void operator=( const Vec2 &A ) { x = A.X(); y = A.Y(); z = 0.0; } ~Vec3() {} float X() const { return x; } float Y() const { return y; } float Z() const { return z; } float & X() { return x; } float & Y() { return y; } float & Z() { return z; } float operator[]( int i ) const { return *( &x + i ); } float & operator[]( int i ) { return *( &x + i ); } private: float x, y, z; }; class Mat3x3 { public: inline Mat3x3( ); Mat3x3( const Mat3x3 &M ) { *this = M; } Mat3x3( const Vec3 &, const Vec3 &, const Vec3 & ); // Three columns. ~Mat3x3( ) {} float operator()( int i, int j ) const { return m[i][j]; } float & operator()( int i, int j ) { return m[i][j]; } Mat3x3 & operator=( float ); Mat3x3 & operator=( const Mat3x3 & ); inline void ScaleRows( float, float, float ); inline void ScaleCols( float, float, float ); void Col( int n, const Vec3 & ); const float *Base() const { return &(m[0][0]); } private: float m[3][3]; }; class Mat4x4 { public: Mat4x4( ); Mat4x4( const Mat4x4 &M ) { *this = M; } Mat4x4( const Mat3x3 &M ) ; ~Mat4x4( ) {} float operator()( int i, int j ) const { return m[i][j]; } float & operator()( int i, int j ) { return m[i][j]; } Mat4x4 & operator=( float ); Mat4x4 & operator=( const Mat4x4 & ); void Row( int i, int j, const Vec3 & ); void Col( int i, int j, const Vec3 & ); void ScaleRows( float, float, float, float ); void ScaleCols( float, float, float, float ); const float *Base() const { return &(m[0][0]); } private: float m[4][4]; }; //========================================== //=== External operators === //========================================== extern Vec3 operator * ( const Mat4x4 &, const Vec3 & ); extern Vec3 operator * ( const Vec3 &, const Mat4x4 & ); extern Mat3x3 operator * ( float , const Mat3x3 & ); extern Mat3x3 operator * ( const Mat3x3 &, float ); extern Mat3x3 operator / ( const Mat3x3 &, double ); extern Mat3x3 & operator *=( Mat3x3 &, float ); extern Mat3x3 & operator *=( Mat3x3 &, const Mat3x3 & ); extern Mat3x3 operator * ( const Mat3x3 &, const Mat3x3 & ); extern Mat3x3 operator + ( const Mat3x3 &, const Mat3x3 & ); extern Mat3x3 & operator +=( Mat3x3 &, const Mat3x3 & ); extern Mat3x3 operator - ( const Mat3x3 &, const Mat3x3 & ); extern Mat3x3 & operator -=( Mat3x3 &, const Mat3x3 & ); extern Mat4x4 operator * ( float , const Mat4x4 & ); extern Mat4x4 operator * ( const Mat4x4 &, float ); extern Mat4x4 operator / ( const Mat4x4 &, float ); extern Mat4x4 & operator *=( Mat4x4 &, float ); extern Mat4x4 operator * ( const Mat4x4 &, const Mat4x4 & ); extern Mat4x4 operator + ( const Mat4x4 &, const Mat4x4 & ); extern Mat4x4 & operator +=( Mat4x4 &, const Mat4x4 & ); extern Mat4x4 operator - ( const Mat4x4 &, const Mat4x4 & ); extern Mat4x4 & operator -=( Mat4x4 &, const Mat4x4 & ); //========================================== //=== Miscellaneous external functions === //========================================== extern Vec3 OrthogonalTo( const Vec3 & ); // A vector orthogonal to that given. extern Vec3 Min ( const Vec3 &, const Vec3 & ); extern Vec3 Max ( const Vec3 &, const Vec3 & ); extern double Angle ( const Vec3 &, const Vec3 & ); extern int Orthonormal ( Vec3 &, Vec3 & ); extern int Orthonormal ( Vec3 &, Vec3 &, Vec3 & ); extern float Trace ( const Mat3x3 & ); extern float Normalize ( Vec3 & ); extern float Norm1 ( const Mat3x3 & ); extern float SupNorm ( const Mat3x3 & ); extern double Determinant ( const Mat3x3 & ); extern Mat3x3 Transp ( const Mat3x3 & ); extern Mat3x3 Householder ( const Vec3 &, const Vec3 & ); extern Mat3x3 Householder ( const Vec3 & ); extern Mat3x3 Rotation3x3 ( float, float, float ); // Values in [0,1]. extern Mat3x3 Inverse ( const Mat3x3 & ); extern Mat3x3 Diag3x3 ( const Vec3 & ); extern Mat3x3 Diag3x3 ( float, float, float ); extern Mat3x3 Rotation3x3 ( const Vec3 &Axis, float angle ); extern Mat4x4 Rotation4x4 ( const Vec3 &Axis, const Vec3 &Origin, float angle ); //========================================== //=== Norm-related functions === //========================================== inline double LenSqr ( const Vec3 &A ) { return Sqr(A[0]) + Sqr(A[1]) + Sqr(A[2]); } inline double Len ( const Vec3 &A ) { return Sqrt( LenSqr( A ) ); } inline double Norm1 ( const Vec3 &A ) { return Abs(A[0]) + Abs(A[1]) + Abs(A[2]); } inline double Norm2 ( const Vec3 &A ) { return Len( A ); } inline float SupNorm( const Vec3 &A ) { return MaxAbs( A[0], A[1], A[2] ); } //========================================== //=== Addition === //========================================== inline Vec3 operator+( const Vec3 &A, const Vec3 &B ) { return Vec3( A.X() + B.X(), A.Y() + B.Y(), A.Z() + B.Z() ); } inline Vec3& operator+=( Vec3 &A, const Vec3 &B ) { A.X() += B.X(); A.Y() += B.Y(); A.Z() += B.Z(); return A; } //========================================== //=== Subtraction === //========================================== inline Vec3 operator-( const Vec3 &A, const Vec3 &B ) { return Vec3( A.X() - B.X(), A.Y() - B.Y(), A.Z() - B.Z() ); } inline Vec3 operator-( const Vec3 &A ) { return Vec3( -A.X(), -A.Y(), -A.Z() ); } inline Vec3& operator-=( Vec3 &A, const Vec3 &B ) { A.X() -= B.X(); A.Y() -= B.Y(); A.Z() -= B.Z(); return A; } //========================================== //=== Multiplication === //========================================== inline Vec3 operator*( float a, const Vec3 &x ) { return Vec3( a * x.X(), a * x.Y(), a * x.Z() ); } inline Vec3 operator*( const Vec3 &x, float a ) { return Vec3( a * x.X(), a * x.Y(), a * x.Z() ); } inline float operator*( const Vec3 &A, const Vec3 &B ) // Inner product. { return A.X() * B.X() + A.Y() * B.Y() + A.Z() * B.Z(); } inline Vec3& operator*=( Vec3 &A, float a ) { A.X() *= a; A.Y() *= a; A.Z() *= a; return A; } inline Vec3& operator*=( Vec3 &A, const Mat3x3 &M ) // A = M * A { float x = M(0,0) * A.X() + M(0,1) * A.Y() + M(0,2) * A.Z(); float y = M(1,0) * A.X() + M(1,1) * A.Y() + M(1,2) * A.Z(); float z = M(2,0) * A.X() + M(2,1) * A.Y() + M(2,2) * A.Z(); A.X() = x; A.Y() = y; A.Z() = z; return A; } inline Vec3& operator*=( Vec3 &A, const Mat4x4 &M ) // A = M * A { float x = M(0,0) * A.X() + M(0,1) * A.Y() + M(0,2) * A.Z() + M(0,3); float y = M(1,0) * A.X() + M(1,1) * A.Y() + M(1,2) * A.Z() + M(1,3); float z = M(2,0) * A.X() + M(2,1) * A.Y() + M(2,2) * A.Z() + M(2,3); A.X() = x; A.Y() = y; A.Z() = z; return A; } //========================================== //=== Division === //========================================== inline Vec3 operator/( const Vec3 &A, double c ) { double t = 1.0 / c; return Vec3( A.X() * t, A.Y() * t, A.Z() * t ); } inline Vec3& operator/=( Vec3 &A, double a ) { A.X() /= a; A.Y() /= a; A.Z() /= a; return A; } inline Vec3 operator/( const Vec3 &A, const Vec3 &B ) // Remove component parallel to B. { Vec3 C; // Cumbersome due to compiler falure. double x = LenSqr( B ); if( x > 0.0 ) C = A - B * (( A * B ) / x); else C = A; return C; } inline void operator/=( Vec3 &A, const Vec3 &B ) // Remove component parallel to B. { double x = LenSqr( B ); if( x > 0.0 ) A -= B * (( A * B ) / x); } //========================================== //=== Miscellaneous === //========================================== inline float operator|( const Vec3 &A, const Vec3 &B ) // Inner product. { return A * B; } inline Vec3 Unit( const Vec3 &A ) { double d = LenSqr( A ); return d > 0.0 ? A / sqrt(d) : Vec3(0,0,0); } inline Vec3 Unit( float x, float y, float z ) { return Unit( Vec3( x, y, z ) ); } inline Vec3 Ortho( const Vec3 &A, const Vec3 &B ) { return Unit( A / B ); } inline int operator==( const Vec3 &A, float x ) { return (A[0] == x) && (A[1] == x) && (A[2] == x); } inline Vec3 operator^( const Vec3 &A, const Vec3 &B ) { return Vec3( A.Y() * B.Z() - A.Z() * B.Y(), A.Z() * B.X() - A.X() * B.Z(), A.X() * B.Y() - A.Y() * B.X() ); } inline double dist( const Vec3 &A, const Vec3 &B ) { return Len( A - B ); } inline double Dihedral( const Vec3 &A, const Vec3 &B, const Vec3 &C ) { return ArcCos( Unit( A ^ B ) * Unit( C ^ B ) ); } inline Vec3 operator>>( const Vec3 &A, const Vec3 &B ) // Project A onto B. { Vec3 C; double x = LenSqr( B ); if( x > 0.0 ) C = B * (( A * B ) / x); return C; } inline Vec3 operator<<( const Vec3 &A, const Vec3 &B ) // Project B onto A. { return B >> A; } inline double Triple( const Vec3 &A, const Vec3 &B, const Vec3 &C ) { return ( A ^ B ) * C; } //========================================== //=== Operations involving Matrices === //========================================== inline Mat3x3 Outer( const Vec3 &A, const Vec3 &B ) // Outer product. { Mat3x3 C; C(0,0) = A.X() * B.X(); C(0,1) = A.X() * B.Y(); C(0,2) = A.X() * B.Z(); C(1,0) = A.Y() * B.X(); C(1,1) = A.Y() * B.Y(); C(1,2) = A.Y() * B.Z(); C(2,0) = A.Z() * B.X(); C(2,1) = A.Z() * B.Y(); C(2,2) = A.Z() * B.Z(); return C; } inline Vec3 operator*( const Mat3x3 &M, const Vec3 &A ) { return Vec3( M(0,0) * A[0] + M(0,1) * A[1] + M(0,2) * A[2], M(1,0) * A[0] + M(1,1) * A[1] + M(1,2) * A[2], M(2,0) * A[0] + M(2,1) * A[1] + M(2,2) * A[2]); } inline Vec3 operator*( const Vec3 &A, const Mat3x3 &M ) { return Vec3( A[0] * M(0,0) + A[1] * M(1,0) + A[2] * M(2,0), A[0] * M(0,1) + A[1] * M(1,1) + A[2] * M(2,1), A[0] * M(0,2) + A[1] * M(1,2) + A[2] * M(2,2)); } //========================================== //=== Operations on Matrices === //========================================== inline Mat3x3 operator+( const Mat3x3 &A, const Mat3x3 &B ) { Mat3x3 C; C(0,0) = A(0,0) + B(0,0); C(0,1) = A(0,1) + B(0,1); C(0,2) = A(0,2) + B(0,2); C(1,0) = A(1,0) + B(1,0); C(1,1) = A(1,1) + B(1,1); C(1,2) = A(1,2) + B(1,2); C(2,0) = A(2,0) + B(2,0); C(2,1) = A(2,1) + B(2,1); C(2,2) = A(2,2) + B(2,2); return C; } inline Mat3x3 operator-( const Mat3x3 &A, const Mat3x3 &B ) { Mat3x3 C; C(0,0) = A(0,0) - B(0,0); C(0,1) = A(0,1) - B(0,1); C(0,2) = A(0,2) - B(0,2); C(1,0) = A(1,0) - B(1,0); C(1,1) = A(1,1) - B(1,1); C(1,2) = A(1,2) - B(1,2); C(2,0) = A(2,0) - B(2,0); C(2,1) = A(2,1) - B(2,1); C(2,2) = A(2,2) - B(2,2); return C; } inline Mat3x3 operator*( const Mat3x3 &A, const Mat3x3 &B ) { Mat3x3 C; C(0,0) = A(0,0) * B(0,0) + A(0,1) * B(1,0) + A(0,2) * B(2,0); C(0,1) = A(0,0) * B(0,1) + A(0,1) * B(1,1) + A(0,2) * B(2,1); C(0,2) = A(0,0) * B(0,2) + A(0,1) * B(1,2) + A(0,2) * B(2,2); C(1,0) = A(1,0) * B(0,0) + A(1,1) * B(1,0) + A(1,2) * B(2,0); C(1,1) = A(1,0) * B(0,1) + A(1,1) * B(1,1) + A(1,2) * B(2,1); C(1,2) = A(1,0) * B(0,2) + A(1,1) * B(1,2) + A(1,2) * B(2,2); C(2,0) = A(2,0) * B(0,0) + A(2,1) * B(1,0) + A(2,2) * B(2,0); C(2,1) = A(2,0) * B(0,1) + A(2,1) * B(1,1) + A(2,2) * B(2,1); C(2,2) = A(2,0) * B(0,2) + A(2,1) * B(1,2) + A(2,2) * B(2,2); return C; } inline void Mat3x3::ScaleRows( float a, float b, float c ) { m[0][0] *= a; m[0][1] *= a; m[0][2] *= a; m[1][0] *= b; m[1][1] *= b; m[1][2] *= b; m[2][0] *= c; m[2][1] *= c; m[2][2] *= c; } inline void Mat3x3::ScaleCols( float a, float b, float c ) { m[0][0] *= a; m[0][1] *= b; m[0][2] *= c; m[1][0] *= a; m[1][1] *= b; m[1][2] *= c; m[2][0] *= a; m[2][1] *= b; m[2][2] *= c; } //========================================== //=== Special Matrices === //========================================== inline Mat3x3::Mat3x3() { m[0][0] = 0; m[0][1] = 0; m[0][2] = 0; m[1][0] = 0; m[1][1] = 0; m[1][2] = 0; m[2][0] = 0; m[2][1] = 0; m[2][2] = 0; } inline Mat3x3 Ident3x3() { Mat3x3 I; I(0,0) = 1.0; I(1,1) = 1.0; I(2,2) = 1.0; return I; } inline Mat4x4 Ident4x4() { Mat4x4 I; I(0,0) = 1.0; I(1,1) = 1.0; I(2,2) = 1.0; I(3,3) = 1.0; return I; } inline void Adjoint( const Mat3x3 &M, Mat3x3 &A ) { A(0,0) = M(1,1) * M(2,2) - M(1,2) * M(2,1); A(0,1) = M(1,2) * M(2,0) - M(1,0) * M(2,2); A(0,2) = M(1,0) * M(2,1) - M(1,1) * M(2,0); A(1,0) = M(0,2) * M(2,1) - M(0,1) * M(2,2); A(1,1) = M(0,0) * M(2,2) - M(0,2) * M(2,0); A(1,2) = M(0,1) * M(2,0) - M(0,0) * M(2,1); A(2,0) = M(0,1) * M(1,2) - M(0,2) * M(1,1); A(2,1) = M(0,2) * M(1,0) - M(0,0) * M(1,2); A(2,2) = M(0,0) * M(1,1) - M(0,1) * M(1,0); } inline void TranspAdjoint( const Mat3x3 &M, Mat3x3 &A ) { A(0,0) = M(1,1) * M(2,2) - M(1,2) * M(2,1); A(1,0) = M(1,2) * M(2,0) - M(1,0) * M(2,2); A(2,0) = M(1,0) * M(2,1) - M(1,1) * M(2,0); A(0,1) = M(0,2) * M(2,1) - M(0,1) * M(2,2); A(1,1) = M(0,0) * M(2,2) - M(0,2) * M(2,0); A(2,1) = M(0,1) * M(2,0) - M(0,0) * M(2,1); A(0,2) = M(0,1) * M(1,2) - M(0,2) * M(1,1); A(1,2) = M(0,2) * M(1,0) - M(0,0) * M(1,2); A(2,2) = M(0,0) * M(1,1) - M(0,1) * M(1,0); } inline void Adjoint( const Mat3x3 &M, Mat3x3 &A, double &det ) { Adjoint( M, A ); det = A(0,0) * M(0,0) + A(1,0) * M(1,0) + A(2,0) * M(2,0); } inline void TranspAdjoint( const Mat3x3 &M, Mat3x3 &A, double &det ) { TranspAdjoint( M, A ); det = A(0,0) * M(0,0) + A(0,1) * M(1,0) + A(0,2) * M(2,0); } //========================================== //=== Output routines === //========================================== extern ostream &operator<<( ostream &out, const Vec3 & ); extern ostream &operator<<( ostream &out, const Mat3x3 & ); extern ostream &operator<<( ostream &out, const Mat4x4 & ); #endif