Sign in to follow this  
The Rug

OpenGL *sigh* Matrix problems

Recommended Posts

What I'm trying to do is create a matrix class which mimics OpenGL's matrix implementation. This is a real bugger, since every article I have found explains things differently and, for the most part, badly. What I want is to: 1. Be able to concatenate transformations like in OpenGL, ie. be able to multiply my one matrix by another 2. Implement rotations by creating a rotation matrix, then multiplying the currewnt matrix by that rotation matrix This is what I have so far:
// These functions are members of class Matrix4x4

             void multiplyBy(const Matrix4x4 &mat) {
                  float newData[16];

                  newData[0]  = data[0] * mat.data[0]  +  data[1] * mat.data[4]  +  data[2] * mat.data[8]  +  data[3] * mat.data[12];
                  newData[1]  = data[0] * mat.data[1]  +  data[1] * mat.data[5]  +  data[2] * mat.data[6]  +  data[3] * mat.data[13];
                  newData[2]  = data[0] * mat.data[2]  +  data[1] * mat.data[6]  +  data[2] * mat.data[10]  +  data[3] * mat.data[14];                  
                  newData[3]  = data[0] * mat.data[3]  +  data[1] * mat.data[7]  +  data[2] * mat.data[11]  +  data[3] * mat.data[15];

                  newData[4]  = data[4] * mat.data[0]  +  data[5] * mat.data[4]  +  data[6] * mat.data[8]  +  data[7] * mat.data[12];
                  newData[5]  = data[4] * mat.data[1]  +  data[5] * mat.data[5]  +  data[6] * mat.data[6]  +  data[7] * mat.data[13];
                  newData[6]  = data[4] * mat.data[2]  +  data[5] * mat.data[6]  +  data[6] * mat.data[10]  +  data[7] * mat.data[14];                  
                  newData[7]  = data[4] * mat.data[3]  +  data[5] * mat.data[7]  +  data[6] * mat.data[11]  +  data[7] * mat.data[15];

                  newData[8]  = data[8] * mat.data[0]  +  data[9] * mat.data[4]  +  data[10] * mat.data[8]  +  data[11] * mat.data[12];
                  newData[9]  = data[8] * mat.data[1]  +  data[9] * mat.data[5]  +  data[10] * mat.data[6]  +  data[11] * mat.data[13];
                  newData[10] = data[8] * mat.data[2]  +  data[9] * mat.data[6]  +  data[10] * mat.data[10]  +  data[11] * mat.data[14];                  
                  newData[11] = data[8] * mat.data[3]  +  data[9] * mat.data[7]  +  data[10] * mat.data[11]  +  data[11] * mat.data[15];

                  newData[12] = data[12] * mat.data[0]  +  data[13] * mat.data[4]  +  data[14] * mat.data[8]  +  data[15] * mat.data[12];
                  newData[13] = data[12] * mat.data[1]  +  data[13] * mat.data[5]  +  data[14] * mat.data[6]  +  data[15] * mat.data[13];
                  newData[14] = data[12] * mat.data[2]  +  data[13] * mat.data[6]  +  data[14] * mat.data[10]  +  data[15] * mat.data[14];                  
                  newData[15] = data[12] * mat.data[3]  +  data[13] * mat.data[7]  +  data[14] * mat.data[11]  +  data[15] * mat.data[15];

                  // copy new information into current matrix
                  for(int count=0; count<16; ++count)
                      data[count] = newData[count];
                  }



             void rotatef(float angle, float x, float y, float z) {
                  // ..convert angle to radians..
                  angle *= 0.0174532925;

                  Matrix4x4 temp;

                  // Rotate around X axis
                  if(x > 0.0) {
                     temp.data[5]  =  cos( angle );
                     temp.data[6]  = -sin( angle );
                     temp.data[9]  =  sin( angle );
                     temp.data[10] =  cos( angle );                                                               
                     }

                  // Rotate around Y axis
                  if(y > 0.0) {
                     temp.data[0]  =  cos( angle );
                     temp.data[2]  =  sin( angle );
                     temp.data[8]  = -sin( angle );
                     temp.data[10] =  cos( angle );                                                               
                     }

                  // Rotate around Z axis
                  if(z > 0.0) {
                     temp.data[0]  =  cos( angle );
                     temp.data[1]  = -sin( angle );
                     temp.data[4]  =  sin( angle );
                     temp.data[5]  =  cos( angle );                                                               
                     }

                     multiplyBy(temp);
                  }



This doesn't work properly, however. I basically create the matrix, load it to identity, and then call rotatef on that matrix. I then load the matrix with glLoadMatrixf. This seems to produce the opposite effect of calling glRotatef with the same values. Using glLoadTransposeMatrixf, however, seems to work. This tells me that my matrices aren't entirely broken, just muddled up- and I have no idea why. Big rates to anyone who can help me!

Share this post


Link to post
Share on other sites
based on what you said at the end (as i cant be bothered to check your maths, heh) you are performing a row major operation when you should be treating the matrix as column major to get the right effect.

