初学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. C# 泛型约束 xxx<T> Where T:约束(一)

    泛型约束 代码举例 发现我们游戏的代码中,主程写了很多类似这样的代码: public static T CreateObject<T>(out int objectId) where T ...

  2. cron定时任务介绍

    什么是cron? Cron是linux系统中用来定期执行或指定程序任务的一种服务或软件.与它相关的有两个工具:crond 和 crontab.crond 就是 cron 在系统内的宿主程序,cront ...

  3. 【转】Zookeeper学习---zookeeper 选举机制介绍

    [原文]https://www.toutiao.com/i6593162565872779784/ zookeeper集群 配置多个实例共同构成一个集群对外提供服务以达到水平扩展的目的,每个服务器上的 ...

  4. Java学习---面试基础知识点总结

    Java中sleep和wait的区别 ① 这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类. sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线 ...

  5. 一个汇编的HelloWorld!

    花了一下午时间,感觉最坑的是,书写代码的个数和编译器的坑比较多,还各种版本的编译器! 会让人“眼花缭乱”! 主要代码 将文件保存为*.asm include io32.inc .data ;数据 sr ...

  6. [LOJ 6030]「雅礼集训 2017 Day1」矩阵

    [LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...

  7. SQLSERVER无排序生成序号

    实现方式:ROW_NUMBER() SELECT RowID=(ROW_NUMBER() OVER(ORDER BY(SELECT ))) FROM dbo.tbl_name 实现方式:IDENTIT ...

  8. C++构造析构函数生命期及对象生命期

  9. oneinstack远程管理数据库

    本篇文章主要内容是本地工具连接数据非网页(网站)连接 如果你想使用网页(网站)连接远程数据库,请看下面的官网教程 OneinStack如何配置MySQL远程连接? 为了安全考虑,OneinStack仅 ...

  10. thinkphp5整合 gatewaywork实现聊天

    1:将下载的gatewaywork下的\vendor  下的workman文件夹,整个复制到tp5下的vendor目录下 2:tp5\application\push   新键push文件夹,将下载的 ...