📄 scene.cpp
字号:
// Scene.cpp: implementation of the CScene class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <math.h>
#include "2DCube.h"
#include "Scene.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CScene::CScene()
{}
CScene::~CScene()
{}
int CScene::SetMatrix(int matkind,Matrix * mat)
{
if( NULL == mat )
return 0;
switch (matkind)
{
case MAT_WORLD:
memcpy( (void *)&m_WorldMatrix , (void *)mat , sizeof(Matrix) );
break;
case MAT_VIEW:
memcpy( (void *)&m_ViewMatrix , (void *)mat , sizeof(Matrix) );
break;
case MAT_PROJ:
memcpy( (void *)&m_ProjMatrix , (void *)mat , sizeof(Matrix) );
break;
default:
break;
}
return 1;
}
//SetProjection用于把一个矩阵设置为透视投影矩阵。
Matrix * CScene::SetProjection(Matrix * projmat,float nearclip, float farclip, float fov)
{
IdentifyMatrix(projmat);
projmat ->_a43 = 1/nearclip;
projmat ->_a44 = 0;
return projmat;
}
//SetViewLookAt函数用于把一个矩阵设置为视矩阵。其实现如下:
Matrix * CScene::SetViewLookAt(Matrix * matView,Vert3 *vlookat, Vert3 *vEye, Vert3 *updir)
{
Vert3 u,v,n;
Matrix matvrp;
float mo;
n.x = vlookat->x - vEye->x; //计算向量n
n.y = vlookat->y - vEye->y;
n.z = vlookat->z - vEye->z;
ChaMult(&u,updir,&n); //updir叉乘n得到u
ChaMult(&v,&n,&u); //n叉乘u得到v
mo = ::sqrtf(u.x * u.x + u.y * u.y + u.z * u.z);//计算向量模长
u.x /= mo; //化为单位向量
u.y /= mo;
u.z /= mo;
mo = ::sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
v.x /= mo;
v.y /= mo;
v.z /= mo;
mo = ::sqrtf(n.x * n.x + n.y * n.y + n.z * n.z);
n.x /= mo;
n.y /= mo;
n.z /= mo;
IdentifyMatrix(matView); //设置复合的旋转矩阵
matView->_a11 = u.x;
matView->_a12 = u.y;
matView->_a13 = u.z;
matView->_a21 = v.x;
matView->_a22 = v.y;
matView->_a23 = v.z;
matView->_a31 = n.x;
matView->_a32 = n.y;
matView->_a33 = n.z;
IdentifyMatrix(&matvrp); //设置平移矩阵
matvrp._a14 = -vEye->x;
matvrp._a24 = -vEye->y;
matvrp._a34 = -vEye->z;
MultMatrix(matView,matView,&matvrp); //两矩阵相乘,得到最终的变换矩阵
return matView;
}
//矩阵右乘表示摄像机位置的矩阵matvrp实现摄像机的平移,得到最终的视矩阵。
//函数IdentifyMatrix把一个矩阵单位化:
Matrix * CScene::IdentifyMatrix(Matrix * mat)
{
mat->_a11 = 1.0f;
mat->_a12 = 0.0f;
mat->_a13 = 0.0f;
mat->_a14 = 0.0f;
mat->_a21 = 0.0f;
mat->_a22 = 1.0f;
mat->_a23 = 0.0f;
mat->_a24 = 0.0f;
mat->_a31 = 0.0f;
mat->_a32 = 0.0f;
mat->_a33 = 1.0f;
mat->_a34 = 0.0f;
mat->_a41 = 0.0f;
mat->_a42 = 0.0f;
mat->_a43 = 0.0f;
mat->_a44 = 1.0f;
return mat;
}
//函数MatRotation把一个矩阵设置为旋转变换矩阵。其实现如下:
Matrix * CScene::MatRotation(Matrix * mat,float alpha,int axis)
{
float sinalpha = (float)sin(alpha);
float cosalpha = (float)cos(alpha);
switch (axis) //依照参数值设置关于不同轴的旋转矩阵
{
case AXIS_X:
{
mat->_a11 = 1.0f;
mat->_a12 = 0.0f;
mat->_a13 = 0.0f;
mat->_a14 = 0.0f;
mat->_a21 = 0.0f;
mat->_a22 = cosalpha;
mat->_a23 = -sinalpha;
mat->_a24 =0.0f ;
mat->_a31 = 0.0f;
mat->_a32 = sinalpha;
mat->_a33 = cosalpha;
mat->_a34 = 0.0f;
mat->_a41 = 0.0f;
mat->_a42 = 0.0f;
mat->_a43 = 0.0f;
mat->_a44 = 1.0f;
}
break;
case AXIS_Y:
{
mat ->_a11 = cosalpha;
mat ->_a12 = 0.0f;
mat ->_a13 = sinalpha;
mat ->_a14 = 0.0f;
mat ->_a21 = 0.0f;
mat ->_a22 = 1.0f;
mat ->_a23 = 0.0f;
mat ->_a24 = 0.0f;
mat ->_a31 = -sinalpha;
mat ->_a32 = 0.0f;
mat ->_a33 = cosalpha;
mat ->_a34 = 0.0f;
mat ->_a41 = 0.0f;
mat ->_a42 = 0.0f;
mat ->_a43 = 0.0f;
mat ->_a44 = 1.0f;
}
break;
case AXIS_Z:
{
mat ->_a11 = cosalpha;
mat ->_a12 = -sinalpha;
mat ->_a13 = 0.0f;
mat ->_a14 = 0.0f;
mat ->_a21 = sinalpha;
mat ->_a22 = cosalpha;
mat ->_a23 = 0.0f;
mat ->_a24 = 0.0f;
mat ->_a31 = 0.0f;
mat ->_a32 = 0.0f;
mat ->_a33 = 1.0f;
mat ->_a34 = 0.0f;
mat ->_a41 = 0.0f;
mat ->_a42 = 0.0f;
mat ->_a43 = 0.0f;
mat ->_a44 = 1.0f;
}
break;
default:
break;
}
return mat;
}
//函数MatTranslation与MatRotation类似,它完成把一个矩阵设为平移变换矩阵的工作。其实现如下:
//函数的第一个参数是要被设置的矩阵,第二个参数是旋转的角度,第三个参数是旋转轴,必须为上面三个宏中的一个。该函数针对不同轴的旋转,把矩阵设为三种旋转矩阵中的一种。
Matrix * CScene::MatTranslation(Matrix * mat,float xoffset,float yoffset,float zoffset)
{
mat ->_a11 = 1.0f;
mat ->_a12 = 0.0f;
mat ->_a13 = 0.0f;
mat ->_a14 = xoffset;
mat ->_a21 = 0.0f;
mat ->_a22 = 1.0f;
mat ->_a23 = 0.0f;
mat ->_a24 = yoffset;
mat ->_a31 = 0.0f;
mat ->_a32 = 0.0f;
mat ->_a33 = 1.0f;
mat ->_a34 = zoffset;
mat ->_a41 = 0.0f;
mat ->_a42 = 0.0f;
mat ->_a43 = 0.0f;
mat ->_a44 = 1.0f;
return mat;
}
//函数MultMatrix实现矩阵乘法:
Matrix * CScene::MultMatrix(Matrix * outmat,Matrix * inmat1,Matrix * inmat2)
{
Matrix matout;
matout._a11 = (inmat1 ->_a11) * (inmat2 ->_a11) + (inmat1 ->_a12) * (inmat2 ->_a21) + (inmat1 ->_a13) * (inmat2 ->_a31) + (inmat1 ->_a14) * (inmat2 ->_a41) ;
matout._a12 = (inmat1 ->_a11) * (inmat2 ->_a12) + (inmat1 ->_a12) * (inmat2 ->_a22) + (inmat1 ->_a13) * (inmat2 ->_a32) + (inmat1 ->_a14) * (inmat2 ->_a42) ;
matout._a13 = (inmat1 ->_a11) * (inmat2 ->_a13) + (inmat1 ->_a12) * (inmat2 ->_a23) + (inmat1 ->_a13) * (inmat2 ->_a33) + (inmat1 ->_a14) * (inmat2 ->_a43) ;
matout._a14 = (inmat1 ->_a11) * (inmat2 ->_a14) + (inmat1 ->_a12) * (inmat2 ->_a24) + (inmat1 ->_a13) * (inmat2 ->_a34) + (inmat1 ->_a14) * (inmat2 ->_a44) ;
matout._a21 = (inmat1 ->_a21) * (inmat2 ->_a11) + (inmat1 ->_a22) * (inmat2 ->_a21) + (inmat1 ->_a23) * (inmat2 ->_a31) + (inmat1 ->_a24) * (inmat2 ->_a41) ;
matout._a22 = (inmat1 ->_a21) * (inmat2 ->_a12) + (inmat1 ->_a22) * (inmat2 ->_a22) + (inmat1 ->_a23) * (inmat2 ->_a32) + (inmat1 ->_a24) * (inmat2 ->_a42) ;
matout._a23 = (inmat1 ->_a21) * (inmat2 ->_a13) + (inmat1 ->_a22) * (inmat2 ->_a23) + (inmat1 ->_a23) * (inmat2 ->_a33) + (inmat1 ->_a24) * (inmat2 ->_a43) ;
matout._a24 = (inmat1 ->_a21) * (inmat2 ->_a14) + (inmat1 ->_a22) * (inmat2 ->_a24) + (inmat1 ->_a23) * (inmat2 ->_a34) + (inmat1 ->_a24) * (inmat2 ->_a44) ;
matout._a31 = (inmat1 ->_a31) * (inmat2 ->_a11) + (inmat1 ->_a32) * (inmat2 ->_a21) + (inmat1 ->_a33) * (inmat2 ->_a31) + (inmat1 ->_a34) * (inmat2 ->_a41) ;
matout._a32 = (inmat1 ->_a31) * (inmat2 ->_a12) + (inmat1 ->_a32) * (inmat2 ->_a22) + (inmat1 ->_a33) * (inmat2 ->_a32) + (inmat1 ->_a34) * (inmat2 ->_a42) ;
matout._a33 = (inmat1 ->_a31) * (inmat2 ->_a13) + (inmat1 ->_a32) * (inmat2 ->_a23) + (inmat1 ->_a33) * (inmat2 ->_a33) + (inmat1 ->_a34) * (inmat2 ->_a43) ;
matout._a34 = (inmat1 ->_a31) * (inmat2 ->_a14) + (inmat1 ->_a32) * (inmat2 ->_a24) + (inmat1 ->_a33) * (inmat2 ->_a34) + (inmat1 ->_a34) * (inmat2 ->_a44) ;
matout._a41 = (inmat1 ->_a41) * (inmat2 ->_a11) + (inmat1 ->_a42) * (inmat2 ->_a21) + (inmat1 ->_a43) * (inmat2 ->_a31) + (inmat1 ->_a44) * (inmat2 ->_a41) ;
matout._a42 = (inmat1 ->_a41) * (inmat2 ->_a12) + (inmat1 ->_a42) * (inmat2 ->_a22) + (inmat1 ->_a43) * (inmat2 ->_a32) + (inmat1 ->_a44) * (inmat2 ->_a42) ;
matout._a43 = (inmat1 ->_a41) * (inmat2 ->_a13) + (inmat1 ->_a42) * (inmat2 ->_a23) + (inmat1 ->_a43) * (inmat2 ->_a33) + (inmat1 ->_a44) * (inmat2 ->_a43) ;
matout._a44 = (inmat1 ->_a41) * (inmat2 ->_a14) + (inmat1 ->_a42) * (inmat2 ->_a24) + (inmat1 ->_a43) * (inmat2 ->_a34) + (inmat1 ->_a44) * (inmat2 ->_a44) ;
memcpy( (void *)outmat , (void *)&matout , sizeof(Matrix) );
return outmat;
}
//DrawPrimtive函数。它的作用是依照设置的三种矩阵的变换,在显示器上绘制vertexbuf中所有点表示的多边形图元。其实现如下:
void CScene::DrawPrimtive(HDC hdc,int nVertex,Vert3 * vertexbuf)
{
Matrix matcombined; //用于纪录矩阵运算结果
IdentifyMatrix(&matcombined);
//依次与三个矩阵相乘
MultMatrix( &matcombined , &matcombined , &m_ProjMatrix );
MultMatrix( &matcombined , &matcombined , &m_ViewMatrix );
MultMatrix( &matcombined , &matcombined , &m_WorldMatrix );
Vert3 destcur ;
Vert3 destlast;
Vert3 * sourcecur = vertexbuf;
SetPixel( hdc , 0 , 0 , RGB(0,0,0) );
MultVertWithMatrix( &destlast , sourcecur , &matcombined ); //将向量与结果矩阵相乘,得到//变换后的向量
sourcecur ++;
//循环绘制多边形图元所有的边
for (int j = 1 ; j < nVertex ; j++ )
{
MoveToEx( hdc , 100 + (int)destlast.x / destlast.w , 100 + (int)destlast.y / destlast.w , NULL );
MultVertWithMatrix( &destcur , sourcecur , &matcombined );
LineTo( hdc , 100 + (int)destcur.x / destcur.w , 100 + (int)destcur.y / destcur.w );
memcpy( (void * )&destlast , (void * )&destcur , sizeof(Vert3) );
sourcecur ++;
}//绘制到最后一个顶点;
//把最后一个顶点与第一个相连;
MoveToEx( hdc , 100 + (int)destlast.x / destlast.w , 100 + (int)destlast.y / destlast.w , NULL );
MultVertWithMatrix( &destcur , vertexbuf , &matcombined );
LineTo( hdc , 100 + (int)destcur.x / destcur.w , 100 + (int)destcur.y/destcur.w );
}
//DianMult:实现向量的点乘
float CScene::DianMult(Vert3 *vertin1, Vert3 *vertin2)
{
return ( (vertin1 ->x) * (vertin2 ->x) + (vertin1 ->y) * (vertin2 ->y) + (vertin1 ->z) * (vertin2 ->z) ) ;
}
//ChaMult:实现向量的叉乘
Vert3 * CScene::ChaMult(Vert3 *vertout, Vert3 *vertu, Vert3 *vertv)
{
Vert3 out;
out.x = (vertu ->y) * (vertv ->z) - (vertv ->y) * (vertu ->z) ;
out.y = (vertv ->x) * (vertu ->z) - (vertu ->x) * (vertv ->z) ;
out.z = (vertu ->x) * (vertv ->y) - (vertv ->x) * (vertu ->y) ;
memcpy( vertout , &out , sizeof(Vert3) );
return vertout;
}
//MultVertWithMatrix:实现向量与矩阵的乘法
void CScene::MultVertWithMatrix(Vert3 *vertout, Vert3 *vertin, Matrix *mat)
{
vertout ->x = (mat ->_a11) * (vertin ->x) + (mat ->_a12) * (vertin ->y) + (mat ->_a13) * (vertin ->z) + (mat ->_a14) * (vertin ->w) ;
vertout ->y = (mat ->_a21) * (vertin ->x) + (mat ->_a22) * (vertin ->y) + (mat ->_a23) * (vertin ->z) + (mat ->_a24) * (vertin ->w) ;
vertout ->z = (mat ->_a31) * (vertin ->x) + (mat ->_a32) * (vertin ->y) + (mat ->_a33) * (vertin ->z) + (mat ->_a34) * (vertin ->w) ;
vertout ->w = (mat ->_a41) * (vertin ->x) + (mat ->_a42) * (vertin ->y) + (mat ->_a43) * (vertin ->z) + (mat ->_a44) * (vertin ->w) ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -