初学Direct X(7) ——位图的旋转,缩放以及平移

初学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一下,我还会继续学下去,看看会不会找到这个问题的答案。

原文地址:https://www.cnblogs.com/leihui/p/8947918.html