Thus, glLoadTransposeMatrixf works as it transposes the matrix from row major to column major.

Share this post


Link to post
Share on other sites
potential insight:

remember that ogl uses column major whereas many tutorials present the row major form of matrix mulitplies in referene to rotations,scale and translates. so for instance the translation vector is in the fourth column, not the fourth row.

this would explain why the transpose resolves the issue, too.

Share this post


Link to post
Share on other sites
Well, I'm in a bit of a pickle now, since it turns out glLoadTransposeMatrixf only worked for the simplest of rotations. So I'm starting to think the problem is something else (orinigating somewhere between my keyboard and my chair, most likely...)

I hate to just ask for code, but I think its the only way I'm going to understand this. If anyone has any OpenGL matrix code for multiplying matrices, I'd love to see it.

Thanks a lot to the previous posters (Ali_B gets an A for effort [wink])

Share this post


Link to post
Share on other sites
for the operation:
ret = mat * v


ret[0] = (mat[0]*v[0]) + (mat[4]*v[1]) + (mat[8]*v[2]) + (mat[12]*v[3]);
ret[4] = (mat[0]*v[4]) + (mat[4]*v[5]) + (mat[8]*v[6]) + (mat[12]*v[7]);
ret[8] = (mat[0]*v[8]) + (mat[4]*v[9]) + (mat[8]*v[10])+ (mat[12]*v[11]);
ret[12]= (mat[0]*v[12])+ (mat[4]*v[13])+ (mat[8]*v[14])+ (mat[12]*v[15]);

ret[1] = (mat[1]*v[0]) + (mat[5]*v[1]) + (mat[9]*v[2]) + (mat[13]*v[3]);
ret[5] = (mat[1]*v[4]) + (mat[5]*v[5]) + (mat[9]*v[6]) + (mat[13]*v[7]);
ret[9] = (mat[1]*v[8]) + (mat[5]*v[9]) + (mat[9]*v[10])+ (mat[13]*v[11]);
ret[13]= (mat[1]*v[12])+ (mat[5]*v[13])+ (mat[9]*v[14])+ (mat[13]*v[15]);

ret[2] = (mat[2]*v[0]) + (mat[6]*v[1]) + (mat[10]*v[2]) + (mat[14]*v[3]);
ret[6] = (mat[2]*v[4]) + (mat[6]*v[5]) + (mat[10]*v[6]) + (mat[14]*v[7]);
ret[10]= (mat[2]*v[8]) + (mat[6]*v[9]) + (mat[10]*v[10])+ (mat[14]*v[11]);
ret[14]= (mat[2]*v[12])+ (mat[6]*v[13])+ (mat[10]*v[14])+ (mat[14]*v[15]);

ret[3] = (mat[3]*v[0]) + (mat[7]*v[1]) + (mat[11]*v[2]) + (mat[15]*v[3]);
ret[7] = (mat[3]*v[4]) + (mat[7]*v[5]) + (mat[11]*v[6]) + (mat[15]*v[7]);
ret[11]= (mat[3]*v[8]) + (mat[7]*v[9]) + (mat[11]*v[10])+ (mat[15]*v[11]);
ret[15]= (mat[3]*v[12])+ (mat[7]*v[13])+ (mat[11]*v[14])+ (mat[15]*v[15]);


This is my operator * code and I use my matrix class with opengl (including glmultmatrixf). So if this doesnt work for you then your problem is elsewhere.

About rotation, when you create temp, does the constructor initialize it to the identity?

Share this post


Link to post
Share on other sites
Thankyou, that is awesome!

Yes, it was my numbers that were jiggered. Ah well, I should pay more attention. Just so you know the_phantom, I did rate you up again, but it made absolutely no difference [grin]

Ahhh, GameDev. Is there anything it can't do?

Share this post


Link to post
Share on other sites

float mtx[16];
/*
IN OpenGL:
|Rx 0 0 Tx|
|0 Ry 0 Ty|
|0 0 Rz Tz|
|0 0 0 1 |

therefore:
|0 1 2 3 |
|4 5 6 7 |
|8 9 10 11|
|12 13 14 15|

and thusly:

mtx[0] == Rx
mtx[5] == Ry
mtx[10] == Rz
tehTranslate3f = mtx[3], mtx[7], mtx[11]
*/




Now when you do rotations with matrices you perform them in some developer defined order, right? let's pretend you multiply matrices A by B by C in Dx/row major/LHSsystems. Notice that the ANS matrix will be also be in Dx/Row Major/LHS form.

ANS = A * B * C

However to accomplish the same results when the matrices are in OGL/column major/RHS systems would be to multiply them in reverse order, which results in the ANS matrix to be in the OGL/Column Major/RHS form.

ANS = C * B * A


consider the following example:

let A and b be LHS matrices where
A =
|1 2|
|3 4|
B=
|5 6|
|7 8|
ANS = A * B =
|(1*5 + 2*7) (1*6 + 2*8)|
|(3*5 + 4*7) (3*6 + 4*8)|
=
|19 22|
|43 42|

