ページ「MonoGame/クラスライブラリ/RenderTargetUsage列挙体」と「AABB」の間の差分

提供: MonoBook
< MonoGame‎ | クラスライブラリ(ページ間の差分)
ナビゲーションに移動 検索に移動
imported>Administrator
 
imported>Administrator
 
1行目: 1行目:
RenderTargetUsage列挙体は、グラフィックデバイス([[MonoGame/クラスライブラリ/GraphicsDeviceクラス|GraphicsDeviceクラス]])に新たなレンダリングターゲット([[MonoGame/クラスライブラリ/RenderTarget2Dクラス|RenderTarget2Dクラス]])を設定したとき、そのレンダリングターゲットの[[データ]]をどのように処理するかを指定するのに使用する列挙体である。
+
'''AABB''' (語源:Axis Aligned Bounding Box)とは、「軸に平行な直方体」という意味であり、3Dゲームなどで[[衝突判定]]に用いる見えない四角形の領域を指す。日本語では「豆腐」などとも呼ばれる。
  
== 名前空間 ==
+
3Dモデルの衝突判定を[[レイキャスト]]などを使ってクソ真面目に[[ポリゴン]]単位で行うと非現実的なくらい物凄い負荷になる。そこでモデルを覆うようなXYZ軸に平行な立方体(全部同じ角度の立方体)を動的に作り出し、AABBどうしで当たり判定を行えば、いわゆる2DなアクションゲームのX軸Y軸の衝突判定処理にZ軸の処理を加えるだけでよく非常に軽い処理となる。[[モデル]]単位のAABBでは大雑把すぎるという場合は[[ボーン]]単位などでAABBを用意して衝突判定を行うという手法が使われる。
* [[MonoGame/クラスライブラリ/Microsoft.Xna.Framework.Graphics名前空間|Microsoft.Xna.Framework.Graphics名前空間]]
 
  
== 構文 ==
+
ゲーム以外の3Dアプリでも「[[マウス]]でモデルを掴むように動かす操作」を実現するためにAABBを利用しているのがほとんどである。
public enum RenderTargetUsage
 
  
== フィールド ==
+
[[物理演算エンジン]]での衝突判定では[[レイキャスト]]などを使ってクソ真面目に計算していることが多いため、そのような場合の高速化には表示用のモデルとは別に見えないローポリゴンモデルを被せるように用意して物理演算エンジンに喰わせることもある。これはAABBとは別の技術だが、実のところ物理演算エンジン内部でも物凄く小さなAABBを大量に生成して衝突判定を行っている実装も多い。
{| class="wikitable"
 
|+
 
! 値
 
! 概要
 
|-
 
| DiscardContents
 
| 常にレンダリングターゲットのデータを削除する。
 
|-
 
| PlatformContents
 
| プラットフォームに応じて扱いを変える。使うな危険。
 
|-
 
| PreserveContents
 
| 常にレンダリングターゲットのデータを保持する。
 
|}
 
  
== 備考 ==
+
== 実装例 ==
=== PreserveContentsは遅い ===
+
[[MonoGame]]での実装例。[[デバッグ]]はしていない。
PreserveContentsは[[VRAM]]容量が少ない環境では[[メインメモリ]]への保存と復元が発生するため絶望的なほど遅くなる。
+
<source lang="csharp">
[[PC]]ではまず問題になることはないようだが、一部の[[スマホ]]では絶望的な速度になるようだ。
+
    using System;
なるべくDiscardContentsを使ったほうが良さそうだ。
+
    using Microsoft.Xna.Framework;
  
=== DiscardContentsの注意点 ===
+
    // FromとToを結ぶ立方体
GraphicsDeviceが最初から持っているレンダリングターゲット(DirectXでいうプライマリサーフェイス)に相当するものはDiscardContentsに設定されている。
+
    public struct AABB
DiscardContentsの欠点はGraphicsDevice.SetRenderTargetするたびに破棄される点であり、レンダリング系APIの呼出順序を間違えると残念なことになる。
+
    {
 +
        public Vector3 From;
 +
        public Vector3 To;
  
たとば以下のコードは正常に動作しない。
+
         public Vector3 Center
<source lang="csharp">
 
         protected override void Draw(GameTime gameTime)
 
 
         {
 
         {
             // (1)プライマリサーフェイスを塗りつぶす
+
             get
             _graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
+
             {
 +
                return this.From + this.Harf;
 +
            }
 +
        }
  
             // (2)レンダリングターゲットを切り替える
+
        public Vector3 Harf
             _graphics.GraphicsDevice.SetRenderTarget(new RenderTarget2D(GraphicsDevice, 128, 128));
+
        {
 +
             get
 +
             {
 +
                return this.Width * 0.5f;
 +
            }
 +
        }
  
             // (3)レンダリングターゲットをプライマリサーフェイスに戻す
+
        public Vector3 Width {
             // このときプライマリサーフェイスはDiscardContents設定なので内容がクリアされ(1)の塗りつぶしが無かったことにされる。
+
             get
            _graphics.GraphicsDevice.SetRenderTarget(null);
+
             {
 +
                return this.To - this.From;  
 +
            }
 +
        }
  
             base.Draw(gameTime);
+
        public AABB(Vector3 from, Vector3 to)
 +
        {
 +
            this.From = new Vector3(Math.Min(from.X, to.X), Math.Min(from.Y, to.Y), Math.Min(from.Z, to.Z));
 +
             this.To  = new Vector3(Math.Max(from.X, to.X), Math.Max(from.Y, to.Y), Math.Max(from.Z, to.Z));  
 
         }
 
         }
</source>
 
  
DiscardContentsの場合は以下のような呼出順序で書かなければならない。
+
         public bool Contains(AABB target)
<source lang="csharp">
 
         protected override void Draw(GameTime gameTime)
 
 
         {
 
         {
             // (1)レンダリングターゲットを切り替える
+
             if ((this.Harf.X + target.Harf.X) < Math.Abs(this.Center.X - target.Center.X)) return false;
            _graphics.GraphicsDevice.SetRenderTarget(new RenderTarget2D(GraphicsDevice, 128, 128));
+
             if ((this.Harf.Y + target.Harf.Y) < Math.Abs(this.Center.Y - target.Center.Y)) return false;
 
+
             if ((this.Harf.Z + target.Harf.Z) < Math.Abs(this.Center.Z - target.Center.Z)) return false;
             // (2)レンダリングターゲットをプライマリサーフェイスに戻す(と同時にまっさらになる)
 
            _graphics.GraphicsDevice.SetRenderTarget(null);
 
 
 
             // (3)プライマリサーフェイスを塗りつぶす
 
            _graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
 
  
             base.Draw(gameTime);
+
             return true;
 
         }
 
         }
 +
    }
 
