SDL_RenderCopy

testsprite2をベースにしたサンプルを作りながら、SDL_Textureの使い方を勉強する。SDL_RenderCopy関数に渡すdstrectのwとhが有効になり、拡大・縮小はこれを使って行えるようだ(画像の幅が64pxの場合、w = 128とすると幅が倍になる)。しかしながら回転はサポートされていない。
SDLのMLでも話し合われているようだが、英語わかんない(^^;)のもあって話の流れを追っている最中。いくつか提案や議論があったりするようだけど、どうなんだろう。今のところはソースにも変化なし。

手っ取り早く回転を実現するには、SDL_RenderCopy関数の引数を増やすのが手軽かな。今のところDirect3Dで行えればいいので、それ以外のレンダラーではスルーの方向で実装するとか。SDL_RenderCopy関数からD3D_RenderCopy関数が呼ばれ、その関数で頂点座標計算から描画までが完結しているから、その座標計算直後に回転処理を加える、と(そんなに簡単な話なのかな?)。
そんな感じで手を加えたところ、なんとか回転できるようになった。いくつか問題もあるが、今回は真剣に解決することはしない。以下は今後のためのメモ。
回転の計算をするのに三角関数を使おうとしても、sin関数やcos関数を呼べない場合がある。現在Visual C++ 2005 Express Editionを使っているので、SDLの配布アーカイブに付属するプロジェクトファイルをベースにしているが、そのプロジェクトファイルを使用するとリンカオプションに/NODEFAULTLIBが付いているため、三角関数をそのまま使えなかった。これは組み込み関数を使用することで対処した。

Index: SDL-svn/src/video/win32/SDL_d3drender.c
===================================================================
--- SDL-svn/src/video/win32/SDL_d3drender.c	(リビジョン 2714)
+++ SDL-svn/src/video/win32/SDL_d3drender.c	(作業コピー)
@@ -57,7 +57,7 @@
 static int D3D_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
                           Uint8 a, const SDL_Rect * rect);
 static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
-                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
+                          const SDL_Rect * srcrect, const SDL_Rect * dstrect, const float angle);
 static void D3D_RenderPresent(SDL_Renderer * renderer);
 static void D3D_DestroyTexture(SDL_Renderer * renderer,
                                SDL_Texture * texture);
@@ -705,15 +705,31 @@
     }
     return 0;
 }
+
+#include <math.h>
+#define M_PI 3.14159265358979323846f
+#pragma intrinsic(sin)
+#pragma intrinsic(cos)
 
+static void
+rotate_vertex(float *x, float *y, const float px, const float py, const float angle)
+{
+	float rad = angle * M_PI / 180.0f;
+	float dx = *x - px;
+	float dy = *y - py;
+	*x = px + dx * cosf(rad) - dy * sinf(rad);
+	*y = py + dx * sinf(rad) + dy * cosf(rad);
+}
+
 static int
 D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
-               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
+               const SDL_Rect * srcrect, const SDL_Rect * dstrect, const float angle)
 {
     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
     D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
     float minx, miny, maxx, maxy;
     float minu, maxu, minv, maxv;
+	float centerx, centery;
     DWORD color;
     Vertex vertices[4];
     HRESULT result;
@@ -727,6 +743,8 @@
     miny = (float) dstrect->y - 0.5f;
     maxx = (float) dstrect->x + dstrect->w - 0.5f;
     maxy = (float) dstrect->y + dstrect->h - 0.5f;
+	centerx = (maxx + minx) / 2;
+	centery = (maxy + miny) / 2;
 
     minu = (float) srcrect->x / texture->w;
     maxu = (float) (srcrect->x + srcrect->w) / texture->w;
@@ -767,6 +785,11 @@
     vertices[3].u = minu;
     vertices[3].v = maxv;
 
+	rotate_vertex(&vertices[0].x, &vertices[0].y, centerx, centery, angle);
+	rotate_vertex(&vertices[1].x, &vertices[1].y, centerx, centery, angle);
+	rotate_vertex(&vertices[2].x, &vertices[2].y, centerx, centery, angle);
+	rotate_vertex(&vertices[3].x, &vertices[3].y, centerx, centery, angle);
+
     switch (texture->blendMode) {
     case SDL_TEXTUREBLENDMODE_NONE:
         IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,

ひとまず拡大縮小回転については実現できた。実はまだSGEやSDL_ttfとの併用する問題もあるんで、相変わらずすぐに導入できないのが残念なところ。まあ強烈に困っているわけでもないので徐々に考えていこう。