now let's try it in RHS where A and B are
A =
|1 3|
|2 4|
B=
|5 7|
|6 8|
ANS = B * A =
|(5*1 + 7*2) (5*3 + 7*4)|
|(6*1 + 8*2) (6*3 + 8*4)|
=
|19 43|
|22 42|
= transpose of ANS in the LHS system


now why all this info .. perhaps you have the order matrix mulitplies backwards (for the rotations, translations and projections) in your code, and you mulitply method is actually a-ok? after all, in general matrix mulitplicaiton is not commutative. just another possibility for you to consider.

Share this post


Link to post
Share on other sites
Maybe I'm being an ass, but it seems that OpenGL can do these things for you and possibly be more efficent(not to insult anybody).

// R = M * V

float* multMatrix(const float M[16], const float V[16]) // you guys seem to like those letters
{
float R[16]; // result

glMatrixMode (GL_MODELVIEW); // you can use any matrix, but we need to choose one
glPushMatrix ();
glLoadMatrixf(M); // GL_MATRIX = M
glMultMatrixf(V); // GL_MATRIX = M * V
glGetFloatv (GL_MODELVIEW_MATRIX, R); // R = GL_MATRIX -> R = M * V
glPopMatrix();

return R;
}

// optional matrix:
// glMatrixMode can have GL_MODELVIEW, GL_PROJECTION or GL_TEXTURE
// thus glGetFloatv must have GL_MODELVIEW_MATRIX, GL_PROJECTION_MATRIX or GL_TEXTURE_MATRIX respectivly


this way you can also preform OpenGL operations and output the matrix to see the resulting matrix, just trying to help

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
glLoadTransposeMatrixf is it extension or what i can't find it in the blue book??

Share this post


Link to post
Share on other sites
You might have noticed that my previous 2 posts in this thread were empty.. I don't know what happenned!! There was a lot of text in my posting... Or the connection was not that good.. And you know http is UDP!!

So.. In order to be able to submit the stuff, I'll post each file at a time (4 files)..

Share this post


Link to post
Share on other sites
matrix.h

//*************************************************************************
//
// File Name: Matrix.h
// Author : Justin Legakis (Original Author)
// Ali BaderEddin (Applied some changes + added useful comments)
//
// Description: A class that represents a matrix and supports many matrix
// operations.
//
// 0 1 2 3
// 0 [1 0 0 5]
// 1 [0 1 0 0]
// 2 [0 0 1 0] ==> matrix [0][3] is equal to 5
// 3 [0 0 0 1] (that's how matrix is represened)
//
//*************************************************************************

#ifndef _MATRIX_H_
#define _MATRIX_H_

#include <math.h>
#include <assert.h>

#include "vectors.h"

class Matrix
{
private:

// REPRESENTATION
float data[4][4];

public:

// CONSTRUCTORS & DESTRUCTOR
Matrix() { Clear(); }

Matrix(const Matrix& A)
{
for (int y = 0; y < 4; y++)
for (int x = 0; x < 4; x++)
data[y][x] = A.data[y][x];
}

~Matrix() {}

// ACCESSOR
float Get (int x, int y) const
{
assert (x >= 0 && x < 4);
assert (y >= 0 && y < 4);
return data[y][x];
}

// MODIFIERS
void Set(int x, int y, float v)
{
assert (x >= 0 && x < 4);
assert (y >= 0 && y < 4);
data[y][x] = v;
}

void SetToIdentity()
{
for (int y = 0; y < 4; y++)
for (int x = 0; x < 4; x++)
data[y][x] = (x == y);
}

void Clear()
{
for (int y = 0; y < 4; y++)
for (int x = 0; x < 4; x++)
data[y][x] = 0;
}

// OVERLOADED OPERATORS
Matrix& operator=(const Matrix& A)
{
for (int y=0; y<4; y++)
for (int x=0; x<4; x++)
data[y][x] = A.data[y][x];

return (*this);
}

int operator==(const Matrix& A) const
{
for (int y=0; y<4; y++)
for (int x=0; x<4; x++)
if (this->data[y][x] != A.data[y][x])
return 0;
return 1;
}

int operator!=(const Matrix &A) const { return !(*this==A); }

friend Matrix operator+(const Matrix &A, const Matrix &B);
friend Matrix operator-(const Matrix &A, const Matrix &B);
friend Matrix operator*(const Matrix &A, const Matrix &B);
friend Matrix operator*(const Matrix &A, float f);
friend Matrix operator*(float f, const Matrix &A) { return A * f; }

Matrix& operator+=(const Matrix& A)
{
*this = *this + A;
return *this;
}

Matrix& operator-=(const Matrix& A)
{
*this = *this - A;
return *this;
}

Matrix& operator*=(const float d)
{
*this = *this * d;
return *this;
}

Matrix& operator*=(const Matrix& A)
{
*this = *this * A;
return *this;
}

// TRANSFORMATIONS
void Translate(float x, float y, float z);
void Scale(float x, float y, float z);
void Scale(float s) { Scale(s, s, s); }
void XRotate(float theta);
void YRotate(float theta);
void ZRotate(float theta);
void Transform(Vec4f &v);

void Transform(Vec3f &v)
{
Vec4f v2 = Vec4f(v.x(),v.y(),v.z(),1);
Transform(v2);
v.Set(v2.x(),v2.y(),v2.z());
}

void Transform(Vec2f &v)
{
Vec4f v2 = Vec4f(v.x(),v.y(),1,1);
Transform(v2);
v.Set(v2.x(),v2.y());
}

// INPUT / OUTPUT (Edited by Ali BaderEddin)
void Write(FILE *F = stdout) const
{
assert (F != NULL);

for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
fprintf (F, "%.2f ", data[y][x]);

fprintf (F,"\n");
}

fprintf (F,"\n");
}

