原创教程:使用GDI+模拟directx 3D渲染中的坐标变换

gameatp 2011-01-05 10:48:53
加精
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
...全文
4856 74 打赏 收藏 转发到动态 举报
写回复
用AI写文章
74 条回复
切换为时间正序
请发表友善的回复…
发表回复
wenh7788 2013-04-23
  • 打赏
  • 举报
回复
我要挖坟了~~~ 谁能把楼主的例子发我下?楼主提供的下载链接已经不存在的。非常感谢!!!! 416532793@qq.com
iComputerLion 2011-04-11
  • 打赏
  • 举报
回复
硬件厂商对楼主的行为肯定是大加赞赏的
skywind 2011-03-14
  • 打赏
  • 举报
回复
呵呵,我写了个轻量级的图形库和楼主的类似,只不过是不依靠GDI+,而是一个类似
GDI+ Replacement的东西,纯软件实现,跨平台。
http://blog.csdn.net/skywind/archive/2011/03/11/6241079.aspx
包括图像变换,抗锯齿,几何作图等基本功能。支持SSE2/MMX优化等功能。
木子月月鱼 2011-03-09
  • 打赏
  • 举报
回复
麻烦楼主能不能把那几个矩阵变化的原理说具体一点?非常感谢!
laowang2 2011-02-09
  • 打赏
  • 举报
回复
beaugauge2012 2011-02-09
  • 打赏
  • 举报
回复
很好的入门教学。

----------------------
虚拟仪表控件 www.beaugauge.com
tiger_ok1 2011-02-06
  • 打赏
  • 举报
回复
计算机图形学。。。。。收藏 。。。。。。。学习 。。。。。。。
Dennis99999 2011-02-04
  • 打赏
  • 举报
回复
貴於經過 消化=>理解 =>應用=>創新=>再應用!!! BRAVO !!!
Dennis99999 2011-02-04
  • 打赏
  • 举报
回复
有摳到癢處! 好文章!值得閱讀!...頂!
comewisdom 2011-02-03
  • 打赏
  • 举报
回复
呵呵,俺正在学。。。也快出东东了。。。:)
yuankai19881108 2011-02-03
  • 打赏
  • 举报
回复

zhan7505201
(zhan7505201)
等 级:
#61楼 得分:0回复于:2011-02-02 08:10:13
好好学习。
zhan7505201 2011-02-02
  • 打赏
  • 举报
回复
好好学习。
z121221222 2011-02-01
  • 打赏
  • 举报
回复
学习长见识了
chenbin5587 2011-01-31
  • 打赏
  • 举报
回复
不知道干嘛!!!!
zlcp520 2011-01-31
  • 打赏
  • 举报
回复
内容存入剪贴板
gameice 2011-01-31
  • 打赏
  • 举报
回复
赞一个, 值得阅读.
zju3020912063 2011-01-28
  • 打赏
  • 举报
回复
有时间搞代码不如去看公式,怎么都以绕远路为荣,D3D的矩阵变换数学原理又不是很难,说起来根本就只有一个变换公式而已,分n个矩阵的意义和面向对象的分层是一样的.
dongch123 2011-01-28
  • 打赏
  • 举报
回复
我觉得有代码好,直观,更容易学习
beaugauge2012 2011-01-28
  • 打赏
  • 举报
回复
我觉得有代码好,直观,更容易学习。


------------------
虚拟仪表控件 www.beaugauge.com
gameatp 2011-01-28
  • 打赏
  • 举报
回复
[Quote=引用 51 楼 zju3020912063 的回复:]

有时间搞代码不如去看公式,怎么都以绕远路为荣,D3D的矩阵变换数学原理又不是很难,说起来根本就只有一个变换公式而已,分n个矩阵的意义和面向对象的分层是一样的.
[/Quote]
看一次自己再实现一次那不是更好
加载更多回复(29)

8,303

社区成员

发帖
与我相关
我的任务
社区描述
游戏开发相关内容讨论专区
社区管理员
  • 游戏开发
  • 呆呆敲代码的小Y
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