原理:马华东老师的课件
代码:参考《计算机图形学原理及算法教程(Visual C++版)》—和青芳
typedef double array2d[4][4];
typedef double array[9];
class Matrix3D
{
public:
/*
变换矩阵
T[0][0]~T[2][2] 对图形进行比例、旋转、对称等变换
T[3][i] i=0,1,2 对图形进行平移变换
T[i][3] i=0,1,2 对图形做透视投影变换
T[3][3] 产生整体比例变换
*/
array2d T;
//立体顶点齐次坐标
array XP, YP, ZP, CP;
//立体顶点经变换后的坐标值
array XT, YT, ZT;
public:
void clearT(); //将变换矩阵清零
void PriXYZ(); //立方体顶点齐次坐标
void XCalculate(); //立方体顶点齐次坐标乘以变换矩阵T
void Draw(); //绘制立方体
public:
void drawOri(); //绘制原始立方体
void translation(double dx, double dy, double dz); //平移
void scaling(double sx, double sy, double sz); //缩放
void mirror(int axis); //对称
void rotation(int axis, double theta); //绕某个轴逆时针旋转theta角度
void shear(int axis, double a, double b); //错切
};
//将变换矩阵清零
void Matrix3D::clearT()
{
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
T[i][j] = 0;
}
//立方体顶点齐次坐标
void Matrix3D::PriXYZ()
{
double pi = 3.14159;
double cx = 320;
double cy = 180;
int ed = 2000, eh = 100, od = 400, hl = 1;
int h=80, r=100, n = 4, flag = 0, nn = 0;
double thy = 0.2, thx = 0.2;
for(double th = 0; th <= 2*pi+0.1; th += 2*pi/n)
{
double x = r * cos(th);
double y = h;
double z = r * sin(th);
double zw = z;
double xw = x;
x = zw * cos(thy) - xw * sin(thy);
z = zw * sin(thy) + xw * cos(thy);
double yw = y;
zw = z;
y = yw * cos(thx) - zw * sin(thx);
z = yw * sin(thx) + zw * cos(thx);
XP[nn] = x;
YP[nn] = y;
ZP[nn] = z;
nn++;
}
flag = 0;
nn = 0;
for(th=0; th <= 2*pi+0.1; th += 2*pi/n)
{
double x = r * cos(th);
double y = -h;
double z = r * sin(th);
double zw = z;
double xw = x;
x = zw * cos(thy) - xw * sin(thy);
z = zw * sin(thy) + xw * cos(thy);
double yw = y;
zw = z;
y = yw * cos(thx) - zw * sin(thx);
z = yw * sin(thx) + zw * cos(thx);
XP[nn+4] = x;
YP[nn+4] = y;
ZP[nn+4] = z;
nn++;
}
for(int i=0; i<8; i++)
CP[i] = 1;
}
//齐次坐标乘以变换矩阵
void Matrix3D::XCalculate()
{
PriXYZ();
for (int i = 0; i < 8; i++ )
{
XT[i] = XP[i] * T[0][0] + YP[i] * T[1][0] + ZP[i] * T[2][0] + CP[i] * T[3][0];
YT[i] = XP[i] * T[0][1] + YP[i] * T[1][1] + ZP[i] * T[2][1] + CP[i] * T[3][1];
ZT[i] = XP[i] * T[0][2] + YP[i] * T[1][2] + ZP[i] * T[2][2] + CP[i] * T[3][2];
}
}
//绘制立方体
void Matrix3D::Draw()
{
CFrameWnd* pWnd =(CFrameWnd*)AfxGetApp()->m_pMainWnd;
CDC* pDC = pWnd->GetActiveView()->GetDC();
double cx = 320;
double cy = 180;
XCalculate();
array bx, by, bz;
for (int i = 0; i < 4; i++ )
{
bx[i+4] = bx[i] = XT[i+4];
by[i+4] = by[i] = YT[i+4];
bz[i+4] = bz[i] = ZT[i+4];
}
for ( i = 0; i < 4; i++ )
{
XT[i+4] = XT[i];
YT[i+4] = YT[i];
ZT[i+4] = ZT[i];
}
for(i=0; i < 4; i++)
{
pDC->MoveTo(cx + XT[i], cy + YT[i]);
pDC->LineTo(cx + XT[i], cy + YT[i]);
pDC->LineTo(cx + XT[i+1], cy + YT[i+1]);
pDC->LineTo(cx + bx[i+1], cy + by[i+1]);
pDC->LineTo(cx + bx[i], cy + by[i]);
}
pWnd->GetActiveView()->ReleaseDC(pDC);
}
//绘制原始立方体
void Matrix3D::drawOri()
{
clearT();
for(int i=0; i<4; i++)
T[i][i] = 1;
Draw();
}
//平移
void Matrix3D::translation(double dx, double dy, double dz)
{
clearT();
for(int i=0; i<4; i++)
T[i][i] = 1;
T[3][0] = dx; //x轴方向上平移
T[3][1] = dy; //y轴方向上平移
T[3][2] = dz; //z轴方向上平移
}
//缩放
void Matrix3D::scaling(double sx, double sy, double sz)
{
clearT();
T[0][0] = sx; //x轴方向上缩放
T[1][1] = sy; //y轴方向上缩放
T[2][2] = sz; //z轴方向上缩放
}
//对称
void Matrix3D::mirror(int axis)
{
clearT();
for(int i=0; i<3; i++)
T[i][i] = 1;
if(axis == 0) //关于平面YOZ对称
{
T[0][0] = -1;
}
else if(axis == 1) //关于平面XOZ对称
{
T[1][1] = -1;
}
else if(axis == 2) //关于平面XOY对称
{
T[2][2] = -1;
}
else if(axis == 3) //关于x轴对称
{
for(i=1; i<4; i++)
T[i][i] = -1;
}
else if(axis == 4) //关于y轴对称
{
T[0][0] = T[3][3] = -1;
}
else if(axis == 5) //关于z轴对称
{
T[0][0] = T[1][1] = -1;
}
else if(axis == 6) //关于原点对称
{
for(i=0; i<3; i++)
T[i][i] = -1;
}
}
//绕某个轴,逆时针旋转theta度
void Matrix3D::rotation(int axis, double theta)
{
clearT();
if(axis == 0) //绕X轴旋转
{
T[0][0] = 1;
T[1][1] = cos(theta * 3.14 / 180);
T[1][2] = sin(theta * 3.14 / 180);
T[2][1] = -sin(theta * 3.14 / 180);
T[2][2] = cos(theta * 3.14 / 180);
}
else if(axis == 1) //绕Y轴旋转
{
T[1][1] = 1;
T[0][0] = cos(theta * 3.14 / 180);
T[0][2] = -sin(theta * 3.14 / 180);
T[2][0] = sin(theta * 3.14 / 180);
T[2][2] = cos(theta * 3.14 / 180);
}
else //绕Z轴旋转
{
T[2][2] = 1;
T[0][0] = cos(theta * 3.14 / 180);
T[0][1] = sin(theta * 3.14 / 180);
T[1][0] = -sin(theta * 3.14 / 180);
T[1][1] = cos(theta * 3.14 / 180);
}
T[3][3] = 1;
}
//错切
void Matrix3D::shear(int axis, double a, double b)
{
clearT();
for(int i=0; i<4; i++)
T[i][i] = 1;
if(axis == 0) //沿x轴错切
{
T[1][0] = a; //含y错切
T[2][0] = b; //含z错切
}
else if(axis == 1) //沿y轴错切
{
T[0][1] = a; //含x错切
T[2][1] = b; //含z错切
}
else if(axis == 2) //研z轴错切
{
T[0][2] = a; //含x错切
T[1][2] = b; //含y错切
}
}
void CMy3DchangeView::OnDraw(CDC* pDC)
{
CMy3DchangeDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
Matrix3D m;
//原始立方体
//m.drawOri();
//平移
//m.translation(200, 0, 0);
//缩放
//m.scaling(2, 1, 2);
//对称
//m.mirror(0); //关于YOZ对称
//m.mirror(1); //关于XOZ对称
//m.mirror(2); //关于XOY对称
//旋转
//m.rotation(0, -60); //绕x轴顺时针旋转60度
//m.rotation(1, -60); //绕y轴顺时针旋转60度
//m.rotation(2, -60); //绕z轴顺时针旋转60度
//错切
m.shear(0, 2, 0); //沿x轴含y为2,含z为0的错切
//m.shear(1, 0, 1.1); //沿y轴含x为0,含z为1.1的错切
//m.shear(2, 1.2, 0); //沿z轴含x为1.2,含y为0的错切---没有变化?
m.Draw();
}
平移
缩放
关于YOZ对称
绕x轴顺时针旋转60度
沿x轴含y为2,含z为0的错切
版权声明:本文为u012319493原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。