void Write3x3(FILE *F = stdout) const
{
assert (F != NULL);

for (int y = 0; y < 4; y++)
{
if (y == 2) continue;

for (int x = 0; x < 4; x++)
{
if (x == 2) continue;
fprintf (F, "%.2f ", data[y][x]);
}

fprintf (F,"\n");
}

fprintf (F,"\n");
}

void Read(FILE *F)
{
assert (F != NULL);

for (int y = 0; y < 4; y++)
for (int x = 0; x < 4; x++)
{
int scanned = fscanf (F,"%f",&data[y][x]);
assert (scanned == 1);
}
}

void Read3x3(FILE *F)
{
assert (F != NULL);
Clear();

for (int y = 0; y < 4; y++)
{
if (y == 2) continue;

for (int x = 0; x < 4; x++)
{
if (x == 2) continue;
int scanned = fscanf (F,"%f",&data[y][x]);
assert (scanned == 1);
}
}
}

/***** Stuff Added By Ali BaderEddin *****/


// Loading OpenGL matrix into our Matrix
void LoadOpenGLMatrix (float *mat)
{
for (int i = 0; i < 16; i++)
this->data[i%4][i/4] = mat[i];
}

// Saving our matrix into an OpenGL Matrix
float * GetOpenGLMatrix ()
{
float * mat;

mat = (float *) malloc (16 * sizeof (float));

for (int i = 0; i < 16; i++)
mat[i] = this->data[i%4][i/4];

return mat;
}
};

#endif

Share this post


Link to post
Share on other sites
matrix.cpp

//*************************************************************************
//
// File Name: Matrix.cpp
// Author : Justin Legakis (Original Author)
// Ali BaderEddin (Applied some changes + added useful comments)
//
// Description: A class that represents a matrix and supports many matrix
// operations.
//
// 0 1 2 3
// 0 [1 0 0 5]
// 1 [0 1 0 0]
// 2 [0 0 1 0] ==> matrix [0][3] is equal to 5
// 3 [0 0 0 1] (that's how matrix is represened)
//
//*************************************************************************/


#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>

#include "matrix.h"
#include "vectors.h"

// OVERLOADED OPERATORS

Matrix operator+(const Matrix& A, const Matrix& B)
{
Matrix answer;
for (int y=0; y<4; y++)
for (int x=0; x<4; x++)
answer.data[y][x] = A.data[y][x] + B.data[y][x];

return answer;
}

Matrix operator-(const Matrix& A, const Matrix& B)
{
Matrix answer;
for (int y=0; y<4; y++)
for (int x=0; x<4; x++)
answer.data[y][x] = A.data[y][x] - B.data[y][x];

return answer;
}

Matrix operator*(const Matrix& A, const Matrix& B)
{
Matrix answer;

for (int y=0; y<4; y++)
for (int x=0; x<4; x++)
for (int i=0; i<4; i++)
answer.data[y][x] += A.data[y][i] * B.data[i][x];

return answer;
}

Matrix operator*(const Matrix& A, float f)
{
Matrix answer;
for (int y=0; y<4; y++)
for (int x=0; x<4; x++)
answer.data[y][x] = A.data[y][x] * f;

return answer;
}

// TRANSFORMATIONS

/* Translation Matrix

0 1 2 3
0 [1 0 0 t_x]
1 [0 1 0 t_y]
2 [0 0 1 t_z]
3 [0 0 0 1]

*/

void Matrix::Translate(float t_x, float t_y, float t_z)
{
Matrix t;
t.SetToIdentity();
t.data[0][3] = t_x;
t.data[1][3] = t_y;
t.data[2][3] = t_z;
t *= *this;
*this = t;
}

/* Scaling Matrix

0 1 2 3
0 [s_z 0 0 0]
1 [0 s_y 0 0]
2 [0 0 s_z 0]
3 [0 0 0 1]

*/

void Matrix::Scale(float s_x, float s_y, float s_z)
{
Matrix s;
s.SetToIdentity();
s.data[0][0] = s_x;
s.data[1][1] = s_y;
s.data[2][2] = s_z;
s.data[3][3] = 1;
s *= *this;
*this = s;
}

