DirectX9.0 入门手册(6)

DirectX9.0 入门手册(6)

       第一次写这种文章,再加上自己也是菜鸟,虽然有部分内容是参考一些书籍及自己翻译一些英文文章所写出来的,但我相信文章里面肯定也还有很多bug,如果你发现了请告诉我,或者你有什么想法也可以和我交流,我诚心和志同道合的人成为朋友,我的QQ61010818,我的邮箱fowenler@126.com

    无论计算机图形技术如何发展,只要它以二维的屏幕作为显示介质,那么它显示的图像即使多么的有立体感,也还是二维的。有时我会想,有没有以某个空间作为显示介质的的可能呢,不过即使有,也只能是显示某个范围内的图像,不可能有无限大的空间作为显示介质,如果有,那就是现实世界了。

    既然显示器的屏幕是二维的,那么我们就要对图像作些处理,让它可以欺骗我们的眼睛,产生一种立体的真实感。在D3D中,这种处理就是一系列的空间变换,从模型空间变到世界空间,再变到视图空间,最后投影到我们的显示器屏幕上。

·世界空间与世界矩阵

    什 么是模型空间呢?每个模型(3D物体)都有它自己的空间,空间的中心(原点)就是模型的中心。在模型空间里,只有模型上的不同点有位置的相对关系。那什么 是世界空间呢?世界就是物体(模型)所存在的地方。当我们把一个模型放进世界里面去,那么它就有了一个世界坐标,这个世界坐标是用来标记世界中不同的模型 所处的位置的。在世界空间里,世界的中心就是原点(0, 0, 0),也就是你显示器屏幕中间的那一点。我们可以在世界空间里摆放很多个模型,并且设置它们在世界空间中的坐标,这样模型与模型之间就有了相对的位置。

    世界矩阵有什么用呢?我们可以利用它来改变世界空间的坐标。这样,在世界空间里面的模型就可以移动、旋转和缩放了。

    我们可以使用上一章末尾所讲的那几个函数来产生世界矩阵。例如产生一个绕X轴旋转的转阵:D3DXMatrixRotationX(&matrix,1)。利用matrix这个矩阵,就可以使世界空间中的物体绕X轴转动1弧度。

    可以结合后面的例子来理解世界矩阵。

·视图空间与视图矩阵

    世界空间建立起来后,我们不一定能看到模型,因为我们还没有“眼睛”啊。在视图空间里,我们可以建立我们在三维空间中的眼睛:摄像机。我们就是通过这个虚拟的摄像机来观察世界空间中的模型的。所以视图空间也叫摄像机空间。

要建立起这个虚拟的摄像机,我们需要一个视图矩阵,产生视图矩阵的一个函数是:

D3DXMATRIX *D3DXMatrixLookAtLH(

    D3DXMATRIX* pOut,

    CONST D3DXVECTOR3* pEye,

    CONST D3DXVECTOR3* pAt,

    CONST D3DXVECTOR3* pUp

);

pOut:返回的视图矩阵指针

pEye:设置摄像机的位置

pAt:设置摄像机的观察点

pUp:设置方向“上”

这个函数的后缀LH 是表示左手系的意思,聪明的你一定能够猜出肯定有个叫D3DXMatrixLookAtRH的函数。至于左手系和右手系的区别,这里就不多说了,记住左手 系中的Z正方向是指向显示器里面的就行了。只能弄懂了视图矩阵的含义,建立视图矩阵完成可以不依赖函数,自己手动完成。视图矩阵其实就是定义了摄像机在世 界空间中的位置、观察点、方向“上”这些信息。

    可以结合后面的例子来理解视图矩阵。

·投影与投影矩阵

    定义投影矩阵很像是定义摄像机的镜头,下面看它的函数声明:

D3DXMATRIX *D3DXMatrixPerspectiveFovLH(

    D3DXMATRIX* pOut,

    FLOAT fovY,

    FLOAT Aspect,

    FLOAT zn,

    FLOAT zf

);

pOut:返回的投影矩阵指针

