Code:
//***********************************************
//** Matrix header for use with 1.0 object file *
//***********************************************
#ifndef _MATRIX_1_0
#define _MATRIX_1_0
#define PI 3.14159
//Defines a point in 2D space
struct point2D
{
int x;
int y;
point2D operator = (point2D newpoint)
{
x=newpoint.x;
y=newpoint.y;
return *this;
}
};
//Defines a point in 2D texture space
struct Texel
{
int u;
int v;
Texel operator =(Texel nt)
{
u=nt.u;
v=nt.v;
return *this;
}
};
//Defines a point in 3D space
struct point3D
{
double x;
double y;
double z;
point3D operator =(point3D np)
{
x=np.x;
y=np.y;
z=np.z;
return *this;
}
};
//Defines a vertex in 3D space
struct Vertex
{
point3D Local;
point3D World;
point3D View;
point2D Screen;
Texel Texture;
Vertex operator =(Vertex vt)
{
Local=vt.Local;
World=vt.World;
View=vt.View;
Screen=vt.Screen;
Texture=vt.Texture;
return *this;
}
};
//Pipeline modes
enum plMode {WORLD,VIEW,SCREEN};
//Structure to store state of pipeline
struct plPipeLine
{
int plProjDist;
point2D plCenters;
point3D plTranslate_Local;
point3D plScale_Local;
point3D plRotate_Local;
point3D plTranslate_World;
point3D plRotate_World;
int NumVertexes;
Vertex *Vertexes;
};
class MatrixPackage
{
double master[4][4];
const double COS[360];
const double SIN[360];
point2D Centers;
int ProjDist;
//Master concatenation function
void MatrixMult(const double mat1[4][4],
const double mat2[4][4],
double result[4][4]);
void Copy(const double source[4][4],const double target[4][4]);
//Setup translation matrix
void Translate(const double dx,const double dy,
const double dz);
void Translate(point3D tr);
//Setup scale matrix
void Scale(const double sx,const double sy,const double sz);
void Scale(point3D sc);
//Setup rotation matrix
void Rotate(const int ax=0,const int ay=0,const int az=0);
void Rotate(point3D rt);
//Transform from local to world space
void WorldTransform(Vertex *Vertexes,const int NumVertexes);
//Transform from world to view space
void ViewTransform(Vertex *Vertexes,const int NumVertexes);
//Project from 3D to 2D - view space to screen space
void Project(Vertex *Vertexes,const int NumVertexes);
//Runs pipeline from local space to world space
void ToWorld(plPipeLine &plState);
//Runs pipeline from world space to view space
void ToView(plPipeLine &plState);
//Runs full pipeline, local to screen space
void ToScreen(plPipeLine &plState);
public:
MatrixPackage1(void);
void InitMaster(void);
void SetProjectionDist(const int newdistance)
{ProjDist=newdistance;};
void SetCenterScreen(const int cx,const int cy)
{Centers.x=cx;Centers.y=cy;};
void SetCenterScreen(point2D nc) {Centers=nc;};
//Execute pipeline according to plMode
double *Execute(plMode pm);
};
#endif //end of _MATRIX_ define block
//**************************
//* 3D Matrix package *
//* Source code file *
//* Compiled to matrix.obj *
//* Version 1.0 *
//**************************
#include <math.h>
#include "c:\tc\matrix.h"
#ifndef _MATRIX_1_0
#error Object file version does not match header version
#endif
MatrixPackage::MatrixPackage(void)
{
InitMaster();
for (int i=0;i<360;i++)
{
const COS[i]=cos((double)i*PI/(double)180.0);
const SIN[i]=sin((double)i*PI/(double)180.0);
}
CenterX=160;CenterY=100;ProjDist=320;
}
void MatrixPackage::InitMaster(void)
{
//Sets matrix to identity matrix
master[0][0]=1.0;
master[0][1]=0.0;
master[0][2]=0.0;
master[0][3]=0.0;
master[1][0]=0.0;
master[1][1]=1.0;
master[1][2]=0.0;
master[1][3]=0.0;
master[2][0]=0.0;
master[2][1]=0.0;
master[2][2]=1.0;
master[2][3]=0.0;
master[3][0]=0.0;
master[3][1]=0.0;
master[3][2]=0.0;
master[3][3]=1.0;
}
void MatrixPackage::Copy(const double source[4][4],
const double target[4][4])
{
target[0][0]=source[0][0];
target[0][1]=source[0][1];
target[0][2]=source[0][2];
target[0][3]=source[0][3];
target[1][0]=source[1][0];
target[1][1]=source[1][1];
target[1][2]=source[1][2];
target[1][3]=source[1][3];
target[2][0]=source[2][0];
target[2][1]=source[2][1];
target[2][2]=source[2][2];
target[2][3]=source[2][3];
target[3][0]=source[3][0];
target[3][1]=source[3][1];
target[3][2]=source[3][2];
target[3][3]=source[3][3];
}
void MatrixPackage::MatrixMult(const double mat1[4][4],
const double mat2[4][4],
double result[4][4])
{
for (int i=0;i<4;i++)
{
for (int j=0;j<4;j++)
{
result[i][j]+=((mat1[i][0]*mat2[0][j])+
(mat1[i][1]*mat2[1][j])+
(mat1[i][2]*mat2[2][j])+
(mat1[i][3]*mat2[3][j]));
}
}
}
void MatrixPackage::Translate(const double dx,
const double dy,
const double dz)
{
double temp[4][4];
double result[4][4];
temp[0][0]=1.0;
temp[0][1]=0.0;
temp[0][2]=0.0;
temp[0][3]=0.0;
temp[1][0]=0.0;
temp[1][1]=1.0;
temp[1][2]=0.0;
temp[1][3]=0.0;
temp[2][0]=0.0;
temp[2][1]=0.0;
temp[2][2]=1.0;
temp[2][3]=0.0;
temp[3][0]=dx;
temp[3][1]=dy;
temp[3][2]=dz;
temp[3][3]=1.0;
MatrixMult(temp,master,result);
Copy(result,master);
}
MatrixPackage::Scale(const double sx,
const double sy,
const double sz)
{
double temp[4][4];
double result[4][4];
temp[0][0]=sx;
temp[0][1]=0.0;
temp[0][2]=0.0;
temp[0][3]=0.0;
temp[1][0]=0.0;
temp[1][1]=sy;
temp[1][2]=0.0;
temp[1][3]=0.0;
temp[2][0]=0.0;
temp[2][1]=0.0;
temp[2][2]=sz;
temp[2][3]=0.0;
temp[3][0]=0.0;
temp[3][1]=0.0;
temp[3][2]=0.0;
temp[3][3]=1.0;
MatrixMult(temp,master,result);
Copy(result,master);
}
void MatrixPackage::Rotate(const int ax,const int ay,const int az)
{
const double xmat[4][4];
const double ymat[4][4];
const double zmat[4][4];
double mat1[4][4];
double mat2[4][4];
//************************************************************************
//X rotation
xmat[0][0]=1.0;
xmat[0][1]=0.0;
xmat[0][2]=0.0;
xmat[0][3]=0.0;
xmat[1][0]=0.0;
xmat[1][1]=COS[ax];
xmat[1][2]=SIN[ax];
xmat[1][3]=0.0;
xmat[2][0]=0.0;
xmat[2][1]=-SIN[ax];
xmat[2][2]=COS[ax];
xmat[2][3]=0.0;
xmat[3][0]=0.0;
xmat[3][1]=0.0;
xmat[3][2]=0.0;
xmat[3][3]=1.0;
//Multiply - store result in mat1
MatrixMult(xmat,master,mat1);
//************************************************** **********************
//************************************************** **********************
//Y rotation
ymat[0][0]=COS[ay];
ymat[0][1]=0.0;
ymat[0][2]=-SIN[ay];
ymat[0][3]=0.0;
ymat[1][0]=0;
ymat[1][1]=1;
ymat[1][2]=0;
ymat[1][3]=0;
ymat[2][0]=SIN[ay];
ymat[2][1]=0;
ymat[2][2]=COS[ay];
ymat[2][3]=0;
ymat[3][0]=0.0;
ymat[3][1]=0.0;
ymat[3][2]=0.0;
ymat[3][3]=1.0;
//Multiply - store result in mat2
MatrixMult(ymat,mat1,mat2);
//************************************************** **********************
//************************************************** **********************
//Z rotation
zmat[0][0]=COS[az];
zmat[0][1]=SIN[az];
zmat[0][2]=0.0;
zmat[0][3]=0.0;
zmat[1][0]=-SIN[az];
zmat[1][1]=COS[az];
zmat[1][2]=0.0;
zmat[1][3]=0.0;
zmat[2][0]=0.0;
zmat[2][1]=0.0;
zmat[2][2]=1.0;
zmat[2][3]=0.0;
zmat[3][0]=0.0;
zmat[3][1]=0.0;
zmat[3][2]=0.0;
zmat[3][3]=1.0;
//Multiply - store result in master
MatrixMult(zmat,mat2,master);
//************************************************** **********************
}
void MatrixPackage::WorldTransform(Vertex *Vertexes,
const int NumVertexes)
{
for (int i=0;i<NumVertexes;i++)
{
double lx=Vertexes->Local.x;
double ly=Vertexes->Local.y;
double lz=Vertexes->Local.z;
Vertexes->World.x=lx*master[0][0]+ly*master[1][0]+
lz*master[2][0]+master[3][0];
Vertexes->World.y=lx*master[0][1]+ly*master[1][1]+
lz*master[2][1]+master[3][1];
Vertexes->World.z=lx*master[0][2]+lz*master[1][2]+
lz*master[2][2]+master[3][2];
}
}
void MatrixPackage::ViewTransform(Vertex *Vertexes,
const int NumVertexes)
{
for (int i=0;i<NumVertexes;i++)
{
double wx=Vertexes->World.x;
double wy=Vertexes->World.y;
double wz=Vertexes->World.z;
Vertexes->View.x=wx*master[0][0]+wy*master[1][0]+
wz*master[2][0]+master[3][0];
Vertexes->View.y=wx*master[0][1]+wy*master[1][1]+
wz*master[2][1]+master[3][1];
Vertexes->View.z=wx*master[0][2]+wz*master[1][2]+
wz*master[2][2]+master[3][2];
}
}
void MatrixPackage::Project(Vertex *Vertexes,
const int NumVertexes)
{
for (int i=0;i<NumVertexes;i++)
{
double vx=Vertexes->View.x;
double vy=Vertexes->View.y;
double vz=Vertexes->View.z;
Vertexes->Screen.x=(int)((vx*(double)ProjDist)/vz);
Vertexes->Screen.y=(int)((vy*(double)ProjDist)/vz);
Vertexes->Screen.x+=Centers.x;
Vertexes->Screen.y+=Centers.y;
}
}
void MatrixPackage::ToWorld(plPipeLine &plState)
{
SetProjectionDist(plState.plProjDist);
SetCenterScreen(plState.plCenters);
Translate(plState.plTranslate_Local);
Scale(plState.plScale_Local);
Rotate(plState.plRotate_Local);
Transform(plState.Vertexes,plState.NumVertexes);
}
void MatrixPackage::ToView(plPipeLine &plState)
{
SetProjectionDist(plState.plProjDist);
SetCenterScreen(plState.plCenters);
Translate(plState.plTranslate_Local);
Scale(plState.plScale_Local);
Rotate(plState.plRotate_Local);
Transform(plState.Vertexes,plState.NumVertexes);
InitMaster();
Translate(plState.plTranslate2);
Rotate(plState.plRotate2);
ViewTransform(plState.Vertexes,plState.NumVertexes);
}
void MatrixPackage::ToScreen(plPipeLine &plState)
{
SetProjectionDist(plState.plProjDist);
SetCenterScreen(plState.plCenters);
Translate(plState.plTranslate_Local);
Scale(plState.plScale_Local);
Rotate(plState.plRotate_Local);
Transform(plState.Vertexes,plState.NumVertexes);
InitMaster();
Translate(plState.plTranslate2);
Rotate(plState.plRotate2);
ViewTransform(plState.Vertexes,plState.NumVertexes);
Project(plState.Vertexes,plState.NumVertexes);
}
double *MatrixPackage1::Execute(plMode pm)
{
switch (pm)
{
case WORLD: ToWorld(plState);break;
case VIEW: ToView(plState);break;
case SCREEN: ToScreen(plState);break;
}
return &master;
}
void MatrixPackage::Translate(const point3D &pt)
{
Translate(pt.x,pt.y,pt.z);
}
void MatrixPackage::Rotate(const point3D &pt)
{
Rotate(pt.x,pt.y,pt.z);
}
void MatrixPackage::Scale(const point3D &pt)
{
Scale(pt.x,pt.y,pt.z);
}
This code will handle rotation, scaling, translation, etc.,etc.