/* X Rotation Matrix

0 1 2 3
0 [1 0 0 0]
1 [0 cos -sin 0]
2 [0 sin cos 0]
3 [0 0 0 1]

*/


void Matrix::XRotate(float theta)
{
Matrix rx;
rx.SetToIdentity();
rx.data[1][1]= (float)cos((float)theta);
rx.data[1][2]=-(float)sin((float)theta);
rx.data[2][1]= (float)sin((float)theta);
rx.data[2][2]= (float)cos((float)theta);
rx *= *this;
*this = rx;
}

/* Y Rotation Matrix

0 1 2 3
0 [cos 0 sin 0]
1 [0 1 0 0]
2 [-sin 0 cos 0]
3 [0 0 0 1]

*/


void Matrix::YRotate(float theta)
{
Matrix ry;
ry.SetToIdentity();
ry.data[0][0]= (float)cos((float)theta);
ry.data[0][2]= (float)sin((float)theta);
ry.data[2][0]=-(float)sin((float)theta);
ry.data[2][2]= (float)cos((float)theta);
ry *= *this;
*this = ry;
}

/* Z Rotation Matrix

0 1 2 3
0 [cos -sin 0 0]
1 [sin cos 0 0]
2 [0 0 1 0]
3 [0 0 0 1]

*/


void Matrix::ZRotate(float theta)
{
Matrix rz;
rz.SetToIdentity();
rz.data[0][0]= (float)cos((float)theta);
rz.data[0][1]=-(float)sin((float)theta);
rz.data[1][0]= (float)sin((float)theta);
rz.data[1][1]= (float)cos((float)theta);
rz *= *this;
*this = rz;
}

void Matrix::Transform(Vec4f &v)
{
Vec4f answer;

for (int y=0; y<4; y++)
{
answer.data[y] = 0;
for (int i=0; i<4; i++)
answer.data[y] += data[y][i] * v[i];
}

v = answer;
}


Share this post


Link to post
Share on other sites
vector.h

//*************************************************************************
//
// File Name: Vector.h
// Author : Justin Legakis (Original Author)
// Ali BaderEddin (Applied some changes)
//
// Description: A class that represents a 2d, 3d, and 4d vector
// and supports many vector operations.
//
//*************************************************************************/


#ifndef _VECTORS_H_
#define _VECTORS_H_

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>

class Matrix;

class Vec2f
{
private:

// REPRESENTATION
float data[2];

public:

// CONSTRUCTORS & DESTRUCTOR
Vec2f() { data[0] = data[1] = 0; }

Vec2f(const Vec2f &V)
{
data[0] = V.data[0];
data[1] = V.data[1];
}

Vec2f(float d0, float d1)
{
data[0] = d0;
data[1] = d1;
}

Vec2f(const Vec2f &V1, const Vec2f &V2)
{
data[0] = V1.data[0] - V2.data[0];
data[1] = V1.data[1] - V2.data[1];
}

~Vec2f() { }

// ACCESSORS
void Get(float &d0, float &d1) const
{
d0 = data[0];
d1 = data[1];
}

float operator[](int i) const
{
assert (i >= 0 && i < 2);
return data[i];
}

float x() const { return data[0]; }
float y() const { return data[1]; }
float Length() const
{
float l = (float)sqrt( data[0] * data[0] + data[1] * data[1] );
return l;
}

// MODIFIERS
void Set(float d0, float d1)
{
data[0] = d0;
data[1] = d1;
}

void Scale(float d0, float d1)
{
data[0] *= d0;
data[1] *= d1;
}

void Divide(float d0, float d1)
{
data[0] /= d0;
data[1] /= d1;
}

void Negate()
{
data[0] = -data[0];
data[1] = -data[1];
}

// OVERLOADED OPERATORS
Vec2f& operator=(const Vec2f &V)
{
data[0] = V.data[0];
data[1] = V.data[1];
return *this;
}

int operator==(const Vec2f &V) const
{
return ((data[0] == V.data[0]) &&
(data[1] == V.data[1]));
}

int operator!=(const Vec2f &V)
{
return ((data[0] != V.data[0]) ||
(data[1] != V.data[1]));
}

Vec2f& operator+=(const Vec2f &V)
{
data[0] += V.data[0];
data[1] += V.data[1];
return *this;
}

Vec2f& operator-=(const Vec2f &V)
{
data[0] -= V.data[0];
data[1] -= V.data[1];
return *this;
}

Vec2f& operator*=(float f)
{
data[0] *= f;
data[1] *= f;
return *this;
}

Vec2f& operator/=(float f)
{
data[0] /= f;
data[1] /= f;
return *this;
}

// OPERATIONS
float Dot2(const Vec2f &V) const
{
return data[0] * V.data[0] + data[1] * V.data[1] ;
}

// STATIC OPERATIONS
static void Add(Vec2f &a, const Vec2f &b, const Vec2f &c )
{
a.data[0] = b.data[0] + c.data[0];
a.data[1] = b.data[1] + c.data[1];
}

static void Sub(Vec2f &a, const Vec2f &b, const Vec2f &c )
{
a.data[0] = b.data[0] - c.data[0];
a.data[1] = b.data[1] - c.data[1];
}

static void CopyScale(Vec2f &a, const Vec2f &b, float c )
{
a.data[0] = b.data[0] * c;
a.data[1] = b.data[1] * c;
}

static void AddScale(Vec2f &a, const Vec2f &b, const Vec2f &c, float d )
{
a.data[0] = b.data[0] + c.data[0] * d;
a.data[1] = b.data[1] + c.data[1] * d;
}

static void Average(Vec2f &a, const Vec2f &b, const Vec2f &c )
{
a.data[0] = (b.data[0] + c.data[0]) * 0.5f;
a.data[1] = (b.data[1] + c.data[1]) * 0.5f;
}

static void WeightedSum(Vec2f &a, const Vec2f &b, float c, const Vec2f &d, float e )
{
a.data[0] = b.data[0] * c + d.data[0] * e;
a.data[1] = b.data[1] * c + d.data[1] * e;
}

// INPUT / OUTPUT
void Write(FILE *F = stdout)
{
fprintf (F, "%f %f\n",data[0],data[1]);
}
};

