//Copyright(C) 2009 にょろ. All rights reserved. #region usingディレクトリ using System; using System.Collections.Generic; using System.Linq; using System.Text; using SlimDX; using SlimDX.Direct3D9; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; #endregion namespace TextureManage { public class DrawTexture { #region 変数,プロパティ #region private 変数,プロパティ List Vertex; TransformedColoredTexturedVertex[] VertexArray { get { return Vertex.ToArray(); } } #endregion #region protected 変数,プロパティ #endregion #region public 変数,プロパティ public Texture Texture { get; set; } public Device Device { get; set; } public int TextureWidth{get; private set;} public int TextureHeight{get; private set;} /// /// 横のマス目の数 /// public int Cols { get; set; } /// /// 縦のマス目の数 /// public int Rows { get; set; } /// /// 一マス目の横幅 /// public int Width { get { return TextureWidth / Cols; } set { Cols = TextureWidth / value; } } /// /// 一マス目の縦幅 /// public int Height { get { return TextureHeight / Rows; } set { Rows = TextureHeight / value; } } public float WidthU { get { return 1.0f / Cols; } } public float HeightV { get { return 1.0f / Rows; } } #endregion #endregion #region コンストラクタ public DrawTexture(Device Device, Bitmap Bitmap) { this.Device = Device; this.Texture = GetTexture(Bitmap); Vertex = new List(); TextureWidth = Bitmap.Width; TextureHeight = Bitmap.Height; Cols = Rows = 1; } #endregion #region メンバ #region private メンバ /// /// 原点をCenterにとるPointをorgラジアン回転させた点 /// /// 原点 /// (0,0)からの点 /// 回転 /// Point GetRollPoint(Point Center, Point Point, double org) { //PointをDevice座標からCenter座標へ平行移動 Point.X -= Center.X; Point.Y -= Center.Y; Point p = new Point(Point.X, Point.Y); double cos=Math.Cos(org); double sin=Math.Sin(org); //p(=Point)を回転させたあとにCenterを足して元に戻す。 Point.X = (int)(Center.X + p.X * cos - p.Y * sin); Point.Y = (int)(Center.Y + p.X * sin + p.Y * cos); return Point; } /// /// 原点をCenterにとるPointをorgラジアン回転させた点 /// /// 原点X /// 原点Y /// (0,0)からの点X /// (0,0)からの点Y /// 回転角 /// Point GetRollPoint (int cx,int cy,int px,int py,double org) { return GetRollPoint(new Point(cx,cy),new Point(px,py),org); } #endregion #region public メンバ #region 画像取得 /// /// BitmapからTextureに変換 /// /// 元Bitmap /// テクスチャ public Texture GetTexture(Bitmap src) { //不安なので2の累乗に int h = 1; int w = 1; while (w < src.Width) { w *= 2; } while (h < src.Height) { h *= 2; } //サイズを考慮したBitmapに移す Bitmap bmp = new Bitmap(w, h); Graphics g = Graphics.FromImage(bmp); g.Clear(Color.Transparent); g.DrawImage(src, (w - src.Width) / 2, (h - src.Height) / 2); g.Dispose(); //空のテクスチャ用意(Managedリソースにしてますタブン) Texture tex = new Texture(Device, w, h, 0, Usage.None, Format.A8R8G8B8, Pool.Managed); SurfaceDescription desc = tex.GetLevelDescription(0); DataStream buf = (tex.LockRectangle(0, new Rectangle(0, 0, desc.Height, desc.Width), LockFlags.None)).Data; //Bitmap→byteの配列に移す BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); IntPtr ptr = bmpdata.Scan0; byte[] temp = new byte[bmpdata.Width * bmpdata.Height * 4]; Marshal.Copy(ptr, temp, 0, bmpdata.Width * bmpdata.Height * 4); //Bitmapアンロック bmp.UnlockBits(bmpdata); //取得したBitmapのデータをテクスチャに移す for (int y = 0; y <= bmpdata.Height - 1; y++) { for (int x = 0; x <= bmpdata.Width - 1; x++) { //タテヨコ逆にコピー buf.Write((UInt32)temp[y * bmpdata.Width * 4 + x * 4] + (UInt32)temp[y * bmpdata.Width * 4 + x * 4 + 1] * 256 + (UInt32)temp[y * bmpdata.Width * 4 + x * 4 + 2] * 256 * 256 + (UInt32)temp[y * bmpdata.Width * 4 + x * 4 + 3] * 256 * 256 * 256); } } tex.UnlockRectangle(0); return tex; } #endregion #region 登録関係 /// /// x,yを始点としてwidth,heightの大きさで四角形を登録 /// /// 起点のx座標 /// 起点のy座標 /// 実際の横標 /// 実際の縦標 /// 起点のu座標 /// 起点のv座標 /// UV座標の横幅 /// UV座標の縦幅 public void AddRectangle(int x, int y, int width, int height, float u, float v, float uw, float vh) { Vertex.Add(new TransformedColoredTexturedVertex() { Position = new Vector4() { X = x, Y = y, W = 1 }, TextureCoordinates = new Vector2 { X = u, Y = v }, Color = -1 }); Vertex.Add(new TransformedColoredTexturedVertex() { Position = new Vector4() { X = x + width, Y = y, W = 1 }, TextureCoordinates = new Vector2 { X = u + uw , Y = v }, Color = -1 }); Vertex.Add(new TransformedColoredTexturedVertex() { Position = new Vector4() { X = x, Y = y + height, W = 1 }, TextureCoordinates = new Vector2 { X = u, Y = v + vh }, Color = -1 }); Vertex.Add(new TransformedColoredTexturedVertex() { Position = new Vector4() { X = x + width, Y = y, W = 1 }, TextureCoordinates = new Vector2 { X = u + uw , Y = v }, Color = -1 }); Vertex.Add(new TransformedColoredTexturedVertex() { Position = new Vector4() { X = x + width, Y = y + height, W = 1 }, TextureCoordinates = new Vector2 { X = u + uw , Y = v + vh }, Color = -1 }); Vertex.Add(new TransformedColoredTexturedVertex() { Position = new Vector4() { X = x, Y = y + height, W = 1 }, TextureCoordinates = new Vector2 { X = u, Y = v + vh }, Color = -1 }); } /// /// x,yを始点としてwidth,heightの大きさで四角形を登録(等倍) /// /// 起点のx座標 /// 起点のy座標 /// 実際の横標 /// 実際の縦標 /// 起点のu座標 /// 起点のv座標 public void AddRectangle(int x, int y, int width, int height, float u, float v) { AddRectangle(x, y, width, height, u, v, width / TextureWidth, height / TextureHeight); } /// /// x,yを中心とした四角形の登録 /// /// 起点のx座標 /// 起点のy座標 /// 実際の横標 /// 実際の縦標 /// 起点のu座標 /// 起点のv座標 /// UV座標の横幅 /// UV座標の縦幅 public void AddRectangleCenter(int x, int y, int width, int height, float u, float v, float uw, float vh) { AddRectangle(x - width / 2, y - height / 2, width, height, u - uw / 2, v - vh / 2, uw, vh); } /// /// x,yを中心とした四角形の登録 /// /// 起点のx座標 /// 起点のy座標 /// 実際の横標 /// 実際の縦標 /// 起点のu座標 /// 起点のv座標 /// UV座標の横幅 /// UV座標の縦幅 public void AddRectangleCenter(int x, int y, int width, int height, float u, float v) { float uw = width / TextureWidth; float vh = height / TextureHeight; AddRectangleCenter(x, y, width, height, u, v, uw, vh); } /// /// 一升分の四角形をx,yに登録 /// /// 起点のx座標 /// 起点のy座標 /// 升座標のx座標 /// 升座標のy座標 public void AddRectangle(int x, int y, int x升, int y升) { AddRectangle(x, y, Width, Height, x升, y升, 1, 1); } /// /// width升*height升分の四角形をx,yに登録 /// /// 起点のx座標 /// 起点のy座標 /// 升座標のx座標 /// 升座標のy座標 public void AddRectangle(int x, int y, int width, int height, int x升, int y升, int width升, int height升) { AddRectangle(x, y, width, height, x升 * WidthU, y升 * HeightV, width升 * WidthU, height升 * HeightV); } /// /// width升*height升分の四角形をx,yに登録 /// /// 起点のx座標 /// 起点のy座標 /// 升座標のx座標 /// 升座標のy座標 public void AddRectangle(int x, int y, int x升, int y升, int width升, int height升) { AddRectangle(x, y, Width * width升, Height * height升, x升 * Cols, y升 * Rows, width升 * WidthU, height升 * HeightV); } /// /// x,yを中心としてx升,y升からwidth升,height升分の四角形 /// /// 起点のx座標 /// 起点のy座標 /// 実際の横標 /// 実際の縦標 /// 升座標のx座標 /// 升座標のy座標 /// /// 升座標の縦幅 public void AddRectangleCenter(int x, int y, int width, int height, int x升, int y升, int width升, int height升) { AddRectangle(x - width / 2, y - height / 2, width, height, x升, y升, width升, height升); } /// /// x,yを中心としてx升,y升からwidth升,height升分の四角形 /// /// 起点のx座標 /// 起点のy座標 /// 升座標のx座標 /// 升座標のy座標 /// /// 升座標の縦幅 public void AddRectangleCenter(int x, int y, int x升, int y升, int width升, int height升) { AddRectangleCenter(x, y, width升 * Width, height升 * height升, x升, y升, width升, height升); } /// /// x,yを中心としてx升,y升から1分の四角形 /// /// 起点のx座標 /// 起点のy座標 /// 升座標のx座標 /// 升座標のy座標 public void AddRectangleCenter(int x, int y, int x升, int y升) { AddRectangleCenter(x, y, Width, Height, x升, y升, 1, 1); } /// /// x,yを起点として(0,0)の升を登録 /// /// /// public void AddRectangle(int x, int y) { AddRectangle(x, y, 0, 0); } /// /// x,yを始点としてwidth,heightの大きさで(中心で)回転orgで四角形を登録 /// /// 起点のx座標 /// 起点のy座標 /// 実際の横標 /// 実際の縦標 /// 起点のu座標 /// 起点のv座標 /// UV座標の横幅 /// UV座標の縦幅 /// 回転角 public void AddRollRectangle(int x, int y, int width, int height, float u, float v, float uw, float vh, double org) { int cx = x + width / 2; int cy = y + height / 2; Point p1 = GetRollPoint(cx, cy, x, y, org); Point p2 = GetRollPoint(cx, cy, x + width, y, org); Point p3 = GetRollPoint(cx, cy, x, y + height, org); Point p4 = GetRollPoint(cx, cy, x + width, y + height, org); Vertex.Add(new TransformedColoredTexturedVertex() { Position = new Vector4() { X = p1.X, Y = p1.Y, W = 1 }, TextureCoordinates = new Vector2 { X = u, Y = v }, Color = -1 }); Vertex.Add(new TransformedColoredTexturedVertex() { Position = new Vector4() { X = p2.X, Y = p2.Y, W = 1 }, TextureCoordinates = new Vector2 { X = u + uw , Y = v }, Color = -1 }); Vertex.Add(new TransformedColoredTexturedVertex() { Position = new Vector4() { X = p3.X, Y = p3.Y, W = 1 }, TextureCoordinates = new Vector2 { X = u, Y = v + vh }, Color = -1 }); Vertex.Add(new TransformedColoredTexturedVertex() { Position = new Vector4() { X = p2.X, Y = p2.Y, W = 1 }, TextureCoordinates = new Vector2 { X = u + uw , Y = v }, Color = -1 }); Vertex.Add(new TransformedColoredTexturedVertex() { Position = new Vector4() { X = p4.X, Y = p4.Y, W = 1 }, TextureCoordinates = new Vector2 { X = u + uw , Y = v + vh }, Color = -1 }); Vertex.Add(new TransformedColoredTexturedVertex() { Position = new Vector4() { X = p3.X, Y = p3.Y, W = 1 }, TextureCoordinates = new Vector2 { X = u, Y = v + vh }, Color = -1 }); } /// /// x,yを始点としてwidth,heightの大きさで(中心で)回転orgで四角形を登録 /// /// 起点のx座標 /// 起点のy座標 /// 実際の横標 /// 実際の縦標 /// 起点のx座標 /// 起点のy座標 /// 升座標のx座標 /// 升座標のy座標 /// /// 升座標の縦幅 /// /// 回転角 public void AddRollRectangle(int x, int y, int x升, int y升, int width升, int height升, double org) { AddRollRectangle(x, y, Width * width升, Height * height升, x升 * WidthU, x升 * HeightV, WidthU * width升, HeightV * height升, org); } /// /// x,yを始点としてwidth,heightの大きさで(中心で)回転orgで四角形を登録 /// /// 起点のx座標 /// 起点のy座標 /// 実際の横標 /// 実際の縦標 /// 升座標のx座標 /// 升座標のy座標 /// /// 升座標の縦幅 /// 回転角 public void AddRollRectangleCenter(int x, int y, int x升, int y升, int width升, int height升, double org) { AddRollRectangle(x, y, Width * x升, Height * y升, width升, height升, org); } /// /// x,yを始点としてwidth,heightの大きさで(中心で)回転orgで四角形を登録 /// /// 起点のx座標 /// 起点のy座標 /// 升座標のx座標 /// 升座標のy座標 /// 回転角 public void AddRollRectangleCenter(int x, int y, int x升, int y升,double org) { AddRollRectangleCenter(x, y, x升, y升, 1, 1, org); } #endregion #region 描画関係 public void Draw(bool reset) { Device.SetTexture(0, Texture); var List= VertexArray; Device.DrawUserPrimitives(PrimitiveType.TriangleList,0, List.Length / 3, List); if (reset) { Vertex.Clear(); } } public void Draw() { Draw(true); } #endregion #endregion #region protected メンバ #endregion #endregion #region オーバーライド メンバ #endregion } }