Hi,
I have been quite confused by matrix operations when developing games.
I decided to learn to understand it but having a little confusion now.
I created the following codes using opengl & glut:
main.cpp
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <atlstr.h>
#include <time.h>
#include "Cube.h"
#include "Vector4.h"
#include "Matrix16.h"
// Set the size of the OpenGL Window
double winL = -300;
double winR = 300;
double winB = -300;
double winT = 300;
double start;
double last;
double now;
void UpdateScene(void);
void DrawScene(void);
void DrawAxis(void);
void renderBitmapString(float x, float y, void *font,char *string);
void Keyboard(int key, int x, int y);
CCube cube(5);
// This function is continuously called.
void Idle(void)
{
DrawScene();
}
void renderBitmapString(float x, float y, void *font,char *string)
{
char *c;
glRasterPos2f(x, y);
for (c=string; *c != '\0'; c++) {
glutBitmapCharacter(font, *c);
}
} /* end renderBitmapString() */
void
UpdateScene(void)
{
last = clock();
now = (last - start) / CLOCKS_PER_SEC;
start = last;
cube.Update(now);
}
void
DrawScene(void)
{
UpdateScene();
glLoadIdentity();
gluLookAt(0, 0, 80, 0, 0, 0, 0, 1, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Your drawing code here
DrawAxis();
cube.Render();
// End drawing code
glutSwapBuffers();
}
void
DrawAxis(void)
{
glBegin(GL_LINES);
glColor3f(1, 0, 0);
glVertex3f(-200, 0, 0);
glVertex3f(200, 0, 0);
glColor3f(0, 1, 0);
glVertex3f(0, -200, 0);
glVertex3f(0, 200, 0);
glColor3f(0, 0, 1);
glVertex3f(0, 0, -200);
glVertex3f(0, 0, 200);
glEnd();
}
void
Init(void)
{
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glMatrixMode(GL_PROJECTION);
gluPerspective(45, (winR - winL) / (winT - winB), 1, 1000);
glMatrixMode(GL_MODELVIEW);
start = clock();
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glEnable ( GL_COLOR_MATERIAL ) ;
glEnable(GL_LIGHTING);
float pos[4] = {0, 100, 0, 1};
glLightfv(GL_LIGHT0, GL_POSITION, pos);
glEnable(GL_LIGHT0);
}
void
Reshape(int width, int height)
{
glViewport(0, 0, width, height);
}
/* ARGSUSED1 */
void
Key(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
case ' ':
glutIdleFunc(Idle);
break;
case 'q':
cube.Rotate(-5, 1, 0, 0, 1);
break;
case 'w':
cube.Rotate(5, 1, 0, 0, 1);
break;
case 'a':
cube.Rotate(-5, 0, 1, 0, 1);
break;
case 's':
cube.Rotate(5, 0, 1, 0, 1);
break;
case 'z':
cube.Rotate(-5, 0, 0, 1, 1);
break;
case 'x':
cube.Rotate(5, 0, 0, 1, 1);
break;
case 'r':
cube.Translate(-5, 0, 0, 2);
break;
case 'f':
cube.Translate(5, 0, 0, 2);
break;
case 'e':
cube.Translate(-5, 0, 0, 1);
break;
case 'd':
cube.Translate(5, 0, 0, 1);
break;
case 'l':
cube.Scale(2, 2, 2);
break;
default:
cube.Reset();
break;
}
}
void Keyboard(int key, int x, int y)
{
switch(key)
{
case GLUT_KEY_UP:
cube.Rotate(-5, 1, 0, 0, 2);
break;
case GLUT_KEY_DOWN:
cube.Rotate(5, 1, 0, 0, 2);
break;
case GLUT_KEY_LEFT:
cube.Rotate(-5, 0, 1, 0, 2);
break;
case GLUT_KEY_RIGHT:
cube.Rotate(5, 0, 1, 0, 2);
break;
case GLUT_KEY_PAGE_UP:
cube.Rotate(-5, 0, 0, 1, 2);
break;
case GLUT_KEY_PAGE_DOWN:
cube.Rotate(5, 0, 0, 1, 2);
break;
}
}
int
main(int argc, char **argv)
{
glutInitWindowSize((winR - winL), (winT - winB));
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE);
glutCreateWindow("Physics");
Init();
glutReshapeFunc(Reshape);
glutKeyboardFunc(Key);
glutSpecialFunc(Keyboard);
glutDisplayFunc(DrawScene);
glutIdleFunc(Idle);
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}
Matrix16.h
#pragma once
#include <iostream>
using namespace std;
#include "Vector4.h"
static const float PI = 3.14159265359f;
inline float DEG2RAD(float a)
{
return (PI/180*(a));
}
inline float RAD2DEG(float a)
{
return (180/PI*(a));
}
class CMatrix16
{
public:
CMatrix16(void);
CMatrix16(float m11, float m12, float m13, float m14,
float m21, float m22, float m23, float m24,
float m31, float m32, float m33, float m34,
float m41, float m42, float m43, float m44);
~CMatrix16(void);
// Modification
static CMatrix16 & Add(const CMatrix16 & m1, const CMatrix16 & m2, CMatrix16 & result);
static CMatrix16 & Subtract(const CMatrix16 & m1, const CMatrix16 & m2, CMatrix16 & result);
static CMatrix16 & Multiply(const CMatrix16 & m1, const CMatrix16 & m2, CMatrix16 & result);
static CMatrix16 & Multiply(const CMatrix16 & m1, float multiplyBy, CMatrix16 & result);
static CVector4 & Multiply(const CMatrix16 & m1, const CVector4 & v, CVector4 & result);
static CMatrix16 & Transpose(const CMatrix16 & m1, CMatrix16 & result);
//static CMatrix16 & Invert(const CMatrix16 & m1, CMatrix16 & result);
static CMatrix16 & SetIdentity(CMatrix16 & m1);
static float Determinant(const CMatrix16 & m1);
inline static CMatrix16 Translation(const CVector4 & v)
{
return Translation(v.X(), v.Y(), v.Z());
}
inline static CMatrix16 Translation(float x, float y, float z)
{
return CMatrix16(1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
x, y, z, 1);
}
inline static CMatrix16 Scale(float x, float y, float z)
{
return CMatrix16(x, 0, 0, 0,
0, y, 0, 0,
0, 0, z, 0,
0, 0, 0, 1);
}
inline static CMatrix16 Rotation(float angle, float x, float y, float z)
{
angle = angle - ((int) angle / 360);
angle = DEG2RAD(angle);
float c = cos(angle);
float s = sin(angle);
return CMatrix16(c + x * x * (1 - c), x * y * (1 - c) - s * z, x * z * (1 - c) + s * y, 0,
x * y * (1 - c) + s * z, c + y * y * (1 - c), y * z * (1 - c) - s * x, 0,
x * z * (1 - c) - s * y, y * z * (1 - c) + s * x, c + z * z * (1 - c), 0,
0, 0, 0, 1);
}
inline CMatrix16 & Transpose() { CMatrix16 temp(*this); return CMatrix16::Transpose(temp, (*this)); }
//inline CMatrix16 & Invert() { CMatrix16 temp((*this)); return CMatrix16::Invert(temp, (*this)); }
inline CMatrix16 & SetIdentity() { return CMatrix16::SetIdentity((*this)); }
inline float Determinant() const { return CMatrix16::Determinant((*this)); }
// Auxilliaries
CMatrix16 & operator+=(const CMatrix16 & m1) { return CMatrix16::Add((*this), m1, (*this)); }
CMatrix16 & operator-=(const CMatrix16 & m1) { return CMatrix16::Subtract((*this), m1, (*this)); }
CMatrix16 & operator*=(const CMatrix16 & m1) { CMatrix16 temp((*this)); return CMatrix16::Multiply(temp, m1, (*this)); }
CMatrix16 & operator*=(const float multiplyBy) { CMatrix16 temp((*this)); return CMatrix16::Multiply(temp, multiplyBy, (*this)); }
// Conversion
void ToArray(float * m) const
{
m[0] = _m11; m[4] = _m21; m[8] = _m31; m[12] = _m41;
m[1] = _m12; m[5] = _m22; m[9] = _m32; m[13] = _m42;
m[2] = _m13; m[6] = _m23; m[10] = _m33; m[14] = _m43;
m[3] = _m14; m[7] = _m24; m[11] = _m34; m[15] = _m44;
}
// Output and Input
void Write(ostream & out) const
{
out << "[\t" << _m11 << ",\t" << _m12 << ",\t" << _m13 << ",\t" << _m14 << "\t]" << endl
<< "[\t" << _m21 << ",\t" << _m22 << ",\t" << _m23 << ",\t" << _m24 << "\t]" << endl
<< "[\t" << _m31 << ",\t" << _m32 << ",\t" << _m33 << ",\t" << _m34 << "\t]" << endl
<< "[\t" << _m41 << ",\t" << _m42 << ",\t" << _m43 << ",\t" << _m44 << "\t]" << endl;
}
void Read(istream & in)
{
char ch;
in >> _m11 >> ch >> _m12 >> ch >> _m13 >> ch >> _m14
>> _m21 >> ch >> _m22 >> ch >> _m23 >> ch >> _m24
>> _m31 >> ch >> _m32 >> ch >> _m33 >> ch >> _m34
>> _m41 >> ch >> _m42 >> ch >> _m43 >> ch >> _m44;
}
float _m11, _m12, _m13, _m14,
_m21, _m22, _m23, _m24,
_m31, _m32, _m33, _m34,
_m41, _m42, _m43, _m44;
};
inline CMatrix16 operator+ (const CMatrix16 & m1, const CMatrix16 & m2) { CMatrix16 m; return CMatrix16::Add(m1, m2, m); }
inline CMatrix16 operator- (const CMatrix16 & m1, const CMatrix16 & m2) { CMatrix16 m; return CMatrix16::Subtract(m1, m2, m); }
inline CMatrix16 operator* (const CMatrix16 & m1, const CMatrix16 & m2) { CMatrix16 m; return CMatrix16::Multiply(m1, m2, m); }
inline CMatrix16 operator* (const CMatrix16 & m1, float multiplyBy) { CMatrix16 m; return CMatrix16::Multiply(m1, multiplyBy, m); }
inline CMatrix16 operator* (float multiplyBy, const CMatrix16 & m1) { CMatrix16 m; return CMatrix16::Multiply(m1, multiplyBy, m); }
inline CVector4 operator* (const CMatrix16 & m1, const CVector4 & v) { CVector4 temp; return CMatrix16::Multiply(m1, v, temp); }
inline CVector4 operator* (const CVector4 & v, const CMatrix16 & m1) { CVector4 temp; return CMatrix16::Multiply(m1, v, temp); }
inline ostream & operator<< (ostream & out, const CMatrix16 & mat) { mat.Write(out); return out; }
inline istream & operator>> (istream & in, CMatrix16 & mat) { mat.Read(in); return in; }
Matrix16.cpp
#include ".\matrix16.h"
CMatrix16::CMatrix16(void)
: _m11(0), _m12(0), _m13(0), _m14(0),
_m21(0), _m22(0), _m23(0), _m24(0),
_m31(0), _m32(0), _m33(0), _m34(0),
_m41(0), _m42(0), _m43(0), _m44(0)
{
}
CMatrix16::CMatrix16(float m11, float m12, float m13, float m14,
float m21, float m22, float m23, float m24,
float m31, float m32, float m33, float m34,
float m41, float m42, float m43, float m44)
: _m11(m11), _m12(m12), _m13(m13), _m14(m14),
_m21(m21), _m22(m22), _m23(m23), _m24(m24),
_m31(m31), _m32(m32), _m33(m33), _m34(m34),
_m41(m41), _m42(m42), _m43(m43), _m44(m44)
{
}
CMatrix16::~CMatrix16(void)
{
}
CMatrix16 & CMatrix16::Add(const CMatrix16 & m1, const CMatrix16 & m2, CMatrix16 & result)
{
result._m11 = m1._m11 + m2._m11;
result._m12 = m1._m12 + m2._m12;
result._m13 = m1._m13 + m2._m13;
result._m14 = m1._m14 + m2._m14;
result._m21 = m1._m21 + m2._m21;
result._m22 = m1._m22 + m2._m22;
result._m23 = m1._m23 + m2._m23;
result._m24 = m1._m24 + m2._m24;
result._m31 = m1._m31 + m2._m31;
result._m32 = m1._m32 + m2._m32;
result._m33 = m1._m33 + m2._m33;
result._m34 = m1._m34 + m2._m34;
result._m41 = m1._m41 + m2._m41;
result._m42 = m1._m42 + m2._m42;
result._m43 = m1._m43 + m2._m43;
result._m44 = m1._m44 + m2._m44;
return result;
}
CMatrix16 & CMatrix16::Subtract(const CMatrix16 & m1, const CMatrix16 & m2, CMatrix16 & result)
{
result._m11 = m1._m11 - m2._m11;
result._m12 = m1._m12 - m2._m12;
result._m13 = m1._m13 - m2._m13;
result._m14 = m1._m14 - m2._m14;
result._m21 = m1._m21 - m2._m21;
result._m22 = m1._m22 - m2._m22;
result._m23 = m1._m23 - m2._m23;
result._m24 = m1._m24 - m2._m24;
result._m31 = m1._m31 - m2._m31;
result._m32 = m1._m32 - m2._m32;
result._m33 = m1._m33 - m2._m33;
result._m34 = m1._m34 - m2._m34;
result._m41 = m1._m41 - m2._m41;
result._m42 = m1._m42 - m2._m42;
result._m43 = m1._m43 - m2._m43;
result._m44 = m1._m44 - m2._m44;
return result;
}
CMatrix16 & CMatrix16::Multiply(const CMatrix16 & m1, const CMatrix16 & m2, CMatrix16 & result)
{
result._m11 = m1._m11 * m2._m11 + m1._m12 * m2._m21 + m1._m13 * m2._m31 + m1._m14 * m2._m41;
result._m12 = m1._m11 * m2._m12 + m1._m12 * m2._m22 + m1._m13 * m2._m32 + m1._m14 * m2._m42;
result._m13 = m1._m11 * m2._m13 + m1._m12 * m2._m23 + m1._m13 * m2._m33 + m1._m14 * m2._m43;
result._m14 = m1._m11 * m2._m14 + m1._m12 * m2._m24 + m1._m13 * m2._m34 + m1._m14 * m2._m44;
result._m21 = m1._m21 * m2._m11 + m1._m22 * m2._m21 + m1._m23 * m2._m31 + m1._m24 * m2._m41;
result._m22 = m1._m21 * m2._m12 + m1._m22 * m2._m22 + m1._m23 * m2._m32 + m1._m24 * m2._m42;
result._m23 = m1._m21 * m2._m13 + m1._m22 * m2._m23 + m1._m23 * m2._m33 + m1._m24 * m2._m43;
result._m24 = m1._m21 * m2._m14 + m1._m22 * m2._m24 + m1._m23 * m2._m34 + m1._m24 * m2._m44;
result._m31 = m1._m31 * m2._m11 + m1._m32 * m2._m21 + m1._m33 * m2._m31 + m1._m34 * m2._m41;
result._m32 = m1._m31 * m2._m12 + m1._m32 * m2._m22 + m1._m33 * m2._m32 + m1._m34 * m2._m42;
result._m33 = m1._m31 * m2._m13 + m1._m32 * m2._m23 + m1._m33 * m2._m33 + m1._m34 * m2._m43;
result._m34 = m1._m31 * m2._m14 + m1._m32 * m2._m24 + m1._m33 * m2._m34 + m1._m34 * m2._m44;
result._m41 = m1._m41 * m2._m11 + m1._m42 * m2._m21 + m1._m43 * m2._m31 + m1._m44 * m2._m41;
result._m42 = m1._m41 * m2._m12 + m1._m42 * m2._m22 + m1._m43 * m2._m32 + m1._m44 * m2._m42;
result._m43 = m1._m41 * m2._m13 + m1._m42 * m2._m23 + m1._m43 * m2._m33 + m1._m44 * m2._m43;
result._m44 = m1._m41 * m2._m14 + m1._m42 * m2._m24 + m1._m43 * m2._m34 + m1._m44 * m2._m44;
return result;
}
CMatrix16 & CMatrix16::Multiply(const CMatrix16 & m1, float multiplyBy, CMatrix16 & result)
{
result._m11 = m1._m11 * multiplyBy;
result._m12 = m1._m12 * multiplyBy;
result._m13 = m1._m13 * multiplyBy;
result._m14 = m1._m14 * multiplyBy;
result._m21 = m1._m21 * multiplyBy;
result._m22 = m1._m22 * multiplyBy;
result._m23 = m1._m23 * multiplyBy;
result._m24 = m1._m24 * multiplyBy;
result._m31 = m1._m31 * multiplyBy;
result._m32 = m1._m32 * multiplyBy;
result._m33 = m1._m33 * multiplyBy;
result._m34 = m1._m34 * multiplyBy;
result._m41 = m1._m41 * multiplyBy;
result._m42 = m1._m42 * multiplyBy;
result._m43 = m1._m43 * multiplyBy;
result._m44 = m1._m44 * multiplyBy;
return result;
}
CVector4 & CMatrix16::Multiply(const CMatrix16 & m1, const CVector4 & v, CVector4 &result)
{
result.X(m1._m11 * v.X() + m1._m21 * v.Y() + m1._m31 * v.Z() + m1._m41);
result.Y(m1._m12 * v.X() + m1._m22 * v.Y() + m1._m32 * v.Z() + m1._m42);
result.Z(m1._m13 * v.X() + m1._m23 * v.Y() + m1._m33 * v.Z() + m1._m43);
return result;
}
CMatrix16 & CMatrix16::Transpose(const CMatrix16 & m1, CMatrix16 & result)
{
result._m11 = m1._m11;
result._m12 = m1._m21;
result._m13 = m1._m31;
result._m14 = m1._m41;
result._m21 = m1._m12;
result._m22 = m1._m22;
result._m23 = m1._m32;
result._m24 = m1._m42;
result._m31 = m1._m13;
result._m32 = m1._m23;
result._m33 = m1._m33;
result._m34 = m1._m43;
result._m41 = m1._m14;
result._m42 = m1._m24;
result._m43 = m1._m34;
result._m44 = m1._m44;
return result;
}
/*CMatrix16 & CMatrix16::Invert(const CMatrix16 & m1, CMatrix16 & result)
{
float temp = 1 / m1.Determinant();
result._m11 = m1._m22 * m1._m33 * m1._m44 + m1._m23 * m1._m34 * m1._m42 + m1._m24 * m1._m32 * m1._m43
- m1._m22 * m1._m34 * m1._m43 - m1._m23 * m1._m32 * m1._m44 - m1._m24 * m1._m33 * m1._m42;
result._m21 = m1._m12 * m1._m34 * m1._m43 + m1._m13 * m1._m32 * m1._m44 + m1._m14 * m1._m33 * m1._m42
- m1._m12 * m1._m33 * m1._m44 - m1._m13 * m1._m34 * m1._m42 - m1._m14 * m1._m32 * m1._m43;
result._m31 = m1._m12 * m1._m23 * m1._m44 + m1._m13 * m1._m24 * m1._m42 + m1._m14 * m1._m22 * m1._m43
- m1._m12 * m1._m24 * m1._m43 - m1._m13 * m1._m22 * m1._m44 - m1._m14 * m1._m23 * m1._m42;
result._m41 = m1._m12 * m1._m24 * m1._m33 + m1._m13 * m1._m22 * m1._m34 + m1._m14 * m1._m23 * m1._m32
- m1._m12 * m1._m23 * m1._m34 - m1._m13 * m1._m24 * m1._m32 - m1._m14 * m1._m22 * m1._m33;
result._m12 = m1._m21 * m1._m34 * m1._m43 + m1._m23 * m1._m31 * m1._m44 + m1._m24 * m1._m33 * m1._m41
- m1._m21 * m1._m33 * m1._m44 - m1._m23 * m1._m34 * m1._m41 - m1._m24 * m1._m31 * m1._m43;
result._m22 = m1._m11 * m1._m33 * m1._m44 + m1._m13 * m1._m34 * m1._m41 + m1._m14 * m1._m31 * m1._m43
- m1._m11 * m1._m34 * m1._m43 - m1._m13 * m1._m31 * m1._m44 - m1._m14 * m1._m33 * m1._m41;
result._m32 = m1._m11 * m1._m24 * m1._m43 + m1._m13 * m1._m21 * m1._m44 + m1._m14 * m1._m23 * m1._m41
- m1._m11 * m1._m23 * m1._m44 - m1._m13 * m1._m24 * m1._m41 - m1._m14 * m1._m21 * m1._m43;
result._m42 = m1._m11 * m1._m23 * m1._m34 + m1._m13 * m1._m24 * m1._m31 + m1._m14 * m1._m21 * m1._m33
- m1._m11 * m1._m24 * m1._m33 - m1._m13 * m1._m21 * m1._m34 - m1._m14 * m1._m23 * m1._m31;
result._m13 = m1._m21 * m1._m32 * m1._m44 + m1._m22 * m1._m34 * m1._m41 + m1._m24 * m1._m31 * m1._m42
- m1._m21 * m1._m34 * m1._m42 - m1._m22 * m1._m31 * m1._m44 - m1._m24 * m1._m32 * m1._m41;
result._m23 = m1._m11 * m1._m34 * m1._m42 + m1._m12 * m1._m31 * m1._m44 + m1._m14 * m1._m32 * m1._m41
- m1._m11 * m1._m32 * m1._m44 - m1._m12 * m1._m34 * m1._m41 - m1._m14 * m1._m31 * m1._m42;
result._m33 = m1._m11 * m1._m22 * m1._m44 + m1._m12 * m1._m24 * m1._m41 + m1._m14 * m1._m21 * m1._m42
- m1._m11 * m1._m24 * m1._m42 - m1._m12 * m1._m21 * m1._m44 - m1._m14 * m1._m22 * m1._m41;
result._m43 = m1._m11 * m1._m24 * m1._m32 + m1._m12 * m1._m21 * m1._m34 + m1._m14 * m1._m22 * m1._m31
- m1._m11 * m1._m22 * m1._m34 - m1._m12 * m1._m24 * m1._m31 - m1._m14 * m1._m21 * m1._m32;
result._m14 = m1._m21 * m1._m33 * m1._m42 + m1._m22 * m1._m31 * m1._m43 + m1._m23 * m1._m32 * m1._m41
- m1._m21 * m1._m32 * m1._m43 - m1._m22 * m1._m33 * m1._m41 - m1._m23 * m1._m31 * m1._m42;
result._m24 = m1._m11 * m1._m32 * m1._m43 + m1._m12 * m1._m33 * m1._m41 + m1._m13 * m1._m31 * m1._m42
- m1._m11 * m1._m22 * m1._m42 - m1._m12 * m1._m31 * m1._m43 - m1._m13 * m1._m32 * m1._m41;
result._m34 = m1._m11 * m1._m23 * m1._m42 + m1._m12 * m1._m21 * m1._m43 + m1._m13 * m1._m22 * m1._m41
- m1._m11 * m1._m22 * m1._m43 - m1._m12 * m1._m23 * m1._m41 - m1._m13 * m1._m21 * m1._m42;
result._m44 = m1._m11 * m1._m22 * m1._m33 + m1._m12 * m1._m23 * m1._m31 + m1._m13 * m1._m21 * m1._m32
- m1._m11 * m1._m23 * m1._m32 - m1._m12 * m1._m21 * m1._m33 - m1._m13 * m1._m22 * m1._m31;
result = result * temp;
return result;
}*/
CMatrix16 & CMatrix16::SetIdentity(CMatrix16 & m1)
{
m1._m11 = 1; m1._m12 = 0; m1._m13 = 0; m1._m14 = 0;
m1._m21 = 0; m1._m22 = 1; m1._m23 = 0; m1._m24 = 0;
m1._m31 = 0; m1._m32 = 0; m1._m33 = 1; m1._m34 = 0;
m1._m41 = 0; m1._m42 = 0; m1._m43 = 0; m1._m44 = 1;
return m1;
}
float CMatrix16::Determinant(const CMatrix16 & m1)
{
return m1._m11 * m1._m22 * m1._m33 * m1._m44 + m1._m11 * m1._m23 * m1._m34 * m1._m42 + m1._m11 * m1._m24 * m1._m32 * m1._m43 +
m1._m12 * m1._m21 * m1._m34 * m1._m43 + m1._m12 * m1._m23 * m1._m31 * m1._m44 + m1._m12 * m1._m24 * m1._m33 * m1._m41 +
m1._m13 * m1._m21 * m1._m32 * m1._m44 + m1._m13 * m1._m22 * m1._m34 * m1._m41 + m1._m13 * m1._m24 * m1._m31 * m1._m42 +
m1._m14 * m1._m21 * m1._m33 * m1._m42 + m1._m14 * m1._m22 * m1._m31 * m1._m43 + m1._m14 * m1._m23 * m1._m32 * m1._m41 -
m1._m11 * m1._m22 * m1._m34 * m1._m43 - m1._m11 * m1._m23 * m1._m32 * m1._m44 - m1._m11 * m1._m24 * m1._m33 * m1._m42 -
m1._m12 * m1._m21 * m1._m33 * m1._m44 - m1._m12 * m1._m23 * m1._m34 * m1._m41 - m1._m12 * m1._m24 * m1._m31 * m1._m43 -
m1._m13 * m1._m21 * m1._m34 * m1._m42 - m1._m13 * m1._m22 * m1._m31 * m1._m44 - m1._m13 * m1._m24 * m1._m32 * m1._m41 -
m1._m14 * m1._m21 * m1._m32 * m1._m43 - m1._m14 * m1._m22 * m1._m33 * m1._m41 - m1._m14 * m1._m23 * m1._m31 * m1._m42;
}
Vector4.h
#pragma once
#include <iostream>
using namespace std;
#include <math.h>
class CVector4
{
public:
// Constructors
CVector4(void);
CVector4(float x, float y, float z, float w = 1);
~CVector4(void);
// Selectors
inline float X() const { return _x; }
inline float Y() const { return _y; }
inline float Z() const { return _z; }
// Mutators
inline void X(float x) { _x = x; }
inline void Y(float y) { _y = y; }
inline void Z(float z) { _z = z; }
// Magnitude
inline float Length() const { return sqrt(LengthSq()); }
inline float LengthSq() const { return _x * _x + _y * _y + _z * _z; }
inline void Zero() { X(0); Y(0); Z(0); }
// Unit
CVector4 & Unit();
static void Unit(const CVector4 & v);
// Modification
static float Dot(const CVector4 & v1, const CVector4 & v2);
static CVector4 & Cross(const CVector4 & v1, const CVector4 & v2, CVector4 & result);
static CVector4 & Add(const CVector4 & v1, const CVector4 & v2, CVector4 & result);
static CVector4 & Subtract(const CVector4 & v1, const CVector4 & v2, CVector4 & result);
static CVector4 & Multiply(const CVector4 & v, float multiplyBy, CVector4 & result);
static CVector4 & Invert(CVector4 & v);
// Auxilliaries
CVector4 & operator+=(const CVector4 & v) { return CVector4::Add((*this), v, (*this)); }
CVector4 & operator-=(const CVector4 & v) { return CVector4::Subtract((*this), v, (*this)); }
CVector4 & operator*=(const CVector4 & v) { CVector4 temp((*this)); return CVector4::Cross(temp, v, (*this)); }
CVector4 & operator*=(float multiplyBy) { CVector4 temp((*this)); return CVector4::Multiply(temp, multiplyBy, (*this)); }
CVector4 & operator/=(float divideBy) { CVector4 temp((*this)); return CVector4::Multiply(temp, (1 / divideBy), (*this)); }
// Input and output
void Write(ostream & out) const { out << "[" << _x << "," << _y << "," << _z << "]"; }
void Read(istream & in) { char ch; in >> ch >> _x >> ch >> _y >> ch >> _z >> ch; }
private:
float _x, _y, _z, _w;
};
inline CVector4 operator+(const CVector4 & v1, const CVector4 & v2) { CVector4 v; return CVector4::Add(v1, v2, v); }
inline CVector4 operator-(const CVector4 & v1, const CVector4 & v2) { CVector4 v; return CVector4::Subtract(v1, v2, v); }
inline CVector4 operator*(const CVector4 & v1, const CVector4 & v2) { CVector4 v; return CVector4::Cross(v1, v2, v); }
inline CVector4 operator*(const CVector4 & v1, float multiplyBy) { CVector4 v; return CVector4::Multiply(v1, multiplyBy, v); }
inline CVector4 operator/(const CVector4 & v1, float divideBy) { CVector4 v; float m = 1 / divideBy; return CVector4::Multiply(v1, m, v); }
inline float operator|(const CVector4 & v1, const CVector4 & v2) { return CVector4::Dot(v1, v2); }
inline ostream & operator<<(ostream & out, const CVector4 & v) { v.Write(out); return out; }
inline istream & operator>>(istream & in, CVector4 & v) { v.Read(in); return in; }
Vector4.cpp
#include ".\vector4.h"
CVector4::CVector4(void)
: _x(0), _y(0), _z(0), _w(1)
{
}
CVector4::CVector4(float x, float y, float z, float w)
: _x(x), _y(y), _z(z), _w(w)
{
}
CVector4::~CVector4(void)
{
}
float CVector4::Dot(const CVector4 & v1, const CVector4 & v2)
{
return v1.X() * v2.X() + v1.Y() * v2.Y() + v1.Z() * v2.Z();
}
CVector4 & CVector4::Cross(const CVector4 & v1, const CVector4 & v2, CVector4 & result)
{
result.X(v1.Y() * v2.Z() - v1.Z() * v2.Y());
result.Y(v1.Z() * v2.X() - v1.X() * v2.Z());
result.Z(v1.X() * v2.Y() - v1.Y() * v2.X());
return result;
}
CVector4 & CVector4::Add(const CVector4 & v1, const CVector4 & v2, CVector4 & result)
{
result.X(v1.X() + v2.X());
result.Y(v1.Y() + v2.Y());
result.Z(v1.Z() + v2.Z());
return result;
}
CVector4 & CVector4::Subtract(const CVector4 & v1, const CVector4 & v2, CVector4 & result)
{
result.X(v1.X() - v2.X());
result.Y(v1.Y() - v2.Y());
result.Z(v1.Z() - v2.Z());
return result;
}
CVector4 & CVector4::Multiply(const CVector4 & v, float multiplyBy, CVector4 & result)
{
result.X(v.X() * multiplyBy);
result.Y(v.Y() * multiplyBy);
result.Z(v.Z() * multiplyBy);
return result;
}
CVector4 & CVector4::Invert(CVector4 & v)
{
v.X(-v.X());
v.Y(-v.Y());
v.Z(-v.Z());
return v;
}
cube.h
#pragma once
#include "Matrix16.h"
#include "Vector4.h"
class CCube
{
public:
CCube(void);
CCube(float size);
~CCube(void);
float GetSize() const { return _size; }
void Update(float dt);
void Render() const;
void DrawAxis() const;
void Rotate(float angle, float x, float y, float z, int Order)
{
switch(Order)
{
case 1:
_r = CMatrix16::Rotation(angle, x, y, z) * _r;
break;
case 2:
_r = _r * CMatrix16::Rotation(angle, x, y, z);
break;
}
MarkDirty();
}
void Translate(float x, float y, float z, int Order)
{
switch(Order)
{
case 1:
_t += (CVector4(x, y, z) * _r);
break;
case 2:
_t += CVector4(x, y, z);
break;
}
MarkDirty();
}
void Scale(float x, float y, float z)
{
_s._m11 *= x;
_s._m22 *= y;
_s._m33 *= z;
MarkDirty();
}
const CMatrix16 & GetTransform() const
{
if(_dirty)
{
_trans.SetIdentity();
_trans = _r * _s;
_trans._m41 = _t.X();
_trans._m42 = _t.Y();
_trans._m43 = _t.Z();
_trans._m44 = 1;
_dirty = false;
}
return _trans;
}
void MarkDirty() { _dirty = true; }
void Reset()
{
_s.SetIdentity();
_r.SetIdentity();
_t.Zero();
MarkDirty();
GetTransform();
}
private:
float _size;
mutable bool _dirty;
CMatrix16 _s;
CMatrix16 _r;
CVector4 _t;
mutable CMatrix16 _trans;
};
cube.cpp
#include "Cube.h"
#include <GL\glut.h>
CCube::CCube(void)
: _size(1), _dirty(true), _s(), _r(), _t(), _trans()
{
_s.SetIdentity();
_r.SetIdentity();
GetTransform();
}
CCube::CCube(float size)
: _size(size), _dirty(true), _s(), _r(), _t(), _trans()
{
_s.SetIdentity();
_r.SetIdentity();
GetTransform();
}
CCube::~CCube(void)
{
}
void CCube::Update(float dt)
{
}
void CCube::Render() const
{
glPushMatrix();
float m[16];
GetTransform().ToArray(m);
glMultMatrixf(m);
DrawAxis();
glColor3f(1, 0, 0);
glutSolidCube(_size);
glPopMatrix();
}
void CCube::DrawAxis(void) const
{
glBegin(GL_LINES);
glColor3f(1, 1, 0);
glVertex3f(-30, 0, 0);
glVertex3f(30, 0, 0);
glColor3f(1, 0, 1);
glVertex3f(0, -30, 0);
glVertex3f(0, 30, 0);
glColor3f(0, 1, 1);
glVertex3f(0, 0, -30);
glVertex3f(0, 0, 30);
glEnd();
}
Keys:
Q & W - Rotate clockwise-anticlockwise in along local X
A & S - Rotate clockwise-anticlockwise in along local Y
Z & X - Rotate clockwise-anticlockwise in along local Z
E & D - Translate in local X axis
A & S - Translate in world X axis
Up & Down Arrow - Rotate clockwise-anticlockwise in along world X
Left & Right Arrow - Rotate clockwise-anticlockwise in along world Y
Pg Up & Pg Down - Rotate clockwise-anticlockwise in along world Z
I am not sure whether the translation part is wrong or the rotation.
When I translate, say (20, 0, 0), then rotate 90 in world space Y, the object still rotate on its own space.
I would expect it to orbit around the world space Y.
Please anyone could give me some pointers?