// ====================================================================
// ====================================================================

class Vec3f
{
private:

// REPRESENTATION
float data[3];

public:

// CONSTRUCTORS & DESTRUCTOR
Vec3f() { data[0] = data[1] = data[2] = 0; }

Vec3f(const Vec3f &V)
{
data[0] = V.data[0];
data[1] = V.data[1];
data[2] = V.data[2];
}

Vec3f(float d0, float d1, float d2)
{
data[0] = d0;
data[1] = d1;
data[2] = d2;
}

Vec3f(const Vec3f &V1, const Vec3f &V2)
{
data[0] = V1.data[0] - V2.data[0];
data[1] = V1.data[1] - V2.data[1];
data[2] = V1.data[2] - V2.data[2];
}

~Vec3f() { }

// ACCESSORS
void Get(float &d0, float &d1, float &d2) const
{
d0 = data[0];
d1 = data[1];
d2 = data[2];
}

float operator[](int i) const
{
assert (i >= 0 && i < 3);
return data[i];
}

float x() const { return data[0]; }
float y() const { return data[1]; }
float z() const { return data[2]; }
float r() const { return data[0]; }
float g() const { return data[1]; }
float b() const { return data[2]; }
float Length() const
{
float l = (float)sqrt( data[0] * data[0] +
data[1] * data[1] +
data[2] * data[2] );
return l;
}

// MODIFIERS
void Set(float d0, float d1, float d2)
{
data[0] = d0;
data[1] = d1;
data[2] = d2;
}

void Scale(float d0, float d1, float d2)
{
data[0] *= d0;
data[1] *= d1;
data[2] *= d2;
}

void Divide(float d0, float d1, float d2)
{
data[0] /= d0;
data[1] /= d1;
data[2] /= d2;
}

void Normalize()
{
float l = Length();
if (l > 0)
{
data[0] /= l;
data[1] /= l;
data[2] /= l;
}
}

void Negate()
{
data[0] = -data[0];
data[1] = -data[1];
data[2] = -data[2];
}

// OVERLOADED OPERATORS
Vec3f& operator=(const Vec3f &V)
{
data[0] = V.data[0];
data[1] = V.data[1];
data[2] = V.data[2];
return *this;
}

int operator==(const Vec3f &V)
{
return ((data[0] == V.data[0]) &&
(data[1] == V.data[1]) &&
(data[2] == V.data[2]));
}

int operator!=(const Vec3f &V)
{
return ((data[0] != V.data[0]) ||
(data[1] != V.data[1]) ||
(data[2] != V.data[2]));
}

Vec3f& operator+=(const Vec3f &V)
{
data[0] += V.data[0];
data[1] += V.data[1];
data[2] += V.data[2];
return *this;
}

Vec3f& operator-=(const Vec3f &V)
{
data[0] -= V.data[0];
data[1] -= V.data[1];
data[2] -= V.data[2];
return *this;
}

Vec3f& operator*=(int i)
{
data[0] = float(data[0] * i);
data[1] = float(data[1] * i);
data[2] = float(data[2] * i);
return *this;
}

Vec3f& operator*=(float f)
{
data[0] *= f;
data[1] *= f;
data[2] *= f;
return *this;
}

Vec3f& operator/=(int i)
{
data[0] = float(data[0] / i);
data[1] = float(data[1] / i);
data[2] = float(data[2] / i);
return *this;
}

Vec3f& operator/=(float f)
{
data[0] /= f;
data[1] /= f;
data[2] /= f;
return *this;
}

// OPERATIONS
float Dot3(const Vec3f &V) const
{
return data[0] * V.data[0] +
data[1] * V.data[1] +
data[2] * V.data[2] ;
}

// STATIC OPERATIONS
friend void Add(Vec3f &a, const Vec3f &b, const Vec3f &c )
{
a.data[0] = b.data[0] + c.data[0];
a.data[1] = b.data[1] + c.data[1];
a.data[2] = b.data[2] + c.data[2];
}

friend void Sub(Vec3f &a, const Vec3f &b, const Vec3f &c )
{
a.data[0] = b.data[0] - c.data[0];
a.data[1] = b.data[1] - c.data[1];
a.data[2] = b.data[2] - c.data[2];
}

friend void CopyScale(Vec3f &a, const Vec3f &b, float c )
{
a.data[0] = b.data[0] * c;
a.data[1] = b.data[1] * c;
a.data[2] = b.data[2] * c;
}

friend void AddScale(Vec3f &a, const Vec3f &b, const Vec3f &c, float d )
{
a.data[0] = b.data[0] + c.data[0] * d;
a.data[1] = b.data[1] + c.data[1] * d;
a.data[2] = b.data[2] + c.data[2] * d;
}

friend void Average(Vec3f &a, const Vec3f &b, const Vec3f &c )
{
a.data[0] = (b.data[0] + c.data[0]) * 0.5f;
a.data[1] = (b.data[1] + c.data[1]) * 0.5f;
a.data[2] = (b.data[2] + c.data[2]) * 0.5f;
}

friend void WeightedSum(Vec3f &a, const Vec3f &b, float c, const Vec3f &d, float e )
{
a.data[0] = b.data[0] * c + d.data[0] * e;
a.data[1] = b.data[1] * c + d.data[1] * e;
a.data[2] = b.data[2] * c + d.data[2] * e;
}

static void Cross3(Vec3f &c, const Vec3f &v1, const Vec3f &v2)
{
float x = v1.data[1]*v2.data[2] - v1.data[2]*v2.data[1];
float y = v1.data[2]*v2.data[0] - v1.data[0]*v2.data[2];
float z = v1.data[0]*v2.data[1] - v1.data[1]*v2.data[0];
c.data[0] = x; c.data[1] = y; c.data[2] = z;
}

// INPUT / OUTPUT
void Write(FILE *F = stdout)
{
fprintf (F, "%f %f %f\n",data[0],data[1],data[2]);
}
};

