使用GDI+模拟directx 3D渲染中的坐标变换

Directx 渲染管线一个重要功能就是将3d空间里 建立好的虚拟系统投影映射到屏幕的2D空间里显示,其实主要有4个步骤,也就是坐标系的变换,如下:
物体坐标系 -> 世界坐标系 –> 摄像机坐标系 -> 屏幕坐标系统

每个变换都有相对应的矩阵:
1、 物体坐标系 -> 世界坐标系 (主要用到旋转、平移、缩放矩阵)
2、 世界坐标系 –> 摄像机坐标系(视口矩阵)
3、 摄像机坐标系->屏幕坐标系(投影矩阵)

首先我们的关键任务就是定义一个矩阵类和向量类以及矩阵向量之间的运算,然后写出获得这些矩阵的函数来:
向量类
class Vector4
{
public:
Vector4();
Vector4(float x,float y,float z,float w);
Vector4(const Vector4& v);
// 取负,+=,-=,*=,+,-,*,=操作
Vector4 operator-() const;
void operator+=(const Vector4& rhs);
void operator-=(const Vector4& rhs);
void operator*=(float s);
Vector4 operator+(const Vector4& rhs) const;
Vector4 operator-(const Vector4& rhs) const;
Vector4 operator*(float s) const;
void operator=(const Vector4& rhs);
// 单位化、叉积、点积
float Length();
static Vector4 Normalize(Vector4& v);
static Vector4 Cross3(const Vector4& v0, const Vector4& v1);
static float Dot3(const Vector4& v0, const Vector4& v1);
static float Dot4(const Vector4& v0, const Vector4& v1);
// 坐标变换
static Vector4 Transform(const Vector4&v,const Matrix44&mat);

float x;
float y;
float z;
float w;

};
矩阵类
class Matrix44
{
public:
Matrix44();
Matrix44(const Vector4& row0, const Vector4& row1, const Vector4& row2, const Vector4& row3);
Matrix44(const Matrix44& rhs);

static Matrix44 Identity();

// 旋转、缩放、平移矩阵、乘
static Matrix44 RotationX(float angle);
static Matrix44 RotationY(float angle);
static Matrix44 RotationZ(float angle);
static Matrix44 Scaling(float sx,float sy,float sz);
static Matrix44 Translation(float x,float y,float z);
static Matrix44 Multiply(const Matrix44& m0, const Matrix44& m1);
// 视口、投影矩阵
static Matrix44 ViewMatrix(Vector4& eye,Vector4& at,Vector4& up);
static Matrix44 ProjMatrix(float fovy,float aspect,float zn,float zf);

Vector4 r0;
Vector4 r1;
Vector4 r2;
Vector4 r3;
};
向量、矩阵的运算以及视口投影矩阵的获得我都以类静态函数给出,直接调用就用 ‘类名:’来引用.例如:Matrix44::ViewMatrix(…);就是获得视口矩阵的调用,参数自己加

最后投影过后还需要将坐标映射到屏幕上还需要做以下工作:

math::Matrix44 mat;
mat.r0.x = g_clientWndW;
mat.r2.x = g_clientWndW/2;
mat.r2.y = g_clientWndH/2;
mat.r1.y = -g_clientWndW;
Vector4 vTemp[8];

for(int i = 0;i < 8;i++)
{
vTemp[i] = math::Vector4::Transform(g_cubeVertex[i] , worldMatrix);
vTemp[i] = math::Vector4::Transform(vTemp[i] , g_viewMatrix);
vTemp[i] = math::Vector4::Transform(vTemp[i] , g_projMatrix);

vTemp[i].x /= vTemp[i].w;
vTemp[i].y /= vTemp[i].w;
vTemp[i].z /= vTemp[i].w;
vTemp[i].w = 1;


vTemp[i] = math::Vector4::Transform(vTemp[i] , mat);
}

//
vTemp[i].x /= vTemp[i].w;
vTemp[i].y /= vTemp[i].w;
vTemp[i].z /= vTemp[i].w;
vTemp[i].w = 1;
除以w是为了让坐标锁定在-1到1之间,然后再乘以个mat矩阵就是具体屏幕坐标,mat矩阵其实就是将坐标x放大屏幕宽度大小,y放大屏幕高度大小,然后将y轴取反,x,y分别平移到屏幕左上角。
其实就是下面坐标系变换,如图:

最终效果图(我简单绘制了一个立方体,并且把不可见变用虚线绘制,就用变换后的坐标点连接的线用GDI+的DrawLine实现):

代码下载地址:
http://download.csdn.net/source/2962028



http://bbs.csdn.net/topics/350262983
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值