fovY:定义镜头垂直观察范围,以弧度为单位。对于这个参数,下面是我的理解:如果定义为D3DX_PI/4 (90度角),那么就是表示以摄像机的观察方向为平分线,上方45度角和下方45度角就是摄像机所能看到的垂直范围了。嗯,可以想象一下自己的眼睛,如果 可以把自己眼睛的fovY值设为D3DX_PI/2(180度角),那么我们就可以不用抬头就看得见头顶的东西了。如果设为D3DX_PI的话。。。我先 编译一下试试(building…)。哈哈,结果啥也看不见。很难想象如果自己能同时看到所有方向的物体,那么将是一个怎样的画面啊。

Aspect:设置纵横比。如果定义为1,那么所看到的物体大小不变。如果定义为其它值,你所看到的物体就会变形。不过一般情况下这个值设为显示器屏幕的长宽比。(终于明白为什么有些人会说电视上的自己看起来会比较胖了……)

zn:设置摄像机所能观察到的最远距离

zf:设置摄像机所能观察到的最近距离

·一小段代码

    请看以下代码片段:

D3DXMATRIXA16 matWorld;

    D3DXMatrixIdentity( &matWorld );

    D3DXMatrixRotationX( &matWorld, timeGetTime()/1000.0f );

    g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

 

    D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f );

    D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );

    D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );

    D3DXMATRIXA16 matView;

    D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );

    g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

 

    D3DXMATRIXA16 matProj;

    D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/2, 1.0f, 1.0f, 500.0f );

g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );

 

通过上面三个转换,就建立了一个我们可以通过显示器屏幕来观察的3D世界。上面三个转换分别是:

从模型空间到世界空间的世界转换:SetTransform( D3DTS_WORLD, &matWorld )。

从世界空间到视图空间的视图转换:SetTransform( D3DTS_VIEW, &matView )。

从视图空间到到屏幕的投影转换:SetTransform( D3DTS_PROJECTION, &matProj )。

现在来观察matWorld, matView,matProj这三个矩阵的特点。我们使用D3DXMatrixRotationX函数来产生了一个绕X轴旋转的转换矩阵,通过设置世界 转换,在世界空间里面的物体将绕X轴作旋转。然后我们定义了三个三维的向量,用来设置摄像机的位置,观察方向和定义方向“上”。使用 D3DXMatrixLookAtLH函数来把这三个向量放进视图矩阵里面去。然后通过设置视图转换,我们就建立了一个虚拟的摄像机。最后通过 D3DXMatrixPerspectiveFovLH函数,我们得到一个投影矩阵,用来设置虚拟摄像机的镜头。

我还是解释一下上面说的那个方向“上”是什么东西吧。这个“上”其实指的就是摄像机在刚建立的时候是如何摆放的,是向左边侧着摆,还是向右边侧着摆,还是倒过来摆,都是通过这个方向“上”来指定的。按照正常的理解,摄像机的“上”方向就是Y轴的正方向,但是我们可以指定方向“上”为Y轴的负方向,这样世界建立起来后就是颠倒的了。不过颠倒与否,也是相对来说的了,试问在没有引力的世界中,谁能说出哪是上哪是下呢?是不是看得一头雾水啊?只要自己亲手改变一下这些参数,就可以体会到了。

设置上面三个转换的先后顺序并不一定得按照世界到视图到投影这个顺序,不过习惯上按照这种顺序来写,感觉会好一点。

·使用矩阵相乘来创建世界矩阵

    在世界空间中的物体运动往往是很复杂的,比如物体自身旋转的同时,还绕世界的原点旋转。怎么实现这种运动呢?通过矩阵相乘来把两个矩阵“混”在一起。现在我们假设某一物体建立在世界的原点上,看以下代码:

    //定义三个矩阵

    D3DXMATRIX matWorld, matWorldY,matMoveLeft;

    //一个矩阵把物体移到(30,0,0)处,一个矩阵使物体绕原点(0,0,0)旋转

    D3DXMatrixTranslation(&matMoveRight,30,0,0);

    D3DXMatrixRotationY(&matWorldY, radian/1000.0f);

