http://hi.baidu.com/zyb_debug/blog/item/b837e41ffd64f7fd1ad5761b.html
以前一直有个想法就是写标题上的ADT,但一直担心自己写的效率不高。

最近看了一段源码,终于圆了我的梦想。

话不多说,国外高手写的matrix,想法果然不一样,直接看代码吧。

来自 《游戏编程精粹1》

mtxlib.h
/* Copyright (C) Dante Treglia II and Mark A. DeLoura, 2000. 
 * All rights reserved worldwide.
 *
 * This software is provided "as is" without express or implied
 * warranties. You may freely copy and compile this source into
 * applications you distribute provided that the copyright text
 * below is included in the resulting source code, for example:
 * "Portions Copyright (C) Dante Treglia II and Mark A. DeLoura, 2000"
 
*/
//==========================================================
// C++ Matrix Library
// Version: 2.6
// Date: May 19, 2000
// Authors: Dante Treglia II and Mark A. DeLoura
// Thanks to: Miguel Gomez, Stan Melax, Pete Isensee, 
//   Gabor Nagy, Scott Bilas, James Boer, Eric Lengyel
//==========================================================

#ifndef _MTXLIB_H
#define _MTXLIB_H
#include 
<cstdio>
#include 
<cmath>
#include 
<cassert>

static inline float DegToRad(float a) { return a*0.01745329252f;};
static inline float RadToDeg(float a) { return a*57.29577951f;};

class vector2;
class vector3;
class vector4;
class matrix33;
class matrix44;

////////////////////////////////////////////////////////////
// vector2 class
//