</source>
 
</source>
  
 
== 関連項目 ==
 
== 関連項目 ==
* [[MonoGame/クラスライブラリ/GraphicsDeviceクラス|GraphicsDeviceクラス]]
+
* [[物理演算エンジン]]
** [[MonoGame/クラスライブラリ/GraphicsDeviceクラス/SetRenderTargetメソッド|SetRenderTargetメソッド]]
+
* [[衝突判定]]
** [[MonoGame/クラスライブラリ/GraphicsDeviceクラス/SetRenderTargetsメソッド|SetRenderTargetsメソッド]]
 
** [[MonoGame/クラスライブラリ/GraphicsDeviceクラス/GetRenderTargetsメソッド|GetRenderTargetsメソッド]]
 
* [[MonoGame/クラスライブラリ/RenderTarget2Dクラス|RenderTarget2Dクラス]]
 
* [[MonoGame/クラスライブラリ/RenderTargetCubeクラス|RenderTargetCubeクラス]]
 
* [[MonoGame/クラスライブラリ/CubeMapFace列挙体|CubeMapFace列挙体]]
 
* [[MonoGame/クラスライブラリ/RenderTargetBinding構造体|RenderTargetBinding構造体]]
 
  
[[category: MonoGame]]
+
[[category: 3DCG]]

2017年11月10日 (金) 11:48時点における版

AABB (語源:Axis Aligned Bounding Box)とは、「軸に平行な直方体」という意味であり、3Dゲームなどで衝突判定に用いる見えない四角形の領域を指す。日本語では「豆腐」などとも呼ばれる。

3Dモデルの衝突判定をレイキャストなどを使ってクソ真面目にポリゴン単位で行うと非現実的なくらい物凄い負荷になる。そこでモデルを覆うようなXYZ軸に平行な立方体(全部同じ角度の立方体)を動的に作り出し、AABBどうしで当たり判定を行えば、いわゆる2DなアクションゲームのX軸Y軸の衝突判定処理にZ軸の処理を加えるだけでよく非常に軽い処理となる。モデル単位のAABBでは大雑把すぎるという場合はボーン単位などでAABBを用意して衝突判定を行うという手法が使われる。

ゲーム以外の3Dアプリでも「マウスでモデルを掴むように動かす操作」を実現するためにAABBを利用しているのがほとんどである。

物理演算エンジンでの衝突判定ではレイキャストなどを使ってクソ真面目に計算していることが多いため、そのような場合の高速化には表示用のモデルとは別に見えないローポリゴンモデルを被せるように用意して物理演算エンジンに喰わせることもある。これはAABBとは別の技術だが、実のところ物理演算エンジン内部でも物凄く小さなAABBを大量に生成して衝突判定を行っている実装も多い。

実装例

MonoGameでの実装例。デバッグはしていない。

    using System;
    using Microsoft.Xna.Framework;

    // FromとToを結ぶ立方体
    public struct AABB
    {
        public Vector3 From;
        public Vector3 To;

        public Vector3 Center
        {
            get
            {
                return this.From + this.Harf;
            }
        }

        public Vector3 Harf
        {
            get
            {
                return this.Width * 0.5f;
            }
        }

        public Vector3 Width { 
            get 
            { 
                return this.To - this.From; 
            } 
        }

        public AABB(Vector3 from, Vector3 to)
        {
            this.From = new Vector3(Math.Min(from.X, to.X), Math.Min(from.Y, to.Y), Math.Min(from.Z, to.Z)); 
            this.To   = new Vector3(Math.Max(from.X, to.X), Math.Max(from.Y, to.Y), Math.Max(from.Z, to.Z)); 
        }

        public bool Contains(AABB target)
        {
            if ((this.Harf.X + target.Harf.X) < Math.Abs(this.Center.X - target.Center.X)) return false;
            if ((this.Harf.Y + target.Harf.Y) < Math.Abs(this.Center.Y - target.Center.Y)) return false;
            if ((this.Harf.Z + target.Harf.Z) < Math.Abs(this.Center.Z - target.Center.Z)) return false;

            return true;
        }
    }

関連項目