//第一次矩阵相乘。先旋转,再平移

    D3DXMatrixMultiply(&matWorld, &matWorldY, &matMoveRight);

    //第二次矩阵相乘。在第一次矩阵相乘的结果上,再以Y轴旋转

    D3DXMatrixMultiply(&matWorld, &matWorld, &matWorldY);

    //设置世界矩阵

    m_pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );

 

    矩 阵相乘的时候,矩阵的先后顺序很重要,如果顺序弄错了,物体就不会按我们预料的那样运动。从最后一次矩阵相乘看起,最后相乘的两个矩阵是matWorld 和matWorldY,其中matWorld又是由matWorldY和matMoveRight相乘得来的,那么这三个矩阵相乘的顺序就是 (matWorldY,matMoveRight,matWorldY)。这个顺序意味着什么呢?第一个matWorldY使物体绕Y轴旋转,这时候的物 体还处于原点,所以它绕Y轴旋转也就是绕自身的旋转。它转呀转呀,这时候matMoveRight来了,它把物体从(0,0,0)移到了(30,0, 0),这时候物体就不再是绕Y轴旋转了,它是在(30,0,0)这个位置继续绕自身旋转。然后matWorldY又来了,它使物体再次以Y轴旋转,不过此 时物体不在原点了,所以物体就以原点为中心作画圆的运动(它自身的旋转仍在继续),这个圆的半径是30。如果换一个顺序,把matMoveRight放在 第一的话,那么就是先移动再旋转再旋转(第二次旋转没用),这时候物体就只是画圆运动而已,它自身没有旋转。如果把matMoveRight放在最后,那 么就是先旋转再旋转(第二次旋转没用)再移动,这时候物体就没有作画圆运动了,它只是在(30,0,0)这个位置上作自身旋转。好了,理解这个需要一点点 想象力。你可以先写好几个矩阵相乘的顺序,自己想象一下相乘的结果会使物体作什么运动,然后再编译执行程序,看看物体的运动是不是和自己想像中的一样,这 样可以锻炼自己的空间思维能力。

    好了,又写完一章了。下一章可能要过一些日子才能写。因为自己还没找到工作,国庆过后就得出发去找工了,接下来的日子要作一些找工前的准备,所以就没什么时间继续写了。至于什么时候写第七篇,呵呵,应该不用很久,找到工作后立刻回来这里报道~~大家祝我好运吧^_^
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
本火锅店点餐系统采用Java语言和Vue技术,框架采用SSM,搭配Mysql数据库,运行在Idea里,采用小程序模式。本火锅店点餐系统提供管理员、用户两种角色的服务。总的功能包括菜品的查询、菜品的购买、餐桌预定和订单管理。本系统可以帮助管理员更新菜品信息和管理订单信息,帮助用户实现在线的点餐方式,并可以实现餐桌预定。本系统采用成熟技术开发可以完成点餐管理的相关工作。 本系统的功能围绕用户、管理员两种权限设计。根据不同权限的不同需求设计出更符合用户要求的功能。本系统中管理员主要负责审核管理用户,发布分享新的菜品,审核用户的订餐信息和餐桌预定信息等,用户可以对需要的菜品进行购买、预定餐桌等。用户可以管理个人资料、查询菜品、在线点餐和预定餐桌、管理订单等,用户的个人资料是由管理员添加用户资料时产生,用户的订单内容由用户在购买菜品时产生,用户预定信息由用户在预定餐桌操作时产生。 本系统的功能设计为管理员、用户两部分。管理员为菜品管理、菜品分类管理、用户管理、订单管理等,用户的功能为查询菜品,在线点餐、预定餐桌、管理个人信息等。 管理员负责用户信息的删除和管理,用户的姓名和手机号都可以由管理员在此功能里看到。管理员可以对菜品的信息进行管理、审核。本功能可以实现菜品的定时更新和审核管理。本功能包括查询餐桌,也可以发布新的餐桌信息。管理员可以查询已预定的餐桌,并进行审核。管理员可以管理公告和系统的轮播图,可以安排活动。管理员可以对个人的资料进行修改和管理,管理员还可以在本功能里修改密码。管理员可以查询用户的订单,并完成菜品的安排。 当用户登录进系统后可以修改自己的资料,可以使自己信息的保持正确性。还可以修改密码。用户可以浏览所有的菜品,可以查看详细的菜品内容,也可以进行菜品的点餐。在本功能里用户可以进行点餐。用户可以浏览没有预定出去的餐桌,选择合适的餐桌可以进行预定。用户可以管理购物车里的菜品。用户可以管理自己的订单,在订单管理界面里也可以进行查询操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值