class vector2 
{
public:
  
// Members
  float x, y;

public:
  
// Constructors
  vector2() {};
  
// Constructor with initializing float values
  vector2(float inX, float inY): x(inX), y(inY) {}
  
// Constructor with initializing vector2
  vector2(const vector2 &v): x(v.x), y(v.y) {}

public:
  
// Array indexing
  float                 &operator [] (unsigned int i) {
    assert (i
<2);
    
return *(&x+i);
  }
  
// Array indexing
  const float           &operator [] (unsigned int i) const {
    assert (i
<2);
    
return *(&x+i);
  }
  
// Add a vector2 to this one
  vector2               &operator += (const vector2 &v) {
    x 
+= v.x;
    y 
+= v.y;
    
return *this;
  }
  
// Subtract a vector2 from this one
  vector2               &operator -= (const vector2 &v) {
    x 
-= v.x;
    y 
-= v.y;
    
return *this;
  }
  
// Multiply the vector2 by a float
  vector2               &operator *= (float f) {
    x 
*= f;
    y 
*= f;
    
return *this;
  }
  
// Divide the vector2 by a float
  vector2               &operator /= (float f) {
    x 
/= f;
    y 
/= f;
    
return *this;
  }
  
// Are these two vector2's equal?
  friend bool           operator == (const vector2 &a, const vector2 &b) {
    
return((a.x == b.x) && (a.y == b.y));
  }
  
// Are these two vector2's not equal?
  friend bool           operator != (const vector2 &a, const vector2 &b) {
    
return((a.x != b.x) || (a.y != b.y));
  }
  
// Negate this vector
  friend vector2        operator - (const vector2 &a) {
    
return vector2(-a.x, -a.y);
  }
  
// Add two vector2's
  friend vector2        operator + (const vector2 &a, const vector2 &b) {
    vector2 ret(a);
    ret 
+= b;
    
return ret;
  }
  
// Subtract one vector2 from another
  friend vector2        operator - (const vector2 &a, const vector2 &b) {
    vector2 ret(a);
    ret 
-= b;
    
return ret;
  }
  
// Multiply vector2 by a float
  friend vector2        operator * (const vector2 &v, float f) {
    
return vector2(f * v.x, f * v.y);
  }
  
// Multiply vector2 by a float
  friend vector2        operator * (float f, const vector2 &v) {
    
return vector2(f * v.x, f * v.y);
  }
  
// Divide vector2 by a float
  friend vector2        operator / (const vector2 &v, float f) {
    
return vector2(v.x / f, v.y / f);
  }

public:
  
// Methods
  
// Set Values
  void                  set(float xIn, float yIn) {
    x 
= xIn;
    y 
= yIn;
  }
  
// Get length of a vector2
  float                 length() const {
    
return(float) sqrt(x*+ y*y);
  }
  
// Get squared length of a vector2
  float                 lengthSqr() const {
    
return(x*+ y*y);
  }
  
// Does vector2 equal (0, 0)?
  bool                  isZero() const {
    
return((x == 0.0F&& (y == 0.0F));
  }
  
// Normalize a vector2
  vector2               &normalize() {
    
float m = length();

    
if (m > 0.0F)
      m 
= 1.0F / m;
    
else
      m 
= 0.0F;
    x 
*= m;
    y 
*= m;

    
return *this;
  }

  
// Debug
  void                  fprint(FILE* file, char* str) const;
};


////////////////////////////////////////////////////////////
// vector3 class
//

class vector3 
{
public:
  
// Members
  float x, y, z;

public:
  
// Constructors
  vector3() {};
  
// Constructor with initializing float values
  vector3(float inX, float inY, float inZ): x(inX), y(inY), z(inZ) {}
  
// Constructor with initializing vector3
  vector3(const vector3 &v): x(v.x), y(v.y), z(v.z) {}
  
// Constructor with initializing vector2
  explicit vector3(const vector2 &v): x(v.x), y(v.y), z(0.0F) {}
  
// Constructor with initializing vector4
  
// TODO
  explicit vector3(const vector4 &v);

public:
  
// Operators
  
// Array indexing
  float                 &operator [] (unsigned int i) {
    assert (i
<3);
    
return *(&x+i);
  }
  
// Array indexing
  const float           &operator [] (unsigned int i) const {
    assert (i
<3);
    
return *(&x+i);
  }
  
// Assign from a vector2
  vector3               &operator =  (const vector2 &v) {
    x 
= v.x;
    y 
= v.y;
    z 
= 0.0F;
    
return *this;
  }
  
// Add a vector3 to this one
  vector3               &operator += (const vector3 &v) {
    x 
+= v.x;
    y 
+= v.y;
    z 
+= v.z;
    
return *this;
  }
  
// Subtract a vector3 from this one
  vector3               &operator -= (const vector3 &v) {
    x 
-= v.x;
    y 
-= v.y;
    z 
-= v.z;
    
return *this;
  }
  
// Multiply the vector3 by a float
  vector3               &operator *= (float f) {
    x 
*= f;
    y 
*= f;
    z 
*= f;
    
return *this;
  }
  
// Divide the vector3 by a float
  vector3               &operator /= (float f) {
    x 
/= f;
    y 
/= f;
    z 
/= f;
    
return *this;
  }
  
// Are these two vector3's equal?
  friend bool           operator == (const vector3 &a, const vector3 &b) {
    
return((a.x == b.x) && (a.y == b.y) && (a.z == b.z));
  }
  
// Are these two vector3's not equal?
  friend bool           operator != (const vector3 &a, const vector3 &b) {
    
return((a.x != b.x) || (a.y != b.y) || (a.z != b.z));
  }
  
// Negate a vector3
  friend vector3        operator - (const vector3 &a) {
    
return vector3(-a.x, -a.y, -a.z);
  }
  
// Add two vector3's
  friend vector3        operator + (const vector3 &a, const vector3 &b) {
    vector3 ret(a);
    ret 
+= b;
    
return ret;
  }
  
// Subtract one vector3 from another
  friend vector3        operator - (const vector3 &a, const vector3 &b) {
    vector3 ret(a);
    ret 
-= b;
    
return ret;
  }
  
// Multiply vector3 by a float
  friend vector3        operator * (const vector3 &v, float f) {
    
return vector3(f * v.x, f * v.y, f * v.z);
  }
  
// Multiply vector3 by a float
  friend vector3        operator * (float f, const vector3 &v) {
    
return vector3(f * v.x, f * v.y, f * v.z);
  }
  
// Divide vector3 by a float
  friend vector3        operator / (const vector3 &v, float f) {
    
return vector3(v.x / f, v.y / f, v.z / f);
  }

public:
  
// Methods
  
// Set Values
  void                  set(float xIn, float yIn, float zIn) {
    x 
= xIn;
    y 
= yIn;
    z 
= zIn;
  }
  
// Get length of a vector3
  float                 length() const {
    
return(float) sqrt(x*+ y*+ z*z);
  }
  
// Get squared length of a vector3
  float                 lengthSqr() const {
    
return(x*+ y*+ z*z);
  }
  
// Does vector3 equal (0, 0, 0)?
  bool                  isZero() const {
    
return((x == 0.0F&& (y == 0.0F&& (z == 0.0F));
  }
  
// Normalize a vector3
  vector3               &normalize() {
    
float m = length();
    
if (m > 0.0F)
      m 
= 1.0F / m;
    
else
      m 
= 0.0F;
    x 
*= m;
    y 
*= m;
    z 
*= m;
    
return *this;
  }

  
// Debug
  void                  fprint(FILE* file, char* str) const;
};


////////////////////////////////////////////////////////////
// vector4 class
//

class vector4 
{
public:
  
// Members
  float x, y, z, w;

public:
  
// Constructors
  
// vector4(): x(0), y(0), z(0), w(0) {};
  vector4() {};
  
// Constructor with initializing float values
  vector4(float inX, float inY, float inZ, float inW): x(inX), y(inY), z(inZ), w(inW) {};
  
// Constructor with initializing vector4
  vector4(const vector4 &v): x(v.x), y(v.y), z(v.z), w(v.w) {};
  
// Constructor with initializing vector3
  explicit vector4(const vector3 &v): x(v.x), y(v.y), z(v.z), w(0.0F) {};
  
// Constructor with initializing vector2
  explicit vector4(const vector2 &v): x(v.x), y(v.y), z(0.0F), w(0.0F) {};

public:
  
// Operators
  
// Array indexing
  float                 &operator [] (unsigned int i) {
    assert (i
<4);
    
//return *(&x+i);
    return(i == 0? x : (i == 1? y : (i == 2? z : w;
  }
  
// Array indexing
  const float           &operator [] (unsigned int i) const {
    assert (i
<4);
    
//return *(&x+i);
    return(i == 0? x : (i == 1? y : (i == 2? z : w;
  }
  
// Assign from a vector3
  vector4               &operator =  (const vector3 &v) { 
    x 
= v.x;
    y 
= v.y;
    z 
= v.z;
    w 
= 0.0F;
    
return *this;
  }
  
// Assign from a vector2
  vector4               &operator =  (const vector2 &v) {
    x 
= v.x;
    y 
= v.y;
    z 
= 0.0F;
    w 
= 0.0F;
    
return *this;
  }
  
// Add a vector4 to this one
  vector4               &operator += (const vector4 &v) {
    x 
+= v.x;
    y 
+= v.y;
    z 
+= v.z;
    w 
+= v.w;
    
return *this;
  }
  
// Subtract a vector4 from this one
  vector4               &operator -= (const vector4 &v) {
    x 
-= v.x;
    y 
-= v.y;
    z 
-= v.z;
    w 
-= v.w;
    
return *this;
  }
  
// Multiply the vector4 by a float
  vector4               &operator *= (float f) {
    x 
*= f;
    y 
*= f;
    z 
*= f;
    w 
*= f;
    
return *this;
  }
  
// Divide the vector4 by a float
  vector4               &operator /= (float f) {
    x 
/= f;
    y 
/= f;
    z 
/= f;
    w 
/= f;
    
return *this;
  }
  
// Are these two vector4's equal?
  friend bool           operator == (const vector4 &a, const vector4 &b) {
    
return((a.x == b.x) && (a.y == b.y) &&
        (a.z 
== b.z) && (a.w == b.w));
  }
  
// Are these two vector4's not equal?
  friend bool           operator != (const vector4 &a, const vector4 &b) {
    
return((a.x != b.x) || (a.y != b.y) ||
        (a.z 
!= b.z) || (a.w != b.w));
  }
  
// Negate a vector4
  friend vector4        operator - (const vector4 &a) {
    
return vector4(-a.x, -a.y, -a.z, -a.w);
  }
  
// Add two vector4's
  friend vector4        operator + (const vector4 &a, const vector4 &b) {
    vector4 ret(a);
    ret 
+= b;
    
return ret;
  }
  
// Subtract one vector4 from another
  friend vector4        operator - (const vector4 &a, const vector4 &b) {
    vector4 ret(a);
    ret 
-= b;
    
return ret;
  }
  
// Multiply vector4 by a float
  friend vector4        operator * (const vector4 &v, float f) {
    
return vector4(f * v.x, f * v.y, f * v.z, f * v.w);
  }
  
// Multiply vector4 by a float
  friend vector4        operator * (float f, const vector4 &v) {
    
return vector4(f * v.x, f * v.y, f * v.z, f * v.w);
  }
  
// Divide vector4 by a float
  friend vector4        operator / (const vector4 &v, float f) {
    
return vector4(v.x / f, v.y / f, v.z / f, v.w / f);
  }

public:
  
// Methods
  
// Set Values
  void                  set(float xIn, float yIn, float zIn, float wIn) {
    x 
= xIn;
    y 
= yIn;
    z 
= zIn;
    w 
= wIn;
  }
  
// Get length of a vector4
  float                 length() const {
    
return(float) sqrt(x*+ y*+ z*+ w*w);
  }
  
// Get squared length of a vector4
  float                 lengthSqr() const {
    
return(x*+ y*+ z*+ w*w);
  }
  
// Does vector4 equal (0, 0, 0, 0)?
  bool                  isZero() const {
    
return((x == 0.0F&& (y == 0.0F&& (z == 0.0F&& (w == 0.0F));
  }
  
// Normalize a vector4
  vector4               &normalize() {
    
float m = length();
    
if (m > 0.0F)
      m 
= 1.0F / m;
    
else
      m 
= 0.0F;
    x 
*= m;
    y 
*= m;
    z 
*= m;
    w 
*= m;
    
return *this;
  }

  
// Debug
  void                  fprint(FILE* file, char* str) const;
};


////////////////////////////////////////////////////////////
// Miscellaneous vector functions
//

vector2 Normalized(
const vector2 &a);
vector3 Normalized(
const vector3 &a);
vector4 Normalized(
const vector4 &a);
float DotProduct(const vector2 &a, const vector2 &b);
float DotProduct(const vector3 &a, const vector3 &b);
float DotProduct(const vector4 &a, const vector4 &b);
void SwapVec(vector2 &a, vector2 &b);
void SwapVec(vector3 &a, vector3 &b);
void SwapVec(vector4 &a, vector4 &b);
vector3 CrossProduct(
const vector3 &a, const vector3 &b);
bool NearlyEquals(const vector2 &a, const vector2 &b, float r);
bool NearlyEquals(const vector3 &a, const vector3 &b, float r);
bool NearlyEquals(const vector4 &a, const vector4 &b, float r);


////////////////////////////////////////////////////////////
// matrix33 class
//

class matrix33 
{
public:
  
// Members
  vector3       col[3];

public:
  
// Constructors
  matrix33() {};
  
// Constructor with initializing value
  matrix33(float v) {
    col[
0].set(v, v, v);
    col[
1].set(v, v, v);
    col[
2].set(v, v, v);
  }
  
// Constructor with initializing matrix33
  matrix33(const matrix33 &m) {
    col[
0= m[0];
    col[
1= m[1];
    col[
2= m[2];
  }
  
// Constructor with initializing vector3's
  matrix33(const vector3 &v0, const vector3 &v1, const vector3 &v2) {
    col[
0= v0;
    col[
1= v1;
    col[
2= v2;
  }

public:
  
// Operators
  
// Array indexing
  vector3       &operator [] (unsigned int i) {
    assert (i
<3);
    
return(vector3&)col[i];
  }
  
// Array indexing
  const vector3     &operator [] (unsigned int i) const {
    assert (i
<3);
    
return(vector3&)col[i];
  }
  
// Assign
  matrix33      &operator =  (const matrix33 &m) {
    col[
0= m[0];
    col[
1= m[1];
    col[
2= m[2];
    
return *this;
  }
  
// Add a matrix33 to this one
  matrix33      &operator += (const matrix33 &m) {
    col[
0+= m[0];
    col[
1+= m[1];
    col[
2+= m[2];
    
return *this;
  }
  
// Subtract a matrix33 from this one
  matrix33      &operator -= (const matrix33 &m) {
    col[
0-= m[0];
    col[
1-= m[1];
    col[
2-= m[2];
    
return *this;
  }
  
// Multiply the matrix33 by another matrix33
  matrix33      &operator *= (const matrix33 &m);
  
// Multiply the matrix33 by a float
  matrix33      &operator *= (float f) {
    col[
0*= f;
    col[
1*= f;
    col[
2*= f;
    
return *this;
  }
  
// Are these two matrix33's equal?
  friend bool       operator == (const matrix33 &a, const matrix33 &b) {
    
return((a[0== b[0]) && (a[1== b[1]) && (a[2== b[2]));
  }
  
// Are these two matrix33's not equal?
  friend bool       operator != (const matrix33 &a, const matrix33 &b) {
    
return((a[0!= b[0]) || (a[1!= b[1]) || (a[2!= b[2]));
  }
  
// Add two matrix33's
  friend matrix33   operator + (const matrix33 &a, const matrix33 &b) {
    matrix33 ret(a);
    ret 
+= b;
    
return ret;
  }
  
// Subtract one matrix33 from another
  friend matrix33   operator - (const matrix33 &a, const matrix33 &b) {
    matrix33 ret(a);
    ret 
-= b;
    
return ret;
  }
  
// Multiply matrix33 by another matrix33
  friend matrix33   operator * (const matrix33 &a, const matrix33 &b) {
    matrix33 ret(a);
    ret 
*= b;
    
return ret;
  }
  
// Multiply a vector3 by this matrix33
  friend vector3    operator * (const matrix33 &m, const vector3 &v) {
    vector3 ret;
    ret.x 
= v.x * m[0][0+ v.y * m[1][0+ v.z * m[2][0];
    ret.y 
= v.x * m[0][1+ v.y * m[1][1+ v.z * m[2][1];
    ret.z 
= v.x * m[0][2+ v.y * m[1][2+ v.z * m[2][2];
    
return ret;
  }
  
// Multiply a vector3 by this matrix33
  friend vector3    operator * (const vector3 &v, const matrix33 &m) {
    vector3 ret;
    ret.x 
= DotProduct(m[0], v);
    ret.y 
= DotProduct(m[1], v);
    ret.z 
= DotProduct(m[2], v);
    
return ret;
  }
  
// Multiply matrix33 by a float
  friend matrix33   operator * (const matrix33 &m, float f) {
    matrix33 ret(m);
    ret 
*= f;
    
return ret;
  }
  
// Multiply matrix33 by a float
  friend matrix33   operator * (float f, const matrix33 &m) {
    matrix33 ret(m);
    ret 
*= f;
    
return ret;
  }

public:
  
// Methods
  
// Set matrix33 to the identity matrix
  matrix33      &identity() {
    col[
0].set(1.00.00.0);
    col[
1].set(0.01.00.0);
    col[
2].set(0.00.01.0);
    
return *this;
  }
  
// Transpose the matrix33
  matrix33      &transpose();
  
// Invert the matrix33
  matrix33      &invert();

  
// Debug
  void          fprint(FILE* file, char* str) const;
};

matrix33    IdentityMatrix33();
matrix33    TransposeMatrix33(
const matrix33 &m);
matrix33    InvertMatrix33(
const matrix33 &m);
matrix33    RotateRadMatrix33(
float rad);
matrix33    TranslateMatrix33(
float x, float y);
matrix33    ScaleMatrix33(
float x, float y, float z = 1.0);


////////////////////////////////////////////////////////////
// matrix44 class
//

class matrix44 
{
public:
  
// Members
  vector4   col[4];

public:
  
// Constructors
  matrix44() {};
  
// Constructor with initializing value
  matrix44(float v) {
    col[
0].set(v, v, v, v);
    col[
1].set(v, v, v, v);
    col[
2].set(v, v, v, v);
    col[
3].set(v, v, v, v);
  }
  
// Constructor with initializing matrix44
  matrix44(const matrix44 &m) {
    col[
0= m[0];
    col[
1= m[1];
    col[
2= m[2];
    col[
3= m[3];
  }
  
// Constructor with initializing vector4's
  matrix44(const vector4 &v0, const vector4 &v1, 
      
const vector4 &v2, const vector4 &v3) {
    col[
0= v0;
    col[
1= v1;
    col[
2= v2;
    col[
3= v3;
  }
  
// Constructor with initializing matrix33
  explicit matrix44(const matrix33 &m) {
    col[
0= m[0];
    col[
1= m[1];
    col[
2= m[2];
    col[
3].set(0.00.00.01.0);
  }

public:
  
// Operators
  
// Array indexing
  vector4       &operator [] (unsigned int i) {
    assert (i
<4);
    
return col[i];
  }
  
// Array indexing
  const vector4     &operator [] (unsigned int i) const {
    assert (i
<4);
    
return col[i];
  }
  
// Assign
  matrix44      &operator =  (const matrix44 &m) {
    col[
0= m[0];
    col[
1= m[1];
    col[
2= m[2];
    col[
3= m[3];
    
return *this;
  }
  
// Assign a matrix33 to the matrix44
  matrix44      &operator =  (const matrix33 &m) {
    col[
0= m[0];
    col[
1= m[1];
    col[
2= m[2];
    col[
3].set(0.00.00.01.0);
    
return *this;
  }
  
// Add a matrix44 to this one
  matrix44      &operator += (const matrix44 &m) {
    col[
0+= m[0];
    col[
1+= m[1];
    col[
2+= m[2];
    col[
3+= m[3];
    
return *this;
  }
  
// Subtract a matrix44 from this one
  matrix44      &operator -= (const matrix44 &m) {
    col[
0-= m[0];
    col[
1-= m[1];
    col[
2-= m[2];
    col[
3-= m[3];
    
return *this;
  }
  
// Multiply the matrix44 by another matrix44
  matrix44      &operator *= (const matrix44 &m);
  
// Multiply the matrix44 by a float
  matrix44      &operator *= (float f) {
    col[
0*= f;
    col[
1*= f;
    col[
2*= f;
    col[
3*= f;
    
return *this;
  }
  
//matrix44      &operator /= (float f) {}
  
// Are these two matrix44's equal?
  friend bool       operator == (const matrix44 &a, const matrix44 &b) {
    
return((a[0== b[0]) && (a[1== b[1]) &&
        (a[
2== b[2]) && (a[3== b[3]));
  }
  
// Are these two matrix44's not equal?
  friend bool       operator != (const matrix44 &a, const matrix44 &b) {
    
return((a[0!= b[0]) || (a[1!= b[1]) ||
        (a[
2!= b[2]) || (a[3!= b[3]));
  }
  
// Add two matrix44's
  friend matrix44   operator + (const matrix44 &a, const matrix44 &b) {
    matrix44 ret(a);
    ret 
+= b;
    
return ret;
  }
  
// Subtract one matrix44 from another
  friend matrix44   operator - (const matrix44 &a, const matrix44 &b) {
    matrix44 ret(a);
    ret 
-= b;
    
return ret;
  }
  
// Multiply matrix44 by another matrix44
  friend matrix44   operator * (const matrix44 &a, const matrix44 &b) {
    matrix44 ret(a);
    ret 
*= b;
    
return ret;
  }
  
// Multiply a vector3 by this matrix44
  friend vector3    operator * (const matrix44 &m, const vector3 &v) {
    vector4 ret(v);
    ret 
= m * ret;
    
return vector3(ret.x, ret.y, ret.z);
  }
  
// Multiply a vector3 by this matrix44
  friend vector3    operator * (const vector3 &v, const matrix44 &m) {
    vector4 ret(v);
    ret 
= ret * m;
    
return vector3(ret.x, ret.y, ret.z);
  }
  
// Multiply a vector4 by this matrix44
  friend vector4    operator * (const matrix44 &m, const vector4 &v) {
    vector4 ret;
    ret.x 
= v.x * m[0][0+ v.y * m[1][0+ v.z * m[2][0+ v.w * m[3][0];
    ret.y 
= v.x * m[0][1+ v.y * m[1][1+ v.z * m[2][1+ v.w * m[3][1];
    ret.z 
= v.x * m[0][2+ v.y * m[1][2+ v.z * m[2][2+ v.w * m[3][2];
    ret.w 
= v.x * m[0][3+ v.y * m[1][3+ v.z * m[2][3+ v.w * m[3][3];
    
return ret;
  }
  
// Multiply a vector4 by this matrix44
  friend vector4    operator * (const vector4 &v, const matrix44 &m) {
    vector4 ret;
    ret.x 
= DotProduct(m[0], v);
    ret.y 
= DotProduct(m[1], v);
    ret.z 
= DotProduct(m[2], v);
    ret.w 
= DotProduct(m[3], v);
    
return ret;
  }
  
// Multiply matrix44 by a float
  friend matrix44   operator * (const matrix44 &m, float f) {
    matrix44 ret(m);
    ret 
*= f;
    
return ret;
  }
  
// Set matrix44 to the identity matrix
  friend matrix44   operator * (float f, const matrix44 &m) {
    matrix44 ret(m);
    ret 
*= f;
    
return ret;
  }

public:
  
// Methods
  
// Set matrix44 to the identity matrix
  matrix44      &identity() {
    col[
0].set(1.00.00.00.0);
    col[
1].set(0.01.00.00.0);
    col[
2].set(0.00.01.00.0);
    col[
3].set(0.00.00.01.0);
    
return *this;
  }
  
// Transpose the matrix44
  matrix44      &transpose();
  
// Invert the matrix44
  matrix44      &invert();

  
// Debug
  void          fprint(FILE* file, char* str) const;
};

matrix44    IdentityMatrix44();
matrix44    TransposeMatrix44(
const matrix44 &m);
matrix44    InvertMatrix44(
const matrix44 &m);
matrix44    RotateRadMatrix44(
char axis, float rad);
matrix44    RotateRadMatrix44(
const vector3 &axis, float rad);
matrix44    TranslateMatrix44(
float x, float y, float z);
matrix44    ScaleMatrix44(
float x, float y, float z, float w = 1.0);
matrix44    LookAtMatrix44(
const vector3 &camPos, const vector3 &camUp, 
    
const vector3 &target );
matrix44    FrustumMatrix44(
float l, float r, float b, float t, 
    
float n, float f);
matrix44    PerspectiveMatrix44(
float fovY, float aspect, 
    
float n, float f);
matrix44    OrthoMatrix44(
float l, float r, float b, float t, 
    
float n, float f);
matrix44    OrthoNormalMatrix44(
const vector3 &xdir, 
    
const vector3 &ydir, const vector3 &zdir);

#endif

mtxlib.cpp
/* Copyright (C) Dante Treglia II and Mark A. DeLoura, 2000. 
 * All rights reserved worldwide.
 *
 * This software is provided "as is" without express or implied
 * warranties. You may freely copy and compile this source into
 * applications you distribute provided that the copyright text
 * below is included in the resulting source code, for example:
 * "Portions Copyright (C) Dante Treglia II and Mark A. DeLoura, 2000"
 
*/
//==========================================================
// C++ Matrix Library
// Version: 2.6
// Date: May 19, 2000
// Authors: Dante Treglia II and Mark A. DeLoura
// Thanks to: Miguel Gomez, Stan Melax, Pete Isensee, 
//   Gabor Nagy, Scott Bilas, James Boer, Eric Lengyel
//==========================================================
#include "mtxlib.h"
#include 
<cmath>
#include 
<cassert>

////////////////////////////////////////////////////////////
// Miscellaneous vector functions
//

// Return Normal of vector2's
vector2 Normalized(const vector2 &a)
{
  vector2 ret(a);
  
return ret.normalize();
}
// Return Normal of vector3's
vector3 Normalized(const vector3 &a)
{
  vector3 ret(a);
  
return ret.normalize();
}
// Return Normal of vector4's
vector4 Normalized(const vector4 &a)
{
  vector4 ret(a);
  
return ret.normalize();
}

// Dot product of two vector2's
float DotProduct(const vector2 &a, const vector2 &b) 
{
  
return a.x*b.x + a.y*b.y;
}

// Dot product of two vector3's
float DotProduct(const vector3 &a, const vector3 &b) 
{
  
return a.x*b.x + a.y*b.y + a.z*b.z;
}

// Dot product of two vector4's
float DotProduct(const vector4 &a, const vector4 &b) 
{
  
return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
}

// Swap two vector2's
void SwapVec(vector2 &a, vector2 &b) 
{
  vector2 tmp(a);

  a 
= b;
  b 
= tmp;
}

// Swap two vector3's
void SwapVec(vector3 &a, vector3 &b) 
{
  vector3 tmp(a);

  a 
= b;
  b 
= tmp;
}

// Swap two vector4's
void SwapVec(vector4 &a, vector4 &b) 
{
  vector4 tmp(a);

  a 
= b;
  b 
= tmp;
}

// Cross product of two vector3's
vector3 CrossProduct(const vector3 &a, const vector3 &b) 
{
  
return vector3(a.y*b.z - a.z*b.y,
      a.z
*b.x - a.x*b.z,
      a.x
*b.y - a.y*b.x);
}

// Are these two vector2's nearly equal?
bool NearlyEquals( const vector2& a, const vector2& b, float r ) 
{
  vector2 diff 
= a - b;  // difference

  
return(DotProduct(diff, diff) < r*r);  // radius
}

// Are these two vector3's nearly equal?
bool NearlyEquals( const vector3& a, const vector3& b, float r ) 
{
  vector3 diff 
= a - b;  // difference

  
return(DotProduct(diff, diff) < r*r);  // radius
}

// Are these two vector4's nearly equal?
bool NearlyEquals( const vector4& a, const vector4& b, float r ) 
{
  vector4 diff 
= a - b;  // difference

  
return(DotProduct(diff, diff) < r*r);  // radius
}


////////////////////////////////////////////////////////////
// matrix33 class
//

// Multiply the matrix33 by another matrix33
matrix33 &matrix33::operator *= (const matrix33 &m) 
{
  matrix33 t;

  
for (unsigned int r = 0; r < 3; r++)
  {
  
for (unsigned int c = 0; c < 3; c++)
  {
    
float f = 0;

    f 
+= col[0][r] * m[c][0];
    f 
+= col[1][r] * m[c][1];
    f 
+= col[2][r] * m[c][2];

    t[c][r] 
= f;
  }
  }

  
*this = t;

  
return *this;
}

// Transpose the matrix33
matrix33 &matrix33::transpose() 
{
  
float t;

  
for (unsigned int c = 0; c < 3; c++)
  {
  
for (unsigned int r = c + 1; r < 3; r++)
  {
    t 
= col[c][r];
    col[c][r] 
= col[r][c];
    col[r][c] 
= t;
  } 
  }

  
return *this;
}

// Invert the matrix33
matrix33 &matrix33::invert() 
{
  matrix33 a(
*this);
  matrix33 b(IdentityMatrix33());

  unsigned 
int c, r;
  unsigned 
int cc;
  unsigned 
int rowMax; // Points to max abs value row in this column
  unsigned int row;
  
float tmp;

  
// Go through columns
  for (c=0; c<3; c++)
  {
  
// Find the row with max value in this column
  rowMax = c;
  
for (r=c+1; r<3; r++)
  {
    
if (fabs(a[c][r]) > fabs(a[c][rowMax]))
    {
    rowMax 
= r;
    }
  }

  
// If the max value here is 0, we can't invert.  Return identity.
  if (a[rowMax][c] == 0.0F)
    
return(identity());

  
// Swap row "rowMax" with row "c"
  for (cc=0; cc<3; cc++)
  {
    tmp 
= a[cc][c];
    a[cc][c] 
= a[cc][rowMax];
    a[cc][rowMax] 
= tmp;
    tmp 
= b[cc][c];
    b[cc][c] 
= b[cc][rowMax];
    b[cc][rowMax] 
= tmp;
  }

  
// Now everything we do is on row "c".
  
// Set the max cell to 1 by dividing the entire row by that value
  tmp = a[c][c];
  
for (cc=0; cc<3; cc++)
  {
    a[cc][c] 
/= tmp;
    b[cc][c] 
/= tmp;
  }

  
// Now do the other rows, so that this column only has a 1 and 0's
  for (row = 0; row < 3; row++)
  {
    
if (row != c)
    {
    tmp 
= a[c][row];
    
for (cc=0; cc<3; cc++)
    {
      a[cc][row] 
-= a[cc][c] * tmp;
      b[cc][row] 
-= b[cc][c] * tmp;
    }
    }
  }

  }

  
*this = b;

  
return *this;
}

// Return a matrix33 set to the identity matrix
matrix33 IdentityMatrix33() 
{
  matrix33 ret;

  
return ret.identity();
}

// Return the transpose of the matrix33
matrix33 TransposeMatrix33(const matrix33 &m) 
{
  matrix33 ret(m);

  
return ret.transpose();
}

// Return the inverted matrix33
matrix33 InvertMatrix33(const matrix33 &m) 
{
  matrix33 ret(m);

  
return ret.invert();
}

// Return a 2D rotation matrix33
matrix33 RotateRadMatrix33(float rad) 
{
  matrix33 ret;
  
float sinA, cosA;

  sinA 
= (float)sin(rad);
  cosA 
= (float)cos(rad);

  ret[
0][0= cosA; ret[1][0= -sinA; ret[2][0= 0.0F;
  ret[
0][1= sinA; ret[1][1=  cosA; ret[2][1= 0.0F;
  ret[
0][2= 0.0F; ret[1][2=  0.0F; ret[2][2= 1.0F;

  
return ret;
}

// Return a 2D translation matrix33
matrix33 TranslateMatrix33(float x, float y) 
{
  matrix33 ret;

  ret.identity();
  ret[
2][0= x;
  ret[
2][1= y;

  
return ret;
}

// Return a 2D/3D scale matrix33
matrix33 ScaleMatrix33(float x, float y, float z) 
{
  matrix33 ret;

  ret.identity();
  ret[
0][0= x;
  ret[
1][1= y;
  ret[
2][2= z;

  
return ret;
}


////////////////////////////////////////////////////////////
// matrix44 class
//

// Multiply the matrix44 by another matrix44
matrix44 &matrix44::operator *= (const matrix44 &m) 
{
  matrix44 t;
  
for (unsigned int r = 0; r < 4; r++)
  {
  
for (unsigned int c = 0; c < 4; c++)
  {
    
float f = 0;

    f 
+= (col[0][r] * m[c][0]);
    f 
+= (col[1][r] * m[c][1]);
    f 
+= (col[2][r] * m[c][2]);
    f 
+= (col[3][r] * m[c][3]);

    t[c][r] 
= f;
  }
  }
  
*this = t;
  
return *this;
}


// Transpose the matrix44
matrix44 &matrix44::transpose() 
{
  
float t;

  
for (unsigned int c = 0; c < 4; c++)
  {
  
for (unsigned int r = c + 1; r < 4; r++)
  {
    t 
= col[c][r];
    col[c][r] 
= col[r][c];
    col[r][c] 
= t;
  } 
  } 

  
return *this;
}

// Invert the matrix44
matrix44 &matrix44::invert() 
{
  matrix44 a(
*this);
  matrix44 b(IdentityMatrix44());

  unsigned 
int r, c;
  unsigned 
int cc;
  unsigned 
int rowMax; // Points to max abs value row in this column
  unsigned int row;
  
float tmp;

  
// Go through columns
  for (c=0; c<4; c++)
  {

  
// Find the row with max value in this column
  rowMax = c;
  
for (r=c+1; r<4; r++)
  {
    
if (fabs(a[c][r]) > fabs(a[c][rowMax]))
    {
    rowMax 
= r;
    }
  }

  
// If the max value here is 0, we can't invert.  Return identity.
  if (a[rowMax][c] == 0.0F)
    
return(identity());

  
// Swap row "rowMax" with row "c"
  for (cc=0; cc<4; cc++)
  {
    tmp 
= a[cc][c];
    a[cc][c] 
= a[cc][rowMax];
    a[cc][rowMax] 
= tmp;
    tmp 
= b[cc][c];
    b[cc][c] 
= b[cc][rowMax];
    b[cc][rowMax] 
= tmp;
  }

  
// Now everything we do is on row "c".
  
// Set the max cell to 1 by dividing the entire row by that value
  tmp = a[c][c];
  
for (cc=0; cc<4; cc++)
  {
    a[cc][c] 
/= tmp;
    b[cc][c] 
/= tmp;
  }

  
// Now do the other rows, so that this column only has a 1 and 0's
  for (row = 0; row < 4; row++)
  {
    
if (row != c)
    {
    tmp 
= a[c][row];
    
for (cc=0; cc<4; cc++)
    {
      a[cc][row] 
-= a[cc][c] * tmp;
      b[cc][row] 
-= b[cc][c] * tmp;
    }
    }
  }

  }

  
*this = b;

  
return *this;
}

// Return a matrix44 set to the identity matrix
matrix44 IdentityMatrix44() 
{
  matrix44 ret;

  
return ret.identity();
}

// Return the transpose of the matrix44
matrix44 TransposeMatrix44(const matrix44 &m) 
{
  matrix44 ret(m);

  
return ret.transpose();
}

// Return the inverted matrix44
matrix44 InvertMatrix44(const matrix44 &m) 
{
  matrix44 ret(m);

  
return ret.invert();
}

// Return a 3D axis-rotation matrix44
// Pass in 'x', 'y', or 'z' for the axis.
matrix44 RotateRadMatrix44(char axis, float rad) 
{
  matrix44 ret;
  
float sinA, cosA;

  sinA 
= (float)sin(rad);
  cosA 
= (float)cos(rad);

  
switch (axis)
  {
  
case 'x':
  
case 'X':
    ret[
0][0=  1.0F; ret[1][0=  0.0F; ret[2][0=  0.0F;
    ret[
0][1=  0.0F; ret[1][1=  cosA; ret[2][1= -sinA;
    ret[
0][2=  0.0F; ret[1][2=  sinA; ret[2][2=  cosA;
    
break;

  
case 'y':
  
case 'Y':
    ret[
0][0=  cosA; ret[1][0=  0.0F; ret[2][0=  sinA;
    ret[
0][1=  0.0F; ret[1][1=  1.0F; ret[2][1=  0.0F;
    ret[
0][2= -sinA; ret[1][2=  0.0F; ret[2][2=  cosA;
    
break;

  
case 'z':
  
case 'Z':
    ret[
0][0=  cosA; ret[1][0= -sinA; ret[2][0=  0.0F;
    ret[
0][1=  sinA; ret[1][1=  cosA; ret[2][1=  0.0F;
    ret[
0][2=  0.0F; ret[1][2=  0.0F; ret[2][2=  1.0F;
    
break;
  }

  ret[
0][3= 0.0F; ret[1][3= 0.0F; ret[2][3= 0.0F;
  ret[
3][0= 0.0F;
  ret[
3][1= 0.0F;
  ret[
3][2= 0.0F;
  ret[
3][3= 1.0F;

  
return ret;
}

// Return a 3D axis-rotation matrix44
// Pass in an arbitrary vector3 axis.
matrix44 RotateRadMatrix44(const vector3 &axis, float rad) 
{
  matrix44 ret;
  
float sinA, cosA;
  
float invCosA;
  vector3 nrm 
= axis;
  
float x, y, z;
  
float xSq, ySq, zSq;

  nrm.normalize();
  sinA 
= (float)sin(rad);
  cosA 
= (float)cos(rad);
  invCosA 
= 1.0F - cosA;

  x 
= nrm.x;
  y 
= nrm.y;
  z 
= nrm.z;

  xSq 
= x * x;
  ySq 
= y * y;
  zSq 
= z * z;

  ret[
0][0= (invCosA * xSq) + (cosA);
  ret[
1][0= (invCosA * x * y) - (sinA * z );
  ret[
2][0= (invCosA * x * z) + (sinA * y );
  ret[
3][0= 0.0F;

  ret[
0][1= (invCosA * x * y) + (sinA * z);
  ret[
1][1= (invCosA * ySq) + (cosA);
  ret[
2][1= (invCosA * y * z) - (sinA * x);
  ret[
3][1= 0.0F;

  ret[
0][2= (invCosA * x * z) - (sinA * y);
  ret[
1][2= (invCosA * y * z) + (sinA * x);
  ret[
2][2= (invCosA * zSq) + (cosA);
  ret[
3][2= 0.0F;

  ret[
0][3= 0.0F;
  ret[
1][3= 0.0F;
  ret[
2][3= 0.0F;
  ret[
3][3= 1.0F;

  
return ret;
}

// Return a 3D translation matrix44
matrix44 TranslateMatrix44(float x, float y, float z) 
{
  matrix44 ret;

  ret.identity();
  ret[
3][0= x;
  ret[
3][1= y;
  ret[
3][2= z;

  
return ret;
}

// Return a 3D/4D scale matrix44
matrix44 ScaleMatrix44(float x, float y, float z, float w) 
{
  matrix44 ret;

  ret.identity();
  ret[
0][0= x;
  ret[
1][1= y;
  ret[
2][2= z;
  ret[
3][3= w;

  
return ret;
}

// Return a "lookat" matrix44 given the current camera position (vector3),
//   camera-up vector3, and camera-target vector3.
matrix44 LookAtMatrix44(const vector3 &camPos, const vector3 &target, 
    
const vector3 &camUp ) 
{
  matrix44 ret;

  vector3 F 
= target - camPos;
  F.normalize();

  vector3 S 
= CrossProduct(F, Normalized(camUp));
  S.normalize();

  vector3 U 
= CrossProduct(S, F);
  U.normalize();

  ret[
0][0= S.x;
  ret[
1][0= S.y;
  ret[
2][0= S.z;
  ret[
3][0= 0.0;

  ret[
0][1= U.x;
  ret[
1][1= U.y;
  ret[
2][1= U.z;
  ret[
3][1= 0.0;

  ret[
0][2= -F.x;
  ret[
1][2= -F.y;
  ret[
2][2= -F.z;
  ret[
3][2= 0.0;

  ret[
0][3= 0.0F;
  ret[
1][3= 0.0F;
  ret[
2][3= 0.0F;
  ret[
3][3= 1.0F;

  ret 
*= TranslateMatrix44(-camPos.x, -camPos.y, -camPos.z);

  
return ret;
}

// Return a frustum matrix44 given the left, right, bottom, top,
//   near, and far values for the frustum boundaries.
matrix44 FrustumMatrix44(float l, float r, 
    
float b, float t, float n, float f) 
{
  matrix44 ret;
  
float width = r-l;
  
float height = t-b;
  
float depth = f-n;

  ret[
0][0= (2*n) / width;
  ret[
0][1= 0.0F;
  ret[
0][2= 0.0F;
  ret[
0][3= 0.0F;

  ret[
1][0= 0.0F;
  ret[
1][1= (2*n) / height;
  ret[
1][2= 0.0F;
  ret[
1][3= 0.0F;

  ret[
2][0= (r + l) / width;
  ret[
2][1= (t + b) / height;
  ret[
2][2= -(f + n) / depth;
  ret[
2][3= -1.0F;

  ret[
3][0= 0.0F;
  ret[
3][1= 0.0F;
  ret[
3][2= -(2*f*n) / depth;
  ret[
3][3= 0.0F;

  
return ret;
}

// Return a perspective matrix44 given the field-of-view in the Y
//   direction in degrees, the aspect ratio of Y/X, and near and
//   far plane distances.
matrix44 PerspectiveMatrix44(float fovY, float aspect, float n, float f) 
{
  matrix44 ret;
  
float angle;
  
float cot;

  angle 
= fovY / 2.0F;
  angle 
= DegToRad( angle );

  cot 
= (float) cos(angle) / (float) sin(angle);

  ret[
0][0= cot / aspect;
  ret[
0][1= 0.0F;
  ret[
0][2= 0.0F;
  ret[
0][3= 0.0F;

  ret[
1][0= 0.0F;
  ret[
1][1= cot;
  ret[
1][2= 0.0F;
  ret[
1][3= 0.0F;

  ret[
2][0= 0.0F;
  ret[
2][1= 0.0F;
  ret[
2][2= -(f + n) / (f - n);
  ret[
2][3= -1.0F;


  ret[
3][0= 0.0F;
  ret[
3][1= 0.0F;
  ret[
3][2= -(2*f*n) / (f - n);
  ret[
3][3= 0.0F;

  
return ret;
}

// Return an orthographic matrix44 given the left, right, bottom, top,
//   near, and far values for the frustum boundaries.
matrix44 OrthoMatrix44(float l, float r, 
    
float b, float t, float n, float f) 
{
  matrix44 ret;
  
float width = r-l;
  
float height = t-b;
  
float depth = f-n;

  ret[
0][0= 2.0F / width;
  ret[
0][1= 0.0F;
  ret[
0][2= 0.0F;
  ret[
0][3= 0.0F;

  ret[
1][0= 0.0F;
  ret[
1][1= 2.0F / height;
  ret[
1][2= 0.0F;
  ret[
1][3= 0.0F;

  ret[
2][0= 0.0F;
  ret[
2][1= 0.0F;
  ret[
2][2= -(2.0F/ depth;
  ret[
2][3= 0.0F;

  ret[
3][0= -(r + l) / width;
  ret[
1][3= -(t + b) / height;
  ret[
3][2= -(f + n) / depth;
  ret[
3][3= 1.0F;

  
return ret;
}

// Return an orientation matrix using 3 basis normalized vectors
matrix44    OrthoNormalMatrix44(const vector3 &xdir, 
    
const vector3 &ydir, const vector3 &zdir)
{
  matrix44 ret;

  ret[
0= (vector4)xdir;
  ret[
1= (vector4)ydir;
  ret[
2= (vector4)zdir;
  ret[
3].set(0.00.00.01.0);

  
return ret;
}


////////////////////////////////////////////////////////////
// Debug functions
//

// Print a vector2 to a file
void vector2::fprint(FILE* file, char* str) const 
{
  fprintf(file, 
"%svector2: <%f, %f>\n", str, x, y);
}

// Print a vector3 to a file
void vector3::fprint(FILE* file, char* str) const 
{
  fprintf(file, 
"%svector3: <%f, %f, %f>\n", str, x, y, z);
}

// Print a vector4 to a file
void vector4::fprint(FILE* file, char* str) const 
{
  fprintf(file, 
"%svector4: <%f, %f, %f, %f>\n", str, x, y, z, w);
}

// Print a matrix33 to a file
void matrix33::fprint(FILE* file, char * str) const 
{
  fprintf(file, 
"%smatrix33:\n", str);
  vector3 row0(col[
0][0], col[1][0], col[2][0]);
  row0.fprint(file, 
"\t");
  vector3 row1(col[
0][1], col[1][1], col[2][1]);
  row1.fprint(file, 
"\t");
  vector3 row2(col[
0][2], col[1][2], col[2][2]);
  row2.fprint(file, 
"\t");
}

// Print a matrix44 to a file
void matrix44::fprint(FILE* file, char* str) const 
{
  fprintf(file, 
"%smatrix44:\n", str);
  vector4 row0(col[
0][0], col[1][0], col[2][0], col[3][0]);
  row0.fprint(file, 
"\t");
  vector4 row1(col[
0][1], col[1][1], col[2][1], col[3][1]);
  row1.fprint(file, 
"\t");
  vector4 row2(col[
0][2], col[1][2], col[2][2], col[3][2]);
  row2.fprint(file, 
"\t");
  vector4 row3(col[
0][3], col[1][3], col[2][3], col[3][3]);
  row3.fprint(file, 
"\t");
}
Posted on 2009-09-08 10:46 zyb_debug 阅读(1462) 评论(4)  编辑 收藏 引用

Feedback

# re: 实作ADTvector2 vector3 vector4 matrix44 matrix33  回复  更多评论   

2009-09-08 11:42 by Touchsoft
跟我见过的几个差不多。

# re: 实作ADTvector2 vector3 vector4 matrix44 matrix33  回复  更多评论   

2009-09-09 14:21 by oh,no
说实话,“实现”比侯捷口中的“实作”好听多了,这个没必要学台湾的说法。

# re: 实作ADTvector2 vector3 vector4 matrix44 matrix33  回复  更多评论   

2009-09-09 16:24 by zyb_debug
@oh,no
这个无所谓,技术至上

# re: 实作ADTvector2 vector3 vector4 matrix44 matrix33  回复  更多评论   

2009-09-09 17:48 by 凡客诚品
这个无所谓,技术至上

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理