初学Direct X(7)

——位图的旋转,缩放以及平移


本文旨在实现通过D3DXMatrixTransformation2D函数实现位图的旋转,缩放以及平移操作,但是具体的原理部分会在后面进一步的探讨。

1. 使用

下面是D3DXMatrixTransformation2D函数的定义:

D3DXMATRIX* D3DXMatrixTransformation2D(
_Inout_ D3DXMATRIX *pOut,
_In_ const D3DXVECTOR2 *pScalingCenter,
_In_ FLOAT pScalingRotation,
_In_ const D3DXVECTOR2 *pScaling,
_In_ const D3DXVECTOR2 *pRotationCenter,
_In_ FLOAT Rotation,
_In_ const D3DXVECTOR2 *pTranslation
);

各个参数的作用都简洁明了,根据参数可计算出最终的变换矩阵,并保存在pOut中,注意这是在2维中的函数,所以其中的变换参数都是二维的,我们需要提前定义这些参数,就像下面这样:

// 控制缩放比例
D3DXVECTOR2 scale(scaling, scaling);
// 控制平移
D3DXVECTOR2 trans((float)x, (float)y);
// 旋转中心
D3DXVECTOR2 scenter((float)width / 2, (float)height / 2);

最后,将其作为参数传入D3DXMatrixTransformation2D

D3DXMatrixTransformation2D(
&mat,
&scenter, /*缩放中心*/
0,
&scale /*缩放*/,
&scenter /*旋转中心*/,
rotation /*旋转度数,弧度*/,
&trans /*平移*/
);

最终可以得到一个变换矩阵,仅仅只是得到了。但是要怎么使得渲染器知道绘制时候作用这个变换矩阵呢?如下即可:

spriteobj->SetTransform(&mat);

2. 问题

在我使用的时候发现一个问题,在设置缩放中心或者旋转中心的时候,理应乘以一个放缩量,就像下面这样:

D3DXVECTOR2 center((float)(width * scaling) / 2, (float)(height*scaling) / 2);

而不是

D3DXVECTOR2 scenter((float)width / 2, (float)height / 2);

当然,若是在位图进行同比例放缩之时,使用scenter是可以的,因为只要是同比例缩放,中心点始终是不会变的。但是若放缩比例不一致比如:

D3DXVECTOR2 scale(scaling, scaling + 2);

这意味着,y方向上缩放长度是x方向的两倍,中心点也会偏移原来的位置。其实无论哪种情况,似乎使用center这样的定义方式来定义中心点始终是没有问题的。但是这里有一个问题是我百思不得其解,此问题相关描述如下:

目的:要实现位图(image)在窗口中心显示并围绕自身中心点旋转并放缩。

位图的宽高分别是widthheight,放缩值为scaling,x与y方向上平移变量分别为xy

// 控制缩放比例
D3DXVECTOR2 scale(scaling, scaling);
// 控制平移
D3DXVECTOR2 trans((float)x, (float)y);
// 旋转,缩放中心,会随放缩比例变化
D3DXVECTOR2 center((float)(width * scaling) / 2, (float)(height*scaling) / 2); D3DXMATRIX mat; D3DXMatrixTransformation2D(
&mat,
&center, /*缩放中心*/
0,
&scale /*缩放*/,
&center /*旋转中心*/,
rotation /*旋转度数*/,
&trans /*平移*/);
spriteobj->SetTransform(&mat); //获取srcRect
// ... spriteobj->Draw(image, &srcRect, NULL, NULL, color);

调用以上函数以及个参数如下,它们是在Begin()End()之间的代码:

// rotate
r = timeGetTime() / 600.0f;
// scaling
s += scale;
if (s < 0.1f || s > 1.25f)
scale *= -1;
width = height = 512;
frame = 0;
columns = 1;
color = D3DCOLOR_XRGB(255,255,255); Sprite_Transform_Draw(
sunflower, // => image
SCREENW / 2 - width / 2, // => x
SCREENH / 2 - height / 2, // => y (xy用于平移位图至屏幕窗口中心)
width, // => width
height, // => height
frame, // => ignore
columns, // => ignore
r, // => rotation
s, // => scale
color // => ignore
);

看起来似乎可以使得sunflowercenter为中心旋转并缩放,但是事实并不是这样的,我也不知道原因是什么,这使得我十分的困惑。因为实际的结果并不是以center为中心旋转并缩放的。我尝试着将缩放比例注释掉,也就是说将s设置为了1,此时位图停止了放缩,旋转的中心是center正常。 但是一旦将s设置为了递增或递减的变量(就像代码写的那样),那么此时的旋转和放缩中心就不是真正的位图中心了。

这里remark一下,我还会继续学下去,看看会不会找到这个问题的答案。

