From f7343ec6ab64cd1f3d6cd3318c165b3718d02b92 Mon Sep 17 00:00:00 2001 From: Stefano Musumeci Date: Wed, 28 May 2014 17:46:33 +0100 Subject: [PATCH] TINYGL: Implemented first draft of new matrix and vector classes. --- graphics/tinygl/zmath.cpp | 213 ++++++++++++++++++++++++++++++++++++++ graphics/tinygl/zmath.h | 195 ++++++++++++++++++++++++++-------- 2 files changed, 367 insertions(+), 41 deletions(-) diff --git a/graphics/tinygl/zmath.cpp b/graphics/tinygl/zmath.cpp index 34a69be7c0a..3b0be33d809 100644 --- a/graphics/tinygl/zmath.cpp +++ b/graphics/tinygl/zmath.cpp @@ -267,4 +267,217 @@ V4 gl_V4_New(float x, float y, float z, float w) { return a; } +Vector3::Vector3() { + // Empty constructor, no overhead +} + +Vector3::Vector3(const Vector3 &other) { + memcpy(_v,other._v,sizeof(_v)); +} + +Vector3::Vector3(float x, float y, float z) { + _v[0] = x; + _v[1] = y; + _v[2] = z; +} + +void Vector3::normalize() { + float n; + n = sqrt(_v[0] * _v[0] + _v[1] * _v[1] + _v[2] * _v[2]); + if (n != 0) { + _v[0] /= n; + _v[1] /= n; + _v[2] /= n; + } +} + +Vector4::Vector4() { + // Empty constructor, no overhead +} + + +Vector4::Vector4(float x, float y, float z, float w) { + _v[0] = x; + _v[1] = y; + _v[2] = z; + _v[3] = w; +} + +Matrix4::Matrix4() { + // Empty constructor, no overhead +} + + +Matrix4::Matrix4(const Matrix4 &other) { + memcpy(_m,other._m,sizeof(_m)); +} + +TinyGL::Matrix4 Matrix4::identity() { + Matrix4 a; + a.fill(0); + a.set(0,0,1.0f); + a.set(1,1,1.0f); + a.set(2,2,1.0f); + a.set(3,3,1.0f); + return a; +} + +TinyGL::Matrix4 Matrix4::transpose() const { + Matrix4 a; + + a.set(0,0, this->get(0,0)); + a.set(0,1, this->get(1,0)); + a.set(0,2, this->get(2,0)); + a.set(0,3, this->get(3,0)); + + a.set(1,0, this->get(0,1)); + a.set(1,1, this->get(1,1)); + a.set(1,2, this->get(2,1)); + a.set(1,3, this->get(3,1)); + + a.set(2,0, this->get(0,2)); + a.set(2,1, this->get(1,2)); + a.set(2,2, this->get(2,2)); + a.set(2,3, this->get(3,2)); + + a.set(3,0, this->get(0,3)); + a.set(3,1, this->get(1,3)); + a.set(3,2, this->get(2,3)); + a.set(3,3, this->get(3,3)); + + return a; +} + +TinyGL::Matrix4 Matrix4::inverseOrtho() const { + Matrix4 a; + + int i, j; + float s; + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) + a.set(i,j, this->get(j,i)); + a.set(3,0, 0.0f); + a.set(3,1, 0.0f); + a.set(3,2, 0.0f); + a.set(3,3, 1.0f); + for (i = 0; i < 3; i++) { + s = 0; + for (j = 0; j < 3; j++) + s -= this->get(j,i) * this->get(j,3); + a.set(i,3,s); + } + } + + return a; +} + +TinyGL::Matrix4 Matrix4::inverse() const { + Matrix4 source(*this); + int k; + float max, tmp, t; + + // identitée dans r + Matrix4 result = identity(); + + for (int j = 0; j < 4; j++) { + max = source.get(j,j); + k = j; + for (int i = j + 1; i < 4; i++) { + if (fabs(source.get(i,j)) > fabs(max)) { + k = i; + max = source.get(i,j); + } + } + // non intersible matrix + if (max == 0) + return result; + + if (k != j) { + for (int i = 0; i < 4; i++) { + tmp = source.get(j,i); + source.set(j,i, source.get(k,i)); + source.set(k,i, tmp); + + tmp = result.get(j,i); + result.set(j,i, source.get(k,i)); + result.set(k,i,tmp); + } + } + + max = 1 / max; + for (int i = 0; i < 4; i++) { + source.set(j,i, max * source.get(j,i)); + result.set(j,i, max * result.get(j,i)); + } + + for (int l = 0; l < 4; l++) { + if (l != j) { + t = source.get(l,j); + for (int i = 0; i < 4; i++) { + source.set(l,i, source.get(l,i) - t * source.get(j,i)); + result.set(l,i, result.get(l,i) - t * result.get(j,i)); + } + } + } + } + + return result; +} + +TinyGL::Matrix4 Matrix4::rotation(float t, int u) const { + Matrix4 a = identity(); + float s, c; + int v, w; + + if ((v = u + 1) > 2) + v = 0; + if ((w = v + 1) > 2) + w = 0; + s = sin(t); + c = cos(t); + a.set(v,v,c); + a.set(v,w,-s); + a.set(w,v,s); + a.set(w,w,c); + + return a; +} + +TinyGL::Vector3 Matrix4::transform(const Vector3 &vector) const { + return Vector3( + vector.getX() * get(0,0) + vector.getY() * get(0,1) + vector.getZ() * get(0,2) + get(0,3), + vector.getX() * get(1,0) + vector.getY() * get(1,1) + vector.getZ() * get(1,2) + get(1,3), + vector.getX() * get(2,0) + vector.getY() * get(2,1) + vector.getZ() * get(2,2) + get(2,3)); +} + +TinyGL::Vector3 Matrix4::transform3x3( const Vector3 &vector ) const +{ + return Vector3( + vector.getX() * get(0,0) + vector.getY() * get(0,1) + vector.getZ() * get(0,2), + vector.getX() * get(1,0) + vector.getY() * get(1,1) + vector.getZ() * get(1,2), + vector.getX() * get(2,0) + vector.getY() * get(2,1) + vector.getZ() * get(2,2)); +} + +TinyGL::Vector4 Matrix4::transform(const Vector4 &vector) const { + return Vector4( + vector.getX() * get(0,0) + vector.getY() * get(0,1) + vector.getZ() * get(0,2) + vector.getW() * get(0,3), + vector.getX() * get(1,0) + vector.getY() * get(1,1) + vector.getZ() * get(1,2) + vector.getW() * get(1,3), + vector.getX() * get(2,0) + vector.getY() * get(2,1) + vector.getZ() * get(2,2) + vector.getW() * get(2,3), + vector.getX() * get(3,0) + vector.getY() * get(3,1) + vector.getZ() * get(3,2) + vector.getW() * get(3,3)); +} + +bool Matrix4::IsIdentity() const +{ + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + if (i == j) { + if (_m[i][j] != 1.0) + return false; + } else if (_m[i][j] != 0.0) + return false; + } + } + return true; +} + } // end of namespace TinyGL diff --git a/graphics/tinygl/zmath.h b/graphics/tinygl/zmath.h index 5a89d729255..6d938e72aed 100644 --- a/graphics/tinygl/zmath.h +++ b/graphics/tinygl/zmath.h @@ -4,54 +4,167 @@ namespace TinyGL { // Matrix & Vertex - -class Vector3 -{ +class Vector3 { public: Vector3(); + Vector3(const Vector3 &other); Vector3(float x, float y, float z); + + float getX() const { return _v[0]; } + float getY() const { return _v[1]; } + float getZ() const { return _v[2]; } - Vector3 operator*(float value); - Vector3 operator+(const Vector3& other); - Vector3 operator-(const Vector3& other); + void setX(float val) { _v[0] = val; } + void setY(float val) { _v[1] = val; } + void setZ(float val) { _v[2] = val; } + void normalize(); + + Vector3& operator=(const Vector3 &other) + { + memcpy(_v,other._v,sizeof(_v)); + return *this; + } + + Vector3 operator-() const + { + return Vector3(-_v[0],-_v[1],_v[2]); + } + + Vector3 operator*(float factor) const { + return Vector3(_v[0] * factor, _v[1] * factor, _v[2] * factor); + } + + Vector3 operator+(const Vector3 &other) const { + return Vector3(_v[0] + other._v[0], _v[1] + other._v[1], _v[2] + other._v[2]); + } + + Vector3 operator-(const Vector3 &other) const { + return Vector3(_v[0] - other._v[0], _v[1] - other._v[1], _v[2] - other._v[2]); + } + + Vector3& operator*=(float factor) { + _v[0] *= factor; + _v[1] *= factor; + _v[2] *= factor; + return *this; + } + + Vector3& operator+=(float factor) { + _v[0] += factor; + _v[1] += factor; + _v[2] += factor; + return *this; + } + + Vector3& operator-=(float factor) { + _v[0] -= factor; + _v[1] -= factor; + _v[2] -= factor; + return *this; + } private: - float v[3]; + float _v[3]; }; -class Vector4 -{ +class Vector4 { public: Vector4(); Vector4(float x, float y, float z, float w); - Vector4 operator*(float value); - Vector4 operator+(const Vector4& other); - Vector4 operator-(const Vector4& other); + float getX() const { return _v[0]; } + float getY() const { return _v[1]; } + float getZ() const { return _v[2]; } + float getW() const { return _v[3]; } + + void setX(float val) { _v[0] = val; } + void setY(float val) { _v[1] = val; } + void setZ(float val) { _v[2] = val; } + void setW(float val) { _v[3] = val; } + private: - float v[4]; + float _v[4]; }; -class Matrix4 -{ +class Matrix4 { public: Matrix4(); - Matrix4(const Matrix4& other); + Matrix4(const Matrix4 &other); + + bool IsIdentity() const; + + Matrix4& operator=(const Matrix4 &other) + { + memcpy(_m,other._m,sizeof(_m)); + return *this; + } + + Matrix4 operator+(const Matrix4& b) const + { + Matrix4 result; + for(int i = 0; i < 4; i++) { + for(int j = 0; j < 4; j++) { + result.set(i,j, get(i,j) + b.get(i,j)); + } + } + return result; + } + + Matrix4 operator-(const Matrix4& b) const + { + Matrix4 result; + for(int i = 0; i < 4; i++) { + for(int j = 0; j < 4; j++) { + result.set(i,j, get(i,j) - b.get(i,j)); + } + } + return result; + } + + Matrix4 operator*(const Matrix4 &b) const + { + Matrix4 result; + float s; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + s = 0.0; + for (int k = 0; k < 4; k++) + s += this->get(i,k) * b.get(k,j); + result.set(i,j,s); + } + } + return result; + } - Matrix4 operator=(const Matrix4& other); - Matrix4 operator*(const Matrix4& b); static Matrix4 identity(); + void fill(float val) { + for(int i = 0; i < 4; i++) { + for(int j = 0; j < 4; j++) { + _m[i][j] = val; + } + } + } + + inline void set(int x,int y,float val) { + _m[x][y] = val; + } + + inline float get(int x, int y) const { + return _m[x][y]; + } + Matrix4 transpose() const; Matrix4 inverseOrtho() const; Matrix4 inverse() const; - Matrix4 rotation() const; + Matrix4 rotation(float t, int u) const; - Vector3 transform(const Vector3& vector); - Vector4 transform(const Vector4& vector); + Vector3 transform(const Vector3 &vector) const; + Vector3 transform3x3(const Vector3 &vector) const; // Transform the vector as if this were a 3x3 matrix. + Vector4 transform(const Vector4 &vector) const; private: - float m[4][4]; + float _m[4][4]; }; struct M4 { @@ -60,11 +173,11 @@ struct M4 { struct M3 { - float m[3][3]; + float m[3][3]; }; struct M34 { - float m[3][4]; + float m[3][4]; }; @@ -81,26 +194,26 @@ struct V4 { float v[4]; }; -void gl_M4_Id(M4 *a); -int gl_M4_IsId(const M4 *a); -void gl_M4_Move(M4 *a, const M4 *b); -void gl_MoveV3(V3 *a, const V3 *b); -void gl_MulM4V3(V3 *a, const M4 *b, const V3 *c); -void gl_MulM3V3(V3 *a, const M4 *b, const V3 *c); +void gl_M4_Id(M4 *a); // Done +int gl_M4_IsId(const M4 *a); // Done +void gl_M4_Move(M4 *a, const M4 *b); // Done (= operator) +void gl_MoveV3(V3 *a, const V3 *b); // Done (= operator) +void gl_MulM4V3(V3 *a, const M4 *b, const V3 *c); // Done +void gl_MulM3V3(V3 *a, const M4 *b, const V3 *c); // Done -void gl_M4_MulV4(V4 *a, const M4 *b, const V4 *c); -void gl_M4_InvOrtho(M4 *a, const M4 &b); -void gl_M4_Inv(M4 *a, const M4 *b); -void gl_M4_Mul(M4 *c, const M4 *a, const M4 *b); -void gl_M4_MulLeft(M4 *c, const M4 *a); -void gl_M4_Transpose(M4 *a, const M4 *b); -void gl_M4_Rotate(M4 *c, float t, int u); -int gl_V3_Norm(V3 *a); +void gl_M4_MulV4(V4 *a, const M4 *b, const V4 *c); // Done +void gl_M4_InvOrtho(M4 *a, const M4 &b); // Done +void gl_M4_Inv(M4 *a, const M4 *b); // Done +void gl_M4_Mul(M4 *c, const M4 *a, const M4 *b); // Done +void gl_M4_MulLeft(M4 *c, const M4 *a); // Done +void gl_M4_Transpose(M4 *a, const M4 *b); // Done +void gl_M4_Rotate(M4 *c, float t, int u); // Done +int gl_V3_Norm(V3 *a); // Done -V3 gl_V3_New(float x, float y, float z); -V4 gl_V4_New(float x, float y, float z, float w); +V3 gl_V3_New(float x, float y, float z); // Done +V4 gl_V4_New(float x, float y, float z, float w); // Done -int gl_Matrix_Inv(float *r, float *m, int n); +int gl_Matrix_Inv(float *r, float *m, int n); // Only for internal use - could be removed. } // end of namespace TinyGL