// ====================================================================
// ====================================================================

class Vec4f
{

private:

friend class Matrix;

// REPRESENTATION
float data[4];

public:

// CONSTRUCTORS & DESTRUCTOR
Vec4f() { data[0] = data[1] = data[2] = data[3] = 0; }

Vec4f(const Vec4f &V)
{
data[0] = V.data[0];
data[1] = V.data[1];
data[2] = V.data[2];
data[3] = V.data[3];
}

Vec4f(float d0, float d1, float d2, float d3)
{
data[0] = d0;
data[1] = d1;
data[2] = d2;
data[3] = d3;
}

Vec4f(const Vec3f &V, float w)
{
data[0] = V.x();
data[1] = V.y();
data[2] = V.z();
data[3] = w;
}

Vec4f(const Vec4f &V1, const Vec4f &V2)
{
data[0] = V1.data[0] - V2.data[0];
data[1] = V1.data[1] - V2.data[1];
data[2] = V1.data[2] - V2.data[2];
data[3] = V1.data[3] - V2.data[3];
}

~Vec4f() { }

// ACCESSORS
void Get(float &d0, float &d1, float &d2, float &d3) const
{
d0 = data[0];
d1 = data[1];
d2 = data[2];
d3 = data[3];
}

float operator[](int i) const
{
assert (i >= 0 && i < 4);
return data[i];
}

float x() const { return data[0]; }
float y() const { return data[1]; }
float z() const { return data[2]; }
float w() const { return data[3]; }
float r() const { return data[0]; }
float g() const { return data[1]; }
float b() const { return data[2]; }
float a() const { return data[3]; }

float Length() const
{
float l = (float)sqrt( data[0] * data[0] +
data[1] * data[1] +
data[2] * data[2] +
data[3] * data[3] );
return l;
}

// MODIFIERS
void Set(float d0, float d1, float d2, float d3)
{
data[0] = d0;
data[1] = d1;
data[2] = d2;
data[3] = d3;
}

void Scale(float d0, float d1, float d2, float d3)
{
data[0] *= d0;
data[1] *= d1;
data[2] *= d2;
data[3] *= d3;
}

void Divide(float d0, float d1, float d2, float d3)
{
data[0] /= d0;
data[1] /= d1;
data[2] /= d2;
data[3] /= d3;
}

void Negate()
{
data[0] = -data[0];
data[1] = -data[1];
data[2] = -data[2];
data[3] = -data[3];
}

void Normalize()
{
float l = Length();
if (l > 0)
{
data[0] /= l;
data[1] /= l;
data[2] /= l;
}
}

void DivideByW()
{
if (data[3] != 0)
{
data[0] /= data[3];
data[1] /= data[3];
data[2] /= data[3];
}
else
{
data[0] = data[1] = data[2] = 0;
}

data[3] = 1;
}

// OVERLOADED OPERATORS
Vec4f& operator=(const Vec4f &V)
{
data[0] = V.data[0];
data[1] = V.data[1];
data[2] = V.data[2];
data[3] = V.data[3];
return *this;
}

int operator==(const Vec4f &V) const
{
return ((data[0] == V.data[0]) &&
(data[1] == V.data[1]) &&
(data[2] == V.data[2]) &&
(data[3] == V.data[3]));
}

int operator!=(const Vec4f &V) const
{
return ((data[0] != V.data[0]) ||
(data[1] != V.data[1]) ||
(data[2] != V.data[2]) ||
(data[3] != V.data[3]));
}

Vec4f& operator+=(const Vec4f &V)
{
data[0] += V.data[0];
data[1] += V.data[1];
data[2] += V.data[2];
data[3] += V.data[3];
return *this;
}

Vec4f& operator-=(const Vec4f &V)
{
data[0] -= V.data[0];
data[1] -= V.data[1];
data[2] -= V.data[2];
data[3] -= V.data[3];
return *this;
}

Vec4f& operator*=(float f)
{
data[0] *= f;
data[1] *= f;
data[2] *= f;
data[3] *= f;
return *this;
}

Vec4f& operator/=(float f)
{
data[0] /= f;
data[1] /= f;
data[2] /= f;
data[3] /= f;
return *this;
}

// OPERATIONS
float Dot2(const Vec4f &V) const
{
return data[0] * V.data[0] +
data[1] * V.data[1];
}

float Dot3(const Vec4f &V) const
{
return data[0] * V.data[0] +
data[1] * V.data[1] +
data[2] * V.data[2];
}

float Dot4(const Vec4f &V) const
{
return data[0] * V.data[0] +
data[1] * V.data[1] +
data[2] * V.data[2] +
data[3] * V.data[3];
}

// STATIC OPERATIONS
static void Add(Vec4f &a, const Vec4f &b, const Vec4f &c )
{
a.data[0] = b.data[0] + c.data[0];
a.data[1] = b.data[1] + c.data[1];
a.data[2] = b.data[2] + c.data[2];
a.data[3] = b.data[3] + c.data[3];
}

static void Sub(Vec4f &a, const Vec4f &b, const Vec4f &c )
{
a.data[0] = b.data[0] - c.data[0];
a.data[1] = b.data[1] - c.data[1];
a.data[2] = b.data[2] - c.data[2];
a.data[3] = b.data[3] - c.data[3];
}

static void CopyScale(Vec4f &a, const Vec4f &b, float c )
{
a.data[0] = b.data[0] * c;
a.data[1] = b.data[1] * c;
a.data[2] = b.data[2] * c;
a.data[3] = b.data[3] * c;
}

static void AddScale(Vec4f &a, const Vec4f &b, const Vec4f &c, float d )
{
a.data[0] = b.data[0] + c.data[0] * d;
a.data[1] = b.data[1] + c.data[1] * d;
a.data[2] = b.data[2] + c.data[2] * d;
a.data[3] = b.data[3] + c.data[3] * d;
}

static void Average(Vec4f &a, const Vec4f &b, const Vec4f &c )
{
a.data[0] = (b.data[0] + c.data[0]) * 0.5f;
a.data[1] = (b.data[1] + c.data[1]) * 0.5f;
a.data[2] = (b.data[2] + c.data[2]) * 0.5f;
a.data[3] = (b.data[3] + c.data[3]) * 0.5f;
}

static void WeightedSum(Vec4f &a, const Vec4f &b, float c, const Vec4f &d, float e )
{
a.data[0] = b.data[0] * c + d.data[0] * e;
a.data[1] = b.data[1] * c + d.data[1] * e;
a.data[2] = b.data[2] * c + d.data[2] * e;
a.data[3] = b.data[3] * c + d.data[3] * e;
}

static void Cross3(Vec4f &c, const Vec4f &v1, const Vec4f &v2)
{
float x = v1.data[1]*v2.data[2] - v1.data[2]*v2.data[1];
float y = v1.data[2]*v2.data[0] - v1.data[0]*v2.data[2];
float z = v1.data[0]*v2.data[1] - v1.data[1]*v2.data[0];
c.data[0] = x; c.data[1] = y; c.data[2] = z;
}

// INPUT / OUTPUT
void Write(FILE *F = stdout)
{
fprintf (F, "%f %f %f %f\n",data[0],data[1],data[2],data[3]);
}
};

#endif



Share this post


Link to post
Share on other sites
test.cpp

#include "vectors.h"
#include "matrix.h"

void main ()
{
Matrix A, B, C;

A.SetToIdentity ();
A.Scale (2);

B.SetToIdentity ();
B.Translate (1, 1, 1);

C = A + B;

A.Write ();
B.Write ();
C.Write ();
}



Sorry for the inconvenience...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this