初学Direct X(7) ——位图的旋转,缩放以及平移的更多相关文章

  1. 初学Direct X(5)

    初学Direct X(5) 前面学习了使用表面绘制屏幕,但这种方法与另一种比较起来,有着绘图速度颇慢以及缺乏对任何透明类型的支持,这就是前面的篮框以及炸弹会有黑色背景的原因,这种方法就是纹理.他可以绘 ...

  2. 初学Direct X(8) ——碰撞检测

    初学Direct X(8) --碰撞检测 真正让一个游戏鹤立鸡群的是程序对碰撞的响应有多好,这里介绍两种检测的方法: 1) 基于边框的碰撞检测 2) 基于距离的碰撞检测 1. 基于边框的碰撞检测 1. ...

  3. 初学Direct X(6)

    初学Direct X(6) 这一文本应和上一篇放在一起的,但是上一章写着写着发现对Draw绘制透明位图的方式有感觉了,决定就单写一篇,留作笔记了. 那这一篇是记录如何使用位图表来绘制动画帧,想象一下, ...

  4. 初学Direct X(4)

    初学Direct X(4) 本文学着做出一个如下的小游戏 游戏方式是使用键盘控制红色的Bucket收集蓝色的炸弹 1.酝酿一下 现在我已经掌握: 将位图文件加载到内存 绘制位图到buckbuffer ...

  5. 初学Direct X (2)

    初学Direct X (2) 这一次要学习如何现实位图,尽管看过对双缓冲机制还有很多疑问,但是这并不阻碍我对他的入门了解 Direct3D提供了一个双重/后台缓冲区,在调用CreateDevice之时 ...

  6. Android 学习笔记之Bitmap位图的旋转

    位图的旋转也可以借助Matrix或者Canvas来实现. 通过postRotate方法设置旋转角度,然后用createBitmap方法创建一个经过旋转处理的Bitmap对象,最后用drawBitmap ...

  7. Android学习笔记之Bitmap位图的旋转

    位图的旋转也可以借助Matrix或者Canvas来实现. 通过postRotate方法设置旋转角度,然后用createBitmap方法创建一个经过旋转处理的Bitmap对象,最后用drawBitmap ...

  8. osg矩阵变换节点-----平移旋转缩放

    osg矩阵变换节点-----平移旋转缩放 转自:http://www.cnblogs.com/ylwn817/articles/1973396.html 平移旋转缩放这个三个是osg矩阵操作中,最常见 ...

  9. osg中使用MatrixTransform来实现模型的平移/旋转/缩放

    osg中使用MatrixTransform来实现模型的平移/旋转/缩放 转自:http://www.cnblogs.com/kekec/archive/2011/08/15/2139893.html# ...

随机推荐

  1. 大话存储 3 - 七种磁盘RAID技术

    RAID技术 Redundant Array of Independent Disks 由独立的磁盘组成的具有冗余特性的阵列. 有两个特性: 阵列:需要很多磁盘来组成 冗余:允许某块磁盘损坏之后,数据 ...

  2. NFS网络共享介绍与使用

    什么是NFS(网络文件系统)? NFS(Network File System)即网络文件系统,是FreeBSD支持的文件系统中的一种,它允许网络中的计算机之间通过TCP/IP网络共享资源.它的主要功 ...

  3. python基础学习13----生成器&迭代器

    生成器是属于迭代器,但迭代器不只是生成器 首先是一个简单的生成器 def gener(): print(1) yield 1 print(2) yield 2 print(3) yield 3 g=g ...

  4. 常用的 接口访问方法 post 和get

    public string GetFunction(string serviceAddress) { HttpWebRequest request = (HttpWebRequest)WebReque ...

  5. django -- Celery实现异步任务

    1. 环境 python==2.7 djang==1.11.2 # 1.8, 1.9, 1.10应该都没问题 celery-with-redis==3.0 # 需要用到redis作为中间人服务(Bro ...

  6. 【转】Mysql学习---MySQL悲观锁中的排它锁

    [原文]https://www.toutiao.com/i6595305814087434760/ 悲观锁中的排它锁. 排它锁关键字:for update 特点:会锁住行或者表,防止其他事务进行修改操 ...

  7. ESXI6.0新添加硬盘未能格式化成功

    最近练手,手头现有的硬盘是从其他机器上拆下来的,插入ESXI主机上,然后在系统配置硬盘的时候,不能格式化 报错 提示如下错误:"在ESXi"xxx.xxx.xxx.xxx" ...

  8. BZOJ4919:[Lydsy1706月赛]大根堆(set启发式合并)

    Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切地说,你需要选择尽可能多的节点,满足大根堆的性质: ...

  9. Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换(转载)

    第二篇:JAVA字符编码系列二:Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换 1.函数介绍在Java中,字符串用统一的Unicode编码,每个字符占用两个字节,与编码有关的两 ...

  10. 服务器 三 MQTT服务器手机开发

    目的: 实现手机4G网络控制单片机,需要搭建服务器,手机或者各种控制端远程控制. 本教程 1  MQTT服务器硬件模块 2 MQTT服务器电脑搭建 2.1自己搭建 2.2租阿里云服务器 2 MQTT服 ...